summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimo Sorce <simo@redhat.com>2013-10-17 00:57:55 -0400
committerSimo Sorce <simo@redhat.com>2013-10-18 16:29:51 -0400
commite3e42a950ada355a41f7dfa1fd4609ef4c102500 (patch)
treec0ae7b3df012bb01fc8a3f9a6a4e55c82b1cc911
parentfd8d8833e2f3496893c970550eecc6449b59b9d5 (diff)
downloadgss-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.c72
-rw-r--r--src/ntlm.h14
-rw-r--r--src/ntlm_crypto.c29
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;
}
diff --git a/src/ntlm.h b/src/ntlm.h
index bfbfb47..2d6e2e4 100644
--- a/src/ntlm.h
+++ b/src/ntlm.h
@@ -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])