1 /* $Cambridge: exim/src/src/auths/auth-spa.c,v 1.1 2004/10/07 13:10:00 ph10 Exp $ */
3 /*************************************************
4 * Exim - an Internet mail transport agent *
5 *************************************************/
8 * This file provides the necessary methods for authenticating with
9 * Microsoft's Secure Password Authentication.
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).
14 * Tom Kistner provided additional code, adding spa_build_auth_challenge() to
15 * support server authentication mode.
17 * Mark Lyda provided a patch to solve this problem:
19 - Exim is indicating in its Authentication Request message (Type 1) that it
20 can transmit text in either Unicode or OEM format.
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.
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.
29 * http://www.innovation.ch/java/ntlm.html
30 * http://www.kuro5hin.org/story/2002/4/28/1436/66154
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.
37 * typedef signed short int16;
38 * typedef unsigned short uint16;
39 * typedef unsigned uint32;
40 * typedef unsigned char uint8;
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.
51 int main (int argc, char ** argv)
53 SPAAuthRequest request;
54 SPAAuthChallenge challenge;
55 SPAAuthResponse response;
58 char *username, *password, *domain, *challenge_str;
62 printf ("Usage: %s <username> <password> [SPA Challenge]\n",
71 spa_build_auth_request (&request, username, domain);
73 spa_bits_to_base64 (msgbuf, (unsigned char*)&request,
74 spa_request_length(&request));
76 printf ("SPA Login request for username=%s:\n %s\n",
81 printf ("Run: %s <username> <password> [NTLM Challenge] " \
82 "to complete authenitcation\n", argv [0]);
86 challenge_str = argv [3];
88 spa_build_auth_response (&challenge, &response, username, password);
89 spa_bits_to_base64 (msgbuf, (unsigned char*)&response,
90 spa_request_length(&response));
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);
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:
105 Unix SMB/Netbios implementation.
108 a partial implementation of DES designed for use in the
109 SMB authentication protocol
111 Copyright (C) Andrew Tridgell 1998
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.
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.
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.
131 This code makes no attempt to be fast! In fact, it is a very
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)
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.
142 There is no entry point into this code that allows normal DES operation.
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)
153 extern int DEBUGLEVEL;
155 #include <sys/types.h> /* For size_t */
156 #include "auth-spa.h"
166 typedef unsigned char uchar;
177 #define RW_PCVAL(read,inbuf,outbuf,len) \
178 { if (read) { PCVAL (inbuf,0,outbuf,len); } \
179 else { PSCVAL(inbuf,0,outbuf,len); } }
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); } } }
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); } } }
189 #define RW_CVAL(read, inbuf, outbuf, offset) \
190 { if (read) { (outbuf) = CVAL (inbuf,offset); } \
191 else { SCVAL(inbuf,offset,outbuf); } }
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); } } }
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); } } }
201 #undef CAREFUL_ALIGNMENT
203 /* we know that the 386 can handle misalignment and has the "right"
206 #define CAREFUL_ALIGNMENT 0
209 #ifndef CAREFUL_ALIGNMENT
210 #define CAREFUL_ALIGNMENT 1
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))
218 #if CAREFUL_ALIGNMENT
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)))
231 #else /* CAREFUL_ALIGNMENT */
233 /* this handles things for architectures like the 386 that can handle
236 WARNING: This section is dependent on the length of int16x and int32x
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)))
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))
252 #endif /* CAREFUL_ALIGNMENT */
254 /* macros for reading / writing arrays */
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); }
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]); }
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)
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)
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)))
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))
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)
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)
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])); } } \
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])); } } \
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])); } } \
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)); }
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)); }
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)); }
343 #endif /* _BYTEORDER_H */
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]);
350 void mdfour (unsigned char *out, unsigned char *in, int n);
354 * base64.c -- base-64 conversion routines.
356 * For license terms, see the file COPYING in this directory.
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
363 static const char base64digits[] =
364 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
367 static const char base64val[] = {
368 BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD,
370 BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD,
372 BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, 62, BAD, BAD, BAD,
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
380 #define DECODE64(c) (isascii(c) ? base64val[c] : BAD)
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) */
386 for (; inlen >= 3; inlen -= 3)
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];
396 unsigned char fragment;
398 *out++ = base64digits[in[0] >> 2];
399 fragment = (in[0] << 4) & 0x30;
401 fragment |= in[1] >> 4;
402 *out++ = base64digits[fragment];
403 *out++ = (inlen < 2) ? '=' : base64digits[(in[1] << 2) & 0x3c];
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 */
414 register unsigned char digit1, digit2, digit3, digit4;
416 if (in[0] == '+' && in[1] == ' ')
424 if (DECODE64 (digit1) == BAD)
427 if (DECODE64 (digit2) == BAD)
430 if (digit3 != '=' && DECODE64 (digit3) == BAD)
433 if (digit4 != '=' && DECODE64 (digit4) == BAD)
436 *out++ = (DECODE64 (digit1) << 2) | (DECODE64 (digit2) >> 4);
441 ((DECODE64 (digit2) << 4) & 0xf0) | (DECODE64 (digit3) >> 2);
445 *out++ = ((DECODE64 (digit3) << 6) & 0xc0) | DECODE64 (digit4);
450 while (*in && *in != '\r' && digit4 != '=');
456 #define uchar unsigned char
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
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
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
488 static uchar perm4[48] = { 32, 1, 2, 3, 4, 5,
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
498 static uchar perm5[32] = { 16, 7, 20, 21,
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
520 static uchar sc[16] = { 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 };
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}},
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}},
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}},
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}},
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}},
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}},
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}},
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}}
565 permute (char *out, char *in, uchar * p, int n)
568 for (i = 0; i < n; i++)
569 out[i] = in[p[i] - 1];
573 lshift (char *d, int count, int n)
577 for (i = 0; i < n; i++)
578 out[i] = d[(i + count) % n];
579 for (i = 0; i < n; i++)
584 concat (char *out, char *in1, char *in2, int l1, int l2)
593 xor (char *out, char *in1, char *in2, int n)
596 for (i = 0; i < n; i++)
597 out[i] = in1[i] ^ in2[i];
601 dohash (char *out, char *in, char *key, int forw)
613 permute (pk1, key, perm1, 56);
615 for (i = 0; i < 28; i++)
617 for (i = 0; i < 28; i++)
620 for (i = 0; i < 16; i++)
622 lshift (c, sc[i], 28);
623 lshift (d, sc[i], 28);
625 concat (cd, c, d, 28, 28);
626 permute (ki[i], cd, perm2, 48);
629 permute (pd1, in, perm3, 64);
631 for (j = 0; j < 32; j++)
637 for (i = 0; i < 16; i++)
646 permute (er, r, perm4, 48);
648 xor (erk, er, ki[forw ? i : 15 - i], 48);
650 for (j = 0; j < 8; j++)
651 for (k = 0; k < 6; k++)
652 b[j][k] = erk[j * 6 + k];
654 for (j = 0; j < 8; j++)
657 m = (b[j][0] << 1) | b[j][5];
659 n = (b[j][1] << 3) | (b[j][2] << 2) | (b[j][3] << 1) | b[j][4];
661 for (k = 0; k < 4; k++)
662 b[j][k] = (sbox[j][m][n] & (1 << (3 - k))) ? 1 : 0;
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);
670 xor (r2, l, pcb, 32);
672 for (j = 0; j < 32; j++)
675 for (j = 0; j < 32; j++)
679 concat (rl, r, l, 32, 32);
681 permute (out, rl, perm6, 64);
685 str_to_key (unsigned char *str, unsigned char *key)
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++)
699 key[i] = (key[i] << 1);
705 smbhash (unsigned char *out, unsigned char *in, unsigned char *key, int forw)
711 unsigned char key2[8];
713 str_to_key (key, key2);
715 for (i = 0; i < 64; i++)
717 inb[i] = (in[i / 8] & (1 << (7 - (i % 8)))) ? 1 : 0;
718 keyb[i] = (key2[i / 8] & (1 << (7 - (i % 8)))) ? 1 : 0;
722 dohash (outb, inb, keyb, forw);
724 for (i = 0; i < 8; i++)
729 for (i = 0; i < 64; i++)
732 out[i / 8] |= (1 << (7 - (i % 8)));
737 E_P16 (unsigned char *p14, unsigned char *p16)
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);
745 E_P24 (unsigned char *p21, unsigned char *c8, unsigned char *p24)
747 smbhash (p24, c8, p21, 1);
748 smbhash (p24 + 8, c8, p21 + 7, 1);
749 smbhash (p24 + 16, c8, p21 + 14, 1);
753 D_P16 (unsigned char *p14, unsigned char *in, unsigned char *out)
755 smbhash (out, in, p14, 0);
756 smbhash (out + 8, in + 8, p14 + 7, 0);
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 ****************************************************************************/
765 StrnCpy (char *dest, const char *src, size_t n)
775 while (n-- && (*d++ = *src++));
781 skip_multibyte_char (char c)
783 /* bogus if to get rid of unused compiler warning */
791 /*******************************************************************
792 safe string copy into a known length string. maxlength does not
793 include the terminating zero.
794 ********************************************************************/
797 safe_strcpy (char *dest, const char *src, size_t maxlength)
803 DEBUG (0, ("ERROR: NULL dest in safe_strcpy\n"));
817 DEBUG (0, ("ERROR: string overflow by %d in safe_strcpy [%.50s]\n",
818 (int) (len - maxlength), src));
822 memcpy (dest, src, len);
834 size_t skip = skip_multibyte_char (*s);
839 if (islower ((unsigned char)(*s)))
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
855 spa_smb_encrypt (uchar * passwd, uchar * c8, uchar * p24)
857 uchar p14[15], p21[21];
859 memset (p21, '\0', 21);
860 memset (p14, '\0', 14);
861 StrnCpy ((char *) p14, (char *) passwd, 14);
863 strupper ((char *) p14);
866 SMBOWFencrypt (p21, c8, p24);
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);
876 /* Routines for Windows NT MD4 Hash functions. */
878 _my_wcslen (int16x * str)
887 * Convert a string into an NT UNICODE string.
888 * Note that regardless of processor type
889 * this must be in intel (little-endian)
894 _my_mbstowcs (int16x * dst, uchar * src, int len)
899 for (i = 0; i < len; i++)
912 * Creates the MD4 Hash of the users password in NT UNICODE.
916 E_md4hash (uchar * passwd, uchar * p16)
921 /* Password cannot be longer than 128 characters */
922 len = strlen ((char *) passwd);
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);
931 mdfour (p16, (unsigned char *) wpwd, len);
934 /* Does both the NT and LM owfs of a user's password */
936 nt_lm_owf_gen (char *pwd, uchar nt_p16[16], uchar p16[16])
940 memset (passwd, '\0', 130);
941 safe_strcpy (passwd, pwd, sizeof (passwd) - 1);
943 /* Calculate the MD4 hash (NT compatible) of the password */
944 memset (nt_p16, '\0', 16);
945 E_md4hash ((uchar *) passwd, nt_p16);
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);
953 /* Mangle the passwords into Lanman format */
957 /* Calculate the SMB (lanman) hash functions of the password */
959 memset (p16, '\0', 16);
960 E_P16 ((uchar *) passwd, (uchar *) p16);
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);
967 /* clear out local copy of user's password (just being paranoid). */
968 memset (passwd, '\0', sizeof (passwd));
971 /* Does the des encryption from the NT or LM MD4 hash. */
973 SMBOWFencrypt (uchar passwd[16], uchar * c8, uchar p24[24])
977 memset (p21, '\0', 21);
979 memcpy (p21, passwd, 16);
980 E_P24 (p21, c8, p24);
983 /* Does the des encryption from the FIRST 8 BYTES of the NT or LM MD4 hash. */
985 NTLMSSPOWFencrypt (uchar passwd[8], uchar * ntlmchalresp, uchar p24[24])
989 memset (p21, '\0', 21);
990 memcpy (p21, passwd, 8);
991 memset (p21 + 8, 0xbd, 8);
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);
1003 /* Does the NT MD4 hash then des encryption. */
1006 spa_smb_nt_encrypt (uchar * passwd, uchar * c8, uchar * p24)
1010 memset (p21, '\0', 21);
1012 E_md4hash (passwd, p21);
1013 SMBOWFencrypt (p21, c8, p24);
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);
1023 static uint32x A, B, C, D;
1026 F (uint32x X, uint32x Y, uint32x Z)
1028 return (X & Y) | ((~X) & Z);
1032 G (uint32x X, uint32x Y, uint32x Z)
1034 return (X & Y) | (X & Z) | (Y & Z);
1038 H (uint32x X, uint32x Y, uint32x Z)
1044 lshift_a (uint32x x, int s)
1047 return ((x << s) & 0xFFFFFFFF) | (x >> (32 - s));
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)
1054 /* this applies md4 to 64 byte chunks */
1056 spa_mdfour64 (uint32x * M)
1059 uint32x AA, BB, CC, DD;
1062 for (j = 0; j < 16; j++)
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);
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);
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);
1131 for (j = 0; j < 16; j++)
1136 copy64 (uint32x * M, unsigned char *in)
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);
1146 copy4 (unsigned char *out, uint32x x)
1149 out[1] = (x >> 8) & 0xFF;
1150 out[2] = (x >> 16) & 0xFF;
1151 out[3] = (x >> 24) & 0xFF;
1154 /* produce a md4 message digest from data of length n bytes */
1156 mdfour (unsigned char *out, unsigned char *in, int n)
1158 unsigned char buf[128];
1176 for (i = 0; i < 128; i++)
1178 memcpy (buf, in, n);
1183 copy4 (buf + 56, b);
1189 copy4 (buf + 120, b);
1192 copy64 (M, buf + 64);
1196 for (i = 0; i < 128; i++)
1203 copy4 (out + 12, D);
1208 char versionString[] = "libntlm version 0.21";
1210 /* Utility routines that handle NTLM auth structures. */
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.
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
1223 #define spa_bytes_add(ptr, header, buf, count) \
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; \
1236 ptr->header.maxlen = 0; \
1237 SIVAL(&ptr->header.offset,0,((ptr->buffer - ((uint8x*)ptr)) + ptr->bufIndex)); \
1241 #define spa_string_add(ptr, header, string) \
1245 if (p) len = strlen(p); \
1246 spa_bytes_add(ptr, header, ((unsigned char*)p), len); \
1249 #define spa_unicode_add_string(ptr, header, string) \
1252 unsigned char *b = NULL; \
1257 b = strToUnicode(p); \
1259 spa_bytes_add(ptr, header, b, len*2); \
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))
1272 dumpRaw (FILE * fp, unsigned char *buf, size_t len)
1276 for (i = 0; i < len; ++i)
1277 fprintf (fp, "%02x ", buf[i]);
1283 unicodeToString (char *p, size_t len)
1286 static char buf[1024];
1288 assert (len + 1 < sizeof buf);
1290 for (i = 0; i < len; ++i)
1300 static unsigned char *
1301 strToUnicode (char *p)
1303 static unsigned char buf[1024];
1304 size_t l = strlen (p);
1307 assert (l * 2 < sizeof buf);
1318 static unsigned char *
1319 toString (char *p, size_t len)
1321 static unsigned char buf[1024];
1323 assert (len + 1 < sizeof buf);
1325 memcpy (buf, p, len);
1331 dumpSmbNtlmAuthRequest (FILE * fp, SPAAuthRequest * request)
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));
1342 dumpSmbNtlmAuthChallenge (FILE * fp, SPAAuthChallenge * challenge)
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);
1354 dumpSmbNtlmAuthResponse (FILE * fp, SPAAuthResponse * response)
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));
1372 spa_build_auth_request (SPAAuthRequest * request, char *user, char *domain)
1374 char *u = strdup (user);
1375 char *p = strchr (u, '@');
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);
1396 spa_build_auth_challenge (SPAAuthRequest * request, SPAAuthChallenge * challenge)
1400 int p = (int)getpid();
1401 int random_seed = (int)time(NULL) ^ ((p << 16) | p);
1403 request = request; /* Added by PH to stop compilers whinging */
1405 /* Ensure challenge data is cleared, in case it isn't all used. This
1406 patch added by PH on suggestion of Russell King */
1408 memset(challenge, 0, sizeof(SPAAuthChallenge));
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);
1418 /* generate eight pseudo random bytes (method ripped from host.c) */
1421 chalstr[i] = (unsigned char)(random_seed >> 16) % 256;
1422 random_seed = (1103515245 - (chalstr[i])) * random_seed + 12345;
1425 memcpy(challenge->challengeData,chalstr,8);
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. */
1439 spa_build_auth_response (SPAAuthChallenge * challenge,
1440 SPAAuthResponse * response, char *user,
1443 uint8x lmRespData[24];
1444 uint8x ntRespData[24];
1445 char *d = strdup (GetUnicodeString (challenge, uDomain));
1447 char *u = strdup (user);
1448 char *p = strchr (u, '@');
1456 spa_smb_encrypt ((uchar *)password, challenge->challengeData, lmRespData);
1457 spa_smb_nt_encrypt ((uchar *)password, challenge->challengeData, ntRespData);
1459 response->bufIndex = 0;
1460 memcpy (response->ident, "NTLMSSP\0\0\0", 8);
1461 SIVAL (&response->msgType, 0, 3);
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);
1470 response->flags = challenge->flags;
1478 /* This is the re-organized version (see comments above) */
1481 spa_build_auth_response (SPAAuthChallenge * challenge,
1482 SPAAuthResponse * response, char *user,
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, '@');
1499 else domain = d = strdup((cf & 0x1)?
1500 (const char *)GetUnicodeString(challenge, uDomain) :
1501 (const char *)GetString(challenge, uDomain));
1503 spa_smb_encrypt ((uchar *)password, challenge->challengeData, lmRespData);
1504 spa_smb_nt_encrypt ((uchar *)password, challenge->challengeData, ntRespData);
1506 response->bufIndex = 0;
1507 memcpy (response->ident, "NTLMSSP\0\0\0", 8);
1508 SIVAL (&response->msgType, 0, 3);
1510 spa_bytes_add (response, lmResponse, lmRespData, (cf & 0x200) ? 24 : 0);
1511 spa_bytes_add (response, ntResponse, ntRespData, (cf & 0x8000) ? 24 : 0);
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);
1523 spa_string_add (response, sessionKey, NULL);
1524 response->flags = challenge->flags;
1526 if (d != NULL) free (d);