Skip to content

Commit f906f11

Browse files
simo5frozencemetery
authored andcommitted
Special ccache handling for {HOSTNAME} acceptor
This applies only to the case when GssapiS4U2Proxy is enabled. When using the {HOSTNAME} acceptor, the principal used in the server ccache can vary with each request. GSSAPI does not handle gracefully a request to resolve a ccache if there is already another credential under a different name. Even with ccache collections GSSAPI will resolve an existing ccache from the collection if any is available and throw an error if it does not match the desired_name. This even if there is a client_keytab that could be used to initiate a new cache in the collection with the right name. Therefore in case GssapiAcceptor is set to the special value {HOSTNAME}, instead of using the provided ccache or the process default ccache we create a new ccache named after the hostname in the delegated ccache directory. This directory is required when the S4U2Proxy mode is enabled so we are guaranteed to have it available an writable. Signed-off-by: Simo Sorce <simo@redhat.com> [rharwood@redhat.com: nits]
1 parent 9c437ca commit f906f11

File tree

1 file changed

+55
-7
lines changed

1 file changed

+55
-7
lines changed

src/mod_auth_gssapi.c

Lines changed: 55 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,9 @@ static bool mag_conn_is_https(conn_rec *c)
194194
return false;
195195
}
196196

197+
static char *get_ccache_name(request_rec *req, char *dir, const char *name,
198+
bool use_unique, apr_pool_t *pool);
199+
197200
static bool mag_acquire_creds(request_rec *req,
198201
struct mag_config *cfg,
199202
gss_OID_set desired_mechs,
@@ -226,7 +229,52 @@ static bool mag_acquire_creds(request_rec *req,
226229
}
227230

228231
#ifdef HAVE_CRED_STORE
229-
gss_const_key_value_set_t store = cfg->cred_store;
232+
gss_const_key_value_set_t store = NULL;
233+
234+
/* When using multiple names, we need to use individual separate ccaches
235+
* for each principal or gss_acquire_cred() on the default ccache will
236+
* fail when names don't match. This is needed only for the s4u2proxy
237+
* case, where we try to acquire proxy credentials. The lucky thing is
238+
* that in this case we require the use of a delegated creedntials
239+
* directory, so we just use this directory to also hold permanent ccaches
240+
* for individual acceptor names. */
241+
if (cfg->acceptor_name_from_req && cfg->use_s4u2proxy &&
242+
cfg->deleg_ccache_dir) {
243+
244+
gss_key_value_set_desc *s;
245+
bool add = true;
246+
char *ccname;
247+
char *special_name;
248+
249+
special_name = apr_psprintf(req->pool, "acceptor_%s", req->hostname);
250+
ccname = get_ccache_name(req, cfg->deleg_ccache_dir, special_name,
251+
false, req->pool);
252+
253+
s = apr_pcalloc(req->pool, sizeof(gss_key_value_set_desc));
254+
s->count = cfg->cred_store->count;
255+
s->elements = apr_pcalloc(req->pool,
256+
(s->count + 1) *
257+
sizeof(gss_key_value_element_desc));
258+
for (size_t i = 0; i < s->count; i++) {
259+
gss_key_value_element_desc *el = &cfg->cred_store->elements[i];
260+
s->elements[i].key = el->key;
261+
if (strcmp(el->key, "ccache") == 0) {
262+
s->elements[i].value = ccname;
263+
add = false;
264+
} else {
265+
s->elements[i].value = el->value;
266+
}
267+
}
268+
if (add) {
269+
s->elements[s->count].key = "ccache";
270+
s->elements[s->count].value = ccname;
271+
s->count++;
272+
}
273+
274+
store = s;
275+
} else {
276+
store = cfg->cred_store;
277+
}
230278

231279
maj = gss_acquire_cred_from(&min, acceptor_name, GSS_C_INDEFINITE,
232280
desired_mechs, cred_usage, store, creds,
@@ -287,8 +335,8 @@ static char *escape(apr_pool_t *pool, const char *name,
287335
return escaped;
288336
}
289337

290-
static char *get_ccache_name(request_rec *req, char *dir, const char *gss_name,
291-
bool use_unique, struct mag_conn *mc)
338+
static char *get_ccache_name(request_rec *req, char *dir, const char *name,
339+
bool use_unique, apr_pool_t *pool)
292340
{
293341
char *ccname, *escaped;
294342
int ccachefd;
@@ -297,15 +345,15 @@ static char *get_ccache_name(request_rec *req, char *dir, const char *gss_name,
297345
/* We need to escape away '/', we can't have path separators in
298346
* a ccache file name */
299347
/* first double escape the esacping char (~) if any */
300-
escaped = escape(req->pool, gss_name, '~', "~~");
348+
escaped = escape(req->pool, name, '~', "~~");
301349
/* then escape away the separator (/) if any */
302350
escaped = escape(req->pool, escaped, '/', "~");
303351

304352
if (use_unique == false) {
305-
return apr_psprintf(mc->pool, "%s/%s", dir, escaped);
353+
return apr_psprintf(pool, "%s/%s", dir, escaped);
306354
}
307355

308-
ccname = apr_psprintf(mc->pool, "%s/%s-XXXXXX", dir, escaped);
356+
ccname = apr_psprintf(pool, "%s/%s-XXXXXX", dir, escaped);
309357

310358
umask_save = umask(0177);
311359
ccachefd = mkstemp(ccname);
@@ -1297,7 +1345,7 @@ static int mag_complete(struct mag_req_cfg *req_cfg, struct mag_conn *mc,
12971345
"requester: %s", mc->gss_name);
12981346

12991347
ccache_path = get_ccache_name(req, cfg->deleg_ccache_dir, mc->gss_name,
1300-
cfg->deleg_ccache_unique, mc);
1348+
cfg->deleg_ccache_unique, mc->pool);
13011349
if (ccache_path == NULL) {
13021350
goto done;
13031351
}

0 commit comments

Comments
 (0)