Added a new directive (KrbDelegateBasic), which can be used to pass on authentication...
[mod_auth_kerb.cvs/.git] / src / mod_auth_kerb.c
index 175bbf1..71cc0e6 100644 (file)
@@ -46,7 +46,7 @@
 
 #include "config.h"
 
-#define MODAUTHKERB_VERSION "5.0-rc4"
+#define MODAUTHKERB_VERSION "5.0-rc5"
 
 #include <httpd.h>
 #include <http_config.h>
@@ -120,6 +120,7 @@ typedef struct {
        int krb_verify_kdc;
        char *krb_service_name;
        int krb_authoritative;
+       int krb_delegate_basic;
 #ifdef KRB5
        char *krb_5_keytab;
        int krb_method_gssapi;
@@ -167,7 +168,10 @@ static const command_rec kerb_auth_cmds[] = {
      TAKE1, "Service name to be used by Apache for authentication."),
 
    command("KrbAuthoritative", ap_set_flag_slot, krb_authoritative,
-     FLAG, "Set to 'off' to allow access control to be passed along to lower modules if the UserID is not known to this module."),
+     FLAG, "Set to 'off' to allow access control to be passed along to lower modules iff the UserID is not known to this module."),
+
+   command("KrbDelegateBasic", ap_set_flag_slot, krb_delegate_basic,
+     FLAG, "Always offer Basic authentication regardless of KrbMethodK5Pass and pass on authentication to lower modules if Basic headers arrive."),
 
 #ifdef KRB5
    command("Krb5Keytab", ap_set_file_slot, krb_5_keytab,
@@ -198,13 +202,13 @@ static const command_rec kerb_auth_cmds[] = {
 /* This is our replacement krb5_rc_store function */
 static krb5_error_code
 mod_auth_kerb_rc_store(krb5_context context, krb5_rcache rcache,
-                        krb5_donot_replay *donot_replay)
+                       krb5_donot_replay_internal *donot_replay)
 {
    return 0;
 }
 
 /* And this is the operations vector for our replay cache */
-const krb5_rc_ops mod_auth_kerb_rc_ops = {
+const krb5_rc_ops_internal mod_auth_kerb_rc_ops = {
   0,
   "dfl",
   krb5_rc_dfl_init,
@@ -231,6 +235,7 @@ static void *kerb_dir_create_config(MK_POOL *p, char *d)
         ((kerb_auth_config *)rec)->krb_verify_kdc = 1;
        ((kerb_auth_config *)rec)->krb_service_name = "HTTP";
        ((kerb_auth_config *)rec)->krb_authoritative = 1;
+       ((kerb_auth_config *)rec)->krb_delegate_basic = 0;
 #ifdef KRB5
        ((kerb_auth_config *)rec)->krb_method_k5pass = 1;
        ((kerb_auth_config *)rec)->krb_method_gssapi = 1;
@@ -595,7 +600,7 @@ verify_krb5_user(request_rec *r, krb5_context context, krb5_principal principal,
    if (ret) {
       log_rerror(APLOG_MARK, APLOG_ERR, 0, r, 
                 "generating new memory ccache failed: %s",
-                krb5_get_err_text(kcontext, ret));
+                krb5_get_err_text(context, ret));
       goto end;
    }
 
@@ -995,6 +1000,8 @@ get_gss_creds(request_rec *r,
                 "gss_import_name() failed"));
       return HTTP_INTERNAL_SERVER_ERROR;
    }
+
+   log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "Acquiring creds for %s", buf);
    
    major_status = gss_acquire_cred(&minor_status, server_name, GSS_C_INDEFINITE,
                                   GSS_C_NO_OID_SET, GSS_C_ACCEPT,
@@ -1239,14 +1246,15 @@ set_kerb_auth_headers(request_rec *r, const kerb_auth_config *conf,
    /* get the user realm specified in .htaccess */
    auth_name = ap_auth_name(r);
 
-   /* XXX should the WWW-Authenticate header be cleared first? */
+   /* XXX should the WWW-Authenticate header be cleared first?
+    * apache in the proxy mode should retain client's authN headers? */
 #ifdef KRB5
    if (negotiate_ret_value != NULL && conf->krb_method_gssapi) {
       negoauth_param = (*negotiate_ret_value == '\0') ? "Negotiate" :
                  ap_pstrcat(r->pool, "Negotiate ", negotiate_ret_value, NULL);
       ap_table_add(r->err_headers_out, header_name, negoauth_param);
    }
-   if (use_krb5pwd && conf->krb_method_k5pass) {
+   if ((use_krb5pwd && conf->krb_method_k5pass) || conf->krb_delegate_basic) {
       ap_table_add(r->err_headers_out, header_name,
                   ap_pstrcat(r->pool, "Basic realm=\"", auth_name, "\"", NULL));
       set_basic = 1;
@@ -1254,7 +1262,8 @@ set_kerb_auth_headers(request_rec *r, const kerb_auth_config *conf,
 #endif
 
 #ifdef KRB4
-   if (use_krb4 && conf->krb_method_k4pass && !set_basic)
+   if (!set_basic && 
+       ((use_krb4 && conf->krb_method_k4pass) || conf->krb_delegate_basic))
       ap_table_add(r->err_headers_out, header_name,
                  ap_pstrcat(r->pool, "Basic realm=\"", auth_name, "\"", NULL));
 #endif
@@ -1286,17 +1295,27 @@ int kerb_authenticate_user(request_rec *r)
       return DECLINED;
 
    /* get what the user sent us in the HTTP header */
-   auth_line = MK_TABLE_GET(r->headers_in, "Authorization");
+   auth_line = MK_TABLE_GET(r->headers_in, (r->proxyreq == PROXYREQ_PROXY)
+                                           ? "Proxy-Authorization"
+                                           : "Authorization");
    if (!auth_line) {
-       auth_line = MK_TABLE_GET(r->headers_in, "Proxy-Authorization");
-       if (!auth_line) {
-               set_kerb_auth_headers(r, conf, use_krb4, use_krb5,
-                                    (use_krb5) ? "\0" : NULL);
-               return HTTP_UNAUTHORIZED;
-       }
+      set_kerb_auth_headers(r, conf, use_krb4, use_krb5, 
+                           (use_krb5) ? "\0" : NULL);
+      return HTTP_UNAUTHORIZED;
    }
    auth_type = ap_getword_white(r->pool, &auth_line);
 
+   /* If we are delegating Basic to other modules, DECLINE the request */
+   if (conf->krb_delegate_basic &&
+#ifdef KRB5
+       !conf->krb_method_k5pass &&
+#endif
+#ifdef KRB4
+       !conf->krb_method_k4pass &&
+#endif
+       (strcasecmp(auth_type, "Basic") == 0))
+       return DECLINED;
+
    if (already_succeeded(r))
       return last_return;
 
@@ -1352,6 +1371,12 @@ module MODULE_VAR_EXPORT auth_kerb_module = {
        NULL,                           /*      process initialization        */
        NULL,                           /*      process exit/cleanup          */
        NULL                            /* [ 1] post read_request handling    */
+#ifdef EAPI
+       ,NULL,                          /* EAPI: add_module                   */
+       NULL,                           /* EAPI: remove_module                */
+       NULL,                           /* EAPI: rewrite_command              */
+       NULL                            /* EAPI: new_connection               */
+#endif
 };
 #else
 static int