~ubuntu-branches/ubuntu/raring/curl/raring-updates

« back to all changes in this revision

Viewing changes to lib/http_ntlm.c

  • Committer: Package Import Robot
  • Author(s): Alessandro Ghedini
  • Date: 2011-11-13 21:07:32 UTC
  • mto: (3.6.1 experimental) (1.3.1)
  • mto: This revision was merged to the branch mainline in revision 55.
  • Revision ID: package-import@ubuntu.com-20111113210732-bk5n25x2tu7aplur
Tags: upstream-7.22.0
ImportĀ upstreamĀ versionĀ 7.22.0

Show diffs side-by-side

added added

removed removed

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