fixed [1851056] problem with password beginning with ':'
[mod_auth_kerb.git] / src / mod_auth_kerb.c
index 71ce099..1fb4603 100644 (file)
@@ -50,7 +50,7 @@
 #include <stdio.h>
 #include <stdarg.h>
 
-#define MODAUTHKERB_VERSION "5.1"
+#define MODAUTHKERB_VERSION "5.3"
 
 #define MECH_NEGOTIATE "Negotiate"
 #define SERVICE_NAME "HTTP"
 #include <unistd.h>
 #endif
 
+#ifndef KRB5_LIB_FUNCTION
+#  if defined(_WIN32)
+#    define KRB5_LIB_FUNCTION _stdcall
+#  else
+#    define KRB5_LIB_FUNCTION
+#  endif
+#endif
+
 #ifdef STANDARD20_MODULE_STUFF
 module AP_MODULE_DECLARE_DATA auth_kerb_module;
 #else
@@ -442,7 +450,7 @@ authenticate_user_krb4pwd(request_rec *r,
    int all_principals_unkown;
 
    sent_pw = ap_pbase64decode(r->pool, auth_line);
-   sent_name = ap_getword (r->pool, &sent_pw, ':');
+   sent_name = ap_getword_nulls_nc (r->pool, (char **) &sent_pw, ':');
 
    sent_instance = strchr(sent_name, '.');
    if (sent_instance)
@@ -893,7 +901,7 @@ authenticate_user_krb5pwd(request_rec *r,
    }
 
    sent_pw = ap_pbase64decode(r->pool, auth_line);
-   sent_name = ap_getword (r->pool, &sent_pw, ':');
+   sent_name = ap_getword_nulls_nc (r->pool, (char **) &sent_pw, ':');
 
    if (sent_pw == NULL || *sent_pw == '\0') {
       log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
@@ -1029,14 +1037,18 @@ end:
  ********************************************************************/
 
 static const char *
-get_gss_error(MK_POOL *p, OM_uint32 err_maj, OM_uint32 err_min, char *prefix)
+get_gss_error(request_rec *r, OM_uint32 err_maj, OM_uint32 err_min, char *prefix)
 {
    OM_uint32 maj_stat, min_stat; 
    OM_uint32 msg_ctx = 0;
    gss_buffer_desc status_string;
    char *err_msg;
 
-   err_msg = apr_pstrdup(p, prefix);
+   log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
+             "GSS-API major_status:%8.8x, minor_status:%8.8x",
+             err_maj, err_min);
+
+   err_msg = apr_pstrdup(r->pool, prefix);
    do {
       maj_stat = gss_display_status (&min_stat,
                                     err_maj,
@@ -1044,11 +1056,16 @@ get_gss_error(MK_POOL *p, OM_uint32 err_maj, OM_uint32 err_min, char *prefix)
                                     GSS_C_NO_OID,
                                     &msg_ctx,
                                     &status_string);
-      if (GSS_ERROR(maj_stat))
-        break;
-      err_msg = apr_pstrcat(p, err_msg, ": ", (char*) status_string.value, NULL);
-      gss_release_buffer(&min_stat, &status_string);
-      
+      if (!GSS_ERROR(maj_stat)) {
+         err_msg = apr_pstrcat(r->pool, err_msg, ": ",
+                              (char*) status_string.value, NULL);
+        gss_release_buffer(&min_stat, &status_string);
+      }
+   } while (!GSS_ERROR(maj_stat) && msg_ctx != 0);
+
+   msg_ctx = 0;
+   err_msg = apr_pstrcat(r->pool, err_msg, " (", NULL);
+   do {
       maj_stat = gss_display_status (&min_stat,
                                     err_min,
                                     GSS_C_MECH_CODE,
@@ -1056,11 +1073,12 @@ get_gss_error(MK_POOL *p, OM_uint32 err_maj, OM_uint32 err_min, char *prefix)
                                     &msg_ctx,
                                     &status_string);
       if (!GSS_ERROR(maj_stat)) {
-        err_msg = apr_pstrcat(p, err_msg,
-                             " (", (char*) status_string.value, ")", NULL);
+        err_msg = apr_pstrcat(r->pool, err_msg, ", ",
+                              (char *) status_string.value, NULL);
         gss_release_buffer(&min_stat, &status_string);
       }
    } while (!GSS_ERROR(maj_stat) && msg_ctx != 0);
+   err_msg = apr_pstrcat(r->pool, err_msg, ")", NULL);
 
    return err_msg;
 }
@@ -1100,7 +1118,7 @@ store_gss_creds(request_rec *r, kerb_auth_config *conf, char *princ_name,
    if (GSS_ERROR(maj_stat)) {
       log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
         "Cannot store delegated credential (%s)", 
-        get_gss_error(r->pool, maj_stat, min_stat, "gss_krb5_copy_ccache"));
+        get_gss_error(r, maj_stat, min_stat, "gss_krb5_copy_ccache"));
       goto end;
    }
 
@@ -1146,7 +1164,7 @@ get_gss_creds(request_rec *r,
    memset(&token, 0, sizeof(token));
    if (GSS_ERROR(major_status)) {
       log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
-                "%s", get_gss_error(r->pool, major_status, minor_status,
+                "%s", get_gss_error(r, major_status, minor_status,
                 "gss_import_name() failed"));
       return HTTP_INTERNAL_SERVER_ERROR;
    }
@@ -1156,7 +1174,7 @@ get_gss_creds(request_rec *r,
       /* Perhaps we could just ignore this error but it's safer to give up now,
          I think */
       log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
-                "%s", get_gss_error(r->pool, major_status, minor_status,
+                "%s", get_gss_error(r, major_status, minor_status,
                                     "gss_display_name() failed"));
       return HTTP_INTERNAL_SERVER_ERROR;
    }
@@ -1171,7 +1189,7 @@ get_gss_creds(request_rec *r,
    gss_release_name(&minor_status2, &server_name);
    if (GSS_ERROR(major_status)) {
       log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
-                "%s", get_gss_error(r->pool, major_status, minor_status,
+                "%s", get_gss_error(r, major_status, minor_status,
                                     "gss_acquire_cred() failed"));
       return HTTP_INTERNAL_SERVER_ERROR;
    }
@@ -1250,6 +1268,7 @@ authenticate_user_gss(request_rec *r, kerb_auth_config *conf,
   gss_OID_desc spnego_oid;
   gss_ctx_id_t context = GSS_C_NO_CONTEXT;
   gss_cred_id_t server_creds = GSS_C_NO_CREDENTIAL;
+  OM_uint32 ret_flags = 0;
 
   *negotiate_ret_value = "\0";
 
@@ -1318,11 +1337,12 @@ authenticate_user_gss(request_rec *r, kerb_auth_config *conf,
                                  &client_name,
                                  NULL,
                                  &output_token,
-                                 NULL,
+                                 &ret_flags,
                                  NULL,
                                  &delegated_cred);
   log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
-            "Verification returned code %d", major_status);
+            "Client %s us their credential",
+            (ret_flags & GSS_C_DELEG_FLAG) ? "sent" : "didn't send");
   if (output_token.length) {
      char *token = NULL;
      size_t len;
@@ -1352,7 +1372,7 @@ authenticate_user_gss(request_rec *r, kerb_auth_config *conf,
                  "Warning: received token seems to be NTLM, which isn't supported by the Kerberos module. Check your IE configuration.");
 
      log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
-               "%s", get_gss_error(r->pool, major_status, minor_status,
+               "%s", get_gss_error(r, major_status, minor_status,
                                    "gss_accept_sec_context() failed"));
      /* Don't offer the Negotiate method again if call to GSS layer failed */
      *negotiate_ret_value = NULL;
@@ -1374,7 +1394,7 @@ authenticate_user_gss(request_rec *r, kerb_auth_config *conf,
   gss_release_name(&minor_status, &client_name); 
   if (GSS_ERROR(major_status)) {
     log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
-              "%s", get_gss_error(r->pool, major_status, minor_status,
+              "%s", get_gss_error(r, major_status, minor_status,
                                   "gss_display_name() failed"));
     ret = HTTP_INTERNAL_SERVER_ERROR;
     goto end;
@@ -1554,18 +1574,18 @@ have_rcache_type(const char *type)
 {
    krb5_error_code ret;
    krb5_context context;
-   krb5_rcache id;
+   krb5_rcache id = NULL;
    int found;
 
-   memset(&id, 0, sizeof(id));
-
    ret = krb5_init_context(&context);
    if (ret)
       return 0;
 
-   ret = krb5_rc_resolve_type(context, &id, type);
+   ret = krb5_rc_resolve_full(context, &id, "none:");
    found = (ret == 0);
 
+   if (ret == 0)
+      krb5_rc_destroy(context, id);
    krb5_free_context(context);
 
    return found;