curl_ntlm_core.c
Go to the documentation of this file.
00001 /***************************************************************************
00002  *                                  _   _ ____  _
00003  *  Project                     ___| | | |  _ \| |
00004  *                             / __| | | | |_) | |
00005  *                            | (__| |_| |  _ <| |___
00006  *                             \___|\___/|_| \_\_____|
00007  *
00008  * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
00009  *
00010  * This software is licensed as described in the file COPYING, which
00011  * you should have received as part of this distribution. The terms
00012  * are also available at https://curl.haxx.se/docs/copyright.html.
00013  *
00014  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
00015  * copies of the Software, and permit persons to whom the Software is
00016  * furnished to do so, under the terms of the COPYING file.
00017  *
00018  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
00019  * KIND, either express or implied.
00020  *
00021  ***************************************************************************/
00022 
00023 #include "curl_setup.h"
00024 
00025 #if defined(USE_NTLM)
00026 
00027 /*
00028  * NTLM details:
00029  *
00030  * http://davenport.sourceforge.net/ntlm.html
00031  * https://www.innovation.ch/java/ntlm.html
00032  */
00033 
00034 #if !defined(USE_WINDOWS_SSPI) || defined(USE_WIN32_CRYPTO)
00035 
00036 #ifdef USE_OPENSSL
00037 
00038 #  ifdef USE_OPENSSL
00039 #    include <openssl/des.h>
00040 #    ifndef OPENSSL_NO_MD4
00041 #      include <openssl/md4.h>
00042 #    endif
00043 #    include <openssl/md5.h>
00044 #    include <openssl/ssl.h>
00045 #    include <openssl/rand.h>
00046 #  else
00047 #    include <des.h>
00048 #    ifndef OPENSSL_NO_MD4
00049 #      include <md4.h>
00050 #    endif
00051 #    include <md5.h>
00052 #    include <ssl.h>
00053 #    include <rand.h>
00054 #  endif
00055 #  if (OPENSSL_VERSION_NUMBER < 0x00907001L)
00056 #    define DES_key_schedule des_key_schedule
00057 #    define DES_cblock des_cblock
00058 #    define DES_set_odd_parity des_set_odd_parity
00059 #    define DES_set_key des_set_key
00060 #    define DES_ecb_encrypt des_ecb_encrypt
00061 #    define DESKEY(x) x
00062 #    define DESKEYARG(x) x
00063 #  else
00064 #    define DESKEYARG(x) *x
00065 #    define DESKEY(x) &x
00066 #  endif
00067 
00068 #elif defined(USE_GNUTLS_NETTLE)
00069 
00070 #  include <nettle/des.h>
00071 #  include <nettle/md4.h>
00072 
00073 #elif defined(USE_GNUTLS)
00074 
00075 #  include <gcrypt.h>
00076 #  define MD5_DIGEST_LENGTH 16
00077 #  define MD4_DIGEST_LENGTH 16
00078 
00079 #elif defined(USE_MBEDTLS)
00080 
00081 #  include <mbedtls/des.h>
00082 #  include <mbedtls/md4.h>
00083 
00084 #elif defined(USE_NSS)
00085 
00086 #  include <nss.h>
00087 #  include <pk11pub.h>
00088 #  include <hasht.h>
00089 #  include "curl_md4.h"
00090 #  define MD5_DIGEST_LENGTH MD5_LENGTH
00091 
00092 #elif defined(USE_DARWINSSL)
00093 
00094 #  include <CommonCrypto/CommonCryptor.h>
00095 #  include <CommonCrypto/CommonDigest.h>
00096 
00097 #elif defined(USE_OS400CRYPTO)
00098 #  include "cipher.mih"  /* mih/cipher */
00099 #  include "curl_md4.h"
00100 #elif defined(USE_WIN32_CRYPTO)
00101 #  include <wincrypt.h>
00102 #else
00103 #  error "Can't compile NTLM support without a crypto library."
00104 #endif
00105 
00106 #include "urldata.h"
00107 #include "non-ascii.h"
00108 #include "strcase.h"
00109 #include "curl_ntlm_core.h"
00110 #include "curl_md5.h"
00111 #include "curl_hmac.h"
00112 #include "warnless.h"
00113 #include "curl_endian.h"
00114 #include "curl_des.h"
00115 /* The last 3 #include files should be in this order */
00116 #include "curl_printf.h"
00117 #include "curl_memory.h"
00118 #include "memdebug.h"
00119 
00120 #define NTLM_HMAC_MD5_LEN     (16)
00121 #define NTLMv2_BLOB_SIGNATURE "\x01\x01\x00\x00"
00122 #define NTLMv2_BLOB_LEN       (44 -16 + ntlm->target_info_len + 4)
00123 
00124 /*
00125 * Turns a 56-bit key into being 64-bit wide.
00126 */
00127 static void extend_key_56_to_64(const unsigned char *key_56, char *key)
00128 {
00129   key[0] = key_56[0];
00130   key[1] = (unsigned char)(((key_56[0] << 7) & 0xFF) | (key_56[1] >> 1));
00131   key[2] = (unsigned char)(((key_56[1] << 6) & 0xFF) | (key_56[2] >> 2));
00132   key[3] = (unsigned char)(((key_56[2] << 5) & 0xFF) | (key_56[3] >> 3));
00133   key[4] = (unsigned char)(((key_56[3] << 4) & 0xFF) | (key_56[4] >> 4));
00134   key[5] = (unsigned char)(((key_56[4] << 3) & 0xFF) | (key_56[5] >> 5));
00135   key[6] = (unsigned char)(((key_56[5] << 2) & 0xFF) | (key_56[6] >> 6));
00136   key[7] = (unsigned char) ((key_56[6] << 1) & 0xFF);
00137 }
00138 
00139 #ifdef USE_OPENSSL
00140 /*
00141  * Turns a 56 bit key into the 64 bit, odd parity key and sets the key.  The
00142  * key schedule ks is also set.
00143  */
00144 static void setup_des_key(const unsigned char *key_56,
00145                           DES_key_schedule DESKEYARG(ks))
00146 {
00147   DES_cblock key;
00148 
00149   /* Expand the 56-bit key to 64-bits */
00150   extend_key_56_to_64(key_56, (char *) &key);
00151 
00152   /* Set the key parity to odd */
00153   DES_set_odd_parity(&key);
00154 
00155   /* Set the key */
00156   DES_set_key(&key, ks);
00157 }
00158 
00159 #elif defined(USE_GNUTLS_NETTLE)
00160 
00161 static void setup_des_key(const unsigned char *key_56,
00162                           struct des_ctx *des)
00163 {
00164   char key[8];
00165 
00166   /* Expand the 56-bit key to 64-bits */
00167   extend_key_56_to_64(key_56, key);
00168 
00169   /* Set the key parity to odd */
00170   Curl_des_set_odd_parity((unsigned char *) key, sizeof(key));
00171 
00172   /* Set the key */
00173   des_set_key(des, (const uint8_t *) key);
00174 }
00175 
00176 #elif defined(USE_GNUTLS)
00177 
00178 /*
00179  * Turns a 56 bit key into the 64 bit, odd parity key and sets the key.
00180  */
00181 static void setup_des_key(const unsigned char *key_56,
00182                           gcry_cipher_hd_t *des)
00183 {
00184   char key[8];
00185 
00186   /* Expand the 56-bit key to 64-bits */
00187   extend_key_56_to_64(key_56, key);
00188 
00189   /* Set the key parity to odd */
00190   Curl_des_set_odd_parity((unsigned char *) key, sizeof(key));
00191 
00192   /* Set the key */
00193   gcry_cipher_setkey(*des, key, sizeof(key));
00194 }
00195 
00196 #elif defined(USE_MBEDTLS)
00197 
00198 static bool encrypt_des(const unsigned char *in, unsigned char *out,
00199                         const unsigned char *key_56)
00200 {
00201   mbedtls_des_context ctx;
00202   char key[8];
00203 
00204   /* Expand the 56-bit key to 64-bits */
00205   extend_key_56_to_64(key_56, key);
00206 
00207   /* Set the key parity to odd */
00208   mbedtls_des_key_set_parity((unsigned char *) key);
00209 
00210   /* Perform the encryption */
00211   mbedtls_des_init(&ctx);
00212   mbedtls_des_setkey_enc(&ctx, (unsigned char *) key);
00213   return mbedtls_des_crypt_ecb(&ctx, in, out) == 0;
00214 }
00215 
00216 #elif defined(USE_NSS)
00217 
00218 /*
00219  * Expands a 56 bit key KEY_56 to 64 bit and encrypts 64 bit of data, using
00220  * the expanded key.  The caller is responsible for giving 64 bit of valid
00221  * data is IN and (at least) 64 bit large buffer as OUT.
00222  */
00223 static bool encrypt_des(const unsigned char *in, unsigned char *out,
00224                         const unsigned char *key_56)
00225 {
00226   const CK_MECHANISM_TYPE mech = CKM_DES_ECB; /* DES cipher in ECB mode */
00227   PK11SlotInfo *slot = NULL;
00228   char key[8];                                /* expanded 64 bit key */
00229   SECItem key_item;
00230   PK11SymKey *symkey = NULL;
00231   SECItem *param = NULL;
00232   PK11Context *ctx = NULL;
00233   int out_len;                                /* not used, required by NSS */
00234   bool rv = FALSE;
00235 
00236   /* use internal slot for DES encryption (requires NSS to be initialized) */
00237   slot = PK11_GetInternalKeySlot();
00238   if(!slot)
00239     return FALSE;
00240 
00241   /* Expand the 56-bit key to 64-bits */
00242   extend_key_56_to_64(key_56, key);
00243 
00244   /* Set the key parity to odd */
00245   Curl_des_set_odd_parity((unsigned char *) key, sizeof(key));
00246 
00247   /* Import the key */
00248   key_item.data = (unsigned char *)key;
00249   key_item.len = sizeof(key);
00250   symkey = PK11_ImportSymKey(slot, mech, PK11_OriginUnwrap, CKA_ENCRYPT,
00251                              &key_item, NULL);
00252   if(!symkey)
00253     goto fail;
00254 
00255   /* Create the DES encryption context */
00256   param = PK11_ParamFromIV(mech, /* no IV in ECB mode */ NULL);
00257   if(!param)
00258     goto fail;
00259   ctx = PK11_CreateContextBySymKey(mech, CKA_ENCRYPT, symkey, param);
00260   if(!ctx)
00261     goto fail;
00262 
00263   /* Perform the encryption */
00264   if(SECSuccess == PK11_CipherOp(ctx, out, &out_len, /* outbuflen */ 8,
00265                                  (unsigned char *)in, /* inbuflen */ 8)
00266       && SECSuccess == PK11_Finalize(ctx))
00267     rv = /* all OK */ TRUE;
00268 
00269 fail:
00270   /* cleanup */
00271   if(ctx)
00272     PK11_DestroyContext(ctx, PR_TRUE);
00273   if(symkey)
00274     PK11_FreeSymKey(symkey);
00275   if(param)
00276     SECITEM_FreeItem(param, PR_TRUE);
00277   PK11_FreeSlot(slot);
00278   return rv;
00279 }
00280 
00281 #elif defined(USE_DARWINSSL)
00282 
00283 static bool encrypt_des(const unsigned char *in, unsigned char *out,
00284                         const unsigned char *key_56)
00285 {
00286   char key[8];
00287   size_t out_len;
00288   CCCryptorStatus err;
00289 
00290   /* Expand the 56-bit key to 64-bits */
00291   extend_key_56_to_64(key_56, key);
00292 
00293   /* Set the key parity to odd */
00294   Curl_des_set_odd_parity((unsigned char *) key, sizeof(key));
00295 
00296   /* Perform the encryption */
00297   err = CCCrypt(kCCEncrypt, kCCAlgorithmDES, kCCOptionECBMode, key,
00298                 kCCKeySizeDES, NULL, in, 8 /* inbuflen */, out,
00299                 8 /* outbuflen */, &out_len);
00300 
00301   return err == kCCSuccess;
00302 }
00303 
00304 #elif defined(USE_OS400CRYPTO)
00305 
00306 static bool encrypt_des(const unsigned char *in, unsigned char *out,
00307                         const unsigned char *key_56)
00308 {
00309   char key[8];
00310   _CIPHER_Control_T ctl;
00311 
00312   /* Setup the cipher control structure */
00313   ctl.Func_ID = ENCRYPT_ONLY;
00314   ctl.Data_Len = sizeof(key);
00315 
00316   /* Expand the 56-bit key to 64-bits */
00317   extend_key_56_to_64(key_56, ctl.Crypto_Key);
00318 
00319   /* Set the key parity to odd */
00320   Curl_des_set_odd_parity((unsigned char *) ctl.Crypto_Key, ctl.Data_Len);
00321 
00322   /* Perform the encryption */
00323   _CIPHER((_SPCPTR *) &out, &ctl, (_SPCPTR *) &in);
00324 
00325   return TRUE;
00326 }
00327 
00328 #elif defined(USE_WIN32_CRYPTO)
00329 
00330 static bool encrypt_des(const unsigned char *in, unsigned char *out,
00331                         const unsigned char *key_56)
00332 {
00333   HCRYPTPROV hprov;
00334   HCRYPTKEY hkey;
00335   struct {
00336     BLOBHEADER hdr;
00337     unsigned int len;
00338     char key[8];
00339   } blob;
00340   DWORD len = 8;
00341 
00342   /* Acquire the crypto provider */
00343   if(!CryptAcquireContext(&hprov, NULL, NULL, PROV_RSA_FULL,
00344                           CRYPT_VERIFYCONTEXT))
00345     return FALSE;
00346 
00347   /* Setup the key blob structure */
00348   memset(&blob, 0, sizeof(blob));
00349   blob.hdr.bType = PLAINTEXTKEYBLOB;
00350   blob.hdr.bVersion = 2;
00351   blob.hdr.aiKeyAlg = CALG_DES;
00352   blob.len = sizeof(blob.key);
00353 
00354   /* Expand the 56-bit key to 64-bits */
00355   extend_key_56_to_64(key_56, blob.key);
00356 
00357   /* Set the key parity to odd */
00358   Curl_des_set_odd_parity((unsigned char *) blob.key, sizeof(blob.key));
00359 
00360   /* Import the key */
00361   if(!CryptImportKey(hprov, (BYTE *) &blob, sizeof(blob), 0, 0, &hkey)) {
00362     CryptReleaseContext(hprov, 0);
00363 
00364     return FALSE;
00365   }
00366 
00367   memcpy(out, in, 8);
00368 
00369   /* Perform the encryption */
00370   CryptEncrypt(hkey, 0, FALSE, 0, out, &len, len);
00371 
00372   CryptDestroyKey(hkey);
00373   CryptReleaseContext(hprov, 0);
00374 
00375   return TRUE;
00376 }
00377 
00378 #endif /* defined(USE_WIN32_CRYPTO) */
00379 
00380  /*
00381   * takes a 21 byte array and treats it as 3 56-bit DES keys. The
00382   * 8 byte plaintext is encrypted with each key and the resulting 24
00383   * bytes are stored in the results array.
00384   */
00385 void Curl_ntlm_core_lm_resp(const unsigned char *keys,
00386                             const unsigned char *plaintext,
00387                             unsigned char *results)
00388 {
00389 #ifdef USE_OPENSSL
00390   DES_key_schedule ks;
00391 
00392   setup_des_key(keys, DESKEY(ks));
00393   DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) results,
00394                   DESKEY(ks), DES_ENCRYPT);
00395 
00396   setup_des_key(keys + 7, DESKEY(ks));
00397   DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) (results + 8),
00398                   DESKEY(ks), DES_ENCRYPT);
00399 
00400   setup_des_key(keys + 14, DESKEY(ks));
00401   DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) (results + 16),
00402                   DESKEY(ks), DES_ENCRYPT);
00403 #elif defined(USE_GNUTLS_NETTLE)
00404   struct des_ctx des;
00405   setup_des_key(keys, &des);
00406   des_encrypt(&des, 8, results, plaintext);
00407   setup_des_key(keys + 7, &des);
00408   des_encrypt(&des, 8, results + 8, plaintext);
00409   setup_des_key(keys + 14, &des);
00410   des_encrypt(&des, 8, results + 16, plaintext);
00411 #elif defined(USE_GNUTLS)
00412   gcry_cipher_hd_t des;
00413 
00414   gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
00415   setup_des_key(keys, &des);
00416   gcry_cipher_encrypt(des, results, 8, plaintext, 8);
00417   gcry_cipher_close(des);
00418 
00419   gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
00420   setup_des_key(keys + 7, &des);
00421   gcry_cipher_encrypt(des, results + 8, 8, plaintext, 8);
00422   gcry_cipher_close(des);
00423 
00424   gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
00425   setup_des_key(keys + 14, &des);
00426   gcry_cipher_encrypt(des, results + 16, 8, plaintext, 8);
00427   gcry_cipher_close(des);
00428 #elif defined(USE_MBEDTLS) || defined(USE_NSS) || defined(USE_DARWINSSL) \
00429   || defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO)
00430   encrypt_des(plaintext, results, keys);
00431   encrypt_des(plaintext, results + 8, keys + 7);
00432   encrypt_des(plaintext, results + 16, keys + 14);
00433 #endif
00434 }
00435 
00436 /*
00437  * Set up lanmanager hashed password
00438  */
00439 CURLcode Curl_ntlm_core_mk_lm_hash(struct Curl_easy *data,
00440                                    const char *password,
00441                                    unsigned char *lmbuffer /* 21 bytes */)
00442 {
00443   CURLcode result;
00444   unsigned char pw[14];
00445   static const unsigned char magic[] = {
00446     0x4B, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 /* i.e. KGS!@#$% */
00447   };
00448   size_t len = CURLMIN(strlen(password), 14);
00449 
00450   Curl_strntoupper((char *)pw, password, len);
00451   memset(&pw[len], 0, 14 - len);
00452 
00453   /*
00454    * The LanManager hashed password needs to be created using the
00455    * password in the network encoding not the host encoding.
00456    */
00457   result = Curl_convert_to_network(data, (char *)pw, 14);
00458   if(result)
00459     return result;
00460 
00461   {
00462     /* Create LanManager hashed password. */
00463 
00464 #ifdef USE_OPENSSL
00465     DES_key_schedule ks;
00466 
00467     setup_des_key(pw, DESKEY(ks));
00468     DES_ecb_encrypt((DES_cblock *)magic, (DES_cblock *)lmbuffer,
00469                     DESKEY(ks), DES_ENCRYPT);
00470 
00471     setup_des_key(pw + 7, DESKEY(ks));
00472     DES_ecb_encrypt((DES_cblock *)magic, (DES_cblock *)(lmbuffer + 8),
00473                     DESKEY(ks), DES_ENCRYPT);
00474 #elif defined(USE_GNUTLS_NETTLE)
00475     struct des_ctx des;
00476     setup_des_key(pw, &des);
00477     des_encrypt(&des, 8, lmbuffer, magic);
00478     setup_des_key(pw + 7, &des);
00479     des_encrypt(&des, 8, lmbuffer + 8, magic);
00480 #elif defined(USE_GNUTLS)
00481     gcry_cipher_hd_t des;
00482 
00483     gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
00484     setup_des_key(pw, &des);
00485     gcry_cipher_encrypt(des, lmbuffer, 8, magic, 8);
00486     gcry_cipher_close(des);
00487 
00488     gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0);
00489     setup_des_key(pw + 7, &des);
00490     gcry_cipher_encrypt(des, lmbuffer + 8, 8, magic, 8);
00491     gcry_cipher_close(des);
00492 #elif defined(USE_MBEDTLS) || defined(USE_NSS) || defined(USE_DARWINSSL) \
00493   || defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO)
00494     encrypt_des(magic, lmbuffer, pw);
00495     encrypt_des(magic, lmbuffer + 8, pw + 7);
00496 #endif
00497 
00498     memset(lmbuffer + 16, 0, 21 - 16);
00499   }
00500 
00501   return CURLE_OK;
00502 }
00503 
00504 #if USE_NTRESPONSES
00505 static void ascii_to_unicode_le(unsigned char *dest, const char *src,
00506                                 size_t srclen)
00507 {
00508   size_t i;
00509   for(i = 0; i < srclen; i++) {
00510     dest[2 * i] = (unsigned char)src[i];
00511     dest[2 * i + 1] = '\0';
00512   }
00513 }
00514 
00515 #if USE_NTLM_V2 && !defined(USE_WINDOWS_SSPI)
00516 
00517 static void ascii_uppercase_to_unicode_le(unsigned char *dest,
00518                                           const char *src, size_t srclen)
00519 {
00520   size_t i;
00521   for(i = 0; i < srclen; i++) {
00522     dest[2 * i] = (unsigned char)(toupper(src[i]));
00523     dest[2 * i + 1] = '\0';
00524   }
00525 }
00526 
00527 #endif /* USE_NTLM_V2 && !USE_WINDOWS_SSPI */
00528 
00529 /*
00530  * Set up nt hashed passwords
00531  * @unittest: 1600
00532  */
00533 CURLcode Curl_ntlm_core_mk_nt_hash(struct Curl_easy *data,
00534                                    const char *password,
00535                                    unsigned char *ntbuffer /* 21 bytes */)
00536 {
00537   size_t len = strlen(password);
00538   unsigned char *pw = malloc(len * 2);
00539   CURLcode result;
00540   if(!pw)
00541     return CURLE_OUT_OF_MEMORY;
00542 
00543   ascii_to_unicode_le(pw, password, len);
00544 
00545   /*
00546    * The NT hashed password needs to be created using the password in the
00547    * network encoding not the host encoding.
00548    */
00549   result = Curl_convert_to_network(data, (char *)pw, len * 2);
00550   if(result)
00551     return result;
00552 
00553   {
00554     /* Create NT hashed password. */
00555 #ifdef USE_OPENSSL
00556     MD4_CTX MD4pw;
00557     MD4_Init(&MD4pw);
00558     MD4_Update(&MD4pw, pw, 2 * len);
00559     MD4_Final(ntbuffer, &MD4pw);
00560 #elif defined(USE_GNUTLS_NETTLE)
00561     struct md4_ctx MD4pw;
00562     md4_init(&MD4pw);
00563     md4_update(&MD4pw, (unsigned int)(2 * len), pw);
00564     md4_digest(&MD4pw, MD4_DIGEST_SIZE, ntbuffer);
00565 #elif defined(USE_GNUTLS)
00566     gcry_md_hd_t MD4pw;
00567     gcry_md_open(&MD4pw, GCRY_MD_MD4, 0);
00568     gcry_md_write(MD4pw, pw, 2 * len);
00569     memcpy(ntbuffer, gcry_md_read(MD4pw, 0), MD4_DIGEST_LENGTH);
00570     gcry_md_close(MD4pw);
00571 #elif defined(USE_MBEDTLS)
00572     mbedtls_md4(pw, 2 * len, ntbuffer);
00573 #elif defined(USE_NSS) || defined(USE_OS400CRYPTO)
00574     Curl_md4it(ntbuffer, pw, 2 * len);
00575 #elif defined(USE_DARWINSSL)
00576     (void)CC_MD4(pw, (CC_LONG)(2 * len), ntbuffer);
00577 #elif defined(USE_WIN32_CRYPTO)
00578     HCRYPTPROV hprov;
00579     if(CryptAcquireContext(&hprov, NULL, NULL, PROV_RSA_FULL,
00580                            CRYPT_VERIFYCONTEXT)) {
00581       HCRYPTHASH hhash;
00582       if(CryptCreateHash(hprov, CALG_MD4, 0, 0, &hhash)) {
00583         DWORD length = 16;
00584         CryptHashData(hhash, pw, (unsigned int)len * 2, 0);
00585         CryptGetHashParam(hhash, HP_HASHVAL, ntbuffer, &length, 0);
00586         CryptDestroyHash(hhash);
00587       }
00588       CryptReleaseContext(hprov, 0);
00589     }
00590 #endif
00591 
00592     memset(ntbuffer + 16, 0, 21 - 16);
00593   }
00594 
00595   free(pw);
00596 
00597   return CURLE_OK;
00598 }
00599 
00600 #if USE_NTLM_V2 && !defined(USE_WINDOWS_SSPI)
00601 
00602 /* This returns the HMAC MD5 digest */
00603 CURLcode Curl_hmac_md5(const unsigned char *key, unsigned int keylen,
00604                        const unsigned char *data, unsigned int datalen,
00605                        unsigned char *output)
00606 {
00607   HMAC_context *ctxt = Curl_HMAC_init(Curl_HMAC_MD5, key, keylen);
00608 
00609   if(!ctxt)
00610     return CURLE_OUT_OF_MEMORY;
00611 
00612   /* Update the digest with the given challenge */
00613   Curl_HMAC_update(ctxt, data, datalen);
00614 
00615   /* Finalise the digest */
00616   Curl_HMAC_final(ctxt, output);
00617 
00618   return CURLE_OK;
00619 }
00620 
00621 /* This creates the NTLMv2 hash by using NTLM hash as the key and Unicode
00622  * (uppercase UserName + Domain) as the data
00623  */
00624 CURLcode Curl_ntlm_core_mk_ntlmv2_hash(const char *user, size_t userlen,
00625                                        const char *domain, size_t domlen,
00626                                        unsigned char *ntlmhash,
00627                                        unsigned char *ntlmv2hash)
00628 {
00629   /* Unicode representation */
00630   size_t identity_len = (userlen + domlen) * 2;
00631   unsigned char *identity = malloc(identity_len);
00632   CURLcode result = CURLE_OK;
00633 
00634   if(!identity)
00635     return CURLE_OUT_OF_MEMORY;
00636 
00637   ascii_uppercase_to_unicode_le(identity, user, userlen);
00638   ascii_to_unicode_le(identity + (userlen << 1), domain, domlen);
00639 
00640   result = Curl_hmac_md5(ntlmhash, 16, identity, curlx_uztoui(identity_len),
00641                          ntlmv2hash);
00642 
00643   free(identity);
00644 
00645   return result;
00646 }
00647 
00648 /*
00649  * Curl_ntlm_core_mk_ntlmv2_resp()
00650  *
00651  * This creates the NTLMv2 response as set in the ntlm type-3 message.
00652  *
00653  * Parameters:
00654  *
00655  * ntlmv2hash       [in] - The ntlmv2 hash (16 bytes)
00656  * challenge_client [in] - The client nonce (8 bytes)
00657  * ntlm             [in] - The ntlm data struct being used to read TargetInfo
00658                            and Server challenge received in the type-2 message
00659  * ntresp          [out] - The address where a pointer to newly allocated
00660  *                         memory holding the NTLMv2 response.
00661  * ntresp_len      [out] - The length of the output message.
00662  *
00663  * Returns CURLE_OK on success.
00664  */
00665 CURLcode Curl_ntlm_core_mk_ntlmv2_resp(unsigned char *ntlmv2hash,
00666                                        unsigned char *challenge_client,
00667                                        struct ntlmdata *ntlm,
00668                                        unsigned char **ntresp,
00669                                        unsigned int *ntresp_len)
00670 {
00671 /* NTLMv2 response structure :
00672 ------------------------------------------------------------------------------
00673 0     HMAC MD5         16 bytes
00674 ------BLOB--------------------------------------------------------------------
00675 16    Signature        0x01010000
00676 20    Reserved         long (0x00000000)
00677 24    Timestamp        LE, 64-bit signed value representing the number of
00678                        tenths of a microsecond since January 1, 1601.
00679 32    Client Nonce     8 bytes
00680 40    Unknown          4 bytes
00681 44    Target Info      N bytes (from the type-2 message)
00682 44+N  Unknown          4 bytes
00683 ------------------------------------------------------------------------------
00684 */
00685 
00686   unsigned int len = 0;
00687   unsigned char *ptr = NULL;
00688   unsigned char hmac_output[NTLM_HMAC_MD5_LEN];
00689   curl_off_t tw;
00690 
00691   CURLcode result = CURLE_OK;
00692 
00693 #if CURL_SIZEOF_CURL_OFF_T < 8
00694 #error "this section needs 64bit support to work"
00695 #endif
00696 
00697   /* Calculate the timestamp */
00698 #ifdef DEBUGBUILD
00699   char *force_timestamp = getenv("CURL_FORCETIME");
00700   if(force_timestamp)
00701     tw = CURL_OFF_T_C(11644473600) * 10000000;
00702   else
00703 #endif
00704     tw = ((curl_off_t)time(NULL) + CURL_OFF_T_C(11644473600)) * 10000000;
00705 
00706   /* Calculate the response len */
00707   len = NTLM_HMAC_MD5_LEN + NTLMv2_BLOB_LEN;
00708 
00709   /* Allocate the response */
00710   ptr = malloc(len);
00711   if(!ptr)
00712     return CURLE_OUT_OF_MEMORY;
00713 
00714   memset(ptr, 0, len);
00715 
00716   /* Create the BLOB structure */
00717   snprintf((char *)ptr + NTLM_HMAC_MD5_LEN, NTLMv2_BLOB_LEN,
00718            NTLMv2_BLOB_SIGNATURE
00719            "%c%c%c%c",  /* Reserved = 0 */
00720            0, 0, 0, 0);
00721 
00722   Curl_write64_le(tw, ptr + 24);
00723   memcpy(ptr + 32, challenge_client, 8);
00724   memcpy(ptr + 44, ntlm->target_info, ntlm->target_info_len);
00725 
00726   /* Concatenate the Type 2 challenge with the BLOB and do HMAC MD5 */
00727   memcpy(ptr + 8, &ntlm->nonce[0], 8);
00728   result = Curl_hmac_md5(ntlmv2hash, NTLM_HMAC_MD5_LEN, ptr + 8,
00729                          NTLMv2_BLOB_LEN + 8, hmac_output);
00730   if(result) {
00731     free(ptr);
00732     return result;
00733   }
00734 
00735   /* Concatenate the HMAC MD5 output  with the BLOB */
00736   memcpy(ptr, hmac_output, NTLM_HMAC_MD5_LEN);
00737 
00738   /* Return the response */
00739   *ntresp = ptr;
00740   *ntresp_len = len;
00741 
00742   return result;
00743 }
00744 
00745 /*
00746  * Curl_ntlm_core_mk_lmv2_resp()
00747  *
00748  * This creates the LMv2 response as used in the ntlm type-3 message.
00749  *
00750  * Parameters:
00751  *
00752  * ntlmv2hash        [in] - The ntlmv2 hash (16 bytes)
00753  * challenge_client  [in] - The client nonce (8 bytes)
00754  * challenge_client  [in] - The server challenge (8 bytes)
00755  * lmresp           [out] - The LMv2 response (24 bytes)
00756  *
00757  * Returns CURLE_OK on success.
00758  */
00759 CURLcode  Curl_ntlm_core_mk_lmv2_resp(unsigned char *ntlmv2hash,
00760                                       unsigned char *challenge_client,
00761                                       unsigned char *challenge_server,
00762                                       unsigned char *lmresp)
00763 {
00764   unsigned char data[16];
00765   unsigned char hmac_output[16];
00766   CURLcode result = CURLE_OK;
00767 
00768   memcpy(&data[0], challenge_server, 8);
00769   memcpy(&data[8], challenge_client, 8);
00770 
00771   result = Curl_hmac_md5(ntlmv2hash, 16, &data[0], 16, hmac_output);
00772   if(result)
00773     return result;
00774 
00775   /* Concatenate the HMAC MD5 output  with the client nonce */
00776   memcpy(lmresp, hmac_output, 16);
00777   memcpy(lmresp+16, challenge_client, 8);
00778 
00779   return result;
00780 }
00781 
00782 #endif /* USE_NTLM_V2 && !USE_WINDOWS_SSPI */
00783 
00784 #endif /* USE_NTRESPONSES */
00785 
00786 #endif /* !USE_WINDOWS_SSPI || USE_WIN32_CRYPTO */
00787 
00788 #endif /* USE_NTLM */


rc_visard_driver
Author(s): Heiko Hirschmueller , Christian Emmerich , Felix Ruess
autogenerated on Thu Jun 6 2019 20:43:02