diff options
author | Simo Sorce <simo@redhat.com> | 2013-10-17 00:57:55 -0400 |
---|---|---|
committer | Simo Sorce <simo@redhat.com> | 2013-10-18 16:29:51 -0400 |
commit | e3e42a950ada355a41f7dfa1fd4609ef4c102500 (patch) | |
tree | c0ae7b3df012bb01fc8a3f9a6a4e55c82b1cc911 | |
parent | fd8d8833e2f3496893c970550eecc6449b59b9d5 (diff) | |
download | gss-ntlmssp-e3e42a950ada355a41f7dfa1fd4609ef4c102500.tar.gz gss-ntlmssp-e3e42a950ada355a41f7dfa1fd4609ef4c102500.tar.xz gss-ntlmssp-e3e42a950ada355a41f7dfa1fd4609ef4c102500.zip |
Support connectionless signing and sealing.
In connectionless mode (GSS_C_DATAGRAM_FLAG on) sealing keys
ust be rotated for each message.
-rw-r--r-- | src/gss_signseal.c | 72 | ||||
-rw-r--r-- | src/ntlm.h | 14 | ||||
-rw-r--r-- | src/ntlm_crypto.c | 29 |
3 files changed, 104 insertions, 11 deletions
diff --git a/src/gss_signseal.c b/src/gss_signseal.c index 5828c2a..e8ec43a 100644 --- a/src/gss_signseal.c +++ b/src/gss_signseal.c @@ -20,9 +20,7 @@ #include <string.h> #include <time.h> -#include <gssapi/gssapi.h> -#include <gssapi/gssapi_ext.h> - +#include "gssapi_ntlmssp.h" #include "gss_ntlmssp.h" uint32_t gssntlm_get_mic(uint32_t *minor_status, @@ -50,6 +48,17 @@ 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->send.seal_key, + &ctx->send.seal_handle, + ctx->send.seq_num); + if (retmin) { + *minor_status = retmin; + return GSS_S_FAILURE; + } + } + message_token->value = malloc(16); if (!message_token->value) { *minor_status = ENOMEM; @@ -70,8 +79,10 @@ uint32_t gssntlm_get_mic(uint32_t *minor_status, return GSS_S_FAILURE; } - /* increment seq_num upon succesful signature */ - ctx->send.seq_num++; + if (!(ctx->gss_flags & GSS_C_DATAGRAM_FLAG)) { + /* increment seq_num upon succesful signature */ + ctx->send.seq_num++; + } return GSS_S_COMPLETE; } @@ -102,6 +113,17 @@ 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->recv.seal_key, + &ctx->recv.seal_handle, + ctx->send.seq_num); + if (retmin) { + *minor_status = retmin; + return GSS_S_FAILURE; + } + } + message.data = message_buffer->value; message.length = message_buffer->length; retmin = ntlm_sign(&ctx->recv.sign_key, ctx->recv.seq_num, @@ -116,8 +138,10 @@ uint32_t gssntlm_verify_mic(uint32_t *minor_status, return GSS_S_BAD_SIG; } - /* increment seq_num upon succesful signature */ - ctx->recv.seq_num++; + if (!(ctx->gss_flags & GSS_C_DATAGRAM_FLAG)) { + /* increment seq_num upon succesful signature */ + ctx->recv.seq_num++; + } return GSS_S_COMPLETE; } @@ -157,6 +181,17 @@ 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->send.seal_key, + &ctx->send.seal_handle, + ctx->send.seq_num); + if (retmin) { + *minor_status = retmin; + return GSS_S_FAILURE; + } + } + output_message_buffer->value = malloc(input_message_buffer->length + 16); if (!output_message_buffer->value) { *minor_status = ENOMEM; @@ -179,8 +214,10 @@ uint32_t gssntlm_wrap(uint32_t *minor_status, return GSS_S_FAILURE; } - /* increment seq_num upon succesful signature */ - ctx->send.seq_num++; + if (!(ctx->gss_flags & GSS_C_DATAGRAM_FLAG)) { + /* increment seq_num upon succesful encryption */ + ctx->send.seq_num++; + } return GSS_S_COMPLETE; } @@ -215,6 +252,17 @@ 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->recv.seal_key, + &ctx->recv.seal_handle, + ctx->send.seq_num); + if (retmin) { + *minor_status = retmin; + return GSS_S_FAILURE; + } + } + output_message_buffer->value = malloc(input_message_buffer->length - 16); if (!output_message_buffer->value) { *minor_status = ENOMEM; @@ -240,7 +288,9 @@ uint32_t gssntlm_unwrap(uint32_t *minor_status, return GSS_S_BAD_SIG; } - /* increment seq_num upon succesful signature */ - ctx->send.seq_num++; + if (!(ctx->gss_flags & GSS_C_DATAGRAM_FLAG)) { + /* increment seq_num upon succesful encryption */ + ctx->recv.seq_num++; + } return GSS_S_COMPLETE; } @@ -306,6 +306,20 @@ int ntlm_signseal_keys(uint32_t flags, bool client, struct ntlm_rc4_handle **seal_recv_handle); /** + * @brief Regens the NTLM Seal key. + * Used only in connectionless mode. See MS-NLMP 3.4 + * + * @param seal_key The current sealing key + * @param seal_handle The current sealing handle + * @param seq_num The current (application provided) sequence number + * + * @return 0 on success or error. + */ +int ntlm_seal_regen(struct ntlm_key *seal_key, + struct ntlm_rc4_handle **seal_handle, + uint32_t seq_num); + +/** * @brief Verifies a 16 bit NT Response * * @param nt_response The NT Response buffer including client challenge diff --git a/src/ntlm_crypto.c b/src/ntlm_crypto.c index e305e03..a51b03e 100644 --- a/src/ntlm_crypto.c +++ b/src/ntlm_crypto.c @@ -549,6 +549,35 @@ int ntlm_signseal_keys(uint32_t flags, bool client, return 0; } +int ntlm_seal_regen(struct ntlm_key *seal_key, + struct ntlm_rc4_handle **seal_handle, + uint32_t seq_num) +{ + struct ntlm_buffer payload; + struct ntlm_buffer result; + uint8_t inbuf[20]; + uint8_t outbuf[16]; + uint32_t le; + int ret; + + RC4_FREE(seal_handle); + + memcpy(inbuf, seal_key->data, seal_key->length); + le = htole32(seq_num); + memcpy(&inbuf[16], &le, 4); + + payload.data = inbuf; + payload.length = 20; + result.data = outbuf; + result.length = 16; + + ret = MD5_HASH(&payload, &result); + if (ret) return ret; + + ret = RC4_INIT(&result, NTLM_CIPHER_ENCRYPT, seal_handle); + return ret; +} + int ntlmv2_verify_nt_response(struct ntlm_buffer *nt_response, struct ntlm_key *ntlmv2_key, uint8_t server_chal[8]) |