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 <pazke@donpac.ru> + * + * 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 <ctype.h> + +#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__ */