Skip to content

Commit

Permalink
Add S4U2Proxy support
Browse files Browse the repository at this point in the history
SU2Proxy support is enabled when GssapiUseS4U2Proxy is set to On
When S4U2Proxy is enabled GssapiDelegCcacheDir is used to determine
where delegated credentials are stored. The ccache type used is always
of type FILE and is located in the provided directory (defaults to /tmp).
The credentials are stored in a file named after the client credentials
so the directory SHOUL NOT be world writeable if a mutiuser system is
used as ccache file names are predictable.
  • Loading branch information
simo5 committed Jul 20, 2014
1 parent 6e86569 commit 5401c93
Show file tree
Hide file tree
Showing 2 changed files with 127 additions and 21 deletions.
144 changes: 124 additions & 20 deletions src/mod_auth_gssapi.c
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,39 @@ static bool mag_conn_is_https(conn_rec *c)
return false;
}

static void mag_store_deleg_creds(request_rec *req,
char *dir, char *clientname,
gss_cred_id_t delegated_cred,
char **ccachefile)
{
gss_key_value_element_desc element;
gss_key_value_set_desc store;
char *value;
uint32_t maj, min;

value = apr_psprintf(req->pool, "FILE:%s/%s", dir, clientname);
if (!value) {
ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, NULL,
"OOM storing delegated credentials");
return;
}

element.key = "ccache";
element.value = value;
store.elements = &element;
store.count = 1;

maj = gss_store_cred_into(&min, delegated_cred, GSS_C_INITIATE,
GSS_C_NULL_OID, 1, 1, &store, NULL, NULL);
if (GSS_ERROR(maj)) {
ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, req,
mag_error(req, "failed to store delegated creds",
maj, min));
}

*ccachefile = value;
}

static int mag_auth(request_rec *req)
{
const char *type;
Expand All @@ -129,6 +162,7 @@ static int mag_auth(request_rec *req)
gss_buffer_desc output = GSS_C_EMPTY_BUFFER;
gss_buffer_desc name = GSS_C_EMPTY_BUFFER;
gss_name_t client = GSS_C_NO_NAME;
gss_cred_id_t acquired_cred = GSS_C_NO_CREDENTIAL;
gss_cred_id_t delegated_cred = GSS_C_NO_CREDENTIAL;
uint32_t flags;
uint32_t vtime;
Expand Down Expand Up @@ -209,7 +243,22 @@ static int mag_auth(request_rec *req)
if (!input.value) goto done;
input.length = apr_base64_decode(input.value, auth_header_value);

maj = gss_accept_sec_context(&min, pctx, GSS_C_NO_CREDENTIAL,
#ifdef HAVE_GSS_ACQUIRE_CRED_FROM
if (cfg->use_s4u2proxy) {
maj = gss_acquire_cred_from(&min, GSS_C_NO_NAME, 0,
GSS_C_NO_OID_SET, GSS_C_BOTH,
cfg->cred_store, &acquired_cred,
NULL, NULL);
if (GSS_ERROR(maj)) {
ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, req,
mag_error(req, "gss_acquire_cred_from() failed",
maj, min));
goto done;
}
}
#endif

maj = gss_accept_sec_context(&min, pctx, acquired_cred,
&input, GSS_C_NO_CHANNEL_BINDINGS,
&client, &mech_type, &output, &flags, &vtime,
&delegated_cred);
Expand All @@ -234,16 +283,6 @@ static int mag_auth(request_rec *req)
goto done;
}

#ifdef HAVE_GSS_STORE_CRED_INTO
if (cfg->cred_store.count != 0 && delegated_cred != GSS_C_NO_CREDENTIAL) {
gss_key_value_set_desc store = {0, NULL};
/* FIXME: run substitutions */

maj = gss_store_cred_into(&min, delegated_cred, GSS_C_INITIATE,
GSS_C_NULL_OID, 1, 1, &store, NULL, NULL);
}
#endif

req->ap_auth_type = apr_pstrdup(req->pool, "Negotiate");

/* Always set the GSS name in an env var */
Expand All @@ -257,6 +296,19 @@ static int mag_auth(request_rec *req)
clientname = apr_pstrndup(req->pool, name.value, name.length);
apr_table_set(req->subprocess_env, "GSS_NAME", clientname);

#ifdef HAVE_GSS_STORE_CRED_INTO
if (cfg->deleg_ccache_dir && delegated_cred != GSS_C_NO_CREDENTIAL) {
char *ccachefile = NULL;

mag_store_deleg_creds(req, cfg->deleg_ccache_dir, clientname,
delegated_cred, &ccachefile);

if (ccachefile) {
apr_table_set(req->subprocess_env, "KRB5CCNAME", ccachefile);
}
}
#endif

if (cfg->map_to_local) {
maj = gss_localname(&min, client, mech_type, &lname);
if (maj != GSS_S_COMPLETE) {
Expand Down Expand Up @@ -346,6 +398,21 @@ static const char *mag_use_sess(cmd_parms *parms, void *mconfig, int on)
return NULL;
}

static const char *mag_use_s4u2p(cmd_parms *parms, void *mconfig, int on)
{
struct mag_config *cfg = (struct mag_config *)mconfig;
cfg->use_s4u2proxy = on ? true : false;

if (cfg->deleg_ccache_dir == NULL) {
cfg->deleg_ccache_dir = apr_pstrdup(parms->pool, "/tmp");
if (!cfg->deleg_ccache_dir) {
ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0,
parms->server, "%s", "OOM setting deleg_ccache_dir.");
}
}
return NULL;
}

static const char *mag_sess_key(cmd_parms *parms, void *mconfig, const char *w)
{
struct mag_config *cfg = (struct mag_config *)mconfig;
Expand Down Expand Up @@ -387,6 +454,8 @@ static const char *mag_sess_key(cmd_parms *parms, void *mconfig, const char *w)
return NULL;
}

#define MAX_CRED_OPTIONS 10

static const char *mag_cred_store(cmd_parms *parms, void *mconfig,
const char *w)
{
Expand All @@ -413,22 +482,49 @@ static const char *mag_cred_store(cmd_parms *parms, void *mconfig,
return NULL;
}

size = sizeof(gss_key_value_element_desc) * cfg->cred_store.count + 1;
elements = apr_palloc(parms->pool, size);
if (!elements) {
if (!cfg->cred_store) {
cfg->cred_store = apr_pcalloc(parms->pool,
sizeof(gss_key_value_set_desc));
if (!cfg->cred_store) {
ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, parms->server,
"%s", "OOM handling GssapiCredStore option");
return NULL;
}
size = sizeof(gss_key_value_element_desc) * MAX_CRED_OPTIONS;
cfg->cred_store->elements = apr_palloc(parms->pool, size);
if (!cfg->cred_store->elements) {
ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, parms->server,
"%s", "OOM handling GssapiCredStore option");
}
}

elements = cfg->cred_store->elements;
count = cfg->cred_store->count;

if (count >= MAX_CRED_OPTIONS) {
ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, parms->server,
"%s", "OOM handling GssapiCredStore option");
"Too many GssapiCredStore options (MAX: %d)",
MAX_CRED_OPTIONS);
return NULL;
}
cfg->cred_store->count++;

for (count = 0; count < cfg->cred_store.count; count++) {
elements[count] = cfg->cred_store.elements[count];
}
elements[count].key = key;
elements[count].value = value;

cfg->cred_store.elements = elements;
cfg->cred_store.count = count;
return NULL;
}

static const char *mag_deleg_ccache_dir(cmd_parms *parms, void *mconfig,
const char *value)
{
struct mag_config *cfg = (struct mag_config *)mconfig;

cfg->deleg_ccache_dir = apr_pstrdup(parms->pool, value);
if (!cfg->deleg_ccache_dir) {
ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, parms->server,
"%s", "OOM handling GssapiDelegCcacheDir option");
}

return NULL;
}
Expand All @@ -444,8 +540,16 @@ static const command_rec mag_commands[] = {
"Authentication uses mod_sessions to hold status"),
AP_INIT_RAW_ARGS("GssapiSessionKey", mag_sess_key, NULL, OR_AUTHCFG,
"Key Used to seal session data."),
#ifdef HAVE_GSS_ACQUIRE_CRED_FROM
AP_INIT_FLAG("GssapiUseS4U2Proxy", mag_use_s4u2p, NULL, OR_AUTHCFG,
"Initializes credentials for s4u2proxy usage"),
#endif
#ifdef HAVE_GSS_STORE_CRED_INTO
AP_INIT_ITERATE("GssapiCredStore", mag_cred_store, NULL, OR_AUTHCFG,
"Credential Store"),
AP_INIT_RAW_ARGS("GssapiDelegCcacheDir", mag_deleg_ccache_dir, NULL,
OR_AUTHCFG, "Directory to store delegated credentials"),
#endif
{ NULL }
};

Expand Down
4 changes: 3 additions & 1 deletion src/mod_auth_gssapi.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,9 @@ struct mag_config {
bool map_to_local;
bool gss_conn_ctx;
bool use_sessions;
gss_key_value_set_desc cred_store;
bool use_s4u2proxy;
char *deleg_ccache_dir;
gss_key_value_set_desc *cred_store;
struct seal_key *mag_skey;
};

Expand Down

0 comments on commit 5401c93

Please sign in to comment.