From eb88d778e751639d68d932b23a648e591bcc0ba8 Mon Sep 17 00:00:00 2001 From: Bill Nagel Date: Tue, 2 Dec 2014 13:21:52 -0500 Subject: [PATCH] ntlm: Use Windows Crypt API Allow the use of the Windows Crypt API for NTLMv1 functions. --- lib/config-win32.h | 3 ++ lib/curl_ntlm_core.c | 75 +++++++++++++++++++++++++++++++++++++++++--- lib/curl_ntlm_core.h | 22 ++++++++----- lib/curl_setup.h | 2 +- 4 files changed, 88 insertions(+), 14 deletions(-) diff --git a/lib/config-win32.h b/lib/config-win32.h index 684da7ae5..ba3e7a708 100644 --- a/lib/config-win32.h +++ b/lib/config-win32.h @@ -699,6 +699,9 @@ # define CURL_DISABLE_LDAP 1 #endif +/* Define to use the Windows crypto library. */ +#define USE_WIN32_CRYPTO + /* ---------------------------------------------------------------- */ /* ADDITIONAL DEFINITIONS */ /* ---------------------------------------------------------------- */ diff --git a/lib/curl_ntlm_core.c b/lib/curl_ntlm_core.c index 21fb37550..ee015398c 100644 --- a/lib/curl_ntlm_core.c +++ b/lib/curl_ntlm_core.c @@ -22,7 +22,7 @@ #include "curl_setup.h" -#if defined(USE_NTLM) && !defined(USE_WINDOWS_SSPI) +#if defined(USE_NTLM) /* * NTLM details: @@ -90,6 +90,8 @@ #elif defined(USE_OS400CRYPTO) # include "cipher.mih" /* mih/cipher */ # include "curl_md4.h" +#elif defined(USE_WIN32_CRYPTO) +# include #else # error "Can't compile NTLM support without a crypto library." #endif @@ -267,7 +269,51 @@ static bool encrypt_des(const unsigned char *in, unsigned char *out, return TRUE; } -#endif /* defined(USE_OS400CRYPTO) */ +#elif defined(USE_WIN32_CRYPTO) + +static bool encrypt_des(const unsigned char *in, unsigned char *out, + const unsigned char *key_56) +{ + HCRYPTPROV hprov; + HCRYPTKEY hkey; + struct { + BLOBHEADER hdr; + unsigned int len; + char key[8]; + } blob; + unsigned int len = 8; + + /* Acquire the crypto provider */ + if(!CryptAcquireContext(&hprov, NULL, NULL, PROV_RSA_FULL, + CRYPT_VERIFYCONTEXT)) + return FALSE; + + memset(&blob, 0, sizeof(blob)); + extend_key_56_to_64(key_56, blob.key); + blob.hdr.bType = PLAINTEXTKEYBLOB; + blob.hdr.bVersion = 2; + blob.hdr.aiKeyAlg = CALG_DES; + blob.len = sizeof(blob.key); + + /* Import the key */ + if(!CryptImportKey(hprov, (char *) &blob, sizeof(blob), 0, 0, &hkey)) { + CryptReleaseContext(hprov, 0); + + return FALSE; + } + + memcpy(out, in, 8); + + /* Perform the encryption */ + CryptEncrypt(hkey, 0, FALSE, 0, out, &len, len); + + CryptDestroyKey(hkey); + CryptReleaseContext(hprov, 0); + + return TRUE; +} + +#endif /* defined(USE_WIN32_CRYPTO) */ #endif /* defined(USE_SSLEAY) */ @@ -319,7 +365,8 @@ void Curl_ntlm_core_lm_resp(const unsigned char *keys, setup_des_key(keys + 14, &des); gcry_cipher_encrypt(des, results + 16, 8, plaintext, 8); gcry_cipher_close(des); -#elif defined(USE_NSS) || defined(USE_DARWINSSL) || defined(USE_OS400CRYPTO) +#elif defined(USE_NSS) || defined(USE_DARWINSSL) || defined(USE_OS400CRYPTO) \ + || defined(USE_WIN32_CRYPTO) encrypt_des(plaintext, results, keys); encrypt_des(plaintext, results + 8, keys + 7); encrypt_des(plaintext, results + 16, keys + 14); @@ -382,7 +429,8 @@ CURLcode Curl_ntlm_core_mk_lm_hash(struct SessionHandle *data, setup_des_key(pw + 7, &des); gcry_cipher_encrypt(des, lmbuffer + 8, 8, magic, 8); gcry_cipher_close(des); -#elif defined(USE_NSS) || defined(USE_DARWINSSL) || defined(USE_OS400CRYPTO) +#elif defined(USE_NSS) || defined(USE_DARWINSSL) || defined(USE_OS400CRYPTO) \ + || defined(USE_WIN32_CRYPTO) encrypt_des(magic, lmbuffer, pw); encrypt_des(magic, lmbuffer + 8, pw + 7); #endif @@ -477,6 +525,19 @@ CURLcode Curl_ntlm_core_mk_nt_hash(struct SessionHandle *data, Curl_md4it(ntbuffer, pw, 2 * len); #elif defined(USE_DARWINSSL) (void)CC_MD4(pw, (CC_LONG)(2 * len), ntbuffer); +#elif defined(USE_WIN32_CRYPTO) + HCRYPTPROV hprov; + if(CryptAcquireContext(&hprov, NULL, NULL, PROV_RSA_FULL, + CRYPT_VERIFYCONTEXT)) { + HCRYPTHASH hhash; + if(CryptCreateHash(hprov, CALG_MD4, 0, 0, &hhash)) { + unsigned int length = 16; + CryptHashData(hhash, pw, (unsigned int)len * 2, 0); + CryptGetHashParam(hhash, HP_HASHVAL, ntbuffer, &length, 0); + CryptDestroyHash(hhash); + } + CryptReleaseContext(hprov, 0); + } #endif memset(ntbuffer + 16, 0, 21 - 16); @@ -487,6 +548,8 @@ CURLcode Curl_ntlm_core_mk_nt_hash(struct SessionHandle *data, return CURLE_OK; } +#ifndef USE_WINDOWS_SSPI + /* This returns the HMAC MD5 digest */ CURLcode Curl_hmac_md5(const unsigned char *key, unsigned int keylen, const unsigned char *data, unsigned int datalen, @@ -667,6 +730,8 @@ CURLcode Curl_ntlm_core_mk_lmv2_resp(unsigned char *ntlmv2hash, return result; } +#endif /* !USE_WINDOWS_SSPI */ + #endif /* USE_NTRESPONSES */ -#endif /* USE_NTLM && !USE_WINDOWS_SSPI */ +#endif /* USE_NTLM */ diff --git a/lib/curl_ntlm_core.h b/lib/curl_ntlm_core.h index 0a6dd934c..5e89ef056 100644 --- a/lib/curl_ntlm_core.h +++ b/lib/curl_ntlm_core.h @@ -24,7 +24,7 @@ #include "curl_setup.h" -#if defined(USE_NTLM) && !defined(USE_WINDOWS_SSPI) +#if defined(USE_NTLM) #ifdef USE_SSLEAY # if !defined(OPENSSL_VERSION_NUMBER) && \ @@ -46,7 +46,9 @@ #ifndef USE_NTRESPONSES # define USE_NTRESPONSES 1 -# define USE_NTLM2SESSION 1 +# ifndef USE_WIN32_CRYPTO +# define USE_NTLM2SESSION 1 +# endif #endif void Curl_ntlm_core_lm_resp(const unsigned char *keys, @@ -58,14 +60,16 @@ CURLcode Curl_ntlm_core_mk_lm_hash(struct SessionHandle *data, unsigned char *lmbuffer /* 21 bytes */); #if USE_NTRESPONSES -CURLcode Curl_hmac_md5(const unsigned char *key, unsigned int keylen, - const unsigned char *data, unsigned int datalen, - unsigned char *output); - CURLcode Curl_ntlm_core_mk_nt_hash(struct SessionHandle *data, const char *password, unsigned char *ntbuffer /* 21 bytes */); +#ifndef USE_WINDOWS_SSPI + +CURLcode Curl_hmac_md5(const unsigned char *key, unsigned int keylen, + const unsigned char *data, unsigned int datalen, + unsigned char *output); + CURLcode Curl_ntlm_core_mk_ntlmv2_hash(const char *user, size_t userlen, const char *domain, size_t domlen, unsigned char *ntlmhash, @@ -82,8 +86,10 @@ CURLcode Curl_ntlm_core_mk_lmv2_resp(unsigned char *ntlmv2hash, unsigned char *challenge_server, unsigned char *lmresp); -#endif +#endif /* !USE_WINDOWS_SSPI */ -#endif /* USE_NTLM && !USE_WINDOWS_SSPI */ +#endif /* USE_NTRESPONSES */ + +#endif /* USE_NTLM */ #endif /* HEADER_CURL_NTLM_CORE_H */ diff --git a/lib/curl_setup.h b/lib/curl_setup.h index 6370e80f5..84c1b41ce 100644 --- a/lib/curl_setup.h +++ b/lib/curl_setup.h @@ -624,7 +624,7 @@ int netware_init(void); #if !defined(CURL_DISABLE_NTLM) && !defined(CURL_DISABLE_CRYPTO_AUTH) #if defined(USE_SSLEAY) || defined(USE_WINDOWS_SSPI) || \ defined(USE_GNUTLS) || defined(USE_NSS) || defined(USE_DARWINSSL) || \ - defined(USE_OS400CRYPTO) + defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO) #define USE_NTLM #endif #endif