1 /***************************************************************************
2 * _ _ ____ _
3 * Project ___| | | | _ \| |
4 * / __| | | | |_) | |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
7 *
8 * Copyright (C) 1998 - 2011, 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 "non-ascii.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 */
readint_le(unsigned char * buf)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
print_flags(FILE * handle,unsigned long flags)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
print_hex(FILE * handle,const char * buf,size_t len)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
Curl_input_ntlm(struct connectdata * conn,bool proxy,const char * header)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 */
setup_des_key(const unsigned char * key_56,DES_key_schedule DESKEYARG (ks))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 */
extend_key_56_to_64(const unsigned char * key_56,char * key)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 */
setup_des_key(const unsigned char * key_56,gcry_cipher_hd_t * des)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 */
encrypt_des(const unsigned char * in,unsigned char * out,const unsigned char * key_56)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 */
lm_resp(const unsigned char * keys,const unsigned char * plaintext,unsigned char * results)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 */
mk_lm_hash(struct SessionHandle * data,const char * password,unsigned char * lmbuffer)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 /*
529 * The LanManager hashed password needs to be created using the
530 * password in the network encoding not the host encoding.
531 */
532 if(Curl_convert_to_network(data, (char *)pw, 14))
533 return;
534
535 {
536 /* Create LanManager hashed password. */
537
538 #ifdef USE_SSLEAY
539 DES_key_schedule ks;
540
541 setup_des_key(pw, DESKEY(ks));
542 DES_ecb_encrypt((DES_cblock *)magic, (DES_cblock *)lmbuffer,
543 DESKEY(ks), DES_ENCRYPT);
544
545 setup_des_key(pw+7, DESKEY(ks));
546 DES_ecb_encrypt((DES_cblock *)magic, (DES_cblock *)(lmbuffer+8),
547 DESKEY(ks), DES_ENCRYPT);
548 #elif defined(USE_GNUTLS)
549 gcry_cipher_hd_t des;
550
551 gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
552 setup_des_key(pw, &des);
553 gcry_cipher_encrypt(des, lmbuffer, 8, magic, 8);
554 gcry_cipher_close(des);
555
556 gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
557 setup_des_key(pw+7, &des);
558 gcry_cipher_encrypt(des, lmbuffer+8, 8, magic, 8);
559 gcry_cipher_close(des);
560 #elif defined(USE_NSS)
561 encrypt_des(magic, lmbuffer, pw);
562 encrypt_des(magic, lmbuffer+8, pw+7);
563 #endif
564
565 memset(lmbuffer + 16, 0, 21 - 16);
566 }
567 }
568
569 #if USE_NTRESPONSES
ascii_to_unicode_le(unsigned char * dest,const char * src,size_t srclen)570 static void ascii_to_unicode_le(unsigned char *dest, const char *src,
571 size_t srclen)
572 {
573 size_t i;
574 for (i=0; i<srclen; i++) {
575 dest[2*i] = (unsigned char)src[i];
576 dest[2*i+1] = '\0';
577 }
578 }
579
580 /*
581 * Set up nt hashed passwords
582 */
mk_nt_hash(struct SessionHandle * data,const char * password,unsigned char * ntbuffer)583 static CURLcode mk_nt_hash(struct SessionHandle *data,
584 const char *password,
585 unsigned char *ntbuffer /* 21 bytes */)
586 {
587 size_t len = strlen(password);
588 unsigned char *pw = malloc(len*2);
589 CURLcode result;
590 if(!pw)
591 return CURLE_OUT_OF_MEMORY;
592
593 ascii_to_unicode_le(pw, password, len);
594
595 /*
596 * The NT hashed password needs to be created using the password in the
597 * network encoding not the host encoding.
598 */
599 result = Curl_convert_to_network(data, (char *)pw, len*2);
600 if(result)
601 return result;
602
603 {
604 /* Create NT hashed password. */
605 #ifdef USE_SSLEAY
606 MD4_CTX MD4pw;
607 MD4_Init(&MD4pw);
608 MD4_Update(&MD4pw, pw, 2*len);
609 MD4_Final(ntbuffer, &MD4pw);
610 #elif defined(USE_GNUTLS)
611 gcry_md_hd_t MD4pw;
612 gcry_md_open(&MD4pw, GCRY_MD_MD4, 0);
613 gcry_md_write(MD4pw, pw, 2*len);
614 memcpy (ntbuffer, gcry_md_read (MD4pw, 0), MD4_DIGEST_LENGTH);
615 gcry_md_close(MD4pw);
616 #elif defined(USE_NSS)
617 Curl_md4it(ntbuffer, pw, 2*len);
618 #endif
619
620 memset(ntbuffer + 16, 0, 21 - 16);
621 }
622
623 free(pw);
624 return CURLE_OK;
625 }
626 #endif
627
628
629 #endif
630
631 #ifdef USE_WINDOWS_SSPI
632
633 static void
ntlm_sspi_cleanup(struct ntlmdata * ntlm)634 ntlm_sspi_cleanup(struct ntlmdata *ntlm)
635 {
636 if(ntlm->type_2) {
637 free(ntlm->type_2);
638 ntlm->type_2 = NULL;
639 }
640 if(ntlm->has_handles) {
641 s_pSecFn->DeleteSecurityContext(&ntlm->c_handle);
642 s_pSecFn->FreeCredentialsHandle(&ntlm->handle);
643 ntlm->has_handles = 0;
644 }
645 if(ntlm->p_identity) {
646 if(ntlm->identity.User) free(ntlm->identity.User);
647 if(ntlm->identity.Password) free(ntlm->identity.Password);
648 if(ntlm->identity.Domain) free(ntlm->identity.Domain);
649 ntlm->p_identity = NULL;
650 }
651 }
652
653 #endif
654
655 #define SHORTPAIR(x) ((x) & 0xff), (((x) >> 8) & 0xff)
656 #define LONGQUARTET(x) ((x) & 0xff), (((x) >> 8)&0xff), \
657 (((x) >>16)&0xff), (((x)>>24) & 0xff)
658
659 #define HOSTNAME_MAX 1024
660
661 /* this is for creating ntlm header output */
Curl_output_ntlm(struct connectdata * conn,bool proxy)662 CURLcode Curl_output_ntlm(struct connectdata *conn,
663 bool proxy)
664 {
665 const char *domain=""; /* empty */
666 char host [HOSTNAME_MAX+ 1] = ""; /* empty */
667 #ifndef USE_WINDOWS_SSPI
668 size_t domlen = strlen(domain);
669 size_t hostlen = strlen(host);
670 size_t hostoff; /* host name offset */
671 size_t domoff; /* domain name offset */
672 #endif
673 size_t size;
674 char *base64=NULL;
675 unsigned char ntlmbuf[1024]; /* enough, unless the user+host+domain is very
676 long */
677
678 /* point to the address of the pointer that holds the string to sent to the
679 server, which is for a plain host or for a HTTP proxy */
680 char **allocuserpwd;
681
682 /* point to the name and password for this */
683 const char *userp;
684 const char *passwdp;
685 /* point to the correct struct with this */
686 struct ntlmdata *ntlm;
687 struct auth *authp;
688
689 DEBUGASSERT(conn);
690 DEBUGASSERT(conn->data);
691
692 #ifdef USE_NSS
693 if(CURLE_OK != Curl_nss_force_init(conn->data))
694 return CURLE_OUT_OF_MEMORY;
695 #endif
696
697 if(proxy) {
698 allocuserpwd = &conn->allocptr.proxyuserpwd;
699 userp = conn->proxyuser;
700 passwdp = conn->proxypasswd;
701 ntlm = &conn->proxyntlm;
702 authp = &conn->data->state.authproxy;
703 }
704 else {
705 allocuserpwd = &conn->allocptr.userpwd;
706 userp = conn->user;
707 passwdp = conn->passwd;
708 ntlm = &conn->ntlm;
709 authp = &conn->data->state.authhost;
710 }
711 authp->done = FALSE;
712
713 /* not set means empty */
714 if(!userp)
715 userp="";
716
717 if(!passwdp)
718 passwdp="";
719
720 #ifdef USE_WINDOWS_SSPI
721 if (s_hSecDll == NULL) {
722 /* not thread safe and leaks - use curl_global_init() to avoid */
723 CURLcode err = Curl_sspi_global_init();
724 if (s_hSecDll == NULL)
725 return err;
726 }
727 #endif
728
729 switch(ntlm->state) {
730 case NTLMSTATE_TYPE1:
731 default: /* for the weird cases we (re)start here */
732 #ifdef USE_WINDOWS_SSPI
733 {
734 SecBuffer buf;
735 SecBufferDesc desc;
736 SECURITY_STATUS status;
737 ULONG attrs;
738 const char *user;
739 int domlen;
740 TimeStamp tsDummy; /* For Windows 9x compatibility of SPPI calls */
741
742 ntlm_sspi_cleanup(ntlm);
743
744 user = strchr(userp, '\\');
745 if(!user)
746 user = strchr(userp, '/');
747
748 if(user) {
749 domain = userp;
750 domlen = user - userp;
751 user++;
752 }
753 else {
754 user = userp;
755 domain = "";
756 domlen = 0;
757 }
758
759 if(user && *user) {
760 /* note: initialize all of this before doing the mallocs so that
761 * it can be cleaned up later without leaking memory.
762 */
763 ntlm->p_identity = &ntlm->identity;
764 memset(ntlm->p_identity, 0, sizeof(*ntlm->p_identity));
765 if((ntlm->identity.User = (unsigned char *)strdup(user)) == NULL)
766 return CURLE_OUT_OF_MEMORY;
767 ntlm->identity.UserLength = strlen(user);
768 if((ntlm->identity.Password = (unsigned char *)strdup(passwdp)) == NULL)
769 return CURLE_OUT_OF_MEMORY;
770 ntlm->identity.PasswordLength = strlen(passwdp);
771 if((ntlm->identity.Domain = malloc(domlen+1)) == NULL)
772 return CURLE_OUT_OF_MEMORY;
773 strncpy((char *)ntlm->identity.Domain, domain, domlen);
774 ntlm->identity.Domain[domlen] = '\0';
775 ntlm->identity.DomainLength = domlen;
776 ntlm->identity.Flags = SEC_WINNT_AUTH_IDENTITY_ANSI;
777 }
778 else {
779 ntlm->p_identity = NULL;
780 }
781
782 if(s_pSecFn->AcquireCredentialsHandleA(
783 NULL, (char *)"NTLM", SECPKG_CRED_OUTBOUND, NULL, ntlm->p_identity,
784 NULL, NULL, &ntlm->handle, &tsDummy
785 ) != SEC_E_OK) {
786 return CURLE_OUT_OF_MEMORY;
787 }
788
789 desc.ulVersion = SECBUFFER_VERSION;
790 desc.cBuffers = 1;
791 desc.pBuffers = &buf;
792 buf.cbBuffer = sizeof(ntlmbuf);
793 buf.BufferType = SECBUFFER_TOKEN;
794 buf.pvBuffer = ntlmbuf;
795
796 status = s_pSecFn->InitializeSecurityContextA(&ntlm->handle, NULL,
797 (char *) host,
798 ISC_REQ_CONFIDENTIALITY |
799 ISC_REQ_REPLAY_DETECT |
800 ISC_REQ_CONNECTION,
801 0, SECURITY_NETWORK_DREP,
802 NULL, 0,
803 &ntlm->c_handle, &desc,
804 &attrs, &tsDummy);
805
806 if(status == SEC_I_COMPLETE_AND_CONTINUE ||
807 status == SEC_I_CONTINUE_NEEDED) {
808 s_pSecFn->CompleteAuthToken(&ntlm->c_handle, &desc);
809 }
810 else if(status != SEC_E_OK) {
811 s_pSecFn->FreeCredentialsHandle(&ntlm->handle);
812 return CURLE_RECV_ERROR;
813 }
814
815 ntlm->has_handles = 1;
816 size = buf.cbBuffer;
817 }
818 #else
819 hostoff = 0;
820 domoff = hostoff + hostlen; /* This is 0: remember that host and domain
821 are empty */
822
823 /* Create and send a type-1 message:
824
825 Index Description Content
826 0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP"
827 (0x4e544c4d53535000)
828 8 NTLM Message Type long (0x01000000)
829 12 Flags long
830 16 Supplied Domain security buffer(*)
831 24 Supplied Workstation security buffer(*)
832 32 start of data block
833
834 */
835 #if USE_NTLM2SESSION
836 #define NTLM2FLAG NTLMFLAG_NEGOTIATE_NTLM2_KEY
837 #else
838 #define NTLM2FLAG 0
839 #endif
840 snprintf((char *)ntlmbuf, sizeof(ntlmbuf), NTLMSSP_SIGNATURE "%c"
841 "\x01%c%c%c" /* 32-bit type = 1 */
842 "%c%c%c%c" /* 32-bit NTLM flag field */
843 "%c%c" /* domain length */
844 "%c%c" /* domain allocated space */
845 "%c%c" /* domain name offset */
846 "%c%c" /* 2 zeroes */
847 "%c%c" /* host length */
848 "%c%c" /* host allocated space */
849 "%c%c" /* host name offset */
850 "%c%c" /* 2 zeroes */
851 "%s" /* host name */
852 "%s", /* domain string */
853 0, /* trailing zero */
854 0,0,0, /* part of type-1 long */
855
856 LONGQUARTET(
857 NTLMFLAG_NEGOTIATE_OEM|
858 NTLMFLAG_REQUEST_TARGET|
859 NTLMFLAG_NEGOTIATE_NTLM_KEY|
860 NTLM2FLAG|
861 NTLMFLAG_NEGOTIATE_ALWAYS_SIGN
862 ),
863 SHORTPAIR(domlen),
864 SHORTPAIR(domlen),
865 SHORTPAIR(domoff),
866 0,0,
867 SHORTPAIR(hostlen),
868 SHORTPAIR(hostlen),
869 SHORTPAIR(hostoff),
870 0,0,
871 host /* this is empty */, domain /* this is empty */);
872
873 /* initial packet length */
874 size = 32 + hostlen + domlen;
875 #endif
876
877 DEBUG_OUT({
878 fprintf(stderr, "**** TYPE1 header flags=0x%02.2x%02.2x%02.2x%02.2x 0x%08.8x ",
879 LONGQUARTET(NTLMFLAG_NEGOTIATE_OEM|
880 NTLMFLAG_REQUEST_TARGET|
881 NTLMFLAG_NEGOTIATE_NTLM_KEY|
882 NTLM2FLAG|
883 NTLMFLAG_NEGOTIATE_ALWAYS_SIGN),
884 NTLMFLAG_NEGOTIATE_OEM|
885 NTLMFLAG_REQUEST_TARGET|
886 NTLMFLAG_NEGOTIATE_NTLM_KEY|
887 NTLM2FLAG|
888 NTLMFLAG_NEGOTIATE_ALWAYS_SIGN);
889 print_flags(stderr,
890 NTLMFLAG_NEGOTIATE_OEM|
891 NTLMFLAG_REQUEST_TARGET|
892 NTLMFLAG_NEGOTIATE_NTLM_KEY|
893 NTLM2FLAG|
894 NTLMFLAG_NEGOTIATE_ALWAYS_SIGN);
895 fprintf(stderr, "\n****\n");
896 });
897
898 /* now size is the size of the base64 encoded package size */
899 size = Curl_base64_encode(NULL, (char *)ntlmbuf, size, &base64);
900
901 if(size >0 ) {
902 Curl_safefree(*allocuserpwd);
903 *allocuserpwd = aprintf("%sAuthorization: NTLM %s\r\n",
904 proxy?"Proxy-":"",
905 base64);
906 DEBUG_OUT(fprintf(stderr, "**** Header %s\n ", *allocuserpwd));
907 free(base64);
908 }
909 else
910 return CURLE_OUT_OF_MEMORY; /* FIX TODO */
911
912 break;
913
914 case NTLMSTATE_TYPE2:
915 /* We received the type-2 message already, create a type-3 message:
916
917 Index Description Content
918 0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP"
919 (0x4e544c4d53535000)
920 8 NTLM Message Type long (0x03000000)
921 12 LM/LMv2 Response security buffer(*)
922 20 NTLM/NTLMv2 Response security buffer(*)
923 28 Domain Name security buffer(*)
924 36 User Name security buffer(*)
925 44 Workstation Name security buffer(*)
926 (52) Session Key (optional) security buffer(*)
927 (60) Flags (optional) long
928 52 (64) start of data block
929
930 */
931
932 {
933 #ifdef USE_WINDOWS_SSPI
934 SecBuffer type_2, type_3;
935 SecBufferDesc type_2_desc, type_3_desc;
936 SECURITY_STATUS status;
937 ULONG attrs;
938 TimeStamp tsDummy; /* For Windows 9x compatibility of SPPI calls */
939
940 type_2_desc.ulVersion = type_3_desc.ulVersion = SECBUFFER_VERSION;
941 type_2_desc.cBuffers = type_3_desc.cBuffers = 1;
942 type_2_desc.pBuffers = &type_2;
943 type_3_desc.pBuffers = &type_3;
944
945 type_2.BufferType = SECBUFFER_TOKEN;
946 type_2.pvBuffer = ntlm->type_2;
947 type_2.cbBuffer = ntlm->n_type_2;
948 type_3.BufferType = SECBUFFER_TOKEN;
949 type_3.pvBuffer = ntlmbuf;
950 type_3.cbBuffer = sizeof(ntlmbuf);
951
952 status = s_pSecFn->InitializeSecurityContextA(&ntlm->handle, &ntlm->c_handle,
953 (char *) host,
954 ISC_REQ_CONFIDENTIALITY |
955 ISC_REQ_REPLAY_DETECT |
956 ISC_REQ_CONNECTION,
957 0, SECURITY_NETWORK_DREP, &type_2_desc,
958 0, &ntlm->c_handle, &type_3_desc,
959 &attrs, &tsDummy);
960
961 if(status != SEC_E_OK)
962 return CURLE_RECV_ERROR;
963
964 size = type_3.cbBuffer;
965
966 ntlm_sspi_cleanup(ntlm);
967
968 #else
969 int lmrespoff;
970 unsigned char lmresp[24]; /* fixed-size */
971 #if USE_NTRESPONSES
972 int ntrespoff;
973 unsigned char ntresp[24]; /* fixed-size */
974 #endif
975 size_t useroff;
976 const char *user;
977 size_t userlen;
978
979 user = strchr(userp, '\\');
980 if(!user)
981 user = strchr(userp, '/');
982
983 if(user) {
984 domain = userp;
985 domlen = (user - domain);
986 user++;
987 }
988 else
989 user = userp;
990 userlen = strlen(user);
991
992 if(Curl_gethostname(host, HOSTNAME_MAX)) {
993 infof(conn->data, "gethostname() failed, continuing without!");
994 hostlen = 0;
995 }
996 else {
997 /* If the workstation if configured with a full DNS name (i.e.
998 * workstation.somewhere.net) gethostname() returns the fully qualified
999 * name, which NTLM doesn't like.
1000 */
1001 char *dot = strchr(host, '.');
1002 if(dot)
1003 *dot = '\0';
1004 hostlen = strlen(host);
1005 }
1006
1007 #if USE_NTLM2SESSION
1008 /* We don't support NTLM2 if we don't have USE_NTRESPONSES */
1009 if(ntlm->flags & NTLMFLAG_NEGOTIATE_NTLM2_KEY) {
1010 unsigned char ntbuffer[0x18];
1011 unsigned char tmp[0x18];
1012 unsigned char md5sum[MD5_DIGEST_LENGTH];
1013 unsigned char entropy[8];
1014
1015 /* Need to create 8 bytes random data */
1016 #ifdef USE_SSLEAY
1017 MD5_CTX MD5pw;
1018 Curl_ossl_seed(conn->data); /* Initiate the seed if not already done */
1019 RAND_bytes(entropy,8);
1020 #elif defined(USE_GNUTLS)
1021 gcry_md_hd_t MD5pw;
1022 Curl_gtls_seed(conn->data); /* Initiate the seed if not already done */
1023 gcry_randomize(entropy, 8, GCRY_STRONG_RANDOM);
1024 #elif defined(USE_NSS)
1025 PK11Context *MD5pw;
1026 unsigned int outlen;
1027 Curl_nss_seed(conn->data); /* Initiate the seed if not already done */
1028 PK11_GenerateRandom(entropy, 8);
1029 #endif
1030
1031 /* 8 bytes random data as challenge in lmresp */
1032 memcpy(lmresp,entropy,8);
1033 /* Pad with zeros */
1034 memset(lmresp+8,0,0x10);
1035
1036 /* Fill tmp with challenge(nonce?) + entropy */
1037 memcpy(tmp,&ntlm->nonce[0],8);
1038 memcpy(tmp+8,entropy,8);
1039
1040 #ifdef USE_SSLEAY
1041 MD5_Init(&MD5pw);
1042 MD5_Update(&MD5pw, tmp, 16);
1043 MD5_Final(md5sum, &MD5pw);
1044 #elif defined(USE_GNUTLS)
1045 gcry_md_open(&MD5pw, GCRY_MD_MD5, 0);
1046 gcry_md_write(MD5pw, tmp, MD5_DIGEST_LENGTH);
1047 memcpy(md5sum, gcry_md_read (MD5pw, 0), MD5_DIGEST_LENGTH);
1048 gcry_md_close(MD5pw);
1049 #elif defined(USE_NSS)
1050 MD5pw = PK11_CreateDigestContext(SEC_OID_MD5);
1051 PK11_DigestOp(MD5pw, tmp, 16);
1052 PK11_DigestFinal(MD5pw, md5sum, &outlen, MD5_DIGEST_LENGTH);
1053 PK11_DestroyContext(MD5pw, PR_TRUE);
1054 #endif
1055
1056 /* We shall only use the first 8 bytes of md5sum,
1057 but the des code in lm_resp only encrypt the first 8 bytes */
1058 if(mk_nt_hash(conn->data, passwdp, ntbuffer) == CURLE_OUT_OF_MEMORY)
1059 return CURLE_OUT_OF_MEMORY;
1060 lm_resp(ntbuffer, md5sum, ntresp);
1061
1062 /* End of NTLM2 Session code */
1063 }
1064 else
1065 #endif
1066 {
1067
1068 #if USE_NTRESPONSES
1069 unsigned char ntbuffer[0x18];
1070 #endif
1071 unsigned char lmbuffer[0x18];
1072
1073 #if USE_NTRESPONSES
1074 if(mk_nt_hash(conn->data, passwdp, ntbuffer) == CURLE_OUT_OF_MEMORY)
1075 return CURLE_OUT_OF_MEMORY;
1076 lm_resp(ntbuffer, &ntlm->nonce[0], ntresp);
1077 #endif
1078
1079 mk_lm_hash(conn->data, passwdp, lmbuffer);
1080 lm_resp(lmbuffer, &ntlm->nonce[0], lmresp);
1081 /* A safer but less compatible alternative is:
1082 * lm_resp(ntbuffer, &ntlm->nonce[0], lmresp);
1083 * See http://davenport.sourceforge.net/ntlm.html#ntlmVersion2 */
1084 }
1085
1086 lmrespoff = 64; /* size of the message header */
1087 #if USE_NTRESPONSES
1088 ntrespoff = lmrespoff + 0x18;
1089 domoff = ntrespoff + 0x18;
1090 #else
1091 domoff = lmrespoff + 0x18;
1092 #endif
1093 useroff = domoff + domlen;
1094 hostoff = useroff + userlen;
1095
1096 /*
1097 * In the case the server sets the flag NTLMFLAG_NEGOTIATE_UNICODE, we
1098 * need to filter it off because libcurl doesn't UNICODE encode the
1099 * strings it packs into the NTLM authenticate packet.
1100 */
1101 ntlm->flags &= ~NTLMFLAG_NEGOTIATE_UNICODE;
1102
1103 /* Create the big type-3 message binary blob */
1104 size = snprintf((char *)ntlmbuf, sizeof(ntlmbuf),
1105 NTLMSSP_SIGNATURE "%c"
1106 "\x03%c%c%c" /* type-3, 32 bits */
1107
1108 "%c%c" /* LanManager length */
1109 "%c%c" /* LanManager allocated space */
1110 "%c%c" /* LanManager offset */
1111 "%c%c" /* 2 zeroes */
1112
1113 "%c%c" /* NT-response length */
1114 "%c%c" /* NT-response allocated space */
1115 "%c%c" /* NT-response offset */
1116 "%c%c" /* 2 zeroes */
1117
1118 "%c%c" /* domain length */
1119 "%c%c" /* domain allocated space */
1120 "%c%c" /* domain name offset */
1121 "%c%c" /* 2 zeroes */
1122
1123 "%c%c" /* user length */
1124 "%c%c" /* user allocated space */
1125 "%c%c" /* user offset */
1126 "%c%c" /* 2 zeroes */
1127
1128 "%c%c" /* host length */
1129 "%c%c" /* host allocated space */
1130 "%c%c" /* host offset */
1131 "%c%c" /* 2 zeroes */
1132
1133 "%c%c" /* session key length (unknown purpose) */
1134 "%c%c" /* session key allocated space (unknown purpose) */
1135 "%c%c" /* session key offset (unknown purpose) */
1136 "%c%c" /* 2 zeroes */
1137
1138 "%c%c%c%c" /* flags */
1139
1140 /* domain string */
1141 /* user string */
1142 /* host string */
1143 /* LanManager response */
1144 /* NT response */
1145 ,
1146 0, /* zero termination */
1147 0,0,0, /* type-3 long, the 24 upper bits */
1148
1149 SHORTPAIR(0x18), /* LanManager response length, twice */
1150 SHORTPAIR(0x18),
1151 SHORTPAIR(lmrespoff),
1152 0x0, 0x0,
1153
1154 #if USE_NTRESPONSES
1155 SHORTPAIR(0x18), /* NT-response length, twice */
1156 SHORTPAIR(0x18),
1157 SHORTPAIR(ntrespoff),
1158 0x0, 0x0,
1159 #else
1160 0x0, 0x0,
1161 0x0, 0x0,
1162 0x0, 0x0,
1163 0x0, 0x0,
1164 #endif
1165 SHORTPAIR(domlen),
1166 SHORTPAIR(domlen),
1167 SHORTPAIR(domoff),
1168 0x0, 0x0,
1169
1170 SHORTPAIR(userlen),
1171 SHORTPAIR(userlen),
1172 SHORTPAIR(useroff),
1173 0x0, 0x0,
1174
1175 SHORTPAIR(hostlen),
1176 SHORTPAIR(hostlen),
1177 SHORTPAIR(hostoff),
1178 0x0, 0x0,
1179
1180 0x0, 0x0,
1181 0x0, 0x0,
1182 0x0, 0x0,
1183 0x0, 0x0,
1184
1185 LONGQUARTET(ntlm->flags));
1186 DEBUGASSERT(size==64);
1187
1188 DEBUGASSERT(size == (size_t)lmrespoff);
1189 /* We append the binary hashes */
1190 if(size < (sizeof(ntlmbuf) - 0x18)) {
1191 memcpy(&ntlmbuf[size], lmresp, 0x18);
1192 size += 0x18;
1193 }
1194
1195 DEBUG_OUT({
1196 fprintf(stderr, "**** TYPE3 header lmresp=");
1197 print_hex(stderr, (char *)&ntlmbuf[lmrespoff], 0x18);
1198 });
1199
1200 #if USE_NTRESPONSES
1201 if(size < (sizeof(ntlmbuf) - 0x18)) {
1202 DEBUGASSERT(size == (size_t)ntrespoff);
1203 memcpy(&ntlmbuf[size], ntresp, 0x18);
1204 size += 0x18;
1205 }
1206
1207 DEBUG_OUT({
1208 fprintf(stderr, "\n ntresp=");
1209 print_hex(stderr, (char *)&ntlmbuf[ntrespoff], 0x18);
1210 });
1211
1212 #endif
1213
1214 DEBUG_OUT({
1215 fprintf(stderr, "\n flags=0x%02.2x%02.2x%02.2x%02.2x 0x%08.8x ",
1216 LONGQUARTET(ntlm->flags), ntlm->flags);
1217 print_flags(stderr, ntlm->flags);
1218 fprintf(stderr, "\n****\n");
1219 });
1220
1221
1222 /* Make sure that the domain, user and host strings fit in the target
1223 buffer before we copy them there. */
1224 if(size + userlen + domlen + hostlen >= sizeof(ntlmbuf)) {
1225 failf(conn->data, "user + domain + host name too big");
1226 return CURLE_OUT_OF_MEMORY;
1227 }
1228
1229 DEBUGASSERT(size == domoff);
1230 memcpy(&ntlmbuf[size], domain, domlen);
1231 size += domlen;
1232
1233 DEBUGASSERT(size == useroff);
1234 memcpy(&ntlmbuf[size], user, userlen);
1235 size += userlen;
1236
1237 DEBUGASSERT(size == hostoff);
1238 memcpy(&ntlmbuf[size], host, hostlen);
1239 size += hostlen;
1240
1241 /* convert domain, user, and host to ASCII but leave the rest as-is */
1242 if(Curl_convert_to_network(conn->data, (char *)&ntlmbuf[domoff],
1243 size-domoff))
1244 return CURLE_CONV_FAILED;
1245
1246 #endif
1247
1248 /* convert the binary blob into base64 */
1249 size = Curl_base64_encode(NULL, (char *)ntlmbuf, size, &base64);
1250
1251 if(size >0 ) {
1252 Curl_safefree(*allocuserpwd);
1253 *allocuserpwd = aprintf("%sAuthorization: NTLM %s\r\n",
1254 proxy?"Proxy-":"",
1255 base64);
1256 DEBUG_OUT(fprintf(stderr, "**** %s\n ", *allocuserpwd));
1257 free(base64);
1258 }
1259 else
1260 return CURLE_OUT_OF_MEMORY; /* FIX TODO */
1261
1262 ntlm->state = NTLMSTATE_TYPE3; /* we sent a type-3 */
1263 authp->done = TRUE;
1264 }
1265 break;
1266
1267 case NTLMSTATE_TYPE3:
1268 /* connection is already authenticated,
1269 * don't send a header in future requests */
1270 if(*allocuserpwd) {
1271 free(*allocuserpwd);
1272 *allocuserpwd=NULL;
1273 }
1274 authp->done = TRUE;
1275 break;
1276 }
1277
1278 return CURLE_OK;
1279 }
1280
1281
1282 void
Curl_ntlm_cleanup(struct connectdata * conn)1283 Curl_ntlm_cleanup(struct connectdata *conn)
1284 {
1285 #ifdef USE_WINDOWS_SSPI
1286 ntlm_sspi_cleanup(&conn->ntlm);
1287 ntlm_sspi_cleanup(&conn->proxyntlm);
1288 #else
1289 (void)conn;
1290 #endif
1291 }
1292
1293
1294 #endif /* USE_NTLM */
1295 #endif /* !CURL_DISABLE_HTTP */
1296