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