Skip to content

Commit d399969

Browse files
committed
Special ccache handling for {HOSTNAME} acceptor
This applies only to the case when GssapiS4U2Proxy is enabled. When using the {HOTNAME} 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 <[email protected]>
1 parent 70da315 commit d399969

File tree

1 file changed

+57
-7
lines changed

1 file changed

+57
-7
lines changed

src/mod_auth_gssapi.c

Lines changed: 57 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,
@@ -221,12 +224,59 @@ static bool mag_acquire_creds(request_rec *req,
221224
"gss_import_name() failed to import hostnname");
222225
return false;
223226
}
227+
224228
} else {
225229
acceptor_name = cfg->acceptor_name;
226230
}
227231

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

231281
maj = gss_acquire_cred_from(&min, acceptor_name, GSS_C_INDEFINITE,
232282
desired_mechs, cred_usage, store, creds,
@@ -287,8 +337,8 @@ static char *escape(apr_pool_t *pool, const char *name,
287337
return escaped;
288338
}
289339

290-
static char *get_ccache_name(request_rec *req, char *dir, const char *gss_name,
291-
bool use_unique, struct mag_conn *mc)
340+
static char *get_ccache_name(request_rec *req, char *dir, const char *name,
341+
bool use_unique, apr_pool_t *pool)
292342
{
293343
char *ccname, *escaped;
294344
int ccachefd;
@@ -297,15 +347,15 @@ static char *get_ccache_name(request_rec *req, char *dir, const char *gss_name,
297347
/* We need to escape away '/', we can't have path separators in
298348
* a ccache file name */
299349
/* first double escape the esacping char (~) if any */
300-
escaped = escape(req->pool, gss_name, '~', "~~");
350+
escaped = escape(req->pool, name, '~', "~~");
301351
/* then escape away the separator (/) if any */
302352
escaped = escape(req->pool, escaped, '/', "~");
303353

304354
if (use_unique == false) {
305-
return apr_psprintf(mc->pool, "%s/%s", dir, escaped);
355+
return apr_psprintf(pool, "%s/%s", dir, escaped);
306356
}
307357

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

310360
umask_save = umask(0177);
311361
ccachefd = mkstemp(ccname);
@@ -1297,7 +1347,7 @@ static int mag_complete(struct mag_req_cfg *req_cfg, struct mag_conn *mc,
12971347
"requester: %s", mc->gss_name);
12981348

12991349
ccache_path = get_ccache_name(req, cfg->deleg_ccache_dir, mc->gss_name,
1300-
cfg->deleg_ccache_unique, mc);
1350+
cfg->deleg_ccache_unique, mc->pool);
13011351
if (ccache_path == NULL) {
13021352
goto done;
13031353
}

0 commit comments

Comments
 (0)