X-Git-Url: http://www.project-moonshot.org/gitweb/?a=blobdiff_plain;f=src%2Fmod_auth_kerb.c;h=587e9300d43c47a797c6d6ff65069e92f9960dd6;hb=36747dc9f7fc3ce8e5d646c7b7ce46d5d1cd3434;hp=880b6eaac09b673a6687ee1af6117e2e5785d30b;hpb=dda1d7e4425e0aac9bc01c3b59adcdbbf4475ceb;p=mod_auth_kerb.git diff --git a/src/mod_auth_kerb.c b/src/mod_auth_kerb.c index 880b6ea..587e930 100644 --- a/src/mod_auth_kerb.c +++ b/src/mod_auth_kerb.c @@ -50,7 +50,7 @@ #include #include -#define MODAUTHKERB_VERSION "5.1" +#define MODAUTHKERB_VERSION "5.3" #define MECH_NEGOTIATE "Negotiate" #define SERVICE_NAME "HTTP" @@ -118,6 +118,14 @@ #include #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 @@ -157,6 +165,7 @@ typedef struct { char *krb_5_keytab; int krb_method_gssapi; int krb_method_k5pass; + int krb5_do_auth_to_local; #endif #ifdef KRB4 char *krb_4_srvtab; @@ -219,6 +228,9 @@ static const command_rec kerb_auth_cmds[] = { command("KrbMethodK5Passwd", ap_set_flag_slot, krb_method_k5pass, FLAG, "Enable Kerberos V5 password authentication."), + + command("KrbLocalUserMapping", ap_set_flag_slot, krb5_do_auth_to_local, + FLAG, "Set to 'on' to have Kerberos do auth_to_local mapping of principal names to system user names."), #endif #ifdef KRB4 @@ -295,7 +307,6 @@ const krb5_rc_ops_internal mod_auth_kerb_rc_ops = { }; #endif - /*************************************************************************** Auth Configuration Initialization ***************************************************************************/ @@ -312,6 +323,7 @@ static void *kerb_dir_create_config(MK_POOL *p, char *d) ((kerb_auth_config *)rec)->krb_ssl_preauthentication = 0; #endif #ifdef KRB5 + ((kerb_auth_config *)rec)->krb5_do_auth_to_local = 0; ((kerb_auth_config *)rec)->krb_method_k5pass = 1; ((kerb_auth_config *)rec)->krb_method_gssapi = 1; #endif @@ -442,7 +454,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 +905,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 +1041,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 +1060,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 +1077,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 +1122,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 +1168,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 +1178,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 +1193,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 +1272,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 +1341,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 +1376,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 +1398,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; @@ -1385,7 +1409,7 @@ authenticate_user_gss(request_rec *r, kerb_auth_config *conf, if (conf->krb_save_credentials && delegated_cred != GSS_C_NO_CREDENTIAL) store_gss_creds(r, conf, (char *)output_token.value, delegated_cred); - + gss_release_buffer(&minor_status, &output_token); ret = OK; @@ -1408,6 +1432,66 @@ end: return ret; } + +static int +do_krb5_an_to_ln(request_rec *r) { + krb5_error_code code; + int ret = HTTP_INTERNAL_SERVER_ERROR; + char *MK_USER_LNAME = NULL; + krb5_context kcontext = NULL; + krb5_principal client = NULL; + + code = krb5_init_context(&kcontext); + if (code) { + log_rerror(APLOG_MARK, APLOG_ERR, 0, r, + "Cannot initialize Kerberos5 context (%d)", code); + goto end; + } + + code = krb5_parse_name(kcontext, MK_USER, &client); + if (code) { + log_rerror(APLOG_MARK, APLOG_ERR, 0, r, + "krb5_parse_name() failed: %s", + krb5_get_err_text(kcontext, code)); + goto end; + } + MK_USER_LNAME = apr_pcalloc(r->pool, strlen(MK_USER)+1); + if (MK_USER_LNAME == NULL) { + log_rerror(APLOG_MARK, APLOG_ERR, 0, r, + "ap_pcalloc() failed (not enough memory)"); + goto end; + } + code = krb5_aname_to_localname(kcontext, client, strlen(MK_USER), MK_USER_LNAME); + if (code) { + if (code != KRB5_LNAME_NOTRANS) { + log_rerror(APLOG_MARK, APLOG_ERR, 0, r, + "krb5_aname_to_localname() failed: %s", + krb5_get_err_text(kcontext, code)); + + } + else { + log_rerror(APLOG_MARK, APLOG_NOTICE, 0, r, + "krb5_aname_to_localname() found no " + "mapping for principal %s", + MK_USER); + } + } + else { + log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, + "kerb_authenticate_a_name_to_local_name %s -> %s", + (MK_USER)?MK_USER:"(NULL)", (MK_USER_LNAME)?MK_USER_LNAME:"(NULL)"); + MK_USER = apr_pstrdup(r->pool, MK_USER_LNAME); + ret = OK; + } + end: + if (client) + krb5_free_principal(kcontext, client); + if (kcontext) + krb5_free_context(kcontext); + return ret; +} + + #endif /* KRB5 */ static int @@ -1532,6 +1616,8 @@ kerb_authenticate_user(request_rec *r) strcasecmp(auth_type, "Basic") == 0) { ret = authenticate_user_krb5pwd(r, conf, auth_line); } + if (ret == OK && conf->krb5_do_auth_to_local) + ret = do_krb5_an_to_ln(r); #endif #ifdef KRB4