~ubuntu-branches/ubuntu/edgy/curl/edgy

« back to all changes in this revision

Viewing changes to lib/http_ntlm.c

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2006-06-29 15:04:24 UTC
  • mfrom: (1.1.5 upstream)
  • Revision ID: james.westby@ubuntu.com-20060629150424-pn00qumt9sml8p4m
Tags: 7.15.4-1ubuntu1
Synchronize to Debian. Only change left: Removal of stunnel and
libdb4.2-dev build dependencies.

Show diffs side-by-side

added added

removed removed

Lines of Context:
5
5
 *                            | (__| |_| |  _ <| |___
6
6
 *                             \___|\___/|_| \_\_____|
7
7
 *
8
 
 * Copyright (C) 1998 - 2005, Daniel Stenberg, <daniel@haxx.se>, et al.
 
8
 * Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
9
9
 *
10
10
 * This software is licensed as described in the file COPYING, which
11
11
 * you should have received as part of this distribution. The terms
18
18
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19
19
 * KIND, either express or implied.
20
20
 *
21
 
 * $Id: http_ntlm.c,v 1.49 2005/11/14 22:10:52 bagder Exp $
 
21
 * $Id: http_ntlm.c,v 1.52 2006-06-07 14:14:05 bagder Exp $
22
22
 ***************************************************************************/
23
23
#include "setup.h"
24
24
 
27
27
   http://davenport.sourceforge.net/ntlm.html
28
28
   http://www.innovation.ch/java/ntlm.html
29
29
 
 
30
   Another implementation:
 
31
   http://lxr.mozilla.org/mozilla/source/security/manager/ssl/src/nsNTLMAuthModule.cpp
 
32
 
30
33
*/
31
34
 
32
35
#ifndef CURL_DISABLE_HTTP
33
36
#ifdef USE_NTLM
34
37
 
 
38
#define DEBUG_ME 0
 
39
 
35
40
/* -- WIN32 approved -- */
36
41
#include <stdio.h>
37
42
#include <string.h>
46
51
#include "http_ntlm.h"
47
52
#include "url.h"
48
53
#include "memory.h"
 
54
#include "ssluse.h"
49
55
 
50
56
#define _MPRINTF_REPLACE /* use our functions only */
51
57
#include <curl/mprintf.h>
54
60
 
55
61
#include <openssl/des.h>
56
62
#include <openssl/md4.h>
 
63
#include <openssl/md5.h>
57
64
#include <openssl/ssl.h>
 
65
#include <openssl/rand.h>
58
66
 
59
67
#if OPENSSL_VERSION_NUMBER < 0x00907001L
60
68
#define DES_key_schedule des_key_schedule
89
97
/* Define this to make the type-3 message include the NT response message */
90
98
#define USE_NTRESPONSES 1
91
99
 
 
100
/* Define this to make the type-3 message include the NTLM2Session response
 
101
   message, requires USE_NTRESPONSES. */
 
102
#define USE_NTLM2SESSION 1
 
103
 
 
104
#ifndef USE_WINDOWS_SSPI
 
105
/* this function converts from the little endian format used in the incoming
 
106
   package to whatever endian format we're using natively */
 
107
static unsigned int readint_le(unsigned char *buf) /* must point to a
 
108
                                                      4 bytes buffer*/
 
109
{
 
110
  return ((unsigned int)buf[0]) | ((unsigned int)buf[1] << 8) |
 
111
    ((unsigned int)buf[2] << 16) | ((unsigned int)buf[3] << 24);
 
112
}
 
113
#endif
 
114
 
 
115
#if DEBUG_ME
 
116
# define DEBUG_OUT(x) x
 
117
static void print_flags(FILE *handle, unsigned long flags)
 
118
{
 
119
  if(flags & NTLMFLAG_NEGOTIATE_UNICODE)
 
120
    fprintf(handle, "NTLMFLAG_NEGOTIATE_UNICODE ");
 
121
  if(flags & NTLMFLAG_NEGOTIATE_OEM)
 
122
    fprintf(handle, "NTLMFLAG_NEGOTIATE_OEM ");
 
123
  if(flags & NTLMFLAG_REQUEST_TARGET)
 
124
    fprintf(handle, "NTLMFLAG_REQUEST_TARGET ");
 
125
  if(flags & (1<<3))
 
126
    fprintf(handle, "NTLMFLAG_UNKNOWN_3 ");
 
127
  if(flags & NTLMFLAG_NEGOTIATE_SIGN)
 
128
    fprintf(handle, "NTLMFLAG_NEGOTIATE_SIGN ");
 
129
  if(flags & NTLMFLAG_NEGOTIATE_SEAL)
 
130
    fprintf(handle, "NTLMFLAG_NEGOTIATE_SEAL ");
 
131
  if(flags & NTLMFLAG_NEGOTIATE_DATAGRAM_STYLE)
 
132
    fprintf(handle, "NTLMFLAG_NEGOTIATE_DATAGRAM_STYLE ");
 
133
  if(flags & NTLMFLAG_NEGOTIATE_LM_KEY)
 
134
    fprintf(handle, "NTLMFLAG_NEGOTIATE_LM_KEY ");
 
135
  if(flags & NTLMFLAG_NEGOTIATE_NETWARE)
 
136
    fprintf(handle, "NTLMFLAG_NEGOTIATE_NETWARE ");
 
137
  if(flags & NTLMFLAG_NEGOTIATE_NTLM_KEY)
 
138
    fprintf(handle, "NTLMFLAG_NEGOTIATE_NTLM_KEY ");
 
139
  if(flags & (1<<10))
 
140
    fprintf(handle, "NTLMFLAG_UNKNOWN_10 ");
 
141
  if(flags & (1<<11))
 
142
    fprintf(handle, "NTLMFLAG_UNKNOWN_11 ");
 
143
  if(flags & NTLMFLAG_NEGOTIATE_DOMAIN_SUPPLIED)
 
144
    fprintf(handle, "NTLMFLAG_NEGOTIATE_DOMAIN_SUPPLIED ");
 
145
  if(flags & NTLMFLAG_NEGOTIATE_WORKSTATION_SUPPLIED)
 
146
    fprintf(handle, "NTLMFLAG_NEGOTIATE_WORKSTATION_SUPPLIED ");
 
147
  if(flags & NTLMFLAG_NEGOTIATE_LOCAL_CALL)
 
148
    fprintf(handle, "NTLMFLAG_NEGOTIATE_LOCAL_CALL ");
 
149
  if(flags & NTLMFLAG_NEGOTIATE_ALWAYS_SIGN)
 
150
    fprintf(handle, "NTLMFLAG_NEGOTIATE_ALWAYS_SIGN ");
 
151
  if(flags & NTLMFLAG_TARGET_TYPE_DOMAIN)
 
152
    fprintf(handle, "NTLMFLAG_TARGET_TYPE_DOMAIN ");
 
153
  if(flags & NTLMFLAG_TARGET_TYPE_SERVER)
 
154
    fprintf(handle, "NTLMFLAG_TARGET_TYPE_SERVER ");
 
155
  if(flags & NTLMFLAG_TARGET_TYPE_SHARE)
 
156
    fprintf(handle, "NTLMFLAG_TARGET_TYPE_SHARE ");
 
157
  if(flags & NTLMFLAG_NEGOTIATE_NTLM2_KEY)
 
158
    fprintf(handle, "NTLMFLAG_NEGOTIATE_NTLM2_KEY ");
 
159
  if(flags & NTLMFLAG_REQUEST_INIT_RESPONSE)
 
160
    fprintf(handle, "NTLMFLAG_REQUEST_INIT_RESPONSE ");
 
161
  if(flags & NTLMFLAG_REQUEST_ACCEPT_RESPONSE)
 
162
    fprintf(handle, "NTLMFLAG_REQUEST_ACCEPT_RESPONSE ");
 
163
  if(flags & NTLMFLAG_REQUEST_NONNT_SESSION_KEY)
 
164
    fprintf(handle, "NTLMFLAG_REQUEST_NONNT_SESSION_KEY ");
 
165
  if(flags & NTLMFLAG_NEGOTIATE_TARGET_INFO)
 
166
    fprintf(handle, "NTLMFLAG_NEGOTIATE_TARGET_INFO ");
 
167
  if(flags & (1<<24))
 
168
    fprintf(handle, "NTLMFLAG_UNKNOWN_24 ");
 
169
  if(flags & (1<<25))
 
170
    fprintf(handle, "NTLMFLAG_UNKNOWN_25 ");
 
171
  if(flags & (1<<26))
 
172
    fprintf(handle, "NTLMFLAG_UNKNOWN_26 ");
 
173
  if(flags & (1<<27))
 
174
    fprintf(handle, "NTLMFLAG_UNKNOWN_27 ");
 
175
  if(flags & (1<<28))
 
176
    fprintf(handle, "NTLMFLAG_UNKNOWN_28 ");
 
177
  if(flags & NTLMFLAG_NEGOTIATE_128)
 
178
    fprintf(handle, "NTLMFLAG_NEGOTIATE_128 ");
 
179
  if(flags & NTLMFLAG_NEGOTIATE_KEY_EXCHANGE)
 
180
    fprintf(handle, "NTLMFLAG_NEGOTIATE_KEY_EXCHANGE ");
 
181
  if(flags & NTLMFLAG_NEGOTIATE_56)
 
182
    fprintf(handle, "NTLMFLAG_NEGOTIATE_56 ");
 
183
}
 
184
 
 
185
static void print_hex(FILE *handle, const char *buf, size_t len)
 
186
{
 
187
  const char *p = buf;
 
188
  fprintf(stderr, "0x");
 
189
  while (len-- > 0)
 
190
    fprintf(stderr, "%02.2x", (unsigned int)*p++);
 
191
}
 
192
#else
 
193
# define DEBUG_OUT(x)
 
194
#endif
 
195
 
92
196
/*
93
197
  (*) = A "security buffer" is a triplet consisting of two shorts and one
94
198
  long:
107
211
{
108
212
  /* point to the correct struct with this */
109
213
  struct ntlmdata *ntlm;
 
214
#ifndef USE_WINDOWS_SSPI
 
215
  static const char type2_marker[] = { 0x02, 0x00, 0x00, 0x00 };
 
216
#endif
110
217
 
111
218
  ntlm = proxy?&conn->proxyntlm:&conn->ntlm;
112
219
 
143
250
      ntlm->state = NTLMSTATE_TYPE2; /* we got a type-2 */
144
251
 
145
252
#ifdef USE_WINDOWS_SSPI
146
 
      if ((ntlm->type_2 = malloc(size+1)) == NULL) {
 
253
      ntlm->type_2 = malloc(size+1);
 
254
      if (ntlm->type_2 == NULL) {
147
255
        free(buffer);
148
256
        return CURLE_OUT_OF_MEMORY;
149
257
      }
150
258
      ntlm->n_type_2 = size;
151
259
      memcpy(ntlm->type_2, buffer, size);
152
260
#else
153
 
      if(size >= 48)
154
 
        /* the nonce of interest is index [24 .. 31], 8 bytes */
155
 
        memcpy(ntlm->nonce, &buffer[24], 8);
156
 
      /* FIX: add an else here! */
157
 
 
158
 
      /* at index decimal 20, there's a 32bit NTLM flag field */
 
261
      ntlm->flags = 0;
 
262
 
 
263
      if((size < 32) ||
 
264
         (memcmp(buffer, "NTLMSSP", 8) != 0) ||
 
265
         (memcmp(buffer+8, type2_marker, sizeof(type2_marker)) != 0)) {
 
266
        /* This was not a good enough type-2 message */
 
267
        free(buffer);
 
268
        return CURLNTLM_BAD;
 
269
      }
 
270
 
 
271
      ntlm->flags = readint_le(&buffer[20]);
 
272
      memcpy(ntlm->nonce, &buffer[24], 8);
 
273
 
 
274
      DEBUG_OUT({
 
275
        fprintf(stderr, "**** TYPE2 header flags=0x%08.8lx ", ntlm->flags);
 
276
        print_flags(stderr, ntlm->flags);
 
277
        fprintf(stderr, "\n                  nonce=");
 
278
        print_hex(stderr, ntlm->nonce, 8);
 
279
        fprintf(stderr, "\n****\n");
 
280
      });
159
281
 
160
282
      free(buffer);
161
283
#endif
199
321
  * 8 byte plaintext is encrypted with each key and the resulting 24
200
322
  * bytes are stored in the results array.
201
323
  */
202
 
static void calc_resp(unsigned char *keys,
 
324
static void lm_resp(unsigned char *keys,
203
325
                      unsigned char *plaintext,
204
326
                      unsigned char *results)
205
327
{
218
340
                  DESKEY(ks), DES_ENCRYPT);
219
341
}
220
342
 
 
343
 
221
344
/*
222
 
 * Set up lanmanager and nt hashed passwords
 
345
 * Set up lanmanager hashed password
223
346
 */
224
 
static void mkhash(char *password,
225
 
                   unsigned char *nonce,  /* 8 bytes */
226
 
                   unsigned char *lmresp  /* must fit 0x18 bytes */
227
 
#ifdef USE_NTRESPONSES
228
 
                   , unsigned char *ntresp  /* must fit 0x18 bytes */
229
 
#endif
230
 
  )
 
347
static void mk_lm_hash(char *password, unsigned char *lmbuffer /* 21 bytes */)
231
348
{
232
 
  /* 21 bytes fits 3 7-bytes chunks, as we use 56 bit (7 bytes) as DES input,
233
 
     and we add three different ones, see the calc_resp() function */
234
 
  unsigned char lmbuffer[21];
235
 
#ifdef USE_NTRESPONSES
236
 
  unsigned char ntbuffer[21];
237
 
#endif
238
 
  unsigned char *pw;
 
349
  unsigned char pw[14];
239
350
  static const unsigned char magic[] = {
240
 
    0x4B, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25
 
351
    0x4B, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 /* i.e. KGS!@#$% */
241
352
  };
242
353
  unsigned int i;
243
354
  size_t len = strlen(password);
244
355
 
245
 
  /* make it fit at least 14 bytes */
246
 
  pw = malloc(len<7?14:len*2);
247
 
  if(!pw)
248
 
    return; /* this will lead to a badly generated package */
249
 
 
250
356
  if (len > 14)
251
357
    len = 14;
252
358
 
257
363
    pw[i] = 0;
258
364
 
259
365
  {
260
 
    /* create LanManager hashed password */
 
366
    /* Create LanManager hashed password. */
 
367
 
261
368
    DES_key_schedule ks;
262
369
 
263
370
    setup_des_key(pw, DESKEY(ks));
268
375
    DES_ecb_encrypt((DES_cblock *)magic, (DES_cblock *)(lmbuffer+8),
269
376
                    DESKEY(ks), DES_ENCRYPT);
270
377
 
271
 
    memset(lmbuffer+16, 0, sizeof(lmbuffer)-16);
272
 
  }
273
 
  /* create LM responses */
274
 
  calc_resp(lmbuffer, nonce, lmresp);
275
 
 
276
 
#ifdef USE_NTRESPONSES
 
378
    memset(lmbuffer + 16, 0, 21 - 16);
 
379
  }
 
380
  }
 
381
 
 
382
#if USE_NTRESPONSES
 
383
static void utf8_to_unicode_le(unsigned char *dest, const char *src,
 
384
                               size_t srclen)
 
385
{
 
386
  size_t i;
 
387
  for (i=0; i<srclen; i++) {
 
388
    dest[2*i]   = (unsigned char)src[i];
 
389
    dest[2*i+1] =   '\0';
 
390
  }
 
391
}
 
392
 
 
393
/*
 
394
 * Set up nt hashed passwords
 
395
 */
 
396
static void mk_nt_hash(char *password, unsigned char *ntbuffer /* 21 bytes */)
 
397
{
 
398
  size_t len = strlen(password);
 
399
  unsigned char *pw = malloc(len*2);
 
400
 
 
401
  utf8_to_unicode_le(pw, password, len);
 
402
 
277
403
  {
278
 
    /* create NT hashed password */
 
404
    /* Create NT hashed password. */
279
405
    MD4_CTX MD4;
280
406
 
281
 
    len = strlen(password);
282
 
 
283
 
    for (i=0; i<len; i++) {
284
 
      pw[2*i]   = password[i];
285
 
      pw[2*i+1] = 0;
286
 
    }
287
 
 
288
407
    MD4_Init(&MD4);
289
408
    MD4_Update(&MD4, pw, 2*len);
290
409
    MD4_Final(ntbuffer, &MD4);
291
410
 
292
 
    memset(ntbuffer+16, 0, sizeof(ntbuffer)-16);
 
411
    memset(ntbuffer + 16, 0, 21 - 16);
293
412
  }
294
413
 
295
 
  calc_resp(ntbuffer, nonce, ntresp);
296
 
#endif
297
 
 
298
414
  free(pw);
299
415
}
 
416
#endif
 
417
 
300
418
 
301
419
#endif
302
420
 
324
442
 
325
443
#endif
326
444
 
327
 
#define SHORTPAIR(x) ((x) & 0xff), ((x) >> 8)
 
445
#define SHORTPAIR(x) ((x) & 0xff), (((x) >> 8) & 0xff)
328
446
#define LONGQUARTET(x) ((x) & 0xff), (((x) >> 8)&0xff), \
329
 
  (((x) >>16)&0xff), ((x)>>24)
 
447
  (((x) >>16)&0xff), (((x)>>24) & 0xff)
 
448
 
 
449
#define HOSTNAME_MAX 1024
330
450
 
331
451
/* this is for creating ntlm header output */
332
452
CURLcode Curl_output_ntlm(struct connectdata *conn,
333
453
                          bool proxy)
334
454
{
335
455
  const char *domain=""; /* empty */
336
 
  const char *host=""; /* empty */
 
456
  char host [HOSTNAME_MAX+ 1] = ""; /* empty */
337
457
#ifndef USE_WINDOWS_SSPI
338
 
  int domlen=(int)strlen(domain);
339
 
  int hostlen = (int)strlen(host);
340
 
  int hostoff; /* host name offset */
341
 
  int domoff;  /* domain name offset */
 
458
  size_t domlen = strlen(domain);
 
459
  size_t hostlen = strlen(host);
 
460
  size_t hostoff; /* host name offset */
 
461
  size_t domoff;  /* domain name offset */
342
462
#endif
343
463
  size_t size;
344
464
  char *base64=NULL;
345
 
  unsigned char ntlmbuf[512]; /* enough, unless the host/domain is very long */
 
465
  unsigned char ntlmbuf[1024]; /* enough, unless the user+host+domain is very
 
466
                                  long */
346
467
 
347
468
  /* point to the address of the pointer that holds the string to sent to the
348
469
     server, which is for a plain host or for a HTTP proxy */
399
520
      s_hSecDll = LoadLibrary("secur32.dll");
400
521
    if (s_hSecDll != NULL) {
401
522
      INIT_SECURITY_INTERFACE pInitSecurityInterface;
402
 
        pInitSecurityInterface =
403
 
          (INIT_SECURITY_INTERFACE)GetProcAddress(s_hSecDll,
404
 
                                                  "InitSecurityInterfaceA");
405
 
        if (pInitSecurityInterface != NULL)
406
 
          s_pSecFn = pInitSecurityInterface();
 
523
      pInitSecurityInterface =
 
524
        (INIT_SECURITY_INTERFACE)GetProcAddress(s_hSecDll,
 
525
                                                "InitSecurityInterfaceA");
 
526
      if (pInitSecurityInterface != NULL)
 
527
        s_pSecFn = pInitSecurityInterface();
407
528
    }
408
529
  }
409
530
  if (s_pSecFn == NULL)
500
621
    size = buf.cbBuffer;
501
622
  }
502
623
#else
503
 
    hostoff = 32;
504
 
    domoff = hostoff + hostlen;
 
624
    hostoff = 0;
 
625
    domoff = hostoff + hostlen; /* This is 0: remember that host and domain
 
626
                                   are empty */
505
627
 
506
628
    /* Create and send a type-1 message:
507
629
 
515
637
    32    start of data block
516
638
 
517
639
    */
518
 
 
 
640
#if USE_NTLM2SESSION
 
641
#define NTLM2FLAG NTLMFLAG_NEGOTIATE_NTLM2_KEY
 
642
#else
 
643
#define NTLM2FLAG 0
 
644
#endif
519
645
    snprintf((char *)ntlmbuf, sizeof(ntlmbuf), "NTLMSSP%c"
520
646
             "\x01%c%c%c" /* 32-bit type = 1 */
521
647
             "%c%c%c%c"   /* 32-bit NTLM flag field */
533
659
             0,0,0, /* part of type-1 long */
534
660
 
535
661
             LONGQUARTET(
536
 
               NTLMFLAG_NEGOTIATE_OEM|      /*   2 */
537
 
               NTLMFLAG_NEGOTIATE_NTLM_KEY  /* 200 */
538
 
               /* equals 0x0202 */
 
662
               NTLMFLAG_NEGOTIATE_OEM|
 
663
               NTLMFLAG_REQUEST_TARGET|
 
664
               NTLMFLAG_NEGOTIATE_NTLM_KEY|
 
665
               NTLM2FLAG|
 
666
               NTLMFLAG_NEGOTIATE_ALWAYS_SIGN
539
667
               ),
540
668
             SHORTPAIR(domlen),
541
669
             SHORTPAIR(domlen),
545
673
             SHORTPAIR(hostlen),
546
674
             SHORTPAIR(hostoff),
547
675
             0,0,
548
 
             host, domain);
 
676
             host /* this is empty */, domain /* this is empty */);
549
677
 
550
678
    /* initial packet length */
551
679
    size = 32 + hostlen + domlen;
552
680
#endif
553
681
 
554
 
    /* now keeper of the base64 encoded package size */
 
682
    DEBUG_OUT({
 
683
      fprintf(stderr, "**** TYPE1 header flags=0x%02.2x%02.2x%02.2x%02.2x 0x%08.8x ",
 
684
              LONGQUARTET(NTLMFLAG_NEGOTIATE_OEM|
 
685
                          NTLMFLAG_REQUEST_TARGET|
 
686
                          NTLMFLAG_NEGOTIATE_NTLM_KEY|
 
687
                          NTLM2FLAG|
 
688
                          NTLMFLAG_NEGOTIATE_ALWAYS_SIGN),
 
689
              NTLMFLAG_NEGOTIATE_OEM|
 
690
              NTLMFLAG_REQUEST_TARGET|
 
691
              NTLMFLAG_NEGOTIATE_NTLM_KEY|
 
692
              NTLM2FLAG|
 
693
              NTLMFLAG_NEGOTIATE_ALWAYS_SIGN);
 
694
      print_flags(stderr,
 
695
                  NTLMFLAG_NEGOTIATE_OEM|
 
696
                  NTLMFLAG_REQUEST_TARGET|
 
697
                  NTLMFLAG_NEGOTIATE_NTLM_KEY|
 
698
                  NTLM2FLAG|
 
699
                  NTLMFLAG_NEGOTIATE_ALWAYS_SIGN);
 
700
      fprintf(stderr, "\n****\n");
 
701
    });
 
702
 
 
703
    /* now size is the size of the base64 encoded package size */
555
704
    size = Curl_base64_encode((char *)ntlmbuf, size, &base64);
556
705
 
557
706
    if(size >0 ) {
567
716
    break;
568
717
 
569
718
  case NTLMSTATE_TYPE2:
570
 
    /* We received the type-2 already, create a type-3 message:
 
719
    /* We received the type-2 message already, create a type-3 message:
571
720
 
572
721
    Index   Description            Content
573
722
    0       NTLMSSP Signature      Null-terminated ASCII "NTLMSSP"
622
771
 
623
772
#else
624
773
    int lmrespoff;
 
774
    unsigned char lmresp[24]; /* fixed-size */
 
775
#if USE_NTRESPONSES
625
776
    int ntrespoff;
626
 
    int useroff;
627
 
    unsigned char lmresp[0x18]; /* fixed-size */
628
 
#ifdef USE_NTRESPONSES
629
 
    unsigned char ntresp[0x18]; /* fixed-size */
 
777
    unsigned char ntresp[24]; /* fixed-size */
630
778
#endif
 
779
    size_t useroff;
631
780
    const char *user;
632
 
    int userlen;
 
781
    size_t userlen;
633
782
 
634
783
    user = strchr(userp, '\\');
635
784
    if(!user)
637
786
 
638
787
    if (user) {
639
788
      domain = userp;
640
 
      domlen = (int)(user - domain);
 
789
      domlen = (user - domain);
641
790
      user++;
642
791
    }
643
792
    else
644
793
      user = userp;
645
 
    userlen = (int)strlen(user);
646
 
 
647
 
    mkhash(passwdp, &ntlm->nonce[0], lmresp
648
 
#ifdef USE_NTRESPONSES
649
 
           , ntresp
650
 
#endif
651
 
      );
652
 
 
653
 
    domoff = 64; /* always */
 
794
    userlen = strlen(user);
 
795
 
 
796
    if (gethostname(host, HOSTNAME_MAX)) {
 
797
      infof(conn->data, "gethostname() failed, continuing without!");
 
798
      hostlen = 0;
 
799
    }
 
800
    else {
 
801
      hostlen = strlen(host);
 
802
    }
 
803
 
 
804
#if USE_NTLM2SESSION
 
805
    /* We don't support NTLM2 if we don't have USE_NTRESPONSES */
 
806
    if (ntlm->flags & NTLMFLAG_NEGOTIATE_NTLM2_KEY) {
 
807
      unsigned char ntbuffer[0x18];
 
808
      unsigned char tmp[0x18];
 
809
      unsigned char md5sum[MD5_DIGEST_LENGTH];
 
810
      MD5_CTX MD5;
 
811
      unsigned char random[8];
 
812
 
 
813
      /* Need to create 8 bytes random data */
 
814
      Curl_ossl_seed(conn->data); /* Initiate the seed if not already done */
 
815
      RAND_bytes(random,8);
 
816
 
 
817
      /* 8 bytes random data as challenge in lmresp */
 
818
      memcpy(lmresp,random,8);
 
819
      /* Pad with zeros */
 
820
      memset(lmresp+8,0,0x10);
 
821
 
 
822
      /* Fill tmp with challenge(nonce?) + random */
 
823
      memcpy(tmp,&ntlm->nonce[0],8);
 
824
      memcpy(tmp+8,random,8);
 
825
 
 
826
      MD5_Init(&MD5);
 
827
      MD5_Update(&MD5, tmp, 16);
 
828
      MD5_Final(md5sum, &MD5);
 
829
      /* We shall only use the first 8 bytes of md5sum,
 
830
         but the des code in lm_resp only encrypt the first 8 bytes */
 
831
      mk_nt_hash(passwdp, ntbuffer);
 
832
      lm_resp(ntbuffer, md5sum, ntresp);
 
833
 
 
834
      /* End of NTLM2 Session code */
 
835
    }
 
836
    else {
 
837
#endif
 
838
 
 
839
#if USE_NTRESPONSES
 
840
      unsigned char ntbuffer[0x18];
 
841
#endif
 
842
      unsigned char lmbuffer[0x18];
 
843
 
 
844
#if USE_NTRESPONSES
 
845
      mk_nt_hash(passwdp, ntbuffer);
 
846
      lm_resp(ntbuffer, &ntlm->nonce[0], ntresp);
 
847
#endif
 
848
 
 
849
      mk_lm_hash(passwdp, lmbuffer);
 
850
      lm_resp(lmbuffer, &ntlm->nonce[0], lmresp);
 
851
      /* A safer but less compatible alternative is:
 
852
       *   lm_resp(ntbuffer, &ntlm->nonce[0], lmresp);
 
853
       * See http://davenport.sourceforge.net/ntlm.html#ntlmVersion2 */
 
854
    }
 
855
 
 
856
    lmrespoff = 64; /* size of the message header */
 
857
#if USE_NTRESPONSES
 
858
    ntrespoff = lmrespoff + 0x18;
 
859
    domoff = ntrespoff + 0x18;
 
860
#else
 
861
    domoff = lmrespoff + 0x18;
 
862
#endif
654
863
    useroff = domoff + domlen;
655
864
    hostoff = useroff + userlen;
656
 
    lmrespoff = hostoff + hostlen;
657
 
    ntrespoff = lmrespoff + 0x18;
658
865
 
659
866
    /* Create the big type-3 message binary blob */
660
867
    size = snprintf((char *)ntlmbuf, sizeof(ntlmbuf),
661
868
                    "NTLMSSP%c"
662
869
                    "\x03%c%c%c" /* type-3, 32 bits */
663
870
 
664
 
                    "%c%c%c%c" /* LanManager length + allocated space */
 
871
                    "%c%c" /* LanManager length */
 
872
                    "%c%c" /* LanManager allocated space */
665
873
                    "%c%c" /* LanManager offset */
666
874
                    "%c%c" /* 2 zeroes */
667
875
 
683
891
                    "%c%c"  /* host length */
684
892
                    "%c%c"  /* host allocated space */
685
893
                    "%c%c"  /* host offset */
686
 
                    "%c%c%c%c%c%c"  /* 6 zeroes */
687
 
 
688
 
                    "\xff\xff"  /* message length */
689
 
                    "%c%c"  /* 2 zeroes */
690
 
 
691
 
                    "\x01\x82" /* flags */
692
 
                    "%c%c"  /* 2 zeroes */
 
894
                    "%c%c"  /* 2 zeroes */
 
895
 
 
896
                    "%c%c"  /* session key length (unknown purpose) */
 
897
                    "%c%c"  /* session key allocated space (unknown purpose) */
 
898
                    "%c%c"  /* session key offset (unknown purpose) */
 
899
                    "%c%c"  /* 2 zeroes */
 
900
 
 
901
                    "%c%c%c%c" /* flags */
693
902
 
694
903
                    /* domain string */
695
904
                    /* user string */
705
914
                    SHORTPAIR(lmrespoff),
706
915
                    0x0, 0x0,
707
916
 
708
 
#ifdef USE_NTRESPONSES
 
917
#if USE_NTRESPONSES
709
918
                    SHORTPAIR(0x18),  /* NT-response length, twice */
710
919
                    SHORTPAIR(0x18),
711
 
#else
712
 
                    0x0, 0x0,
713
 
                    0x0, 0x0,
714
 
#endif
715
920
                    SHORTPAIR(ntrespoff),
716
921
                    0x0, 0x0,
717
 
 
 
922
#else
 
923
                    0x0, 0x0,
 
924
                    0x0, 0x0,
 
925
                    0x0, 0x0,
 
926
                    0x0, 0x0,
 
927
#endif
718
928
                    SHORTPAIR(domlen),
719
929
                    SHORTPAIR(domlen),
720
930
                    SHORTPAIR(domoff),
728
938
                    SHORTPAIR(hostlen),
729
939
                    SHORTPAIR(hostlen),
730
940
                    SHORTPAIR(hostoff),
731
 
                    0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
732
 
 
733
 
                    0x0, 0x0,
734
 
 
735
 
                    0x0, 0x0);
736
 
 
737
 
    /* size is now 64 */
738
 
    size=64;
739
 
    ntlmbuf[62]=ntlmbuf[63]=0;
740
 
 
741
 
    /* Make sure that the user and domain strings fit in the target buffer
742
 
       before we copy them there. */
743
 
    if(size + userlen + domlen >= sizeof(ntlmbuf)) {
744
 
      failf(conn->data, "user + domain name too big");
 
941
                    0x0, 0x0,
 
942
 
 
943
                    0x0, 0x0,
 
944
                    0x0, 0x0,
 
945
                    0x0, 0x0,
 
946
                    0x0, 0x0,
 
947
 
 
948
                    LONGQUARTET(ntlm->flags));
 
949
    DEBUG_OUT(assert(size==64));
 
950
 
 
951
    DEBUG_OUT(assert(size == lmrespoff));
 
952
    /* We append the binary hashes */
 
953
    if(size < (sizeof(ntlmbuf) - 0x18)) {
 
954
      memcpy(&ntlmbuf[size], lmresp, 0x18);
 
955
      size += 0x18;
 
956
    }
 
957
 
 
958
    DEBUG_OUT({
 
959
        fprintf(stderr, "**** TYPE3 header lmresp=");
 
960
        print_hex(stderr, &ntlmbuf[lmrespoff], 0x18);
 
961
    });
 
962
 
 
963
#if USE_NTRESPONSES
 
964
    if(size < (sizeof(ntlmbuf) - 0x18)) {
 
965
      DEBUG_OUT(assert(size == ntrespoff));
 
966
      memcpy(&ntlmbuf[size], ntresp, 0x18);
 
967
      size += 0x18;
 
968
    }
 
969
 
 
970
    DEBUG_OUT({
 
971
        fprintf(stderr, "\n                  ntresp=");
 
972
        print_hex(stderr, &ntlmbuf[ntrespoff], 0x18);
 
973
    });
 
974
 
 
975
#endif
 
976
 
 
977
    DEBUG_OUT({
 
978
        fprintf(stderr, "\n                  flags=0x%02.2x%02.2x%02.2x%02.2x 0x%08.8x ",
 
979
                LONGQUARTET(ntlm->flags), ntlm->flags);
 
980
        print_flags(stderr, ntlm->flags);
 
981
        fprintf(stderr, "\n****\n");
 
982
    });
 
983
 
 
984
 
 
985
    /* Make sure that the domain, user and host strings fit in the target
 
986
       buffer before we copy them there. */
 
987
    if(size + userlen + domlen + hostlen >= sizeof(ntlmbuf)) {
 
988
      failf(conn->data, "user + domain + host name too big");
745
989
      return CURLE_OUT_OF_MEMORY;
746
990
    }
747
991
 
 
992
    curlassert(size == domoff);
748
993
    memcpy(&ntlmbuf[size], domain, domlen);
749
994
    size += domlen;
750
995
 
 
996
    curlassert(size == useroff);
751
997
    memcpy(&ntlmbuf[size], user, userlen);
752
998
    size += userlen;
753
999
 
754
 
    /* we append the binary hashes to the end of the blob */
755
 
    if(size < ((int)sizeof(ntlmbuf) - 0x18)) {
756
 
      memcpy(&ntlmbuf[size], lmresp, 0x18);
757
 
      size += 0x18;
758
 
    }
759
 
 
760
 
#ifdef USE_NTRESPONSES
761
 
    if(size < ((int)sizeof(ntlmbuf) - 0x18)) {
762
 
      memcpy(&ntlmbuf[size], ntresp, 0x18);
763
 
      size += 0x18;
764
 
    }
765
 
#endif
766
 
 
767
 
    ntlmbuf[56] = (unsigned char)(size & 0xff);
768
 
    ntlmbuf[57] = (unsigned char)(size >> 8);
 
1000
    curlassert(size == hostoff);
 
1001
    memcpy(&ntlmbuf[size], host, hostlen);
 
1002
    size += hostlen;
769
1003
 
770
1004
#endif
771
1005
 
810
1044
  ntlm_sspi_cleanup(&conn->proxyntlm);
811
1045
  if (s_hSecDll != NULL) {
812
1046
    FreeLibrary(s_hSecDll);
813
 
        s_hSecDll = NULL;
814
 
        s_pSecFn = NULL;
 
1047
    s_hSecDll = NULL;
 
1048
    s_pSecFn = NULL;
815
1049
  }
816
1050
#else
817
1051
  (void)conn;