summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRobbie Harwood <rharwood@redhat.com>2016-05-08 02:31:00 -0400
committerSimo Sorce <simo@redhat.com>2016-05-18 17:46:14 -0400
commit6a0bc4f5cd46b1ab85dba5bd2de28f568cc947b0 (patch)
tree8f1451065efa8afb840cde844b48cf1c3de5c6b0
parent6e746f91177902528e42ac982e965fe469aa8855 (diff)
downloadmod_auth_gssapi-6a0bc4f5cd46b1ab85dba5bd2de28f568cc947b0.tar.gz
mod_auth_gssapi-6a0bc4f5cd46b1ab85dba5bd2de28f568cc947b0.tar.xz
mod_auth_gssapi-6a0bc4f5cd46b1ab85dba5bd2de28f568cc947b0.zip
Implement unique ccache names
Unique ccache names may be requested using the GssapiDelegCcacheUnique configuration option. This option is off by default. If both unique ccache names and session use are enabled, then a mechanism for removing old ccaches must be supplied. Signed-off-by: Robbie Harwood <rharwood@redhat.com> Also-authored-by: Petr Vobornik <pvoborni@redhat.com> Reviewed-by: Simo Sorce <simo@redhat.com>
-rw-r--r--README13
-rw-r--r--src/asn1c/GSSSessionData.c17
-rw-r--r--src/asn1c/GSSSessionData.h2
-rw-r--r--src/asn1c/Uint32.c1
-rw-r--r--src/asn1c/Uint32.h1
-rw-r--r--src/asn1c/session.asn13
-rw-r--r--src/environ.c17
-rw-r--r--src/mod_auth_gssapi.c65
-rw-r--r--src/mod_auth_gssapi.h8
-rw-r--r--src/sessions.c10
10 files changed, 103 insertions, 34 deletions
diff --git a/README b/README
index b4eca28..781f3ea 100644
--- a/README
+++ b/README
@@ -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) {