summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimo Sorce <simo@redhat.com>2014-08-06 21:40:32 -0400
committerSimo Sorce <simo@redhat.com>2014-08-06 23:59:38 -0400
commit9183a98c62ca9669937b6e4c61ed58c81b4eead6 (patch)
treed77f82ed93e588bfd2f2414c98bf1e8d09fd8f06
parenta3e554fbf28fbf0c67d4511dec809069feed6d3b (diff)
downloadgss-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
-rw-r--r--src/gss_serialize.c6
-rw-r--r--src/gss_signseal.c54
-rw-r--r--src/ntlm.h35
-rw-r--r--src/ntlm_crypto.c195
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;
}
diff --git a/src/ntlm.h b/src/ntlm.h
index 5e90e14..29f6221 100644
--- a/src/ntlm.h
+++ b/src/ntlm.h
@@ -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,