summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimo Sorce <simo@redhat.com>2014-07-07 11:42:57 -0400
committerSimo Sorce <simo@redhat.com>2014-07-09 05:14:36 -0400
commitf9cd5e4ba41b112804f824f460108cfb743526e0 (patch)
treeefd2bcf51da456f9097fbdc8fa2465f05b2f5422
parent285432d9f918c45a1746d0f569eee727aaa9673b (diff)
downloadmod_auth_gssapi-sessions.tar.gz
mod_auth_gssapi-sessions.tar.xz
mod_auth_gssapi-sessions.zip
Add permanent session keys supportsessions
Keys (encryption+MAC) can now be stored in apache configuration. The key must be a base64 encoded blob of original length of 32 bytes (16 bytes for encryption and 16 for the MAC key) The format is: key:<base64 blob>
-rw-r--r--src/crypto.c65
-rw-r--r--src/crypto.h3
-rw-r--r--src/mod_auth_gssapi.c53
3 files changed, 94 insertions, 27 deletions
diff --git a/src/crypto.c b/src/crypto.c
index 9be58e5..584bf16 100644
--- a/src/crypto.c
+++ b/src/crypto.c
@@ -13,56 +13,73 @@ struct seal_key {
unsigned char *hkey;
};
-apr_status_t SEAL_KEY_CREATE(struct seal_key **skey)
+apr_status_t SEAL_KEY_CREATE(apr_pool_t *p, struct seal_key **skey,
+ struct databuf *keys)
{
struct seal_key *n;
+ int keylen;
int ret;
- n = calloc(1, sizeof(*n));
+ n = apr_pcalloc(p, sizeof(*n));
if (!n) return ENOMEM;
n->cipher = EVP_aes_128_cbc();
if (!n->cipher) {
- free(n);
- return EFAULT;
+ ret = EFAULT;
+ goto done;
}
+ keylen = n->cipher->key_len;
+
n->md = EVP_sha256();
if (!n->md) {
- free(n);
- return EFAULT;
+ ret = EFAULT;
+ goto done;
}
- n->ekey = malloc(n->cipher->key_len);
+ n->ekey = apr_palloc(p, keylen);
if (!n->ekey) {
- free(n);
- return ENOMEM;
+ ret = ENOMEM;
+ goto done;
}
- n->hkey = malloc(n->cipher->key_len);
+ n->hkey = apr_palloc(p, keylen);
if (!n->hkey) {
- free(n);
- return ENOMEM;
+ ret = ENOMEM;
+ goto done;
}
- ret = RAND_bytes(n->ekey, n->cipher->key_len);
- if (ret == 0) {
- free(n->ekey);
- free(n->hkey);
- free(n);
- return EFAULT;
+ if (keys) {
+ if (keys->length != (keylen * 2)) {
+ ret = EINVAL;
+ goto done;
+ }
+ memcpy(n->ekey, keys->value, keylen);
+ memcpy(n->hkey, keys->value + keylen, keylen);
+ } else {
+ ret = RAND_bytes(n->ekey, keylen);
+ if (ret == 0) {
+ ret = EFAULT;
+ goto done;
+ }
+
+ ret = RAND_bytes(n->hkey, keylen);
+ if (ret == 0) {
+ ret = EFAULT;
+ goto done;
+ }
}
- ret = RAND_bytes(n->hkey, n->cipher->key_len);
- if (ret == 0) {
+ ret = 0;
+done:
+ if (ret) {
free(n->ekey);
free(n->hkey);
free(n);
- return EFAULT;
+ } else {
+ *skey = n;
}
-
- *skey = n;
- return 0;
+ return ret;
}
apr_status_t SEAL_BUFFER(apr_pool_t *p, struct seal_key *skey,
diff --git a/src/crypto.h b/src/crypto.h
index a8b5ca0..cfc83fa 100644
--- a/src/crypto.h
+++ b/src/crypto.h
@@ -10,7 +10,8 @@ struct databuf {
int length;
};
-apr_status_t SEAL_KEY_CREATE(struct seal_key **skey);
+apr_status_t SEAL_KEY_CREATE(apr_pool_t *p, struct seal_key **skey,
+ struct databuf *keys);
apr_status_t SEAL_BUFFER(apr_pool_t *p, struct seal_key *skey,
struct databuf *plain, struct databuf *cipher);
apr_status_t UNSEAL_BUFFER(apr_pool_t *p, struct seal_key *skey,
diff --git a/src/mod_auth_gssapi.c b/src/mod_auth_gssapi.c
index 240d47a..668470f 100644
--- a/src/mod_auth_gssapi.c
+++ b/src/mod_auth_gssapi.c
@@ -47,6 +47,7 @@ module AP_MODULE_DECLARE_DATA auth_gssapi_module;
APR_DECLARE_OPTIONAL_FN(int, ssl_is_https, (conn_rec *));
struct mag_config {
+ apr_pool_t *pool;
bool ssl_only;
bool map_to_local;
bool gss_conn_ctx;
@@ -218,6 +219,8 @@ static void mag_check_session(request_rec *req,
}
if (!cfg->mag_skey) {
+ ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, req,
+ "Session key not available, no cookies!");
/* we do not have a key, just return */
return;
}
@@ -273,13 +276,15 @@ static void mag_attempt_session(request_rec *req,
if (!mc->established) return;
rc = mag_session_load(req, &sess);
if (rc != OK || sess == NULL) {
- ap_log_rerror(APLOG_MARK, APLOG_INFO|APLOG_NOERRNO, 0, req,
+ ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, req,
"Sessions not available, can't send cookies!");
return;
}
if (!cfg->mag_skey) {
- rc = SEAL_KEY_CREATE(&cfg->mag_skey);
+ ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, req,
+ "Session key not available, generating new one.");
+ rc = SEAL_KEY_CREATE(cfg->pool, &cfg->mag_skey, NULL);
if (rc != OK) {
ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, req,
"Failed to create sealing key!");
@@ -524,6 +529,7 @@ static void *mag_create_dir_config(apr_pool_t *p, char *dir)
cfg = (struct mag_config *)apr_pcalloc(p, sizeof(struct mag_config));
if (!cfg) return NULL;
+ cfg->pool = p;
return cfg;
}
@@ -556,6 +562,47 @@ static const char *mag_use_sess(cmd_parms *parms, void *mconfig, int on)
return NULL;
}
+static const char *mag_sess_key(cmd_parms *parms, void *mconfig, const char *w)
+{
+ struct mag_config *cfg = (struct mag_config *)mconfig;
+ struct databuf keys;
+ unsigned char *val;
+ apr_status_t rc;
+ const char *k;
+ int l;
+
+ if (strncmp(w, "key:", 4) != 0) {
+ ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, parms->server,
+ "Invalid key format, expected prefix 'key:'");
+ return NULL;
+ }
+ k = w + 4;
+
+ l = apr_base64_decode_len(k);
+ val = apr_palloc(parms->temp_pool, l);
+ if (!val) {
+ ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, parms->server,
+ "Failed to get memory to decode key");
+ return NULL;
+ }
+
+ keys.length = (int)apr_base64_decode_binary(val, k);
+ keys.value = (unsigned char *)val;
+
+ if (keys.length != 32) {
+ ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, parms->server,
+ "Invalid key lenght, expected 32 got %d", keys.length);
+ return NULL;
+ }
+
+ rc = SEAL_KEY_CREATE(cfg->pool, &cfg->mag_skey, &keys);
+ if (rc != OK) {
+ ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, parms->server,
+ "Failed to import sealing key!");
+ }
+ return NULL;
+}
+
static const char *mag_cred_store(cmd_parms *parms, void *mconfig,
const char *w)
{
@@ -611,6 +658,8 @@ static const command_rec mag_commands[] = {
"Authentication is bound to the TCP connection"),
AP_INIT_FLAG("GssapiUseSessions", mag_use_sess, NULL, OR_AUTHCFG,
"Authentication uses mod_sessions to hold status"),
+ AP_INIT_RAW_ARGS("GssapiSessionKey", mag_sess_key, NULL, OR_AUTHCFG,
+ "Key Used to seal session data."),
AP_INIT_ITERATE("GssapiCredStore", mag_cred_store, NULL, OR_AUTHCFG,
"Credential Store"),
{ NULL }