Skip to content

Commit 6e86569

Browse files
committed
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:<base64 blob>
1 parent 63dbb99 commit 6e86569

File tree

4 files changed

+87
-26
lines changed

4 files changed

+87
-26
lines changed

src/crypto.c

Lines changed: 41 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -13,56 +13,73 @@ struct seal_key {
1313
unsigned char *hkey;
1414
};
1515

16-
apr_status_t SEAL_KEY_CREATE(struct seal_key **skey)
16+
apr_status_t SEAL_KEY_CREATE(apr_pool_t *p, struct seal_key **skey,
17+
struct databuf *keys)
1718
{
1819
struct seal_key *n;
20+
int keylen;
1921
int ret;
2022

21-
n = calloc(1, sizeof(*n));
23+
n = apr_pcalloc(p, sizeof(*n));
2224
if (!n) return ENOMEM;
2325

2426
n->cipher = EVP_aes_128_cbc();
2527
if (!n->cipher) {
26-
free(n);
27-
return EFAULT;
28+
ret = EFAULT;
29+
goto done;
2830
}
2931

32+
keylen = n->cipher->key_len;
33+
3034
n->md = EVP_sha256();
3135
if (!n->md) {
32-
free(n);
33-
return EFAULT;
36+
ret = EFAULT;
37+
goto done;
3438
}
3539

36-
n->ekey = malloc(n->cipher->key_len);
40+
n->ekey = apr_palloc(p, keylen);
3741
if (!n->ekey) {
38-
free(n);
39-
return ENOMEM;
42+
ret = ENOMEM;
43+
goto done;
4044
}
4145

42-
n->hkey = malloc(n->cipher->key_len);
46+
n->hkey = apr_palloc(p, keylen);
4347
if (!n->hkey) {
44-
free(n);
45-
return ENOMEM;
48+
ret = ENOMEM;
49+
goto done;
4650
}
4751

48-
ret = RAND_bytes(n->ekey, n->cipher->key_len);
49-
if (ret == 0) {
50-
free(n->ekey);
51-
free(n->hkey);
52-
free(n);
53-
return EFAULT;
52+
if (keys) {
53+
if (keys->length != (keylen * 2)) {
54+
ret = EINVAL;
55+
goto done;
56+
}
57+
memcpy(n->ekey, keys->value, keylen);
58+
memcpy(n->hkey, keys->value + keylen, keylen);
59+
} else {
60+
ret = RAND_bytes(n->ekey, keylen);
61+
if (ret == 0) {
62+
ret = EFAULT;
63+
goto done;
64+
}
65+
66+
ret = RAND_bytes(n->hkey, keylen);
67+
if (ret == 0) {
68+
ret = EFAULT;
69+
goto done;
70+
}
5471
}
5572

56-
ret = RAND_bytes(n->hkey, n->cipher->key_len);
57-
if (ret == 0) {
73+
ret = 0;
74+
done:
75+
if (ret) {
5876
free(n->ekey);
5977
free(n->hkey);
6078
free(n);
61-
return EFAULT;
79+
} else {
80+
*skey = n;
6281
}
63-
64-
*skey = n;
65-
return 0;
82+
return ret;
6683
}
6784

6885
apr_status_t SEAL_BUFFER(apr_pool_t *p, struct seal_key *skey,

src/crypto.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ struct databuf {
1010
int length;
1111
};
1212

13-
apr_status_t SEAL_KEY_CREATE(struct seal_key **skey);
13+
apr_status_t SEAL_KEY_CREATE(apr_pool_t *p, struct seal_key **skey,
14+
struct databuf *keys);
1415
apr_status_t SEAL_BUFFER(apr_pool_t *p, struct seal_key *skey,
1516
struct databuf *plain, struct databuf *cipher);
1617
apr_status_t UNSEAL_BUFFER(apr_pool_t *p, struct seal_key *skey,

src/mod_auth_gssapi.c

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,47 @@ static const char *mag_use_sess(cmd_parms *parms, void *mconfig, int on)
346346
return NULL;
347347
}
348348

349+
static const char *mag_sess_key(cmd_parms *parms, void *mconfig, const char *w)
350+
{
351+
struct mag_config *cfg = (struct mag_config *)mconfig;
352+
struct databuf keys;
353+
unsigned char *val;
354+
apr_status_t rc;
355+
const char *k;
356+
int l;
357+
358+
if (strncmp(w, "key:", 4) != 0) {
359+
ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, parms->server,
360+
"Invalid key format, expected prefix 'key:'");
361+
return NULL;
362+
}
363+
k = w + 4;
364+
365+
l = apr_base64_decode_len(k);
366+
val = apr_palloc(parms->temp_pool, l);
367+
if (!val) {
368+
ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, parms->server,
369+
"Failed to get memory to decode key");
370+
return NULL;
371+
}
372+
373+
keys.length = (int)apr_base64_decode_binary(val, k);
374+
keys.value = (unsigned char *)val;
375+
376+
if (keys.length != 32) {
377+
ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, parms->server,
378+
"Invalid key lenght, expected 32 got %d", keys.length);
379+
return NULL;
380+
}
381+
382+
rc = SEAL_KEY_CREATE(cfg->pool, &cfg->mag_skey, &keys);
383+
if (rc != OK) {
384+
ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, parms->server,
385+
"Failed to import sealing key!");
386+
}
387+
return NULL;
388+
}
389+
349390
static const char *mag_cred_store(cmd_parms *parms, void *mconfig,
350391
const char *w)
351392
{
@@ -401,6 +442,8 @@ static const command_rec mag_commands[] = {
401442
"Authentication is bound to the TCP connection"),
402443
AP_INIT_FLAG("GssapiUseSessions", mag_use_sess, NULL, OR_AUTHCFG,
403444
"Authentication uses mod_sessions to hold status"),
445+
AP_INIT_RAW_ARGS("GssapiSessionKey", mag_sess_key, NULL, OR_AUTHCFG,
446+
"Key Used to seal session data."),
404447
AP_INIT_ITERATE("GssapiCredStore", mag_cred_store, NULL, OR_AUTHCFG,
405448
"Credential Store"),
406449
{ NULL }

src/sessions.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ void mag_attempt_session(request_rec *req,
147147
if (!cfg->mag_skey) {
148148
ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, req,
149149
"Session key not available, generating new one.");
150-
rc = SEAL_KEY_CREATE(&cfg->mag_skey);
150+
rc = SEAL_KEY_CREATE(cfg->pool, &cfg->mag_skey, NULL);
151151
if (rc != OK) {
152152
ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, req,
153153
"Failed to create sealing key!");

0 commit comments

Comments
 (0)