From 6c31661097c7aac2729ed2a5a6e3a8856b5ae15c Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Sat, 5 Apr 2014 15:20:06 -0400 Subject: Add function to verify MICs --- src/ntlm.c | 46 ---------------------------------------------- src/ntlm.h | 20 ++++++++++++++++++++ src/ntlm_common.h | 46 ++++++++++++++++++++++++++++++++++++++++++++++ src/ntlm_crypto.c | 38 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 104 insertions(+), 46 deletions(-) (limited to 'src') diff --git a/src/ntlm.c b/src/ntlm.c index 9cb3814..41b21f6 100644 --- a/src/ntlm.c +++ b/src/ntlm.c @@ -35,25 +35,6 @@ #include "ntlm.h" -#pragma pack(push, 1) -struct wire_msg_hdr { - uint8_t signature[8]; - uint32_t msg_type; -}; -#pragma pack(pop) - -/* A wire string, the offset is relative to the mesage and must fall into the - * payload section. - * max_len should be set equal to len and ignored by servers. - */ -#pragma pack(push, 1) -struct wire_field_hdr { - uint16_t len; - uint16_t max_len; - uint32_t offset; -}; -#pragma pack(pop) - #pragma pack(push, 1) struct wire_neg_msg { struct wire_msg_hdr header; @@ -76,20 +57,6 @@ struct wire_chal_msg { }; #pragma pack(pop) -#pragma pack(push, 1) -struct wire_auth_msg { - struct wire_msg_hdr header; - struct wire_field_hdr lm_chalresp; - struct wire_field_hdr nt_chalresp; - struct wire_field_hdr domain_name; - struct wire_field_hdr user_name; - struct wire_field_hdr workstation; - struct wire_field_hdr enc_sess_key; - uint32_t neg_flags; - uint8_t payload[]; /* variable */ -}; -#pragma pack(pop) - #pragma pack(push, 1) struct wire_av_pair { uint16_t av_id; @@ -142,19 +109,6 @@ struct wire_ntlm_cli_chal { }; #pragma pack(pop) -/* Version information. - * Used only for debugging and usually placed as the head of the payload when - * used */ -#pragma pack(push, 1) -struct wire_version { - uint8_t major; - uint8_t minor; - uint16_t build; - uint8_t reserved[3]; - uint8_t revision; -}; -#pragma pack(pop) - struct ntlm_ctx { iconv_t from_oem; iconv_t to_oem; diff --git a/src/ntlm.h b/src/ntlm.h index 40508e4..72d62c8 100644 --- a/src/ntlm.h +++ b/src/ntlm.h @@ -430,6 +430,26 @@ int ntlm_mic(struct ntlm_key *exported_session_key, struct ntlm_buffer *authenticate_message, struct ntlm_buffer *mic); +/** + * @brief Verifies a MIC + * + * @param key The keys used to generate the original MIC + * @param negotiate_message The NTLM Negotiate Message (or empty) + * @param challenge_message The NTLM Challenge Message + * @param authenticate_message The NTLM Authenticate Message + * @param mic The original MIC + * + * NOTE: This function zeros the area of memory where the MIC is held in the + * Authenticate Message + * + * @return 0 on success, EACCES if the MIC fails to verify, or an error + */ +int ntlm_verify_mic(struct ntlm_key *key, + struct ntlm_buffer *negotiate_message, + struct ntlm_buffer *challenge_message, + struct ntlm_buffer *authenticate_message, + struct ntlm_buffer *mic); + /* ############## ENCODING / DECODING ############## */ /** diff --git a/src/ntlm_common.h b/src/ntlm_common.h index 264afe1..01d6b16 100644 --- a/src/ntlm_common.h +++ b/src/ntlm_common.h @@ -57,4 +57,50 @@ enum ntlm_cipher_mode { NTLM_CIPHER_DECRYPT, }; +#pragma pack(push, 1) +struct wire_msg_hdr { + uint8_t signature[8]; + uint32_t msg_type; +}; +#pragma pack(pop) + +/* A wire string, the offset is relative to the mesage and must fall into the + * payload section. + * max_len should be set equal to len and ignored by servers. + */ +#pragma pack(push, 1) +struct wire_field_hdr { + uint16_t len; + uint16_t max_len; + uint32_t offset; +}; +#pragma pack(pop) + +#pragma pack(push, 1) +struct wire_auth_msg { + struct wire_msg_hdr header; + struct wire_field_hdr lm_chalresp; + struct wire_field_hdr nt_chalresp; + struct wire_field_hdr domain_name; + struct wire_field_hdr user_name; + struct wire_field_hdr workstation; + struct wire_field_hdr enc_sess_key; + uint32_t neg_flags; + uint8_t payload[]; /* variable */ +}; +#pragma pack(pop) + +/* Version information. + * Used only for debugging and usually placed as the head of the payload when + * used */ +#pragma pack(push, 1) +struct wire_version { + uint8_t major; + uint8_t minor; + uint16_t build; + uint8_t reserved[3]; + uint8_t revision; +}; +#pragma pack(pop) + #endif /* _NTLM_COMMON_H_ */ diff --git a/src/ntlm_crypto.c b/src/ntlm_crypto.c index fbfdc41..5bccb39 100644 --- a/src/ntlm_crypto.c +++ b/src/ntlm_crypto.c @@ -830,3 +830,41 @@ int ntlm_mic(struct ntlm_key *exported_session_key, return HMAC_MD5_IOV(&key, &iov, mic); } + +int ntlm_verify_mic(struct ntlm_key *key, + struct ntlm_buffer *negotiate_message, + struct ntlm_buffer *challenge_message, + struct ntlm_buffer *authenticate_message, + struct ntlm_buffer *mic) +{ + uint8_t micbuf[16]; + struct ntlm_buffer check_mic = { micbuf, 16 }; + struct wire_auth_msg *msg; + size_t payload_offs; + uint32_t flags; + int ret; + + msg = (struct wire_auth_msg *)authenticate_message->data; + payload_offs = offsetof(struct wire_auth_msg, payload); + + /* flags must be checked as they may push the payload further down */ + flags = le32toh(msg->neg_flags); + if (flags & NTLMSSP_NEGOTIATE_VERSION) { + /* skip version for now */ + payload_offs += sizeof(struct wire_version); + } + + if (payload_offs + 16 > authenticate_message->length) return EINVAL; + + /* payload_offs now points at the MIC buffer, clear it off in order + * to be able to calculate the original chcksum */ + memset(&authenticate_message->data[payload_offs], 0, 16); + + ret = ntlm_mic(key, negotiate_message, challenge_message, + authenticate_message, &check_mic); + if (ret) return ret; + + if (memcmp(mic->data, check_mic.data, 16) != 0) return EACCES; + + return 0; +} -- cgit