Handle KerberosV5/KerberosV4 values of AuthType properly
[mod_auth_kerb.cvs/.git] / src / mod_auth_kerb.c
index b037ed0..0fa3474 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,
@@ -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;
@@ -1124,6 +1129,11 @@ 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;
 
+  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,
@@ -1135,6 +1145,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;
@@ -1151,6 +1163,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);
   }
 
@@ -1241,14 +1256,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;
@@ -1256,7 +1272,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
@@ -1281,24 +1298,34 @@ int kerb_authenticate_user(request_rec *r)
    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;
 
@@ -1354,6 +1381,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