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