create a ccache file named /var/run/httpd/clientcaches/foo@EXAMPLE.COM
+### GssapiDelegCcacheUnique
+
+Enables using unique ccache names for delegation. ccache files will be placed
+in GssapiDelegCcacheDir and named using the principal and a six-digit unique
+suffix.
+
+**Note:** Consuming application must delete the ccache otherwise it will
+litter the filesystem if sessions are used. An example sweeper can be found
+in the contrib directory.
+
+#### Example
+ GssapiDelegCcacheUnique On
+
### GssapiUseS4U2Proxy
Enables the use of the s4u2Proxy Kerberos extension also known as
* Generated by asn1c-0.9.27 (http://lionet.info/asn1c)
* From ASN.1 module "GssapiSessionModule"
* found in "session.asn1"
- * `asn1c -fskeletons-copy`
*/
#include "GSSSessionData.h"
0,
"basichash"
},
+ { ATF_NOFLAGS, 0, offsetof(struct GSSSessionData, ccname),
+ (ASN_TAG_CLASS_CONTEXT | (6 << 2)),
+ +1, /* EXPLICIT tag at current level */
+ &asn_DEF_OCTET_STRING,
+ 0, /* Defer constraints checking to the member type */
+ 0, /* PER is not compiled, use -gen-PER */
+ 0,
+ "ccname"
+ },
};
static ber_tlv_tag_t asn_DEF_GSSSessionData_tags_1[] = {
(ASN_TAG_CLASS_UNIVERSAL | (16 << 2))
{ (ASN_TAG_CLASS_CONTEXT | (2 << 2)), 2, 0, 0 }, /* expiration */
{ (ASN_TAG_CLASS_CONTEXT | (3 << 2)), 3, 0, 0 }, /* username */
{ (ASN_TAG_CLASS_CONTEXT | (4 << 2)), 4, 0, 0 }, /* gssname */
- { (ASN_TAG_CLASS_CONTEXT | (5 << 2)), 5, 0, 0 } /* basichash */
+ { (ASN_TAG_CLASS_CONTEXT | (5 << 2)), 5, 0, 0 }, /* basichash */
+ { (ASN_TAG_CLASS_CONTEXT | (6 << 2)), 6, 0, 0 } /* ccname */
};
static asn_SEQUENCE_specifics_t asn_SPC_GSSSessionData_specs_1 = {
sizeof(struct GSSSessionData),
offsetof(struct GSSSessionData, _asn_ctx),
asn_MAP_GSSSessionData_tag2el_1,
- 6, /* Count of tags in the map */
+ 7, /* Count of tags in the map */
0, 0, 0, /* Optional elements (not needed) */
-1, /* Start extensions */
-1 /* Stop extensions */
/sizeof(asn_DEF_GSSSessionData_tags_1[0]), /* 1 */
0, /* No PER visible constraints */
asn_MBR_GSSSessionData_1,
- 6, /* Elements count */
+ 7, /* Elements count */
&asn_SPC_GSSSessionData_specs_1 /* Additional specs */
};
* Generated by asn1c-0.9.27 (http://lionet.info/asn1c)
* From ASN.1 module "GssapiSessionModule"
* found in "session.asn1"
- * `asn1c -fskeletons-copy`
*/
#ifndef _GSSSessionData_H_
OCTET_STRING_t username;
OCTET_STRING_t gssname;
OCTET_STRING_t basichash;
+ OCTET_STRING_t ccname;
/* Context for parsing across buffer boundaries */
asn_struct_ctx_t _asn_ctx;
* Generated by asn1c-0.9.27 (http://lionet.info/asn1c)
* From ASN.1 module "GssapiSessionModule"
* found in "session.asn1"
- * `asn1c -fskeletons-copy`
*/
#include "Uint32.h"
* Generated by asn1c-0.9.27 (http://lionet.info/asn1c)
* From ASN.1 module "GssapiSessionModule"
* found in "session.asn1"
- * `asn1c -fskeletons-copy`
*/
#ifndef _Uint32_H_
expiration [2] Uint32,
username [3] OCTET STRING,
gssname [4] OCTET STRING,
- basichash [5] OCTET STRING
+ basichash [5] OCTET STRING,
+ ccname [6] OCTET STRING
}
END
-/* Copyright (C) 2015 mod_auth_gssapi contributors - See COPYING for (C) terms */
+/* Copyright (C) 2015, 2016 mod_auth_gssapi contributors - See COPYING for (C) terms */
#include "mod_auth_gssapi.h"
}
}
-static void mag_set_KRB5CCANME(request_rec *req, char *ccname)
+static void mag_set_KRB5CCANME(request_rec *req, const char *dir,
+ const char *ccname)
{
apr_status_t status;
apr_finfo_t finfo;
"KRB5CCNAME file (%s) lookup failed!", ccname);
}
- value = apr_psprintf(req->pool, "FILE:%s", ccname);
+ value = apr_psprintf(req->pool, "FILE:%s/%s", dir, ccname);
apr_table_set(req->subprocess_env, "KRB5CCNAME", value);
}
}
#ifdef HAVE_CRED_STORE
- if (cfg->deleg_ccache_dir && mc->delegated) {
- char *ccname;
- ccname = mag_gss_name_to_ccache_name(req,
- cfg->deleg_ccache_dir,
- mc->gss_name);
- if (ccname) {
- mag_set_KRB5CCANME(req, ccname);
- }
+ if (cfg->deleg_ccache_dir && mc->delegated && mc->ccname) {
+ mag_set_KRB5CCANME(req, cfg->deleg_ccache_dir, mc->ccname);
}
#endif
}
-/* Copyright (C) 2014 mod_auth_gssapi contributors - See COPYING for (C) terms */
+/* Copyright (C) 2014, 2016 mod_auth_gssapi contributors - See COPYING for (C) terms */
#include "mod_auth_gssapi.h"
return escaped;
}
-char *mag_gss_name_to_ccache_name(request_rec *req,
- char *dir, const char *gss_name)
+static char *get_ccache_name(request_rec *req, char *dir, const char *gss_name,
+ bool use_unique, struct mag_conn *mc)
{
- char *escaped;
+ char *ccname, *escaped;
+ int ccachefd;
/* We need to escape away '/', we can't have path separators in
* a ccache file name */
/* then escape away the separator (/) if any */
escaped = escape(req->pool, escaped, '/', "~");
- return apr_psprintf(req->pool, "%s/%s", dir, escaped);
+ if (use_unique == false) {
+ return apr_psprintf(req->pool, "%s/%s", dir, escaped);
+ }
+
+ ccname = apr_psprintf(mc->pool, "%s/%s-XXXXXX", dir, escaped);
+
+ ccachefd = mkstemp(ccname);
+ if (ccachefd == -1) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, req,
+ "creating unique ccache file %s failed", ccname);
+ return NULL;
+ }
+ close(ccachefd);
+ return ccname;
}
-static void mag_store_deleg_creds(request_rec *req,
- char *dir, const char *gss_name,
+static void mag_store_deleg_creds(request_rec *req, const char *ccname,
gss_cred_id_t delegated_cred)
{
gss_key_value_element_desc element;
gss_key_value_set_desc store;
- char *ccname;
uint32_t maj, min;
element.key = "ccache";
store.elements = &element;
store.count = 1;
- ccname = mag_gss_name_to_ccache_name(req, dir, gss_name);
element.value = apr_psprintf(req->pool, "FILE:%s", ccname);
maj = gss_store_cred_into(&min, delegated_cred, GSS_C_INITIATE,
#ifdef HAVE_CRED_STORE
if (cfg->deleg_ccache_dir && delegated_cred != GSS_C_NO_CREDENTIAL) {
- mag_store_deleg_creds(req, cfg->deleg_ccache_dir, mc->gss_name,
- delegated_cred);
+ char *ccache_path;
+
+ mc->ccname = 0;
+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, req,
+ "requester: %s", mc->gss_name);
+
+ ccache_path = get_ccache_name(req, cfg->deleg_ccache_dir, mc->gss_name,
+ cfg->deleg_ccache_unique, mc);
+ if (ccache_path == NULL) {
+ goto done;
+ }
+
+ mag_store_deleg_creds(req, ccache_path, delegated_cred);
mc->delegated = true;
+
+ if (!req_cfg->use_sessions && cfg->deleg_ccache_unique) {
+ /* queue removing ccache to avoid littering filesystem */
+ apr_pool_cleanup_register(mc->pool, ccache_path,
+ (int (*)(void *)) unlink,
+ apr_pool_cleanup_null);
+ }
+
+ /* extract filename from full path */
+ mc->ccname = strrchr(ccache_path, '/') + 1;
}
#endif
return NULL;
}
+
+static const char *mag_deleg_ccache_unique(cmd_parms *parms, void *mconfig,
+ int on)
+{
+ struct mag_config *cfg = (struct mag_config *)mconfig;
+ cfg->deleg_ccache_unique = on ? true : false;
+ return NULL;
+}
+
#endif
static const char *mag_sess_key(cmd_parms *parms, void *mconfig, const char *w)
"Credential Store"),
AP_INIT_RAW_ARGS("GssapiDelegCcacheDir", mag_deleg_ccache_dir, NULL,
OR_AUTHCFG, "Directory to store delegated credentials"),
+ AP_INIT_FLAG("GssapiDelegCcacheUnique", mag_deleg_ccache_unique, NULL,
+ OR_AUTHCFG, "Use unique ccaches for delgation"),
#endif
#ifdef HAVE_GSS_ACQUIRE_CRED_WITH_PASSWORD
AP_INIT_FLAG("GssapiBasicAuth", mag_use_basic_auth, NULL, OR_AUTHCFG,
-/* Copyright (C) 2014 mod_auth_gssapi contributors - See COPYING for (C) terms */
+/* Copyright (C) 2014, 2016 mod_auth_gssapi contributors - See COPYING for (C) terms */
#include <stdbool.h>
#include <stdint.h>
+#include <stdlib.h>
#include <time.h>
+#include <unistd.h>
#define APR_WANT_STRFUNC
#include "apr_want.h"
bool use_s4u2proxy;
char *deleg_ccache_dir;
gss_key_value_set_desc *cred_store;
+ bool deleg_ccache_unique;;
#endif
struct seal_key *mag_skey;
bool is_preserved;
int na_count;
struct mag_attr *name_attributes;
+ const char *ccname;
};
#define discard_const(ptr) ((void *)((uintptr_t)(ptr)))
struct mag_conn *mag_new_conn_ctx(apr_pool_t *pool);
const char *mag_str_auth_type(int auth_type);
-char *mag_gss_name_to_ccache_name(request_rec *req,
- char *dir, const char *gss_name);
char *mag_error(request_rec *req, const char *msg, uint32_t maj, uint32_t min);
-/* Copyright (C) 2014 mod_auth_gssapi contributors - See COPYING for (C) terms */
+/* Copyright (C) 2014, 2016 mod_auth_gssapi contributors - See COPYING for (C) terms */
#include "mod_auth_gssapi.h"
#include "asn1c/GSSSessionData.h"
memcpy(mc->basic_hash.value,
gsessdata->basichash.buf, gsessdata->basichash.size);
+ /* ccname */
+ mc->ccname = apr_pstrndup(mc->pool,
+ (char *)gsessdata->ccname.buf,
+ gsessdata->ccname.size);
+ if (!mc->ccname) goto done;
+
/* OK we have a valid token */
mc->established = true;
(const char *)mc->basic_hash.value,
mc->basic_hash.length) != 0)
goto done;
+ if (OCTET_STRING_fromString(&gsessdata.ccname, mc->ccname) != 0)
+ goto done;
ret = encode_GSSSessionData(req->pool, &gsessdata,
&plainbuf.value, &plainbuf.length);
if (ret == false) {