#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;
};
#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;
};
#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;
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 ############## */
/**
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_ */
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;
+}