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