1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3  * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
4  *
5  * This library is free software: you can redistribute it and/or modify it
6  * under the terms of the GNU Lesser General Public License as published by
7  * the Free Software Foundation.
8  *
9  * This library is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
12  * for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public License
15  * along with this library. If not, see <http://www.gnu.org/licenses/>.
16  *
17  */
18 
19 #include "evolution-data-server-config.h"
20 
21 #include <ctype.h>
22 #include <string.h>
23 
24 #include <glib/gi18n-lib.h>
25 
26 #include "camel-network-settings.h"
27 #include "camel-sasl-ntlm.h"
28 #include "camel-stream-process.h"
29 
30 struct _CamelSaslNTLMPrivate {
31 	gint placeholder;  /* allow for future expansion */
32 #ifndef G_OS_WIN32
33 	gboolean tried_helper;
34 	CamelStream *helper_stream;
35 	gchar *type1_msg;
36 #endif
37 };
38 
39 static CamelServiceAuthType sasl_ntlm_auth_type = {
40 	N_("NTLM / SPA"),
41 
42 	N_("This option will connect to a Windows-based server using "
43 	   "NTLM / Secure Password Authentication."),
44 
45 	"NTLM",
46 	TRUE
47 };
48 
49 G_DEFINE_TYPE_WITH_PRIVATE (CamelSaslNTLM, camel_sasl_ntlm, CAMEL_TYPE_SASL)
50 
51 #define NTLM_REQUEST "NTLMSSP\x00\x01\x00\x00\x00\x06\x82\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x30\x00\x00\x00\x00\x00\x00\x00\x30\x00\x00\x00"
52 
53 #define NTLM_CHALLENGE_DOMAIN_OFFSET		12
54 #define NTLM_CHALLENGE_FLAGS_OFFSET		20
55 #define NTLM_CHALLENGE_NONCE_OFFSET		24
56 
57 #define NTLM_RESPONSE_HEADER         "NTLMSSP\x00\x03\x00\x00\x00"
58 #define NTLM_RESPONSE_FLAGS          "\x82\x01"
59 #define NTLM_RESPONSE_BASE_SIZE      64
60 #define NTLM_RESPONSE_LM_RESP_OFFSET 12
61 #define NTLM_RESPONSE_NT_RESP_OFFSET 20
62 #define NTLM_RESPONSE_DOMAIN_OFFSET  28
63 #define NTLM_RESPONSE_USER_OFFSET    36
64 #define NTLM_RESPONSE_HOST_OFFSET    44
65 #define NTLM_RESPONSE_FLAGS_OFFSET   60
66 
67 #define NTLM_AUTH_HELPER "/usr/bin/ntlm_auth"
68 
69 typedef struct {
70 	guint16 length;
71 	guint16 allocated;
72 	guint32 offset;
73 } SecurityBuffer;
74 
75 static GString *
ntlm_get_string(GByteArray * ba,gint offset)76 ntlm_get_string (GByteArray *ba,
77                  gint offset)
78 {
79 	SecurityBuffer *secbuf;
80 	gchar *buf_string;
81 	guint16 buf_length;
82 	guint32 buf_offset;
83 
84 	secbuf = (SecurityBuffer *) &ba->data[offset];
85 	buf_length = GUINT16_FROM_LE (secbuf->length);
86 	buf_offset = GUINT32_FROM_LE (secbuf->offset);
87 
88 	if (ba->len < buf_offset + buf_length)
89 		return NULL;
90 
91 	buf_string = (gchar *) &ba->data[buf_offset];
92 	return g_string_new_len (buf_string, buf_length);
93 }
94 
95 static void
ntlm_set_string(GByteArray * ba,gint offset,const gchar * data,gint len)96 ntlm_set_string (GByteArray *ba,
97                  gint offset,
98                  const gchar *data,
99                  gint len)
100 {
101 	SecurityBuffer *secbuf;
102 
103 	secbuf = (SecurityBuffer *) &ba->data[offset];
104 	secbuf->length = GUINT16_TO_LE (len);
105 	secbuf->offset = GUINT32_TO_LE (ba->len);
106 	secbuf->allocated = secbuf->length;
107 
108 	g_byte_array_append (ba, (guint8 *) data, len);
109 }
110 
111 /* MD4 */
112 static void md4sum                (const guchar *in,
113 				   gint                  nbytes,
114 				   guchar        digest[16]);
115 
116 /* DES */
117 typedef guint32 DES_KS[16][2]; /* Single-key DES key schedule */
118 
119 static void deskey                (DES_KS, guchar *, gint);
120 
121 static void des                   (DES_KS, guchar *);
122 
123 static void setup_schedule        (const guchar *key_56, DES_KS ks);
124 
125 #define LM_PASSWORD_MAGIC "\x4B\x47\x53\x21\x40\x23\x24\x25" \
126                           "\x4B\x47\x53\x21\x40\x23\x24\x25" \
127 			  "\x00\x00\x00\x00\x00"
128 
129 static void
ntlm_lanmanager_hash(const gchar * password,gchar hash[21])130 ntlm_lanmanager_hash (const gchar *password,
131                       gchar hash[21])
132 {
133 	guchar lm_password[15];
134 	DES_KS ks;
135 	gint i;
136 
137 	for (i = 0; i < 14 && password && password[i]; i++)
138 		lm_password[i] = toupper ((guchar) password[i]);
139 
140 	for (; i < 15; i++)
141 		lm_password[i] = '\0';
142 
143 	memcpy (hash, LM_PASSWORD_MAGIC, 21);
144 
145 	setup_schedule (lm_password, ks);
146 	des (ks, (guchar *) hash);
147 
148 	setup_schedule (lm_password + 7, ks);
149 	des (ks, (guchar *) hash + 8);
150 }
151 
152 static void
ntlm_nt_hash(const gchar * password,gchar hash[21])153 ntlm_nt_hash (const gchar *password,
154               gchar hash[21])
155 {
156 	guchar *buf, *p;
157 
158 	if (!password)
159 		password = "";
160 
161 	p = buf = g_malloc (strlen (password) * 2);
162 
163 	while (*password) {
164 		*p++ = *password++;
165 		*p++ = '\0';
166 	}
167 
168 	md4sum (buf, p - buf, (guchar *) hash);
169 	memset (hash + 16, 0, 5);
170 
171 	g_free (buf);
172 }
173 
174 #define KEYBITS(k,s) \
175         (((k[(s) / 8] << ((s) % 8)) & 0xFF) | (k[(s) / 8 + 1] >> (8 - (s) % 8)))
176 
177 /* DES utils */
178 /* Set up a key schedule based on a 56bit key */
179 static void
setup_schedule(const guchar * key_56,DES_KS ks)180 setup_schedule (const guchar *key_56,
181                 DES_KS ks)
182 {
183 	guchar key[8];
184 	gint i, c, bit;
185 
186 	for (i = 0; i < 8; i++) {
187 		key[i] = KEYBITS (key_56, i * 7);
188 
189 		/* Fix parity */
190 		for (c = bit = 0; bit < 8; bit++)
191 			if (key[i] & (1 << bit))
192 				c++;
193 		if (!(c & 1))
194 			key[i] ^= 0x01;
195 	}
196 
197 	deskey (ks, key, 0);
198 }
199 
200 static void
ntlm_calc_response(const guchar key[21],const guchar plaintext[8],guchar results[24])201 ntlm_calc_response (const guchar key[21],
202                     const guchar plaintext[8],
203                     guchar results[24])
204 {
205 	DES_KS ks;
206 
207 	memcpy (results, plaintext, 8);
208 	memcpy (results + 8, plaintext, 8);
209 	memcpy (results + 16, plaintext, 8);
210 
211 	setup_schedule (key, ks);
212 	des (ks, results);
213 
214 	setup_schedule (key + 7, ks);
215 	des (ks, results + 8);
216 
217 	setup_schedule (key + 14, ks);
218 	des (ks, results + 16);
219 }
220 
221 /*
222  * MD4 encoder. (The one everyone else uses is not GPL-compatible;
223  * this is a reimplementation from spec.) This doesn't need to be
224  * efficient for our purposes, although it would be nice to fix
225  * it to not malloc()...
226  */
227 
228 #define F(X,Y,Z) ( ((X)&(Y)) | ((~(X))&(Z)) )
229 #define G(X,Y,Z) ( ((X)&(Y)) | ((X)&(Z)) | ((Y)&(Z)) )
230 #define H(X,Y,Z) ( (X)^(Y)^(Z) )
231 #define ROT(val, n) ( ((val) << (n)) | ((val) >> (32 - (n))) )
232 
233 static void
md4sum(const guchar * in,gint nbytes,guchar digest[16])234 md4sum (const guchar *in,
235         gint nbytes,
236         guchar digest[16])
237 {
238 	guchar *M;
239 	guint32 A, B, C, D, AA, BB, CC, DD, X[16];
240 	gint pbytes, nbits = nbytes * 8, i, j;
241 
242 	/* There is *always* padding of at least one bit. */
243 	pbytes = ((119 - (nbytes % 64)) % 64) + 1;
244 	M = alloca (nbytes + pbytes + 8);
245 	memcpy (M, in, nbytes);
246 	memset (M + nbytes, 0, pbytes + 8);
247 	M[nbytes] = 0x80;
248 	M[nbytes + pbytes] = nbits & 0xFF;
249 	M[nbytes + pbytes + 1] = (nbits >> 8) & 0xFF;
250 	M[nbytes + pbytes + 2] = (nbits >> 16) & 0xFF;
251 	M[nbytes + pbytes + 3] = (nbits >> 24) & 0xFF;
252 
253 	A = 0x67452301;
254 	B = 0xEFCDAB89;
255 	C = 0x98BADCFE;
256 	D = 0x10325476;
257 
258 	for (i = 0; i < nbytes + pbytes + 8; i += 64) {
259 		for (j = 0; j < 16; j++) {
260 			X[j] = (M[i + j * 4]) |
261 				(M[i + j * 4 + 1] << 8) |
262 				(M[i + j * 4 + 2] << 16) |
263 				(M[i + j * 4 + 3] << 24);
264 		}
265 
266 		AA = A;
267 		BB = B;
268 		CC = C;
269 		DD = D;
270 
271 		A = ROT (A + F (B, C, D) + X[0], 3);
272 		D = ROT (D + F (A, B, C) + X[1], 7);
273 		C = ROT (C + F (D, A, B) + X[2], 11);
274 		B = ROT (B + F (C, D, A) + X[3], 19);
275 		A = ROT (A + F (B, C, D) + X[4], 3);
276 		D = ROT (D + F (A, B, C) + X[5], 7);
277 		C = ROT (C + F (D, A, B) + X[6], 11);
278 		B = ROT (B + F (C, D, A) + X[7], 19);
279 		A = ROT (A + F (B, C, D) + X[8], 3);
280 		D = ROT (D + F (A, B, C) + X[9], 7);
281 		C = ROT (C + F (D, A, B) + X[10], 11);
282 		B = ROT (B + F (C, D, A) + X[11], 19);
283 		A = ROT (A + F (B, C, D) + X[12], 3);
284 		D = ROT (D + F (A, B, C) + X[13], 7);
285 		C = ROT (C + F (D, A, B) + X[14], 11);
286 		B = ROT (B + F (C, D, A) + X[15], 19);
287 
288 		A = ROT (A + G (B, C, D) + X[0] + 0x5A827999, 3);
289 		D = ROT (D + G (A, B, C) + X[4] + 0x5A827999, 5);
290 		C = ROT (C + G (D, A, B) + X[8] + 0x5A827999, 9);
291 		B = ROT (B + G (C, D, A) + X[12] + 0x5A827999, 13);
292 		A = ROT (A + G (B, C, D) + X[1] + 0x5A827999, 3);
293 		D = ROT (D + G (A, B, C) + X[5] + 0x5A827999, 5);
294 		C = ROT (C + G (D, A, B) + X[9] + 0x5A827999, 9);
295 		B = ROT (B + G (C, D, A) + X[13] + 0x5A827999, 13);
296 		A = ROT (A + G (B, C, D) + X[2] + 0x5A827999, 3);
297 		D = ROT (D + G (A, B, C) + X[6] + 0x5A827999, 5);
298 		C = ROT (C + G (D, A, B) + X[10] + 0x5A827999, 9);
299 		B = ROT (B + G (C, D, A) + X[14] + 0x5A827999, 13);
300 		A = ROT (A + G (B, C, D) + X[3] + 0x5A827999, 3);
301 		D = ROT (D + G (A, B, C) + X[7] + 0x5A827999, 5);
302 		C = ROT (C + G (D, A, B) + X[11] + 0x5A827999, 9);
303 		B = ROT (B + G (C, D, A) + X[15] + 0x5A827999, 13);
304 
305 		A = ROT (A + H (B, C, D) + X[0] + 0x6ED9EBA1, 3);
306 		D = ROT (D + H (A, B, C) + X[8] + 0x6ED9EBA1, 9);
307 		C = ROT (C + H (D, A, B) + X[4] + 0x6ED9EBA1, 11);
308 		B = ROT (B + H (C, D, A) + X[12] + 0x6ED9EBA1, 15);
309 		A = ROT (A + H (B, C, D) + X[2] + 0x6ED9EBA1, 3);
310 		D = ROT (D + H (A, B, C) + X[10] + 0x6ED9EBA1, 9);
311 		C = ROT (C + H (D, A, B) + X[6] + 0x6ED9EBA1, 11);
312 		B = ROT (B + H (C, D, A) + X[14] + 0x6ED9EBA1, 15);
313 		A = ROT (A + H (B, C, D) + X[1] + 0x6ED9EBA1, 3);
314 		D = ROT (D + H (A, B, C) + X[9] + 0x6ED9EBA1, 9);
315 		C = ROT (C + H (D, A, B) + X[5] + 0x6ED9EBA1, 11);
316 		B = ROT (B + H (C, D, A) + X[13] + 0x6ED9EBA1, 15);
317 		A = ROT (A + H (B, C, D) + X[3] + 0x6ED9EBA1, 3);
318 		D = ROT (D + H (A, B, C) + X[11] + 0x6ED9EBA1, 9);
319 		C = ROT (C + H (D, A, B) + X[7] + 0x6ED9EBA1, 11);
320 		B = ROT (B + H (C, D, A) + X[15] + 0x6ED9EBA1, 15);
321 
322 		A += AA;
323 		B += BB;
324 		C += CC;
325 		D += DD;
326 	}
327 
328 	digest[0] = A & 0xFF;
329 	digest[1] = (A >> 8) & 0xFF;
330 	digest[2] = (A >> 16) & 0xFF;
331 	digest[3] = (A >> 24) & 0xFF;
332 	digest[4] = B & 0xFF;
333 	digest[5] = (B >> 8) & 0xFF;
334 	digest[6] = (B >> 16) & 0xFF;
335 	digest[7] = (B >> 24) & 0xFF;
336 	digest[8] = C & 0xFF;
337 	digest[9] = (C >> 8) & 0xFF;
338 	digest[10] = (C >> 16) & 0xFF;
339 	digest[11] = (C >> 24) & 0xFF;
340 	digest[12] = D & 0xFF;
341 	digest[13] = (D >> 8) & 0xFF;
342 	digest[14] = (D >> 16) & 0xFF;
343 	digest[15] = (D >> 24) & 0xFF;
344 }
345 
346 /* Public domain DES implementation from Phil Karn */
347 static guint32 Spbox[8][64] = {
348 	{ 0x01010400, 0x00000000, 0x00010000, 0x01010404,
349 	  0x01010004, 0x00010404, 0x00000004, 0x00010000,
350 	  0x00000400, 0x01010400, 0x01010404, 0x00000400,
351 	  0x01000404, 0x01010004, 0x01000000, 0x00000004,
352 	  0x00000404, 0x01000400, 0x01000400, 0x00010400,
353 	  0x00010400, 0x01010000, 0x01010000, 0x01000404,
354 	  0x00010004, 0x01000004, 0x01000004, 0x00010004,
355 	  0x00000000, 0x00000404, 0x00010404, 0x01000000,
356 	  0x00010000, 0x01010404, 0x00000004, 0x01010000,
357 	  0x01010400, 0x01000000, 0x01000000, 0x00000400,
358 	  0x01010004, 0x00010000, 0x00010400, 0x01000004,
359 	  0x00000400, 0x00000004, 0x01000404, 0x00010404,
360 	  0x01010404, 0x00010004, 0x01010000, 0x01000404,
361 	  0x01000004, 0x00000404, 0x00010404, 0x01010400,
362 	  0x00000404, 0x01000400, 0x01000400, 0x00000000,
363 	  0x00010004, 0x00010400, 0x00000000, 0x01010004 },
364 	{ 0x80108020, 0x80008000, 0x00008000, 0x00108020,
365 	  0x00100000, 0x00000020, 0x80100020, 0x80008020,
366 	  0x80000020, 0x80108020, 0x80108000, 0x80000000,
367 	  0x80008000, 0x00100000, 0x00000020, 0x80100020,
368 	  0x00108000, 0x00100020, 0x80008020, 0x00000000,
369 	  0x80000000, 0x00008000, 0x00108020, 0x80100000,
370 	  0x00100020, 0x80000020, 0x00000000, 0x00108000,
371 	  0x00008020, 0x80108000, 0x80100000, 0x00008020,
372 	  0x00000000, 0x00108020, 0x80100020, 0x00100000,
373 	  0x80008020, 0x80100000, 0x80108000, 0x00008000,
374 	  0x80100000, 0x80008000, 0x00000020, 0x80108020,
375 	  0x00108020, 0x00000020, 0x00008000, 0x80000000,
376 	  0x00008020, 0x80108000, 0x00100000, 0x80000020,
377 	  0x00100020, 0x80008020, 0x80000020, 0x00100020,
378 	  0x00108000, 0x00000000, 0x80008000, 0x00008020,
379 	  0x80000000, 0x80100020, 0x80108020, 0x00108000 },
380 	{ 0x00000208, 0x08020200, 0x00000000, 0x08020008,
381 	  0x08000200, 0x00000000, 0x00020208, 0x08000200,
382 	  0x00020008, 0x08000008, 0x08000008, 0x00020000,
383 	  0x08020208, 0x00020008, 0x08020000, 0x00000208,
384 	  0x08000000, 0x00000008, 0x08020200, 0x00000200,
385 	  0x00020200, 0x08020000, 0x08020008, 0x00020208,
386 	  0x08000208, 0x00020200, 0x00020000, 0x08000208,
387 	  0x00000008, 0x08020208, 0x00000200, 0x08000000,
388 	  0x08020200, 0x08000000, 0x00020008, 0x00000208,
389 	  0x00020000, 0x08020200, 0x08000200, 0x00000000,
390 	  0x00000200, 0x00020008, 0x08020208, 0x08000200,
391 	  0x08000008, 0x00000200, 0x00000000, 0x08020008,
392 	  0x08000208, 0x00020000, 0x08000000, 0x08020208,
393 	  0x00000008, 0x00020208, 0x00020200, 0x08000008,
394 	  0x08020000, 0x08000208, 0x00000208, 0x08020000,
395 	  0x00020208, 0x00000008, 0x08020008, 0x00020200 },
396 	{ 0x00802001, 0x00002081, 0x00002081, 0x00000080,
397 	  0x00802080, 0x00800081, 0x00800001, 0x00002001,
398 	  0x00000000, 0x00802000, 0x00802000, 0x00802081,
399 	  0x00000081, 0x00000000, 0x00800080, 0x00800001,
400 	  0x00000001, 0x00002000, 0x00800000, 0x00802001,
401 	  0x00000080, 0x00800000, 0x00002001, 0x00002080,
402 	  0x00800081, 0x00000001, 0x00002080, 0x00800080,
403 	  0x00002000, 0x00802080, 0x00802081, 0x00000081,
404 	  0x00800080, 0x00800001, 0x00802000, 0x00802081,
405 	  0x00000081, 0x00000000, 0x00000000, 0x00802000,
406 	  0x00002080, 0x00800080, 0x00800081, 0x00000001,
407 	  0x00802001, 0x00002081, 0x00002081, 0x00000080,
408 	  0x00802081, 0x00000081, 0x00000001, 0x00002000,
409 	  0x00800001, 0x00002001, 0x00802080, 0x00800081,
410 	  0x00002001, 0x00002080, 0x00800000, 0x00802001,
411 	  0x00000080, 0x00800000, 0x00002000, 0x00802080 },
412 	{ 0x00000100, 0x02080100, 0x02080000, 0x42000100,
413 	  0x00080000, 0x00000100, 0x40000000, 0x02080000,
414 	  0x40080100, 0x00080000, 0x02000100, 0x40080100,
415 	  0x42000100, 0x42080000, 0x00080100, 0x40000000,
416 	  0x02000000, 0x40080000, 0x40080000, 0x00000000,
417 	  0x40000100, 0x42080100, 0x42080100, 0x02000100,
418 	  0x42080000, 0x40000100, 0x00000000, 0x42000000,
419 	  0x02080100, 0x02000000, 0x42000000, 0x00080100,
420 	  0x00080000, 0x42000100, 0x00000100, 0x02000000,
421 	  0x40000000, 0x02080000, 0x42000100, 0x40080100,
422 	  0x02000100, 0x40000000, 0x42080000, 0x02080100,
423 	  0x40080100, 0x00000100, 0x02000000, 0x42080000,
424 	  0x42080100, 0x00080100, 0x42000000, 0x42080100,
425 	  0x02080000, 0x00000000, 0x40080000, 0x42000000,
426 	  0x00080100, 0x02000100, 0x40000100, 0x00080000,
427 	  0x00000000, 0x40080000, 0x02080100, 0x40000100 },
428 	{ 0x20000010, 0x20400000, 0x00004000, 0x20404010,
429 	  0x20400000, 0x00000010, 0x20404010, 0x00400000,
430 	  0x20004000, 0x00404010, 0x00400000, 0x20000010,
431 	  0x00400010, 0x20004000, 0x20000000, 0x00004010,
432 	  0x00000000, 0x00400010, 0x20004010, 0x00004000,
433 	  0x00404000, 0x20004010, 0x00000010, 0x20400010,
434 	  0x20400010, 0x00000000, 0x00404010, 0x20404000,
435 	  0x00004010, 0x00404000, 0x20404000, 0x20000000,
436 	  0x20004000, 0x00000010, 0x20400010, 0x00404000,
437 	  0x20404010, 0x00400000, 0x00004010, 0x20000010,
438 	  0x00400000, 0x20004000, 0x20000000, 0x00004010,
439 	  0x20000010, 0x20404010, 0x00404000, 0x20400000,
440 	  0x00404010, 0x20404000, 0x00000000, 0x20400010,
441 	  0x00000010, 0x00004000, 0x20400000, 0x00404010,
442 	  0x00004000, 0x00400010, 0x20004010, 0x00000000,
443 	  0x20404000, 0x20000000, 0x00400010, 0x20004010 },
444 	{ 0x00200000, 0x04200002, 0x04000802, 0x00000000,
445 	  0x00000800, 0x04000802, 0x00200802, 0x04200800,
446 	  0x04200802, 0x00200000, 0x00000000, 0x04000002,
447 	  0x00000002, 0x04000000, 0x04200002, 0x00000802,
448 	  0x04000800, 0x00200802, 0x00200002, 0x04000800,
449 	  0x04000002, 0x04200000, 0x04200800, 0x00200002,
450 	  0x04200000, 0x00000800, 0x00000802, 0x04200802,
451 	  0x00200800, 0x00000002, 0x04000000, 0x00200800,
452 	  0x04000000, 0x00200800, 0x00200000, 0x04000802,
453 	  0x04000802, 0x04200002, 0x04200002, 0x00000002,
454 	  0x00200002, 0x04000000, 0x04000800, 0x00200000,
455 	  0x04200800, 0x00000802, 0x00200802, 0x04200800,
456 	  0x00000802, 0x04000002, 0x04200802, 0x04200000,
457 	  0x00200800, 0x00000000, 0x00000002, 0x04200802,
458 	  0x00000000, 0x00200802, 0x04200000, 0x00000800,
459 	  0x04000002, 0x04000800, 0x00000800, 0x00200002 },
460 	{ 0x10001040, 0x00001000, 0x00040000, 0x10041040,
461 	  0x10000000, 0x10001040, 0x00000040, 0x10000000,
462 	  0x00040040, 0x10040000, 0x10041040, 0x00041000,
463 	  0x10041000, 0x00041040, 0x00001000, 0x00000040,
464 	  0x10040000, 0x10000040, 0x10001000, 0x00001040,
465 	  0x00041000, 0x00040040, 0x10040040, 0x10041000,
466 	  0x00001040, 0x00000000, 0x00000000, 0x10040040,
467 	  0x10000040, 0x10001000, 0x00041040, 0x00040000,
468 	  0x00041040, 0x00040000, 0x10041000, 0x00001000,
469 	  0x00000040, 0x10040040, 0x00001000, 0x00041040,
470 	  0x10001000, 0x00000040, 0x10000040, 0x10040000,
471 	  0x10040040, 0x10000000, 0x00040000, 0x10001040,
472 	  0x00000000, 0x10041040, 0x00040040, 0x10000040,
473 	  0x10040000, 0x10001000, 0x10001040, 0x00000000,
474 	  0x10041040, 0x00041000, 0x00041000, 0x00001040,
475 	  0x00001040, 0x00040040, 0x10000000, 0x10041000 }
476 };
477 
478 #undef F
479 #define	F(l,r,key){\
480 	work = ((r >> 4) | (r << 28)) ^ key[0];\
481 	l ^= Spbox[6][work & 0x3f];\
482 	l ^= Spbox[4][(work >> 8) & 0x3f];\
483 	l ^= Spbox[2][(work >> 16) & 0x3f];\
484 	l ^= Spbox[0][(work >> 24) & 0x3f];\
485 	work = r ^ key[1];\
486 	l ^= Spbox[7][work & 0x3f];\
487 	l ^= Spbox[5][(work >> 8) & 0x3f];\
488 	l ^= Spbox[3][(work >> 16) & 0x3f];\
489 	l ^= Spbox[1][(work >> 24) & 0x3f];\
490 }
491 
492 /* Encrypt or decrypt a block of data in ECB mode */
493 static void
des(guint32 ks[16][2],guchar * block)494 des (guint32 ks[16][2],
495      guchar *block)
496 {
497 	guint32 left, right, work;
498 
499 	/* Read input block and place in left/right in big-endian order */
500 	left = ((guint32) block[0] << 24)
501 	 | ((guint32) block[1] << 16)
502 	 | ((guint32) block[2] << 8)
503 	 | (guint32) block[3];
504 	right = ((guint32) block[4] << 24)
505 	 | ((guint32) block[5] << 16)
506 	 | ((guint32) block[6] << 8)
507 	 | (guint32) block[7];
508 
509 	/* Hoey's clever initial permutation algorithm, from Outerbridge
510 	 * (see Schneier p 478)
511 	 *
512 	 * The convention here is the same as Outerbridge: rotate each
513 	 * register left by 1 bit, i.e., so that "left" contains permuted
514 	 * input bits 2, 3, 4, ... 1 and "right" contains 33, 34, 35, ... 32
515 	 * (using origin-1 numbering as in the FIPS). This allows us to avoid
516 	 * one of the two rotates that would otherwise be required in each of
517 	 * the 16 rounds.
518 	 */
519 	work = ((left >> 4) ^ right) & 0x0f0f0f0f;
520 	right ^= work;
521 	left ^= work << 4;
522 	work = ((left >> 16) ^ right) & 0xffff;
523 	right ^= work;
524 	left ^= work << 16;
525 	work = ((right >> 2) ^ left) & 0x33333333;
526 	left ^= work;
527 	right ^= (work << 2);
528 	work = ((right >> 8) ^ left) & 0xff00ff;
529 	left ^= work;
530 	right ^= (work << 8);
531 	right = (right << 1) | (right >> 31);
532 	work = (left ^ right) & 0xaaaaaaaa;
533 	left ^= work;
534 	right ^= work;
535 	left = (left << 1) | (left >> 31);
536 
537 	/* Now do the 16 rounds */
538 	F (left,right,ks[0]);
539 	F (right,left,ks[1]);
540 	F (left,right,ks[2]);
541 	F (right,left,ks[3]);
542 	F (left,right,ks[4]);
543 	F (right,left,ks[5]);
544 	F (left,right,ks[6]);
545 	F (right,left,ks[7]);
546 	F (left,right,ks[8]);
547 	F (right,left,ks[9]);
548 	F (left,right,ks[10]);
549 	F (right,left,ks[11]);
550 	F (left,right,ks[12]);
551 	F (right,left,ks[13]);
552 	F (left,right,ks[14]);
553 	F (right,left,ks[15]);
554 
555 	/* Inverse permutation, also from Hoey via Outerbridge and Schneier */
556 	right = (right << 31) | (right >> 1);
557 	work = (left ^ right) & 0xaaaaaaaa;
558 	left ^= work;
559 	right ^= work;
560 	left = (left >> 1) | (left << 31);
561 	work = ((left >> 8) ^ right) & 0xff00ff;
562 	right ^= work;
563 	left ^= work << 8;
564 	work = ((left >> 2) ^ right) & 0x33333333;
565 	right ^= work;
566 	left ^= work << 2;
567 	work = ((right >> 16) ^ left) & 0xffff;
568 	left ^= work;
569 	right ^= work << 16;
570 	work = ((right >> 4) ^ left) & 0x0f0f0f0f;
571 	left ^= work;
572 	right ^= work << 4;
573 
574 	/* Put the block back into the user's buffer with final swap */
575 	block[0] = right >> 24;
576 	block[1] = right >> 16;
577 	block[2] = right >> 8;
578 	block[3] = right;
579 	block[4] = left >> 24;
580 	block[5] = left >> 16;
581 	block[6] = left >> 8;
582 	block[7] = left;
583 }
584 
585 /* Key schedule-related tables from FIPS-46 */
586 
587 /* permuted choice table (key) */
588 static guchar pc1[] = {
589 	57, 49, 41, 33, 25, 17,  9,
590 	 1, 58, 50, 42, 34, 26, 18,
591 	10,  2, 59, 51, 43, 35, 27,
592 	19, 11,  3, 60, 52, 44, 36,
593 
594 	63, 55, 47, 39, 31, 23, 15,
595 	 7, 62, 54, 46, 38, 30, 22,
596 	14,  6, 61, 53, 45, 37, 29,
597 	21, 13,  5, 28, 20, 12,  4
598 };
599 
600 /* number left rotations of pc1 */
601 static guchar totrot[] = {
602 	1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28
603 };
604 
605 /* permuted choice key (table) */
606 static guchar pc2[] = {
607 	14, 17, 11, 24,  1,  5,
608 	 3, 28, 15,  6, 21, 10,
609 	23, 19, 12,  4, 26,  8,
610 	16,  7, 27, 20, 13,  2,
611 	41, 52, 31, 37, 47, 55,
612 	30, 40, 51, 45, 33, 48,
613 	44, 49, 39, 56, 34, 53,
614 	46, 42, 50, 36, 29, 32
615 };
616 
617 /* End of DES-defined tables */
618 
619 /* bit 0 is left-most in byte */
620 static gint bytebit[] = {
621 	0200,0100,040,020,010,04,02,01
622 };
623 
624 /* Generate key schedule for encryption or decryption
625  * depending on the value of "decrypt"
626  */
627 static void
deskey(DES_KS k,guchar * key,gint decrypt)628 deskey (DES_KS k,
629         guchar *key,
630         gint decrypt)
631 {
632 	guchar pc1m[56];		/* place to modify pc1 into */
633 	guchar pcr[56];		/* place to rotate pc1 into */
634 	register gint i,j,l;
635 	gint m;
636 	guchar ks[8];
637 
638 	for (j=0; j<56; j++) {		/* convert pc1 to bits of key */
639 		l=pc1[j]-1;		/* integer bit location	 */
640 		m = l & 07;		/* find bit		 */
641 		pc1m[j]=(key[l>>3] &	/* find which key byte l is in */
642 			bytebit[m])	/* and which bit of that byte */
643 			? 1 : 0;	/* and store 1-bit result */
644 	}
645 	for (i=0; i<16; i++) {		/* key chunk for each iteration */
646 		memset (ks,0,sizeof (ks));	/* Clear key schedule */
647 		for (j=0; j<56; j++)	/* rotate pc1 the right amount */
648 			pcr[j] = pc1m[(l = j + totrot[decrypt? 15 - i : i]) < (j < 28? 28 : 56) ? l: l - 28];
649 			/* rotate left and right halves independently */
650 		for (j=0; j<48; j++){	/* select bits individually */
651 			/* check bit that goes to ks[j] */
652 			if (pcr[pc2[j]-1]) {
653 				/* mask it in if it's there */
654 				l= j % 6;
655 				ks[j / 6] |= bytebit[l] >> 2;
656 			}
657 		}
658 		/* Now convert to packed odd/even interleaved form */
659 		k[i][0] = ((guint32) ks[0] << 24)
660 		 | ((guint32) ks[2] << 16)
661 		 | ((guint32) ks[4] << 8)
662 		 | ((guint32) ks[6]);
663 		k[i][1] = ((guint32) ks[1] << 24)
664 		 | ((guint32) ks[3] << 16)
665 		 | ((guint32) ks[5] << 8)
666 		 | ((guint32) ks[7]);
667 	}
668 }
669 
670 static gboolean
sasl_ntlm_try_empty_password_sync(CamelSasl * sasl,GCancellable * cancellable,GError ** error)671 sasl_ntlm_try_empty_password_sync (CamelSasl *sasl,
672                                    GCancellable *cancellable,
673                                    GError **error)
674 {
675 #ifndef G_OS_WIN32
676 	CamelStream *stream;
677 	CamelNetworkSettings *network_settings;
678 	CamelSettings *settings;
679 	CamelService *service;
680 	CamelSaslNTLM *ntlm = CAMEL_SASL_NTLM (sasl);
681 	CamelSaslNTLMPrivate *priv = ntlm->priv;
682 	const gchar *cp;
683 	gchar *user;
684 	gchar buf[1024];
685 	gsize s;
686 	gchar *command;
687 	gint ret;
688 
689 	if (priv->tried_helper)
690 		return !!priv->helper_stream;
691 
692 	priv->tried_helper = TRUE;
693 
694 	if (access (NTLM_AUTH_HELPER, X_OK))
695 		return FALSE;
696 
697 	service = camel_sasl_get_service (sasl);
698 
699 	settings = camel_service_ref_settings (service);
700 	g_return_val_if_fail (CAMEL_IS_NETWORK_SETTINGS (settings), FALSE);
701 
702 	network_settings = CAMEL_NETWORK_SETTINGS (settings);
703 	user = camel_network_settings_dup_user (network_settings);
704 
705 	g_object_unref (settings);
706 
707 	g_return_val_if_fail (user != NULL, FALSE);
708 
709 	cp = strchr (user, '\\');
710 	if (cp != NULL) {
711 		command = g_strdup_printf (
712 			"%s --helper-protocol ntlmssp-client-1 "
713 			"--use-cached-creds --username '%s' "
714 			"--domain '%.*s'", NTLM_AUTH_HELPER,
715 			cp + 1, (gint)(cp - user), user);
716 	} else {
717 		command = g_strdup_printf (
718 			"%s --helper-protocol ntlmssp-client-1 "
719 			"--use-cached-creds --username '%s'",
720 			NTLM_AUTH_HELPER, user);
721 	}
722 
723 	stream = camel_stream_process_new ();
724 
725 	ret = camel_stream_process_connect (
726 		CAMEL_STREAM_PROCESS (stream), command, NULL, error);
727 
728 	g_free (command);
729 	g_free (user);
730 
731 	if (ret) {
732 		g_object_unref (stream);
733 		return FALSE;
734 	}
735 
736 	if (camel_stream_write_string (stream, "YR\n", cancellable, error) < 0) {
737 		g_object_unref (stream);
738 		return FALSE;
739 	}
740 
741 	s = camel_stream_read (stream, buf, sizeof (buf), cancellable, NULL);
742 	if (s < 4) {
743 		g_object_unref (stream);
744 		return FALSE;
745 	}
746 
747 	if (buf[0] != 'Y' || buf[1] != 'R' || buf[2] != ' ' || buf[s - 1] != '\n') {
748 		g_object_unref (stream);
749 		return FALSE;
750 	}
751 
752 	buf[s - 1] = 0;
753 
754 	priv->helper_stream = stream;
755 	priv->type1_msg = g_strdup (buf + 3);
756 	return TRUE;
757 #else
758 	/* Win32 should be able to use SSPI here. */
759 	return FALSE;
760 #endif
761 }
762 
763 static GByteArray *
sasl_ntlm_challenge_sync(CamelSasl * sasl,GByteArray * token,GCancellable * cancellable,GError ** error)764 sasl_ntlm_challenge_sync (CamelSasl *sasl,
765                           GByteArray *token,
766                           GCancellable *cancellable,
767                           GError **error)
768 {
769 #ifndef G_OS_WIN32
770 	CamelSaslNTLM *ntlm = CAMEL_SASL_NTLM (sasl);
771 	CamelSaslNTLMPrivate *priv = ntlm->priv;
772 #endif
773 	CamelNetworkSettings *network_settings;
774 	CamelSettings *settings;
775 	CamelService *service;
776 	GByteArray *ret;
777 	guchar nonce[8], hash[21], lm_resp[24], nt_resp[24];
778 	GString *domain = NULL;
779 	const gchar *password;
780 	const gchar *real_user;
781 	const gchar *cp;
782 	gchar *user = NULL;
783 
784 	service = camel_sasl_get_service (sasl);
785 
786 	settings = camel_service_ref_settings (service);
787 	g_return_val_if_fail (CAMEL_IS_NETWORK_SETTINGS (settings), NULL);
788 
789 	network_settings = CAMEL_NETWORK_SETTINGS (settings);
790 	user = camel_network_settings_dup_user (network_settings);
791 
792 	g_object_unref (settings);
793 
794 	g_return_val_if_fail (user != NULL, NULL);
795 
796 	password = camel_service_get_password (service);
797 	/* Assert a non-NULL password below, not here. */
798 
799 	ret = g_byte_array_new ();
800 
801 #ifndef G_OS_WIN32
802 	if (!priv->tried_helper && password == NULL)
803 		sasl_ntlm_try_empty_password_sync (sasl, cancellable, NULL);
804 
805 	if (priv->helper_stream && password == NULL) {
806 		guchar *data;
807 		gsize length = 0;
808 		gchar buf[1024];
809 		gsize s = 0;
810 		buf[0] = 0;
811 
812 		if (!token || !token->len) {
813 			if (priv->type1_msg) {
814 				data = g_base64_decode (priv->type1_msg, &length);
815 				g_byte_array_append (ret, data, length);
816 				g_free (data);
817 				g_free (priv->type1_msg);
818 				priv->type1_msg = NULL;
819 			}
820 			goto exit;
821 		} else {
822 			gchar *type2;
823 			gchar *string;
824 
825 			type2 = g_base64_encode (token->data, token->len);
826 			string = g_strdup_printf ("TT %s\n", type2);
827 			if (camel_stream_write_string (
828 				priv->helper_stream, string, NULL, NULL) >= 0 &&
829 				(s = camel_stream_read (
830 					priv->helper_stream, buf,
831 					sizeof (buf), cancellable, NULL)) > 4 &&
832 				buf[0] == 'K' &&
833 				buf[1] == 'K' &&
834 				buf[2] == ' ' &&
835 				buf[s - 1] == '\n') {
836 				buf[s - 1] = 0;
837 				data = g_base64_decode (buf + 3, &length);
838 				g_byte_array_append (ret, data, length);
839 				g_free (data);
840 			} else
841 				g_warning ("Didn't get valid response from ntlm_auth helper");
842 
843 			g_free (string);
844 			g_free (type2);
845 		}
846 
847 		/* On failure, we just return an empty string. Setting the
848 		 * GError would cause the providers to abort the whole
849 		 * connection, and we want them to ask the user for a password
850 		 * and continue. */
851 		g_object_unref (priv->helper_stream);
852 		priv->helper_stream = NULL;
853 
854 		goto exit;
855 	}
856 #endif
857 
858 	g_return_val_if_fail (password != NULL, NULL);
859 
860 	if (!token || token->len < NTLM_CHALLENGE_NONCE_OFFSET + 8)
861 		goto fail;
862 
863 	/* 0x00080000: Negotiate NTLM2 Key */
864 	if (token->data[NTLM_CHALLENGE_FLAGS_OFFSET + 2] & 8) {
865 		/* NTLM2 session response */
866 		struct {
867 			guint32 srv[2];
868 			guint32 clnt[2];
869 		} sess_nonce;
870 		GChecksum *md5;
871 		guint8 digest[16];
872 		gsize digest_len = sizeof (digest);
873 
874 		sess_nonce.clnt[0] = g_random_int ();
875 		sess_nonce.clnt[1] = g_random_int ();
876 
877 		/* LM response is 8-byte client nonce, NUL-padded to 24 */
878 		memcpy (lm_resp, sess_nonce.clnt, 8);
879 		memset (lm_resp + 8, 0, 16);
880 
881 		/* Session nonce is client nonce + server nonce */
882 		memcpy (
883 			sess_nonce.srv,
884 			token->data + NTLM_CHALLENGE_NONCE_OFFSET, 8);
885 
886 		/* Take MD5 of session nonce */
887 		md5 = g_checksum_new (G_CHECKSUM_MD5);
888 		g_checksum_update (md5, (gpointer) &sess_nonce, 16);
889 		g_checksum_get_digest (md5, (gpointer) &digest, &digest_len);
890 		g_checksum_get_digest (md5, digest, &digest_len);
891 
892 		g_checksum_free (md5);
893 		ntlm_nt_hash (password, (gchar *) hash);
894 
895 		ntlm_calc_response (hash, digest, nt_resp);
896 	} else {
897 		/* NTLM1 */
898 		memcpy (nonce, token->data + NTLM_CHALLENGE_NONCE_OFFSET, 8);
899 		ntlm_lanmanager_hash (password, (gchar *) hash);
900 		ntlm_calc_response (hash, nonce, lm_resp);
901 		ntlm_nt_hash (password, (gchar *) hash);
902 		ntlm_calc_response (hash, nonce, nt_resp);
903 	}
904 
905 	/* If a domain is supplied as part of the username, use it */
906 	cp = strchr (user, '\\');
907 	if (cp != NULL) {
908 		domain = g_string_new_len (user, cp - user);
909 		real_user = cp + 1;
910 	} else
911 		real_user = user;
912 
913 	/* Otherwise, fall back to the domain of the server, if possible */
914 	if (domain == NULL)
915 		domain = ntlm_get_string (token, NTLM_CHALLENGE_DOMAIN_OFFSET);
916 	if (domain == NULL)
917 		goto fail;
918 
919 	/* Don't jump to 'fail' label after this point. */
920 	g_byte_array_set_size (ret, NTLM_RESPONSE_BASE_SIZE);
921 	memset (ret->data, 0, NTLM_RESPONSE_BASE_SIZE);
922 	memcpy (
923 		ret->data, NTLM_RESPONSE_HEADER,
924 		sizeof (NTLM_RESPONSE_HEADER) - 1);
925 	memcpy (
926 		ret->data + NTLM_RESPONSE_FLAGS_OFFSET,
927 		NTLM_RESPONSE_FLAGS, sizeof (NTLM_RESPONSE_FLAGS) - 1);
928 	/* Mask in the NTLM2SESSION flag */
929 	ret->data[NTLM_RESPONSE_FLAGS_OFFSET + 2] |=
930 		token->data[NTLM_CHALLENGE_FLAGS_OFFSET + 2] & 8;
931 
932 	ntlm_set_string (
933 		ret, NTLM_RESPONSE_DOMAIN_OFFSET,
934 		domain->str, domain->len);
935 	ntlm_set_string (
936 		ret, NTLM_RESPONSE_USER_OFFSET,
937 		real_user, strlen (real_user));
938 	ntlm_set_string (
939 		ret, NTLM_RESPONSE_HOST_OFFSET,
940 		"UNKNOWN", sizeof ("UNKNOWN") - 1);
941 	ntlm_set_string (
942 		ret, NTLM_RESPONSE_LM_RESP_OFFSET,
943 		(const gchar *) lm_resp, sizeof (lm_resp));
944 	ntlm_set_string (
945 		ret, NTLM_RESPONSE_NT_RESP_OFFSET,
946 		(const gchar *) nt_resp, sizeof (nt_resp));
947 
948 	camel_sasl_set_authenticated (sasl, TRUE);
949 
950 	g_string_free (domain, TRUE);
951 
952 	goto exit;
953 
954 fail:
955 	/* If the challenge is malformed, restart authentication.
956 	 * XXX A malicious server could make this loop indefinitely. */
957 	g_byte_array_append (
958 		ret, (guint8 *) NTLM_REQUEST,
959 		sizeof (NTLM_REQUEST) - 1);
960 
961 exit:
962 	g_free (user);
963 
964 	return ret;
965 }
966 
967 static void
sasl_ntlm_finalize(GObject * object)968 sasl_ntlm_finalize (GObject *object)
969 {
970 #ifndef G_OS_WIN32
971 	CamelSaslNTLM *ntlm = CAMEL_SASL_NTLM (object);
972 	CamelSaslNTLMPrivate *priv = ntlm->priv;
973 
974 	g_free (priv->type1_msg);
975 	if (priv->helper_stream)
976 		g_object_unref (priv->helper_stream);
977 #endif
978 	/* Chain up to parent's finalize() method. */
979 	G_OBJECT_CLASS (camel_sasl_ntlm_parent_class)->finalize (object);
980 }
981 
982 static void
camel_sasl_ntlm_class_init(CamelSaslNTLMClass * class)983 camel_sasl_ntlm_class_init (CamelSaslNTLMClass *class)
984 {
985 	GObjectClass *object_class;
986 	CamelSaslClass *sasl_class;
987 
988 	object_class = G_OBJECT_CLASS (class);
989 	object_class->finalize = sasl_ntlm_finalize;
990 
991 	sasl_class = CAMEL_SASL_CLASS (class);
992 	sasl_class->auth_type = &sasl_ntlm_auth_type;
993 	sasl_class->challenge_sync = sasl_ntlm_challenge_sync;
994 	sasl_class->try_empty_password_sync = sasl_ntlm_try_empty_password_sync;
995 }
996 
997 static void
camel_sasl_ntlm_init(CamelSaslNTLM * sasl)998 camel_sasl_ntlm_init (CamelSaslNTLM *sasl)
999 {
1000 	sasl->priv = camel_sasl_ntlm_get_instance_private (sasl);
1001 }
1002