aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGreg Hudson <ghudson@mit.edu>2010-09-26 23:35:05 +0000
committerGreg Hudson <ghudson@mit.edu>2010-09-26 23:35:05 +0000
commitf78b7496a91e172bb1b8ebddd6cf83cee42ab5c7 (patch)
tree9cffc8f3c2cbbe4f824093e257ea7125d9879711
parent4006c3d647a0a0f1eccb5baeb530c96bfbbbf7a5 (diff)
downloadkrb5-f78b7496a91e172bb1b8ebddd6cf83cee42ab5c7.zip
krb5-f78b7496a91e172bb1b8ebddd6cf83cee42ab5c7.tar.gz
krb5-f78b7496a91e172bb1b8ebddd6cf83cee42ab5c7.tar.bz2
When using stream ciphers with NSS, use a loopback pointer instead of
a bogus length to detect copying, and remember the pid to detect use across fork. git-svn-id: svn://anonsvn.mit.edu/krb5/branches/nss@24355 dc483132-0cff-0310-8789-dd5450dbe970
-rw-r--r--src/lib/crypto/nss/enc_provider/enc_gen.c52
1 files changed, 37 insertions, 15 deletions
diff --git a/src/lib/crypto/nss/enc_provider/enc_gen.c b/src/lib/crypto/nss/enc_provider/enc_gen.c
index d2fbfb5..c3ea152 100644
--- a/src/lib/crypto/nss/enc_provider/enc_gen.c
+++ b/src/lib/crypto/nss/enc_provider/enc_gen.c
@@ -53,6 +53,12 @@ static NSSInitContext *k5_nss_ctx = NULL;
static pid_t k5_nss_pid = 0;
static k5_mutex_t k5_nss_lock = K5_MUTEX_PARTIAL_INITIALIZER;
+struct stream_state {
+ struct stream_state *loopback; /* To detect copying */
+ pid_t pid; /* To detect use across fork */
+ PK11Context *ctx;
+};
+
krb5_error_code
k5_nss_map_error(int nss_error)
{
@@ -265,16 +271,27 @@ done:
krb5_error_code
k5_nss_stream_init_state(krb5_data *new_state)
{
- new_state->data = NULL;
- new_state->length = 0;
+ struct stream_state *sstate;
+
+ /* Create a state structure with an uninitialized context. */
+ sstate = calloc(1, sizeof(*sstate));
+ if (sstate == NULL)
+ return ENOMEM;
+ sstate->loopback = NULL;
+ new_state->data = (char *) sstate;
+ new_state->length = sizeof(*sstate);
return 0;
}
krb5_error_code
k5_nss_stream_free_state(krb5_data *state)
{
- if (state->length == (unsigned)-1 && state->data)
- PK11_Finalize((PK11Context *)state->data);
+ struct stream_state *sstate = (struct stream_state *) state->data;
+
+ /* Clean up the OpenSSL context if it was initialized. */
+ if (sstate && sstate->loopback == sstate)
+ PK11_Finalize(sstate->ctx);
+ free(sstate);
return 0;
}
@@ -288,24 +305,29 @@ k5_nss_gen_stream_iov(krb5_key krb_key, krb5_data *state,
SECStatus rv;
SECItem param;
krb5_crypto_iov *iov;
+ struct stream_state *sstate = NULL;
int i;
param.data = NULL;
param.len = 0;
- if (state && state->data) {
- ctx = (PK11Context *)state->data;
- } else {
+ sstate = (state == NULL) ? NULL : (struct stream_state *) state->data;
+ if (sstate == NULL || sstate->loopback == NULL) {
ctx = k5_nss_create_context(krb_key, mech, operation, &param);
- if (state && ctx) {
- state->data = (char *)ctx;
- state->length = -1; /* you don't get to copy this, */
- /* blow up if you try */
+ if (ctx == NULL) {
+ ret = k5_nss_map_last_error();
+ goto done;
}
- }
- if (ctx == NULL) {
- ret = k5_nss_map_last_error();
- goto done;
+ if (sstate) {
+ sstate->loopback = sstate;
+ sstate->pid = getpid();
+ sstate->ctx = ctx;
+ }
+ } else {
+ /* Cipher state can't be copied or used across a fork. */
+ if (sstate->loopback != sstate || sstate->pid != getpid())
+ return EINVAL;
+ ctx = sstate->ctx;
}
for (i=0; i < (int)num_data; i++) {