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