rather FIXME notes
[mod_auth_kerb.cvs/.git] / src / mod_auth_kerb.c
index a69f665..a1311f7 100644 (file)
@@ -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;
@@ -522,7 +527,12 @@ verify_krb5_init_creds(krb5_context context, krb5_creds *creds,
                      keytab, 0, NULL);
 
 end:
+#ifdef HEIMDAL
+   /* XXX Do I ever want to support Heimdal 0.4 ??? */
+   krb5_data_free(&req);
+#else
    krb5_free_data_contents(context, &req);
+#endif
    if (auth_context)
       krb5_auth_con_free (context, auth_context);
    if (new_creds)
@@ -866,6 +876,9 @@ int authenticate_user_krb5pwd(request_rec *r,
    ret = OK;
 
 end:
+   log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
+             "kerb_authenticate_user_krb5pwd ret=%d user=%s authtype=%s",
+             ret, (MK_USER)?MK_USER:"(NULL)", MK_AUTH_TYPE);
    if (client)
       krb5_free_principal(kcontext, client);
    if (ccache)
@@ -995,6 +1008,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,
@@ -1122,6 +1137,12 @@ authenticate_user_gss(request_rec *r, kerb_auth_config *conf,
   accept_sec_token = (cmp_gss_type(&input_token, &spnego_oid) == 0) ?
                        gss_accept_sec_context_spnego : gss_accept_sec_context;
 
+  /* pridat: Read client Negotiate data of length XXX, prefix YYY */
+  log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "Verifying client data using %s",
+            (accept_sec_token == gss_accept_sec_context)
+              ? "KRB5 GSS-API"
+              : "SPNEGO GSS-API");
+
   major_status = accept_sec_token(&minor_status,
                                  &context,
                                  server_creds,
@@ -1133,6 +1154,8 @@ authenticate_user_gss(request_rec *r, kerb_auth_config *conf,
                                  NULL,
                                  NULL,
                                  &delegated_cred);
+  log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
+            "Verification returned code %d", major_status);
   if (output_token.length) {
      char *token = NULL;
      size_t len;
@@ -1149,6 +1172,9 @@ authenticate_user_gss(request_rec *r, kerb_auth_config *conf,
      ap_base64encode(token, output_token.value, output_token.length);
      token[len] = '\0';
      *negotiate_ret_value = token;
+     log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
+               "GSS-API token of length %d bytes will be sent back",
+               major_status, output_token.length);
      gss_release_buffer(&minor_status2, &output_token);
   }
 
@@ -1239,14 +1265,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 +1281,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
@@ -1276,27 +1304,41 @@ int kerb_authenticate_user(request_rec *r)
    /* get the type specified in .htaccess */
    type = ap_auth_type(r);
 
+   log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
+             "kerb_authenticate_user entered with user %s and auth_type %s",
+             (MK_USER)?MK_USER:"(NULL)",type?type:"(NULL)");
+
    if (type && strcasecmp(type, "Kerberos") == 0)
       use_krb5 = use_krb4 = 1;
    else if(type && strcasecmp(type, "KerberosV5") == 0)
-      use_krb4 = 0;
+      use_krb5 = 1;
    else if(type && strcasecmp(type, "KerberosV4") == 0)
-      use_krb5 = 0;
+      use_krb4 = 1;
    else
       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 +1394,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