Remove attempts to quieten compiler static-checking (more)
[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 (CS &challenge, sizeof(challenge),
87                 CCS (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 *)(CS (buf) + (pos)))
233 #  define IVAL(buf,pos) (*(uint32x *)(CS (buf) + (pos)))
234 #  define SVALS(buf,pos) (*(int16x *)(CS (buf) + (pos)))
235 #  define IVALS(buf,pos) (*(int32x *)(CS (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 { for (int l = 0; l < (len); l++) (val)[l] = macro((buf), (pos) + (size)*l); }
249
250 # define SSMBMACRO(macro,buf,pos,val,len,size) \
251 { for (int 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        for (int 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        for (int 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        for (int 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 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 for (int i = 0; i < n; i++)
566   out[i] = in[p[i] - 1];
567 }
568
569 static void
570 lshift (char *d, int count, int n)
571 {
572 char out[64];
573 for (int i = 0; i < n; i++)
574   out[i] = d[(i + count) % n];
575 for (int i = 0; i < n; i++)
576   d[i] = out[i];
577 }
578
579 static void
580 concat (char *out, char *in1, char *in2, int l1, int l2)
581 {
582 while (l1--)
583   *out++ = *in1++;
584 while (l2--)
585   *out++ = *in2++;
586 }
587
588 static void
589 xor (char *out, char *in1, char *in2, int n)
590 {
591 for (int i = 0; i < n; i++)
592   out[i] = in1[i] ^ in2[i];
593 }
594
595 static void
596 dohash (char *out, char *in, char *key, int forw)
597 {
598 int i, j, k;
599 char pk1[56];
600 char c[28];
601 char d[28];
602 char cd[56];
603 char ki[16][48];
604 char pd1[64];
605 char l[32], r[32];
606 char rl[64];
607
608 permute (pk1, key, perm1, 56);
609
610 for (i = 0; i < 28; i++)
611   c[i] = pk1[i];
612 for (i = 0; i < 28; i++)
613   d[i] = pk1[i + 28];
614
615 for (i = 0; i < 16; i++)
616   {
617   lshift (c, sc[i], 28);
618   lshift (d, sc[i], 28);
619
620   concat (cd, c, d, 28, 28);
621   permute (ki[i], cd, perm2, 48);
622   }
623
624 permute (pd1, in, perm3, 64);
625
626 for (j = 0; j < 32; j++)
627   {
628   l[j] = pd1[j];
629   r[j] = pd1[j + 32];
630   }
631
632 for (i = 0; i < 16; i++)
633   {
634   char er[48];
635   char erk[48];
636   char b[8][6];
637   char cb[32];
638   char pcb[32];
639   char r2[32];
640
641   permute (er, r, perm4, 48);
642
643   xor (erk, er, ki[forw ? i : 15 - i], 48);
644
645   for (j = 0; j < 8; j++)
646    for (k = 0; k < 6; k++)
647      b[j][k] = erk[j * 6 + k];
648
649   for (j = 0; j < 8; j++)
650    {
651    int m, n;
652    m = (b[j][0] << 1) | b[j][5];
653
654    n = (b[j][1] << 3) | (b[j][2] << 2) | (b[j][3] << 1) | b[j][4];
655
656    for (k = 0; k < 4; k++)
657      b[j][k] = (sbox[j][m][n] & (1 << (3 - k))) ? 1 : 0;
658    }
659
660   for (j = 0; j < 8; j++)
661    for (k = 0; k < 4; k++)
662      cb[j * 4 + k] = b[j][k];
663   permute (pcb, cb, perm5, 32);
664
665   xor (r2, l, pcb, 32);
666
667   for (j = 0; j < 32; j++)
668    l[j] = r[j];
669
670   for (j = 0; j < 32; j++)
671    r[j] = r2[j];
672   }
673
674 concat (rl, r, l, 32, 32);
675
676 permute (out, rl, perm6, 64);
677 }
678
679 static void
680 str_to_key (uschar *str, uschar *key)
681 {
682 int i;
683
684 key[0] = str[0] >> 1;
685 key[1] = ((str[0] & 0x01) << 6) | (str[1] >> 2);
686 key[2] = ((str[1] & 0x03) << 5) | (str[2] >> 3);
687 key[3] = ((str[2] & 0x07) << 4) | (str[3] >> 4);
688 key[4] = ((str[3] & 0x0F) << 3) | (str[4] >> 5);
689 key[5] = ((str[4] & 0x1F) << 2) | (str[5] >> 6);
690 key[6] = ((str[5] & 0x3F) << 1) | (str[6] >> 7);
691 key[7] = str[6] & 0x7F;
692 for (i = 0; i < 8; i++)
693     key[i] = (key[i] << 1);
694 }
695
696
697 static void
698 smbhash (uschar *out, uschar *in, uschar *key, int forw)
699 {
700 int i;
701 char outb[64];
702 char inb[64];
703 char keyb[64];
704 uschar key2[8];
705
706 str_to_key (key, key2);
707
708 for (i = 0; i < 64; i++)
709   {
710   inb[i] = (in[i / 8] & (1 << (7 - (i % 8)))) ? 1 : 0;
711   keyb[i] = (key2[i / 8] & (1 << (7 - (i % 8)))) ? 1 : 0;
712   outb[i] = 0;
713   }
714
715 dohash (outb, inb, keyb, forw);
716
717 for (i = 0; i < 8; i++)
718   out[i] = 0;
719
720 for (i = 0; i < 64; i++)
721   if (outb[i])
722    out[i / 8] |= (1 << (7 - (i % 8)));
723 }
724
725 void
726 E_P16 (uschar *p14, uschar *p16)
727 {
728 uschar sp8[8] = { 0x4b, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 };
729 smbhash (p16, sp8, p14, 1);
730 smbhash (p16 + 8, sp8, p14 + 7, 1);
731 }
732
733 void
734 E_P24 (uschar *p21, uschar *c8, uschar *p24)
735 {
736 smbhash (p24, c8, p21, 1);
737 smbhash (p24 + 8, c8, p21 + 7, 1);
738 smbhash (p24 + 16, c8, p21 + 14, 1);
739 }
740
741 void
742 D_P16 (uschar *p14, uschar *in, uschar *out)
743 {
744 smbhash (out, in, p14, 0);
745 smbhash (out + 8, in + 8, p14 + 7, 0);
746 }
747
748 /****************************************************************************
749  Like strncpy but always null terminates. Make sure there is room!
750  The variable n should always be one less than the available size.
751 ****************************************************************************/
752
753 char *
754 StrnCpy (char *dest, const char *src, size_t n)
755 {
756 char *d = dest;
757 if (!dest)
758   return (NULL);
759 if (!src)
760   {
761   *dest = 0;
762   return (dest);
763   }
764 while (n-- && (*d++ = *src++));
765 *d = 0;
766 return (dest);
767 }
768
769 size_t
770 skip_multibyte_char (char c)
771 {
772 /* bogus if to get rid of unused compiler warning */
773 if (c)
774   return 0;
775 else
776   return 0;
777 }
778
779
780 /*******************************************************************
781 safe string copy into a known length string. maxlength does not
782 include the terminating zero.
783 ********************************************************************/
784
785 char *
786 safe_strcpy (char *dest, const char *src, size_t maxlength)
787 {
788 size_t len;
789
790 if (!dest)
791   {
792   DEBUG_X (0, ("ERROR: NULL dest in safe_strcpy\n"));
793   return NULL;
794   }
795
796 if (!src)
797   {
798   *dest = 0;
799   return dest;
800   }
801
802 len = strlen (src);
803
804 if (len > maxlength)
805   {
806   DEBUG_X (0, ("ERROR: string overflow by %d in safe_strcpy [%.50s]\n",
807             (int) (len - maxlength), src));
808   len = maxlength;
809   }
810
811 memcpy (dest, src, len);
812 dest[len] = 0;
813 return dest;
814 }
815
816
817 void
818 strupper (char *s)
819 {
820 while (*s)
821   {
822    size_t skip = skip_multibyte_char (*s);
823    if (skip != 0)
824      s += skip;
825    else
826      {
827        if (islower ((uschar)(*s)))
828          *s = toupper (*s);
829        s++;
830      }
831   }
832 }
833
834
835 /*
836  This implements the X/Open SMB password encryption
837  It takes a password, a 8 byte "crypt key" and puts 24 bytes of
838  encrypted password into p24
839  */
840
841 void
842 spa_smb_encrypt (uschar * passwd, uschar * c8, uschar * p24)
843 {
844 uschar p14[15], p21[21];
845
846 memset (p21, '\0', 21);
847 memset (p14, '\0', 14);
848 StrnCpy (CS  p14, CS  passwd, 14);
849
850 strupper (CS  p14);
851 E_P16 (p14, p21);
852
853 SMBOWFencrypt (p21, c8, p24);
854
855 #ifdef DEBUG_PASSWORD
856 DEBUG_X (100, ("spa_smb_encrypt: lm#, challenge, response\n"));
857 dump_data (100, CS  p21, 16);
858 dump_data (100, CS  c8, 8);
859 dump_data (100, CS  p24, 24);
860 #endif
861 }
862
863 /* Routines for Windows NT MD4 Hash functions. */
864 static int
865 _my_wcslen (int16x * str)
866 {
867 int len = 0;
868 while (*str++ != 0)
869   len++;
870 return len;
871 }
872
873 /*
874  * Convert a string into an NT UNICODE string.
875  * Note that regardless of processor type
876  * this must be in intel (little-endian)
877  * format.
878  */
879
880 static int
881 _my_mbstowcs (int16x * dst, uschar * src, int len)
882 {
883 int i;
884 int16x val;
885
886 for (i = 0; i < len; i++)
887   {
888   val = *src;
889   SSVAL (dst, 0, val);
890   dst++;
891   src++;
892   if (val == 0)
893    break;
894   }
895 return i;
896 }
897
898 /*
899  * Creates the MD4 Hash of the users password in NT UNICODE.
900  */
901
902 void
903 E_md4hash (uschar * passwd, uschar * p16)
904 {
905 int len;
906 int16x wpwd[129];
907
908 /* Password cannot be longer than 128 characters */
909 len = strlen (CS  passwd);
910 if (len > 128)
911   len = 128;
912 /* Password must be converted to NT unicode */
913 _my_mbstowcs (wpwd, passwd, len);
914 wpwd[len] = 0;               /* Ensure string is null terminated */
915 /* Calculate length in bytes */
916 len = _my_wcslen (wpwd) * sizeof (int16x);
917
918 mdfour (p16, US wpwd, len);
919 }
920
921 /* Does both the NT and LM owfs of a user's password */
922 void
923 nt_lm_owf_gen (char *pwd, uschar nt_p16[16], uschar p16[16])
924 {
925 char passwd[130];
926
927 memset (passwd, '\0', 130);
928 safe_strcpy (passwd, pwd, sizeof (passwd) - 1);
929
930 /* Calculate the MD4 hash (NT compatible) of the password */
931 memset (nt_p16, '\0', 16);
932 E_md4hash (US passwd, nt_p16);
933
934 #ifdef DEBUG_PASSWORD
935 DEBUG_X (100, ("nt_lm_owf_gen: pwd, nt#\n"));
936 dump_data (120, passwd, strlen (passwd));
937 dump_data (100, CS  nt_p16, 16);
938 #endif
939
940 /* Mangle the passwords into Lanman format */
941 passwd[14] = '\0';
942 strupper (passwd);
943
944 /* Calculate the SMB (lanman) hash functions of the password */
945
946 memset (p16, '\0', 16);
947 E_P16 (US passwd, US p16);
948
949 #ifdef DEBUG_PASSWORD
950 DEBUG_X (100, ("nt_lm_owf_gen: pwd, lm#\n"));
951 dump_data (120, passwd, strlen (passwd));
952 dump_data (100, CS  p16, 16);
953 #endif
954 /* clear out local copy of user's password (just being paranoid). */
955 memset (passwd, '\0', sizeof (passwd));
956 }
957
958 /* Does the des encryption from the NT or LM MD4 hash. */
959 void
960 SMBOWFencrypt (uschar passwd[16], uschar * c8, uschar p24[24])
961 {
962 uschar p21[21];
963
964 memset (p21, '\0', 21);
965
966 memcpy (p21, passwd, 16);
967 E_P24 (p21, c8, p24);
968 }
969
970 /* Does the des encryption from the FIRST 8 BYTES of the NT or LM MD4 hash. */
971 void
972 NTLMSSPOWFencrypt (uschar passwd[8], uschar * ntlmchalresp, uschar p24[24])
973 {
974 uschar p21[21];
975
976 memset (p21, '\0', 21);
977 memcpy (p21, passwd, 8);
978 memset (p21 + 8, 0xbd, 8);
979
980 E_P24 (p21, ntlmchalresp, p24);
981 #ifdef DEBUG_PASSWORD
982 DEBUG_X (100, ("NTLMSSPOWFencrypt: p21, c8, p24\n"));
983 dump_data (100, CS  p21, 21);
984 dump_data (100, CS  ntlmchalresp, 8);
985 dump_data (100, CS  p24, 24);
986 #endif
987 }
988
989
990 /* Does the NT MD4 hash then des encryption. */
991
992 void
993 spa_smb_nt_encrypt (uschar * passwd, uschar * c8, uschar * p24)
994 {
995 uschar p21[21];
996
997 memset (p21, '\0', 21);
998
999 E_md4hash (passwd, p21);
1000 SMBOWFencrypt (p21, c8, p24);
1001
1002 #ifdef DEBUG_PASSWORD
1003 DEBUG_X (100, ("spa_smb_nt_encrypt: nt#, challenge, response\n"));
1004 dump_data (100, CS  p21, 16);
1005 dump_data (100, CS  c8, 8);
1006 dump_data (100, CS  p24, 24);
1007 #endif
1008 }
1009
1010 static uint32x A, B, C, D;
1011
1012 static uint32x
1013 F (uint32x X, uint32x Y, uint32x Z)
1014 {
1015 return (X & Y) | ((~X) & Z);
1016 }
1017
1018 static uint32x
1019 G (uint32x X, uint32x Y, uint32x Z)
1020 {
1021 return (X & Y) | (X & Z) | (Y & Z);
1022 }
1023
1024 static uint32x
1025 H (uint32x X, uint32x Y, uint32x Z)
1026 {
1027 return X ^ Y ^ Z;
1028 }
1029
1030 static uint32x
1031 lshift_a (uint32x x, int s)
1032 {
1033 x &= 0xFFFFFFFF;
1034 return ((x << s) & 0xFFFFFFFF) | (x >> (32 - s));
1035 }
1036
1037 #define ROUND1(a,b,c,d,k,s) a = lshift_a(a + F(b,c,d) + X[k], s)
1038 #define ROUND2(a,b,c,d,k,s) a = lshift_a(a + G(b,c,d) + X[k] + (uint32x)0x5A827999,s)
1039 #define ROUND3(a,b,c,d,k,s) a = lshift_a(a + H(b,c,d) + X[k] + (uint32x)0x6ED9EBA1,s)
1040
1041 /* this applies md4 to 64 byte chunks */
1042 static void
1043 spa_mdfour64 (uint32x * M)
1044 {
1045 int j;
1046 uint32x AA, BB, CC, DD;
1047 uint32x X[16];
1048
1049 for (j = 0; j < 16; j++)
1050   X[j] = M[j];
1051
1052 AA = A;
1053 BB = B;
1054 CC = C;
1055 DD = D;
1056
1057 ROUND1 (A, B, C, D, 0, 3);
1058 ROUND1 (D, A, B, C, 1, 7);
1059 ROUND1 (C, D, A, B, 2, 11);
1060 ROUND1 (B, C, D, A, 3, 19);
1061 ROUND1 (A, B, C, D, 4, 3);
1062 ROUND1 (D, A, B, C, 5, 7);
1063 ROUND1 (C, D, A, B, 6, 11);
1064 ROUND1 (B, C, D, A, 7, 19);
1065 ROUND1 (A, B, C, D, 8, 3);
1066 ROUND1 (D, A, B, C, 9, 7);
1067 ROUND1 (C, D, A, B, 10, 11);
1068 ROUND1 (B, C, D, A, 11, 19);
1069 ROUND1 (A, B, C, D, 12, 3);
1070 ROUND1 (D, A, B, C, 13, 7);
1071 ROUND1 (C, D, A, B, 14, 11);
1072 ROUND1 (B, C, D, A, 15, 19);
1073
1074 ROUND2 (A, B, C, D, 0, 3);
1075 ROUND2 (D, A, B, C, 4, 5);
1076 ROUND2 (C, D, A, B, 8, 9);
1077 ROUND2 (B, C, D, A, 12, 13);
1078 ROUND2 (A, B, C, D, 1, 3);
1079 ROUND2 (D, A, B, C, 5, 5);
1080 ROUND2 (C, D, A, B, 9, 9);
1081 ROUND2 (B, C, D, A, 13, 13);
1082 ROUND2 (A, B, C, D, 2, 3);
1083 ROUND2 (D, A, B, C, 6, 5);
1084 ROUND2 (C, D, A, B, 10, 9);
1085 ROUND2 (B, C, D, A, 14, 13);
1086 ROUND2 (A, B, C, D, 3, 3);
1087 ROUND2 (D, A, B, C, 7, 5);
1088 ROUND2 (C, D, A, B, 11, 9);
1089 ROUND2 (B, C, D, A, 15, 13);
1090
1091 ROUND3 (A, B, C, D, 0, 3);
1092 ROUND3 (D, A, B, C, 8, 9);
1093 ROUND3 (C, D, A, B, 4, 11);
1094 ROUND3 (B, C, D, A, 12, 15);
1095 ROUND3 (A, B, C, D, 2, 3);
1096 ROUND3 (D, A, B, C, 10, 9);
1097 ROUND3 (C, D, A, B, 6, 11);
1098 ROUND3 (B, C, D, A, 14, 15);
1099 ROUND3 (A, B, C, D, 1, 3);
1100 ROUND3 (D, A, B, C, 9, 9);
1101 ROUND3 (C, D, A, B, 5, 11);
1102 ROUND3 (B, C, D, A, 13, 15);
1103 ROUND3 (A, B, C, D, 3, 3);
1104 ROUND3 (D, A, B, C, 11, 9);
1105 ROUND3 (C, D, A, B, 7, 11);
1106 ROUND3 (B, C, D, A, 15, 15);
1107
1108 A += AA;
1109 B += BB;
1110 C += CC;
1111 D += DD;
1112
1113 A &= 0xFFFFFFFF;
1114 B &= 0xFFFFFFFF;
1115 C &= 0xFFFFFFFF;
1116 D &= 0xFFFFFFFF;
1117
1118 for (j = 0; j < 16; j++)
1119   X[j] = 0;
1120 }
1121
1122 static void
1123 copy64 (uint32x * M, uschar *in)
1124 {
1125 int i;
1126
1127 for (i = 0; i < 16; i++)
1128   M[i] = (in[i * 4 + 3] << 24) | (in[i * 4 + 2] << 16) |
1129     (in[i * 4 + 1] << 8) | (in[i * 4 + 0] << 0);
1130 }
1131
1132 static void
1133 copy4 (uschar *out, uint32x x)
1134 {
1135 out[0] = x & 0xFF;
1136 out[1] = (x >> 8) & 0xFF;
1137 out[2] = (x >> 16) & 0xFF;
1138 out[3] = (x >> 24) & 0xFF;
1139 }
1140
1141 /* produce a md4 message digest from data of length n bytes */
1142 void
1143 mdfour (uschar *out, uschar *in, int n)
1144 {
1145 uschar buf[128];
1146 uint32x M[16];
1147 uint32x b = n * 8;
1148 int i;
1149
1150 A = 0x67452301;
1151 B = 0xefcdab89;
1152 C = 0x98badcfe;
1153 D = 0x10325476;
1154
1155 while (n > 64)
1156   {
1157   copy64 (M, in);
1158   spa_mdfour64 (M);
1159   in += 64;
1160   n -= 64;
1161   }
1162
1163 for (i = 0; i < 128; i++)
1164   buf[i] = 0;
1165 memcpy (buf, in, n);
1166 buf[n] = 0x80;
1167
1168 if (n <= 55)
1169   {
1170   copy4 (buf + 56, b);
1171   copy64 (M, buf);
1172   spa_mdfour64 (M);
1173   }
1174 else
1175   {
1176   copy4 (buf + 120, b);
1177   copy64 (M, buf);
1178   spa_mdfour64 (M);
1179   copy64 (M, buf + 64);
1180   spa_mdfour64 (M);
1181   }
1182
1183 for (i = 0; i < 128; i++)
1184   buf[i] = 0;
1185 copy64 (M, buf);
1186
1187 copy4 (out, A);
1188 copy4 (out + 4, B);
1189 copy4 (out + 8, C);
1190 copy4 (out + 12, D);
1191
1192 A = B = C = D = 0;
1193 }
1194
1195 char versionString[] = "libntlm version 0.21";
1196
1197 /* Utility routines that handle NTLM auth structures. */
1198
1199 /* The [IS]VAL macros are to take care of byte order for non-Intel
1200  * Machines -- I think this file is OK, but it hasn't been tested.
1201  * The other files (the ones stolen from Samba) should be OK.
1202  */
1203
1204
1205 /* I am not crazy about these macros -- they seem to have gotten
1206  * a bit complex.  A new scheme for handling string/buffer fields
1207  * in the structures probably needs to be designed
1208  */
1209
1210 #define spa_bytes_add(ptr, header, buf, count) \
1211 { \
1212 if (buf && (count) != 0) /* we hate -Wint-in-bool-contex */ \
1213   { \
1214   SSVAL(&ptr->header.len,0,count); \
1215   SSVAL(&ptr->header.maxlen,0,count); \
1216   SIVAL(&ptr->header.offset,0,((ptr->buffer - ((uint8x*)ptr)) + ptr->bufIndex)); \
1217   memcpy(ptr->buffer+ptr->bufIndex, buf, count); \
1218   ptr->bufIndex += count; \
1219   } \
1220 else \
1221   { \
1222   ptr->header.len = \
1223   ptr->header.maxlen = 0; \
1224   SIVAL(&ptr->header.offset,0,((ptr->buffer - ((uint8x*)ptr)) + ptr->bufIndex)); \
1225   } \
1226 }
1227
1228 #define spa_string_add(ptr, header, string) \
1229 { \
1230 char *p = string; \
1231 int len = 0; \
1232 if (p) len = strlen(p); \
1233 spa_bytes_add(ptr, header, (US p), len); \
1234 }
1235
1236 #define spa_unicode_add_string(ptr, header, string) \
1237 { \
1238 char *p = string; \
1239 uschar *b = NULL; \
1240 int len = 0; \
1241 if (p) \
1242   { \
1243   len = strlen(p); \
1244   b = strToUnicode(p); \
1245   } \
1246 spa_bytes_add(ptr, header, b, len*2); \
1247 }
1248
1249
1250 #define GetUnicodeString(structPtr, header) \
1251 unicodeToString(((char*)structPtr) + IVAL(&structPtr->header.offset,0) , SVAL(&structPtr->header.len,0)/2)
1252 #define GetString(structPtr, header) \
1253 toString(((CS structPtr) + IVAL(&structPtr->header.offset,0)), SVAL(&structPtr->header.len,0))
1254
1255 #ifdef notdef
1256
1257 #define DumpBuffer(fp, structPtr, header) \
1258 dumpRaw(fp,(US structPtr)+IVAL(&structPtr->header.offset,0),SVAL(&structPtr->header.len,0))
1259
1260
1261 static void
1262 dumpRaw (FILE * fp, uschar *buf, size_t len)
1263 {
1264 int i;
1265
1266 for (i = 0; i < len; ++i)
1267   fprintf (fp, "%02x ", buf[i]);
1268
1269 fprintf (fp, "\n");
1270 }
1271
1272 #endif
1273
1274 char *
1275 unicodeToString (char *p, size_t len)
1276 {
1277 int i;
1278 static char buf[1024];
1279
1280 assert (len + 1 < sizeof buf);
1281
1282 for (i = 0; i < len; ++i)
1283   {
1284   buf[i] = *p & 0x7f;
1285   p += 2;
1286   }
1287
1288 buf[i] = '\0';
1289 return buf;
1290 }
1291
1292 static uschar *
1293 strToUnicode (char *p)
1294 {
1295 static uschar buf[1024];
1296 size_t l = strlen (p);
1297 int i = 0;
1298
1299 assert (l * 2 < sizeof buf);
1300
1301 while (l--)
1302   {
1303   buf[i++] = *p++;
1304   buf[i++] = 0;
1305   }
1306
1307 return buf;
1308 }
1309
1310 static uschar *
1311 toString (char *p, size_t len)
1312 {
1313 static uschar buf[1024];
1314
1315 assert (len + 1 < sizeof buf);
1316
1317 memcpy (buf, p, len);
1318 buf[len] = 0;
1319 return buf;
1320 }
1321
1322 #ifdef notdef
1323
1324 void
1325 dumpSmbNtlmAuthRequest (FILE * fp, SPAAuthRequest * request)
1326 {
1327 fprintf (fp, "NTLM Request:\n");
1328 fprintf (fp, "      Ident = %s\n", request->ident);
1329 fprintf (fp, "      mType = %d\n", IVAL (&request->msgType, 0));
1330 fprintf (fp, "      Flags = %08x\n", IVAL (&request->flags, 0));
1331 fprintf (fp, "       User = %s\n", GetString (request, user));
1332 fprintf (fp, "     Domain = %s\n", GetString (request, domain));
1333 }
1334
1335 void
1336 dumpSmbNtlmAuthChallenge (FILE * fp, SPAAuthChallenge * challenge)
1337 {
1338 fprintf (fp, "NTLM Challenge:\n");
1339 fprintf (fp, "      Ident = %s\n", challenge->ident);
1340 fprintf (fp, "      mType = %d\n", IVAL (&challenge->msgType, 0));
1341 fprintf (fp, "     Domain = %s\n", GetUnicodeString (challenge, uDomain));
1342 fprintf (fp, "      Flags = %08x\n", IVAL (&challenge->flags, 0));
1343 fprintf (fp, "  Challenge = ");
1344 dumpRaw (fp, challenge->challengeData, 8);
1345 }
1346
1347 void
1348 dumpSmbNtlmAuthResponse (FILE * fp, SPAAuthResponse * response)
1349 {
1350 fprintf (fp, "NTLM Response:\n");
1351 fprintf (fp, "      Ident = %s\n", response->ident);
1352 fprintf (fp, "      mType = %d\n", IVAL (&response->msgType, 0));
1353 fprintf (fp, "     LmResp = ");
1354 DumpBuffer (fp, response, lmResponse);
1355 fprintf (fp, "     NTResp = ");
1356 DumpBuffer (fp, response, ntResponse);
1357 fprintf (fp, "     Domain = %s\n", GetUnicodeString (response, uDomain));
1358 fprintf (fp, "       User = %s\n", GetUnicodeString (response, uUser));
1359 fprintf (fp, "        Wks = %s\n", GetUnicodeString (response, uWks));
1360 fprintf (fp, "       sKey = ");
1361 DumpBuffer (fp, response, sessionKey);
1362 fprintf (fp, "      Flags = %08x\n", IVAL (&response->flags, 0));
1363 }
1364 #endif
1365
1366 void
1367 spa_build_auth_request (SPAAuthRequest * request, char *user, char *domain)
1368 {
1369 char *u = strdup (user);
1370 char *p = strchr (u, '@');
1371
1372 if (p)
1373   {
1374   if (!domain)
1375    domain = p + 1;
1376   *p = '\0';
1377   }
1378
1379 request->bufIndex = 0;
1380 memcpy (request->ident, "NTLMSSP\0\0\0", 8);
1381 SIVAL (&request->msgType, 0, 1);
1382 SIVAL (&request->flags, 0, 0x0000b207);      /* have to figure out what these mean */
1383 spa_string_add (request, user, u);
1384 spa_string_add (request, domain, domain);
1385 free (u);
1386 }
1387
1388
1389
1390 void
1391 spa_build_auth_challenge (SPAAuthRequest * request, SPAAuthChallenge * challenge)
1392 {
1393 char chalstr[8];
1394 int i;
1395 int p = (int)getpid();
1396 int random_seed = (int)time(NULL) ^ ((p << 16) | p);
1397
1398 /* Ensure challenge data is cleared, in case it isn't all used. This
1399 patch added by PH on suggestion of Russell King */
1400
1401 memset(challenge, 0, sizeof(SPAAuthChallenge));
1402
1403 challenge->bufIndex = 0;
1404 memcpy (challenge->ident, "NTLMSSP\0", 8);
1405 SIVAL (&challenge->msgType, 0, 2);
1406 SIVAL (&challenge->flags, 0, 0x00008201);
1407 SIVAL (&challenge->uDomain.len, 0, 0x0000);
1408 SIVAL (&challenge->uDomain.maxlen, 0, 0x0000);
1409 SIVAL (&challenge->uDomain.offset, 0, 0x00002800);
1410
1411 /* generate eight pseudo random bytes (method ripped from host.c) */
1412
1413 for(i=0;i<8;i++)
1414   {
1415   chalstr[i] = (uschar)(random_seed >> 16) % 256;
1416   random_seed = (1103515245 - (chalstr[i])) * random_seed + 12345;
1417   }
1418
1419 memcpy(challenge->challengeData,chalstr,8);
1420 }
1421
1422
1423
1424
1425 /* This is the original source of this function, preserved here for reference.
1426 The new version below was re-organized by PH following a patch and some further
1427 suggestions from Mark Lyda to fix the problem that is described at the head of
1428 this module. At the same time, I removed the untidiness in the code below that
1429 involves the "d" and "domain" variables. */
1430
1431 #ifdef NEVER
1432 void
1433 spa_build_auth_response (SPAAuthChallenge * challenge,
1434                         SPAAuthResponse * response, char *user,
1435                         char *password)
1436 {
1437 uint8x lmRespData[24];
1438 uint8x ntRespData[24];
1439 char *d = strdup (GetUnicodeString (challenge, uDomain));
1440 char *domain = d;
1441 char *u = strdup (user);
1442 char *p = strchr (u, '@');
1443
1444 if (p)
1445   {
1446   domain = p + 1;
1447   *p = '\0';
1448   }
1449
1450 spa_smb_encrypt (US password, challenge->challengeData, lmRespData);
1451 spa_smb_nt_encrypt (US password, challenge->challengeData, ntRespData);
1452
1453 response->bufIndex = 0;
1454 memcpy (response->ident, "NTLMSSP\0\0\0", 8);
1455 SIVAL (&response->msgType, 0, 3);
1456
1457 spa_bytes_add (response, lmResponse, lmRespData, 24);
1458 spa_bytes_add (response, ntResponse, ntRespData, 24);
1459 spa_unicode_add_string (response, uDomain, domain);
1460 spa_unicode_add_string (response, uUser, u);
1461 spa_unicode_add_string (response, uWks, u);
1462 spa_string_add (response, sessionKey, NULL);
1463
1464 response->flags = challenge->flags;
1465
1466 free (d);
1467 free (u);
1468 }
1469 #endif
1470
1471
1472 /* This is the re-organized version (see comments above) */
1473
1474 void
1475 spa_build_auth_response (SPAAuthChallenge * challenge,
1476                         SPAAuthResponse * response, char *user,
1477                         char *password)
1478 {
1479 uint8x lmRespData[24];
1480 uint8x ntRespData[24];
1481 uint32x cf = IVAL(&challenge->flags, 0);
1482 char *u = strdup (user);
1483 char *p = strchr (u, '@');
1484 char *d = NULL;
1485 char *domain;
1486
1487 if (p)
1488   {
1489   domain = p + 1;
1490   *p = '\0';
1491   }
1492
1493 else domain = d = strdup((cf & 0x1)?
1494   CCS GetUnicodeString(challenge, uDomain) :
1495   CCS GetString(challenge, uDomain));
1496
1497 spa_smb_encrypt (US password, challenge->challengeData, lmRespData);
1498 spa_smb_nt_encrypt (US password, challenge->challengeData, ntRespData);
1499
1500 response->bufIndex = 0;
1501 memcpy (response->ident, "NTLMSSP\0\0\0", 8);
1502 SIVAL (&response->msgType, 0, 3);
1503
1504 spa_bytes_add (response, lmResponse, lmRespData, (cf & 0x200) ? 24 : 0);
1505 spa_bytes_add (response, ntResponse, ntRespData, (cf & 0x8000) ? 24 : 0);
1506
1507 if (cf & 0x1) {      /* Unicode Text */
1508      spa_unicode_add_string (response, uDomain, domain);
1509      spa_unicode_add_string (response, uUser, u);
1510      spa_unicode_add_string (response, uWks, u);
1511 } else {             /* OEM Text */
1512      spa_string_add (response, uDomain, domain);
1513      spa_string_add (response, uUser, u);
1514      spa_string_add (response, uWks, u);
1515 }
1516
1517 spa_string_add (response, sessionKey, NULL);
1518 response->flags = challenge->flags;
1519
1520 if (d != NULL) free (d);
1521 free (u);
1522 }