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