Imported Upstream version 7.44.0
[platform/upstream/curl.git] / lib / curl_ntlm_msgs.c
1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
9  *
10  * This software is licensed as described in the file COPYING, which
11  * you should have received as part of this distribution. The terms
12  * are also available at http://curl.haxx.se/docs/copyright.html.
13  *
14  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15  * copies of the Software, and permit persons to whom the Software is
16  * furnished to do so, under the terms of the COPYING file.
17  *
18  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19  * KIND, either express or implied.
20  *
21  ***************************************************************************/
22
23 #include "curl_setup.h"
24
25 #if defined(USE_NTLM) && !defined(USE_WINDOWS_SSPI)
26
27 /*
28  * NTLM details:
29  *
30  * http://davenport.sourceforge.net/ntlm.html
31  * http://www.innovation.ch/java/ntlm.html
32  */
33
34 #define DEBUG_ME 0
35
36 #include "urldata.h"
37 #include "non-ascii.h"
38 #include "sendf.h"
39 #include "curl_base64.h"
40 #include "curl_ntlm_core.h"
41 #include "curl_gethostname.h"
42 #include "curl_multibyte.h"
43 #include "warnless.h"
44
45 #include "vtls/vtls.h"
46
47 #ifdef USE_NSS
48 #include "vtls/nssg.h" /* for Curl_nss_force_init() */
49 #endif
50
51 #define BUILDING_CURL_NTLM_MSGS_C
52 #include "curl_ntlm_msgs.h"
53 #include "curl_sasl.h"
54 #include "curl_endian.h"
55 #include "curl_printf.h"
56
57 /* The last #include files should be: */
58 #include "curl_memory.h"
59 #include "memdebug.h"
60
61 /* "NTLMSSP" signature is always in ASCII regardless of the platform */
62 #define NTLMSSP_SIGNATURE "\x4e\x54\x4c\x4d\x53\x53\x50"
63
64 #define SHORTPAIR(x) ((x) & 0xff), (((x) >> 8) & 0xff)
65 #define LONGQUARTET(x) ((x) & 0xff), (((x) >> 8) & 0xff), \
66   (((x) >> 16) & 0xff), (((x) >> 24) & 0xff)
67
68 #if DEBUG_ME
69 # define DEBUG_OUT(x) x
70 static void ntlm_print_flags(FILE *handle, unsigned long flags)
71 {
72   if(flags & NTLMFLAG_NEGOTIATE_UNICODE)
73     fprintf(handle, "NTLMFLAG_NEGOTIATE_UNICODE ");
74   if(flags & NTLMFLAG_NEGOTIATE_OEM)
75     fprintf(handle, "NTLMFLAG_NEGOTIATE_OEM ");
76   if(flags & NTLMFLAG_REQUEST_TARGET)
77     fprintf(handle, "NTLMFLAG_REQUEST_TARGET ");
78   if(flags & (1<<3))
79     fprintf(handle, "NTLMFLAG_UNKNOWN_3 ");
80   if(flags & NTLMFLAG_NEGOTIATE_SIGN)
81     fprintf(handle, "NTLMFLAG_NEGOTIATE_SIGN ");
82   if(flags & NTLMFLAG_NEGOTIATE_SEAL)
83     fprintf(handle, "NTLMFLAG_NEGOTIATE_SEAL ");
84   if(flags & NTLMFLAG_NEGOTIATE_DATAGRAM_STYLE)
85     fprintf(handle, "NTLMFLAG_NEGOTIATE_DATAGRAM_STYLE ");
86   if(flags & NTLMFLAG_NEGOTIATE_LM_KEY)
87     fprintf(handle, "NTLMFLAG_NEGOTIATE_LM_KEY ");
88   if(flags & NTLMFLAG_NEGOTIATE_NETWARE)
89     fprintf(handle, "NTLMFLAG_NEGOTIATE_NETWARE ");
90   if(flags & NTLMFLAG_NEGOTIATE_NTLM_KEY)
91     fprintf(handle, "NTLMFLAG_NEGOTIATE_NTLM_KEY ");
92   if(flags & (1<<10))
93     fprintf(handle, "NTLMFLAG_UNKNOWN_10 ");
94   if(flags & NTLMFLAG_NEGOTIATE_ANONYMOUS)
95     fprintf(handle, "NTLMFLAG_NEGOTIATE_ANONYMOUS ");
96   if(flags & NTLMFLAG_NEGOTIATE_DOMAIN_SUPPLIED)
97     fprintf(handle, "NTLMFLAG_NEGOTIATE_DOMAIN_SUPPLIED ");
98   if(flags & NTLMFLAG_NEGOTIATE_WORKSTATION_SUPPLIED)
99     fprintf(handle, "NTLMFLAG_NEGOTIATE_WORKSTATION_SUPPLIED ");
100   if(flags & NTLMFLAG_NEGOTIATE_LOCAL_CALL)
101     fprintf(handle, "NTLMFLAG_NEGOTIATE_LOCAL_CALL ");
102   if(flags & NTLMFLAG_NEGOTIATE_ALWAYS_SIGN)
103     fprintf(handle, "NTLMFLAG_NEGOTIATE_ALWAYS_SIGN ");
104   if(flags & NTLMFLAG_TARGET_TYPE_DOMAIN)
105     fprintf(handle, "NTLMFLAG_TARGET_TYPE_DOMAIN ");
106   if(flags & NTLMFLAG_TARGET_TYPE_SERVER)
107     fprintf(handle, "NTLMFLAG_TARGET_TYPE_SERVER ");
108   if(flags & NTLMFLAG_TARGET_TYPE_SHARE)
109     fprintf(handle, "NTLMFLAG_TARGET_TYPE_SHARE ");
110   if(flags & NTLMFLAG_NEGOTIATE_NTLM2_KEY)
111     fprintf(handle, "NTLMFLAG_NEGOTIATE_NTLM2_KEY ");
112   if(flags & NTLMFLAG_REQUEST_INIT_RESPONSE)
113     fprintf(handle, "NTLMFLAG_REQUEST_INIT_RESPONSE ");
114   if(flags & NTLMFLAG_REQUEST_ACCEPT_RESPONSE)
115     fprintf(handle, "NTLMFLAG_REQUEST_ACCEPT_RESPONSE ");
116   if(flags & NTLMFLAG_REQUEST_NONNT_SESSION_KEY)
117     fprintf(handle, "NTLMFLAG_REQUEST_NONNT_SESSION_KEY ");
118   if(flags & NTLMFLAG_NEGOTIATE_TARGET_INFO)
119     fprintf(handle, "NTLMFLAG_NEGOTIATE_TARGET_INFO ");
120   if(flags & (1<<24))
121     fprintf(handle, "NTLMFLAG_UNKNOWN_24 ");
122   if(flags & (1<<25))
123     fprintf(handle, "NTLMFLAG_UNKNOWN_25 ");
124   if(flags & (1<<26))
125     fprintf(handle, "NTLMFLAG_UNKNOWN_26 ");
126   if(flags & (1<<27))
127     fprintf(handle, "NTLMFLAG_UNKNOWN_27 ");
128   if(flags & (1<<28))
129     fprintf(handle, "NTLMFLAG_UNKNOWN_28 ");
130   if(flags & NTLMFLAG_NEGOTIATE_128)
131     fprintf(handle, "NTLMFLAG_NEGOTIATE_128 ");
132   if(flags & NTLMFLAG_NEGOTIATE_KEY_EXCHANGE)
133     fprintf(handle, "NTLMFLAG_NEGOTIATE_KEY_EXCHANGE ");
134   if(flags & NTLMFLAG_NEGOTIATE_56)
135     fprintf(handle, "NTLMFLAG_NEGOTIATE_56 ");
136 }
137
138 static void ntlm_print_hex(FILE *handle, const char *buf, size_t len)
139 {
140   const char *p = buf;
141   (void)handle;
142   fprintf(stderr, "0x");
143   while(len-- > 0)
144     fprintf(stderr, "%02.2x", (unsigned int)*p++);
145 }
146 #else
147 # define DEBUG_OUT(x) Curl_nop_stmt
148 #endif
149
150 /*
151  * ntlm_decode_type2_target()
152  *
153  * This is used to decode the "target info" in the ntlm type-2 message
154  * received.
155  *
156  * Parameters:
157  *
158  * data      [in]     - The session handle.
159  * buffer    [in]     - The decoded type-2 message.
160  * size      [in]     - The input buffer size, at least 32 bytes.
161  * ntlm      [in/out] - The ntlm data struct being used and modified.
162  *
163  * Returns CURLE_OK on success.
164  */
165 static CURLcode ntlm_decode_type2_target(struct SessionHandle *data,
166                                          unsigned char *buffer,
167                                          size_t size,
168                                          struct ntlmdata *ntlm)
169 {
170   unsigned short target_info_len = 0;
171   unsigned int target_info_offset = 0;
172
173   if(size >= 48) {
174     target_info_len = Curl_read16_le(&buffer[40]);
175     target_info_offset = Curl_read32_le(&buffer[44]);
176     if(target_info_len > 0) {
177       if(((target_info_offset + target_info_len) > size) ||
178          (target_info_offset < 48)) {
179         infof(data, "NTLM handshake failure (bad type-2 message). "
180                     "Target Info Offset Len is set incorrect by the peer\n");
181         return CURLE_BAD_CONTENT_ENCODING;
182       }
183
184       ntlm->target_info = malloc(target_info_len);
185       if(!ntlm->target_info)
186         return CURLE_OUT_OF_MEMORY;
187
188       memcpy(ntlm->target_info, &buffer[target_info_offset], target_info_len);
189     }
190   }
191
192   ntlm->target_info_len = target_info_len;
193
194   return CURLE_OK;
195 }
196
197 /*
198   NTLM message structure notes:
199
200   A 'short' is a 'network short', a little-endian 16-bit unsigned value.
201
202   A 'long' is a 'network long', a little-endian, 32-bit unsigned value.
203
204   A 'security buffer' represents a triplet used to point to a buffer,
205   consisting of two shorts and one long:
206
207     1. A 'short' containing the length of the buffer content in bytes.
208     2. A 'short' containing the allocated space for the buffer in bytes.
209     3. A 'long' containing the offset to the start of the buffer in bytes,
210        from the beginning of the NTLM message.
211 */
212
213 /*
214  * Curl_sasl_decode_ntlm_type2_message()
215  *
216  * This is used to decode an already encoded NTLM type-2 message. The message
217  * is first decoded from a base64 string into a raw NTLM message and checked
218  * for validity before the appropriate data for creating a type-3 message is
219  * written to the given NTLM data structure.
220  *
221  * Parameters:
222  *
223  * data     [in]     - The session handle.
224  * type2msg [in]     - The base64 encoded type-2 message.
225  * ntlm     [in/out] - The ntlm data struct being used and modified.
226  *
227  * Returns CURLE_OK on success.
228  */
229 CURLcode Curl_sasl_decode_ntlm_type2_message(struct SessionHandle *data,
230                                              const char *type2msg,
231                                              struct ntlmdata *ntlm)
232 {
233   static const char type2_marker[] = { 0x02, 0x00, 0x00, 0x00 };
234
235   /* NTLM type-2 message structure:
236
237           Index  Description            Content
238             0    NTLMSSP Signature      Null-terminated ASCII "NTLMSSP"
239                                         (0x4e544c4d53535000)
240             8    NTLM Message Type      long (0x02000000)
241            12    Target Name            security buffer
242            20    Flags                  long
243            24    Challenge              8 bytes
244           (32)   Context                8 bytes (two consecutive longs) (*)
245           (40)   Target Information     security buffer (*)
246           (48)   OS Version Structure   8 bytes (*)
247   32 (48) (56)   Start of data block    (*)
248                                         (*) -> Optional
249   */
250
251   CURLcode result = CURLE_OK;
252   unsigned char *type2 = NULL;
253   size_t type2_len = 0;
254
255 #if defined(USE_NSS)
256   /* Make sure the crypto backend is initialized */
257   result = Curl_nss_force_init(data);
258   if(result)
259     return result;
260 #elif defined(CURL_DISABLE_VERBOSE_STRINGS)
261   (void)data;
262 #endif
263
264   /* Decode the base-64 encoded type-2 message */
265   if(strlen(type2msg) && *type2msg != '=') {
266     result = Curl_base64_decode(type2msg, &type2, &type2_len);
267     if(result)
268       return result;
269   }
270
271   /* Ensure we have a valid type-2 message */
272   if(!type2) {
273     infof(data, "NTLM handshake failure (empty type-2 message)\n");
274     return CURLE_BAD_CONTENT_ENCODING;
275   }
276
277   ntlm->flags = 0;
278
279   if((type2_len < 32) ||
280      (memcmp(type2, NTLMSSP_SIGNATURE, 8) != 0) ||
281      (memcmp(type2 + 8, type2_marker, sizeof(type2_marker)) != 0)) {
282     /* This was not a good enough type-2 message */
283     free(type2);
284     infof(data, "NTLM handshake failure (bad type-2 message)\n");
285     return CURLE_BAD_CONTENT_ENCODING;
286   }
287
288   ntlm->flags = Curl_read32_le(&type2[20]);
289   memcpy(ntlm->nonce, &type2[24], 8);
290
291   if(ntlm->flags & NTLMFLAG_NEGOTIATE_TARGET_INFO) {
292     result = ntlm_decode_type2_target(data, type2, type2_len, ntlm);
293     if(result) {
294       free(type2);
295       infof(data, "NTLM handshake failure (bad type-2 message)\n");
296       return result;
297     }
298   }
299
300   DEBUG_OUT({
301     fprintf(stderr, "**** TYPE2 header flags=0x%08.8lx ", ntlm->flags);
302     ntlm_print_flags(stderr, ntlm->flags);
303     fprintf(stderr, "\n                  nonce=");
304     ntlm_print_hex(stderr, (char *)ntlm->nonce, 8);
305     fprintf(stderr, "\n****\n");
306     fprintf(stderr, "**** Header %s\n ", header);
307   });
308
309   free(type2);
310
311   return result;
312 }
313
314 /* copy the source to the destination and fill in zeroes in every
315    other destination byte! */
316 static void unicodecpy(unsigned char *dest, const char *src, size_t length)
317 {
318   size_t i;
319   for(i = 0; i < length; i++) {
320     dest[2 * i] = (unsigned char)src[i];
321     dest[2 * i + 1] = '\0';
322   }
323 }
324
325 /*
326  * Curl_sasl_create_ntlm_type1_message()
327  *
328  * This is used to generate an already encoded NTLM type-1 message ready for
329  * sending to the recipient using the appropriate compile time crypto API.
330  *
331  * Parameters:
332  *
333  * userp   [in]     - The user name in the format User or Domain\User.
334  * passdwp [in]     - The user's password.
335  * ntlm    [in/out] - The ntlm data struct being used and modified.
336  * outptr  [in/out] - The address where a pointer to newly allocated memory
337  *                    holding the result will be stored upon completion.
338  * outlen  [out]    - The length of the output message.
339  *
340  * Returns CURLE_OK on success.
341  */
342 CURLcode Curl_sasl_create_ntlm_type1_message(const char *userp,
343                                              const char *passwdp,
344                                              struct ntlmdata *ntlm,
345                                              char **outptr, size_t *outlen)
346 {
347   /* NTLM type-1 message structure:
348
349        Index  Description            Content
350          0    NTLMSSP Signature      Null-terminated ASCII "NTLMSSP"
351                                      (0x4e544c4d53535000)
352          8    NTLM Message Type      long (0x01000000)
353         12    Flags                  long
354        (16)   Supplied Domain        security buffer (*)
355        (24)   Supplied Workstation   security buffer (*)
356        (32)   OS Version Structure   8 bytes (*)
357   (32) (40)   Start of data block    (*)
358                                      (*) -> Optional
359   */
360
361   size_t size;
362
363   unsigned char ntlmbuf[NTLM_BUFSIZE];
364   const char *host = "";              /* empty */
365   const char *domain = "";            /* empty */
366   size_t hostlen = 0;
367   size_t domlen = 0;
368   size_t hostoff = 0;
369   size_t domoff = hostoff + hostlen;  /* This is 0: remember that host and
370                                          domain are empty */
371   (void)userp;
372   (void)passwdp;
373
374   /* Clean up any former leftovers and initialise to defaults */
375   Curl_sasl_ntlm_cleanup(ntlm);
376
377 #if USE_NTRESPONSES && USE_NTLM2SESSION
378 #define NTLM2FLAG NTLMFLAG_NEGOTIATE_NTLM2_KEY
379 #else
380 #define NTLM2FLAG 0
381 #endif
382   snprintf((char *)ntlmbuf, NTLM_BUFSIZE,
383            NTLMSSP_SIGNATURE "%c"
384            "\x01%c%c%c" /* 32-bit type = 1 */
385            "%c%c%c%c"   /* 32-bit NTLM flag field */
386            "%c%c"       /* domain length */
387            "%c%c"       /* domain allocated space */
388            "%c%c"       /* domain name offset */
389            "%c%c"       /* 2 zeroes */
390            "%c%c"       /* host length */
391            "%c%c"       /* host allocated space */
392            "%c%c"       /* host name offset */
393            "%c%c"       /* 2 zeroes */
394            "%s"         /* host name */
395            "%s",        /* domain string */
396            0,           /* trailing zero */
397            0, 0, 0,     /* part of type-1 long */
398
399            LONGQUARTET(NTLMFLAG_NEGOTIATE_OEM |
400                        NTLMFLAG_REQUEST_TARGET |
401                        NTLMFLAG_NEGOTIATE_NTLM_KEY |
402                        NTLM2FLAG |
403                        NTLMFLAG_NEGOTIATE_ALWAYS_SIGN),
404            SHORTPAIR(domlen),
405            SHORTPAIR(domlen),
406            SHORTPAIR(domoff),
407            0, 0,
408            SHORTPAIR(hostlen),
409            SHORTPAIR(hostlen),
410            SHORTPAIR(hostoff),
411            0, 0,
412            host,  /* this is empty */
413            domain /* this is empty */);
414
415   /* Initial packet length */
416   size = 32 + hostlen + domlen;
417
418   DEBUG_OUT({
419     fprintf(stderr, "* TYPE1 header flags=0x%02.2x%02.2x%02.2x%02.2x "
420             "0x%08.8x ",
421             LONGQUARTET(NTLMFLAG_NEGOTIATE_OEM |
422                         NTLMFLAG_REQUEST_TARGET |
423                         NTLMFLAG_NEGOTIATE_NTLM_KEY |
424                         NTLM2FLAG |
425                         NTLMFLAG_NEGOTIATE_ALWAYS_SIGN),
426             NTLMFLAG_NEGOTIATE_OEM |
427             NTLMFLAG_REQUEST_TARGET |
428             NTLMFLAG_NEGOTIATE_NTLM_KEY |
429             NTLM2FLAG |
430             NTLMFLAG_NEGOTIATE_ALWAYS_SIGN);
431     ntlm_print_flags(stderr,
432                      NTLMFLAG_NEGOTIATE_OEM |
433                      NTLMFLAG_REQUEST_TARGET |
434                      NTLMFLAG_NEGOTIATE_NTLM_KEY |
435                      NTLM2FLAG |
436                      NTLMFLAG_NEGOTIATE_ALWAYS_SIGN);
437     fprintf(stderr, "\n****\n");
438   });
439
440   /* Return with binary blob encoded into base64 */
441   return Curl_base64_encode(NULL, (char *)ntlmbuf, size, outptr, outlen);
442 }
443
444 /*
445  * Curl_sasl_create_ntlm_type3_message()
446  *
447  * This is used to generate an already encoded NTLM type-3 message ready for
448  * sending to the recipient using the appropriate compile time crypto API.
449  *
450  * Parameters:
451  *
452  * data    [in]     - The session handle.
453  * userp   [in]     - The user name in the format User or Domain\User.
454  * passdwp [in]     - The user's password.
455  * ntlm    [in/out] - The ntlm data struct being used and modified.
456  * outptr  [in/out] - The address where a pointer to newly allocated memory
457  *                    holding the result will be stored upon completion.
458  * outlen  [out]    - The length of the output message.
459  *
460  * Returns CURLE_OK on success.
461  */
462 CURLcode Curl_sasl_create_ntlm_type3_message(struct SessionHandle *data,
463                                              const char *userp,
464                                              const char *passwdp,
465                                              struct ntlmdata *ntlm,
466                                              char **outptr, size_t *outlen)
467
468 {
469   /* NTLM type-3 message structure:
470
471           Index  Description            Content
472             0    NTLMSSP Signature      Null-terminated ASCII "NTLMSSP"
473                                         (0x4e544c4d53535000)
474             8    NTLM Message Type      long (0x03000000)
475            12    LM/LMv2 Response       security buffer
476            20    NTLM/NTLMv2 Response   security buffer
477            28    Target Name            security buffer
478            36    User Name              security buffer
479            44    Workstation Name       security buffer
480           (52)   Session Key            security buffer (*)
481           (60)   Flags                  long (*)
482           (64)   OS Version Structure   8 bytes (*)
483   52 (64) (72)   Start of data block
484                                           (*) -> Optional
485   */
486
487   CURLcode result = CURLE_OK;
488   size_t size;
489   unsigned char ntlmbuf[NTLM_BUFSIZE];
490   int lmrespoff;
491   unsigned char lmresp[24]; /* fixed-size */
492 #if USE_NTRESPONSES
493   int ntrespoff;
494   unsigned int ntresplen = 24;
495   unsigned char ntresp[24]; /* fixed-size */
496   unsigned char *ptr_ntresp = &ntresp[0];
497   unsigned char *ntlmv2resp = NULL;
498 #endif
499   bool unicode = (ntlm->flags & NTLMFLAG_NEGOTIATE_UNICODE) ? TRUE : FALSE;
500   char host[HOSTNAME_MAX + 1] = "";
501   const char *user;
502   const char *domain = "";
503   size_t hostoff = 0;
504   size_t useroff = 0;
505   size_t domoff = 0;
506   size_t hostlen = 0;
507   size_t userlen = 0;
508   size_t domlen = 0;
509
510   user = strchr(userp, '\\');
511   if(!user)
512     user = strchr(userp, '/');
513
514   if(user) {
515     domain = userp;
516     domlen = (user - domain);
517     user++;
518   }
519   else
520     user = userp;
521
522   if(user)
523     userlen = strlen(user);
524
525   /* Get the machine's un-qualified host name as NTLM doesn't like the fully
526      qualified domain name */
527   if(Curl_gethostname(host, sizeof(host))) {
528     infof(data, "gethostname() failed, continuing without!\n");
529     hostlen = 0;
530   }
531   else {
532     hostlen = strlen(host);
533   }
534
535 #if USE_NTRESPONSES && USE_NTLM_V2
536   if(ntlm->target_info_len) {
537     unsigned char ntbuffer[0x18];
538     unsigned int entropy[2];
539     unsigned char ntlmv2hash[0x18];
540
541     entropy[0] = Curl_rand(data);
542     entropy[1] = Curl_rand(data);
543
544     result = Curl_ntlm_core_mk_nt_hash(data, passwdp, ntbuffer);
545     if(result)
546       return result;
547
548     result = Curl_ntlm_core_mk_ntlmv2_hash(user, userlen, domain, domlen,
549                                            ntbuffer, ntlmv2hash);
550     if(result)
551       return result;
552
553     /* LMv2 response */
554     result = Curl_ntlm_core_mk_lmv2_resp(ntlmv2hash,
555                                          (unsigned char *)&entropy[0],
556                                          &ntlm->nonce[0], lmresp);
557     if(result)
558       return result;
559
560     /* NTLMv2 response */
561     result = Curl_ntlm_core_mk_ntlmv2_resp(ntlmv2hash,
562                                            (unsigned char *)&entropy[0],
563                                            ntlm, &ntlmv2resp, &ntresplen);
564     if(result)
565       return result;
566
567     ptr_ntresp = ntlmv2resp;
568   }
569   else
570 #endif
571
572 #if USE_NTRESPONSES && USE_NTLM2SESSION
573   /* We don't support NTLM2 if we don't have USE_NTRESPONSES */
574   if(ntlm->flags & NTLMFLAG_NEGOTIATE_NTLM2_KEY) {
575     unsigned char ntbuffer[0x18];
576     unsigned char tmp[0x18];
577     unsigned char md5sum[MD5_DIGEST_LENGTH];
578     unsigned int entropy[2];
579
580     /* Need to create 8 bytes random data */
581     entropy[0] = Curl_rand(data);
582     entropy[1] = Curl_rand(data);
583
584     /* 8 bytes random data as challenge in lmresp */
585     memcpy(lmresp, entropy, 8);
586
587     /* Pad with zeros */
588     memset(lmresp + 8, 0, 0x10);
589
590     /* Fill tmp with challenge(nonce?) + entropy */
591     memcpy(tmp, &ntlm->nonce[0], 8);
592     memcpy(tmp + 8, entropy, 8);
593
594     result = Curl_ssl_md5sum(tmp, 16, md5sum, MD5_DIGEST_LENGTH);
595     if(!result)
596       /* We shall only use the first 8 bytes of md5sum, but the des code in
597          Curl_ntlm_core_lm_resp only encrypt the first 8 bytes */
598       result = Curl_ntlm_core_mk_nt_hash(data, passwdp, ntbuffer);
599     if(result)
600       return result;
601
602     Curl_ntlm_core_lm_resp(ntbuffer, md5sum, ntresp);
603
604     /* End of NTLM2 Session code */
605
606   }
607   else
608 #endif
609   {
610
611 #if USE_NTRESPONSES
612     unsigned char ntbuffer[0x18];
613 #endif
614     unsigned char lmbuffer[0x18];
615
616 #if USE_NTRESPONSES
617     result = Curl_ntlm_core_mk_nt_hash(data, passwdp, ntbuffer);
618     if(result)
619       return result;
620
621     Curl_ntlm_core_lm_resp(ntbuffer, &ntlm->nonce[0], ntresp);
622 #endif
623
624     result = Curl_ntlm_core_mk_lm_hash(data, passwdp, lmbuffer);
625     if(result)
626       return result;
627
628     Curl_ntlm_core_lm_resp(lmbuffer, &ntlm->nonce[0], lmresp);
629
630     /* A safer but less compatible alternative is:
631      *   Curl_ntlm_core_lm_resp(ntbuffer, &ntlm->nonce[0], lmresp);
632      * See http://davenport.sourceforge.net/ntlm.html#ntlmVersion2 */
633   }
634
635   if(unicode) {
636     domlen = domlen * 2;
637     userlen = userlen * 2;
638     hostlen = hostlen * 2;
639   }
640
641   lmrespoff = 64; /* size of the message header */
642 #if USE_NTRESPONSES
643   ntrespoff = lmrespoff + 0x18;
644   domoff = ntrespoff + ntresplen;
645 #else
646   domoff = lmrespoff + 0x18;
647 #endif
648   useroff = domoff + domlen;
649   hostoff = useroff + userlen;
650
651   /* Create the big type-3 message binary blob */
652   size = snprintf((char *)ntlmbuf, NTLM_BUFSIZE,
653                   NTLMSSP_SIGNATURE "%c"
654                   "\x03%c%c%c"  /* 32-bit type = 3 */
655
656                   "%c%c"  /* LanManager length */
657                   "%c%c"  /* LanManager allocated space */
658                   "%c%c"  /* LanManager offset */
659                   "%c%c"  /* 2 zeroes */
660
661                   "%c%c"  /* NT-response length */
662                   "%c%c"  /* NT-response allocated space */
663                   "%c%c"  /* NT-response offset */
664                   "%c%c"  /* 2 zeroes */
665
666                   "%c%c"  /* domain length */
667                   "%c%c"  /* domain allocated space */
668                   "%c%c"  /* domain name offset */
669                   "%c%c"  /* 2 zeroes */
670
671                   "%c%c"  /* user length */
672                   "%c%c"  /* user allocated space */
673                   "%c%c"  /* user offset */
674                   "%c%c"  /* 2 zeroes */
675
676                   "%c%c"  /* host length */
677                   "%c%c"  /* host allocated space */
678                   "%c%c"  /* host offset */
679                   "%c%c"  /* 2 zeroes */
680
681                   "%c%c"  /* session key length (unknown purpose) */
682                   "%c%c"  /* session key allocated space (unknown purpose) */
683                   "%c%c"  /* session key offset (unknown purpose) */
684                   "%c%c"  /* 2 zeroes */
685
686                   "%c%c%c%c",  /* flags */
687
688                   /* domain string */
689                   /* user string */
690                   /* host string */
691                   /* LanManager response */
692                   /* NT response */
693
694                   0,                /* zero termination */
695                   0, 0, 0,          /* type-3 long, the 24 upper bits */
696
697                   SHORTPAIR(0x18),  /* LanManager response length, twice */
698                   SHORTPAIR(0x18),
699                   SHORTPAIR(lmrespoff),
700                   0x0, 0x0,
701
702 #if USE_NTRESPONSES
703                   SHORTPAIR(ntresplen),  /* NT-response length, twice */
704                   SHORTPAIR(ntresplen),
705                   SHORTPAIR(ntrespoff),
706                   0x0, 0x0,
707 #else
708                   0x0, 0x0,
709                   0x0, 0x0,
710                   0x0, 0x0,
711                   0x0, 0x0,
712 #endif
713                   SHORTPAIR(domlen),
714                   SHORTPAIR(domlen),
715                   SHORTPAIR(domoff),
716                   0x0, 0x0,
717
718                   SHORTPAIR(userlen),
719                   SHORTPAIR(userlen),
720                   SHORTPAIR(useroff),
721                   0x0, 0x0,
722
723                   SHORTPAIR(hostlen),
724                   SHORTPAIR(hostlen),
725                   SHORTPAIR(hostoff),
726                   0x0, 0x0,
727
728                   0x0, 0x0,
729                   0x0, 0x0,
730                   0x0, 0x0,
731                   0x0, 0x0,
732
733                   LONGQUARTET(ntlm->flags));
734
735   DEBUGASSERT(size == 64);
736   DEBUGASSERT(size == (size_t)lmrespoff);
737
738   /* We append the binary hashes */
739   if(size < (NTLM_BUFSIZE - 0x18)) {
740     memcpy(&ntlmbuf[size], lmresp, 0x18);
741     size += 0x18;
742   }
743
744   DEBUG_OUT({
745     fprintf(stderr, "**** TYPE3 header lmresp=");
746     ntlm_print_hex(stderr, (char *)&ntlmbuf[lmrespoff], 0x18);
747   });
748
749 #if USE_NTRESPONSES
750   if(size < (NTLM_BUFSIZE - ntresplen)) {
751     DEBUGASSERT(size == (size_t)ntrespoff);
752     memcpy(&ntlmbuf[size], ptr_ntresp, ntresplen);
753     size += ntresplen;
754   }
755
756   DEBUG_OUT({
757     fprintf(stderr, "\n   ntresp=");
758     ntlm_print_hex(stderr, (char *)&ntlmbuf[ntrespoff], ntresplen);
759   });
760
761   free(ntlmv2resp);/* Free the dynamic buffer allocated for NTLMv2 */
762
763 #endif
764
765   DEBUG_OUT({
766     fprintf(stderr, "\n   flags=0x%02.2x%02.2x%02.2x%02.2x 0x%08.8x ",
767             LONGQUARTET(ntlm->flags), ntlm->flags);
768     ntlm_print_flags(stderr, ntlm->flags);
769     fprintf(stderr, "\n****\n");
770   });
771
772   /* Make sure that the domain, user and host strings fit in the
773      buffer before we copy them there. */
774   if(size + userlen + domlen + hostlen >= NTLM_BUFSIZE) {
775     failf(data, "user + domain + host name too big");
776     return CURLE_OUT_OF_MEMORY;
777   }
778
779   DEBUGASSERT(size == domoff);
780   if(unicode)
781     unicodecpy(&ntlmbuf[size], domain, domlen / 2);
782   else
783     memcpy(&ntlmbuf[size], domain, domlen);
784
785   size += domlen;
786
787   DEBUGASSERT(size == useroff);
788   if(unicode)
789     unicodecpy(&ntlmbuf[size], user, userlen / 2);
790   else
791     memcpy(&ntlmbuf[size], user, userlen);
792
793   size += userlen;
794
795   DEBUGASSERT(size == hostoff);
796   if(unicode)
797     unicodecpy(&ntlmbuf[size], host, hostlen / 2);
798   else
799     memcpy(&ntlmbuf[size], host, hostlen);
800
801   size += hostlen;
802
803   /* Convert domain, user, and host to ASCII but leave the rest as-is */
804   result = Curl_convert_to_network(data, (char *)&ntlmbuf[domoff],
805                                    size - domoff);
806   if(result)
807     return CURLE_CONV_FAILED;
808
809   /* Return with binary blob encoded into base64 */
810   result = Curl_base64_encode(NULL, (char *)ntlmbuf, size, outptr, outlen);
811
812   Curl_sasl_ntlm_cleanup(ntlm);
813
814   return result;
815 }
816
817 #endif /* USE_NTLM && !USE_WINDOWS_SSPI */