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