Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 13 additions & 2 deletions README
Original file line number Diff line number Diff line change
Expand Up @@ -144,10 +144,21 @@ admin can choose to install a permanent key in the configuration so that
session data remain accessible after a restart or by multiple servers
sharing the same key.

The key must be a base64 encoded raw key of 32 bytes of length.
Two schemes to read persistent keys are provided, 'key' and 'file'.

#### Example
- 'key'
A key is read from the configuration directive.
The key must be a base64 encoded raw key of 32 bytes of length.

- 'file'
A file on the file system is used to store the key. If the file does not
exists one is created with a randomly generated key during the first
execution.


#### Examples
GssapiSessionKey key:VGhpcyBpcyBhIDMyIGJ5dGUgbG9uZyBzZWNyZXQhISE=
GssapiSessionKey file:/var/lib/httpd/secrets/session.key


### GssapiCredStore
Expand Down
99 changes: 85 additions & 14 deletions src/mod_auth_gssapi.c
Original file line number Diff line number Diff line change
Expand Up @@ -1238,34 +1238,105 @@ static const char *mag_deleg_ccache_unique(cmd_parms *parms, void *mconfig,

#endif

#define SESS_KEYS_TOT_LEN 32

static void create_sess_key_file(cmd_parms *parms, const char *name)
{
apr_status_t ret;
apr_file_t *fd = NULL;
unsigned char keys[SESS_KEYS_TOT_LEN];
apr_size_t bw;

ret = apr_file_open(&fd, name,
APR_FOPEN_CREATE | APR_FOPEN_WRITE | APR_FOPEN_EXCL,
APR_FPROT_UREAD | APR_FPROT_UWRITE, parms->temp_pool);
if (ret != APR_SUCCESS) {
char err[256];
apr_strerror(ret, err, sizeof(err));
ap_log_error(APLOG_MARK, APLOG_ERR, 0, parms->server,
"Failed to create key file %s: %s", name, err);
return;
}
ret = apr_generate_random_bytes(keys, SESS_KEYS_TOT_LEN);
if (ret != OK) {
ap_log_error(APLOG_MARK, APLOG_ERR, 0, parms->server,
"Failed to generate random sealing key!");
ret = APR_INCOMPLETE;
goto done;
}
ret = apr_file_write_full(fd, keys, SESS_KEYS_TOT_LEN, &bw);
if ((ret != APR_SUCCESS) || (bw != SESS_KEYS_TOT_LEN)) {
char err[256];
apr_strerror(ret, err, sizeof(err));
ap_log_error(APLOG_MARK, APLOG_ERR, 0, parms->server,
"Failed to store key in %s: %s", name, err);
ret = APR_INCOMPLETE;
goto done;
}
done:
apr_file_close(fd);
if (ret != APR_SUCCESS) apr_file_remove(name, parms->temp_pool);
}

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, 0, parms->server,
"Invalid key format, expected prefix 'key:'");
return NULL;
}
k = w + 4;
if (strncmp(w, "key:", 4) == 0) {
const char *k = w + 4;

l = apr_base64_decode_len(k);
val = apr_palloc(parms->temp_pool, l);

keys.length = (int)apr_base64_decode_binary(val, k);
keys.value = (unsigned char *)val;

if (keys.length != SESS_KEYS_TOT_LEN) {
ap_log_error(APLOG_MARK, APLOG_ERR, 0, parms->server,
"Invalid key length, expected 32 got %d",
keys.length);
return NULL;
}
} else if (strncmp(w, "file:", 5) == 0) {
apr_status_t ret;
apr_file_t *fd = NULL;
apr_int32_t ronly = APR_FOPEN_READ;
const char *fname;

l = apr_base64_decode_len(k);
val = apr_palloc(parms->temp_pool, l);
keys.length = SESS_KEYS_TOT_LEN;
keys.value = apr_palloc(parms->temp_pool, keys.length);

keys.length = (int)apr_base64_decode_binary(val, k);
keys.value = (unsigned char *)val;
fname = w + 5;

if (keys.length != 32) {
ret = apr_file_open(&fd, fname, ronly, 0, parms->temp_pool);
if (APR_STATUS_IS_ENOENT(ret)) {
create_sess_key_file(parms, fname);

ret = apr_file_open(&fd, fname, ronly, 0, parms->temp_pool);
}
if (ret == APR_SUCCESS) {
apr_size_t br;
ret = apr_file_read_full(fd, keys.value, keys.length, &br);
apr_file_close(fd);
if ((ret != APR_SUCCESS) || (br != keys.length)) {
ap_log_error(APLOG_MARK, APLOG_ERR, 0, parms->server,
"Failed to read sealing key from %s!", fname);
return NULL;
}
} else {
ap_log_error(APLOG_MARK, APLOG_ERR, 0, parms->server,
"Failed to open key file %s", fname);
return NULL;
}
} else {
ap_log_error(APLOG_MARK, APLOG_ERR, 0, parms->server,
"Invalid key length, expected 32 got %d", keys.length);
"Invalid key format, unexpected prefix in %s'", w);
return NULL;
}

rc = SEAL_KEY_CREATE(cfg->pool, &cfg->mag_skey, &keys);
if (rc != OK) {
ap_log_error(APLOG_MARK, APLOG_ERR, 0, parms->server,
Expand Down
1 change: 1 addition & 0 deletions tests/httpd.conf
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ CoreDumpDirectory /tmp
GssapiUseSessions On
Session On
SessionCookieName gssapi_session path=/spnego;httponly
GssapiSessionKey file:${HTTPROOT}/session.key
GssapiCredStore ccache:${HTTPROOT}/tmp/httpd_krb5_ccache
GssapiCredStore client_keytab:${HTTPROOT}/http.keytab
GssapiCredStore keytab:${HTTPROOT}/http.keytab
Expand Down