1 /*************************************************
2 * Exim - an Internet mail transport agent *
3 *************************************************/
6 * This file provides the necessary methods for authenticating with
7 * Microsoft's Secure Password Authentication.
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).
12 * Copyright (c) The Exim Maintainers 2021
13 * SPDX-License-Identifier: GPL-2.0-or-later
15 * Tom Kistner provided additional code, adding spa_build_auth_challenge() to
16 * support server authentication mode.
18 * Mark Lyda provided a patch to solve this problem:
20 - Exim is indicating in its Authentication Request message (Type 1) that it
21 can transmit text in either Unicode or OEM format.
23 - Microsoft's SMTP server (smtp.email.msn.com) is responding in its
24 Challenge message (Type 2) that it will be expecting the OEM format.
26 - Exim does not pay attention to the text format requested by Microsoft's
27 SMTP server and, instead, defaults to using the Unicode format.
30 * http://www.innovation.ch/java/ntlm.html
31 * http://www.kuro5hin.org/story/2002/4/28/1436/66154
33 * It seems that some systems have existing but different definitions of some
34 * of the following types. I received a complaint about "int16" causing
35 * compilation problems. So I (PH) have renamed them all, to be on the safe
36 * side, by adding 'x' on the end.
38 * typedef signed short int16;
39 * typedef unsigned short uint16;
40 * typedef unsigned uint32;
41 * typedef unsigned char uint8;
43 * The API is extremely simple:
44 * 1. Form a SPA authentication request based on the username
45 * and (optional) domain
46 * 2. Send the request to the server and get an SPA challenge
47 * 3. Build the challenge response and send it back.
52 int main (int argc, char ** argv)
54 SPAAuthRequest request;
55 SPAAuthChallenge challenge;
56 SPAAuthResponse response;
59 char *username, *password, *domain, *challenge_str;
63 printf ("Usage: %s <username> <password> [SPA Challenge]\n",
72 spa_build_auth_request (&request, username, domain);
74 spa_bits_to_base64 (msgbuf, US &request,
75 spa_request_length(&request));
77 printf ("SPA Login request for username=%s:\n %s\n",
82 printf ("Run: %s <username> <password> [NTLM Challenge] " \
83 "to complete authenitcation\n", argv [0]);
87 challenge_str = argv [3];
89 if (spa_base64_to_bits (CS &challenge, sizeof(challenge),
90 CCS (challenge_str))<0)
92 printf("bad base64 data in challenge: %s\n", challenge_str);
96 spa_build_auth_response (&challenge, &response, username, password);
97 spa_bits_to_base64 (msgbuf, US &response,
98 spa_request_length(&response));
100 printf ("SPA Response to challenge:\n %s\n for " \
101 "username=%s, password=%s:\n %s\n",
102 argv[3], argv [1], argv [2], msgbuf);
107 * All the client code used here was torn by Marc Prud'hommeaux out of the
108 * Samba project (by Andrew Tridgell, Jeremy Allison, and others).
109 * Previous comments are below:
113 Unix SMB/Netbios implementation.
116 a partial implementation of DES designed for use in the
117 SMB authentication protocol
119 Copyright (C) Andrew Tridgell 1998
121 This program is free software; you can redistribute it and/or modify
122 it under the terms of the GNU General Public License as published by
123 the Free Software Foundation; either version 2 of the License, or
124 (at your option) any later version.
126 This program is distributed in the hope that it will be useful,
127 but WITHOUT ANY WARRANTY; without even the implied warranty of
128 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
129 GNU General Public License for more details.
131 You should have received a copy of the GNU General Public License
132 along with this program; if not, write to the Free Software
133 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
139 This code makes no attempt to be fast! In fact, it is a very
142 This code is NOT a complete DES implementation. It implements only
143 the minimum necessary for SMB authentication, as used by all SMB
144 products (including every copy of Microsoft Windows95 ever sold)
146 In particular, it can only do a unchained forward DES pass. This
147 means it is not possible to use this code for encryption/decryption
148 of data, instead it is only useful as a "hash" algorithm.
150 There is no entry point into this code that allows normal DES operation.
152 I believe this means that this code does not come under ITAR
153 regulations but this is NOT a legal opinion. If you are concerned
154 about the applicability of ITAR regulations to this code then you
155 should confirm it for yourself (and maybe let me know if you come
156 up with a different answer to the one above)
159 #define DEBUG_X(a,b) ;
161 extern int DEBUGLEVEL;
164 #include "auth-spa.h"
169 # define _BYTEORDER_H
171 # define RW_PCVAL(read,inbuf,outbuf,len) \
172 { if (read) { PCVAL (inbuf,0,outbuf,len); } \
173 else { PSCVAL(inbuf,0,outbuf,len); } }
175 # define RW_PIVAL(read,big_endian,inbuf,outbuf,len) \
176 { if (read) { if (big_endian) { RPIVAL(inbuf,0,outbuf,len); } else { PIVAL(inbuf,0,outbuf,len); } } \
177 else { if (big_endian) { RPSIVAL(inbuf,0,outbuf,len); } else { PSIVAL(inbuf,0,outbuf,len); } } }
179 # define RW_PSVAL(read,big_endian,inbuf,outbuf,len) \
180 { if (read) { if (big_endian) { RPSVAL(inbuf,0,outbuf,len); } else { PSVAL(inbuf,0,outbuf,len); } } \
181 else { if (big_endian) { RPSSVAL(inbuf,0,outbuf,len); } else { PSSVAL(inbuf,0,outbuf,len); } } }
183 # define RW_CVAL(read, inbuf, outbuf, offset) \
184 { if (read) { (outbuf) = CVAL (inbuf,offset); } \
185 else { SCVAL(inbuf,offset,outbuf); } }
187 # define RW_IVAL(read, big_endian, inbuf, outbuf, offset) \
188 { if (read) { (outbuf) = ((big_endian) ? RIVAL(inbuf,offset) : IVAL (inbuf,offset)); } \
189 else { if (big_endian) { RSIVAL(inbuf,offset,outbuf); } else { SIVAL(inbuf,offset,outbuf); } } }
191 # define RW_SVAL(read, big_endian, inbuf, outbuf, offset) \
192 { if (read) { (outbuf) = ((big_endian) ? RSVAL(inbuf,offset) : SVAL (inbuf,offset)); } \
193 else { if (big_endian) { RSSVAL(inbuf,offset,outbuf); } else { SSVAL(inbuf,offset,outbuf); } } }
195 # undef CAREFUL_ALIGNMENT
197 /* we know that the 386 can handle misalignment and has the "right"
200 # define CAREFUL_ALIGNMENT 0
203 # ifndef CAREFUL_ALIGNMENT
204 # define CAREFUL_ALIGNMENT 1
207 # define CVAL(buf,pos) ((US (buf))[pos])
208 # define PVAL(buf,pos) ((unsigned)CVAL(buf,pos))
209 # define SCVAL(buf,pos,val) (CVAL(buf,pos) = (val))
212 # if CAREFUL_ALIGNMENT
214 # define SVAL(buf,pos) (PVAL(buf,pos)|PVAL(buf,(pos)+1)<<8)
215 # define IVAL(buf,pos) (SVAL(buf,pos)|SVAL(buf,(pos)+2)<<16)
216 # define SSVALX(buf,pos,val) (CVAL(buf,pos)=(val)&0xFF,CVAL(buf,pos+1)=(val)>>8)
217 # define SIVALX(buf,pos,val) (SSVALX(buf,pos,val&0xFFFF),SSVALX(buf,pos+2,val>>16))
218 # define SVALS(buf,pos) ((int16x)SVAL(buf,pos))
219 # define IVALS(buf,pos) ((int32x)IVAL(buf,pos))
220 # define SSVAL(buf,pos,val) SSVALX((buf),(pos),((uint16x)(val)))
221 # define SIVAL(buf,pos,val) SIVALX((buf),(pos),((uint32x)(val)))
222 # define SSVALS(buf,pos,val) SSVALX((buf),(pos),((int16x)(val)))
223 # define SIVALS(buf,pos,val) SIVALX((buf),(pos),((int32x)(val)))
225 # else /* CAREFUL_ALIGNMENT */
227 /* this handles things for architectures like the 386 that can handle
230 WARNING: This section is dependent on the length of int16x and int32x
234 /* get single value from an SMB buffer */
235 # define SVAL(buf,pos) (*(uint16x *)(CS (buf) + (pos)))
236 # define IVAL(buf,pos) (*(uint32x *)(CS (buf) + (pos)))
237 # define SVALS(buf,pos) (*(int16x *)(CS (buf) + (pos)))
238 # define IVALS(buf,pos) (*(int32x *)(CS (buf) + (pos)))
240 /* store single value in an SMB buffer */
241 # define SSVAL(buf,pos,val) SVAL(buf,pos)=((uint16x)(val))
242 # define SIVAL(buf,pos,val) IVAL(buf,pos)=((uint32x)(val))
243 # define SSVALS(buf,pos,val) SVALS(buf,pos)=((int16x)(val))
244 # define SIVALS(buf,pos,val) IVALS(buf,pos)=((int32x)(val))
246 # endif /* CAREFUL_ALIGNMENT */
248 /* macros for reading / writing arrays */
250 # define SMBMACRO(macro,buf,pos,val,len,size) \
251 { for (int l = 0; l < (len); l++) (val)[l] = macro((buf), (pos) + (size)*l); }
253 # define SSMBMACRO(macro,buf,pos,val,len,size) \
254 { for (int l = 0; l < (len); l++) macro((buf), (pos) + (size)*l, (val)[l]); }
256 /* reads multiple data from an SMB buffer */
257 # define PCVAL(buf,pos,val,len) SMBMACRO(CVAL,buf,pos,val,len,1)
258 # define PSVAL(buf,pos,val,len) SMBMACRO(SVAL,buf,pos,val,len,2)
259 # define PIVAL(buf,pos,val,len) SMBMACRO(IVAL,buf,pos,val,len,4)
260 # define PCVALS(buf,pos,val,len) SMBMACRO(CVALS,buf,pos,val,len,1)
261 # define PSVALS(buf,pos,val,len) SMBMACRO(SVALS,buf,pos,val,len,2)
262 # define PIVALS(buf,pos,val,len) SMBMACRO(IVALS,buf,pos,val,len,4)
264 /* stores multiple data in an SMB buffer */
265 # define PSCVAL(buf,pos,val,len) SSMBMACRO(SCVAL,buf,pos,val,len,1)
266 # define PSSVAL(buf,pos,val,len) SSMBMACRO(SSVAL,buf,pos,val,len,2)
267 # define PSIVAL(buf,pos,val,len) SSMBMACRO(SIVAL,buf,pos,val,len,4)
268 # define PSCVALS(buf,pos,val,len) SSMBMACRO(SCVALS,buf,pos,val,len,1)
269 # define PSSVALS(buf,pos,val,len) SSMBMACRO(SSVALS,buf,pos,val,len,2)
270 # define PSIVALS(buf,pos,val,len) SSMBMACRO(SIVALS,buf,pos,val,len,4)
273 /* now the reverse routines - these are used in nmb packets (mostly) */
274 # define SREV(x) ((((x)&0xFF)<<8) | (((x)>>8)&0xFF))
275 # define IREV(x) ((SREV(x)<<16) | (SREV((x)>>16)))
277 # define RSVAL(buf,pos) SREV(SVAL(buf,pos))
278 # define RSVALS(buf,pos) SREV(SVALS(buf,pos))
279 # define RIVAL(buf,pos) IREV(IVAL(buf,pos))
280 # define RIVALS(buf,pos) IREV(IVALS(buf,pos))
281 # define RSSVAL(buf,pos,val) SSVAL(buf,pos,SREV(val))
282 # define RSSVALS(buf,pos,val) SSVALS(buf,pos,SREV(val))
283 # define RSIVAL(buf,pos,val) SIVAL(buf,pos,IREV(val))
284 # define RSIVALS(buf,pos,val) SIVALS(buf,pos,IREV(val))
286 /* reads multiple data from an SMB buffer (big-endian) */
287 # define RPSVAL(buf,pos,val,len) SMBMACRO(RSVAL,buf,pos,val,len,2)
288 # define RPIVAL(buf,pos,val,len) SMBMACRO(RIVAL,buf,pos,val,len,4)
289 # define RPSVALS(buf,pos,val,len) SMBMACRO(RSVALS,buf,pos,val,len,2)
290 # define RPIVALS(buf,pos,val,len) SMBMACRO(RIVALS,buf,pos,val,len,4)
292 /* stores multiple data in an SMB buffer (big-endian) */
293 # define RPSSVAL(buf,pos,val,len) SSMBMACRO(RSSVAL,buf,pos,val,len,2)
294 # define RPSIVAL(buf,pos,val,len) SSMBMACRO(RSIVAL,buf,pos,val,len,4)
295 # define RPSSVALS(buf,pos,val,len) SSMBMACRO(RSSVALS,buf,pos,val,len,2)
296 # define RPSIVALS(buf,pos,val,len) SSMBMACRO(RSIVALS,buf,pos,val,len,4)
298 # define DBG_RW_PCVAL(charmode,string,depth,base,read,inbuf,outbuf,len) \
299 { RW_PCVAL(read,inbuf,outbuf,len) \
300 DEBUG_X(5,("%s%04x %s: ", \
301 tab_depth(depth), base,string)); \
302 if (charmode) print_asc(5, US (outbuf), (len)); else \
303 for (int idx = 0; idx < len; idx++) { DEBUG_X(5,("%02x ", (outbuf)[idx])); } \
306 # define DBG_RW_PSVAL(charmode,string,depth,base,read,big_endian,inbuf,outbuf,len) \
307 { RW_PSVAL(read,big_endian,inbuf,outbuf,len) \
308 DEBUG_X(5,("%s%04x %s: ", \
309 tab_depth(depth), base,string)); \
310 if (charmode) print_asc(5, US (outbuf), 2*(len)); else \
311 for (int idx = 0; idx < len; idx++) { DEBUG_X(5,("%04x ", (outbuf)[idx])); } \
314 # define DBG_RW_PIVAL(charmode,string,depth,base,read,big_endian,inbuf,outbuf,len) \
315 { RW_PIVAL(read,big_endian,inbuf,outbuf,len) \
316 DEBUG_X(5,("%s%04x %s: ", \
317 tab_depth(depth), base,string)); \
318 if (charmode) print_asc(5, US (outbuf), 4*(len)); else \
319 for (int idx = 0; idx < len; idx++) { DEBUG_X(5,("%08x ", (outbuf)[idx])); } \
322 # define DBG_RW_CVAL(string,depth,base,read,inbuf,outbuf) \
323 { RW_CVAL(read,inbuf,outbuf,0) \
324 DEBUG_X(5,("%s%04x %s: %02x\n", \
325 tab_depth(depth), base, string, outbuf)); }
327 # define DBG_RW_SVAL(string,depth,base,read,big_endian,inbuf,outbuf) \
328 { RW_SVAL(read,big_endian,inbuf,outbuf,0) \
329 DEBUG_X(5,("%s%04x %s: %04x\n", \
330 tab_depth(depth), base, string, outbuf)); }
332 # define DBG_RW_IVAL(string,depth,base,read,big_endian,inbuf,outbuf) \
333 { RW_IVAL(read,big_endian,inbuf,outbuf,0) \
334 DEBUG_X(5,("%s%04x %s: %08x\n", \
335 tab_depth(depth), base, string, outbuf)); }
337 #endif /* _BYTEORDER_H */
339 void E_P16 (uschar *p14, uschar *p16);
340 void E_P24 (uschar *p21, uschar *c8, uschar *p24);
341 void D_P16 (uschar *p14, uschar *in, uschar *out);
342 void SMBOWFencrypt (uschar passwd[16], uschar * c8, uschar p24[24]);
344 void mdfour (uschar *out, uschar *in, int n);
348 * base64.c -- base-64 conversion routines.
350 * For license terms, see the file COPYING in this directory.
352 * This base 64 encoding is defined in RFC2045 section 6.8,
353 * "Base64 Content-Transfer-Encoding", but lines must not be broken in the
357 static const char base64digits[] =
358 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
360 #define BAD (char) -1
361 static const char base64val[] = {
362 BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD,
364 BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD,
366 BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, 62, BAD, BAD, BAD,
368 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, BAD, BAD, BAD, BAD, BAD, BAD,
369 BAD, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
370 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, BAD, BAD, BAD, BAD, BAD,
371 BAD, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
372 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, BAD, BAD, BAD, BAD, BAD
374 #define DECODE64(c) (isascii(c) ? base64val[c] : BAD)
377 spa_bits_to_base64 (uschar *out, const uschar *in, int inlen)
378 /* raw bytes in quasi-big-endian order to base 64 string (NUL-terminated) */
380 for (; inlen >= 3; inlen -= 3)
382 *out++ = base64digits[in[0] >> 2];
383 *out++ = base64digits[((in[0] << 4) & 0x30) | (in[1] >> 4)];
384 *out++ = base64digits[((in[1] << 2) & 0x3c) | (in[2] >> 6)];
385 *out++ = base64digits[in[2] & 0x3f];
392 *out++ = base64digits[in[0] >> 2];
393 fragment = (in[0] << 4) & 0x30;
395 fragment |= in[1] >> 4;
396 *out++ = base64digits[fragment];
397 *out++ = (inlen < 2) ? '=' : base64digits[(in[1] << 2) & 0x3c];
404 /* The outlength parameter was added by PH, December 2004 */
407 spa_base64_to_bits (char *out, int outlength, const char *in)
408 /* base 64 to raw bytes in quasi-big-endian order, returning count of bytes */
411 uschar digit1, digit2, digit3, digit4;
413 if (in[0] == '+' && in[1] == ' ')
420 if (len >= outlength) /* Added by PH */
421 return -1; /* Added by PH */
423 if (DECODE64 (digit1) == BAD)
426 if (DECODE64 (digit2) == BAD)
429 if (digit3 != '=' && DECODE64 (digit3) == BAD)
432 if (digit4 != '=' && DECODE64 (digit4) == BAD)
435 *out++ = (DECODE64 (digit1) << 2) | (DECODE64 (digit2) >> 4);
439 if (len >= outlength) /* Added by PH */
440 return -1; /* Added by PH */
442 ((DECODE64 (digit2) << 4) & 0xf0) | (DECODE64 (digit3) >> 2);
446 if (len >= outlength) /* Added by PH */
447 return -1; /* Added by PH */
448 *out++ = ((DECODE64 (digit3) << 6) & 0xc0) | DECODE64 (digit4);
453 while (*in && *in != '\r' && digit4 != '=');
459 static uschar perm1[56] = { 57, 49, 41, 33, 25, 17, 9,
460 1, 58, 50, 42, 34, 26, 18,
461 10, 2, 59, 51, 43, 35, 27,
462 19, 11, 3, 60, 52, 44, 36,
463 63, 55, 47, 39, 31, 23, 15,
464 7, 62, 54, 46, 38, 30, 22,
465 14, 6, 61, 53, 45, 37, 29,
466 21, 13, 5, 28, 20, 12, 4
469 static uschar perm2[48] = { 14, 17, 11, 24, 1, 5,
470 3, 28, 15, 6, 21, 10,
471 23, 19, 12, 4, 26, 8,
472 16, 7, 27, 20, 13, 2,
473 41, 52, 31, 37, 47, 55,
474 30, 40, 51, 45, 33, 48,
475 44, 49, 39, 56, 34, 53,
476 46, 42, 50, 36, 29, 32
479 static uschar perm3[64] = { 58, 50, 42, 34, 26, 18, 10, 2,
480 60, 52, 44, 36, 28, 20, 12, 4,
481 62, 54, 46, 38, 30, 22, 14, 6,
482 64, 56, 48, 40, 32, 24, 16, 8,
483 57, 49, 41, 33, 25, 17, 9, 1,
484 59, 51, 43, 35, 27, 19, 11, 3,
485 61, 53, 45, 37, 29, 21, 13, 5,
486 63, 55, 47, 39, 31, 23, 15, 7
489 static uschar perm4[48] = { 32, 1, 2, 3, 4, 5,
491 8, 9, 10, 11, 12, 13,
492 12, 13, 14, 15, 16, 17,
493 16, 17, 18, 19, 20, 21,
494 20, 21, 22, 23, 24, 25,
495 24, 25, 26, 27, 28, 29,
496 28, 29, 30, 31, 32, 1
499 static uschar perm5[32] = { 16, 7, 20, 21,
510 static uschar perm6[64] = { 40, 8, 48, 16, 56, 24, 64, 32,
511 39, 7, 47, 15, 55, 23, 63, 31,
512 38, 6, 46, 14, 54, 22, 62, 30,
513 37, 5, 45, 13, 53, 21, 61, 29,
514 36, 4, 44, 12, 52, 20, 60, 28,
515 35, 3, 43, 11, 51, 19, 59, 27,
516 34, 2, 42, 10, 50, 18, 58, 26,
517 33, 1, 41, 9, 49, 17, 57, 25
521 static uschar sc[16] = { 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 };
523 static uschar sbox[8][4][16] = {
524 {{14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7},
525 {0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8},
526 {4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0},
527 {15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13}},
529 {{15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10},
530 {3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5},
531 {0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15},
532 {13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9}},
534 {{10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8},
535 {13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1},
536 {13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7},
537 {1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12}},
539 {{7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15},
540 {13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9},
541 {10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4},
542 {3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14}},
544 {{2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9},
545 {14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6},
546 {4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14},
547 {11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3}},
549 {{12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11},
550 {10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8},
551 {9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6},
552 {4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13}},
554 {{4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1},
555 {13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6},
556 {1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2},
557 {6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12}},
559 {{13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7},
560 {1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2},
561 {7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8},
562 {2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11}}
566 permute (char *out, char *in, uschar * p, int n)
568 for (int i = 0; i < n; i++)
569 out[i] = in[p[i] - 1];
573 lshift (char *d, int count, int n)
576 for (int i = 0; i < n; i++)
577 out[i] = d[(i + count) % n];
578 for (int i = 0; i < n; i++)
583 concat (char *out, char *in1, char *in2, int l1, int l2)
592 xor (char *out, char *in1, char *in2, int n)
594 for (int i = 0; i < n; i++)
595 out[i] = in1[i] ^ in2[i];
599 dohash (char *out, char *in, char *key, int forw)
611 permute (pk1, key, perm1, 56);
613 for (i = 0; i < 28; i++)
615 for (i = 0; i < 28; i++)
618 for (i = 0; i < 16; i++)
620 lshift (c, sc[i], 28);
621 lshift (d, sc[i], 28);
623 concat (cd, c, d, 28, 28);
624 permute (ki[i], cd, perm2, 48);
627 permute (pd1, in, perm3, 64);
629 for (j = 0; j < 32; j++)
635 for (i = 0; i < 16; i++)
644 permute (er, r, perm4, 48);
646 xor (erk, er, ki[forw ? i : 15 - i], 48);
648 for (j = 0; j < 8; j++)
649 for (k = 0; k < 6; k++)
650 b[j][k] = erk[j * 6 + k];
652 for (j = 0; j < 8; j++)
655 m = (b[j][0] << 1) | b[j][5];
657 n = (b[j][1] << 3) | (b[j][2] << 2) | (b[j][3] << 1) | b[j][4];
659 for (k = 0; k < 4; k++)
660 b[j][k] = (sbox[j][m][n] & (1 << (3 - k))) ? 1 : 0;
663 for (j = 0; j < 8; j++)
664 for (k = 0; k < 4; k++)
665 cb[j * 4 + k] = b[j][k];
666 permute (pcb, cb, perm5, 32);
668 xor (r2, l, pcb, 32);
670 for (j = 0; j < 32; j++)
673 for (j = 0; j < 32; j++)
677 concat (rl, r, l, 32, 32);
679 permute (out, rl, perm6, 64);
683 str_to_key (uschar *str, uschar *key)
687 key[0] = str[0] >> 1;
688 key[1] = ((str[0] & 0x01) << 6) | (str[1] >> 2);
689 key[2] = ((str[1] & 0x03) << 5) | (str[2] >> 3);
690 key[3] = ((str[2] & 0x07) << 4) | (str[3] >> 4);
691 key[4] = ((str[3] & 0x0F) << 3) | (str[4] >> 5);
692 key[5] = ((str[4] & 0x1F) << 2) | (str[5] >> 6);
693 key[6] = ((str[5] & 0x3F) << 1) | (str[6] >> 7);
694 key[7] = str[6] & 0x7F;
695 for (i = 0; i < 8; i++)
696 key[i] = (key[i] << 1);
701 smbhash (uschar *out, uschar *in, uschar *key, int forw)
709 str_to_key (key, key2);
711 for (i = 0; i < 64; i++)
713 inb[i] = (in[i / 8] & (1 << (7 - (i % 8)))) ? 1 : 0;
714 keyb[i] = (key2[i / 8] & (1 << (7 - (i % 8)))) ? 1 : 0;
718 dohash (outb, inb, keyb, forw);
720 for (i = 0; i < 8; i++)
723 for (i = 0; i < 64; i++)
725 out[i / 8] |= (1 << (7 - (i % 8)));
729 E_P16 (uschar *p14, uschar *p16)
731 uschar sp8[8] = { 0x4b, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 };
732 smbhash (p16, sp8, p14, 1);
733 smbhash (p16 + 8, sp8, p14 + 7, 1);
737 E_P24 (uschar *p21, uschar *c8, uschar *p24)
739 smbhash (p24, c8, p21, 1);
740 smbhash (p24 + 8, c8, p21 + 7, 1);
741 smbhash (p24 + 16, c8, p21 + 14, 1);
745 D_P16 (uschar *p14, uschar *in, uschar *out)
747 smbhash (out, in, p14, 0);
748 smbhash (out + 8, in + 8, p14 + 7, 0);
751 /****************************************************************************
752 Like strncpy but always null terminates. Make sure there is room!
753 The variable n should always be one less than the available size.
754 ****************************************************************************/
757 StrnCpy (char *dest, const char *src, size_t n)
767 while (n-- && (*d++ = *src++));
773 skip_multibyte_char (char c)
775 /* bogus if to get rid of unused compiler warning */
783 /*******************************************************************
784 safe string copy into a known length string. maxlength does not
785 include the terminating zero.
786 ********************************************************************/
789 safe_strcpy (char *dest, const char *src, size_t maxlength)
795 DEBUG_X (0, ("ERROR: NULL dest in safe_strcpy\n"));
809 DEBUG_X (0, ("ERROR: string overflow by %d in safe_strcpy [%.50s]\n",
810 (int) (len - maxlength), src));
814 memcpy (dest, src, len);
825 size_t skip = skip_multibyte_char (*s);
830 if (islower ((uschar)(*s)))
839 This implements the X/Open SMB password encryption
840 It takes a password, a 8 byte "crypt key" and puts 24 bytes of
841 encrypted password into p24
845 spa_smb_encrypt (uschar * passwd, uschar * c8, uschar * p24)
847 uschar p14[15], p21[21];
849 memset (p21, '\0', 21);
850 memset (p14, '\0', 14);
851 StrnCpy (CS p14, CS passwd, 14);
856 SMBOWFencrypt (p21, c8, p24);
858 #ifdef DEBUG_PASSWORD
859 DEBUG_X (100, ("spa_smb_encrypt: lm#, challenge, response\n"));
860 dump_data (100, CS p21, 16);
861 dump_data (100, CS c8, 8);
862 dump_data (100, CS p24, 24);
866 /* Routines for Windows NT MD4 Hash functions. */
868 _my_wcslen (int16x * str)
877 * Convert a string into an NT UNICODE string.
878 * Note that regardless of processor type
879 * this must be in intel (little-endian)
884 _my_mbstowcs (int16x * dst, uschar * src, int len)
889 for (i = 0; i < len; i++)
902 * Creates the MD4 Hash of the users password in NT UNICODE.
906 E_md4hash (uschar * passwd, uschar * p16)
911 /* Password cannot be longer than 128 characters */
912 len = strlen (CS passwd);
915 /* Password must be converted to NT unicode */
916 _my_mbstowcs (wpwd, passwd, len);
917 wpwd[len] = 0; /* Ensure string is null terminated */
918 /* Calculate length in bytes */
919 len = _my_wcslen (wpwd) * sizeof (int16x);
921 mdfour (p16, US wpwd, len);
924 /* Does both the NT and LM owfs of a user's password */
926 nt_lm_owf_gen (char *pwd, uschar nt_p16[16], uschar p16[16])
930 memset (passwd, '\0', 130);
931 safe_strcpy (passwd, pwd, sizeof (passwd) - 1);
933 /* Calculate the MD4 hash (NT compatible) of the password */
934 memset (nt_p16, '\0', 16);
935 E_md4hash (US passwd, nt_p16);
937 #ifdef DEBUG_PASSWORD
938 DEBUG_X (100, ("nt_lm_owf_gen: pwd, nt#\n"));
939 dump_data (120, passwd, strlen (passwd));
940 dump_data (100, CS nt_p16, 16);
943 /* Mangle the passwords into Lanman format */
947 /* Calculate the SMB (lanman) hash functions of the password */
949 memset (p16, '\0', 16);
950 E_P16 (US passwd, US p16);
952 #ifdef DEBUG_PASSWORD
953 DEBUG_X (100, ("nt_lm_owf_gen: pwd, lm#\n"));
954 dump_data (120, passwd, strlen (passwd));
955 dump_data (100, CS p16, 16);
957 /* clear out local copy of user's password (just being paranoid). */
958 memset (passwd, '\0', sizeof (passwd));
961 /* Does the des encryption from the NT or LM MD4 hash. */
963 SMBOWFencrypt (uschar passwd[16], uschar * c8, uschar p24[24])
967 memset (p21, '\0', 21);
969 memcpy (p21, passwd, 16);
970 E_P24 (p21, c8, p24);
973 /* Does the des encryption from the FIRST 8 BYTES of the NT or LM MD4 hash. */
975 NTLMSSPOWFencrypt (uschar passwd[8], uschar * ntlmchalresp, uschar p24[24])
979 memset (p21, '\0', 21);
980 memcpy (p21, passwd, 8);
981 memset (p21 + 8, 0xbd, 8);
983 E_P24 (p21, ntlmchalresp, p24);
984 #ifdef DEBUG_PASSWORD
985 DEBUG_X (100, ("NTLMSSPOWFencrypt: p21, c8, p24\n"));
986 dump_data (100, CS p21, 21);
987 dump_data (100, CS ntlmchalresp, 8);
988 dump_data (100, CS p24, 24);
993 /* Does the NT MD4 hash then des encryption. */
996 spa_smb_nt_encrypt (uschar * passwd, uschar * c8, uschar * p24)
1000 memset (p21, '\0', 21);
1002 E_md4hash (passwd, p21);
1003 SMBOWFencrypt (p21, c8, p24);
1005 #ifdef DEBUG_PASSWORD
1006 DEBUG_X (100, ("spa_smb_nt_encrypt: nt#, challenge, response\n"));
1007 dump_data (100, CS p21, 16);
1008 dump_data (100, CS c8, 8);
1009 dump_data (100, CS p24, 24);
1013 static uint32x A, B, C, D;
1016 F (uint32x X, uint32x Y, uint32x Z)
1018 return (X & Y) | ((~X) & Z);
1022 G (uint32x X, uint32x Y, uint32x Z)
1024 return (X & Y) | (X & Z) | (Y & Z);
1028 H (uint32x X, uint32x Y, uint32x Z)
1034 lshift_a (uint32x x, int s)
1037 return ((x << s) & 0xFFFFFFFF) | (x >> (32 - s));
1040 #define ROUND1(a,b,c,d,k,s) a = lshift_a(a + F(b,c,d) + X[k], s)
1041 #define ROUND2(a,b,c,d,k,s) a = lshift_a(a + G(b,c,d) + X[k] + (uint32x)0x5A827999,s)
1042 #define ROUND3(a,b,c,d,k,s) a = lshift_a(a + H(b,c,d) + X[k] + (uint32x)0x6ED9EBA1,s)
1044 /* this applies md4 to 64 byte chunks */
1046 spa_mdfour64 (uint32x * M)
1049 uint32x AA, BB, CC, DD;
1052 for (j = 0; j < 16; j++)
1060 ROUND1 (A, B, C, D, 0, 3);
1061 ROUND1 (D, A, B, C, 1, 7);
1062 ROUND1 (C, D, A, B, 2, 11);
1063 ROUND1 (B, C, D, A, 3, 19);
1064 ROUND1 (A, B, C, D, 4, 3);
1065 ROUND1 (D, A, B, C, 5, 7);
1066 ROUND1 (C, D, A, B, 6, 11);
1067 ROUND1 (B, C, D, A, 7, 19);
1068 ROUND1 (A, B, C, D, 8, 3);
1069 ROUND1 (D, A, B, C, 9, 7);
1070 ROUND1 (C, D, A, B, 10, 11);
1071 ROUND1 (B, C, D, A, 11, 19);
1072 ROUND1 (A, B, C, D, 12, 3);
1073 ROUND1 (D, A, B, C, 13, 7);
1074 ROUND1 (C, D, A, B, 14, 11);
1075 ROUND1 (B, C, D, A, 15, 19);
1077 ROUND2 (A, B, C, D, 0, 3);
1078 ROUND2 (D, A, B, C, 4, 5);
1079 ROUND2 (C, D, A, B, 8, 9);
1080 ROUND2 (B, C, D, A, 12, 13);
1081 ROUND2 (A, B, C, D, 1, 3);
1082 ROUND2 (D, A, B, C, 5, 5);
1083 ROUND2 (C, D, A, B, 9, 9);
1084 ROUND2 (B, C, D, A, 13, 13);
1085 ROUND2 (A, B, C, D, 2, 3);
1086 ROUND2 (D, A, B, C, 6, 5);
1087 ROUND2 (C, D, A, B, 10, 9);
1088 ROUND2 (B, C, D, A, 14, 13);
1089 ROUND2 (A, B, C, D, 3, 3);
1090 ROUND2 (D, A, B, C, 7, 5);
1091 ROUND2 (C, D, A, B, 11, 9);
1092 ROUND2 (B, C, D, A, 15, 13);
1094 ROUND3 (A, B, C, D, 0, 3);
1095 ROUND3 (D, A, B, C, 8, 9);
1096 ROUND3 (C, D, A, B, 4, 11);
1097 ROUND3 (B, C, D, A, 12, 15);
1098 ROUND3 (A, B, C, D, 2, 3);
1099 ROUND3 (D, A, B, C, 10, 9);
1100 ROUND3 (C, D, A, B, 6, 11);
1101 ROUND3 (B, C, D, A, 14, 15);
1102 ROUND3 (A, B, C, D, 1, 3);
1103 ROUND3 (D, A, B, C, 9, 9);
1104 ROUND3 (C, D, A, B, 5, 11);
1105 ROUND3 (B, C, D, A, 13, 15);
1106 ROUND3 (A, B, C, D, 3, 3);
1107 ROUND3 (D, A, B, C, 11, 9);
1108 ROUND3 (C, D, A, B, 7, 11);
1109 ROUND3 (B, C, D, A, 15, 15);
1121 for (j = 0; j < 16; j++)
1126 copy64 (uint32x * M, uschar *in)
1130 for (i = 0; i < 16; i++)
1131 M[i] = (in[i * 4 + 3] << 24) | (in[i * 4 + 2] << 16) |
1132 (in[i * 4 + 1] << 8) | (in[i * 4 + 0] << 0);
1136 copy4 (uschar *out, uint32x x)
1139 out[1] = (x >> 8) & 0xFF;
1140 out[2] = (x >> 16) & 0xFF;
1141 out[3] = (x >> 24) & 0xFF;
1144 /* produce a md4 message digest from data of length n bytes */
1146 mdfour (uschar *out, uschar *in, int n)
1166 for (i = 0; i < 128; i++)
1168 memcpy (buf, in, n);
1173 copy4 (buf + 56, b);
1179 copy4 (buf + 120, b);
1182 copy64 (M, buf + 64);
1186 for (i = 0; i < 128; i++)
1193 copy4 (out + 12, D);
1198 char versionString[] = "libntlm version 0.21";
1200 /* Utility routines that handle NTLM auth structures. */
1202 /* The [IS]VAL macros are to take care of byte order for non-Intel
1203 * Machines -- I think this file is OK, but it hasn't been tested.
1204 * The other files (the ones stolen from Samba) should be OK.
1208 /* I am not crazy about these macros -- they seem to have gotten
1209 * a bit complex. A new scheme for handling string/buffer fields
1210 * in the structures probably needs to be designed
1213 #define spa_bytes_add(ptr, header, buf, count) \
1215 if (buf && (count) != 0) /* we hate -Wint-in-bool-contex */ \
1217 SSVAL(&ptr->header.len,0,count); \
1218 SSVAL(&ptr->header.maxlen,0,count); \
1219 SIVAL(&ptr->header.offset,0,((ptr->buffer - ((uint8x*)ptr)) + ptr->bufIndex)); \
1220 memcpy(ptr->buffer+ptr->bufIndex, buf, count); \
1221 ptr->bufIndex += count; \
1226 ptr->header.maxlen = 0; \
1227 SIVAL(&ptr->header.offset,0,((ptr->buffer - ((uint8x*)ptr)) + ptr->bufIndex)); \
1231 #define spa_string_add(ptr, header, string) \
1235 if (p) len = strlen(p); \
1236 spa_bytes_add(ptr, header, (US p), len); \
1239 #define spa_unicode_add_string(ptr, header, string) \
1247 b = strToUnicode(p); \
1249 spa_bytes_add(ptr, header, b, len*2); \
1253 #define GetUnicodeString(structPtr, header) \
1254 unicodeToString(((char*)structPtr) + IVAL(&structPtr->header.offset,0) , SVAL(&structPtr->header.len,0)/2)
1255 #define GetString(structPtr, header) \
1256 toString(((CS structPtr) + IVAL(&structPtr->header.offset,0)), SVAL(&structPtr->header.len,0))
1260 #define DumpBuffer(fp, structPtr, header) \
1261 dumpRaw(fp,(US structPtr)+IVAL(&structPtr->header.offset,0),SVAL(&structPtr->header.len,0))
1265 dumpRaw (FILE * fp, uschar *buf, size_t len)
1269 for (i = 0; i < len; ++i)
1270 fprintf (fp, "%02x ", buf[i]);
1278 unicodeToString (char *p, size_t len)
1281 static char buf[1024];
1283 assert (len + 1 < sizeof buf);
1285 for (i = 0; i < len; ++i)
1296 strToUnicode (char *p)
1298 static uschar buf[1024];
1299 size_t l = strlen (p);
1302 assert (l * 2 < sizeof buf);
1314 toString (char *p, size_t len)
1316 static uschar buf[1024];
1318 assert (len + 1 < sizeof buf);
1320 memcpy (buf, p, len);
1328 dumpSmbNtlmAuthRequest (FILE * fp, SPAAuthRequest * request)
1330 fprintf (fp, "NTLM Request:\n");
1331 fprintf (fp, " Ident = %s\n", request->ident);
1332 fprintf (fp, " mType = %d\n", IVAL (&request->msgType, 0));
1333 fprintf (fp, " Flags = %08x\n", IVAL (&request->flags, 0));
1334 fprintf (fp, " User = %s\n", GetString (request, user));
1335 fprintf (fp, " Domain = %s\n", GetString (request, domain));
1339 dumpSmbNtlmAuthChallenge (FILE * fp, SPAAuthChallenge * challenge)
1341 fprintf (fp, "NTLM Challenge:\n");
1342 fprintf (fp, " Ident = %s\n", challenge->ident);
1343 fprintf (fp, " mType = %d\n", IVAL (&challenge->msgType, 0));
1344 fprintf (fp, " Domain = %s\n", GetUnicodeString (challenge, uDomain));
1345 fprintf (fp, " Flags = %08x\n", IVAL (&challenge->flags, 0));
1346 fprintf (fp, " Challenge = ");
1347 dumpRaw (fp, challenge->challengeData, 8);
1351 dumpSmbNtlmAuthResponse (FILE * fp, SPAAuthResponse * response)
1353 fprintf (fp, "NTLM Response:\n");
1354 fprintf (fp, " Ident = %s\n", response->ident);
1355 fprintf (fp, " mType = %d\n", IVAL (&response->msgType, 0));
1356 fprintf (fp, " LmResp = ");
1357 DumpBuffer (fp, response, lmResponse);
1358 fprintf (fp, " NTResp = ");
1359 DumpBuffer (fp, response, ntResponse);
1360 fprintf (fp, " Domain = %s\n", GetUnicodeString (response, uDomain));
1361 fprintf (fp, " User = %s\n", GetUnicodeString (response, uUser));
1362 fprintf (fp, " Wks = %s\n", GetUnicodeString (response, uWks));
1363 fprintf (fp, " sKey = ");
1364 DumpBuffer (fp, response, sessionKey);
1365 fprintf (fp, " Flags = %08x\n", IVAL (&response->flags, 0));
1370 spa_build_auth_request (SPAAuthRequest * request, char *user, char *domain)
1372 char *u = strdup (user);
1373 char *p = strchr (u, '@');
1382 request->bufIndex = 0;
1383 memcpy (request->ident, "NTLMSSP\0\0\0", 8);
1384 SIVAL (&request->msgType, 0, 1);
1385 SIVAL (&request->flags, 0, 0x0000b207); /* have to figure out what these mean */
1386 spa_string_add (request, user, u);
1387 spa_string_add (request, domain, domain);
1394 spa_build_auth_challenge (SPAAuthRequest * request, SPAAuthChallenge * challenge)
1398 int p = (int)getpid();
1399 int random_seed = (int)time(NULL) ^ ((p << 16) | p);
1401 /* Ensure challenge data is cleared, in case it isn't all used. This
1402 patch added by PH on suggestion of Russell King */
1404 memset(challenge, 0, sizeof(SPAAuthChallenge));
1406 challenge->bufIndex = 0;
1407 memcpy (challenge->ident, "NTLMSSP\0", 8);
1408 SIVAL (&challenge->msgType, 0, 2);
1409 SIVAL (&challenge->flags, 0, 0x00008201);
1410 SIVAL (&challenge->uDomain.len, 0, 0x0000);
1411 SIVAL (&challenge->uDomain.maxlen, 0, 0x0000);
1412 SIVAL (&challenge->uDomain.offset, 0, 0x00002800);
1414 /* generate eight pseudo random bytes (method ripped from host.c) */
1418 chalstr[i] = (uschar)(random_seed >> 16) % 256;
1419 random_seed = (1103515245 - (chalstr[i])) * random_seed + 12345;
1422 memcpy(challenge->challengeData,chalstr,8);
1428 /* This is the original source of this function, preserved here for reference.
1429 The new version below was re-organized by PH following a patch and some further
1430 suggestions from Mark Lyda to fix the problem that is described at the head of
1431 this module. At the same time, I removed the untidiness in the code below that
1432 involves the "d" and "domain" variables. */
1436 spa_build_auth_response (SPAAuthChallenge * challenge,
1437 SPAAuthResponse * response, char *user,
1440 uint8x lmRespData[24];
1441 uint8x ntRespData[24];
1442 char *d = strdup (GetUnicodeString (challenge, uDomain));
1444 char *u = strdup (user);
1445 char *p = strchr (u, '@');
1453 spa_smb_encrypt (US password, challenge->challengeData, lmRespData);
1454 spa_smb_nt_encrypt (US password, challenge->challengeData, ntRespData);
1456 response->bufIndex = 0;
1457 memcpy (response->ident, "NTLMSSP\0\0\0", 8);
1458 SIVAL (&response->msgType, 0, 3);
1460 spa_bytes_add (response, lmResponse, lmRespData, 24);
1461 spa_bytes_add (response, ntResponse, ntRespData, 24);
1462 spa_unicode_add_string (response, uDomain, domain);
1463 spa_unicode_add_string (response, uUser, u);
1464 spa_unicode_add_string (response, uWks, u);
1465 spa_string_add (response, sessionKey, NULL);
1467 response->flags = challenge->flags;
1475 /* This is the re-organized version (see comments above) */
1478 spa_build_auth_response (SPAAuthChallenge * challenge,
1479 SPAAuthResponse * response, char *user,
1482 uint8x lmRespData[24];
1483 uint8x ntRespData[24];
1484 uint32x cf = IVAL(&challenge->flags, 0);
1485 char *u = strdup (user);
1486 char *p = strchr (u, '@');
1496 else domain = d = strdup((cf & 0x1)?
1497 CCS GetUnicodeString(challenge, uDomain) :
1498 CCS GetString(challenge, uDomain));
1500 spa_smb_encrypt (US password, challenge->challengeData, lmRespData);
1501 spa_smb_nt_encrypt (US password, challenge->challengeData, ntRespData);
1503 response->bufIndex = 0;
1504 memcpy (response->ident, "NTLMSSP\0\0\0", 8);
1505 SIVAL (&response->msgType, 0, 3);
1507 spa_bytes_add (response, lmResponse, lmRespData, (cf & 0x200) ? 24 : 0);
1508 spa_bytes_add (response, ntResponse, ntRespData, (cf & 0x8000) ? 24 : 0);
1510 if (cf & 0x1) { /* Unicode Text */
1511 spa_unicode_add_string (response, uDomain, domain);
1512 spa_unicode_add_string (response, uUser, u);
1513 spa_unicode_add_string (response, uWks, u);
1514 } else { /* OEM Text */
1515 spa_string_add (response, uDomain, domain);
1516 spa_string_add (response, uUser, u);
1517 spa_string_add (response, uWks, u);
1520 spa_string_add (response, sessionKey, NULL);
1521 response->flags = challenge->flags;
1523 if (d != NULL) free (d);