This patch adds NTLM and NTLMv2 hash and response calculation code.
src/lib-ntlm/ntlm-encrypt.c | 123 ++++++++++++++++++++++++++++++++++++++++++++
src/lib-ntlm/ntlm-encrypt.h | 17 ++++++
2 files changed, 140 insertions(+)
diff -urpNX /usr/share/dontdiff dovecot-1.0-test30.vanilla/src/lib-ntlm/ntlm-encrypt.c dovecot-1.0-test30/src/lib-ntlm/ntlm-encrypt.c
--- dovecot-1.0-test30.vanilla/src/lib-ntlm/ntlm-encrypt.c 1970-01-01 03:00:00.000000000 +0300
+++ dovecot-1.0-test30/src/lib-ntlm/ntlm-encrypt.c 2004-07-27 14:02:37.000000000 +0400
@@ -0,0 +1,123 @@
+/*
+ * NTLM and NTLMv2 hash generation.
+ *
+ * Copyright (c) 2004 Andrey Panin
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include
+
+#include "lib.h"
+#include "compat.h"
+#include "safe-memset.h"
+#include "md4.h"
+#include "hmac-md5.h"
+#include "ntlm.h"
+#include "ntlm-des.h"
+
+
+static int unicode(ucs2le_t *dst, const char *src, int len, int ucase)
+{
+ int i;
+ char *p = (char *) dst;
+
+ memset(dst, 0, len * sizeof(*dst));
+
+ for (i = 0; (i < len - 1) && *src; i++) {
+ *p++ = ucase ? i_toupper(*src) : *src;
+ *p++ = 0;
+ src++;
+ }
+
+ *p++ = 0;
+ *p++ = 0;
+
+ return i;
+}
+
+static void
+ntlmssp_des_encrypt_triad(const unsigned char *hash,
+ const unsigned char *challenge,
+ unsigned char *response)
+{
+ deshash(response, challenge, hash);
+ deshash(response + 8, challenge, hash + 7);
+ deshash(response + 16, challenge, hash + 14);
+}
+
+const unsigned char *
+ntlm_v1_hash(const char *passwd, unsigned char hash[NTLMSSP_HASH_SIZE])
+{
+ int len = strlen(passwd);
+ ucs2le_t wpwd[len + 1];
+
+ unicode(wpwd, passwd, len + 1, 0);
+
+ len *= sizeof(ucs2le_t);
+
+ md4_get_digest(wpwd, len, hash);
+
+ safe_memset(wpwd, 0, len);
+
+ return hash;
+}
+
+static void
+hmac_md5_ucs2le_string_ucase(struct hmac_md5_context *ctx, const char *str)
+{
+ int len = strlen(str);
+ ucs2le_t ustr[len + 1];
+
+ unicode(ustr, str, len + 1, 1);
+
+ hmac_md5_update(ctx, ustr, len * sizeof(ucs2le_t));
+}
+
+static void
+ntlm_v2_hash(const char *user, const char *target,
+ const unsigned char *hash_v1,
+ unsigned char hash[NTLMSSP_V2_HASH_SIZE])
+{
+ struct hmac_md5_context ctx;
+
+ hmac_md5_init(&ctx, hash_v1, NTLMSSP_HASH_SIZE);
+ hmac_md5_ucs2le_string_ucase(&ctx, user);
+ if (target)
+ hmac_md5_ucs2le_string_ucase(&ctx, target);
+ hmac_md5_final(&ctx, hash);
+}
+
+void
+ntlmssp_v1_response(const unsigned char *hash,
+ const unsigned char *challenge,
+ unsigned char response[NTLMSSP_RESPONSE_SIZE])
+{
+ unsigned char des_hash[NTLMSSP_DES_KEY_LENGTH * 3];
+
+ memcpy(des_hash, hash, NTLMSSP_HASH_SIZE);
+ memset(des_hash + NTLMSSP_HASH_SIZE, 0, sizeof(hash) - NTLMSSP_HASH_SIZE);
+
+ ntlmssp_des_encrypt_triad(des_hash, challenge, response);
+}
+
+void
+ntlmssp_v2_response(const char *user, const char *target,
+ const unsigned char *hash_v1,
+ const unsigned char *challenge,
+ const unsigned char *blob, size_t blob_size,
+ unsigned char response[NTLMSSP_V2_RESPONSE_SIZE])
+{
+ struct hmac_md5_context ctx;
+ unsigned char hash[NTLMSSP_V2_HASH_SIZE];
+
+ ntlm_v2_hash(user, target, hash_v1, hash);
+
+ hmac_md5_init(&ctx, hash, NTLMSSP_V2_HASH_SIZE);
+ hmac_md5_update(&ctx, challenge, NTLMSSP_CHALLENGE_SIZE);
+ hmac_md5_update(&ctx, blob, blob_size);
+ hmac_md5_final(&ctx, response);
+}
diff -urpNX /usr/share/dontdiff dovecot-1.0-test30.vanilla/src/lib-ntlm/ntlm-encrypt.h dovecot-1.0-test30/src/lib-ntlm/ntlm-encrypt.h
--- dovecot-1.0-test30.vanilla/src/lib-ntlm/ntlm-encrypt.h 1970-01-01 03:00:00.000000000 +0300
+++ dovecot-1.0-test30/src/lib-ntlm/ntlm-encrypt.h 2004-07-27 10:28:05.000000000 +0400
@@ -0,0 +1,17 @@
+#ifndef __NTLM_ENCRYPT__
+#define __NTLM_ENCRYPT__
+
+const unsigned char *
+ntlm_v1_hash(const char *passwd, unsigned char hash[NTLMSSP_HASH_SIZE]);
+
+void ntlmssp_v1_response(const unsigned char *hash,
+ const unsigned char *challenge,
+ unsigned char response[NTLMSSP_RESPONSE_SIZE]);
+
+void ntlmssp_v2_response(const char *user, const char *target,
+ const unsigned char *hash_v1,
+ const unsigned char *challenge,
+ const unsigned char *blob, size_t blob_size,
+ unsigned char response[NTLMSSP_V2_RESPONSE_SIZE]);
+
+#endif /* __NTLM_ENCRYPT__ */