[Dovecot] [PATCH] support OEM encoding in NTLM messages

Andrey Panin
Fri, 22 Oct 2004 11:39:31 -0000

Hello,

after I started to use dovecot as a backend for exim4 SMTP
authentication on my main mailserver, I noticed that some
clients don't advertise unicode support and so they can't
log in.

To fix the problem the attached patch allows use of OEM encoding
in NTLM messages.

Please consider applying.

Best regards.

P.S. I want to release exim4 patch in the near future, probably
when Timo will stop making incompatible protocol changes ;)

--
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-test49.vanilla/src/auth/mech-ntlm.c
dovecot-1.0-test49/src/auth/mech-ntlm.c
--- dovecot-1.0-test49.vanilla/src/auth/mech-ntlm.c	2004-10-13
04:41:48.000000000 +0400
+++ dovecot-1.0-test49/src/auth/mech-ntlm.c	2004-10-21 23:41:16.000000000 +0400
@@ -26,6 +26,7 @@ struct ntlm_auth_request {

 	/* requested: */
 	int ntlm2_negotiated;
+	int unicode_negotiated;
 	const unsigned char *challenge;

 	/* received: */
@@ -141,6 +142,7 @@ mech_ntlm_auth_continue(struct auth_requ
 			(struct ntlmssp_request *)data;
 		const struct ntlmssp_challenge *message;
 		size_t message_size;
+		uint32_t flags;

 		if (!ntlmssp_check_request(ntlm_request, data_size, &error)) {
 			if (verbose) {
@@ -154,8 +156,9 @@ mech_ntlm_auth_continue(struct auth_requ

 		message = ntlmssp_create_challenge(request->pool, ntlm_request,
 						   &message_size);
-		request->ntlm2_negotiated -			read_le32(&message->flags) &
NTLMSSP_NEGOTIATE_NTLM2;
+		flags = read_le32(&message->flags);
+		request->ntlm2_negotiated = flags & NTLMSSP_NEGOTIATE_NTLM2;
+		request->unicode_negotiated = flags & NTLMSSP_NEGOTIATE_UNICODE;
 		request->challenge = message->challenge;

 		auth_request->callback(auth_request,
@@ -180,7 +183,8 @@ mech_ntlm_auth_continue(struct auth_requ
 		memcpy(request->response, response, data_size);

 		username = p_strdup(auth_request->pool,
-				    ntlmssp_t_str(request->response, user));
+				    ntlmssp_t_str(request->response, user,
+				    request->unicode_negotiated));

 		if (!mech_fix_username(username, &error)) {
 			if (verbose) {
diff -urpNX /usr/share/dontdiff dovecot-1.0-test49.vanilla/src/lib-ntlm/ntlm.h
dovecot-1.0-test49/src/lib-ntlm/ntlm.h
--- dovecot-1.0-test49.vanilla/src/lib-ntlm/ntlm.h	2004-07-30 07:16:22.000000000
+0400
+++ dovecot-1.0-test49/src/lib-ntlm/ntlm.h	2004-10-21 22:17:03.000000000 +0400
@@ -26,10 +26,11 @@ static inline unsigned int __ntlmssp_buf
 	return read_le16(&buffer->length);
 }

-#define ntlmssp_t_str(message, buffer) \
-	__ntlmssp_t_str((message), &message->buffer)
+#define ntlmssp_t_str(message, buffer, unicode) \
+	__ntlmssp_t_str((message), &(message)->buffer, (unicode))

 const char * __ntlmssp_t_str(const void *message,
-			     struct ntlmssp_buffer *buffer);
+			     struct ntlmssp_buffer *buffer,
+			     int unicode);

 #endif
diff -urpNX /usr/share/dontdiff
dovecot-1.0-test49.vanilla/src/lib-ntlm/ntlm-message.c
dovecot-1.0-test49/src/lib-ntlm/ntlm-message.c
--- dovecot-1.0-test49.vanilla/src/lib-ntlm/ntlm-message.c	2004-10-08
21:35:30.000000000 +0400
+++ dovecot-1.0-test49/src/lib-ntlm/ntlm-message.c	2004-10-21 23:49:05.000000000
+0400
@@ -21,42 +21,52 @@
 #include <stdarg.h>
 #include <ctype.h>

-const char * __ntlmssp_t_str(const void *message, struct ntlmssp_buffer
*buffer)
+const char * __ntlmssp_t_str(const void *message, struct ntlmssp_buffer
*buffer,
+			     int unicode)
 {
-	unsigned int len = read_le16(&buffer->length) / sizeof(ucs2le_t);
-	string_t *str = t_str_new(len / 2);
+	unsigned int len = read_le16(&buffer->length);
 	const char *p = ((char *) message) + read_le32(&buffer->offset);
+	string_t *str;
+
+	if (unicode)
+		len /= sizeof(ucs2le_t);
+
+	str = t_str_new(len);

 	while (len-- > 0) {
 		str_append_c(str, *p & 0x7f);
-		p += sizeof(ucs2le_t);
+		p += unicode ? sizeof(ucs2le_t) : 1;
 	}

 	return str_c(str);
 }

-static unsigned int append_string(buffer_t *buf, const char *str, int ucase)
+static unsigned int append_string(buffer_t *buf, const char *str,
+				  int ucase, int unicode)
 {
 	unsigned int length = 0;

 	for ( ; *str; str++) {
 		buffer_append_c(buf, ucase ? toupper(*str) : *str);
-		buffer_append_c(buf, 0);
-		length += sizeof(ucs2le_t);
+		if (unicode) {
+			buffer_append_c(buf, 0);
+			length++;
+		}
+		length++;
 	}

 	return length;
 }

 static void ntlmssp_append_string(buffer_t *buf, size_t buffer_offset,
-				  const char *str)
+				  const char *str, int unicode)
 {
 	struct ntlmssp_buffer buffer;
 	unsigned int length;

 	write_le32(&buffer.offset, buffer_get_used_size(buf));

-	length = append_string(buf, str, 0);
+	length = append_string(buf, str, 0, unicode);

 	write_le16(&buffer.length, length);
 	write_le16(&buffer.space, length);
@@ -95,7 +105,8 @@ static void ntlmssp_append_target_info(b
 				write_le16(&info.length,
 					   strlen(data) * sizeof(ucs2le_t));
 				buffer_append(buf, &info, sizeof(info));
-				length = append_string(buf, data, 0);
+				length = append_string(buf, data, 0, 1) +
+					 sizeof(info);
 				break;
 			default:
 				i_panic("Invalid NTLM target info block type "
@@ -115,10 +126,14 @@ static void ntlmssp_append_target_info(b

 static inline uint32_t ntlmssp_flags(uint32_t client_flags)
 {
-	uint32_t flags = NTLMSSP_NEGOTIATE_UNICODE |
-			 NTLMSSP_NEGOTIATE_NTLM |
+	uint32_t flags = NTLMSSP_NEGOTIATE_NTLM |
 			 NTLMSSP_NEGOTIATE_TARGET_INFO;

+	if (client_flags & NTLMSSP_NEGOTIATE_UNICODE)
+		flags |= NTLMSSP_NEGOTIATE_UNICODE;
+	else
+		flags |= NTLMSSP_NEGOTIATE_OEM;
+
 	if (client_flags & NTLMSSP_NEGOTIATE_NTLM2)
 		flags |= NTLMSSP_NEGOTIATE_NTLM2;

@@ -134,6 +149,7 @@ ntlmssp_create_challenge(pool_t pool, co
 {
 	buffer_t *buf;
 	uint32_t flags = ntlmssp_flags(read_le32(&request->flags));
+	int unicode = flags & NTLMSSP_NEGOTIATE_UNICODE;
 	struct ntlmssp_challenge c;

 	buf = buffer_create_dynamic(pool, sizeof(struct ntlmssp_challenge));
@@ -149,7 +165,7 @@ ntlmssp_create_challenge(pool_t pool, co
 	if (flags & NTLMSSP_TARGET_TYPE_SERVER)
 		ntlmssp_append_string(buf,
 			offsetof(struct ntlmssp_challenge, target_name),
-			my_hostname);
+			my_hostname, unicode);

 	ntlmssp_append_target_info(buf, offsetof(struct ntlmssp_challenge,
 						 target_info),
@@ -200,11 +216,6 @@ int ntlmssp_check_request(const struct n

 	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;
-------------- 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/20041022/457a9af5/attachment-0001.bin>