X-Git-Url: http://www.project-moonshot.org/gitweb/?a=blobdiff_plain;f=src%2Fmod_auth_kerb.c;h=da5a1bc03f91343d88097f4052541a0f18b02014;hb=f76f3c770c70168251f6f747119f099ef9f87fdc;hp=1fb46035c2ba88c4ed179e170b82dfbb4a5bba8a;hpb=176dc312d9322e4becd2c1a6c47d3c9f5cf53a38;p=mod_auth_kerb.cvs%2F.git diff --git a/src/mod_auth_kerb.c b/src/mod_auth_kerb.c index 1fb4603..da5a1bc 100644 --- a/src/mod_auth_kerb.c +++ b/src/mod_auth_kerb.c @@ -165,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; @@ -172,6 +173,13 @@ typedef struct { #endif } kerb_auth_config; +typedef struct krb5_conn_data { + char *authline; + char *user; + char *mech; + int last_return; +} krb5_conn_data; + static void set_kerb_auth_headers(request_rec *r, const kerb_auth_config *conf, int use_krb4, int use_krb5pwd, char *negotiate_ret_value); @@ -227,6 +235,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 @@ -303,7 +314,6 @@ const krb5_rc_ops_internal mod_auth_kerb_rc_ops = { }; #endif - /*************************************************************************** Auth Configuration Initialization ***************************************************************************/ @@ -320,6 +330,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 @@ -564,7 +575,12 @@ verify_krb5_init_creds(request_rec *r, krb5_context context, krb5_creds *creds, } else keytab = ap_req_keytab; +#ifdef HAVE_KRB5_CC_NEW_UNIQUE + ret = krb5_cc_new_unique(context, "MEMORY", NULL, &local_ccache); +#else ret = krb5_cc_resolve(context, "MEMORY:", &local_ccache); +#endif + if (ret) { log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "krb5_cc_resolve() failed when verifying KDC"); @@ -711,7 +727,12 @@ verify_krb5_user(request_rec *r, krb5_context context, krb5_principal principal, goto end; } +#ifdef HAVE_KRB5_CC_NEW_UNIQUE + ret = krb5_cc_new_unique(context, "MEMORY", NULL, &ret_ccache); +#else ret = krb5_cc_resolve(context, "MEMORY:", &ret_ccache); +#endif + if (ret) { log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "generating new memory ccache failed: %s", @@ -893,6 +914,10 @@ authenticate_user_krb5pwd(request_rec *r, int all_principals_unkown; char *p = NULL; + //temporary fix for KrbServiceName Any, use default SERVICE_NAME + if (conf->krb_service_name && strcmp(conf->krb_service_name,"Any") == 0) + snprintf(conf->krb_service_name, 5,"%s",SERVICE_NAME); + code = krb5_init_context(&kcontext); if (code) { log_rerror(APLOG_MARK, APLOG_ERR, 0, r, @@ -1150,6 +1175,10 @@ get_gss_creds(request_rec *r, have_server_princ = conf->krb_service_name && strchr(conf->krb_service_name, '/') != NULL; if (have_server_princ) strncpy(buf, conf->krb_service_name, sizeof(buf)); + else if (conf->krb_service_name && strcmp(conf->krb_service_name,"Any") == 0) { + *server_creds = GSS_C_NO_CREDENTIAL; + return 0; + } else snprintf(buf, sizeof(buf), "%s@%s", (conf->krb_service_name) ? conf->krb_service_name : SERVICE_NAME, @@ -1405,7 +1434,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; @@ -1428,17 +1457,88 @@ end: return ret; } -#endif /* KRB5 */ static int -already_succeeded(request_rec *r) +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 krb5_conn_data * +already_succeeded(request_rec *r, char *auth_line) { - if (ap_is_initial_req(r) || MK_AUTH_TYPE == NULL) - return 0; - if (strcmp(MK_AUTH_TYPE, MECH_NEGOTIATE) || - (strcmp(MK_AUTH_TYPE, "Basic") && strchr(MK_USER, '@'))) - return 1; - return 0; + krb5_conn_data *conn_data; + const char keyname[1024]; + + snprintf(keyname, sizeof(keyname) - 1, + "mod_auth_kerb::connection::%s::%ld", r->connection->remote_ip, + r->connection->id); + + if (apr_pool_userdata_get(&conn_data, keyname, r->connection->pool) != 0) + return NULL; + + if(conn_data) { + if(strcmp(conn_data->authline, auth_line) == 0) { + log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "matched previous auth request"); + return conn_data; + } + } + return NULL; } static void @@ -1483,6 +1583,7 @@ kerb_authenticate_user(request_rec *r) kerb_auth_config *conf = (kerb_auth_config *) ap_get_module_config(r->per_dir_config, &auth_kerb_module); + krb5_conn_data *prevauth = NULL; const char *auth_type = NULL; const char *auth_line = NULL; const char *type = NULL; @@ -1490,6 +1591,7 @@ kerb_authenticate_user(request_rec *r) int ret; static int last_return = HTTP_UNAUTHORIZED; char *negotiate_ret_value = NULL; + char keyname[1024]; /* get the type specified in .htaccess */ type = ap_auth_type(r); @@ -1539,10 +1641,8 @@ kerb_authenticate_user(request_rec *r) (strcasecmp(auth_type, "Basic") == 0)) return DECLINED; - if (already_succeeded(r)) - return last_return; - - ret = HTTP_UNAUTHORIZED; + if ( (prevauth = already_succeeded(r, auth_line)) == NULL) { + ret = HTTP_UNAUTHORIZED; #ifdef KRB5 if (use_krb5 && conf->krb_method_gssapi && @@ -1563,6 +1663,30 @@ kerb_authenticate_user(request_rec *r) if (ret == HTTP_UNAUTHORIZED) set_kerb_auth_headers(r, conf, use_krb4, use_krb5, negotiate_ret_value); + } else { + ret = prevauth->last_return; + MK_USER = prevauth->user; + MK_AUTH_TYPE = prevauth->mech; + } + + /* + * save who was auth'd, if it's not already stashed. + */ + if(!prevauth) { + prevauth = (krb5_conn_data *) apr_pcalloc(r->connection->pool, sizeof(krb5_conn_data)); + prevauth->user = apr_pstrdup(r->connection->pool, MK_USER); + prevauth->authline = apr_pstrdup(r->connection->pool, auth_line); + prevauth->mech = apr_pstrdup(r->connection->pool, auth_type); + prevauth->last_return = ret; + snprintf(keyname, sizeof(keyname) - 1, + "mod_auth_kerb::connection::%s::%ld", + r->connection->remote_ip, r->connection->id); + apr_pool_userdata_set(prevauth, keyname, NULL, r->connection->pool); + } + + if (ret == OK && conf->krb5_do_auth_to_local) + ret = do_krb5_an_to_ln(r); + /* XXX log_debug: if ret==OK, log(user XY authenticated) */ last_return = ret;