File mod_auth_kerb.apache22+.patch of Package apache2-mod_auth_kerb

diff -rNU 20 ../mod_auth_kerb-5.4-o/src/mod_auth_kerb.c ./src/mod_auth_kerb.c
--- ../mod_auth_kerb-5.4-o/src/mod_auth_kerb.c	2014-03-28 13:57:41.000000000 +0100
+++ ./src/mod_auth_kerb.c	2014-03-28 13:56:21.000000000 +0100
@@ -45,40 +45,42 @@
 #ident "$Id: mod_auth_kerb.c,v 1.150 2008/12/04 10:14:03 baalberith Exp $"
 
 #include "config.h"
 
 #include <stdlib.h>
 #include <stdio.h>
 #include <stdarg.h>
 
 #define MODAUTHKERB_VERSION "5.4"
 
 #define MECH_NEGOTIATE "Negotiate"
 #define SERVICE_NAME "HTTP"
 
 #include <httpd.h>
 #include <http_config.h>
 #include <http_core.h>
 #include <http_log.h>
 #include <http_protocol.h>
 #include <http_request.h>
 
+#include "mod_auth.h"
+
 #ifdef STANDARD20_MODULE_STUFF
 #include <apr_strings.h>
 #include <apr_base64.h>
 #else
 #define apr_pstrdup		ap_pstrdup
 #define apr_psprintf		ap_psprintf
 #define apr_pstrcat		ap_pstrcat
 #define apr_pcalloc		ap_pcalloc
 #define apr_table_setn		ap_table_setn
 #define apr_table_add		ap_table_add
 #define apr_base64_decode_len	ap_base64decode_len
 #define apr_base64_decode	ap_base64decode
 #define apr_base64_encode_len	ap_base64encode_len
 #define apr_base64_encode	ap_base64encode
 #define apr_pool_cleanup_null	ap_null_cleanup
 #define apr_pool_cleanup_register	ap_register_cleanup
 #endif /* STANDARD20_MODULE_STUFF */
 
 #ifdef _WIN32
 #define vsnprintf _vsnprintf
@@ -1819,38 +1821,199 @@
 	NULL,				/* EAPI: rewrite_command	      */
 	NULL				/* EAPI: new_connection		      */
 #endif
 };
 #else
 static int
 kerb_init_handler(apr_pool_t *p, apr_pool_t *plog,
       		  apr_pool_t *ptemp, server_rec *s)
 {
    ap_add_version_component(p, "mod_auth_kerb/" MODAUTHKERB_VERSION);
 #ifndef HEIMDAL
    /* Suppress the MIT replay cache.  Requires MIT Kerberos 1.4.0 or later.
       1.3.x are covered by the hack overiding the replay calls */
    if (getenv("KRB5RCACHETYPE") == NULL && have_rcache_type("none"))
       putenv(strdup("KRB5RCACHETYPE=none"));
 #endif
    
    return OK;
 }
 
+static authn_status authenticate_user_krb5pwd22(request_rec *r, const char *sent_name,
+                                   const char *sent_pw)
+{
+    const char      *realms = NULL;
+    const char      *realm = NULL;
+    krb5_context    kcontext = NULL;
+    krb5_error_code code;
+    krb5_principal  client = NULL;
+    krb5_principal  server = NULL;
+    krb5_ccache     ccache = NULL;
+    krb5_keytab     keytab = NULL;
+    int             ret;
+    char            *name = NULL;
+    int             all_principals_unkown;
+    char            *p = NULL;
+
+    kerb_auth_config *conf = 
+    (kerb_auth_config *) ap_get_module_config(r->per_dir_config,
+                                              &auth_kerb_module);
+
+    
+    code = krb5_init_context(&kcontext);
+    if (code) {
+        log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+                   "Cannot initialize Kerberos5 context (%d)", code);
+        return AUTH_GENERAL_ERROR;
+    }
+
+    if (sent_pw == NULL || *sent_pw == '\0') {
+        log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+                   "empty passwords are not accepted");
+        ret = AUTH_DENIED;
+        goto end;
+    }
+    
+    if (conf->krb_5_keytab)
+        krb5_kt_resolve(kcontext, conf->krb_5_keytab, &keytab);
+    
+    if (conf->krb_service_name && strchr(conf->krb_service_name, '/') != NULL)
+        ret = krb5_parse_name (kcontext, conf->krb_service_name, &server);
+    else
+        ret = krb5_sname_to_principal(kcontext, ap_get_server_name(r),
+                                      (conf->krb_service_name) ? conf->krb_service_name : SERVICE_NAME,
+                                      KRB5_NT_SRV_HST, &server);
+    
+    if (ret) {
+        log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+                   "Error parsing server name (%s): %s",
+                   (conf->krb_service_name) ? conf->krb_service_name : SERVICE_NAME,
+                   krb5_get_err_text(kcontext, ret));
+        ret = AUTH_DENIED;
+        goto end;
+    }
+    
+    code = krb5_unparse_name(kcontext, server, &name);
+    if (code) {
+        log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+                   "krb5_unparse_name() failed: %s",
+                   krb5_get_err_text(kcontext, code));
+        ret = AUTH_DENIED;
+        goto end;
+    }
+    log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "Using %s as server principal for password verification", name);
+    free(name);
+    name = NULL;
+    
+    p = strchr(sent_name, '@');
+    if (p) {
+        *p++ = '\0';
+        if (conf->krb_auth_realms && !ap_find_token(r->pool, conf->krb_auth_realms, p)) {
+            log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+                       "Specified realm `%s' not allowed by configuration", p);
+            ret = AUTH_DENIED;
+            goto end;
+        }
+    }
+    
+    realms = (p) ? p : conf->krb_auth_realms;
+    all_principals_unkown = 1;
+    do {
+        name = (char *) sent_name;
+        if (realms && (realm = ap_getword_white(r->pool, &realms)))
+            name = apr_psprintf(r->pool, "%s@%s", sent_name, realm);
+        
+        if (client) {
+            krb5_free_principal(kcontext, client);
+            client = NULL;
+        }
+        
+        code = krb5_parse_name(kcontext, name, &client);
+        if (code) {
+            log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+                       "krb5_parse_name() failed: %s",
+                       krb5_get_err_text(kcontext, code));
+            continue;
+        }
+        
+        code = verify_krb5_user(r, kcontext, client, sent_pw,
+                                server, keytab, conf->krb_verify_kdc, conf->krb_service_name, &ccache);
+        if (code == 0)
+            break;
+        
+        /* ap_getword_white() used above shifts the parameter, so it's not
+         needed to touch the realms variable */
+    } while (realms && *realms);
+    
+    memset((char *)sent_pw, 0, strlen(sent_pw));
+    
+    if (code) {
+        if (all_principals_unkown == 1 && code == KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN)
+            ret = AUTH_USER_NOT_FOUND;
+        else
+            ret = AUTH_DENIED;
+        
+        goto end;
+    }
+    
+    code = krb5_unparse_name(kcontext, client, &name);
+    if (code) {
+        log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "krb5_unparse_name() failed: %s",
+                   krb5_get_err_text(kcontext, code));
+        ret = AUTH_DENIED;
+        goto end;
+    }
+    MK_USER = apr_pstrdup (r->pool, name);
+    MK_AUTH_TYPE = "Basic";
+    free(name);
+    
+    if (conf->krb_save_credentials)
+        store_krb5_creds(kcontext, r, conf, ccache);
+    
+    ret = AUTH_GRANTED;
+    
+end:
+    log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
+               "kerb_authenticate_user_krb5pwd22 ret=%d user=%s authtype=%s",
+               ret, (MK_USER)?MK_USER:"(NULL)", (MK_AUTH_TYPE)?MK_AUTH_TYPE:"(NULL)");
+    if (client)
+        krb5_free_principal(kcontext, client);
+    if (server)
+        krb5_free_principal(kcontext, server);
+    if (ccache)
+        krb5_cc_destroy(kcontext, ccache);
+    if (keytab)
+        krb5_kt_close(kcontext, keytab);
+    krb5_free_context(kcontext);
+    
+    return ret;
+    
+}    
+
+static const authn_provider authn_kerberos_provider =
+{
+    &authenticate_user_krb5pwd22,
+    NULL
+};
+
+
+
 static void
 kerb_register_hooks(apr_pool_t *p)
 {
    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);
+    ap_register_provider(p, AUTHN_PROVIDER_GROUP, "kerberos", "0",
+                         &authn_kerberos_provider);
 }
 
 module AP_MODULE_DECLARE_DATA auth_kerb_module =
 {
    STANDARD20_MODULE_STUFF,
    kerb_dir_create_config,	/* create per-dir    conf structures  */
    NULL,			/* merge  per-dir    conf structures  */
    NULL,			/* create per-server conf structures  */
    NULL,			/* merge  per-server conf structures  */
    kerb_auth_cmds,		/* table of configuration directives  */
    kerb_register_hooks		/* register hooks                     */
 };
 #endif
openSUSE Build Service is sponsored by