From: Simo Sorce Date: Mon, 7 Jul 2014 15:42:57 +0000 (-0400) Subject: Add permanent session keys support X-Git-Tag: v1.0.0~2 X-Git-Url: http://www.project-moonshot.org/gitweb/?p=mod_auth_gssapi.git;a=commitdiff_plain;h=6e86569afd4812f5674810ab66ee67fd5251d538 Add permanent session keys support 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: --- 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 7e8df96..ec78e82 100644 --- a/src/mod_auth_gssapi.c +++ b/src/mod_auth_gssapi.c @@ -346,6 +346,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) { @@ -401,6 +442,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 } diff --git a/src/sessions.c b/src/sessions.c index 766ca66..1086505 100644 --- a/src/sessions.c +++ b/src/sessions.c @@ -147,7 +147,7 @@ void mag_attempt_session(request_rec *req, if (!cfg->mag_skey) { ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, req, "Session key not available, generating new one."); - rc = SEAL_KEY_CREATE(&cfg->mag_skey); + 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!");