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