[Dovecot] [PATCH 0/10] NTLM patchset submission
Andrey Panin
pazke at donpac.ru
Wed Jul 28 16:15:27 EEST 2004
On 210, 07 28, 2004 at 12:36:30AM +0300, Timo Sirainen wrote:
> On 27.7.2004, at 16:18, Andrey Panin wrote:
>
> >It contains common code in src/lib-ntlm directory, Samba compatible
> >NTLM password scheme and authentication mechanism itself.
>
> So now Dovecot has md4, md5, sha1 and des code. Maybe there should be a
> lib-crypto or something similiar for those.. Or anyway md4 and des
> would be better in lib/ than lib-ntlm/.
md4 and hmac-md5 can be moved to lib/ easily. I'm not sure about usefulness
of ntlm-des.c outside of NTLM authentication code.
> >Please take a look.
>
> HMAC-MD5 code looks quite similiar to
> src/auth/password-scheme-cram-md5.c. Could they be merged somehow?
I'll take a look at them later today.
> You use "char var[0]" in end of some structures. I've tried to avoid
> them so far everywhere since C89 doesn't support it. But I guess it's
> common enough feature that it could be allowed the way C99 supports it,
> var[].
We can safely remove this fields, now they serve to illustrate NTLM
message structure only.
> + int len = strlen(passwd);
> + ucs2le_t wpwd[len + 1];
>
> Another C99ism.. Are there enough C99 compilers that it'd be good idea
> to require it? gcc of course works, but how about others?
Reworked using buffer API.
> +ntlmssp_v1_response(const unsigned char *hash,
> ..
> + memset(des_hash + NTLMSSP_HASH_SIZE, 0, sizeof(hash) -
> NTLMSSP_HASH_SIZE);
>
> sizeof(des_hash)
Fixed.
> +#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
>
> offsetof() is ansi-c and defined in stddef.h
Removed.
> +const char * __ntlmssp_t_str(void *message, struct ntlmssp_buffer
> *buffer)
> ..
> + str_append_c(str, '\0');
> +
> + return str_c(str);
>
> str_c() nul-terminates the returned string so str_append_c() isn't
> needed there.
Fixed.
> +static int ntlmssp_check_buffer(struct ntlmssp_buffer *buffer, size_t
> data_size, const char **error)
> +{
> + uint32_t offset = read_le32(&buffer->offset);
> +
> + if (offset <= data_size) {
> + *error = "buffer offset out of bounds";
> + return 0;
> + }
>
> offset >= data_size I'd think?
Fixed.
Updated patches attached.
--
Andrey Panin | Linux and UNIX system administrator
pazke at donpac.ru | PGP key: wwwkeys.pgp.net
-------------- next part --------------
diff -urpNX /usr/share/dontdiff dovecot-1.0-test30.vanilla/src/lib-ntlm/ntlm-types.h dovecot-1.0-test30/src/lib-ntlm/ntlm-types.h
--- dovecot-1.0-test30.vanilla/src/lib-ntlm/ntlm-types.h 1970-01-01 03:00:00.000000000 +0300
+++ dovecot-1.0-test30/src/lib-ntlm/ntlm-types.h 2004-07-28 17:04:41.000000000 +0400
@@ -0,0 +1,130 @@
+/*
+ * NTLM data structures.
+ *
+ * Copyright (c) 2004 Andrey Panin <pazke at 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.
+ */
+
+#ifndef __NTLM_TYPES_H__
+#define __NTLM_TYPES_H__
+
+#define NTLMSSP_MAGIC 0x005053534d4c544eULL
+
+#define NTLMSSP_MSG_TYPE1 1
+#define NTLMSSP_MSG_TYPE2 2
+#define NTLMSSP_MSG_TYPE3 3
+
+#define NTLMSSP_DES_KEY_LENGTH 7
+
+#define NTLMSSP_CHALLENGE_SIZE 8
+
+#define NTLMSSP_HASH_SIZE 16
+#define NTLMSSP_RESPONSE_SIZE 24
+
+#define NTLMSSP_V2_HASH_SIZE 16
+#define NTLMSSP_V2_RESPONSE_SIZE 16
+
+
+typedef uint16_t ucs2le_t;
+
+struct ntlmssp_buffer {
+ uint16_t length; /* length of the buffer */
+ uint16_t space; /* space allocated space for buffer */
+ uint32_t offset; /* data offset from the start of the message */
+};
+
+typedef struct ntlmssp_buffer ntlmssp_buffer_t;
+
+
+/*
+ *
+ */
+struct ntlmssp_message {
+ uint64_t magic; /* NTLMSSP\0 */
+ uint32_t type; /* Should be 1 */
+};
+
+/*
+ * Type 1 message, client sends it to start NTLM authentication sequence.
+ */
+struct ntlmssp_request {
+ uint64_t magic; /* NTLMSSP\0 */
+ uint32_t type; /* Should be 1 */
+ uint32_t flags; /* Flags */
+ ntlmssp_buffer_t domain; /* Domain name (optional) */
+ ntlmssp_buffer_t workstation; /* Workstation name (optional) */
+ /* Start of the data block */
+};
+
+/*
+ * The Type 2 message is sent by the server to the client in response to
+ * the client's Type 1 message. It serves to complete the negotiation of
+ * options with the client, and also provides a challenge to the client.
+ */
+struct ntlmssp_challenge {
+ uint64_t magic; /* NTLMSSP\0 */
+ uint32_t type; /* Should be 2 */
+ ntlmssp_buffer_t target_name; /* Name of authentication target */
+ uint32_t flags; /* Flags */
+ uint8_t challenge[NTLMSSP_CHALLENGE_SIZE]; /* Server challenge */
+ uint32_t context[2]; /* Local authentication context handle */
+ ntlmssp_buffer_t target_info; /* Target information block (for NTLMv2) */
+ /* Start of the data block */
+};
+
+/*
+ * The Type 3 message is the final step in authentication. This message
+ * contains the client's responses to the Type 2 challenge, which demonstrate
+ * that the client has knowledge of the account password without sending the
+ * password directly. The Type 3 message also indicates the domain and username
+ * of the authenticating account, as well as the client workstation name.
+ */
+struct ntlmssp_response {
+ uint64_t magic; /* NTLMSSP\0 */
+ uint32_t type; /* Should be 3 */
+ ntlmssp_buffer_t lm_response; /* LM/LMv2 recponse */
+ ntlmssp_buffer_t ntlm_response; /* NTLM/NTLMv2 recponse */
+ ntlmssp_buffer_t domain; /* Domain name */
+ ntlmssp_buffer_t user; /* User name */
+ ntlmssp_buffer_t workstation; /* Workstation name */
+ ntlmssp_buffer_t session_key; /* Session key (optional */
+ uint32_t flags; /* Flags (optional) */
+ /* Start of the data block */
+};
+
+/*
+ * NTLMv2 Target Information Block item.
+ */
+struct ntlmssp_v2_target_info {
+ uint16_t type; /* Data type (see below) */
+ uint16_t length; /* Length of content field */
+ /* Content (always in ucs2-le) */
+};
+
+/*
+ * NTLMv2 Target Information Block item data type.
+ */
+enum {
+ NTPLMSSP_V2_TARGET_END = 0, /* End of list */
+ NTPLMSSP_V2_TARGET_SERVER, /* NetBIOS server name */
+ NTPLMSSP_V2_TARGET_DOMAIN, /* NT Domain NetBIOS name */
+ NTPLMSSP_V2_TARGET_FQDN, /* Fully qualified host name */
+ NTPLMSSP_V2_TARGET_DNS, /* DNS domain name */
+};
+
+/*
+ * NTLMv2 Authentication data blob.
+ */
+struct ntlmssp_v2_blob {
+ uint32_t magic; /* Should be 0x01010000 */
+ uint32_t reserved; /* Always 0 */
+ uint64_t timestamp; /* Timestamp */
+ uint32_t unknown; /* Unknown something */
+ /* Target Information Block */
+};
+
+#endif /* __NTLM_TYPES_H__ */
diff -urpNX /usr/share/dontdiff dovecot-1.0-test30.vanilla/src/lib-ntlm/ntlm-flags.h dovecot-1.0-test30/src/lib-ntlm/ntlm-flags.h
--- dovecot-1.0-test30.vanilla/src/lib-ntlm/ntlm-flags.h 1970-01-01 03:00:00.000000000 +0300
+++ dovecot-1.0-test30/src/lib-ntlm/ntlm-flags.h 2004-07-27 15:48:44.000000000 +0400
@@ -0,0 +1,139 @@
+/*
+ * NTLM message flags.
+ *
+ * Copyright (c) 2004 Andrey Panin <pazke at 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.1 of the License, or (at your option) any later version.
+ */
+
+#ifndef __NTLM_FLAGS_H__
+#define __NTLM_FLAGS_H__
+
+/*
+ * Indicates that Unicode strings are supported for use in security
+ * buffer data.
+ */
+#define NTLMSSP_NEGOTIATE_UNICODE 0x00000001
+
+/*
+ * Indicates that OEM strings are supported for use in security buffer data.
+ */
+#define NTLMSSP_NEGOTIATE_OEM 0x00000002
+
+/*
+ * Requests that the server's authentication realm be included in the
+ * Type 2 message.
+ */
+#define NTLMSSP_REQUEST_TARGET 0x00000004
+
+/*
+ * Specifies that authenticated communication between the client and server
+ * should carry a digital signature (message integrity).
+ */
+#define NTLMSSP_NEGOTIATE_SIGN 0x00000010
+
+/*
+ * Specifies that authenticated communication between the client and server
+ * should be encrypted (message confidentiality).
+ */
+#define NTLMSSP_NEGOTIATE_SEAL 0x00000020
+
+/*
+ * Indicates that datagram authentication is being used.
+ */
+#define NTLMSSP_NEGOTIATE_DATAGRAM 0x00000040
+
+/*
+ * Indicates that the LAN Manager session key should be
+ * used for signing and sealing authenticated communications.
+ */
+#define NTLMSSP_NEGOTIATE_LM_KEY 0x00000080
+
+/*
+ * Indicates that NTLM authentication is being used.
+ */
+#define NTLMSSP_NEGOTIATE_NTLM 0x00000200
+
+/*
+ * Sent by the client in the Type 1 message to indicate that the name of the
+ * domain in which the client workstation has membership is included in the
+ * message. This is used by the server to determine whether the client is
+ * eligible for local authentication.
+ */
+#define NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED 0x00001000
+
+/*
+ * Sent by the client in the Type 1 message to indicate that the client
+ * workstation's name is included in the message. This is used by the server
+ * to determine whether the client is eligible for local authentication.
+ */
+#define NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED 0x00002000
+
+/*
+ * Sent by the server to indicate that the server and client are on the same
+ * machine. Implies that the client may use the established local credentials
+ * for authentication instead of calculating a response to the challenge.
+ */
+#define NTLMSSP_NEGOTIATE_LOCAL_CALL 0x00004000
+
+/*
+ * Indicates that authenticated communication between the client and server
+ * should be signed with a "dummy" signature.
+ */
+#define NTLMSSP_NEGOTIATE_ALWAYS_SIGN 0x00008000
+
+/*
+ * Sent by the server in the Type 2 message to indicate that the target
+ * authentication realm is a domain.
+ */
+#define NTLMSSP_TARGET_TYPE_DOMAIN 0x00010000
+
+/*
+ * Sent by the server in the Type 2 message to indicate that the target
+ * authentication realm is a server.
+ */
+#define NTLMSSP_TARGET_TYPE_SERVER 0x00020000
+
+/*
+ * Sent by the server in the Type 2 message to indicate that the target
+ * authentication realm is a share. Presumably, this is for share-level
+ * authentication. Usage is unclear.
+ */
+#define NTLMSSP_TARGET_TYPE_SHARE 0x00040000
+
+/*
+ * Indicates that the NTLM2 signing and sealing scheme should be used for
+ * protecting authenticated communications. Note that this refers to a
+ * particular session security scheme, and is not related to the use of
+ * NTLMv2 authentication.
+ */
+#define NTLMSSP_NEGOTIATE_NTLM2 0x00080000
+
+/*
+ * Sent by the server in the Type 2 message to indicate that it is including
+ * a Target Information block in the message. The Target Information block
+ * is used in the calculation of the NTLMv2 response.
+ */
+#define NTLMSSP_NEGOTIATE_TARGET_INFO 0x00800000
+
+/*
+ * Indicates that 128-bit encryption is supported.
+ */
+#define NTLMSSP_NEGOTIATE_128 0x20000000
+
+/*
+ * Indicates that the client will provide an encrypted master session key in the
+ * "Session Key" field of the Type 3 message. This is used in signing and sealing,
+ * and is RC4-encrypted using the previous session key as the encryption key.
+ */
+#define NTLMSSP_NEGOTIATE_KEY_EXCHANGE 0x40000000
+
+/*
+ * Indicates that 56-bit encryption is supported.
+ */
+#define NTLMSSP_NEGOTIATE_56 0x80000000
+
+#endif /* __NTLM_FLAGS_H__ */
diff -urpNX /usr/share/dontdiff dovecot-1.0-test30.vanilla/src/lib-ntlm/ntlm-byteorder.h dovecot-1.0-test30/src/lib-ntlm/ntlm-byteorder.h
--- dovecot-1.0-test30.vanilla/src/lib-ntlm/ntlm-byteorder.h 1970-01-01 03:00:00.000000000 +0300
+++ dovecot-1.0-test30/src/lib-ntlm/ntlm-byteorder.h 2004-07-27 14:01:57.000000000 +0400
@@ -0,0 +1,111 @@
+/*
+ * Little-endian data access functions.
+ *
+ * Copyright (c) 2004 Andrey Panin <pazke at 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.
+ */
+
+#ifndef __NTLM_BYTEORDER_H__
+#define __NTLM_BYTEORDER_H__
+
+#if defined(__i386__) || defined(__vax__)
+
+static inline uint16_t read_le16(const void *addr)
+{
+ return *((uint16_t *) addr);
+}
+
+static inline uint32_t read_le32(const void *addr)
+{
+ return *((uint32_t *) addr);
+}
+
+static inline uint64_t read_le64(const void *addr)
+{
+ return *((uint64_t *) addr);
+}
+
+static inline void write_le16(void *addr, const uint16_t value)
+{
+ *((uint16_t *) addr) = value;
+}
+
+static inline void write_le32(void *addr, const uint32_t value)
+{
+ *((uint32_t *) addr) = value;
+}
+
+static inline void write_le64(void *addr, const uint64_t value)
+{
+ *((uint64_t *) addr) = value;
+}
+
+#else
+
+/*
+ * Dumb and slow, but byteorder and alignment independent code.
+ */
+
+#define readb(addr, pos, type) ((type)(*(((uint8_t *) (addr)) + (pos))))
+
+static inline uint16_t read_le16(const void *addr)
+{
+ return readb(addr, 0, uint16_t) | (readb(addr, 1, uint16_t) << 8);
+}
+
+static inline uint32_t read_le32(const void *addr)
+{
+ return readb(addr, 0, uint32_t) |
+ (readb(addr, 1, uint32_t) << 8) |
+ (readb(addr, 2, uint32_t) << 16) |
+ (readb(addr, 3, uint32_t) << 24);
+}
+
+static inline uint64_t read_le64(const void *addr)
+{
+ return readb(addr, 0, uint64_t) |
+ (readb(addr, 1, uint64_t) << 8) |
+ (readb(addr, 2, uint64_t) << 16) |
+ (readb(addr, 3, uint64_t) << 24) |
+ (readb(addr, 4, uint64_t) << 32) |
+ (readb(addr, 5, uint64_t) << 40) |
+ (readb(addr, 6, uint64_t) << 48) |
+ (readb(addr, 7, uint64_t) << 56);
+}
+
+#define writeb(addr, pos, value) \
+ *(((uint8_t *)(addr)) + (pos)) = (uint8_t) (value)
+
+static inline void write_le16(void *addr, const uint16_t value)
+{
+ writeb(addr, 0, value & 0xff);
+ writeb(addr, 1, (value >> 8) & 0xff);
+}
+
+static inline void write_le32(void *addr, const uint32_t value)
+{
+ writeb(addr, 0, value & 0xff);
+ writeb(addr, 1, (value >> 8) & 0xff);
+ writeb(addr, 2, (value >> 16) & 0xff);
+ writeb(addr, 3, (value >> 24) & 0xff);
+}
+
+static inline void write_le64(void *addr, const uint64_t value)
+{
+ writeb(addr, 0, value & 0xff);
+ writeb(addr, 1, (value >> 8) & 0xff);
+ writeb(addr, 2, (value >> 16) & 0xff);
+ writeb(addr, 3, (value >> 24) & 0xff);
+ writeb(addr, 4, (value >> 32) & 0xff);
+ writeb(addr, 5, (value >> 40) & 0xff);
+ writeb(addr, 6, (value >> 48) & 0xff);
+ writeb(addr, 7, (value >> 56) & 0xff);
+}
+
+#endif
+
+#endif /* __NTLM_BYTEORDER_H__ */
diff -urpNX /usr/share/dontdiff dovecot-1.0-test30.vanilla/src/lib-ntlm/ntlm.h dovecot-1.0-test30/src/lib-ntlm/ntlm.h
--- dovecot-1.0-test30.vanilla/src/lib-ntlm/ntlm.h 1970-01-01 03:00:00.000000000 +0300
+++ dovecot-1.0-test30/src/lib-ntlm/ntlm.h 2004-07-27 11:36:05.000000000 +0400
@@ -0,0 +1,34 @@
+#ifndef __NTLM_H__
+#define __NTLM_H__
+
+#include <stdint.h>
+#include <stddef.h>
+
+#include "ntlm-types.h"
+#include "ntlm-flags.h"
+#include "ntlm-byteorder.h"
+#include "ntlm-encrypt.h"
+#include "ntlm-message.h"
+
+#define ntlmssp_buffer_data(message, buffer) \
+ __ntlmssp_buffer_data((message), &message->buffer)
+
+static inline const void * __ntlmssp_buffer_data(void * message, struct ntlmssp_buffer *buffer)
+{
+ return ((char *) message) + read_le32(&buffer->offset);
+}
+
+#define ntlmssp_buffer_length(message, buffer) \
+ __ntlmssp_buffer_length(&message->buffer)
+
+static inline unsigned int __ntlmssp_buffer_length(struct ntlmssp_buffer *buffer)
+{
+ return read_le16(&buffer->length);
+}
+
+#define ntlmssp_t_str(message, buffer) \
+ __ntlmssp_t_str((message), &message->buffer)
+
+const char * __ntlmssp_t_str(void *message, struct ntlmssp_buffer *buffer);
+
+#endif
-------------- next part --------------
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-28 16:56:01.000000000 +0400
@@ -0,0 +1,112 @@
+/*
+ * NTLM and NTLMv2 hash generation.
+ *
+ * Copyright (c) 2004 Andrey Panin <pazke at 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 "buffer.h"
+#include "compat.h"
+#include "safe-memset.h"
+#include "md4.h"
+#include "hmac-md5.h"
+#include "ntlm.h"
+#include "ntlm-des.h"
+
+static unsigned char *
+t_unicode_str(const char *src, int ucase, size_t *size)
+{
+ buffer_t *wstr = buffer_create_dynamic(unsafe_data_stack_pool, 32, 4096);
+
+ for ( ; *src; src++) {
+ buffer_append_c(wstr, ucase ? i_toupper(*src) : *src);
+ buffer_append_c(wstr, '\0');
+ }
+
+ *size = buffer_get_used_size(wstr);
+ return buffer_free_without_data(wstr);
+}
+
+static void
+ntlmssp_des_encrypt_triad(const unsigned char *hash,
+ const unsigned char *challenge,
+ unsigned char *response)
+{
+ deshash(response, hash, challenge);
+ deshash(response + 8, hash + 7, challenge);
+ deshash(response + 16, hash + 14, challenge);
+}
+
+const unsigned char *
+ntlm_v1_hash(const char *passwd, unsigned char hash[NTLMSSP_HASH_SIZE])
+{
+ size_t len;
+ void *wpwd = t_unicode_str(passwd, 0, &len);
+
+ 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)
+{
+ size_t len;
+ unsigned char *wstr = t_unicode_str(str, 1, &len);
+
+ hmac_md5_update(ctx, wstr, len);
+}
+
+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(des_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__ */
-------------- next part --------------
diff -urpNX /usr/share/dontdiff dovecot-1.0-test30.vanilla/src/lib-ntlm/ntlm-message.c dovecot-1.0-test30/src/lib-ntlm/ntlm-message.c
--- dovecot-1.0-test30.vanilla/src/lib-ntlm/ntlm-message.c 1970-01-01 03:00:00.000000000 +0300
+++ dovecot-1.0-test30/src/lib-ntlm/ntlm-message.c 2004-07-28 14:39:57.000000000 +0400
@@ -0,0 +1,229 @@
+/*
+ * NTLM message handling.
+ *
+ * Copyright (c) 2004 Andrey Panin <pazke at 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 <stdarg.h>
+#include <ctype.h>
+
+#include "lib.h"
+#include "str.h"
+#include "buffer.h"
+#include "hostpid.h"
+#include "randgen.h"
+
+#include "ntlm.h"
+#include "ntlm-message.h"
+
+const char * __ntlmssp_t_str(void *message, struct ntlmssp_buffer *buffer)
+{
+ int len = read_le16(&buffer->length) / sizeof(ucs2le_t);
+ string_t *str = t_str_new(len / 2);
+ char *p = ((char *) message) + read_le32(&buffer->offset);
+
+ while (len--) {
+ str_append_c(str, *p & 0x7f);
+ p += sizeof(ucs2le_t);
+ }
+
+ return str_c(str);
+}
+
+static unsigned int append_string(buffer_t *buf, const char *str, int ucase)
+{
+ unsigned int length = 0;
+
+ for ( ; *str; str++) {
+ buffer_append_c(buf, ucase ? toupper(*str) : *str);
+ buffer_append_c(buf, 0);
+ length += sizeof(ucs2le_t);
+ }
+
+ return length;
+}
+
+static void ntlmssp_append_string(buffer_t *buf, size_t buffer_offset, const char *str)
+{
+ struct ntlmssp_buffer buffer;
+ unsigned int length;
+
+ write_le32(&buffer.offset, buffer_get_used_size(buf));
+
+ length = append_string(buf, str, 0);
+
+ write_le16(&buffer.length, length);
+ write_le16(&buffer.space, length);
+ buffer_write(buf, buffer_offset, &buffer, sizeof(buffer));
+}
+
+static void ntlmssp_append_target_info(buffer_t *buf, size_t buffer_offset, ...)
+{
+ struct ntlmssp_v2_target_info info;
+ struct ntlmssp_buffer buffer;
+ va_list args;
+ unsigned int length, total_length = 0;
+ int type;
+
+ write_le32(&buffer.offset, buffer_get_used_size(buf));
+
+ va_start(args, buffer_offset);
+
+ do {
+ type = va_arg(args, int);
+ const char *data;
+
+ memset(&info, 0, sizeof(info));
+ write_le16(&info.type, type);
+
+ switch (type) {
+ case NTPLMSSP_V2_TARGET_END:
+ buffer_append(buf, &info, sizeof(info));
+ length = sizeof(info);
+ break;
+ case NTPLMSSP_V2_TARGET_SERVER:
+ case NTPLMSSP_V2_TARGET_DOMAIN:
+ case NTPLMSSP_V2_TARGET_FQDN:
+ case NTPLMSSP_V2_TARGET_DNS:
+ data = va_arg(args, char *);
+ write_le16(&info.length, strlen(data) * sizeof(ucs2le_t));
+ buffer_append(buf, &info, sizeof(info));
+ length = append_string(buf, data, 0);
+ break;
+ default:
+ i_panic("Invalid NTLM target info block type %u", type);
+ }
+
+ total_length += length;
+
+ } while (type != NTPLMSSP_V2_TARGET_END);
+
+ va_end(args);
+
+ write_le16(&buffer.length, total_length);
+ write_le16(&buffer.space, total_length);
+ buffer_write(buf, buffer_offset, &buffer, sizeof(buffer));
+}
+
+static inline uint32_t ntlmssp_flags(uint32_t client_flags)
+{
+ uint32_t flags = NTLMSSP_NEGOTIATE_UNICODE |
+ NTLMSSP_NEGOTIATE_NTLM |
+ NTLMSSP_NEGOTIATE_TARGET_INFO;
+
+ if (client_flags & NTLMSSP_REQUEST_TARGET)
+ flags |= NTLMSSP_REQUEST_TARGET | NTLMSSP_TARGET_TYPE_SERVER;
+
+ return flags;
+}
+
+const struct ntlmssp_challenge *
+ntlmssp_create_challenge(pool_t pool, const struct ntlmssp_request *request, size_t *size)
+{
+ buffer_t *buf = buffer_create_dynamic(pool, sizeof(struct ntlmssp_challenge), 4096);
+ uint32_t flags = ntlmssp_flags(read_le32(&request->flags));
+ struct ntlmssp_challenge c;
+
+ memset(&c, 0, sizeof(c));
+ write_le64(&c.magic, NTLMSSP_MAGIC);
+ write_le32(&c.type, NTLMSSP_MSG_TYPE2);
+ write_le32(&c.flags, flags);
+ random_fill(c.challenge, sizeof(c.challenge));
+
+ buffer_write(buf, 0, &c, sizeof(c));
+
+ if (flags & NTLMSSP_TARGET_TYPE_SERVER)
+ ntlmssp_append_string(buf,
+ offsetof(struct ntlmssp_challenge, target_name),
+ my_hostname);
+
+ ntlmssp_append_target_info(buf, offsetof(struct ntlmssp_challenge, target_info),
+ NTPLMSSP_V2_TARGET_FQDN, my_hostname,
+ NTPLMSSP_V2_TARGET_END);
+
+ *size = buffer_get_used_size(buf);
+ return buffer_free_without_data(buf);
+}
+
+static int ntlmssp_check_buffer(struct ntlmssp_buffer *buffer, size_t data_size, const char **error)
+{
+ uint32_t offset = read_le32(&buffer->offset);
+
+ if (offset >= data_size) {
+ *error = "buffer offset out of bounds";
+ return 0;
+ }
+
+ if (offset + read_le16(&buffer->space) > data_size) {
+ *error = "buffer end out of bounds";
+ return 0;
+ }
+
+ return 1;
+}
+
+int ntlmssp_check_request(struct ntlmssp_request *request, size_t data_size, const char **error)
+{
+ uint32_t flags;
+
+ if (data_size < sizeof(struct ntlmssp_request)) {
+ *error = "request too short";
+ return 0;
+ }
+
+ if (read_le64(&request->magic) != NTLMSSP_MAGIC) {
+ *error = "signature mismatch";
+ return 0;
+ }
+
+ if (read_le32(&request->type) != NTLMSSP_MSG_TYPE1) {
+ *error = "message type mismatch";
+ return 0;
+ }
+
+ flags = read_le32(&request->flags);
+
+ if ((flags & NTLMSSP_NEGOTIATE_UNICODE) == 0) {
+ *error = "client doesn't advertise Unicode support";
+ return 0;
+ }
+
+ if ((flags & NTLMSSP_NEGOTIATE_NTLM) == 0) {
+ *error = "client doesn't advertise NTLM support";
+ return 0;
+ }
+
+ return 1;
+}
+
+int ntlmssp_check_response(struct ntlmssp_response *response, size_t data_size, const char **error)
+{
+ if (data_size < sizeof(struct ntlmssp_response)) {
+ *error = "response too short";
+ return 0;
+ }
+
+ if (read_le64(&response->magic) != NTLMSSP_MAGIC) {
+ *error = "signature mismatch";
+ return 0;
+ }
+
+ if (read_le32(&response->type) != NTLMSSP_MSG_TYPE3) {
+ *error = "message type mismatch";
+ return 0;
+ }
+
+ if (!ntlmssp_check_buffer(&response->lm_response, data_size, error) ||
+ !ntlmssp_check_buffer(&response->ntlm_response, data_size, error) ||
+ !ntlmssp_check_buffer(&response->domain, data_size, error) ||
+ !ntlmssp_check_buffer(&response->user, data_size, error) ||
+ !ntlmssp_check_buffer(&response->workstation, data_size, error))
+ return 0;
+
+ return 1;
+}
diff -urpNX /usr/share/dontdiff dovecot-1.0-test30.vanilla/src/lib-ntlm/ntlm-message.h dovecot-1.0-test30/src/lib-ntlm/ntlm-message.h
--- dovecot-1.0-test30.vanilla/src/lib-ntlm/ntlm-message.h 1970-01-01 03:00:00.000000000 +0300
+++ dovecot-1.0-test30/src/lib-ntlm/ntlm-message.h 2004-07-27 11:04:46.000000000 +0400
@@ -0,0 +1,10 @@
+#ifndef __NTLM_MESSAGE_H__
+#define __NTLM_MESSAGE_H__
+
+const struct ntlmssp_challenge *
+ntlmssp_create_challenge(pool_t pool, const struct ntlmssp_request *request, size_t *size);
+
+int ntlmssp_check_request(struct ntlmssp_request *request, size_t data_size, const char **error);
+int ntlmssp_check_response(struct ntlmssp_response *response, size_t data_size, const char **error);
+
+#endif /* __NTLM_MESSAGE_H__ */
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 189 bytes
Desc: Digital signature
URL: <http://dovecot.org/pipermail/dovecot/attachments/20040728/7c09a8ee/attachment-0001.bin>
More information about the dovecot
mailing list