X-Git-Url: http://www.project-moonshot.org/gitweb/?p=mod_auth_gssapi.git;a=blobdiff_plain;f=src%2Fmod_auth_gssapi.c;h=b168dbf270134e706b49bfa486ab6817fa8d55ca;hp=b5e6a2e807fb379e936a18f82899dbc7acf2f0c6;hb=0cea28e5b05b340bbb3b2b60e3a326a6a7d1fcb0;hpb=1fc49992c107bd3830921a8198929a936e8b7fb2 diff --git a/src/mod_auth_gssapi.c b/src/mod_auth_gssapi.c index b5e6a2e..b168dbf 100644 --- a/src/mod_auth_gssapi.c +++ b/src/mod_auth_gssapi.c @@ -119,6 +119,48 @@ static bool mag_conn_is_https(conn_rec *c) return false; } +static char *escape(apr_pool_t *pool, const char *name, + char find, const char *replace) +{ + char *escaped = NULL; + char *namecopy; + char *n; + char *p; + + namecopy = apr_pstrdup(pool, name); + if (!namecopy) goto done; + + p = strchr(namecopy, find); + if (!p) return namecopy; + + /* first segment */ + n = namecopy; + while (p) { + /* terminate previous segment */ + *p = '\0'; + if (escaped) { + escaped = apr_pstrcat(pool, escaped, n, replace, NULL); + } else { + escaped = apr_pstrcat(pool, n, replace, NULL); + } + if (!escaped) goto done; + /* move to next segment */ + n = p + 1; + p = strchr(n, find); + } + /* append last segment if any */ + if (*n) { + escaped = apr_pstrcat(pool, escaped, n, NULL); + } + +done: + if (!escaped) { + ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, NULL, + "OOM escaping name"); + } + return escaped; +} + static void mag_store_deleg_creds(request_rec *req, char *dir, char *clientname, gss_cred_id_t delegated_cred, @@ -128,8 +170,18 @@ static void mag_store_deleg_creds(request_rec *req, gss_key_value_set_desc store; char *value; uint32_t maj, min; - - value = apr_psprintf(req->pool, "FILE:%s/%s", dir, clientname); + char *escaped; + + /* We need to escape away '/', we can't have path separators in + * a ccache file name */ + /* first double escape the esacping char (~) if any */ + escaped = escape(req->pool, clientname, '~', "~~"); + if (!escaped) return; + /* then escape away the separator (/) if any */ + escaped = escape(req->pool, escaped, '/', "~"); + if (!escaped) return; + + value = apr_psprintf(req->pool, "FILE:%s/%s", dir, escaped); if (!value) { ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, NULL, "OOM storing delegated credentials"); @@ -187,19 +239,45 @@ static int mag_auth(request_rec *req) const char *user_ccache = NULL; const char *orig_ccache = NULL; #endif + uint32_t init_flags = 0; type = ap_auth_type(req); if ((type == NULL) || (strcasecmp(type, "GSSAPI") != 0)) { return DECLINED; } - /* ignore auth for subrequests */ + cfg = ap_get_module_config(req->per_dir_config, &auth_gssapi_module); + + /* implicit auth for subrequests if main auth already happened */ if (!ap_is_initial_req(req)) { - return OK; + type = ap_auth_type(req->main); + if ((type != NULL) && (strcasecmp(type, "GSSAPI") == 0)) { + /* warn if the subrequest location and the main request + * location have different configs */ + if (cfg != ap_get_module_config(req->main->per_dir_config, + &auth_gssapi_module)) { + ap_log_rerror(APLOG_MARK, APLOG_WARNING||APLOG_NOERRNO, 0, + req, "Subrequest authentication bypass on " + "location with different configuration!"); + } + if (req->main->user) { + req->user = apr_pstrdup(req->pool, req->main->user); + return OK; + } else { + ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, req, + "The main request is tasked to establish the " + "security context, can't proceed!"); + return HTTP_UNAUTHORIZED; + } + } else { + ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, req, + "Subrequest GSSAPI auth with no auth on the main " + "request. This operation may fail if other " + "subrequests already established a context or the " + "mechanism requires multiple roundtrips."); + } } - cfg = ap_get_module_config(req->per_dir_config, &auth_gssapi_module); - if (cfg->ssl_only) { if (!mag_conn_is_https(req->connection)) { ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, req, @@ -368,9 +446,15 @@ static int mag_auth(request_rec *req) "failed", maj, min)); goto done; } + + if (cfg->deleg_ccache_dir) { + /* delegate ourselves credentials so we store them as requested */ + init_flags |= GSS_C_DELEG_FLAG; + } + /* output and input are inverted here, this is intentional */ maj = gss_init_sec_context(&min, user_cred, &user_ctx, server, - GSS_C_NO_OID, 0, 300, + GSS_C_NO_OID, init_flags, 300, GSS_C_NO_CHANNEL_BINDINGS, &output, NULL, &input, NULL, NULL); if (GSS_ERROR(maj)) { @@ -396,7 +480,7 @@ static int mag_auth(request_rec *req) gss_release_buffer(&min, &input); /* output and input are inverted here, this is intentional */ maj = gss_init_sec_context(&min, user_cred, &user_ctx, server, - GSS_C_NO_OID, 0, 300, + GSS_C_NO_OID, init_flags, 300, GSS_C_NO_CHANNEL_BINDINGS, &output, NULL, &input, NULL, NULL); if (GSS_ERROR(maj)) { @@ -586,7 +670,7 @@ static const char *mag_use_s4u2p(cmd_parms *parms, void *mconfig, int on) static const char *mag_sess_key(cmd_parms *parms, void *mconfig, const char *w) { struct mag_config *cfg = (struct mag_config *)mconfig; - struct databuf keys; + struct databuf key; unsigned char *val; apr_status_t rc; const char *k; @@ -607,16 +691,16 @@ static const char *mag_sess_key(cmd_parms *parms, void *mconfig, const char *w) return NULL; } - keys.length = (int)apr_base64_decode_binary(val, k); - keys.value = (unsigned char *)val; + key.length = (int)apr_base64_decode_binary(val, k); + key.value = (unsigned char *)val; - if (keys.length != 32) { + if (key.length < 32) { ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, parms->server, - "Invalid key lenght, expected 32 got %d", keys.length); + "Invalid key length, expected >=32 got %d", key.length); return NULL; } - rc = SEAL_KEY_CREATE(cfg->pool, &cfg->mag_skey, &keys); + rc = SEAL_KEY_CREATE(cfg->pool, &cfg->mag_skey, &key); if (rc != OK) { ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, parms->server, "Failed to import sealing key!");