summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimo Sorce <simo@redhat.com>2015-06-16 16:06:57 -0400
committerSimo Sorce <simo@redhat.com>2015-06-19 16:42:39 -0400
commit79cb8bb8418cca0c408db3c79d78fa23d5e18564 (patch)
tree7ab7293532487426d2afb0e6c82b83d7bc0fd245
parent6e4513dc0ebe5ff6643223d35b509464d451b230 (diff)
downloadmod_auth_gssapi-79cb8bb8418cca0c408db3c79d78fa23d5e18564.tar.gz
mod_auth_gssapi-79cb8bb8418cca0c408db3c79d78fa23d5e18564.tar.xz
mod_auth_gssapi-79cb8bb8418cca0c408db3c79d78fa23d5e18564.zip
Fix Basic Auth with non-krb5 mechanisms
Try each allowed mechanism explicitly in a loop including sourcing the server name per mechanism to insure the proper name type is used in the accept. Otherwise secondary mechanims will fail to work. Fixes #43 Signed-off-by: Simo Sorce <simo@redhat.com>
-rw-r--r--src/mod_auth_gssapi.c140
1 files changed, 85 insertions, 55 deletions
diff --git a/src/mod_auth_gssapi.c b/src/mod_auth_gssapi.c
index e1ecc36..3c578de 100644
--- a/src/mod_auth_gssapi.c
+++ b/src/mod_auth_gssapi.c
@@ -340,7 +340,6 @@ static bool mag_auth_basic(request_rec *req,
struct mag_config *cfg,
gss_buffer_desc ba_user,
gss_buffer_desc ba_pwd,
- gss_cred_id_t acquired_cred,
gss_cred_usage_t cred_usage,
gss_name_t *client,
gss_OID *mech_type,
@@ -361,6 +360,9 @@ static bool mag_auth_basic(request_rec *req,
gss_ctx_id_t server_ctx = GSS_C_NO_CONTEXT;
gss_buffer_desc input = GSS_C_EMPTY_BUFFER;
gss_buffer_desc output = GSS_C_EMPTY_BUFFER;
+ gss_OID_set allowed_mechs = GSS_C_NO_OID_SET;
+ 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;
bool ret = false;
@@ -393,11 +395,17 @@ static bool mag_auth_basic(request_rec *req,
goto done;
}
+ if (cfg->allowed_mechs && cfg->allowed_mechs->count > 1) {
+ all_mechs_desc.count = cfg->allowed_mechs->count - 1;
+ all_mechs_desc.elements = &cfg->allowed_mechs->elements[1];
+ allowed_mechs = &all_mechs_desc;
+ }
+
maj = gss_acquire_cred_with_password(&min, user, &ba_pwd,
GSS_C_INDEFINITE,
- cfg->allowed_mechs,
+ allowed_mechs,
GSS_C_INITIATE,
- &user_cred, NULL, NULL);
+ &user_cred, &actual_mechs, NULL);
if (GSS_ERROR(maj)) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req,
"In Basic Auth, %s",
@@ -406,27 +414,6 @@ static bool mag_auth_basic(request_rec *req,
goto done;
}
- if (cred_usage == GSS_C_BOTH) {
- /* If GSS_C_BOTH is used then inquire_cred will return the client
- * name instead of the SPN of the server credentials. Therefore we
- * need to acquire a different set of credential setting
- * GSS_C_ACCEPT explicitly */
- if (!mag_acquire_creds(req, cfg, cfg->allowed_mechs,
- GSS_C_ACCEPT, &server_cred, NULL)) {
- goto done;
- }
- } else {
- server_cred = acquired_cred;
- }
- maj = gss_inquire_cred(&min, server_cred, &server,
- NULL, NULL, NULL);
- if (GSS_ERROR(maj)) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req,
- "%s", mag_error(req, "gss_inquired_cred_() "
- "failed", maj, min));
- goto done;
- }
-
#ifdef HAVE_CRED_STORE
if (cfg->deleg_ccache_dir) {
/* delegate ourselves credentials so we store them as requested */
@@ -434,45 +421,89 @@ static bool mag_auth_basic(request_rec *req,
}
#endif
- do {
- /* output and input are inverted here, this is intentional */
- maj = gss_init_sec_context(&min, user_cred, &user_ctx, server,
- GSS_C_NO_OID, init_flags, 300,
- GSS_C_NO_CHANNEL_BINDINGS, &output,
- NULL, &input, NULL, NULL);
- if (GSS_ERROR(maj)) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req,
- "%s", mag_error(req, "gss_init_sec_context() "
- "failed", maj, min));
- goto done;
+ for (int i = 0; i < actual_mechs->count; i++) {
+
+ /* skip spnego if present (it is usually present when
+ * cfg->allowed_mechs is not set) */
+ if (gss_oid_equal(&actual_mechs->elements[i],
+ &gss_mech_spnego)) {
+ continue;
}
+
+ /* free these if looping */
gss_release_buffer(&min, &output);
- maj = gss_accept_sec_context(&min, &server_ctx, acquired_cred,
- &input, GSS_C_NO_CHANNEL_BINDINGS,
- client, mech_type, &output, NULL,
- vtime, delegated_cred);
+ 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];
+
+ /* 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);
if (GSS_ERROR(maj)) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req,
- "%s", mag_error(req, "gss_accept_sec_context()"
- " failed", maj, min));
- goto done;
+ "%s", mag_error(req, "gss_inquired_cred_() "
+ "failed", maj, min));
+ continue;
}
- gss_release_buffer(&min, &input);
- } while (maj == GSS_S_CONTINUE_NEEDED);
- ret = true;
+ 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,
+ &actual_mechs->elements[i], init_flags,
+ 300, GSS_C_NO_CHANNEL_BINDINGS, &output,
+ NULL, &input, NULL, NULL);
+ if (GSS_ERROR(maj)) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req,
+ "%s", mag_error(req, "gss_init_sec_context() "
+ "failed", maj, min));
+ break;
+ }
+ gss_release_buffer(&min, &output);
+ maj = gss_accept_sec_context(&min, &server_ctx, server_cred,
+ &input, GSS_C_NO_CHANNEL_BINDINGS,
+ client, mech_type, &output, NULL,
+ vtime, delegated_cred);
+ if (GSS_ERROR(maj)) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req,
+ "%s", mag_error(req, "gss_accept_sec_context()"
+ " failed", maj, min));
+ break;
+ }
+ gss_release_buffer(&min, &input);
+ } while (maj == GSS_S_CONTINUE_NEEDED);
+
+ if (maj == GSS_S_COMPLETE) {
+ ret = true;
+ break;
+ }
+ }
done:
gss_release_buffer(&min, &output);
gss_release_buffer(&min, &input);
gss_release_name(&min, &server);
- if (server_cred != acquired_cred) {
- gss_release_cred(&min, &server_cred);
- }
+ gss_release_cred(&min, &server_cred);
gss_delete_sec_context(&min, &server_ctx, GSS_C_NO_BUFFER);
gss_release_name(&min, &user);
gss_release_cred(&min, &user_cred);
gss_delete_sec_context(&min, &user_ctx, GSS_C_NO_BUFFER);
+ gss_release_oid_set(&min, &actual_mechs);
#ifdef HAVE_GSS_KRB5_CCACHE_NAME
if (user_ccache != NULL) {
maj = gss_krb5_ccache_name(&min, orig_ccache, NULL);
@@ -692,21 +723,20 @@ static int mag_auth(request_rec *req)
cred_usage = GSS_C_BOTH;
}
#endif
- if (!mag_acquire_creds(req, cfg, desired_mechs,
- cred_usage, &acquired_cred, NULL)) {
- goto done;
- }
-
if (auth_type == AUTH_TYPE_BASIC) {
if (mag_auth_basic(req, cfg, ba_user, ba_pwd,
- acquired_cred, cred_usage,
- &client, &mech_type,
+ cred_usage, &client, &mech_type,
&delegated_cred, &vtime)) {
goto complete;
}
goto done;
}
+ if (!mag_acquire_creds(req, cfg, desired_mechs,
+ cred_usage, &acquired_cred, NULL)) {
+ goto done;
+ }
+
if (auth_type == AUTH_TYPE_NEGOTIATE &&
cfg->allowed_mechs != GSS_C_NO_OID_SET) {
maj = gss_set_neg_mechs(&min, acquired_cred, cfg->allowed_mechs);