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