diff options
-rw-r--r-- | README | 13 | ||||
-rw-r--r-- | src/asn1c/GSSSessionData.c | 17 | ||||
-rw-r--r-- | src/asn1c/GSSSessionData.h | 2 | ||||
-rw-r--r-- | src/asn1c/Uint32.c | 1 | ||||
-rw-r--r-- | src/asn1c/Uint32.h | 1 | ||||
-rw-r--r-- | src/asn1c/session.asn1 | 3 | ||||
-rw-r--r-- | src/environ.c | 17 | ||||
-rw-r--r-- | src/mod_auth_gssapi.c | 65 | ||||
-rw-r--r-- | src/mod_auth_gssapi.h | 8 | ||||
-rw-r--r-- | src/sessions.c | 10 |
10 files changed, 103 insertions, 34 deletions
@@ -171,6 +171,19 @@ A user foo@EXAMPLE.COM delegating its credentials would cause the server to 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 diff --git a/src/asn1c/GSSSessionData.c b/src/asn1c/GSSSessionData.c index 12a98e3..f0dcc2e 100644 --- a/src/asn1c/GSSSessionData.c +++ b/src/asn1c/GSSSessionData.c @@ -2,7 +2,6 @@ * 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" @@ -62,6 +61,15 @@ static asn_TYPE_member_t asn_MBR_GSSSessionData_1[] = { 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)) @@ -72,13 +80,14 @@ static asn_TYPE_tag2member_t asn_MAP_GSSSessionData_tag2el_1[] = { { (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 */ @@ -103,7 +112,7 @@ asn_TYPE_descriptor_t asn_DEF_GSSSessionData = { /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 */ }; diff --git a/src/asn1c/GSSSessionData.h b/src/asn1c/GSSSessionData.h index 53556d8..4ae224f 100644 --- a/src/asn1c/GSSSessionData.h +++ b/src/asn1c/GSSSessionData.h @@ -2,7 +2,6 @@ * 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_ @@ -29,6 +28,7 @@ typedef struct GSSSessionData { 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; diff --git a/src/asn1c/Uint32.c b/src/asn1c/Uint32.c index 794f98b..f5d125a 100644 --- a/src/asn1c/Uint32.c +++ b/src/asn1c/Uint32.c @@ -2,7 +2,6 @@ * 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" diff --git a/src/asn1c/Uint32.h b/src/asn1c/Uint32.h index a0ed876..436e26e 100644 --- a/src/asn1c/Uint32.h +++ b/src/asn1c/Uint32.h @@ -2,7 +2,6 @@ * 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_ diff --git a/src/asn1c/session.asn1 b/src/asn1c/session.asn1 index 1762812..f499779 100644 --- a/src/asn1c/session.asn1 +++ b/src/asn1c/session.asn1 @@ -8,6 +8,7 @@ GssapiSessionModule DEFINITIONS ::= BEGIN expiration [2] Uint32, username [3] OCTET STRING, gssname [4] OCTET STRING, - basichash [5] OCTET STRING + basichash [5] OCTET STRING, + ccname [6] OCTET STRING } END diff --git a/src/environ.c b/src/environ.c index 1fffc90..c9378b1 100644 --- a/src/environ.c +++ b/src/environ.c @@ -1,4 +1,4 @@ -/* 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" @@ -243,7 +243,8 @@ static void mag_set_name_attributes(request_rec *req, struct mag_conn *mc) } } -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; @@ -256,7 +257,7 @@ static void mag_set_KRB5CCANME(request_rec *req, char *ccname) "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); } @@ -277,14 +278,8 @@ void mag_set_req_data(request_rec *req, } #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 } diff --git a/src/mod_auth_gssapi.c b/src/mod_auth_gssapi.c index 35bb9a1..d2b5d2b 100644 --- a/src/mod_auth_gssapi.c +++ b/src/mod_auth_gssapi.c @@ -1,4 +1,4 @@ -/* 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" @@ -202,10 +202,11 @@ static char *escape(apr_pool_t *pool, const char *name, 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 */ @@ -214,22 +215,32 @@ char *mag_gss_name_to_ccache_name(request_rec *req, /* 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, @@ -877,9 +888,30 @@ complete: #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 @@ -1006,6 +1038,15 @@ static const char *mag_use_s4u2p(cmd_parms *parms, void *mconfig, int on) 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) @@ -1330,6 +1371,8 @@ static const command_rec mag_commands[] = { "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, diff --git a/src/mod_auth_gssapi.h b/src/mod_auth_gssapi.h index 1973b2b..0c77b8b 100644 --- a/src/mod_auth_gssapi.h +++ b/src/mod_auth_gssapi.h @@ -1,8 +1,10 @@ -/* 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" @@ -68,6 +70,7 @@ struct mag_config { bool use_s4u2proxy; char *deleg_ccache_dir; gss_key_value_set_desc *cred_store; + bool deleg_ccache_unique;; #endif struct seal_key *mag_skey; @@ -112,12 +115,11 @@ struct mag_conn { 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); diff --git a/src/sessions.c b/src/sessions.c index d8c4873..d99b92d 100644 --- a/src/sessions.c +++ b/src/sessions.c @@ -1,4 +1,4 @@ -/* 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" @@ -179,6 +179,12 @@ void mag_check_session(struct mag_req_cfg *cfg, struct mag_conn **conn) 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; @@ -224,6 +230,8 @@ void mag_attempt_session(struct mag_req_cfg *cfg, struct mag_conn *mc) (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) { |