summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimo Sorce <simo@redhat.com>2016-12-16 09:43:25 -0500
committerSimo Sorce <simo@redhat.com>2017-01-03 11:42:52 -0500
commite2a50ad80f55bf2a933ef177914caa5c7ac6f4a9 (patch)
tree849be9f97ca026229f38ee68e8bc0dd1d0658d3d
parent0d6a1a390a578ab8be5bc0d6225e3e0b07dc7eba (diff)
downloadmod_auth_gssapi-e2a50ad80f55bf2a933ef177914caa5c7ac6f4a9.tar.gz
mod_auth_gssapi-e2a50ad80f55bf2a933ef177914caa5c7ac6f4a9.tar.xz
mod_auth_gssapi-e2a50ad80f55bf2a933ef177914caa5c7ac6f4a9.zip
Add option to store the session encryption key.
With the new 'file:' sytnax a session key can be automatically generated the first time mod_auth_gssapi runs and stored on the filesystem. Signed-off-by: Simo Sorce <simo@redhat.com> Reviewed-by: Robbie Harwood <rharwood@redhat.com> Closes #117
-rw-r--r--README15
-rw-r--r--src/mod_auth_gssapi.c99
-rw-r--r--tests/httpd.conf1
3 files changed, 99 insertions, 16 deletions
diff --git a/README b/README
index e06f2f0..68e2bb4 100644
--- a/README
+++ b/README
@@ -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
diff --git a/src/mod_auth_gssapi.c b/src/mod_auth_gssapi.c
index 8a9ca7f..9f311c5 100644
--- a/src/mod_auth_gssapi.c
+++ b/src/mod_auth_gssapi.c
@@ -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,
diff --git a/tests/httpd.conf b/tests/httpd.conf
index 134a84a..66054c1 100644
--- a/tests/httpd.conf
+++ b/tests/httpd.conf
@@ -137,6 +137,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