Update tag value for tizen 2.0 build
[external/curl.git] / lib / http_ntlm.c
1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2009, 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 #include "setup.h"
23
24 /* NTLM details:
25
26    http://davenport.sourceforge.net/ntlm.html
27    http://www.innovation.ch/java/ntlm.html
28
29    Another implementation:
30    http://lxr.mozilla.org/mozilla/source/security/manager/ssl/src/nsNTLMAuthModule.cpp
31
32 */
33
34 #ifndef CURL_DISABLE_HTTP
35 #ifdef USE_NTLM
36
37 #define DEBUG_ME 0
38
39 /* -- WIN32 approved -- */
40 #include <stdio.h>
41 #include <string.h>
42 #include <stdarg.h>
43 #include <stdlib.h>
44 #include <ctype.h>
45
46 #ifdef HAVE_UNISTD_H
47 #include <unistd.h>
48 #endif
49
50 #if (defined(NETWARE) && !defined(__NOVELL_LIBC__))
51 #include <netdb.h>
52 #endif
53
54 #include "urldata.h"
55 #include "easyif.h"  /* for Curl_convert_... prototypes */
56 #include "sendf.h"
57 #include "rawstr.h"
58 #include "curl_base64.h"
59 #include "http_ntlm.h"
60 #include "url.h"
61 #include "curl_gethostname.h"
62 #include "curl_memory.h"
63
64 #define _MPRINTF_REPLACE /* use our functions only */
65 #include <curl/mprintf.h>
66
67 /* "NTLMSSP" signature is always in ASCII regardless of the platform */
68 #define NTLMSSP_SIGNATURE "\x4e\x54\x4c\x4d\x53\x53\x50"
69
70 #ifdef USE_SSLEAY
71 #include "ssluse.h"
72 #    ifdef USE_OPENSSL
73 #      include <openssl/des.h>
74 #      ifndef OPENSSL_NO_MD4
75 #        include <openssl/md4.h>
76 #      endif
77 #      include <openssl/md5.h>
78 #      include <openssl/ssl.h>
79 #      include <openssl/rand.h>
80 #    else
81 #      include <des.h>
82 #      ifndef OPENSSL_NO_MD4
83 #        include <md4.h>
84 #      endif
85 #      include <md5.h>
86 #      include <ssl.h>
87 #      include <rand.h>
88 #    endif
89
90 #if OPENSSL_VERSION_NUMBER < 0x00907001L
91 #define DES_key_schedule des_key_schedule
92 #define DES_cblock des_cblock
93 #define DES_set_odd_parity des_set_odd_parity
94 #define DES_set_key des_set_key
95 #define DES_ecb_encrypt des_ecb_encrypt
96
97 /* This is how things were done in the old days */
98 #define DESKEY(x) x
99 #define DESKEYARG(x) x
100 #else
101 /* Modern version */
102 #define DESKEYARG(x) *x
103 #define DESKEY(x) &x
104 #endif
105
106 #ifdef OPENSSL_NO_MD4
107 /* This requires MD4, but OpenSSL was compiled without it */
108 #define USE_NTRESPONSES 0
109 #define USE_NTLM2SESSION 0
110 #endif
111
112 #elif defined(USE_GNUTLS)
113
114 #include "gtls.h"
115 #include <gcrypt.h>
116
117 #define MD5_DIGEST_LENGTH 16
118 #define MD4_DIGEST_LENGTH 16
119
120 #elif defined(USE_NSS)
121
122 #include "curl_md4.h"
123 #include "nssg.h"
124 #include <nss.h>
125 #include <pk11pub.h>
126 #include <hasht.h>
127 #define MD5_DIGEST_LENGTH MD5_LENGTH
128
129 #elif defined(USE_WINDOWS_SSPI)
130
131 #include "curl_sspi.h"
132
133 #else
134 #    error "Can't compile NTLM support without a crypto library."
135 #endif
136
137 /* The last #include file should be: */
138 #include "memdebug.h"
139
140 #ifndef USE_NTRESPONSES 
141 /* Define this to make the type-3 message include the NT response message */
142 #define USE_NTRESPONSES 1
143
144 /* Define this to make the type-3 message include the NTLM2Session response
145    message, requires USE_NTRESPONSES. */
146 #define USE_NTLM2SESSION 1
147 #endif
148
149 #ifndef USE_WINDOWS_SSPI
150 /* this function converts from the little endian format used in the incoming
151    package to whatever endian format we're using natively */
152 static unsigned int readint_le(unsigned char *buf) /* must point to a
153                                                       4 bytes buffer*/
154 {
155   return ((unsigned int)buf[0]) | ((unsigned int)buf[1] << 8) |
156     ((unsigned int)buf[2] << 16) | ((unsigned int)buf[3] << 24);
157 }
158 #endif
159
160 #if DEBUG_ME
161 # define DEBUG_OUT(x) x
162 static void print_flags(FILE *handle, unsigned long flags)
163 {
164   if(flags & NTLMFLAG_NEGOTIATE_UNICODE)
165     fprintf(handle, "NTLMFLAG_NEGOTIATE_UNICODE ");
166   if(flags & NTLMFLAG_NEGOTIATE_OEM)
167     fprintf(handle, "NTLMFLAG_NEGOTIATE_OEM ");
168   if(flags & NTLMFLAG_REQUEST_TARGET)
169     fprintf(handle, "NTLMFLAG_REQUEST_TARGET ");
170   if(flags & (1<<3))
171     fprintf(handle, "NTLMFLAG_UNKNOWN_3 ");
172   if(flags & NTLMFLAG_NEGOTIATE_SIGN)
173     fprintf(handle, "NTLMFLAG_NEGOTIATE_SIGN ");
174   if(flags & NTLMFLAG_NEGOTIATE_SEAL)
175     fprintf(handle, "NTLMFLAG_NEGOTIATE_SEAL ");
176   if(flags & NTLMFLAG_NEGOTIATE_DATAGRAM_STYLE)
177     fprintf(handle, "NTLMFLAG_NEGOTIATE_DATAGRAM_STYLE ");
178   if(flags & NTLMFLAG_NEGOTIATE_LM_KEY)
179     fprintf(handle, "NTLMFLAG_NEGOTIATE_LM_KEY ");
180   if(flags & NTLMFLAG_NEGOTIATE_NETWARE)
181     fprintf(handle, "NTLMFLAG_NEGOTIATE_NETWARE ");
182   if(flags & NTLMFLAG_NEGOTIATE_NTLM_KEY)
183     fprintf(handle, "NTLMFLAG_NEGOTIATE_NTLM_KEY ");
184   if(flags & (1<<10))
185     fprintf(handle, "NTLMFLAG_UNKNOWN_10 ");
186   if(flags & NTLMFLAG_NEGOTIATE_ANONYMOUS)
187     fprintf(handle, "NTLMFLAG_NEGOTIATE_ANONYMOUS ");
188   if(flags & NTLMFLAG_NEGOTIATE_DOMAIN_SUPPLIED)
189     fprintf(handle, "NTLMFLAG_NEGOTIATE_DOMAIN_SUPPLIED ");
190   if(flags & NTLMFLAG_NEGOTIATE_WORKSTATION_SUPPLIED)
191     fprintf(handle, "NTLMFLAG_NEGOTIATE_WORKSTATION_SUPPLIED ");
192   if(flags & NTLMFLAG_NEGOTIATE_LOCAL_CALL)
193     fprintf(handle, "NTLMFLAG_NEGOTIATE_LOCAL_CALL ");
194   if(flags & NTLMFLAG_NEGOTIATE_ALWAYS_SIGN)
195     fprintf(handle, "NTLMFLAG_NEGOTIATE_ALWAYS_SIGN ");
196   if(flags & NTLMFLAG_TARGET_TYPE_DOMAIN)
197     fprintf(handle, "NTLMFLAG_TARGET_TYPE_DOMAIN ");
198   if(flags & NTLMFLAG_TARGET_TYPE_SERVER)
199     fprintf(handle, "NTLMFLAG_TARGET_TYPE_SERVER ");
200   if(flags & NTLMFLAG_TARGET_TYPE_SHARE)
201     fprintf(handle, "NTLMFLAG_TARGET_TYPE_SHARE ");
202   if(flags & NTLMFLAG_NEGOTIATE_NTLM2_KEY)
203     fprintf(handle, "NTLMFLAG_NEGOTIATE_NTLM2_KEY ");
204   if(flags & NTLMFLAG_REQUEST_INIT_RESPONSE)
205     fprintf(handle, "NTLMFLAG_REQUEST_INIT_RESPONSE ");
206   if(flags & NTLMFLAG_REQUEST_ACCEPT_RESPONSE)
207     fprintf(handle, "NTLMFLAG_REQUEST_ACCEPT_RESPONSE ");
208   if(flags & NTLMFLAG_REQUEST_NONNT_SESSION_KEY)
209     fprintf(handle, "NTLMFLAG_REQUEST_NONNT_SESSION_KEY ");
210   if(flags & NTLMFLAG_NEGOTIATE_TARGET_INFO)
211     fprintf(handle, "NTLMFLAG_NEGOTIATE_TARGET_INFO ");
212   if(flags & (1<<24))
213     fprintf(handle, "NTLMFLAG_UNKNOWN_24 ");
214   if(flags & (1<<25))
215     fprintf(handle, "NTLMFLAG_UNKNOWN_25 ");
216   if(flags & (1<<26))
217     fprintf(handle, "NTLMFLAG_UNKNOWN_26 ");
218   if(flags & (1<<27))
219     fprintf(handle, "NTLMFLAG_UNKNOWN_27 ");
220   if(flags & (1<<28))
221     fprintf(handle, "NTLMFLAG_UNKNOWN_28 ");
222   if(flags & NTLMFLAG_NEGOTIATE_128)
223     fprintf(handle, "NTLMFLAG_NEGOTIATE_128 ");
224   if(flags & NTLMFLAG_NEGOTIATE_KEY_EXCHANGE)
225     fprintf(handle, "NTLMFLAG_NEGOTIATE_KEY_EXCHANGE ");
226   if(flags & NTLMFLAG_NEGOTIATE_56)
227     fprintf(handle, "NTLMFLAG_NEGOTIATE_56 ");
228 }
229
230 static void print_hex(FILE *handle, const char *buf, size_t len)
231 {
232   const char *p = buf;
233   fprintf(stderr, "0x");
234   while(len-- > 0)
235     fprintf(stderr, "%02.2x", (unsigned int)*p++);
236 }
237 #else
238 # define DEBUG_OUT(x)
239 #endif
240
241 /*
242   (*) = A "security buffer" is a triplet consisting of two shorts and one
243   long:
244
245   1. a 'short' containing the length of the buffer in bytes
246   2. a 'short' containing the allocated space for the buffer in bytes
247   3. a 'long' containing the offset to the start of the buffer from the
248      beginning of the NTLM message, in bytes.
249 */
250
251
252 CURLntlm Curl_input_ntlm(struct connectdata *conn,
253                          bool proxy,   /* if proxy or not */
254                          const char *header) /* rest of the www-authenticate:
255                                                 header */
256 {
257   /* point to the correct struct with this */
258   struct ntlmdata *ntlm;
259 #ifndef USE_WINDOWS_SSPI
260   static const char type2_marker[] = { 0x02, 0x00, 0x00, 0x00 };
261 #endif
262
263 #ifdef USE_NSS
264   if(CURLE_OK != Curl_nss_force_init(conn->data))
265     return CURLNTLM_BAD;
266 #endif
267
268   ntlm = proxy?&conn->proxyntlm:&conn->ntlm;
269
270   /* skip initial whitespaces */
271   while(*header && ISSPACE(*header))
272     header++;
273
274   if(checkprefix("NTLM", header)) {
275     header += strlen("NTLM");
276
277     while(*header && ISSPACE(*header))
278       header++;
279
280     if(*header) {
281       /* We got a type-2 message here:
282
283          Index   Description         Content
284          0       NTLMSSP Signature   Null-terminated ASCII "NTLMSSP"
285                                      (0x4e544c4d53535000)
286          8       NTLM Message Type   long (0x02000000)
287          12      Target Name         security buffer(*)
288          20      Flags               long
289          24      Challenge           8 bytes
290          (32)    Context (optional)  8 bytes (two consecutive longs)
291          (40)    Target Information  (optional) security buffer(*)
292          32 (48) start of data block
293       */
294       size_t size;
295       unsigned char *buffer;
296       size = Curl_base64_decode(header, &buffer);
297       if(!buffer)
298         return CURLNTLM_BAD;
299
300       ntlm->state = NTLMSTATE_TYPE2; /* we got a type-2 */
301
302 #ifdef USE_WINDOWS_SSPI
303       ntlm->type_2 = malloc(size+1);
304       if(ntlm->type_2 == NULL) {
305         free(buffer);
306         return CURLE_OUT_OF_MEMORY;
307       }
308       ntlm->n_type_2 = size;
309       memcpy(ntlm->type_2, buffer, size);
310 #else
311       ntlm->flags = 0;
312
313       if((size < 32) ||
314          (memcmp(buffer, NTLMSSP_SIGNATURE, 8) != 0) ||
315          (memcmp(buffer+8, type2_marker, sizeof(type2_marker)) != 0)) {
316         /* This was not a good enough type-2 message */
317         free(buffer);
318         return CURLNTLM_BAD;
319       }
320
321       ntlm->flags = readint_le(&buffer[20]);
322       memcpy(ntlm->nonce, &buffer[24], 8);
323
324       DEBUG_OUT({
325         fprintf(stderr, "**** TYPE2 header flags=0x%08.8lx ", ntlm->flags);
326         print_flags(stderr, ntlm->flags);
327         fprintf(stderr, "\n                  nonce=");
328         print_hex(stderr, (char *)ntlm->nonce, 8);
329         fprintf(stderr, "\n****\n");
330         fprintf(stderr, "**** Header %s\n ", header);
331       });
332 #endif
333       free(buffer);
334     }
335     else {
336       if(ntlm->state >= NTLMSTATE_TYPE1)
337         return CURLNTLM_BAD;
338
339       ntlm->state = NTLMSTATE_TYPE1; /* we should sent away a type-1 */
340     }
341   }
342   return CURLNTLM_FINE;
343 }
344
345 #ifndef USE_WINDOWS_SSPI
346
347 #ifdef USE_SSLEAY
348 /*
349  * Turns a 56 bit key into the 64 bit, odd parity key and sets the key.  The
350  * key schedule ks is also set.
351  */
352 static void setup_des_key(const unsigned char *key_56,
353                           DES_key_schedule DESKEYARG(ks))
354 {
355   DES_cblock key;
356
357   key[0] = key_56[0];
358   key[1] = (unsigned char)(((key_56[0] << 7) & 0xFF) | (key_56[1] >> 1));
359   key[2] = (unsigned char)(((key_56[1] << 6) & 0xFF) | (key_56[2] >> 2));
360   key[3] = (unsigned char)(((key_56[2] << 5) & 0xFF) | (key_56[3] >> 3));
361   key[4] = (unsigned char)(((key_56[3] << 4) & 0xFF) | (key_56[4] >> 4));
362   key[5] = (unsigned char)(((key_56[4] << 3) & 0xFF) | (key_56[5] >> 5));
363   key[6] = (unsigned char)(((key_56[5] << 2) & 0xFF) | (key_56[6] >> 6));
364   key[7] = (unsigned char) ((key_56[6] << 1) & 0xFF);
365
366   DES_set_odd_parity(&key);
367   DES_set_key(&key, ks);
368 }
369
370 #else /* defined(USE_SSLEAY) */
371
372 /*
373  * Turns a 56 bit key into the 64 bit, odd parity key.  Used by GnuTLS and NSS.
374  */
375 static void extend_key_56_to_64(const unsigned char *key_56, char *key)
376 {
377   key[0] = key_56[0];
378   key[1] = (unsigned char)(((key_56[0] << 7) & 0xFF) | (key_56[1] >> 1));
379   key[2] = (unsigned char)(((key_56[1] << 6) & 0xFF) | (key_56[2] >> 2));
380   key[3] = (unsigned char)(((key_56[2] << 5) & 0xFF) | (key_56[3] >> 3));
381   key[4] = (unsigned char)(((key_56[3] << 4) & 0xFF) | (key_56[4] >> 4));
382   key[5] = (unsigned char)(((key_56[4] << 3) & 0xFF) | (key_56[5] >> 5));
383   key[6] = (unsigned char)(((key_56[5] << 2) & 0xFF) | (key_56[6] >> 6));
384   key[7] = (unsigned char) ((key_56[6] << 1) & 0xFF);
385 }
386
387 #if defined(USE_GNUTLS)
388
389 /*
390  * Turns a 56 bit key into the 64 bit, odd parity key and sets the key.
391  */
392 static void setup_des_key(const unsigned char *key_56,
393                           gcry_cipher_hd_t *des)
394 {
395   char key[8];
396   extend_key_56_to_64(key_56, key);
397   gcry_cipher_setkey(*des, key, 8);
398 }
399
400 #elif defined(USE_NSS)
401
402 /*
403  * Expands a 56 bit key KEY_56 to 64 bit and encrypts 64 bit of data, using
404  * the expanded key.  The caller is responsible for giving 64 bit of valid
405  * data is IN and (at least) 64 bit large buffer as OUT.
406  */
407 static bool encrypt_des(const unsigned char *in, unsigned char *out,
408                         const unsigned char *key_56)
409 {
410   const CK_MECHANISM_TYPE mech = CKM_DES_ECB; /* DES cipher in ECB mode */
411   PK11SlotInfo *slot = NULL;
412   char key[8];                                /* expanded 64 bit key */
413   SECItem key_item;
414   PK11SymKey *symkey = NULL;
415   SECItem *param = NULL;
416   PK11Context *ctx = NULL;
417   int out_len;                                /* not used, required by NSS */
418   bool rv = FALSE;
419
420   /* use internal slot for DES encryption (requires NSS to be initialized) */
421   slot = PK11_GetInternalKeySlot();
422   if(!slot)
423     return FALSE;
424
425   /* expand the 56 bit key to 64 bit and wrap by NSS */
426   extend_key_56_to_64(key_56, key);
427   key_item.data = (unsigned char *)key;
428   key_item.len = /* hard-wired */ 8;
429   symkey = PK11_ImportSymKey(slot, mech, PK11_OriginUnwrap, CKA_ENCRYPT,
430                              &key_item, NULL);
431   if(!symkey)
432     goto fail;
433
434   /* create DES encryption context */
435   param = PK11_ParamFromIV(mech, /* no IV in ECB mode */ NULL);
436   if(!param)
437     goto fail;
438   ctx = PK11_CreateContextBySymKey(mech, CKA_ENCRYPT, symkey, param);
439   if(!ctx)
440     goto fail;
441
442   /* perform the encryption */
443   if(SECSuccess == PK11_CipherOp(ctx, out, &out_len, /* outbuflen */ 8,
444                                  (unsigned char *)in, /* inbuflen */ 8)
445       && SECSuccess == PK11_Finalize(ctx))
446     rv = /* all OK */ TRUE;
447
448 fail:
449   /* cleanup */
450   if(ctx)
451     PK11_DestroyContext(ctx, PR_TRUE);
452   if(symkey)
453     PK11_FreeSymKey(symkey);
454   if(param)
455     SECITEM_FreeItem(param, PR_TRUE);
456   PK11_FreeSlot(slot);
457   return rv;
458 }
459
460 #endif /* defined(USE_NSS) */
461
462 #endif /* defined(USE_SSLEAY) */
463
464  /*
465   * takes a 21 byte array and treats it as 3 56-bit DES keys. The
466   * 8 byte plaintext is encrypted with each key and the resulting 24
467   * bytes are stored in the results array.
468   */
469 static void lm_resp(const unsigned char *keys,
470                     const unsigned char *plaintext,
471                     unsigned char *results)
472 {
473 #ifdef USE_SSLEAY
474   DES_key_schedule ks;
475
476   setup_des_key(keys, DESKEY(ks));
477   DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) results,
478                   DESKEY(ks), DES_ENCRYPT);
479
480   setup_des_key(keys+7, DESKEY(ks));
481   DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) (results+8),
482                   DESKEY(ks), DES_ENCRYPT);
483
484   setup_des_key(keys+14, DESKEY(ks));
485   DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) (results+16),
486                   DESKEY(ks), DES_ENCRYPT);
487 #elif defined(USE_GNUTLS)
488   gcry_cipher_hd_t des;
489
490   gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
491   setup_des_key(keys, &des);
492   gcry_cipher_encrypt(des, results, 8, plaintext, 8);
493   gcry_cipher_close(des);
494
495   gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
496   setup_des_key(keys+7, &des);
497   gcry_cipher_encrypt(des, results+8, 8, plaintext, 8);
498   gcry_cipher_close(des);
499
500   gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
501   setup_des_key(keys+14, &des);
502   gcry_cipher_encrypt(des, results+16, 8, plaintext, 8);
503   gcry_cipher_close(des);
504 #elif defined(USE_NSS)
505   encrypt_des(plaintext, results,    keys);
506   encrypt_des(plaintext, results+8,  keys+7);
507   encrypt_des(plaintext, results+16, keys+14);
508 #endif
509 }
510
511
512 /*
513  * Set up lanmanager hashed password
514  */
515 static void mk_lm_hash(struct SessionHandle *data,
516                        const char *password,
517                        unsigned char *lmbuffer /* 21 bytes */)
518 {
519   unsigned char pw[14];
520   static const unsigned char magic[] = {
521     0x4B, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 /* i.e. KGS!@#$% */
522   };
523   size_t len = CURLMIN(strlen(password), 14);
524
525   Curl_strntoupper((char *)pw, password, len);
526   memset(&pw[len], 0, 14-len);
527
528 #ifdef CURL_DOES_CONVERSIONS
529   /*
530    * The LanManager hashed password needs to be created using the
531    * password in the network encoding not the host encoding.
532    */
533   if(data)
534     Curl_convert_to_network(data, (char *)pw, 14);
535 #else
536   (void)data;
537 #endif
538
539   {
540     /* Create LanManager hashed password. */
541
542 #ifdef USE_SSLEAY
543     DES_key_schedule ks;
544
545     setup_des_key(pw, DESKEY(ks));
546     DES_ecb_encrypt((DES_cblock *)magic, (DES_cblock *)lmbuffer,
547                     DESKEY(ks), DES_ENCRYPT);
548
549     setup_des_key(pw+7, DESKEY(ks));
550     DES_ecb_encrypt((DES_cblock *)magic, (DES_cblock *)(lmbuffer+8),
551                     DESKEY(ks), DES_ENCRYPT);
552 #elif defined(USE_GNUTLS)
553     gcry_cipher_hd_t des;
554
555     gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
556     setup_des_key(pw, &des);
557     gcry_cipher_encrypt(des, lmbuffer, 8, magic, 8);
558     gcry_cipher_close(des);
559
560     gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
561     setup_des_key(pw+7, &des);
562     gcry_cipher_encrypt(des, lmbuffer+8, 8, magic, 8);
563     gcry_cipher_close(des);
564 #elif defined(USE_NSS)
565     encrypt_des(magic, lmbuffer,   pw);
566     encrypt_des(magic, lmbuffer+8, pw+7);
567 #endif
568
569     memset(lmbuffer + 16, 0, 21 - 16);
570   }
571 }
572
573 #if USE_NTRESPONSES
574 static void ascii_to_unicode_le(unsigned char *dest, const char *src,
575                                size_t srclen)
576 {
577   size_t i;
578   for (i=0; i<srclen; i++) {
579     dest[2*i]   = (unsigned char)src[i];
580     dest[2*i+1] =   '\0';
581   }
582 }
583
584 /*
585  * Set up nt hashed passwords
586  */
587 static CURLcode mk_nt_hash(struct SessionHandle *data,
588                            const char *password,
589                            unsigned char *ntbuffer /* 21 bytes */)
590 {
591   size_t len = strlen(password);
592   unsigned char *pw = malloc(len*2);
593   if(!pw)
594     return CURLE_OUT_OF_MEMORY;
595
596   ascii_to_unicode_le(pw, password, len);
597
598 #ifdef CURL_DOES_CONVERSIONS
599   /*
600    * The NT hashed password needs to be created using the
601    * password in the network encoding not the host encoding.
602    */
603   if(data)
604     Curl_convert_to_network(data, (char *)pw, len*2);
605 #else
606   (void)data;
607 #endif
608
609   {
610     /* Create NT hashed password. */
611 #ifdef USE_SSLEAY
612     MD4_CTX MD4pw;
613     MD4_Init(&MD4pw);
614     MD4_Update(&MD4pw, pw, 2*len);
615     MD4_Final(ntbuffer, &MD4pw);
616 #elif defined(USE_GNUTLS)
617     gcry_md_hd_t MD4pw;
618     gcry_md_open(&MD4pw, GCRY_MD_MD4, 0);
619     gcry_md_write(MD4pw, pw, 2*len);
620     memcpy (ntbuffer, gcry_md_read (MD4pw, 0), MD4_DIGEST_LENGTH);
621     gcry_md_close(MD4pw);
622 #elif defined(USE_NSS)
623     Curl_md4it(ntbuffer, pw, 2*len);
624 #endif
625
626     memset(ntbuffer + 16, 0, 21 - 16);
627   }
628
629   free(pw);
630   return CURLE_OK;
631 }
632 #endif
633
634
635 #endif
636
637 #ifdef USE_WINDOWS_SSPI
638
639 static void
640 ntlm_sspi_cleanup(struct ntlmdata *ntlm)
641 {
642   if(ntlm->type_2) {
643     free(ntlm->type_2);
644     ntlm->type_2 = NULL;
645   }
646   if(ntlm->has_handles) {
647     s_pSecFn->DeleteSecurityContext(&ntlm->c_handle);
648     s_pSecFn->FreeCredentialsHandle(&ntlm->handle);
649     ntlm->has_handles = 0;
650   }
651   if(ntlm->p_identity) {
652     if(ntlm->identity.User) free(ntlm->identity.User);
653     if(ntlm->identity.Password) free(ntlm->identity.Password);
654     if(ntlm->identity.Domain) free(ntlm->identity.Domain);
655     ntlm->p_identity = NULL;
656   }
657 }
658
659 #endif
660
661 #define SHORTPAIR(x) ((x) & 0xff), (((x) >> 8) & 0xff)
662 #define LONGQUARTET(x) ((x) & 0xff), (((x) >> 8)&0xff), \
663   (((x) >>16)&0xff), (((x)>>24) & 0xff)
664
665 #define HOSTNAME_MAX 1024
666
667 /* this is for creating ntlm header output */
668 CURLcode Curl_output_ntlm(struct connectdata *conn,
669                           bool proxy)
670 {
671   const char *domain=""; /* empty */
672   char host [HOSTNAME_MAX+ 1] = ""; /* empty */
673 #ifndef USE_WINDOWS_SSPI
674   size_t domlen = strlen(domain);
675   size_t hostlen = strlen(host);
676   size_t hostoff; /* host name offset */
677   size_t domoff;  /* domain name offset */
678 #endif
679   size_t size;
680   char *base64=NULL;
681   unsigned char ntlmbuf[1024]; /* enough, unless the user+host+domain is very
682                                   long */
683
684   /* point to the address of the pointer that holds the string to sent to the
685      server, which is for a plain host or for a HTTP proxy */
686   char **allocuserpwd;
687
688   /* point to the name and password for this */
689   const char *userp;
690   const char *passwdp;
691   /* point to the correct struct with this */
692   struct ntlmdata *ntlm;
693   struct auth *authp;
694
695   DEBUGASSERT(conn);
696   DEBUGASSERT(conn->data);
697
698 #ifdef USE_NSS
699   if(CURLE_OK != Curl_nss_force_init(conn->data))
700     return CURLE_OUT_OF_MEMORY;
701 #endif
702
703   if(proxy) {
704     allocuserpwd = &conn->allocptr.proxyuserpwd;
705     userp = conn->proxyuser;
706     passwdp = conn->proxypasswd;
707     ntlm = &conn->proxyntlm;
708     authp = &conn->data->state.authproxy;
709   }
710   else {
711     allocuserpwd = &conn->allocptr.userpwd;
712     userp = conn->user;
713     passwdp = conn->passwd;
714     ntlm = &conn->ntlm;
715     authp = &conn->data->state.authhost;
716   }
717   authp->done = FALSE;
718
719   /* not set means empty */
720   if(!userp)
721     userp="";
722
723   if(!passwdp)
724     passwdp="";
725
726 #ifdef USE_WINDOWS_SSPI
727   if (s_hSecDll == NULL) {
728     /* not thread safe and leaks - use curl_global_init() to avoid */
729     CURLcode err = Curl_sspi_global_init();
730     if (s_hSecDll == NULL)
731       return err;
732   }
733 #endif
734
735   switch(ntlm->state) {
736   case NTLMSTATE_TYPE1:
737   default: /* for the weird cases we (re)start here */
738 #ifdef USE_WINDOWS_SSPI
739   {
740     SecBuffer buf;
741     SecBufferDesc desc;
742     SECURITY_STATUS status;
743     ULONG attrs;
744     const char *user;
745     int domlen;
746     TimeStamp tsDummy; /* For Windows 9x compatibility of SPPI calls */
747
748     ntlm_sspi_cleanup(ntlm);
749
750     user = strchr(userp, '\\');
751     if(!user)
752       user = strchr(userp, '/');
753
754     if(user) {
755       domain = userp;
756       domlen = user - userp;
757       user++;
758     }
759     else {
760       user = userp;
761       domain = "";
762       domlen = 0;
763     }
764
765     if(user && *user) {
766       /* note: initialize all of this before doing the mallocs so that
767        * it can be cleaned up later without leaking memory.
768        */
769       ntlm->p_identity = &ntlm->identity;
770       memset(ntlm->p_identity, 0, sizeof(*ntlm->p_identity));
771       if((ntlm->identity.User = (unsigned char *)strdup(user)) == NULL)
772         return CURLE_OUT_OF_MEMORY;
773       ntlm->identity.UserLength = strlen(user);
774       if((ntlm->identity.Password = (unsigned char *)strdup(passwdp)) == NULL)
775         return CURLE_OUT_OF_MEMORY;
776       ntlm->identity.PasswordLength = strlen(passwdp);
777       if((ntlm->identity.Domain = malloc(domlen+1)) == NULL)
778         return CURLE_OUT_OF_MEMORY;
779       strncpy((char *)ntlm->identity.Domain, domain, domlen);
780       ntlm->identity.Domain[domlen] = '\0';
781       ntlm->identity.DomainLength = domlen;
782       ntlm->identity.Flags = SEC_WINNT_AUTH_IDENTITY_ANSI;
783     }
784     else {
785       ntlm->p_identity = NULL;
786     }
787
788     if(s_pSecFn->AcquireCredentialsHandleA(
789           NULL, (char *)"NTLM", SECPKG_CRED_OUTBOUND, NULL, ntlm->p_identity,
790           NULL, NULL, &ntlm->handle, &tsDummy
791           ) != SEC_E_OK) {
792       return CURLE_OUT_OF_MEMORY;
793     }
794
795     desc.ulVersion = SECBUFFER_VERSION;
796     desc.cBuffers  = 1;
797     desc.pBuffers  = &buf;
798     buf.cbBuffer   = sizeof(ntlmbuf);
799     buf.BufferType = SECBUFFER_TOKEN;
800     buf.pvBuffer   = ntlmbuf;
801
802     status = s_pSecFn->InitializeSecurityContextA(&ntlm->handle, NULL,
803                                                  (char *) host,
804                                                  ISC_REQ_CONFIDENTIALITY |
805                                                  ISC_REQ_REPLAY_DETECT |
806                                                  ISC_REQ_CONNECTION,
807                                                  0, SECURITY_NETWORK_DREP,
808                                                  NULL, 0,
809                                                  &ntlm->c_handle, &desc,
810                                                  &attrs, &tsDummy);
811
812     if(status == SEC_I_COMPLETE_AND_CONTINUE ||
813         status == SEC_I_CONTINUE_NEEDED) {
814       s_pSecFn->CompleteAuthToken(&ntlm->c_handle, &desc);
815     }
816     else if(status != SEC_E_OK) {
817       s_pSecFn->FreeCredentialsHandle(&ntlm->handle);
818       return CURLE_RECV_ERROR;
819     }
820
821     ntlm->has_handles = 1;
822     size = buf.cbBuffer;
823   }
824 #else
825     hostoff = 0;
826     domoff = hostoff + hostlen; /* This is 0: remember that host and domain
827                                    are empty */
828
829     /* Create and send a type-1 message:
830
831     Index Description          Content
832     0     NTLMSSP Signature    Null-terminated ASCII "NTLMSSP"
833                                (0x4e544c4d53535000)
834     8     NTLM Message Type    long (0x01000000)
835     12    Flags                long
836     16    Supplied Domain      security buffer(*)
837     24    Supplied Workstation security buffer(*)
838     32    start of data block
839
840     */
841 #if USE_NTLM2SESSION
842 #define NTLM2FLAG NTLMFLAG_NEGOTIATE_NTLM2_KEY
843 #else
844 #define NTLM2FLAG 0
845 #endif
846     snprintf((char *)ntlmbuf, sizeof(ntlmbuf), NTLMSSP_SIGNATURE "%c"
847              "\x01%c%c%c" /* 32-bit type = 1 */
848              "%c%c%c%c"   /* 32-bit NTLM flag field */
849              "%c%c"  /* domain length */
850              "%c%c"  /* domain allocated space */
851              "%c%c"  /* domain name offset */
852              "%c%c"  /* 2 zeroes */
853              "%c%c"  /* host length */
854              "%c%c"  /* host allocated space */
855              "%c%c"  /* host name offset */
856              "%c%c"  /* 2 zeroes */
857              "%s"   /* host name */
858              "%s",  /* domain string */
859              0,     /* trailing zero */
860              0,0,0, /* part of type-1 long */
861
862              LONGQUARTET(
863                NTLMFLAG_NEGOTIATE_OEM|
864                NTLMFLAG_REQUEST_TARGET|
865                NTLMFLAG_NEGOTIATE_NTLM_KEY|
866                NTLM2FLAG|
867                NTLMFLAG_NEGOTIATE_ALWAYS_SIGN
868                ),
869              SHORTPAIR(domlen),
870              SHORTPAIR(domlen),
871              SHORTPAIR(domoff),
872              0,0,
873              SHORTPAIR(hostlen),
874              SHORTPAIR(hostlen),
875              SHORTPAIR(hostoff),
876              0,0,
877              host /* this is empty */, domain /* this is empty */);
878
879     /* initial packet length */
880     size = 32 + hostlen + domlen;
881 #endif
882
883     DEBUG_OUT({
884       fprintf(stderr, "**** TYPE1 header flags=0x%02.2x%02.2x%02.2x%02.2x 0x%08.8x ",
885               LONGQUARTET(NTLMFLAG_NEGOTIATE_OEM|
886                           NTLMFLAG_REQUEST_TARGET|
887                           NTLMFLAG_NEGOTIATE_NTLM_KEY|
888                           NTLM2FLAG|
889                           NTLMFLAG_NEGOTIATE_ALWAYS_SIGN),
890               NTLMFLAG_NEGOTIATE_OEM|
891               NTLMFLAG_REQUEST_TARGET|
892               NTLMFLAG_NEGOTIATE_NTLM_KEY|
893               NTLM2FLAG|
894               NTLMFLAG_NEGOTIATE_ALWAYS_SIGN);
895       print_flags(stderr,
896                   NTLMFLAG_NEGOTIATE_OEM|
897                   NTLMFLAG_REQUEST_TARGET|
898                   NTLMFLAG_NEGOTIATE_NTLM_KEY|
899                   NTLM2FLAG|
900                   NTLMFLAG_NEGOTIATE_ALWAYS_SIGN);
901       fprintf(stderr, "\n****\n");
902     });
903
904     /* now size is the size of the base64 encoded package size */
905     size = Curl_base64_encode(NULL, (char *)ntlmbuf, size, &base64);
906
907     if(size >0 ) {
908       Curl_safefree(*allocuserpwd);
909       *allocuserpwd = aprintf("%sAuthorization: NTLM %s\r\n",
910                               proxy?"Proxy-":"",
911                               base64);
912       DEBUG_OUT(fprintf(stderr, "**** Header %s\n ", *allocuserpwd));
913       free(base64);
914     }
915     else
916       return CURLE_OUT_OF_MEMORY; /* FIX TODO */
917
918     break;
919
920   case NTLMSTATE_TYPE2:
921     /* We received the type-2 message already, create a type-3 message:
922
923     Index   Description            Content
924     0       NTLMSSP Signature      Null-terminated ASCII "NTLMSSP"
925                                    (0x4e544c4d53535000)
926     8       NTLM Message Type      long (0x03000000)
927     12      LM/LMv2 Response       security buffer(*)
928     20      NTLM/NTLMv2 Response   security buffer(*)
929     28      Domain Name            security buffer(*)
930     36      User Name              security buffer(*)
931     44      Workstation Name       security buffer(*)
932     (52)    Session Key (optional) security buffer(*)
933     (60)    Flags (optional)       long
934     52 (64) start of data block
935
936     */
937
938   {
939 #ifdef USE_WINDOWS_SSPI
940     SecBuffer type_2, type_3;
941     SecBufferDesc type_2_desc, type_3_desc;
942     SECURITY_STATUS status;
943     ULONG attrs;
944     TimeStamp tsDummy; /* For Windows 9x compatibility of SPPI calls */
945
946     type_2_desc.ulVersion  = type_3_desc.ulVersion  = SECBUFFER_VERSION;
947     type_2_desc.cBuffers   = type_3_desc.cBuffers   = 1;
948     type_2_desc.pBuffers   = &type_2;
949     type_3_desc.pBuffers   = &type_3;
950
951     type_2.BufferType = SECBUFFER_TOKEN;
952     type_2.pvBuffer   = ntlm->type_2;
953     type_2.cbBuffer   = ntlm->n_type_2;
954     type_3.BufferType = SECBUFFER_TOKEN;
955     type_3.pvBuffer   = ntlmbuf;
956     type_3.cbBuffer   = sizeof(ntlmbuf);
957
958     status = s_pSecFn->InitializeSecurityContextA(&ntlm->handle, &ntlm->c_handle,
959                                        (char *) host,
960                                        ISC_REQ_CONFIDENTIALITY |
961                                        ISC_REQ_REPLAY_DETECT |
962                                        ISC_REQ_CONNECTION,
963                                        0, SECURITY_NETWORK_DREP, &type_2_desc,
964                                        0, &ntlm->c_handle, &type_3_desc,
965                                        &attrs, &tsDummy);
966
967     if(status != SEC_E_OK)
968       return CURLE_RECV_ERROR;
969
970     size = type_3.cbBuffer;
971
972     ntlm_sspi_cleanup(ntlm);
973
974 #else
975     int lmrespoff;
976     unsigned char lmresp[24]; /* fixed-size */
977 #if USE_NTRESPONSES
978     int ntrespoff;
979     unsigned char ntresp[24]; /* fixed-size */
980 #endif
981     size_t useroff;
982     const char *user;
983     size_t userlen;
984
985     user = strchr(userp, '\\');
986     if(!user)
987       user = strchr(userp, '/');
988
989     if(user) {
990       domain = userp;
991       domlen = (user - domain);
992       user++;
993     }
994     else
995       user = userp;
996     userlen = strlen(user);
997
998     if(Curl_gethostname(host, HOSTNAME_MAX)) {
999       infof(conn->data, "gethostname() failed, continuing without!");
1000       hostlen = 0;
1001     }
1002     else {
1003       /* If the workstation if configured with a full DNS name (i.e.
1004        * workstation.somewhere.net) gethostname() returns the fully qualified
1005        * name, which NTLM doesn't like.
1006        */
1007       char *dot = strchr(host, '.');
1008       if(dot)
1009         *dot = '\0';
1010       hostlen = strlen(host);
1011     }
1012
1013 #if USE_NTLM2SESSION
1014     /* We don't support NTLM2 if we don't have USE_NTRESPONSES */
1015     if(ntlm->flags & NTLMFLAG_NEGOTIATE_NTLM2_KEY) {
1016       unsigned char ntbuffer[0x18];
1017       unsigned char tmp[0x18];
1018       unsigned char md5sum[MD5_DIGEST_LENGTH];
1019       unsigned char entropy[8];
1020
1021       /* Need to create 8 bytes random data */
1022 #ifdef USE_SSLEAY
1023       MD5_CTX MD5pw;
1024       Curl_ossl_seed(conn->data); /* Initiate the seed if not already done */
1025       RAND_bytes(entropy,8);
1026 #elif defined(USE_GNUTLS)
1027       gcry_md_hd_t MD5pw;
1028       Curl_gtls_seed(conn->data); /* Initiate the seed if not already done */
1029       gcry_randomize(entropy, 8, GCRY_STRONG_RANDOM);
1030 #elif defined(USE_NSS)
1031       PK11Context *MD5pw;
1032       unsigned int outlen;
1033       Curl_nss_seed(conn->data);  /* Initiate the seed if not already done */
1034       PK11_GenerateRandom(entropy, 8);
1035 #endif
1036
1037       /* 8 bytes random data as challenge in lmresp */
1038       memcpy(lmresp,entropy,8);
1039       /* Pad with zeros */
1040       memset(lmresp+8,0,0x10);
1041
1042       /* Fill tmp with challenge(nonce?) + entropy */
1043       memcpy(tmp,&ntlm->nonce[0],8);
1044       memcpy(tmp+8,entropy,8);
1045
1046 #ifdef USE_SSLEAY
1047       MD5_Init(&MD5pw);
1048       MD5_Update(&MD5pw, tmp, 16);
1049       MD5_Final(md5sum, &MD5pw);
1050 #elif defined(USE_GNUTLS)
1051       gcry_md_open(&MD5pw, GCRY_MD_MD5, 0);
1052       gcry_md_write(MD5pw, tmp, MD5_DIGEST_LENGTH);
1053       memcpy(md5sum, gcry_md_read (MD5pw, 0), MD5_DIGEST_LENGTH);
1054       gcry_md_close(MD5pw);
1055 #elif defined(USE_NSS)
1056       MD5pw = PK11_CreateDigestContext(SEC_OID_MD5);
1057       PK11_DigestOp(MD5pw, tmp, 16);
1058       PK11_DigestFinal(MD5pw, md5sum, &outlen, MD5_DIGEST_LENGTH);
1059       PK11_DestroyContext(MD5pw, PR_TRUE);
1060 #endif
1061
1062       /* We shall only use the first 8 bytes of md5sum,
1063          but the des code in lm_resp only encrypt the first 8 bytes */
1064       if(mk_nt_hash(conn->data, passwdp, ntbuffer) == CURLE_OUT_OF_MEMORY)
1065         return CURLE_OUT_OF_MEMORY;
1066       lm_resp(ntbuffer, md5sum, ntresp);
1067
1068       /* End of NTLM2 Session code */
1069     }
1070     else
1071 #endif
1072         {
1073
1074 #if USE_NTRESPONSES
1075       unsigned char ntbuffer[0x18];
1076 #endif
1077       unsigned char lmbuffer[0x18];
1078
1079 #if USE_NTRESPONSES
1080       if(mk_nt_hash(conn->data, passwdp, ntbuffer) == CURLE_OUT_OF_MEMORY)
1081         return CURLE_OUT_OF_MEMORY;
1082       lm_resp(ntbuffer, &ntlm->nonce[0], ntresp);
1083 #endif
1084
1085       mk_lm_hash(conn->data, passwdp, lmbuffer);
1086       lm_resp(lmbuffer, &ntlm->nonce[0], lmresp);
1087       /* A safer but less compatible alternative is:
1088        *   lm_resp(ntbuffer, &ntlm->nonce[0], lmresp);
1089        * See http://davenport.sourceforge.net/ntlm.html#ntlmVersion2 */
1090     }
1091
1092     lmrespoff = 64; /* size of the message header */
1093 #if USE_NTRESPONSES
1094     ntrespoff = lmrespoff + 0x18;
1095     domoff = ntrespoff + 0x18;
1096 #else
1097     domoff = lmrespoff + 0x18;
1098 #endif
1099     useroff = domoff + domlen;
1100     hostoff = useroff + userlen;
1101
1102     /*
1103      * In the case the server sets the flag NTLMFLAG_NEGOTIATE_UNICODE, we
1104      * need to filter it off because libcurl doesn't UNICODE encode the
1105      * strings it packs into the NTLM authenticate packet.
1106      */
1107     ntlm->flags &= ~NTLMFLAG_NEGOTIATE_UNICODE;
1108
1109     /* Create the big type-3 message binary blob */
1110     size = snprintf((char *)ntlmbuf, sizeof(ntlmbuf),
1111                     NTLMSSP_SIGNATURE "%c"
1112                     "\x03%c%c%c" /* type-3, 32 bits */
1113
1114                     "%c%c" /* LanManager length */
1115                     "%c%c" /* LanManager allocated space */
1116                     "%c%c" /* LanManager offset */
1117                     "%c%c" /* 2 zeroes */
1118
1119                     "%c%c" /* NT-response length */
1120                     "%c%c" /* NT-response allocated space */
1121                     "%c%c" /* NT-response offset */
1122                     "%c%c" /* 2 zeroes */
1123
1124                     "%c%c"  /* domain length */
1125                     "%c%c"  /* domain allocated space */
1126                     "%c%c"  /* domain name offset */
1127                     "%c%c"  /* 2 zeroes */
1128
1129                     "%c%c"  /* user length */
1130                     "%c%c"  /* user allocated space */
1131                     "%c%c"  /* user offset */
1132                     "%c%c"  /* 2 zeroes */
1133
1134                     "%c%c"  /* host length */
1135                     "%c%c"  /* host allocated space */
1136                     "%c%c"  /* host offset */
1137                     "%c%c"  /* 2 zeroes */
1138
1139                     "%c%c"  /* session key length (unknown purpose) */
1140                     "%c%c"  /* session key allocated space (unknown purpose) */
1141                     "%c%c"  /* session key offset (unknown purpose) */
1142                     "%c%c"  /* 2 zeroes */
1143
1144                     "%c%c%c%c" /* flags */
1145
1146                     /* domain string */
1147                     /* user string */
1148                     /* host string */
1149                     /* LanManager response */
1150                     /* NT response */
1151                     ,
1152                     0, /* zero termination */
1153                     0,0,0, /* type-3 long, the 24 upper bits */
1154
1155                     SHORTPAIR(0x18),  /* LanManager response length, twice */
1156                     SHORTPAIR(0x18),
1157                     SHORTPAIR(lmrespoff),
1158                     0x0, 0x0,
1159
1160 #if USE_NTRESPONSES
1161                     SHORTPAIR(0x18),  /* NT-response length, twice */
1162                     SHORTPAIR(0x18),
1163                     SHORTPAIR(ntrespoff),
1164                     0x0, 0x0,
1165 #else
1166                     0x0, 0x0,
1167                     0x0, 0x0,
1168                     0x0, 0x0,
1169                     0x0, 0x0,
1170 #endif
1171                     SHORTPAIR(domlen),
1172                     SHORTPAIR(domlen),
1173                     SHORTPAIR(domoff),
1174                     0x0, 0x0,
1175
1176                     SHORTPAIR(userlen),
1177                     SHORTPAIR(userlen),
1178                     SHORTPAIR(useroff),
1179                     0x0, 0x0,
1180
1181                     SHORTPAIR(hostlen),
1182                     SHORTPAIR(hostlen),
1183                     SHORTPAIR(hostoff),
1184                     0x0, 0x0,
1185
1186                     0x0, 0x0,
1187                     0x0, 0x0,
1188                     0x0, 0x0,
1189                     0x0, 0x0,
1190
1191                     LONGQUARTET(ntlm->flags));
1192     DEBUGASSERT(size==64);
1193
1194     DEBUGASSERT(size == (size_t)lmrespoff);
1195     /* We append the binary hashes */
1196     if(size < (sizeof(ntlmbuf) - 0x18)) {
1197       memcpy(&ntlmbuf[size], lmresp, 0x18);
1198       size += 0x18;
1199     }
1200
1201     DEBUG_OUT({
1202         fprintf(stderr, "**** TYPE3 header lmresp=");
1203         print_hex(stderr, (char *)&ntlmbuf[lmrespoff], 0x18);
1204     });
1205
1206 #if USE_NTRESPONSES
1207     if(size < (sizeof(ntlmbuf) - 0x18)) {
1208       DEBUGASSERT(size == (size_t)ntrespoff);
1209       memcpy(&ntlmbuf[size], ntresp, 0x18);
1210       size += 0x18;
1211     }
1212
1213     DEBUG_OUT({
1214         fprintf(stderr, "\n                  ntresp=");
1215         print_hex(stderr, (char *)&ntlmbuf[ntrespoff], 0x18);
1216     });
1217
1218 #endif
1219
1220     DEBUG_OUT({
1221         fprintf(stderr, "\n                  flags=0x%02.2x%02.2x%02.2x%02.2x 0x%08.8x ",
1222                 LONGQUARTET(ntlm->flags), ntlm->flags);
1223         print_flags(stderr, ntlm->flags);
1224         fprintf(stderr, "\n****\n");
1225     });
1226
1227
1228     /* Make sure that the domain, user and host strings fit in the target
1229        buffer before we copy them there. */
1230     if(size + userlen + domlen + hostlen >= sizeof(ntlmbuf)) {
1231       failf(conn->data, "user + domain + host name too big");
1232       return CURLE_OUT_OF_MEMORY;
1233     }
1234
1235     DEBUGASSERT(size == domoff);
1236     memcpy(&ntlmbuf[size], domain, domlen);
1237     size += domlen;
1238
1239     DEBUGASSERT(size == useroff);
1240     memcpy(&ntlmbuf[size], user, userlen);
1241     size += userlen;
1242
1243     DEBUGASSERT(size == hostoff);
1244     memcpy(&ntlmbuf[size], host, hostlen);
1245     size += hostlen;
1246
1247 #ifdef CURL_DOES_CONVERSIONS
1248     /* convert domain, user, and host to ASCII but leave the rest as-is */
1249     if(CURLE_OK != Curl_convert_to_network(conn->data,
1250                                            (char *)&ntlmbuf[domoff],
1251                                            size-domoff)) {
1252       return CURLE_CONV_FAILED;
1253     }
1254 #endif /* CURL_DOES_CONVERSIONS */
1255
1256 #endif
1257
1258     /* convert the binary blob into base64 */
1259     size = Curl_base64_encode(NULL, (char *)ntlmbuf, size, &base64);
1260
1261     if(size >0 ) {
1262       Curl_safefree(*allocuserpwd);
1263       *allocuserpwd = aprintf("%sAuthorization: NTLM %s\r\n",
1264                               proxy?"Proxy-":"",
1265                               base64);
1266       DEBUG_OUT(fprintf(stderr, "**** %s\n ", *allocuserpwd));
1267       free(base64);
1268     }
1269     else
1270       return CURLE_OUT_OF_MEMORY; /* FIX TODO */
1271
1272     ntlm->state = NTLMSTATE_TYPE3; /* we sent a type-3 */
1273     authp->done = TRUE;
1274   }
1275   break;
1276
1277   case NTLMSTATE_TYPE3:
1278     /* connection is already authenticated,
1279      * don't send a header in future requests */
1280     if(*allocuserpwd) {
1281       free(*allocuserpwd);
1282       *allocuserpwd=NULL;
1283     }
1284     authp->done = TRUE;
1285     break;
1286   }
1287
1288   return CURLE_OK;
1289 }
1290
1291
1292 void
1293 Curl_ntlm_cleanup(struct connectdata *conn)
1294 {
1295 #ifdef USE_WINDOWS_SSPI
1296   ntlm_sspi_cleanup(&conn->ntlm);
1297   ntlm_sspi_cleanup(&conn->proxyntlm);
1298 #else
1299   (void)conn;
1300 #endif
1301 }
1302
1303
1304 #endif /* USE_NTLM */
1305 #endif /* !CURL_DISABLE_HTTP */