Added changes to enable compiling on Windows (most likely not sufficient)
[mod_auth_kerb.cvs/.git] / src / mod_auth_kerb.c
index 0fa3474..bd53600 100644 (file)
 
 #include "config.h"
 
-#define MODAUTHKERB_VERSION "5.0-rc5"
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+#define MODAUTHKERB_VERSION "5.0-rc6"
 
 #include <httpd.h>
 #include <http_config.h>
 #include <netdb.h> /* gethostbyname() */
 #endif /* KRB4 */
 
+#ifdef WIN32
+#define vsnprintf _vsnprintf
+#define snprintf _snprintf
+#else
 /* XXX remove dependency on unistd.h ??? */
 #include <unistd.h>
+#endif
 
 #ifdef STANDARD20_MODULE_STUFF
 module AP_MODULE_DECLARE_DATA auth_kerb_module;
@@ -143,12 +152,12 @@ krb5_save_realms(cmd_parms *cmd, kerb_auth_config *sec, char *arg);
 #define command(name, func, var, type, usage)           \
   AP_INIT_ ## type (name, func,                         \
         (void*)APR_XtOffsetOf(kerb_auth_config, var),   \
-        OR_AUTHCFG, usage)
+        OR_AUTHCFG | RSRC_CONF, usage)
 #else
 #define command(name, func, var, type, usage)          \
   { name, func,                                        \
     (void*)XtOffsetOf(kerb_auth_config, var),          \
-    OR_AUTHCFG, type, usage }
+    OR_AUTHCFG | RSRC_CONF, type, usage }
 #endif
 
 static const command_rec kerb_auth_cmds[] = {
@@ -195,6 +204,41 @@ static const command_rec kerb_auth_cmds[] = {
    { NULL }
 };
 
+#ifdef WIN32
+int
+mkstemp(char *template)
+{
+    int start, i;
+    pid_t val;
+    val = getpid();
+    start = strlen(template) - 1;
+    while(template[start] == 'X') {
+       template[start] = '0' + val % 10;
+       val /= 10;
+       start--;
+    }
+    
+    do{
+       int fd;
+       fd = open(template, O_RDWR | O_CREAT | O_EXCL, 0600);
+       if(fd >= 0 || errno != EEXIST)
+           return fd;
+       i = start + 1;
+       do{
+           if(template[i] == 0)
+               return -1;
+           template[i]++;
+           if(template[i] == '9' + 1)
+               template[i] = 'a';
+           if(template[i] <= 'z')
+               break;
+           template[i] = 'a';
+           i++;
+       }while(1);
+    }while(1);
+}
+#endif
+
 #if defined(KRB5) && !defined(HEIMDAL)
 /* Needed to work around problems with replay caches */
 #include "mit-internals.h"
@@ -527,7 +571,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)
@@ -568,7 +617,7 @@ verify_krb5_user(request_rec *r, krb5_context context, krb5_principal principal,
    }
 
    ret = krb5_sname_to_principal(context, ap_get_server_name(r), service, 
-                                KRB5_NT_UNKNOWN, &server);
+                                KRB5_NT_SRV_HST, &server);
    if (ret) {
       log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
                 "krb5_sname_to_principal() failed: %s",
@@ -871,6 +920,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)
@@ -980,20 +1032,21 @@ get_gss_creds(request_rec *r,
               kerb_auth_config *conf,
              gss_cred_id_t *server_creds)
 {
-   gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER;
+   gss_buffer_desc token = GSS_C_EMPTY_BUFFER;
    OM_uint32 major_status, minor_status, minor_status2;
    gss_name_t server_name = GSS_C_NO_NAME;
    char buf[1024];
 
    snprintf(buf, sizeof(buf), "%s@%s", conf->krb_service_name,
-        ap_get_server_name(r));
+           ap_get_server_name(r));
 
-   input_token.value = buf;
-   input_token.length = strlen(buf) + 1;
+   token.value = buf;
+   token.length = strlen(buf) + 1;
 
-   major_status = gss_import_name(&minor_status, &input_token,
+   major_status = gss_import_name(&minor_status, &token,
                                  GSS_C_NT_HOSTBASED_SERVICE,
                                  &server_name);
+   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,
@@ -1001,7 +1054,19 @@ get_gss_creds(request_rec *r,
       return HTTP_INTERNAL_SERVER_ERROR;
    }
 
-   log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "Acquiring creds for %s", buf);
+   major_status = gss_display_name(&minor_status, server_name, &token, NULL);
+   if (GSS_ERROR(major_status)) {
+      /* 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,
+                                    "gss_display_name() failed"));
+      return HTTP_INTERNAL_SERVER_ERROR;
+   }
+
+   log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "Acquiring creds for %s",
+             token.value);
+   gss_release_buffer(&minor_status, &token);
    
    major_status = gss_acquire_cred(&minor_status, server_name, GSS_C_INDEFINITE,
                                   GSS_C_NO_OID_SET, GSS_C_ACCEPT,
@@ -1047,8 +1112,6 @@ cmp_gss_type(gss_buffer_t token, gss_OID oid)
    if (token->length == 0)
       return GSS_S_DEFECTIVE_TOKEN;
 
-   /* XXX if (token->value == NTLMSSP) log_debug("NTLM mechanism used"); */
-
    p = token->value;
    if (*p++ != 0x60)
       return GSS_S_DEFECTIVE_TOKEN;
@@ -1078,7 +1141,11 @@ authenticate_user_gss(request_rec *r, kerb_auth_config *conf,
   int ret;
   gss_name_t client_name = GSS_C_NO_NAME;
   gss_cred_id_t delegated_cred = GSS_C_NO_CREDENTIAL;
-  OM_uint32 (*accept_sec_token)();
+  OM_uint32 
+     (*accept_sec_token)(OM_uint32 *, gss_ctx_id_t *, const gss_cred_id_t,
+                        const gss_buffer_t, const gss_channel_bindings_t,
+                        gss_name_t *, gss_OID *, gss_buffer_t, OM_uint32 *,
+                        OM_uint32 *, gss_cred_id_t *);
   gss_OID_desc spnego_oid;
   gss_ctx_id_t context = GSS_C_NO_CONTEXT;
   gss_cred_id_t server_creds = GSS_C_NO_CREDENTIAL;
@@ -1129,6 +1196,7 @@ 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"
@@ -1170,6 +1238,10 @@ authenticate_user_gss(request_rec *r, kerb_auth_config *conf,
   }
 
   if (GSS_ERROR(major_status)) {
+     if (input_token.length > 7 && memcmp(input_token.value, "NTLMSSP", 7) == 0)
+       log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
+                 "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,
                                    "gss_accept_sec_context() failed"));
@@ -1295,6 +1367,10 @@ 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)