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