diff options
author | Simo Sorce <simo@redhat.com> | 2014-08-06 21:40:32 -0400 |
---|---|---|
committer | Simo Sorce <simo@redhat.com> | 2014-08-06 23:59:38 -0400 |
commit | 9183a98c62ca9669937b6e4c61ed58c81b4eead6 (patch) | |
tree | d77f82ed93e588bfd2f2414c98bf1e8d09fd8f06 /src | |
parent | a3e554fbf28fbf0c67d4511dec809069feed6d3b (diff) | |
download | gss-ntlmssp-9183a98c62ca9669937b6e4c61ed58c81b4eead6.tar.gz gss-ntlmssp-9183a98c62ca9669937b6e4c61ed58c81b4eead6.tar.xz gss-ntlmssp-9183a98c62ca9669937b6e4c61ed58c81b4eead6.zip |
Internalize extended security and datagram status
Move handling of datagram status with ntlm_crypto routines, this
way ntlm_seal_regen becomes an internal detail.
Also better separate exended security and legacy sign/seal crypto
state generation and general handling in sign/seal functions
Diffstat (limited to 'src')
-rw-r--r-- | src/gss_serialize.c | 6 | ||||
-rw-r--r-- | src/gss_signseal.c | 54 | ||||
-rw-r--r-- | src/ntlm.h | 35 | ||||
-rw-r--r-- | src/ntlm_crypto.c | 195 |
4 files changed, 164 insertions, 126 deletions
diff --git a/src/gss_serialize.c b/src/gss_serialize.c index 611d8be..4d54ff5 100644 --- a/src/gss_serialize.c +++ b/src/gss_serialize.c @@ -709,6 +709,12 @@ uint32_t gssntlm_import_sec_context(uint32_t *minor_status, &ectx->recv, &ctx->crypto_state.recv); if (maj != GSS_S_COMPLETE) goto done; + /* We need to restoer also the general crypto status flags */ + ctx->crypto_state.ext_sec = + (ctx->neg_flags & NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY); + ctx->crypto_state.datagram = + (ctx->neg_flags & NTLMSSP_NEGOTIATE_DATAGRAM); + ctx->int_flags = ectx->int_flags; time = le64toh(ectx->expration_time); diff --git a/src/gss_signseal.c b/src/gss_signseal.c index 7513c74..7a7a673 100644 --- a/src/gss_signseal.c +++ b/src/gss_signseal.c @@ -48,15 +48,6 @@ uint32_t gssntlm_get_mic(uint32_t *minor_status, return GSS_S_CALL_INACCESSIBLE_READ; } - if (ctx->gss_flags & GSS_C_DATAGRAM_FLAG) { - /* must regenerate seal key */ - retmin = ntlm_seal_regen(&ctx->crypto_state, NTLM_SEND); - if (retmin) { - *minor_status = retmin; - return GSS_S_FAILURE; - } - } - message_token->value = malloc(NTLM_SIGNATURE_SIZE); if (!message_token->value) { *minor_status = ENOMEM; @@ -77,11 +68,6 @@ uint32_t gssntlm_get_mic(uint32_t *minor_status, return GSS_S_FAILURE; } - if (!(ctx->gss_flags & GSS_C_DATAGRAM_FLAG)) { - /* increment seq_num upon succesful signature */ - ctx->crypto_state.send.seq_num++; - } - return GSS_S_COMPLETE; } @@ -111,15 +97,6 @@ uint32_t gssntlm_verify_mic(uint32_t *minor_status, *qop_state = GSS_C_QOP_DEFAULT; } - if (ctx->gss_flags & GSS_C_DATAGRAM_FLAG) { - /* must regenerate seal key */ - retmin = ntlm_seal_regen(&ctx->crypto_state, NTLM_RECV); - if (retmin) { - *minor_status = retmin; - return GSS_S_FAILURE; - } - } - message.data = message_buffer->value; message.length = message_buffer->length; retmin = ntlm_sign(ctx->neg_flags, NTLM_RECV, @@ -135,11 +112,6 @@ uint32_t gssntlm_verify_mic(uint32_t *minor_status, return GSS_S_BAD_SIG; } - if (!(ctx->gss_flags & GSS_C_DATAGRAM_FLAG)) { - /* increment seq_num upon succesful signature */ - ctx->crypto_state.recv.seq_num++; - } - return GSS_S_COMPLETE; } @@ -178,15 +150,6 @@ uint32_t gssntlm_wrap(uint32_t *minor_status, /* ignore, always seal */ } - if (ctx->gss_flags & GSS_C_DATAGRAM_FLAG) { - /* must regenerate seal key */ - retmin = ntlm_seal_regen(&ctx->crypto_state, NTLM_SEND); - if (retmin) { - *minor_status = retmin; - return GSS_S_FAILURE; - } - } - output_message_buffer->length = input_message_buffer->length + NTLM_SIGNATURE_SIZE; output_message_buffer->value = malloc(output_message_buffer->length); @@ -209,10 +172,6 @@ uint32_t gssntlm_wrap(uint32_t *minor_status, return GSS_S_FAILURE; } - if (!(ctx->gss_flags & GSS_C_DATAGRAM_FLAG)) { - /* increment seq_num upon succesful encryption */ - ctx->crypto_state.send.seq_num++; - } return GSS_S_COMPLETE; } @@ -247,15 +206,6 @@ uint32_t gssntlm_unwrap(uint32_t *minor_status, *qop_state = GSS_C_QOP_DEFAULT; } - if (ctx->gss_flags & GSS_C_DATAGRAM_FLAG) { - /* must regenerate seal key */ - retmin = ntlm_seal_regen(&ctx->crypto_state, NTLM_RECV); - if (retmin) { - *minor_status = retmin; - return GSS_S_FAILURE; - } - } - output_message_buffer->length = input_message_buffer->length - NTLM_SIGNATURE_SIZE; output_message_buffer->value = malloc(output_message_buffer->length); @@ -282,10 +232,6 @@ uint32_t gssntlm_unwrap(uint32_t *minor_status, return GSS_S_BAD_SIG; } - if (!(ctx->gss_flags & GSS_C_DATAGRAM_FLAG)) { - /* increment seq_num upon succesful encryption */ - ctx->crypto_state.recv.seq_num++; - } return GSS_S_COMPLETE; } @@ -137,6 +137,8 @@ struct ntlm_signseal_handle { struct ntlm_signseal_state { struct ntlm_signseal_handle send; struct ntlm_signseal_handle recv; + bool datagram; + bool ext_sec; }; #define NTLM_SEND 1 @@ -314,7 +316,7 @@ int ntlm_encrypted_session_key(struct ntlm_key *key, struct ntlm_key *in, struct ntlm_key *out); /** - * @brief Computes all the sign and seal keys from the session key + * @brief Computes the extended security keys from the session key * * @param flags Incoming challenge/authenticate flags * @param client Wheter this ia a client or a server @@ -328,15 +330,34 @@ int ntlm_signseal_keys(uint32_t flags, bool client, struct ntlm_signseal_state *signseal_state); /** - * @brief Regens the NTLM Seal key. - * Used only in connectionless mode. See MS-NLMP 3.4 + * @brief Verifies a NTLM v1 NT Response * - * @param state Sign and seal keys and state - * @param direction Direction (NTLM_SEND or NTLM_RECV) + * @param nt_response The NT Response buffer + * @param nt_key The NTLMv1 NT Key + * @param ext_sec Whether Extended Security was negotiated + * @param server_chal[8] The Server Challenge + * @param client_chal[8] The Client Challenge * - * @return 0 on success or error. + * @return 0 on success, or an error + */ +int ntlm_verify_nt_response(struct ntlm_buffer *nt_response, + struct ntlm_key *nt_key, bool ext_sec, + uint8_t server_chal[8], uint8_t client_chal[8]); + +/** + * @brief Verifies a NTLM v1 LM Response + * + * @param lm_response The LM Response buffer + * @param lm_key The NTLMv1 LM Key + * @param ext_sec Whether Extended Security was negotiated + * @param server_chal[8] The Server Challenge + * @param client_chal[8] The Client Challenge + * + * @return 0 on success, or an error */ -int ntlm_seal_regen(struct ntlm_signseal_state *state, int direction); +int ntlm_verify_lm_response(struct ntlm_buffer *lm_response, + struct ntlm_key *lm_key, bool ext_sec, + uint8_t server_chal[8], uint8_t client_chal[8]); /** * @brief Verifies a 16 bit NT Response diff --git a/src/ntlm_crypto.c b/src/ntlm_crypto.c index 33f5b65..00ae561 100644 --- a/src/ntlm_crypto.c +++ b/src/ntlm_crypto.c @@ -418,83 +418,100 @@ static int ntlm_key_derivation_function(struct ntlm_key *key, #define NTLM_MODE_CLIENT true #define NTLM_MODE_SERVER false -static int ntlm_signkey(uint32_t flags, bool mode, - struct ntlm_key *random_session_key, +static int ntlm_signkey(bool mode, + struct ntlm_key *session_key, struct ntlm_key *signing_key) { const char *mc; - if (flags & NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY) { - if (mode == NTLM_MODE_CLIENT) { - mc = "session key to client-to-server signing key magic constant"; - } else { - mc = "session key to server-to-client signing key magic constant"; - } - return ntlm_key_derivation_function(random_session_key, - mc, signing_key); + if (mode == NTLM_MODE_CLIENT) { + mc = "session key to client-to-server signing key magic constant"; } else { - signing_key->length = 0; + mc = "session key to server-to-client signing key magic constant"; } - return 0; + return ntlm_key_derivation_function(session_key, + mc, signing_key); } static int ntlm_sealkey(uint32_t flags, bool mode, - struct ntlm_key *random_session_key, + struct ntlm_key *session_key, struct ntlm_key *sealing_key) { struct ntlm_key key; const char *mc; - if (flags & NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY) { - if (flags & NTLMSSP_NEGOTIATE_128) { - key.length = 16; - } else if (flags & NTLMSSP_NEGOTIATE_56) { - key.length = 7; - } else { - key.length = 5; - } - memcpy(key.data, random_session_key->data, key.length); + if (flags & NTLMSSP_NEGOTIATE_128) { + key.length = 16; + } else if (flags & NTLMSSP_NEGOTIATE_56) { + key.length = 7; + } else { + key.length = 5; + } + memcpy(key.data, session_key->data, key.length); - if (mode == NTLM_MODE_CLIENT) { - mc = "session key to client-to-server sealing key magic constant"; - } else { - mc = "session key to server-to-client sealing key magic constant"; - } + if (mode == NTLM_MODE_CLIENT) { + mc = "session key to client-to-server sealing key magic constant"; + } else { + mc = "session key to server-to-client sealing key magic constant"; + } - return ntlm_key_derivation_function(&key, mc, sealing_key); + return ntlm_key_derivation_function(&key, mc, sealing_key); +} - } else if (flags & NTLMSSP_NEGOTIATE_LM_KEY) { +static void no_ext_sec_sealkey(uint32_t flags, + struct ntlm_key *session_key, + struct ntlm_buffer *sealing_key) +{ + if (flags & NTLMSSP_NEGOTIATE_LM_KEY) { if (flags & NTLMSSP_NEGOTIATE_56) { - memcpy(sealing_key->data, random_session_key->data, 7); + memcpy(sealing_key->data, session_key->data, 7); sealing_key->data[7] = 0xA0; } else { - memcpy(sealing_key->data, random_session_key->data, 5); + memcpy(sealing_key->data, session_key->data, 5); sealing_key->data[5] = 0xE5; sealing_key->data[6] = 0x38; sealing_key->data[7] = 0xB0; } sealing_key->length = 8; } else { - *sealing_key = *random_session_key; + memcpy(sealing_key->data, session_key->data, 16); + sealing_key->length = session_key->length; } - return 0; } -int ntlm_signseal_keys(uint32_t flags, bool client, - struct ntlm_key *session_key, - struct ntlm_signseal_state *state) +static int no_ext_sec_handle(uint32_t flags, + struct ntlm_key *session_key, + struct ntlm_rc4_handle **seal_handle) +{ + uint8_t skbuf[16]; + struct ntlm_buffer sealing_key = { skbuf, 16 }; + + no_ext_sec_sealkey(flags, session_key, &sealing_key); + + return RC4_INIT(&sealing_key, NTLM_CIPHER_ENCRYPT, seal_handle); +} + + +static int ext_sec_keys(uint32_t flags, bool client, + struct ntlm_key *session_key, + struct ntlm_signseal_state *state) { struct ntlm_buffer rc4_key; bool mode; int ret; + state->ext_sec = true; + if (flags & NTLMSSP_NEGOTIATE_DATAGRAM) { + state->datagram = true; + } + /* send key */ mode = client ? NTLM_MODE_CLIENT : NTLM_MODE_SERVER; - ret = ntlm_signkey(flags, mode, session_key, &state->send.sign_key); + ret = ntlm_signkey(mode, session_key, &state->send.sign_key); if (ret) return ret; /* recv key */ mode = client ? NTLM_MODE_SERVER : NTLM_MODE_CLIENT; - ret = ntlm_signkey(flags, mode, session_key, &state->recv.sign_key); + ret = ntlm_signkey(mode, session_key, &state->recv.sign_key); if (ret) return ret; /* send key */ @@ -519,9 +536,24 @@ int ntlm_signseal_keys(uint32_t flags, bool client, return 0; } -int ntlm_seal_regen(struct ntlm_signseal_state *state, int direction) +int ntlm_signseal_keys(uint32_t flags, bool client, + struct ntlm_key *session_key, + struct ntlm_signseal_state *state) +{ + + memset(state, 0, sizeof(struct ntlm_signseal_state)); + + if (flags & NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY) { + state->datagram = (flags & NTLMSSP_NEGOTIATE_DATAGRAM); + return ext_sec_keys(flags, client, session_key, state); + } else { + return no_ext_sec_handle(flags, session_key, + &state->send.seal_handle); + } +} + +static int ntlm_seal_regen(struct ntlm_signseal_handle *h) { - struct ntlm_signseal_handle *h; struct ntlm_buffer payload; struct ntlm_buffer result; uint8_t inbuf[20]; @@ -529,12 +561,6 @@ int ntlm_seal_regen(struct ntlm_signseal_state *state, int direction) uint32_t le; int ret; - if (direction == NTLM_SEND) { - h = &state->send; - } else { - h = &state->recv; - } - RC4_FREE(&h->seal_handle); memcpy(inbuf, h->seal_key.data, h->seal_key.length); @@ -713,20 +739,35 @@ int ntlm_sign(uint32_t flags, int direction, struct ntlm_buffer *signature) { struct ntlm_signseal_handle *h; + int ret; - if (direction == NTLM_SEND) { + if (direction == NTLM_SEND || !state->ext_sec) { h = &state->send; } else { h = &state->recv; } - if ((flags & NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY) - && (flags & NTLMSSP_NEGOTIATE_SIGN)) { - return ntlmv2_sign(&h->sign_key, h->seq_num, h->seal_handle, - (flags & NTLMSSP_NEGOTIATE_KEY_EXCH), - message, signature); - } else if (flags & NTLMSSP_NEGOTIATE_SIGN) { - return ntlmv1_sign(h->seal_handle, 0, h->seq_num, message, signature); + if (flags & NTLMSSP_NEGOTIATE_SIGN) { + if (state->ext_sec) { + if (state->datagram) { + ret = ntlm_seal_regen(h); + if (ret) return ret; + } + + ret = ntlmv2_sign(&h->sign_key, h->seq_num, h->seal_handle, + (flags & NTLMSSP_NEGOTIATE_KEY_EXCH), + message, signature); + } else { + ret = ntlmv1_sign(h->seal_handle, 0, h->seq_num, + message, signature); + } + if (ret) return ret; + + if (!state->datagram) { + h->seq_num++; + } + return 0; + } else if (flags & NTLMSSP_NEGOTIATE_ALWAYS_SIGN) { uint32_t le_seq = htole32(h->seq_num); memcpy(signature->data, &le_seq, 4); @@ -755,13 +796,23 @@ int ntlm_seal(uint32_t flags, ret = RC4_UPDATE(h->seal_handle, message, output); if (ret) return ret; - if (flags & NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY) { - return ntlmv2_sign(&h->sign_key, h->seq_num, h->seal_handle, - (flags & NTLMSSP_NEGOTIATE_KEY_EXCH), - message, signature); + if (state->ext_sec) { + if (state->datagram) { + ret = ntlm_seal_regen(h); + if (ret) return ret; + } + ret = ntlmv2_sign(&h->sign_key, h->seq_num, h->seal_handle, + (flags & NTLMSSP_NEGOTIATE_KEY_EXCH), + message, signature); } else { - return ntlmv1_sign(h->seal_handle, 0, h->seq_num, message, signature); + ret = ntlmv1_sign(h->seal_handle, 0, h->seq_num, message, signature); } + if (ret) return ret; + + if (!state->datagram) { + h->seq_num++; + } + return 0; } int ntlm_unseal(uint32_t flags, @@ -778,7 +829,11 @@ int ntlm_unseal(uint32_t flags, return ENOTSUP; } - h = &state->recv; + if (!state->ext_sec) { + h = &state->send; + } else { + h = &state->recv; + } msg_buffer = *message; msg_buffer.length -= NTLM_SIGNATURE_SIZE; @@ -786,13 +841,23 @@ int ntlm_unseal(uint32_t flags, ret = RC4_UPDATE(h->seal_handle, &msg_buffer, output); if (ret) return ret; - if (flags & NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY) { - return ntlmv2_sign(&h->sign_key, h->seq_num, h->seal_handle, - (flags & NTLMSSP_NEGOTIATE_KEY_EXCH), - output, signature); + if (state->ext_sec) { + if (state->datagram) { + ret = ntlm_seal_regen(h); + if (ret) return ret; + } + ret = ntlmv2_sign(&h->sign_key, h->seq_num, h->seal_handle, + (flags & NTLMSSP_NEGOTIATE_KEY_EXCH), + output, signature); } else { - return ntlmv1_sign(h->seal_handle, 0, h->seq_num, output, signature); + ret = ntlmv1_sign(h->seal_handle, 0, h->seq_num, output, signature); } + if (ret) return ret; + + if (!state->datagram) { + h->seq_num++; + } + return 0; } int ntlm_mic(struct ntlm_key *exported_session_key, |