X-Git-Url: http://www.project-moonshot.org/gitweb/?p=mod_auth_gssapi.git;a=blobdiff_plain;f=src%2Fmod_auth_gssapi.c;h=9d9fbc53261f082f927ffc17fb3440a74730ff97;hp=1e4ce70360cd222893de7f1ebe21dd50d93e5ccc;hb=f20a3525f62bdc154e4a93d7e2eb6310067999b3;hpb=db999f985dc4357e32db6bcc893aa354d2595c98 diff --git a/src/mod_auth_gssapi.c b/src/mod_auth_gssapi.c index 1e4ce70..9d9fbc5 100644 --- a/src/mod_auth_gssapi.c +++ b/src/mod_auth_gssapi.c @@ -402,36 +402,18 @@ static bool mag_auth_basic(request_rec *req, gss_name_t server = GSS_C_NO_NAME; gss_cred_id_t server_cred = GSS_C_NO_CREDENTIAL; gss_ctx_id_t server_ctx = GSS_C_NO_CONTEXT; + gss_cred_id_t acquired_cred = GSS_C_NO_CREDENTIAL; gss_buffer_desc input = GSS_C_EMPTY_BUFFER; gss_buffer_desc output = GSS_C_EMPTY_BUFFER; gss_OID_set indicated_mechs = GSS_C_NO_OID_SET; gss_OID_set allowed_mechs; gss_OID_set filtered_mechs; - gss_OID_set_desc all_mechs_desc; gss_OID_set actual_mechs = GSS_C_NO_OID_SET; uint32_t init_flags = 0; uint32_t maj, min; + int present = 0; bool ret = false; -#ifdef HAVE_GSS_KRB5_CCACHE_NAME - rs = apr_generate_random_bytes((unsigned char *)(&rndname), - sizeof(long long unsigned int)); - if (rs != APR_SUCCESS) { - ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req, - "Failed to generate random ccache name"); - goto done; - } - user_ccache = apr_psprintf(req->pool, "MEMORY:user_%qu", rndname); - maj = gss_krb5_ccache_name(&min, user_ccache, &orig_ccache); - if (GSS_ERROR(maj)) { - ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req, - "In Basic Auth, %s", - mag_error(req, "gss_krb5_ccache_name() " - "failed", maj, min)); - goto done; - } -#endif - maj = gss_import_name(&min, &ba_user, GSS_C_NT_USER_NAME, &user); if (GSS_ERROR(maj)) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req, @@ -493,6 +475,42 @@ static bool mag_auth_basic(request_rec *req, allowed_mechs = filtered_mechs; } +#ifdef HAVE_GSS_KRB5_CCACHE_NAME + /* If we are using the krb5 mechanism make sure to set a per thread + * memory ccache so that there can't be interferences between threads. + * Also make sure we have new cache so no cached results end up being + * used. Some implementations of gss_acquire_cred_with_password() do + * not reacquire creds if cached ones are around, failing to check + * again for the password. */ + maj = gss_test_oid_set_member(&min, discard_const(gss_mech_krb5), + allowed_mechs, &present); + if (GSS_ERROR(maj)) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req, + "In Basic Auth, %s", + mag_error(req, "gss_test_oid_set_member() failed", + maj, min)); + goto done; + } + if (present) { + rs = apr_generate_random_bytes((unsigned char *)(&rndname), + sizeof(long long unsigned int)); + if (rs != APR_SUCCESS) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req, + "Failed to generate random ccache name"); + goto done; + } + user_ccache = apr_psprintf(req->pool, "MEMORY:user_%qu", rndname); + maj = gss_krb5_ccache_name(&min, user_ccache, &orig_ccache); + if (GSS_ERROR(maj)) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req, + "In Basic Auth, %s", + mag_error(req, "gss_krb5_ccache_name() " + "failed", maj, min)); + goto done; + } + } +#endif + maj = gss_acquire_cred_with_password(&min, user, &ba_pwd, GSS_C_INDEFINITE, allowed_mechs, @@ -506,6 +524,22 @@ static bool mag_auth_basic(request_rec *req, goto done; } + /* must acquire creds based on the actual mechs we want to try */ + if (!mag_acquire_creds(req, cfg, actual_mechs, + GSS_C_BOTH, &acquired_cred, NULL)) { + goto done; + } + + if (cred_usage == GSS_C_BOTH) { + /* must acquire with GSS_C_ACCEPT to get the server name */ + if (!mag_acquire_creds(req, cfg, actual_mechs, + GSS_C_ACCEPT, &server_cred, NULL)) { + goto done; + } + } else { + server_cred = acquired_cred; + } + #ifdef HAVE_CRED_STORE if (cfg->deleg_ccache_dir) { /* delegate ourselves credentials so we store them as requested */ @@ -525,35 +559,17 @@ static bool mag_auth_basic(request_rec *req, gss_release_buffer(&min, &output); gss_release_buffer(&min, &input); gss_release_name(&min, &server); - gss_release_cred(&min, &server_cred); - - all_mechs_desc.count = 1; - all_mechs_desc.elements = &actual_mechs->elements[i]; - allowed_mechs = &all_mechs_desc; - /* must acquire with GSS_C_ACCEPT to get the server name */ - if (!mag_acquire_creds(req, cfg, allowed_mechs, - GSS_C_ACCEPT, &server_cred, NULL)) { - continue; - } - maj = gss_inquire_cred(&min, server_cred, &server, - NULL, NULL, NULL); + maj = gss_inquire_cred_by_mech(&min, server_cred, + &actual_mechs->elements[i], + &server, NULL, NULL, NULL); if (GSS_ERROR(maj)) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req, - "%s", mag_error(req, "gss_inquired_cred_() " + "%s", mag_error(req, "gss_inquired_cred_by_mech() " "failed", maj, min)); continue; } - if (cred_usage == GSS_C_BOTH) { - /* reacquire server creds in order to allow delegation */ - gss_release_cred(&min, &server_cred); - if (!mag_acquire_creds(req, cfg, allowed_mechs, - GSS_C_BOTH, &server_cred, NULL)) { - continue; - } - } - do { /* output and input are inverted here, this is intentional */ maj = gss_init_sec_context(&min, user_cred, &user_ctx, server, @@ -567,7 +583,7 @@ static bool mag_auth_basic(request_rec *req, break; } gss_release_buffer(&min, &output); - maj = gss_accept_sec_context(&min, &server_ctx, server_cred, + maj = gss_accept_sec_context(&min, &server_ctx, acquired_cred, &input, GSS_C_NO_CHANNEL_BINDINGS, client, mech_type, &output, NULL, vtime, delegated_cred); @@ -590,8 +606,10 @@ done: gss_release_buffer(&min, &output); gss_release_buffer(&min, &input); gss_release_name(&min, &server); - gss_release_cred(&min, &server_cred); + if (server_cred != acquired_cred) + gss_release_cred(&min, &server_cred); gss_delete_sec_context(&min, &server_ctx, GSS_C_NO_BUFFER); + gss_release_cred(&min, &acquired_cred); gss_release_name(&min, &user); gss_release_cred(&min, &user_cred); gss_delete_sec_context(&min, &user_ctx, GSS_C_NO_BUFFER); @@ -816,6 +834,7 @@ static int mag_auth(request_rec *req) cred_usage = GSS_C_BOTH; } #endif + if (auth_type == AUTH_TYPE_BASIC) { if (mag_auth_basic(req, cfg, ba_user, ba_pwd, cred_usage, &client, &mech_type,