added password verification invocation vie the AuthBasicProvider with krb value
[mod_auth_kerb.cvs/.git] / src / mod_auth_kerb.c
index 70bd9f1..65efd49 100644 (file)
 #include <stdio.h>
 #include <stdarg.h>
 
-#define MODAUTHKERB_VERSION "5.3"
+#define MODAUTHKERB_VERSION "5.4"
 
 #define MECH_NEGOTIATE "Negotiate"
 #define SERVICE_NAME "HTTP"
 
+#include <ap_provider.h>
+#include <mod_auth.h>
 #include <httpd.h>
 #include <http_config.h>
 #include <http_core.h>
@@ -154,7 +156,7 @@ typedef struct {
        char *krb_auth_realms;
        int krb_save_credentials;
        int krb_verify_kdc;
-       char *krb_service_name;
+       const char *krb_service_name;
        int krb_authoritative;
        int krb_delegate_basic;
 #if 0
@@ -447,7 +449,7 @@ authenticate_user_krb4pwd(request_rec *r,
                          const char *auth_line)
 {
    int ret;
-   const char *sent_pw;
+   char *sent_pw;
    const char *sent_name;
    char *sent_instance;
    char tkt_file[32];
@@ -926,14 +928,13 @@ store_krb5_creds(krb5_context kcontext,
    return OK;
 }
 
-
 static int
 authenticate_user_krb5pwd(request_rec *r,
                           kerb_auth_config *conf,
                           const char *auth_line)
 {
    const char      *sent_pw = NULL; 
-   char      *sent_name = NULL;
+   const char      *sent_name = NULL;
    const char      *realms = NULL;
    const char      *realm = NULL;
    krb5_context    kcontext = NULL;
@@ -1217,7 +1218,7 @@ get_gss_creds(request_rec *r,
    token.length = strlen(buf) + 1;
 
    major_status = gss_import_name(&minor_status, &token,
-                                 (have_server_princ) ? GSS_KRB5_NT_PRINCIPAL_NAME : GSS_C_NT_HOSTBASED_SERVICE,
+                                 (have_server_princ) ? (gss_OID) GSS_KRB5_NT_PRINCIPAL_NAME : (gss_OID) GSS_C_NT_HOSTBASED_SERVICE,
                                  &server_name);
    memset(&token, 0, sizeof(token));
    if (GSS_ERROR(major_status)) {
@@ -1382,10 +1383,10 @@ authenticate_user_gss(request_rec *r, kerb_auth_config *conf,
                        gss_accept_sec_context_spnego : gss_accept_sec_context;
 #endif
 
-  log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "Verifying client data using %s",
+  log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "Verifying client data using KRB5 GSS-API %s",
             (accept_sec_token == gss_accept_sec_context)
-              ? "KRB5 GSS-API"
-              : "SPNEGO GSS-API");
+              ? ""
+              : "with our SPNEGO lib");
 
   major_status = accept_sec_token(&minor_status,
                                  &context,
@@ -1400,7 +1401,7 @@ authenticate_user_gss(request_rec *r, kerb_auth_config *conf,
                                  &delegated_cred);
   log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
             "Client %s us their credential",
-            (ret_flags & GSS_C_DELEG_FLAG) ? "sent" : "didn't send");
+            (ret_flags & GSS_C_DELEG_FLAG) ? "delegated" : "didn't delegate");
   if (output_token.length) {
      char *token = NULL;
      size_t len;
@@ -1552,13 +1553,13 @@ static krb5_conn_data *
 already_succeeded(request_rec *r, char *auth_line)
 {
    krb5_conn_data *conn_data;
-   const char keyname[1024];
+   char keyname[1024];
 
    snprintf(keyname, sizeof(keyname) - 1,
        "mod_auth_kerb::connection::%s::%ld", r->connection->remote_ip, 
        r->connection->id);
 
-   if (apr_pool_userdata_get(&conn_data, keyname, r->connection->pool) != 0)
+   if (apr_pool_userdata_get((void**)&conn_data, keyname, r->connection->pool) != 0)
        return NULL;
 
    if(conn_data) {
@@ -1606,6 +1607,68 @@ set_kerb_auth_headers(request_rec *r, const kerb_auth_config *conf,
 #endif
 }
 
+static authn_status authn_krb_password(request_rec *r, const char *user,
+                                       const char *password)
+{
+kerb_auth_config *conf =
+      (kerb_auth_config *) ap_get_module_config(r->per_dir_config,
+                                                &auth_kerb_module);
+   krb5_conn_data *prevauth = NULL;
+   const char *auth_type = NULL;
+   char *auth_line = NULL;
+   const char *type = NULL;
+   int use_krb5 = 0, use_krb4 = 0;
+   int ret;
+   static int last_return = HTTP_UNAUTHORIZED;
+   char *negotiate_ret_value = NULL;
+   char keyname[1024];
+
+   auth_line = ap_pbase64encode (r->pool, apr_psprintf(r->pool, "%s:%s", user, password));
+
+   if ( (prevauth = already_succeeded(r, auth_line)) == NULL) {
+      ret = HTTP_UNAUTHORIZED;
+
+#ifdef KRB5
+      ret = authenticate_user_krb5pwd(r, conf, auth_line);
+#endif
+
+#ifdef KRB4
+      if (ret == HTTP_UNAUTHORIZED && use_krb4 && conf->krb_method_k4pass)
+        ret = authenticate_user_krb4pwd(r, conf, auth_line);
+#endif
+
+      if (ret == HTTP_UNAUTHORIZED)
+        set_kerb_auth_headers(r, conf, use_krb4, use_krb5, negotiate_ret_value);
+
+   } else {
+      ret = prevauth->last_return;
+      MK_USER = prevauth->user;
+      MK_AUTH_TYPE = prevauth->mech;
+   }
+
+   /*
+    * save who was auth'd, if it's not already stashed.
+    */
+   if(!prevauth) {
+      prevauth = (krb5_conn_data *) apr_pcalloc(r->connection->pool, sizeof(krb5_conn_data));
+      prevauth->user = apr_pstrdup(r->connection->pool, MK_USER);
+      prevauth->authline = apr_pstrdup(r->connection->pool, auth_line);
+      prevauth->mech = apr_pstrdup(r->connection->pool, auth_type);
+      prevauth->last_return = ret;
+      snprintf(keyname, sizeof(keyname) - 1,
+               "mod_auth_kerb::connection::%s::%ld",
+               r->connection->remote_ip, r->connection->id);
+      apr_pool_userdata_set(prevauth, keyname, NULL, r->connection->pool);
+   }
+   if (ret == OK && conf->krb5_do_auth_to_local)
+   ret = do_krb5_an_to_ln(r);
+
+   last_return = ret;
+   
+   if (last_return == OK) return AUTH_GRANTED;
+   else return AUTH_DENIED;
+}
+
 static int
 kerb_authenticate_user(request_rec *r)
 {
@@ -1614,7 +1677,7 @@ kerb_authenticate_user(request_rec *r)
                                                &auth_kerb_module);
    krb5_conn_data *prevauth = NULL;
    const char *auth_type = NULL;
-   const char *auth_line = NULL;
+   char *auth_line = NULL;
    const char *type = NULL;
    int use_krb5 = 0, use_krb4 = 0;
    int ret;
@@ -1649,7 +1712,7 @@ kerb_authenticate_user(request_rec *r)
 #endif
 
    /* get what the user sent us in the HTTP header */
-   auth_line = MK_TABLE_GET(r->headers_in, (r->proxyreq == PROXYREQ_PROXY)
+   auth_line = (char *)MK_TABLE_GET(r->headers_in, (r->proxyreq == PROXYREQ_PROXY)
                                            ? "Proxy-Authorization"
                                            : "Authorization");
    if (!auth_line) {
@@ -1657,7 +1720,7 @@ kerb_authenticate_user(request_rec *r)
                            (use_krb5) ? "\0" : NULL);
       return HTTP_UNAUTHORIZED;
    }
-   auth_type = ap_getword_white(r->pool, &auth_line);
+   auth_type = ap_getword_white(r->pool, (const char **)&auth_line);
 
    /* If we are delegating Basic to other modules, DECLINE the request */
    if (conf->krb_delegate_basic &&
@@ -1805,6 +1868,11 @@ kerb_init_handler(apr_pool_t *p, apr_pool_t *plog,
 static void
 kerb_register_hooks(apr_pool_t *p)
 {
+   static const authn_provider authn_krb_provider = {
+      &authn_krb_password,
+   };
+
+   ap_register_provider(p, "authn", "krb", "0", &authn_krb_provider);
    ap_hook_post_config(kerb_init_handler, NULL, NULL, APR_HOOK_MIDDLE);
    ap_hook_check_user_id(kerb_authenticate_user, NULL, NULL, APR_HOOK_MIDDLE);
 }