[164] | 1 | /***************************************************************************
|
---|
| 2 | * _ _ ____ _
|
---|
| 3 | * Project ___| | | | _ \| |
|
---|
| 4 | * / __| | | | |_) | |
|
---|
| 5 | * | (__| |_| | _ <| |___
|
---|
| 6 | * \___|\___/|_| \_\_____|
|
---|
| 7 | *
|
---|
| 8 | * Copyright (C) 1998 - 2015, 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 https://curl.haxx.se/docs/copyright.html.
|
---|
| 13 | *
|
---|
| 14 | * You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
---|
| 15 | * copies of the Software, and permit persons to whom the Software is
|
---|
| 16 | * furnished to do so, under the terms of the COPYING file.
|
---|
| 17 | *
|
---|
| 18 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
---|
| 19 | * KIND, either express or implied.
|
---|
| 20 | *
|
---|
| 21 | ***************************************************************************/
|
---|
| 22 |
|
---|
| 23 | #include "curl_setup.h"
|
---|
| 24 |
|
---|
| 25 | #if defined(USE_NTLM)
|
---|
| 26 |
|
---|
| 27 | /*
|
---|
| 28 | * NTLM details:
|
---|
| 29 | *
|
---|
| 30 | * http://davenport.sourceforge.net/ntlm.html
|
---|
| 31 | * http://www.innovation.ch/java/ntlm.html
|
---|
| 32 | */
|
---|
| 33 |
|
---|
| 34 | #if !defined(USE_WINDOWS_SSPI) || defined(USE_WIN32_CRYPTO)
|
---|
| 35 |
|
---|
| 36 | #ifdef USE_OPENSSL
|
---|
| 37 |
|
---|
| 38 | # ifdef USE_OPENSSL
|
---|
| 39 | # include <openssl/des.h>
|
---|
| 40 | # ifndef OPENSSL_NO_MD4
|
---|
| 41 | # include <openssl/md4.h>
|
---|
| 42 | # endif
|
---|
| 43 | # include <openssl/md5.h>
|
---|
| 44 | # include <openssl/ssl.h>
|
---|
| 45 | # include <openssl/rand.h>
|
---|
| 46 | # else
|
---|
| 47 | # include <des.h>
|
---|
| 48 | # ifndef OPENSSL_NO_MD4
|
---|
| 49 | # include <md4.h>
|
---|
| 50 | # endif
|
---|
| 51 | # include <md5.h>
|
---|
| 52 | # include <ssl.h>
|
---|
| 53 | # include <rand.h>
|
---|
| 54 | # endif
|
---|
| 55 | # if (OPENSSL_VERSION_NUMBER < 0x00907001L)
|
---|
| 56 | # define DES_key_schedule des_key_schedule
|
---|
| 57 | # define DES_cblock des_cblock
|
---|
| 58 | # define DES_set_odd_parity des_set_odd_parity
|
---|
| 59 | # define DES_set_key des_set_key
|
---|
| 60 | # define DES_ecb_encrypt des_ecb_encrypt
|
---|
| 61 | # define DESKEY(x) x
|
---|
| 62 | # define DESKEYARG(x) x
|
---|
| 63 | # else
|
---|
| 64 | # define DESKEYARG(x) *x
|
---|
| 65 | # define DESKEY(x) &x
|
---|
| 66 | # endif
|
---|
| 67 |
|
---|
| 68 | #elif defined(USE_GNUTLS_NETTLE)
|
---|
| 69 |
|
---|
| 70 | # include <nettle/des.h>
|
---|
| 71 | # include <nettle/md4.h>
|
---|
| 72 |
|
---|
| 73 | #elif defined(USE_GNUTLS)
|
---|
| 74 |
|
---|
| 75 | # include <gcrypt.h>
|
---|
| 76 | # define MD5_DIGEST_LENGTH 16
|
---|
| 77 | # define MD4_DIGEST_LENGTH 16
|
---|
| 78 |
|
---|
| 79 | #elif defined(USE_NSS)
|
---|
| 80 |
|
---|
| 81 | # include <nss.h>
|
---|
| 82 | # include <pk11pub.h>
|
---|
| 83 | # include <hasht.h>
|
---|
| 84 | # include "curl_md4.h"
|
---|
| 85 | # define MD5_DIGEST_LENGTH MD5_LENGTH
|
---|
| 86 |
|
---|
| 87 | #elif defined(USE_DARWINSSL)
|
---|
| 88 |
|
---|
| 89 | # include <CommonCrypto/CommonCryptor.h>
|
---|
| 90 | # include <CommonCrypto/CommonDigest.h>
|
---|
| 91 |
|
---|
| 92 | #elif defined(USE_OS400CRYPTO)
|
---|
| 93 | # include "cipher.mih" /* mih/cipher */
|
---|
| 94 | # include "curl_md4.h"
|
---|
| 95 | #elif defined(USE_WIN32_CRYPTO)
|
---|
| 96 | # include <wincrypt.h>
|
---|
| 97 | #else
|
---|
| 98 | # error "Can't compile NTLM support without a crypto library."
|
---|
| 99 | #endif
|
---|
| 100 |
|
---|
| 101 | #include "urldata.h"
|
---|
| 102 | #include "non-ascii.h"
|
---|
| 103 | #include "rawstr.h"
|
---|
| 104 | #include "curl_ntlm_core.h"
|
---|
| 105 | #include "curl_md5.h"
|
---|
| 106 | #include "curl_hmac.h"
|
---|
| 107 | #include "warnless.h"
|
---|
| 108 | #include "curl_endian.h"
|
---|
| 109 | #include "curl_des.h"
|
---|
| 110 | #include "curl_printf.h"
|
---|
| 111 |
|
---|
| 112 | /* The last #include files should be: */
|
---|
| 113 | #include "curl_memory.h"
|
---|
| 114 | #include "memdebug.h"
|
---|
| 115 |
|
---|
| 116 | #define NTLM_HMAC_MD5_LEN (16)
|
---|
| 117 | #define NTLMv2_BLOB_SIGNATURE "\x01\x01\x00\x00"
|
---|
| 118 | #define NTLMv2_BLOB_LEN (44 -16 + ntlm->target_info_len + 4)
|
---|
| 119 |
|
---|
| 120 | /*
|
---|
| 121 | * Turns a 56-bit key into being 64-bit wide.
|
---|
| 122 | */
|
---|
| 123 | static void extend_key_56_to_64(const unsigned char *key_56, char *key)
|
---|
| 124 | {
|
---|
| 125 | key[0] = key_56[0];
|
---|
| 126 | key[1] = (unsigned char)(((key_56[0] << 7) & 0xFF) | (key_56[1] >> 1));
|
---|
| 127 | key[2] = (unsigned char)(((key_56[1] << 6) & 0xFF) | (key_56[2] >> 2));
|
---|
| 128 | key[3] = (unsigned char)(((key_56[2] << 5) & 0xFF) | (key_56[3] >> 3));
|
---|
| 129 | key[4] = (unsigned char)(((key_56[3] << 4) & 0xFF) | (key_56[4] >> 4));
|
---|
| 130 | key[5] = (unsigned char)(((key_56[4] << 3) & 0xFF) | (key_56[5] >> 5));
|
---|
| 131 | key[6] = (unsigned char)(((key_56[5] << 2) & 0xFF) | (key_56[6] >> 6));
|
---|
| 132 | key[7] = (unsigned char) ((key_56[6] << 1) & 0xFF);
|
---|
| 133 | }
|
---|
| 134 |
|
---|
| 135 | #ifdef USE_OPENSSL
|
---|
| 136 | /*
|
---|
| 137 | * Turns a 56 bit key into the 64 bit, odd parity key and sets the key. The
|
---|
| 138 | * key schedule ks is also set.
|
---|
| 139 | */
|
---|
| 140 | static void setup_des_key(const unsigned char *key_56,
|
---|
| 141 | DES_key_schedule DESKEYARG(ks))
|
---|
| 142 | {
|
---|
| 143 | DES_cblock key;
|
---|
| 144 |
|
---|
| 145 | /* Expand the 56-bit key to 64-bits */
|
---|
| 146 | extend_key_56_to_64(key_56, (char *) key);
|
---|
| 147 |
|
---|
| 148 | /* Set the key parity to odd */
|
---|
| 149 | #ifndef HAVE_DES_SET_ODD_PARITY /* older boringssl */
|
---|
| 150 | Curl_des_set_odd_parity((unsigned char *) &key, sizeof(key));
|
---|
| 151 | #else
|
---|
| 152 | DES_set_odd_parity(&key);
|
---|
| 153 | #endif
|
---|
| 154 |
|
---|
| 155 | /* Set the key */
|
---|
| 156 | DES_set_key(&key, ks);
|
---|
| 157 | }
|
---|
| 158 |
|
---|
| 159 | #elif defined(USE_GNUTLS_NETTLE)
|
---|
| 160 |
|
---|
| 161 | static void setup_des_key(const unsigned char *key_56,
|
---|
| 162 | struct des_ctx *des)
|
---|
| 163 | {
|
---|
| 164 | char key[8];
|
---|
| 165 |
|
---|
| 166 | /* Expand the 56-bit key to 64-bits */
|
---|
| 167 | extend_key_56_to_64(key_56, key);
|
---|
| 168 |
|
---|
| 169 | /* Set the key parity to odd */
|
---|
| 170 | Curl_des_set_odd_parity((unsigned char *) key, sizeof(key));
|
---|
| 171 |
|
---|
| 172 | /* Set the key */
|
---|
| 173 | des_set_key(des, (const uint8_t *) key);
|
---|
| 174 | }
|
---|
| 175 |
|
---|
| 176 | #elif defined(USE_GNUTLS)
|
---|
| 177 |
|
---|
| 178 | /*
|
---|
| 179 | * Turns a 56 bit key into the 64 bit, odd parity key and sets the key.
|
---|
| 180 | */
|
---|
| 181 | static void setup_des_key(const unsigned char *key_56,
|
---|
| 182 | gcry_cipher_hd_t *des)
|
---|
| 183 | {
|
---|
| 184 | char key[8];
|
---|
| 185 |
|
---|
| 186 | /* Expand the 56-bit key to 64-bits */
|
---|
| 187 | extend_key_56_to_64(key_56, key);
|
---|
| 188 |
|
---|
| 189 | /* Set the key parity to odd */
|
---|
| 190 | Curl_des_set_odd_parity((unsigned char *) key, sizeof(key));
|
---|
| 191 |
|
---|
| 192 | /* Set the key */
|
---|
| 193 | gcry_cipher_setkey(*des, key, sizeof(key));
|
---|
| 194 | }
|
---|
| 195 |
|
---|
| 196 | #elif defined(USE_NSS)
|
---|
| 197 |
|
---|
| 198 | /*
|
---|
| 199 | * Expands a 56 bit key KEY_56 to 64 bit and encrypts 64 bit of data, using
|
---|
| 200 | * the expanded key. The caller is responsible for giving 64 bit of valid
|
---|
| 201 | * data is IN and (at least) 64 bit large buffer as OUT.
|
---|
| 202 | */
|
---|
| 203 | static bool encrypt_des(const unsigned char *in, unsigned char *out,
|
---|
| 204 | const unsigned char *key_56)
|
---|
| 205 | {
|
---|
| 206 | const CK_MECHANISM_TYPE mech = CKM_DES_ECB; /* DES cipher in ECB mode */
|
---|
| 207 | PK11SlotInfo *slot = NULL;
|
---|
| 208 | char key[8]; /* expanded 64 bit key */
|
---|
| 209 | SECItem key_item;
|
---|
| 210 | PK11SymKey *symkey = NULL;
|
---|
| 211 | SECItem *param = NULL;
|
---|
| 212 | PK11Context *ctx = NULL;
|
---|
| 213 | int out_len; /* not used, required by NSS */
|
---|
| 214 | bool rv = FALSE;
|
---|
| 215 |
|
---|
| 216 | /* use internal slot for DES encryption (requires NSS to be initialized) */
|
---|
| 217 | slot = PK11_GetInternalKeySlot();
|
---|
| 218 | if(!slot)
|
---|
| 219 | return FALSE;
|
---|
| 220 |
|
---|
| 221 | /* Expand the 56-bit key to 64-bits */
|
---|
| 222 | extend_key_56_to_64(key_56, key);
|
---|
| 223 |
|
---|
| 224 | /* Set the key parity to odd */
|
---|
| 225 | Curl_des_set_odd_parity((unsigned char *) key, sizeof(key));
|
---|
| 226 |
|
---|
| 227 | /* Import the key */
|
---|
| 228 | key_item.data = (unsigned char *)key;
|
---|
| 229 | key_item.len = sizeof(key);
|
---|
| 230 | symkey = PK11_ImportSymKey(slot, mech, PK11_OriginUnwrap, CKA_ENCRYPT,
|
---|
| 231 | &key_item, NULL);
|
---|
| 232 | if(!symkey)
|
---|
| 233 | goto fail;
|
---|
| 234 |
|
---|
| 235 | /* Create the DES encryption context */
|
---|
| 236 | param = PK11_ParamFromIV(mech, /* no IV in ECB mode */ NULL);
|
---|
| 237 | if(!param)
|
---|
| 238 | goto fail;
|
---|
| 239 | ctx = PK11_CreateContextBySymKey(mech, CKA_ENCRYPT, symkey, param);
|
---|
| 240 | if(!ctx)
|
---|
| 241 | goto fail;
|
---|
| 242 |
|
---|
| 243 | /* Perform the encryption */
|
---|
| 244 | if(SECSuccess == PK11_CipherOp(ctx, out, &out_len, /* outbuflen */ 8,
|
---|
| 245 | (unsigned char *)in, /* inbuflen */ 8)
|
---|
| 246 | && SECSuccess == PK11_Finalize(ctx))
|
---|
| 247 | rv = /* all OK */ TRUE;
|
---|
| 248 |
|
---|
| 249 | fail:
|
---|
| 250 | /* cleanup */
|
---|
| 251 | if(ctx)
|
---|
| 252 | PK11_DestroyContext(ctx, PR_TRUE);
|
---|
| 253 | if(symkey)
|
---|
| 254 | PK11_FreeSymKey(symkey);
|
---|
| 255 | if(param)
|
---|
| 256 | SECITEM_FreeItem(param, PR_TRUE);
|
---|
| 257 | PK11_FreeSlot(slot);
|
---|
| 258 | return rv;
|
---|
| 259 | }
|
---|
| 260 |
|
---|
| 261 | #elif defined(USE_DARWINSSL)
|
---|
| 262 |
|
---|
| 263 | static bool encrypt_des(const unsigned char *in, unsigned char *out,
|
---|
| 264 | const unsigned char *key_56)
|
---|
| 265 | {
|
---|
| 266 | char key[8];
|
---|
| 267 | size_t out_len;
|
---|
| 268 | CCCryptorStatus err;
|
---|
| 269 |
|
---|
| 270 | /* Expand the 56-bit key to 64-bits */
|
---|
| 271 | extend_key_56_to_64(key_56, key);
|
---|
| 272 |
|
---|
| 273 | /* Set the key parity to odd */
|
---|
| 274 | Curl_des_set_odd_parity((unsigned char *) key, sizeof(key));
|
---|
| 275 |
|
---|
| 276 | /* Perform the encryption */
|
---|
| 277 | err = CCCrypt(kCCEncrypt, kCCAlgorithmDES, kCCOptionECBMode, key,
|
---|
| 278 | kCCKeySizeDES, NULL, in, 8 /* inbuflen */, out,
|
---|
| 279 | 8 /* outbuflen */, &out_len);
|
---|
| 280 |
|
---|
| 281 | return err == kCCSuccess;
|
---|
| 282 | }
|
---|
| 283 |
|
---|
| 284 | #elif defined(USE_OS400CRYPTO)
|
---|
| 285 |
|
---|
| 286 | static bool encrypt_des(const unsigned char *in, unsigned char *out,
|
---|
| 287 | const unsigned char *key_56)
|
---|
| 288 | {
|
---|
| 289 | char key[8];
|
---|
| 290 | _CIPHER_Control_T ctl;
|
---|
| 291 |
|
---|
| 292 | /* Setup the cipher control structure */
|
---|
| 293 | ctl.Func_ID = ENCRYPT_ONLY;
|
---|
| 294 | ctl.Data_Len = sizeof(key);
|
---|
| 295 |
|
---|
| 296 | /* Expand the 56-bit key to 64-bits */
|
---|
| 297 | extend_key_56_to_64(key_56, ctl.Crypto_Key);
|
---|
| 298 |
|
---|
| 299 | /* Set the key parity to odd */
|
---|
| 300 | Curl_des_set_odd_parity((unsigned char *) ctl.Crypto_Key, ctl.Data_Len);
|
---|
| 301 |
|
---|
| 302 | /* Perform the encryption */
|
---|
| 303 | _CIPHER((_SPCPTR *) &out, &ctl, (_SPCPTR *) &in);
|
---|
| 304 |
|
---|
| 305 | return TRUE;
|
---|
| 306 | }
|
---|
| 307 |
|
---|
| 308 | #elif defined(USE_WIN32_CRYPTO)
|
---|
| 309 |
|
---|
| 310 | static bool encrypt_des(const unsigned char *in, unsigned char *out,
|
---|
| 311 | const unsigned char *key_56)
|
---|
| 312 | {
|
---|
| 313 | HCRYPTPROV hprov;
|
---|
| 314 | HCRYPTKEY hkey;
|
---|
| 315 | struct {
|
---|
| 316 | BLOBHEADER hdr;
|
---|
| 317 | unsigned int len;
|
---|
| 318 | char key[8];
|
---|
| 319 | } blob;
|
---|
| 320 | DWORD len = 8;
|
---|
| 321 |
|
---|
| 322 | /* Acquire the crypto provider */
|
---|
| 323 | if(!CryptAcquireContext(&hprov, NULL, NULL, PROV_RSA_FULL,
|
---|
| 324 | CRYPT_VERIFYCONTEXT))
|
---|
| 325 | return FALSE;
|
---|
| 326 |
|
---|
| 327 | /* Setup the key blob structure */
|
---|
| 328 | memset(&blob, 0, sizeof(blob));
|
---|
| 329 | blob.hdr.bType = PLAINTEXTKEYBLOB;
|
---|
| 330 | blob.hdr.bVersion = 2;
|
---|
| 331 | blob.hdr.aiKeyAlg = CALG_DES;
|
---|
| 332 | blob.len = sizeof(blob.key);
|
---|
| 333 |
|
---|
| 334 | /* Expand the 56-bit key to 64-bits */
|
---|
| 335 | extend_key_56_to_64(key_56, blob.key);
|
---|
| 336 |
|
---|
| 337 | /* Set the key parity to odd */
|
---|
| 338 | Curl_des_set_odd_parity((unsigned char *) blob.key, sizeof(blob.key));
|
---|
| 339 |
|
---|
| 340 | /* Import the key */
|
---|
| 341 | if(!CryptImportKey(hprov, (BYTE *) &blob, sizeof(blob), 0, 0, &hkey)) {
|
---|
| 342 | CryptReleaseContext(hprov, 0);
|
---|
| 343 |
|
---|
| 344 | return FALSE;
|
---|
| 345 | }
|
---|
| 346 |
|
---|
| 347 | memcpy(out, in, 8);
|
---|
| 348 |
|
---|
| 349 | /* Perform the encryption */
|
---|
| 350 | CryptEncrypt(hkey, 0, FALSE, 0, out, &len, len);
|
---|
| 351 |
|
---|
| 352 | CryptDestroyKey(hkey);
|
---|
| 353 | CryptReleaseContext(hprov, 0);
|
---|
| 354 |
|
---|
| 355 | return TRUE;
|
---|
| 356 | }
|
---|
| 357 |
|
---|
| 358 | #endif /* defined(USE_WIN32_CRYPTO) */
|
---|
| 359 |
|
---|
| 360 | /*
|
---|
| 361 | * takes a 21 byte array and treats it as 3 56-bit DES keys. The
|
---|
| 362 | * 8 byte plaintext is encrypted with each key and the resulting 24
|
---|
| 363 | * bytes are stored in the results array.
|
---|
| 364 | */
|
---|
| 365 | void Curl_ntlm_core_lm_resp(const unsigned char *keys,
|
---|
| 366 | const unsigned char *plaintext,
|
---|
| 367 | unsigned char *results)
|
---|
| 368 | {
|
---|
| 369 | #ifdef USE_OPENSSL
|
---|
| 370 | DES_key_schedule ks;
|
---|
| 371 |
|
---|
| 372 | setup_des_key(keys, DESKEY(ks));
|
---|
| 373 | DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) results,
|
---|
| 374 | DESKEY(ks), DES_ENCRYPT);
|
---|
| 375 |
|
---|
| 376 | setup_des_key(keys + 7, DESKEY(ks));
|
---|
| 377 | DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) (results + 8),
|
---|
| 378 | DESKEY(ks), DES_ENCRYPT);
|
---|
| 379 |
|
---|
| 380 | setup_des_key(keys + 14, DESKEY(ks));
|
---|
| 381 | DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) (results + 16),
|
---|
| 382 | DESKEY(ks), DES_ENCRYPT);
|
---|
| 383 | #elif defined(USE_GNUTLS_NETTLE)
|
---|
| 384 | struct des_ctx des;
|
---|
| 385 | setup_des_key(keys, &des);
|
---|
| 386 | des_encrypt(&des, 8, results, plaintext);
|
---|
| 387 | setup_des_key(keys + 7, &des);
|
---|
| 388 | des_encrypt(&des, 8, results + 8, plaintext);
|
---|
| 389 | setup_des_key(keys + 14, &des);
|
---|
| 390 | des_encrypt(&des, 8, results + 16, plaintext);
|
---|
| 391 | #elif defined(USE_GNUTLS)
|
---|
| 392 | gcry_cipher_hd_t des;
|
---|
| 393 |
|
---|
| 394 | gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
|
---|
| 395 | setup_des_key(keys, &des);
|
---|
| 396 | gcry_cipher_encrypt(des, results, 8, plaintext, 8);
|
---|
| 397 | gcry_cipher_close(des);
|
---|
| 398 |
|
---|
| 399 | gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
|
---|
| 400 | setup_des_key(keys + 7, &des);
|
---|
| 401 | gcry_cipher_encrypt(des, results + 8, 8, plaintext, 8);
|
---|
| 402 | gcry_cipher_close(des);
|
---|
| 403 |
|
---|
| 404 | gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
|
---|
| 405 | setup_des_key(keys + 14, &des);
|
---|
| 406 | gcry_cipher_encrypt(des, results + 16, 8, plaintext, 8);
|
---|
| 407 | gcry_cipher_close(des);
|
---|
| 408 | #elif defined(USE_NSS) || defined(USE_DARWINSSL) || defined(USE_OS400CRYPTO) \
|
---|
| 409 | || defined(USE_WIN32_CRYPTO)
|
---|
| 410 | encrypt_des(plaintext, results, keys);
|
---|
| 411 | encrypt_des(plaintext, results + 8, keys + 7);
|
---|
| 412 | encrypt_des(plaintext, results + 16, keys + 14);
|
---|
| 413 | #endif
|
---|
| 414 | }
|
---|
| 415 |
|
---|
| 416 | /*
|
---|
| 417 | * Set up lanmanager hashed password
|
---|
| 418 | */
|
---|
| 419 | CURLcode Curl_ntlm_core_mk_lm_hash(struct SessionHandle *data,
|
---|
| 420 | const char *password,
|
---|
| 421 | unsigned char *lmbuffer /* 21 bytes */)
|
---|
| 422 | {
|
---|
| 423 | CURLcode result;
|
---|
| 424 | unsigned char pw[14];
|
---|
| 425 | static const unsigned char magic[] = {
|
---|
| 426 | 0x4B, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 /* i.e. KGS!@#$% */
|
---|
| 427 | };
|
---|
| 428 | size_t len = CURLMIN(strlen(password), 14);
|
---|
| 429 |
|
---|
| 430 | Curl_strntoupper((char *)pw, password, len);
|
---|
| 431 | memset(&pw[len], 0, 14 - len);
|
---|
| 432 |
|
---|
| 433 | /*
|
---|
| 434 | * The LanManager hashed password needs to be created using the
|
---|
| 435 | * password in the network encoding not the host encoding.
|
---|
| 436 | */
|
---|
| 437 | result = Curl_convert_to_network(data, (char *)pw, 14);
|
---|
| 438 | if(result)
|
---|
| 439 | return result;
|
---|
| 440 |
|
---|
| 441 | {
|
---|
| 442 | /* Create LanManager hashed password. */
|
---|
| 443 |
|
---|
| 444 | #ifdef USE_OPENSSL
|
---|
| 445 | DES_key_schedule ks;
|
---|
| 446 |
|
---|
| 447 | setup_des_key(pw, DESKEY(ks));
|
---|
| 448 | DES_ecb_encrypt((DES_cblock *)magic, (DES_cblock *)lmbuffer,
|
---|
| 449 | DESKEY(ks), DES_ENCRYPT);
|
---|
| 450 |
|
---|
| 451 | setup_des_key(pw + 7, DESKEY(ks));
|
---|
| 452 | DES_ecb_encrypt((DES_cblock *)magic, (DES_cblock *)(lmbuffer + 8),
|
---|
| 453 | DESKEY(ks), DES_ENCRYPT);
|
---|
| 454 | #elif defined(USE_GNUTLS_NETTLE)
|
---|
| 455 | struct des_ctx des;
|
---|
| 456 | setup_des_key(pw, &des);
|
---|
| 457 | des_encrypt(&des, 8, lmbuffer, magic);
|
---|
| 458 | setup_des_key(pw + 7, &des);
|
---|
| 459 | des_encrypt(&des, 8, lmbuffer + 8, magic);
|
---|
| 460 | #elif defined(USE_GNUTLS)
|
---|
| 461 | gcry_cipher_hd_t des;
|
---|
| 462 |
|
---|
| 463 | gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
|
---|
| 464 | setup_des_key(pw, &des);
|
---|
| 465 | gcry_cipher_encrypt(des, lmbuffer, 8, magic, 8);
|
---|
| 466 | gcry_cipher_close(des);
|
---|
| 467 |
|
---|
| 468 | gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
|
---|
| 469 | setup_des_key(pw + 7, &des);
|
---|
| 470 | gcry_cipher_encrypt(des, lmbuffer + 8, 8, magic, 8);
|
---|
| 471 | gcry_cipher_close(des);
|
---|
| 472 | #elif defined(USE_NSS) || defined(USE_DARWINSSL) || defined(USE_OS400CRYPTO) \
|
---|
| 473 | || defined(USE_WIN32_CRYPTO)
|
---|
| 474 | encrypt_des(magic, lmbuffer, pw);
|
---|
| 475 | encrypt_des(magic, lmbuffer + 8, pw + 7);
|
---|
| 476 | #endif
|
---|
| 477 |
|
---|
| 478 | memset(lmbuffer + 16, 0, 21 - 16);
|
---|
| 479 | }
|
---|
| 480 |
|
---|
| 481 | return CURLE_OK;
|
---|
| 482 | }
|
---|
| 483 |
|
---|
| 484 | #if USE_NTRESPONSES
|
---|
| 485 | static void ascii_to_unicode_le(unsigned char *dest, const char *src,
|
---|
| 486 | size_t srclen)
|
---|
| 487 | {
|
---|
| 488 | size_t i;
|
---|
| 489 | for(i = 0; i < srclen; i++) {
|
---|
| 490 | dest[2 * i] = (unsigned char)src[i];
|
---|
| 491 | dest[2 * i + 1] = '\0';
|
---|
| 492 | }
|
---|
| 493 | }
|
---|
| 494 |
|
---|
| 495 | #if USE_NTLM_V2 && !defined(USE_WINDOWS_SSPI)
|
---|
| 496 |
|
---|
| 497 | static void ascii_uppercase_to_unicode_le(unsigned char *dest,
|
---|
| 498 | const char *src, size_t srclen)
|
---|
| 499 | {
|
---|
| 500 | size_t i;
|
---|
| 501 | for(i = 0; i < srclen; i++) {
|
---|
| 502 | dest[2 * i] = (unsigned char)(toupper(src[i]));
|
---|
| 503 | dest[2 * i + 1] = '\0';
|
---|
| 504 | }
|
---|
| 505 | }
|
---|
| 506 |
|
---|
| 507 | #endif /* USE_NTLM_V2 && !USE_WINDOWS_SSPI */
|
---|
| 508 |
|
---|
| 509 | /*
|
---|
| 510 | * Set up nt hashed passwords
|
---|
| 511 | * @unittest: 1600
|
---|
| 512 | */
|
---|
| 513 | CURLcode Curl_ntlm_core_mk_nt_hash(struct SessionHandle *data,
|
---|
| 514 | const char *password,
|
---|
| 515 | unsigned char *ntbuffer /* 21 bytes */)
|
---|
| 516 | {
|
---|
| 517 | size_t len = strlen(password);
|
---|
| 518 | unsigned char *pw = malloc(len * 2);
|
---|
| 519 | CURLcode result;
|
---|
| 520 | if(!pw)
|
---|
| 521 | return CURLE_OUT_OF_MEMORY;
|
---|
| 522 |
|
---|
| 523 | ascii_to_unicode_le(pw, password, len);
|
---|
| 524 |
|
---|
| 525 | /*
|
---|
| 526 | * The NT hashed password needs to be created using the password in the
|
---|
| 527 | * network encoding not the host encoding.
|
---|
| 528 | */
|
---|
| 529 | result = Curl_convert_to_network(data, (char *)pw, len * 2);
|
---|
| 530 | if(result)
|
---|
| 531 | return result;
|
---|
| 532 |
|
---|
| 533 | {
|
---|
| 534 | /* Create NT hashed password. */
|
---|
| 535 | #ifdef USE_OPENSSL
|
---|
| 536 | MD4_CTX MD4pw;
|
---|
| 537 | MD4_Init(&MD4pw);
|
---|
| 538 | MD4_Update(&MD4pw, pw, 2 * len);
|
---|
| 539 | MD4_Final(ntbuffer, &MD4pw);
|
---|
| 540 | #elif defined(USE_GNUTLS_NETTLE)
|
---|
| 541 | struct md4_ctx MD4pw;
|
---|
| 542 | md4_init(&MD4pw);
|
---|
| 543 | md4_update(&MD4pw, (unsigned int)(2 * len), pw);
|
---|
| 544 | md4_digest(&MD4pw, MD4_DIGEST_SIZE, ntbuffer);
|
---|
| 545 | #elif defined(USE_GNUTLS)
|
---|
| 546 | gcry_md_hd_t MD4pw;
|
---|
| 547 | gcry_md_open(&MD4pw, GCRY_MD_MD4, 0);
|
---|
| 548 | gcry_md_write(MD4pw, pw, 2 * len);
|
---|
| 549 | memcpy (ntbuffer, gcry_md_read (MD4pw, 0), MD4_DIGEST_LENGTH);
|
---|
| 550 | gcry_md_close(MD4pw);
|
---|
| 551 | #elif defined(USE_NSS) || defined(USE_OS400CRYPTO)
|
---|
| 552 | Curl_md4it(ntbuffer, pw, 2 * len);
|
---|
| 553 | #elif defined(USE_DARWINSSL)
|
---|
| 554 | (void)CC_MD4(pw, (CC_LONG)(2 * len), ntbuffer);
|
---|
| 555 | #elif defined(USE_WIN32_CRYPTO)
|
---|
| 556 | HCRYPTPROV hprov;
|
---|
| 557 | if(CryptAcquireContext(&hprov, NULL, NULL, PROV_RSA_FULL,
|
---|
| 558 | CRYPT_VERIFYCONTEXT)) {
|
---|
| 559 | HCRYPTHASH hhash;
|
---|
| 560 | if(CryptCreateHash(hprov, CALG_MD4, 0, 0, &hhash)) {
|
---|
| 561 | DWORD length = 16;
|
---|
| 562 | CryptHashData(hhash, pw, (unsigned int)len * 2, 0);
|
---|
| 563 | CryptGetHashParam(hhash, HP_HASHVAL, ntbuffer, &length, 0);
|
---|
| 564 | CryptDestroyHash(hhash);
|
---|
| 565 | }
|
---|
| 566 | CryptReleaseContext(hprov, 0);
|
---|
| 567 | }
|
---|
| 568 | #endif
|
---|
| 569 |
|
---|
| 570 | memset(ntbuffer + 16, 0, 21 - 16);
|
---|
| 571 | }
|
---|
| 572 |
|
---|
| 573 | free(pw);
|
---|
| 574 |
|
---|
| 575 | return CURLE_OK;
|
---|
| 576 | }
|
---|
| 577 |
|
---|
| 578 | #if USE_NTLM_V2 && !defined(USE_WINDOWS_SSPI)
|
---|
| 579 |
|
---|
| 580 | /* This returns the HMAC MD5 digest */
|
---|
| 581 | CURLcode Curl_hmac_md5(const unsigned char *key, unsigned int keylen,
|
---|
| 582 | const unsigned char *data, unsigned int datalen,
|
---|
| 583 | unsigned char *output)
|
---|
| 584 | {
|
---|
| 585 | HMAC_context *ctxt = Curl_HMAC_init(Curl_HMAC_MD5, key, keylen);
|
---|
| 586 |
|
---|
| 587 | if(!ctxt)
|
---|
| 588 | return CURLE_OUT_OF_MEMORY;
|
---|
| 589 |
|
---|
| 590 | /* Update the digest with the given challenge */
|
---|
| 591 | Curl_HMAC_update(ctxt, data, datalen);
|
---|
| 592 |
|
---|
| 593 | /* Finalise the digest */
|
---|
| 594 | Curl_HMAC_final(ctxt, output);
|
---|
| 595 |
|
---|
| 596 | return CURLE_OK;
|
---|
| 597 | }
|
---|
| 598 |
|
---|
| 599 | /* This creates the NTLMv2 hash by using NTLM hash as the key and Unicode
|
---|
| 600 | * (uppercase UserName + Domain) as the data
|
---|
| 601 | */
|
---|
| 602 | CURLcode Curl_ntlm_core_mk_ntlmv2_hash(const char *user, size_t userlen,
|
---|
| 603 | const char *domain, size_t domlen,
|
---|
| 604 | unsigned char *ntlmhash,
|
---|
| 605 | unsigned char *ntlmv2hash)
|
---|
| 606 | {
|
---|
| 607 | /* Unicode representation */
|
---|
| 608 | size_t identity_len = (userlen + domlen) * 2;
|
---|
| 609 | unsigned char *identity = malloc(identity_len);
|
---|
| 610 | CURLcode result = CURLE_OK;
|
---|
| 611 |
|
---|
| 612 | if(!identity)
|
---|
| 613 | return CURLE_OUT_OF_MEMORY;
|
---|
| 614 |
|
---|
| 615 | ascii_uppercase_to_unicode_le(identity, user, userlen);
|
---|
| 616 | ascii_to_unicode_le(identity + (userlen << 1), domain, domlen);
|
---|
| 617 |
|
---|
| 618 | result = Curl_hmac_md5(ntlmhash, 16, identity, curlx_uztoui(identity_len),
|
---|
| 619 | ntlmv2hash);
|
---|
| 620 |
|
---|
| 621 | free(identity);
|
---|
| 622 |
|
---|
| 623 | return result;
|
---|
| 624 | }
|
---|
| 625 |
|
---|
| 626 | /*
|
---|
| 627 | * Curl_ntlm_core_mk_ntlmv2_resp()
|
---|
| 628 | *
|
---|
| 629 | * This creates the NTLMv2 response as set in the ntlm type-3 message.
|
---|
| 630 | *
|
---|
| 631 | * Parameters:
|
---|
| 632 | *
|
---|
| 633 | * ntlmv2hash [in] - The ntlmv2 hash (16 bytes)
|
---|
| 634 | * challenge_client [in] - The client nonce (8 bytes)
|
---|
| 635 | * ntlm [in] - The ntlm data struct being used to read TargetInfo
|
---|
| 636 | and Server challenge received in the type-2 message
|
---|
| 637 | * ntresp [out] - The address where a pointer to newly allocated
|
---|
| 638 | * memory holding the NTLMv2 response.
|
---|
| 639 | * ntresp_len [out] - The length of the output message.
|
---|
| 640 | *
|
---|
| 641 | * Returns CURLE_OK on success.
|
---|
| 642 | */
|
---|
| 643 | CURLcode Curl_ntlm_core_mk_ntlmv2_resp(unsigned char *ntlmv2hash,
|
---|
| 644 | unsigned char *challenge_client,
|
---|
| 645 | struct ntlmdata *ntlm,
|
---|
| 646 | unsigned char **ntresp,
|
---|
| 647 | unsigned int *ntresp_len)
|
---|
| 648 | {
|
---|
| 649 | /* NTLMv2 response structure :
|
---|
| 650 | ------------------------------------------------------------------------------
|
---|
| 651 | 0 HMAC MD5 16 bytes
|
---|
| 652 | ------BLOB--------------------------------------------------------------------
|
---|
| 653 | 16 Signature 0x01010000
|
---|
| 654 | 20 Reserved long (0x00000000)
|
---|
| 655 | 24 Timestamp LE, 64-bit signed value representing the number of
|
---|
| 656 | tenths of a microsecond since January 1, 1601.
|
---|
| 657 | 32 Client Nonce 8 bytes
|
---|
| 658 | 40 Unknown 4 bytes
|
---|
| 659 | 44 Target Info N bytes (from the type-2 message)
|
---|
| 660 | 44+N Unknown 4 bytes
|
---|
| 661 | ------------------------------------------------------------------------------
|
---|
| 662 | */
|
---|
| 663 |
|
---|
| 664 | unsigned int len = 0;
|
---|
| 665 | unsigned char *ptr = NULL;
|
---|
| 666 | unsigned char hmac_output[NTLM_HMAC_MD5_LEN];
|
---|
| 667 | curl_off_t tw;
|
---|
| 668 |
|
---|
| 669 | CURLcode result = CURLE_OK;
|
---|
| 670 |
|
---|
| 671 | #if CURL_SIZEOF_CURL_OFF_T < 8
|
---|
| 672 | #error "this section needs 64bit support to work"
|
---|
| 673 | #endif
|
---|
| 674 |
|
---|
| 675 | /* Calculate the timestamp */
|
---|
| 676 | #ifdef DEBUGBUILD
|
---|
| 677 | char *force_timestamp = getenv("CURL_FORCETIME");
|
---|
| 678 | if(force_timestamp)
|
---|
| 679 | tw = CURL_OFF_T_C(11644473600) * 10000000;
|
---|
| 680 | else
|
---|
| 681 | #endif
|
---|
| 682 | tw = ((curl_off_t)time(NULL) + CURL_OFF_T_C(11644473600)) * 10000000;
|
---|
| 683 |
|
---|
| 684 | /* Calculate the response len */
|
---|
| 685 | len = NTLM_HMAC_MD5_LEN + NTLMv2_BLOB_LEN;
|
---|
| 686 |
|
---|
| 687 | /* Allocate the response */
|
---|
| 688 | ptr = malloc(len);
|
---|
| 689 | if(!ptr)
|
---|
| 690 | return CURLE_OUT_OF_MEMORY;
|
---|
| 691 |
|
---|
| 692 | memset(ptr, 0, len);
|
---|
| 693 |
|
---|
| 694 | /* Create the BLOB structure */
|
---|
| 695 | snprintf((char *)ptr + NTLM_HMAC_MD5_LEN, NTLMv2_BLOB_LEN,
|
---|
| 696 | NTLMv2_BLOB_SIGNATURE
|
---|
| 697 | "%c%c%c%c", /* Reserved = 0 */
|
---|
| 698 | 0, 0, 0, 0);
|
---|
| 699 |
|
---|
| 700 | Curl_write64_le(tw, ptr + 24);
|
---|
| 701 | memcpy(ptr + 32, challenge_client, 8);
|
---|
| 702 | memcpy(ptr + 44, ntlm->target_info, ntlm->target_info_len);
|
---|
| 703 |
|
---|
| 704 | /* Concatenate the Type 2 challenge with the BLOB and do HMAC MD5 */
|
---|
| 705 | memcpy(ptr + 8, &ntlm->nonce[0], 8);
|
---|
| 706 | result = Curl_hmac_md5(ntlmv2hash, NTLM_HMAC_MD5_LEN, ptr + 8,
|
---|
| 707 | NTLMv2_BLOB_LEN + 8, hmac_output);
|
---|
| 708 | if(result) {
|
---|
| 709 | free(ptr);
|
---|
| 710 | return result;
|
---|
| 711 | }
|
---|
| 712 |
|
---|
| 713 | /* Concatenate the HMAC MD5 output with the BLOB */
|
---|
| 714 | memcpy(ptr, hmac_output, NTLM_HMAC_MD5_LEN);
|
---|
| 715 |
|
---|
| 716 | /* Return the response */
|
---|
| 717 | *ntresp = ptr;
|
---|
| 718 | *ntresp_len = len;
|
---|
| 719 |
|
---|
| 720 | return result;
|
---|
| 721 | }
|
---|
| 722 |
|
---|
| 723 | /*
|
---|
| 724 | * Curl_ntlm_core_mk_lmv2_resp()
|
---|
| 725 | *
|
---|
| 726 | * This creates the LMv2 response as used in the ntlm type-3 message.
|
---|
| 727 | *
|
---|
| 728 | * Parameters:
|
---|
| 729 | *
|
---|
| 730 | * ntlmv2hash [in] - The ntlmv2 hash (16 bytes)
|
---|
| 731 | * challenge_client [in] - The client nonce (8 bytes)
|
---|
| 732 | * challenge_client [in] - The server challenge (8 bytes)
|
---|
| 733 | * lmresp [out] - The LMv2 response (24 bytes)
|
---|
| 734 | *
|
---|
| 735 | * Returns CURLE_OK on success.
|
---|
| 736 | */
|
---|
| 737 | CURLcode Curl_ntlm_core_mk_lmv2_resp(unsigned char *ntlmv2hash,
|
---|
| 738 | unsigned char *challenge_client,
|
---|
| 739 | unsigned char *challenge_server,
|
---|
| 740 | unsigned char *lmresp)
|
---|
| 741 | {
|
---|
| 742 | unsigned char data[16];
|
---|
| 743 | unsigned char hmac_output[16];
|
---|
| 744 | CURLcode result = CURLE_OK;
|
---|
| 745 |
|
---|
| 746 | memcpy(&data[0], challenge_server, 8);
|
---|
| 747 | memcpy(&data[8], challenge_client, 8);
|
---|
| 748 |
|
---|
| 749 | result = Curl_hmac_md5(ntlmv2hash, 16, &data[0], 16, hmac_output);
|
---|
| 750 | if(result)
|
---|
| 751 | return result;
|
---|
| 752 |
|
---|
| 753 | /* Concatenate the HMAC MD5 output with the client nonce */
|
---|
| 754 | memcpy(lmresp, hmac_output, 16);
|
---|
| 755 | memcpy(lmresp+16, challenge_client, 8);
|
---|
| 756 |
|
---|
| 757 | return result;
|
---|
| 758 | }
|
---|
| 759 |
|
---|
| 760 | #endif /* USE_NTLM_V2 && !USE_WINDOWS_SSPI */
|
---|
| 761 |
|
---|
| 762 | #endif /* USE_NTRESPONSES */
|
---|
| 763 |
|
---|
| 764 | #endif /* !USE_WINDOWS_SSPI || USE_WIN32_CRYPTO */
|
---|
| 765 |
|
---|
| 766 | #endif /* USE_NTLM */
|
---|