From cca455a36b7c3472fa64b148ded9a11deef93017 Mon Sep 17 00:00:00 2001 From: Patrick Monnerat Date: Tue, 6 Apr 2021 19:31:03 +0200 Subject: ntlm: support version 2 on 32-bit platforms Closes #6849 --- lib/curl_ntlm_core.c | 69 +++++++++++++++++++++++++++++++++++++++++++--------- lib/curl_ntlm_core.h | 10 +++++--- lib/vauth/ntlm.c | 6 +---- 3 files changed, 66 insertions(+), 19 deletions(-) diff --git a/lib/curl_ntlm_core.c b/lib/curl_ntlm_core.c index 66146a881..89d4ec872 100644 --- a/lib/curl_ntlm_core.c +++ b/lib/curl_ntlm_core.c @@ -513,6 +513,56 @@ CURLcode Curl_ntlm_core_mk_nt_hash(struct Curl_easy *data, #if defined(USE_NTLM_V2) && !defined(USE_WINDOWS_SSPI) +/* Timestamp in tenths of a microsecond since January 1, 1601 00:00:00 UTC. */ +struct ms_filetime { + unsigned int dwLowDateTime; + unsigned int dwHighDateTime; +}; + +/* Convert a time_t to an MS FILETIME (MS-DTYP section 2.3.3). */ +static void time2filetime(struct ms_filetime *ft, time_t t) +{ +#if SIZEOF_TIME_T > 4 + t = (t + CURL_OFF_T_C(11644473600)) * 10000000; + ft->dwLowDateTime = (unsigned int) (t & 0xFFFFFFFF); + ft->dwHighDateTime = (unsigned int) (t >> 32); +#else + unsigned int r, s; + unsigned int i; + + ft->dwLowDateTime = t & 0xFFFFFFFF; + ft->dwHighDateTime = 0; + +# ifndef HAVE_TIME_T_UNSIGNED + /* Extend sign if needed. */ + if(ft->dwLowDateTime & 0x80000000) + ft->dwHighDateTime = ~0; +# endif + + /* Bias seconds to Jan 1, 1601. + 134774 days = 11644473600 seconds = 0x2B6109100 */ + r = ft->dwLowDateTime; + ft->dwLowDateTime = (ft->dwLowDateTime + 0xB6109100U) & 0xFFFFFFFF; + ft->dwHighDateTime += ft->dwLowDateTime < r? 0x03: 0x02; + + /* Convert to tenths of microseconds. */ + ft->dwHighDateTime *= 10000000; + i = 32; + do { + i -= 8; + s = ((ft->dwLowDateTime >> i) & 0xFF) * (10000000 - 1); + r = (s << i) & 0xFFFFFFFF; + s >>= 1; /* Split shift to avoid width overflow. */ + s >>= 31 - i; + ft->dwLowDateTime = (ft->dwLowDateTime + r) & 0xFFFFFFFF; + if(ft->dwLowDateTime < r) + s++; + ft->dwHighDateTime += s; + } while(i); + ft->dwHighDateTime &= 0xFFFFFFFF; +#endif +} + /* This creates the NTLMv2 hash by using NTLM hash as the key and Unicode * (uppercase UserName + Domain) as the data */ @@ -586,22 +636,18 @@ CURLcode Curl_ntlm_core_mk_ntlmv2_resp(unsigned char *ntlmv2hash, unsigned int len = 0; unsigned char *ptr = NULL; unsigned char hmac_output[HMAC_MD5_LENGTH]; - curl_off_t tw; + struct ms_filetime tw; CURLcode result = CURLE_OK; -#if SIZEOF_CURL_OFF_T < 8 -#error "this section needs 64bit support to work" -#endif - /* Calculate the timestamp */ #ifdef DEBUGBUILD char *force_timestamp = getenv("CURL_FORCETIME"); if(force_timestamp) - tw = CURL_OFF_T_C(11644473600) * 10000000; + time2filetime(&tw, (time_t) 0); else #endif - tw = ((curl_off_t)time(NULL) + CURL_OFF_T_C(11644473600)) * 10000000; + time2filetime(&tw, time(NULL)); /* Calculate the response len */ len = HMAC_MD5_LENGTH + NTLMv2_BLOB_LEN; @@ -613,13 +659,14 @@ CURLcode Curl_ntlm_core_mk_ntlmv2_resp(unsigned char *ntlmv2hash, /* Create the BLOB structure */ msnprintf((char *)ptr + HMAC_MD5_LENGTH, NTLMv2_BLOB_LEN, - "%c%c%c%c" /* NTLMv2_BLOB_SIGNATURE */ - "%c%c%c%c", /* Reserved = 0 */ + "%c%c%c%c" /* NTLMv2_BLOB_SIGNATURE */ + "%c%c%c%c" /* Reserved = 0 */ + "%c%c%c%c%c%c%c%c", /* Timestamp */ NTLMv2_BLOB_SIGNATURE[0], NTLMv2_BLOB_SIGNATURE[1], NTLMv2_BLOB_SIGNATURE[2], NTLMv2_BLOB_SIGNATURE[3], - 0, 0, 0, 0); + 0, 0, 0, 0, + LONGQUARTET(tw.dwLowDateTime), LONGQUARTET(tw.dwHighDateTime)); - Curl_write64_le(tw, ptr + 24); memcpy(ptr + 32, challenge_client, 8); memcpy(ptr + 44, ntlm->target_info, ntlm->target_info_len); diff --git a/lib/curl_ntlm_core.h b/lib/curl_ntlm_core.h index a5e02b7f8..02b39d485 100644 --- a/lib/curl_ntlm_core.h +++ b/lib/curl_ntlm_core.h @@ -53,12 +53,16 @@ #endif /* Define USE_NTLM_V2 in order to allow the type-3 message to include the - LMv2 and NTLMv2 response messages, requires USE_NTRESPONSES defined to 1 - and support for 64-bit integers. */ -#if defined(USE_NTRESPONSES) && (SIZEOF_CURL_OFF_T > 4) + LMv2 and NTLMv2 response messages, requires USE_NTRESPONSES defined to 1 */ +#if defined(USE_NTRESPONSES) #define USE_NTLM_V2 #endif +/* Helpers to generate function byte arguments in little endian order */ +#define SHORTPAIR(x) ((int)((x) & 0xff)), ((int)(((x) >> 8) & 0xff)) +#define LONGQUARTET(x) ((int)((x) & 0xff)), ((int)(((x) >> 8) & 0xff)), \ + ((int)(((x) >> 16) & 0xff)), ((int)(((x) >> 24) & 0xff)) + void Curl_ntlm_core_lm_resp(const unsigned char *keys, const unsigned char *plaintext, unsigned char *results); diff --git a/lib/vauth/ntlm.c b/lib/vauth/ntlm.c index a3117f3fe..5831c5662 100644 --- a/lib/vauth/ntlm.c +++ b/lib/vauth/ntlm.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -64,10 +64,6 @@ /* "NTLMSSP" signature is always in ASCII regardless of the platform */ #define NTLMSSP_SIGNATURE "\x4e\x54\x4c\x4d\x53\x53\x50" -#define SHORTPAIR(x) ((int)((x) & 0xff)), ((int)(((x) >> 8) & 0xff)) -#define LONGQUARTET(x) ((int)((x) & 0xff)), ((int)(((x) >> 8) & 0xff)), \ - ((int)(((x) >> 16) & 0xff)), ((int)(((x) >> 24) & 0xff)) - #if DEBUG_ME # define DEBUG_OUT(x) x static void ntlm_print_flags(FILE *handle, unsigned long flags) -- cgit v1.2.1