nit: document that `fout` must be open for reading too
[exim.git] / src / src / auths / auth-spa.c
1 /*************************************************
2 *     Exim - an Internet mail transport agent    *
3 *************************************************/
4
5 /*
6  * This file provides the necessary methods for authenticating with
7  * Microsoft's Secure Password Authentication.
8
9  * All the original code used here was torn by Marc Prud'hommeaux out of the
10  * Samba project (by Andrew Tridgell, Jeremy Allison, and others).
11
12  * Tom Kistner provided additional code, adding spa_build_auth_challenge() to
13  * support server authentication mode.
14
15  * Mark Lyda provided a patch to solve this problem:
16
17  - Exim is indicating in its Authentication Request message (Type 1) that it
18    can transmit text in either Unicode or OEM format.
19
20  - Microsoft's SMTP server (smtp.email.msn.com) is responding in its
21    Challenge message (Type 2) that it will be expecting the OEM format.
22
23  - Exim does not pay attention to the text format requested by Microsoft's
24    SMTP server and, instead, defaults to using the Unicode format.
25
26  * References:
27  * http://www.innovation.ch/java/ntlm.html
28  * http://www.kuro5hin.org/story/2002/4/28/1436/66154
29
30  * It seems that some systems have existing but different definitions of some
31  * of the following types. I received a complaint about "int16" causing
32  * compilation problems. So I (PH) have renamed them all, to be on the safe
33  * side, by adding 'x' on the end.
34
35  * typedef signed short int16;
36  * typedef unsigned short uint16;
37  * typedef unsigned uint32;
38  * typedef unsigned char  uint8;
39
40  * The API is extremely simple:
41  * 1. Form a SPA authentication request based on the username
42  *    and (optional) domain
43  * 2. Send the request to the server and get an SPA challenge
44  * 3. Build the challenge response and send it back.
45  *
46  * Example usage is as
47  * follows:
48  *
49 int main (int argc, char ** argv)
50 {
51        SPAAuthRequest   request;
52        SPAAuthChallenge challenge;
53        SPAAuthResponse  response;
54        char msgbuf[2048];
55        char buffer[512];
56        char *username, *password, *domain, *challenge_str;
57
58        if (argc < 3)
59        {
60                printf ("Usage: %s <username> <password> [SPA Challenge]\n",
61                        argv [0]);
62                exit (1);
63        }
64
65        username = argv [1];
66        password = argv [2];
67        domain = 0;
68
69        spa_build_auth_request (&request, username, domain);
70
71        spa_bits_to_base64 (msgbuf, US &request,
72                spa_request_length(&request));
73
74        printf ("SPA Login request for username=%s:\n   %s\n",
75                argv [1], msgbuf);
76
77        if (argc < 4)
78        {
79                printf ("Run: %s <username> <password> [NTLM Challenge] " \
80                        "to complete authenitcation\n", argv [0]);
81                exit (0);
82        }
83
84        challenge_str = argv [3];
85
86        if (spa_base64_to_bits ((char *)&challenge, sizeof(challenge),
87                 (const char *)(challenge_str))<0)
88        {
89                 printf("bad base64 data in challenge: %s\n", challenge_str);
90                 exit (1);
91        }
92
93        spa_build_auth_response (&challenge, &response, username, password);
94        spa_bits_to_base64 (msgbuf, US &response,
95                spa_request_length(&response));
96
97        printf ("SPA Response to challenge:\n   %s\n for " \
98                "username=%s, password=%s:\n   %s\n",
99                argv[3], argv [1], argv [2], msgbuf);
100        return 0;
101 }
102  *
103  *
104  * All the client code used here was torn by Marc Prud'hommeaux out of the
105  * Samba project (by Andrew Tridgell, Jeremy Allison, and others).
106  * Previous comments are below:
107  */
108
109 /*
110    Unix SMB/Netbios implementation.
111    Version 1.9.
112
113    a partial implementation of DES designed for use in the
114    SMB authentication protocol
115
116    Copyright (C) Andrew Tridgell 1998
117
118    This program is free software; you can redistribute it and/or modify
119    it under the terms of the GNU General Public License as published by
120    the Free Software Foundation; either version 2 of the License, or
121    (at your option) any later version.
122
123    This program is distributed in the hope that it will be useful,
124    but WITHOUT ANY WARRANTY; without even the implied warranty of
125    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
126    GNU General Public License for more details.
127
128    You should have received a copy of the GNU General Public License
129    along with this program; if not, write to the Free Software
130    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
131 */
132
133
134 /* NOTES:
135
136    This code makes no attempt to be fast! In fact, it is a very
137    slow implementation
138
139    This code is NOT a complete DES implementation. It implements only
140    the minimum necessary for SMB authentication, as used by all SMB
141    products (including every copy of Microsoft Windows95 ever sold)
142
143    In particular, it can only do a unchained forward DES pass. This
144    means it is not possible to use this code for encryption/decryption
145    of data, instead it is only useful as a "hash" algorithm.
146
147    There is no entry point into this code that allows normal DES operation.
148
149    I believe this means that this code does not come under ITAR
150    regulations but this is NOT a legal opinion. If you are concerned
151    about the applicability of ITAR regulations to this code then you
152    should confirm it for yourself (and maybe let me know if you come
153    up with a different answer to the one above)
154 */
155
156 #define DEBUG_X(a,b) ;
157
158 extern int DEBUGLEVEL;
159
160 #include "../exim.h"
161 #include "auth-spa.h"
162 #include <assert.h>
163
164
165 #ifndef _BYTEORDER_H
166 # define _BYTEORDER_H
167
168 # define RW_PCVAL(read,inbuf,outbuf,len) \
169        { if (read) { PCVAL (inbuf,0,outbuf,len); } \
170        else      { PSCVAL(inbuf,0,outbuf,len); } }
171
172 # define RW_PIVAL(read,big_endian,inbuf,outbuf,len) \
173        { if (read) { if (big_endian) { RPIVAL(inbuf,0,outbuf,len); } else { PIVAL(inbuf,0,outbuf,len); } } \
174        else      { if (big_endian) { RPSIVAL(inbuf,0,outbuf,len); } else { PSIVAL(inbuf,0,outbuf,len); } } }
175
176 # define RW_PSVAL(read,big_endian,inbuf,outbuf,len) \
177        { if (read) { if (big_endian) { RPSVAL(inbuf,0,outbuf,len); } else { PSVAL(inbuf,0,outbuf,len); } } \
178        else      { if (big_endian) { RPSSVAL(inbuf,0,outbuf,len); } else { PSSVAL(inbuf,0,outbuf,len); } } }
179
180 # define RW_CVAL(read, inbuf, outbuf, offset) \
181        { if (read) { (outbuf) = CVAL (inbuf,offset); } \
182        else      { SCVAL(inbuf,offset,outbuf); } }
183
184 # define RW_IVAL(read, big_endian, inbuf, outbuf, offset) \
185        { if (read) { (outbuf) = ((big_endian) ? RIVAL(inbuf,offset) : IVAL (inbuf,offset)); } \
186        else      { if (big_endian) { RSIVAL(inbuf,offset,outbuf); } else { SIVAL(inbuf,offset,outbuf); } } }
187
188 # define RW_SVAL(read, big_endian, inbuf, outbuf, offset) \
189        { if (read) { (outbuf) = ((big_endian) ? RSVAL(inbuf,offset) : SVAL (inbuf,offset)); } \
190        else      { if (big_endian) { RSSVAL(inbuf,offset,outbuf); } else { SSVAL(inbuf,offset,outbuf); } } }
191
192 # undef CAREFUL_ALIGNMENT
193
194 /* we know that the 386 can handle misalignment and has the "right"
195    byteorder */
196 # ifdef __i386__
197 #  define CAREFUL_ALIGNMENT 0
198 # endif
199
200 # ifndef CAREFUL_ALIGNMENT
201 #  define CAREFUL_ALIGNMENT 1
202 # endif
203
204 # define CVAL(buf,pos) ((US (buf))[pos])
205 # define PVAL(buf,pos) ((unsigned)CVAL(buf,pos))
206 # define SCVAL(buf,pos,val) (CVAL(buf,pos) = (val))
207
208
209 # if CAREFUL_ALIGNMENT
210
211 #  define SVAL(buf,pos) (PVAL(buf,pos)|PVAL(buf,(pos)+1)<<8)
212 #  define IVAL(buf,pos) (SVAL(buf,pos)|SVAL(buf,(pos)+2)<<16)
213 #  define SSVALX(buf,pos,val) (CVAL(buf,pos)=(val)&0xFF,CVAL(buf,pos+1)=(val)>>8)
214 #  define SIVALX(buf,pos,val) (SSVALX(buf,pos,val&0xFFFF),SSVALX(buf,pos+2,val>>16))
215 #  define SVALS(buf,pos) ((int16x)SVAL(buf,pos))
216 #  define IVALS(buf,pos) ((int32x)IVAL(buf,pos))
217 #  define SSVAL(buf,pos,val) SSVALX((buf),(pos),((uint16x)(val)))
218 #  define SIVAL(buf,pos,val) SIVALX((buf),(pos),((uint32x)(val)))
219 #  define SSVALS(buf,pos,val) SSVALX((buf),(pos),((int16x)(val)))
220 #  define SIVALS(buf,pos,val) SIVALX((buf),(pos),((int32x)(val)))
221
222 # else /* CAREFUL_ALIGNMENT */
223
224 /* this handles things for architectures like the 386 that can handle
225    alignment errors */
226 /*
227    WARNING: This section is dependent on the length of int16x and int32x
228    being correct
229 */
230
231 /* get single value from an SMB buffer */
232 #  define SVAL(buf,pos) (*(uint16x *)((char *)(buf) + (pos)))
233 #  define IVAL(buf,pos) (*(uint32x *)((char *)(buf) + (pos)))
234 #  define SVALS(buf,pos) (*(int16x *)((char *)(buf) + (pos)))
235 #  define IVALS(buf,pos) (*(int32x *)((char *)(buf) + (pos)))
236
237 /* store single value in an SMB buffer */
238 #  define SSVAL(buf,pos,val) SVAL(buf,pos)=((uint16x)(val))
239 #  define SIVAL(buf,pos,val) IVAL(buf,pos)=((uint32x)(val))
240 #  define SSVALS(buf,pos,val) SVALS(buf,pos)=((int16x)(val))
241 #  define SIVALS(buf,pos,val) IVALS(buf,pos)=((int32x)(val))
242
243 # endif /* CAREFUL_ALIGNMENT */
244
245 /* macros for reading / writing arrays */
246
247 # define SMBMACRO(macro,buf,pos,val,len,size) \
248 { int l; for (l = 0; l < (len); l++) (val)[l] = macro((buf), (pos) + (size)*l); }
249
250 # define SSMBMACRO(macro,buf,pos,val,len,size) \
251 { int l; for (l = 0; l < (len); l++) macro((buf), (pos) + (size)*l, (val)[l]); }
252
253 /* reads multiple data from an SMB buffer */
254 # define PCVAL(buf,pos,val,len) SMBMACRO(CVAL,buf,pos,val,len,1)
255 # define PSVAL(buf,pos,val,len) SMBMACRO(SVAL,buf,pos,val,len,2)
256 # define PIVAL(buf,pos,val,len) SMBMACRO(IVAL,buf,pos,val,len,4)
257 # define PCVALS(buf,pos,val,len) SMBMACRO(CVALS,buf,pos,val,len,1)
258 # define PSVALS(buf,pos,val,len) SMBMACRO(SVALS,buf,pos,val,len,2)
259 # define PIVALS(buf,pos,val,len) SMBMACRO(IVALS,buf,pos,val,len,4)
260
261 /* stores multiple data in an SMB buffer */
262 # define PSCVAL(buf,pos,val,len) SSMBMACRO(SCVAL,buf,pos,val,len,1)
263 # define PSSVAL(buf,pos,val,len) SSMBMACRO(SSVAL,buf,pos,val,len,2)
264 # define PSIVAL(buf,pos,val,len) SSMBMACRO(SIVAL,buf,pos,val,len,4)
265 # define PSCVALS(buf,pos,val,len) SSMBMACRO(SCVALS,buf,pos,val,len,1)
266 # define PSSVALS(buf,pos,val,len) SSMBMACRO(SSVALS,buf,pos,val,len,2)
267 # define PSIVALS(buf,pos,val,len) SSMBMACRO(SIVALS,buf,pos,val,len,4)
268
269
270 /* now the reverse routines - these are used in nmb packets (mostly) */
271 # define SREV(x) ((((x)&0xFF)<<8) | (((x)>>8)&0xFF))
272 # define IREV(x) ((SREV(x)<<16) | (SREV((x)>>16)))
273
274 # define RSVAL(buf,pos) SREV(SVAL(buf,pos))
275 # define RSVALS(buf,pos) SREV(SVALS(buf,pos))
276 # define RIVAL(buf,pos) IREV(IVAL(buf,pos))
277 # define RIVALS(buf,pos) IREV(IVALS(buf,pos))
278 # define RSSVAL(buf,pos,val) SSVAL(buf,pos,SREV(val))
279 # define RSSVALS(buf,pos,val) SSVALS(buf,pos,SREV(val))
280 # define RSIVAL(buf,pos,val) SIVAL(buf,pos,IREV(val))
281 # define RSIVALS(buf,pos,val) SIVALS(buf,pos,IREV(val))
282
283 /* reads multiple data from an SMB buffer (big-endian) */
284 # define RPSVAL(buf,pos,val,len) SMBMACRO(RSVAL,buf,pos,val,len,2)
285 # define RPIVAL(buf,pos,val,len) SMBMACRO(RIVAL,buf,pos,val,len,4)
286 # define RPSVALS(buf,pos,val,len) SMBMACRO(RSVALS,buf,pos,val,len,2)
287 # define RPIVALS(buf,pos,val,len) SMBMACRO(RIVALS,buf,pos,val,len,4)
288
289 /* stores multiple data in an SMB buffer (big-endian) */
290 # define RPSSVAL(buf,pos,val,len) SSMBMACRO(RSSVAL,buf,pos,val,len,2)
291 # define RPSIVAL(buf,pos,val,len) SSMBMACRO(RSIVAL,buf,pos,val,len,4)
292 # define RPSSVALS(buf,pos,val,len) SSMBMACRO(RSSVALS,buf,pos,val,len,2)
293 # define RPSIVALS(buf,pos,val,len) SSMBMACRO(RSIVALS,buf,pos,val,len,4)
294
295 # define DBG_RW_PCVAL(charmode,string,depth,base,read,inbuf,outbuf,len) \
296        { RW_PCVAL(read,inbuf,outbuf,len) \
297        DEBUG_X(5,("%s%04x %s: ", \
298              tab_depth(depth), base,string)); \
299     if (charmode) print_asc(5, US (outbuf), (len)); else \
300        { int idx; for (idx = 0; idx < len; idx++) { DEBUG_X(5,("%02x ", (outbuf)[idx])); } } \
301        DEBUG_X(5,("\n")); }
302
303 # define DBG_RW_PSVAL(charmode,string,depth,base,read,big_endian,inbuf,outbuf,len) \
304        { RW_PSVAL(read,big_endian,inbuf,outbuf,len) \
305        DEBUG_X(5,("%s%04x %s: ", \
306              tab_depth(depth), base,string)); \
307     if (charmode) print_asc(5, US (outbuf), 2*(len)); else \
308        { int idx; for (idx = 0; idx < len; idx++) { DEBUG_X(5,("%04x ", (outbuf)[idx])); } } \
309        DEBUG_X(5,("\n")); }
310
311 # define DBG_RW_PIVAL(charmode,string,depth,base,read,big_endian,inbuf,outbuf,len) \
312        { RW_PIVAL(read,big_endian,inbuf,outbuf,len) \
313        DEBUG_X(5,("%s%04x %s: ", \
314              tab_depth(depth), base,string)); \
315     if (charmode) print_asc(5, US (outbuf), 4*(len)); else \
316        { int idx; for (idx = 0; idx < len; idx++) { DEBUG_X(5,("%08x ", (outbuf)[idx])); } } \
317        DEBUG_X(5,("\n")); }
318
319 # define DBG_RW_CVAL(string,depth,base,read,inbuf,outbuf) \
320        { RW_CVAL(read,inbuf,outbuf,0) \
321        DEBUG_X(5,("%s%04x %s: %02x\n", \
322              tab_depth(depth), base, string, outbuf)); }
323
324 # define DBG_RW_SVAL(string,depth,base,read,big_endian,inbuf,outbuf) \
325        { RW_SVAL(read,big_endian,inbuf,outbuf,0) \
326        DEBUG_X(5,("%s%04x %s: %04x\n", \
327              tab_depth(depth), base, string, outbuf)); }
328
329 # define DBG_RW_IVAL(string,depth,base,read,big_endian,inbuf,outbuf) \
330        { RW_IVAL(read,big_endian,inbuf,outbuf,0) \
331        DEBUG_X(5,("%s%04x %s: %08x\n", \
332              tab_depth(depth), base, string, outbuf)); }
333
334 #endif /* _BYTEORDER_H */
335
336 void E_P16 (uschar *p14, uschar *p16);
337 void E_P24 (uschar *p21, uschar *c8, uschar *p24);
338 void D_P16 (uschar *p14, uschar *in, uschar *out);
339 void SMBOWFencrypt (uschar passwd[16], uschar * c8, uschar p24[24]);
340
341 void mdfour (uschar *out, uschar *in, int n);
342
343
344 /*
345  * base64.c -- base-64 conversion routines.
346  *
347  * For license terms, see the file COPYING in this directory.
348  *
349  * This base 64 encoding is defined in RFC2045 section 6.8,
350  * "Base64 Content-Transfer-Encoding", but lines must not be broken in the
351  * scheme used here.
352  */
353
354 static const char base64digits[] =
355   "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
356
357 #define BAD    (char) -1
358 static const char base64val[] = {
359   BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD,
360     BAD,
361   BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD,
362     BAD,
363   BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, 62, BAD, BAD, BAD,
364     63,
365   52, 53, 54, 55, 56, 57, 58, 59, 60, 61, BAD, BAD, BAD, BAD, BAD, BAD,
366   BAD, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
367   15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, BAD, BAD, BAD, BAD, BAD,
368   BAD, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
369   41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, BAD, BAD, BAD, BAD, BAD
370 };
371 #define DECODE64(c)  (isascii(c) ? base64val[c] : BAD)
372
373 void
374 spa_bits_to_base64 (uschar *out, const uschar *in, int inlen)
375 /* raw bytes in quasi-big-endian order to base 64 string (NUL-terminated) */
376 {
377   for (; inlen >= 3; inlen -= 3)
378     {
379       *out++ = base64digits[in[0] >> 2];
380       *out++ = base64digits[((in[0] << 4) & 0x30) | (in[1] >> 4)];
381       *out++ = base64digits[((in[1] << 2) & 0x3c) | (in[2] >> 6)];
382       *out++ = base64digits[in[2] & 0x3f];
383       in += 3;
384     }
385   if (inlen > 0)
386     {
387       uschar fragment;
388
389       *out++ = base64digits[in[0] >> 2];
390       fragment = (in[0] << 4) & 0x30;
391       if (inlen > 1)
392        fragment |= in[1] >> 4;
393       *out++ = base64digits[fragment];
394       *out++ = (inlen < 2) ? '=' : base64digits[(in[1] << 2) & 0x3c];
395       *out++ = '=';
396     }
397   *out = '\0';
398 }
399
400
401 /* The outlength parameter was added by PH, December 2004 */
402
403 int
404 spa_base64_to_bits (char *out, int outlength, const char *in)
405 /* base 64 to raw bytes in quasi-big-endian order, returning count of bytes */
406 {
407   int len = 0;
408   register uschar digit1, digit2, digit3, digit4;
409
410   if (in[0] == '+' && in[1] == ' ')
411     in += 2;
412   if (*in == '\r')
413     return (0);
414
415   do
416     {
417       if (len >= outlength)                   /* Added by PH */
418         return (-1);                          /* Added by PH */
419       digit1 = in[0];
420       if (DECODE64 (digit1) == BAD)
421        return (-1);
422       digit2 = in[1];
423       if (DECODE64 (digit2) == BAD)
424        return (-1);
425       digit3 = in[2];
426       if (digit3 != '=' && DECODE64 (digit3) == BAD)
427        return (-1);
428       digit4 = in[3];
429       if (digit4 != '=' && DECODE64 (digit4) == BAD)
430        return (-1);
431       in += 4;
432       *out++ = (DECODE64 (digit1) << 2) | (DECODE64 (digit2) >> 4);
433       ++len;
434       if (digit3 != '=')
435        {
436          if (len >= outlength)                   /* Added by PH */
437            return (-1);                          /* Added by PH */
438          *out++ =
439            ((DECODE64 (digit2) << 4) & 0xf0) | (DECODE64 (digit3) >> 2);
440          ++len;
441          if (digit4 != '=')
442            {
443              if (len >= outlength)                   /* Added by PH */
444                return (-1);                          /* Added by PH */
445              *out++ = ((DECODE64 (digit3) << 6) & 0xc0) | DECODE64 (digit4);
446              ++len;
447            }
448        }
449     }
450   while (*in && *in != '\r' && digit4 != '=');
451
452   return (len);
453 }
454
455
456 static uschar perm1[56] = { 57, 49, 41, 33, 25, 17, 9,
457   1, 58, 50, 42, 34, 26, 18,
458   10, 2, 59, 51, 43, 35, 27,
459   19, 11, 3, 60, 52, 44, 36,
460   63, 55, 47, 39, 31, 23, 15,
461   7, 62, 54, 46, 38, 30, 22,
462   14, 6, 61, 53, 45, 37, 29,
463   21, 13, 5, 28, 20, 12, 4
464 };
465
466 static uschar perm2[48] = { 14, 17, 11, 24, 1, 5,
467   3, 28, 15, 6, 21, 10,
468   23, 19, 12, 4, 26, 8,
469   16, 7, 27, 20, 13, 2,
470   41, 52, 31, 37, 47, 55,
471   30, 40, 51, 45, 33, 48,
472   44, 49, 39, 56, 34, 53,
473   46, 42, 50, 36, 29, 32
474 };
475
476 static uschar perm3[64] = { 58, 50, 42, 34, 26, 18, 10, 2,
477   60, 52, 44, 36, 28, 20, 12, 4,
478   62, 54, 46, 38, 30, 22, 14, 6,
479   64, 56, 48, 40, 32, 24, 16, 8,
480   57, 49, 41, 33, 25, 17, 9, 1,
481   59, 51, 43, 35, 27, 19, 11, 3,
482   61, 53, 45, 37, 29, 21, 13, 5,
483   63, 55, 47, 39, 31, 23, 15, 7
484 };
485
486 static uschar perm4[48] = { 32, 1, 2, 3, 4, 5,
487   4, 5, 6, 7, 8, 9,
488   8, 9, 10, 11, 12, 13,
489   12, 13, 14, 15, 16, 17,
490   16, 17, 18, 19, 20, 21,
491   20, 21, 22, 23, 24, 25,
492   24, 25, 26, 27, 28, 29,
493   28, 29, 30, 31, 32, 1
494 };
495
496 static uschar perm5[32] = { 16, 7, 20, 21,
497   29, 12, 28, 17,
498   1, 15, 23, 26,
499   5, 18, 31, 10,
500   2, 8, 24, 14,
501   32, 27, 3, 9,
502   19, 13, 30, 6,
503   22, 11, 4, 25
504 };
505
506
507 static uschar perm6[64] = { 40, 8, 48, 16, 56, 24, 64, 32,
508   39, 7, 47, 15, 55, 23, 63, 31,
509   38, 6, 46, 14, 54, 22, 62, 30,
510   37, 5, 45, 13, 53, 21, 61, 29,
511   36, 4, 44, 12, 52, 20, 60, 28,
512   35, 3, 43, 11, 51, 19, 59, 27,
513   34, 2, 42, 10, 50, 18, 58, 26,
514   33, 1, 41, 9, 49, 17, 57, 25
515 };
516
517
518 static uschar sc[16] = { 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 };
519
520 static uschar sbox[8][4][16] = {
521   {{14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7},
522    {0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8},
523    {4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0},
524    {15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13}},
525
526   {{15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10},
527    {3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5},
528    {0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15},
529    {13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9}},
530
531   {{10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8},
532    {13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1},
533    {13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7},
534    {1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12}},
535
536   {{7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15},
537    {13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9},
538    {10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4},
539    {3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14}},
540
541   {{2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9},
542    {14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6},
543    {4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14},
544    {11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3}},
545
546   {{12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11},
547    {10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8},
548    {9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6},
549    {4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13}},
550
551   {{4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1},
552    {13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6},
553    {1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2},
554    {6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12}},
555
556   {{13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7},
557    {1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2},
558    {7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8},
559    {2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11}}
560 };
561
562 static void
563 permute (char *out, char *in, uschar * p, int n)
564 {
565   int i;
566   for (i = 0; i < n; i++)
567     out[i] = in[p[i] - 1];
568 }
569
570 static void
571 lshift (char *d, int count, int n)
572 {
573   char out[64];
574   int i;
575   for (i = 0; i < n; i++)
576     out[i] = d[(i + count) % n];
577   for (i = 0; i < n; i++)
578     d[i] = out[i];
579 }
580
581 static void
582 concat (char *out, char *in1, char *in2, int l1, int l2)
583 {
584   while (l1--)
585     *out++ = *in1++;
586   while (l2--)
587     *out++ = *in2++;
588 }
589
590 static void
591 xor (char *out, char *in1, char *in2, int n)
592 {
593   int i;
594   for (i = 0; i < n; i++)
595     out[i] = in1[i] ^ in2[i];
596 }
597
598 static void
599 dohash (char *out, char *in, char *key, int forw)
600 {
601   int i, j, k;
602   char pk1[56];
603   char c[28];
604   char d[28];
605   char cd[56];
606   char ki[16][48];
607   char pd1[64];
608   char l[32], r[32];
609   char rl[64];
610
611   permute (pk1, key, perm1, 56);
612
613   for (i = 0; i < 28; i++)
614     c[i] = pk1[i];
615   for (i = 0; i < 28; i++)
616     d[i] = pk1[i + 28];
617
618   for (i = 0; i < 16; i++)
619     {
620       lshift (c, sc[i], 28);
621       lshift (d, sc[i], 28);
622
623       concat (cd, c, d, 28, 28);
624       permute (ki[i], cd, perm2, 48);
625     }
626
627   permute (pd1, in, perm3, 64);
628
629   for (j = 0; j < 32; j++)
630     {
631       l[j] = pd1[j];
632       r[j] = pd1[j + 32];
633     }
634
635   for (i = 0; i < 16; i++)
636     {
637       char er[48];
638       char erk[48];
639       char b[8][6];
640       char cb[32];
641       char pcb[32];
642       char r2[32];
643
644       permute (er, r, perm4, 48);
645
646       xor (erk, er, ki[forw ? i : 15 - i], 48);
647
648       for (j = 0; j < 8; j++)
649        for (k = 0; k < 6; k++)
650          b[j][k] = erk[j * 6 + k];
651
652       for (j = 0; j < 8; j++)
653        {
654          int m, n;
655          m = (b[j][0] << 1) | b[j][5];
656
657          n = (b[j][1] << 3) | (b[j][2] << 2) | (b[j][3] << 1) | b[j][4];
658
659          for (k = 0; k < 4; k++)
660            b[j][k] = (sbox[j][m][n] & (1 << (3 - k))) ? 1 : 0;
661        }
662
663       for (j = 0; j < 8; j++)
664        for (k = 0; k < 4; k++)
665          cb[j * 4 + k] = b[j][k];
666       permute (pcb, cb, perm5, 32);
667
668       xor (r2, l, pcb, 32);
669
670       for (j = 0; j < 32; j++)
671        l[j] = r[j];
672
673       for (j = 0; j < 32; j++)
674        r[j] = r2[j];
675     }
676
677   concat (rl, r, l, 32, 32);
678
679   permute (out, rl, perm6, 64);
680 }
681
682 static void
683 str_to_key (uschar *str, uschar *key)
684 {
685   int i;
686
687   key[0] = str[0] >> 1;
688   key[1] = ((str[0] & 0x01) << 6) | (str[1] >> 2);
689   key[2] = ((str[1] & 0x03) << 5) | (str[2] >> 3);
690   key[3] = ((str[2] & 0x07) << 4) | (str[3] >> 4);
691   key[4] = ((str[3] & 0x0F) << 3) | (str[4] >> 5);
692   key[5] = ((str[4] & 0x1F) << 2) | (str[5] >> 6);
693   key[6] = ((str[5] & 0x3F) << 1) | (str[6] >> 7);
694   key[7] = str[6] & 0x7F;
695   for (i = 0; i < 8; i++)
696     {
697       key[i] = (key[i] << 1);
698     }
699 }
700
701
702 static void
703 smbhash (uschar *out, uschar *in, uschar *key, int forw)
704 {
705   int i;
706   char outb[64];
707   char inb[64];
708   char keyb[64];
709   uschar key2[8];
710
711   str_to_key (key, key2);
712
713   for (i = 0; i < 64; i++)
714     {
715       inb[i] = (in[i / 8] & (1 << (7 - (i % 8)))) ? 1 : 0;
716       keyb[i] = (key2[i / 8] & (1 << (7 - (i % 8)))) ? 1 : 0;
717       outb[i] = 0;
718     }
719
720   dohash (outb, inb, keyb, forw);
721
722   for (i = 0; i < 8; i++)
723     {
724       out[i] = 0;
725     }
726
727   for (i = 0; i < 64; i++)
728     {
729       if (outb[i])
730        out[i / 8] |= (1 << (7 - (i % 8)));
731     }
732 }
733
734 void
735 E_P16 (uschar *p14, uschar *p16)
736 {
737   uschar sp8[8] = { 0x4b, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 };
738   smbhash (p16, sp8, p14, 1);
739   smbhash (p16 + 8, sp8, p14 + 7, 1);
740 }
741
742 void
743 E_P24 (uschar *p21, uschar *c8, uschar *p24)
744 {
745   smbhash (p24, c8, p21, 1);
746   smbhash (p24 + 8, c8, p21 + 7, 1);
747   smbhash (p24 + 16, c8, p21 + 14, 1);
748 }
749
750 void
751 D_P16 (uschar *p14, uschar *in, uschar *out)
752 {
753   smbhash (out, in, p14, 0);
754   smbhash (out + 8, in + 8, p14 + 7, 0);
755 }
756
757 /****************************************************************************
758  Like strncpy but always null terminates. Make sure there is room!
759  The variable n should always be one less than the available size.
760 ****************************************************************************/
761
762 char *
763 StrnCpy (char *dest, const char *src, size_t n)
764 {
765   char *d = dest;
766   if (!dest)
767     return (NULL);
768   if (!src)
769     {
770       *dest = 0;
771       return (dest);
772     }
773   while (n-- && (*d++ = *src++));
774   *d = 0;
775   return (dest);
776 }
777
778 size_t
779 skip_multibyte_char (char c)
780 {
781   /* bogus if to get rid of unused compiler warning */
782   if (c)
783     return 0;
784   else
785     return 0;
786 }
787
788
789 /*******************************************************************
790 safe string copy into a known length string. maxlength does not
791 include the terminating zero.
792 ********************************************************************/
793
794 char *
795 safe_strcpy (char *dest, const char *src, size_t maxlength)
796 {
797   size_t len;
798
799   if (!dest)
800     {
801       DEBUG_X (0, ("ERROR: NULL dest in safe_strcpy\n"));
802       return NULL;
803     }
804
805   if (!src)
806     {
807       *dest = 0;
808       return dest;
809     }
810
811   len = strlen (src);
812
813   if (len > maxlength)
814     {
815       DEBUG_X (0, ("ERROR: string overflow by %d in safe_strcpy [%.50s]\n",
816                 (int) (len - maxlength), src));
817       len = maxlength;
818     }
819
820   memcpy (dest, src, len);
821   dest[len] = 0;
822   return dest;
823 }
824
825
826 void
827 strupper (char *s)
828 {
829   while (*s)
830     {
831       {
832        size_t skip = skip_multibyte_char (*s);
833        if (skip != 0)
834          s += skip;
835        else
836          {
837            if (islower ((uschar)(*s)))
838              *s = toupper (*s);
839            s++;
840          }
841       }
842     }
843 }
844
845
846 /*
847  This implements the X/Open SMB password encryption
848  It takes a password, a 8 byte "crypt key" and puts 24 bytes of
849  encrypted password into p24
850  */
851
852 void
853 spa_smb_encrypt (uschar * passwd, uschar * c8, uschar * p24)
854 {
855   uschar p14[15], p21[21];
856
857   memset (p21, '\0', 21);
858   memset (p14, '\0', 14);
859   StrnCpy ((char *) p14, (char *) passwd, 14);
860
861   strupper ((char *) p14);
862   E_P16 (p14, p21);
863
864   SMBOWFencrypt (p21, c8, p24);
865
866 #ifdef DEBUG_PASSWORD
867   DEBUG_X (100, ("spa_smb_encrypt: lm#, challenge, response\n"));
868   dump_data (100, (char *) p21, 16);
869   dump_data (100, (char *) c8, 8);
870   dump_data (100, (char *) p24, 24);
871 #endif
872 }
873
874 /* Routines for Windows NT MD4 Hash functions. */
875 static int
876 _my_wcslen (int16x * str)
877 {
878   int len = 0;
879   while (*str++ != 0)
880     len++;
881   return len;
882 }
883
884 /*
885  * Convert a string into an NT UNICODE string.
886  * Note that regardless of processor type
887  * this must be in intel (little-endian)
888  * format.
889  */
890
891 static int
892 _my_mbstowcs (int16x * dst, uschar * src, int len)
893 {
894   int i;
895   int16x val;
896
897   for (i = 0; i < len; i++)
898     {
899       val = *src;
900       SSVAL (dst, 0, val);
901       dst++;
902       src++;
903       if (val == 0)
904        break;
905     }
906   return i;
907 }
908
909 /*
910  * Creates the MD4 Hash of the users password in NT UNICODE.
911  */
912
913 void
914 E_md4hash (uschar * passwd, uschar * p16)
915 {
916   int len;
917   int16x wpwd[129];
918
919   /* Password cannot be longer than 128 characters */
920   len = strlen ((char *) passwd);
921   if (len > 128)
922     len = 128;
923   /* Password must be converted to NT unicode */
924   _my_mbstowcs (wpwd, passwd, len);
925   wpwd[len] = 0;               /* Ensure string is null terminated */
926   /* Calculate length in bytes */
927   len = _my_wcslen (wpwd) * sizeof (int16x);
928
929   mdfour (p16, US wpwd, len);
930 }
931
932 /* Does both the NT and LM owfs of a user's password */
933 void
934 nt_lm_owf_gen (char *pwd, uschar nt_p16[16], uschar p16[16])
935 {
936   char passwd[130];
937
938   memset (passwd, '\0', 130);
939   safe_strcpy (passwd, pwd, sizeof (passwd) - 1);
940
941   /* Calculate the MD4 hash (NT compatible) of the password */
942   memset (nt_p16, '\0', 16);
943   E_md4hash (US passwd, nt_p16);
944
945 #ifdef DEBUG_PASSWORD
946   DEBUG_X (100, ("nt_lm_owf_gen: pwd, nt#\n"));
947   dump_data (120, passwd, strlen (passwd));
948   dump_data (100, (char *) nt_p16, 16);
949 #endif
950
951   /* Mangle the passwords into Lanman format */
952   passwd[14] = '\0';
953   strupper (passwd);
954
955   /* Calculate the SMB (lanman) hash functions of the password */
956
957   memset (p16, '\0', 16);
958   E_P16 (US passwd, US p16);
959
960 #ifdef DEBUG_PASSWORD
961   DEBUG_X (100, ("nt_lm_owf_gen: pwd, lm#\n"));
962   dump_data (120, passwd, strlen (passwd));
963   dump_data (100, (char *) p16, 16);
964 #endif
965   /* clear out local copy of user's password (just being paranoid). */
966   memset (passwd, '\0', sizeof (passwd));
967 }
968
969 /* Does the des encryption from the NT or LM MD4 hash. */
970 void
971 SMBOWFencrypt (uschar passwd[16], uschar * c8, uschar p24[24])
972 {
973   uschar p21[21];
974
975   memset (p21, '\0', 21);
976
977   memcpy (p21, passwd, 16);
978   E_P24 (p21, c8, p24);
979 }
980
981 /* Does the des encryption from the FIRST 8 BYTES of the NT or LM MD4 hash. */
982 void
983 NTLMSSPOWFencrypt (uschar passwd[8], uschar * ntlmchalresp, uschar p24[24])
984 {
985   uschar p21[21];
986
987   memset (p21, '\0', 21);
988   memcpy (p21, passwd, 8);
989   memset (p21 + 8, 0xbd, 8);
990
991   E_P24 (p21, ntlmchalresp, p24);
992 #ifdef DEBUG_PASSWORD
993   DEBUG_X (100, ("NTLMSSPOWFencrypt: p21, c8, p24\n"));
994   dump_data (100, (char *) p21, 21);
995   dump_data (100, (char *) ntlmchalresp, 8);
996   dump_data (100, (char *) p24, 24);
997 #endif
998 }
999
1000
1001 /* Does the NT MD4 hash then des encryption. */
1002
1003 void
1004 spa_smb_nt_encrypt (uschar * passwd, uschar * c8, uschar * p24)
1005 {
1006   uschar p21[21];
1007
1008   memset (p21, '\0', 21);
1009
1010   E_md4hash (passwd, p21);
1011   SMBOWFencrypt (p21, c8, p24);
1012
1013 #ifdef DEBUG_PASSWORD
1014   DEBUG_X (100, ("spa_smb_nt_encrypt: nt#, challenge, response\n"));
1015   dump_data (100, (char *) p21, 16);
1016   dump_data (100, (char *) c8, 8);
1017   dump_data (100, (char *) p24, 24);
1018 #endif
1019 }
1020
1021 static uint32x A, B, C, D;
1022
1023 static uint32x
1024 F (uint32x X, uint32x Y, uint32x Z)
1025 {
1026   return (X & Y) | ((~X) & Z);
1027 }
1028
1029 static uint32x
1030 G (uint32x X, uint32x Y, uint32x Z)
1031 {
1032   return (X & Y) | (X & Z) | (Y & Z);
1033 }
1034
1035 static uint32x
1036 H (uint32x X, uint32x Y, uint32x Z)
1037 {
1038   return X ^ Y ^ Z;
1039 }
1040
1041 static uint32x
1042 lshift_a (uint32x x, int s)
1043 {
1044   x &= 0xFFFFFFFF;
1045   return ((x << s) & 0xFFFFFFFF) | (x >> (32 - s));
1046 }
1047
1048 #define ROUND1(a,b,c,d,k,s) a = lshift_a(a + F(b,c,d) + X[k], s)
1049 #define ROUND2(a,b,c,d,k,s) a = lshift_a(a + G(b,c,d) + X[k] + (uint32x)0x5A827999,s)
1050 #define ROUND3(a,b,c,d,k,s) a = lshift_a(a + H(b,c,d) + X[k] + (uint32x)0x6ED9EBA1,s)
1051
1052 /* this applies md4 to 64 byte chunks */
1053 static void
1054 spa_mdfour64 (uint32x * M)
1055 {
1056   int j;
1057   uint32x AA, BB, CC, DD;
1058   uint32x X[16];
1059
1060   for (j = 0; j < 16; j++)
1061     X[j] = M[j];
1062
1063   AA = A;
1064   BB = B;
1065   CC = C;
1066   DD = D;
1067
1068   ROUND1 (A, B, C, D, 0, 3);
1069   ROUND1 (D, A, B, C, 1, 7);
1070   ROUND1 (C, D, A, B, 2, 11);
1071   ROUND1 (B, C, D, A, 3, 19);
1072   ROUND1 (A, B, C, D, 4, 3);
1073   ROUND1 (D, A, B, C, 5, 7);
1074   ROUND1 (C, D, A, B, 6, 11);
1075   ROUND1 (B, C, D, A, 7, 19);
1076   ROUND1 (A, B, C, D, 8, 3);
1077   ROUND1 (D, A, B, C, 9, 7);
1078   ROUND1 (C, D, A, B, 10, 11);
1079   ROUND1 (B, C, D, A, 11, 19);
1080   ROUND1 (A, B, C, D, 12, 3);
1081   ROUND1 (D, A, B, C, 13, 7);
1082   ROUND1 (C, D, A, B, 14, 11);
1083   ROUND1 (B, C, D, A, 15, 19);
1084
1085   ROUND2 (A, B, C, D, 0, 3);
1086   ROUND2 (D, A, B, C, 4, 5);
1087   ROUND2 (C, D, A, B, 8, 9);
1088   ROUND2 (B, C, D, A, 12, 13);
1089   ROUND2 (A, B, C, D, 1, 3);
1090   ROUND2 (D, A, B, C, 5, 5);
1091   ROUND2 (C, D, A, B, 9, 9);
1092   ROUND2 (B, C, D, A, 13, 13);
1093   ROUND2 (A, B, C, D, 2, 3);
1094   ROUND2 (D, A, B, C, 6, 5);
1095   ROUND2 (C, D, A, B, 10, 9);
1096   ROUND2 (B, C, D, A, 14, 13);
1097   ROUND2 (A, B, C, D, 3, 3);
1098   ROUND2 (D, A, B, C, 7, 5);
1099   ROUND2 (C, D, A, B, 11, 9);
1100   ROUND2 (B, C, D, A, 15, 13);
1101
1102   ROUND3 (A, B, C, D, 0, 3);
1103   ROUND3 (D, A, B, C, 8, 9);
1104   ROUND3 (C, D, A, B, 4, 11);
1105   ROUND3 (B, C, D, A, 12, 15);
1106   ROUND3 (A, B, C, D, 2, 3);
1107   ROUND3 (D, A, B, C, 10, 9);
1108   ROUND3 (C, D, A, B, 6, 11);
1109   ROUND3 (B, C, D, A, 14, 15);
1110   ROUND3 (A, B, C, D, 1, 3);
1111   ROUND3 (D, A, B, C, 9, 9);
1112   ROUND3 (C, D, A, B, 5, 11);
1113   ROUND3 (B, C, D, A, 13, 15);
1114   ROUND3 (A, B, C, D, 3, 3);
1115   ROUND3 (D, A, B, C, 11, 9);
1116   ROUND3 (C, D, A, B, 7, 11);
1117   ROUND3 (B, C, D, A, 15, 15);
1118
1119   A += AA;
1120   B += BB;
1121   C += CC;
1122   D += DD;
1123
1124   A &= 0xFFFFFFFF;
1125   B &= 0xFFFFFFFF;
1126   C &= 0xFFFFFFFF;
1127   D &= 0xFFFFFFFF;
1128
1129   for (j = 0; j < 16; j++)
1130     X[j] = 0;
1131 }
1132
1133 static void
1134 copy64 (uint32x * M, uschar *in)
1135 {
1136   int i;
1137
1138   for (i = 0; i < 16; i++)
1139     M[i] = (in[i * 4 + 3] << 24) | (in[i * 4 + 2] << 16) |
1140       (in[i * 4 + 1] << 8) | (in[i * 4 + 0] << 0);
1141 }
1142
1143 static void
1144 copy4 (uschar *out, uint32x x)
1145 {
1146   out[0] = x & 0xFF;
1147   out[1] = (x >> 8) & 0xFF;
1148   out[2] = (x >> 16) & 0xFF;
1149   out[3] = (x >> 24) & 0xFF;
1150 }
1151
1152 /* produce a md4 message digest from data of length n bytes */
1153 void
1154 mdfour (uschar *out, uschar *in, int n)
1155 {
1156   uschar buf[128];
1157   uint32x M[16];
1158   uint32x b = n * 8;
1159   int i;
1160
1161   A = 0x67452301;
1162   B = 0xefcdab89;
1163   C = 0x98badcfe;
1164   D = 0x10325476;
1165
1166   while (n > 64)
1167     {
1168       copy64 (M, in);
1169       spa_mdfour64 (M);
1170       in += 64;
1171       n -= 64;
1172     }
1173
1174   for (i = 0; i < 128; i++)
1175     buf[i] = 0;
1176   memcpy (buf, in, n);
1177   buf[n] = 0x80;
1178
1179   if (n <= 55)
1180     {
1181       copy4 (buf + 56, b);
1182       copy64 (M, buf);
1183       spa_mdfour64 (M);
1184     }
1185   else
1186     {
1187       copy4 (buf + 120, b);
1188       copy64 (M, buf);
1189       spa_mdfour64 (M);
1190       copy64 (M, buf + 64);
1191       spa_mdfour64 (M);
1192     }
1193
1194   for (i = 0; i < 128; i++)
1195     buf[i] = 0;
1196   copy64 (M, buf);
1197
1198   copy4 (out, A);
1199   copy4 (out + 4, B);
1200   copy4 (out + 8, C);
1201   copy4 (out + 12, D);
1202
1203   A = B = C = D = 0;
1204 }
1205
1206 char versionString[] = "libntlm version 0.21";
1207
1208 /* Utility routines that handle NTLM auth structures. */
1209
1210 /* The [IS]VAL macros are to take care of byte order for non-Intel
1211  * Machines -- I think this file is OK, but it hasn't been tested.
1212  * The other files (the ones stolen from Samba) should be OK.
1213  */
1214
1215
1216 /* I am not crazy about these macros -- they seem to have gotten
1217  * a bit complex.  A new scheme for handling string/buffer fields
1218  * in the structures probably needs to be designed
1219  */
1220
1221 #define spa_bytes_add(ptr, header, buf, count) \
1222 { \
1223 if (buf != NULL  &&  count) \
1224   { \
1225   SSVAL(&ptr->header.len,0,count); \
1226   SSVAL(&ptr->header.maxlen,0,count); \
1227   SIVAL(&ptr->header.offset,0,((ptr->buffer - ((uint8x*)ptr)) + ptr->bufIndex)); \
1228   memcpy(ptr->buffer+ptr->bufIndex, buf, count); \
1229   ptr->bufIndex += count; \
1230   } \
1231 else \
1232   { \
1233   ptr->header.len = \
1234   ptr->header.maxlen = 0; \
1235   SIVAL(&ptr->header.offset,0,((ptr->buffer - ((uint8x*)ptr)) + ptr->bufIndex)); \
1236   } \
1237 }
1238
1239 #define spa_string_add(ptr, header, string) \
1240 { \
1241 char *p = string; \
1242 int len = 0; \
1243 if (p) len = strlen(p); \
1244 spa_bytes_add(ptr, header, (US p), len); \
1245 }
1246
1247 #define spa_unicode_add_string(ptr, header, string) \
1248 { \
1249 char *p = string; \
1250 uschar *b = NULL; \
1251 int len = 0; \
1252 if (p) \
1253   { \
1254   len = strlen(p); \
1255   b = strToUnicode(p); \
1256   } \
1257 spa_bytes_add(ptr, header, b, len*2); \
1258 }
1259
1260
1261 #define GetUnicodeString(structPtr, header) \
1262 unicodeToString(((char*)structPtr) + IVAL(&structPtr->header.offset,0) , SVAL(&structPtr->header.len,0)/2)
1263 #define GetString(structPtr, header) \
1264 toString((((char *)structPtr) + IVAL(&structPtr->header.offset,0)), SVAL(&structPtr->header.len,0))
1265
1266 #ifdef notdef
1267
1268 #define DumpBuffer(fp, structPtr, header) \
1269 dumpRaw(fp,(US structPtr)+IVAL(&structPtr->header.offset,0),SVAL(&structPtr->header.len,0))
1270
1271
1272 static void
1273 dumpRaw (FILE * fp, uschar *buf, size_t len)
1274 {
1275   int i;
1276
1277   for (i = 0; i < len; ++i)
1278     fprintf (fp, "%02x ", buf[i]);
1279
1280   fprintf (fp, "\n");
1281 }
1282
1283 #endif
1284
1285 char *
1286 unicodeToString (char *p, size_t len)
1287 {
1288   int i;
1289   static char buf[1024];
1290
1291   assert (len + 1 < sizeof buf);
1292
1293   for (i = 0; i < len; ++i)
1294     {
1295       buf[i] = *p & 0x7f;
1296       p += 2;
1297     }
1298
1299   buf[i] = '\0';
1300   return buf;
1301 }
1302
1303 static uschar *
1304 strToUnicode (char *p)
1305 {
1306   static uschar buf[1024];
1307   size_t l = strlen (p);
1308   int i = 0;
1309
1310   assert (l * 2 < sizeof buf);
1311
1312   while (l--)
1313     {
1314       buf[i++] = *p++;
1315       buf[i++] = 0;
1316     }
1317
1318   return buf;
1319 }
1320
1321 static uschar *
1322 toString (char *p, size_t len)
1323 {
1324   static uschar buf[1024];
1325
1326   assert (len + 1 < sizeof buf);
1327
1328   memcpy (buf, p, len);
1329   buf[len] = 0;
1330   return buf;
1331 }
1332
1333 #ifdef notdef
1334
1335 void
1336 dumpSmbNtlmAuthRequest (FILE * fp, SPAAuthRequest * request)
1337 {
1338   fprintf (fp, "NTLM Request:\n");
1339   fprintf (fp, "      Ident = %s\n", request->ident);
1340   fprintf (fp, "      mType = %d\n", IVAL (&request->msgType, 0));
1341   fprintf (fp, "      Flags = %08x\n", IVAL (&request->flags, 0));
1342   fprintf (fp, "       User = %s\n", GetString (request, user));
1343   fprintf (fp, "     Domain = %s\n", GetString (request, domain));
1344 }
1345
1346 void
1347 dumpSmbNtlmAuthChallenge (FILE * fp, SPAAuthChallenge * challenge)
1348 {
1349   fprintf (fp, "NTLM Challenge:\n");
1350   fprintf (fp, "      Ident = %s\n", challenge->ident);
1351   fprintf (fp, "      mType = %d\n", IVAL (&challenge->msgType, 0));
1352   fprintf (fp, "     Domain = %s\n", GetUnicodeString (challenge, uDomain));
1353   fprintf (fp, "      Flags = %08x\n", IVAL (&challenge->flags, 0));
1354   fprintf (fp, "  Challenge = ");
1355   dumpRaw (fp, challenge->challengeData, 8);
1356 }
1357
1358 void
1359 dumpSmbNtlmAuthResponse (FILE * fp, SPAAuthResponse * response)
1360 {
1361   fprintf (fp, "NTLM Response:\n");
1362   fprintf (fp, "      Ident = %s\n", response->ident);
1363   fprintf (fp, "      mType = %d\n", IVAL (&response->msgType, 0));
1364   fprintf (fp, "     LmResp = ");
1365   DumpBuffer (fp, response, lmResponse);
1366   fprintf (fp, "     NTResp = ");
1367   DumpBuffer (fp, response, ntResponse);
1368   fprintf (fp, "     Domain = %s\n", GetUnicodeString (response, uDomain));
1369   fprintf (fp, "       User = %s\n", GetUnicodeString (response, uUser));
1370   fprintf (fp, "        Wks = %s\n", GetUnicodeString (response, uWks));
1371   fprintf (fp, "       sKey = ");
1372   DumpBuffer (fp, response, sessionKey);
1373   fprintf (fp, "      Flags = %08x\n", IVAL (&response->flags, 0));
1374 }
1375 #endif
1376
1377 void
1378 spa_build_auth_request (SPAAuthRequest * request, char *user, char *domain)
1379 {
1380   char *u = strdup (user);
1381   char *p = strchr (u, '@');
1382
1383   if (p)
1384     {
1385       if (!domain)
1386        domain = p + 1;
1387       *p = '\0';
1388     }
1389
1390   request->bufIndex = 0;
1391   memcpy (request->ident, "NTLMSSP\0\0\0", 8);
1392   SIVAL (&request->msgType, 0, 1);
1393   SIVAL (&request->flags, 0, 0x0000b207);      /* have to figure out what these mean */
1394   spa_string_add (request, user, u);
1395   spa_string_add (request, domain, domain);
1396   free (u);
1397 }
1398
1399
1400
1401 void
1402 spa_build_auth_challenge (SPAAuthRequest * request, SPAAuthChallenge * challenge)
1403 {
1404   char chalstr[8];
1405   int i;
1406   int p = (int)getpid();
1407   int random_seed = (int)time(NULL) ^ ((p << 16) | p);
1408
1409   request = request;  /* Added by PH to stop compilers whinging */
1410
1411   /* Ensure challenge data is cleared, in case it isn't all used. This
1412   patch added by PH on suggestion of Russell King */
1413
1414   memset(challenge, 0, sizeof(SPAAuthChallenge));
1415
1416   challenge->bufIndex = 0;
1417   memcpy (challenge->ident, "NTLMSSP\0", 8);
1418   SIVAL (&challenge->msgType, 0, 2);
1419   SIVAL (&challenge->flags, 0, 0x00008201);
1420   SIVAL (&challenge->uDomain.len, 0, 0x0000);
1421   SIVAL (&challenge->uDomain.maxlen, 0, 0x0000);
1422   SIVAL (&challenge->uDomain.offset, 0, 0x00002800);
1423
1424   /* generate eight pseudo random bytes (method ripped from host.c) */
1425
1426   for(i=0;i<8;i++) {
1427     chalstr[i] = (uschar)(random_seed >> 16) % 256;
1428     random_seed = (1103515245 - (chalstr[i])) * random_seed + 12345;
1429   };
1430
1431   memcpy(challenge->challengeData,chalstr,8);
1432 }
1433
1434
1435
1436
1437 /* This is the original source of this function, preserved here for reference.
1438 The new version below was re-organized by PH following a patch and some further
1439 suggestions from Mark Lyda to fix the problem that is described at the head of
1440 this module. At the same time, I removed the untidiness in the code below that
1441 involves the "d" and "domain" variables. */
1442
1443 #ifdef NEVER
1444 void
1445 spa_build_auth_response (SPAAuthChallenge * challenge,
1446                         SPAAuthResponse * response, char *user,
1447                         char *password)
1448 {
1449   uint8x lmRespData[24];
1450   uint8x ntRespData[24];
1451   char *d = strdup (GetUnicodeString (challenge, uDomain));
1452   char *domain = d;
1453   char *u = strdup (user);
1454   char *p = strchr (u, '@');
1455
1456   if (p)
1457     {
1458       domain = p + 1;
1459       *p = '\0';
1460     }
1461
1462   spa_smb_encrypt (US password, challenge->challengeData, lmRespData);
1463   spa_smb_nt_encrypt (US password, challenge->challengeData, ntRespData);
1464
1465   response->bufIndex = 0;
1466   memcpy (response->ident, "NTLMSSP\0\0\0", 8);
1467   SIVAL (&response->msgType, 0, 3);
1468
1469   spa_bytes_add (response, lmResponse, lmRespData, 24);
1470   spa_bytes_add (response, ntResponse, ntRespData, 24);
1471   spa_unicode_add_string (response, uDomain, domain);
1472   spa_unicode_add_string (response, uUser, u);
1473   spa_unicode_add_string (response, uWks, u);
1474   spa_string_add (response, sessionKey, NULL);
1475
1476   response->flags = challenge->flags;
1477
1478   free (d);
1479   free (u);
1480 }
1481 #endif
1482
1483
1484 /* This is the re-organized version (see comments above) */
1485
1486 void
1487 spa_build_auth_response (SPAAuthChallenge * challenge,
1488                         SPAAuthResponse * response, char *user,
1489                         char *password)
1490 {
1491   uint8x lmRespData[24];
1492   uint8x ntRespData[24];
1493   uint32x cf = IVAL(&challenge->flags, 0);
1494   char *u = strdup (user);
1495   char *p = strchr (u, '@');
1496   char *d = NULL;
1497   char *domain;
1498
1499   if (p)
1500     {
1501     domain = p + 1;
1502     *p = '\0';
1503     }
1504
1505   else domain = d = strdup((cf & 0x1)?
1506     (const char *)GetUnicodeString(challenge, uDomain) :
1507     (const char *)GetString(challenge, uDomain));
1508
1509   spa_smb_encrypt (US password, challenge->challengeData, lmRespData);
1510   spa_smb_nt_encrypt (US password, challenge->challengeData, ntRespData);
1511
1512   response->bufIndex = 0;
1513   memcpy (response->ident, "NTLMSSP\0\0\0", 8);
1514   SIVAL (&response->msgType, 0, 3);
1515
1516   spa_bytes_add (response, lmResponse, lmRespData, (cf & 0x200) ? 24 : 0);
1517   spa_bytes_add (response, ntResponse, ntRespData, (cf & 0x8000) ? 24 : 0);
1518
1519   if (cf & 0x1) {      /* Unicode Text */
1520        spa_unicode_add_string (response, uDomain, domain);
1521        spa_unicode_add_string (response, uUser, u);
1522        spa_unicode_add_string (response, uWks, u);
1523   } else {             /* OEM Text */
1524        spa_string_add (response, uDomain, domain);
1525        spa_string_add (response, uUser, u);
1526        spa_string_add (response, uWks, u);
1527   }
1528
1529   spa_string_add (response, sessionKey, NULL);
1530   response->flags = challenge->flags;
1531
1532   if (d != NULL) free (d);
1533   free (u);
1534 }