Loading lib/curl_ntlm.c +6 −0 Original line number Diff line number Diff line Loading @@ -235,6 +235,12 @@ void Curl_http_ntlm_cleanup(struct connectdata *conn) #else (void)conn; #endif #ifndef USE_WINDOWS_SSPI Curl_safefree(conn->ntlm.target_info); conn->ntlm.target_info_len = 0; #endif } #endif /* USE_NTLM */ lib/curl_ntlm_core.c +185 −1 Original line number Diff line number Diff line Loading @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms Loading Loading @@ -96,6 +96,9 @@ #include "rawstr.h" #include "curl_memory.h" #include "curl_ntlm_core.h" #include "curl_md5.h" #include "curl_hmac.h" #include "warnless.h" #define _MPRINTF_REPLACE /* use our functions only */ #include <curl/mprintf.h> Loading @@ -103,6 +106,10 @@ /* The last #include file should be: */ #include "memdebug.h" #define NTLM_HMAC_MD5_LEN (16) #define NTLMv2_BLOB_SIGNATURE "\x01\x01\x00\x00" #define NTLMv2_BLOB_LEN (44 -16 + ntlm->target_info_len + 4) #ifdef USE_SSLEAY /* * Turns a 56 bit key into the 64 bit, odd parity key and sets the key. The Loading Loading @@ -377,6 +384,16 @@ static void ascii_to_unicode_le(unsigned char *dest, const char *src, } } static void ascii_uppercase_to_unicode_le(unsigned char *dest, const char *src, size_t srclen) { size_t i; for(i = 0; i < srclen; i++) { dest[2 * i] = (unsigned char)(toupper(src[i])); dest[2 * i + 1] = '\0'; } } /* * Set up nt hashed passwords */ Loading Loading @@ -431,6 +448,173 @@ CURLcode Curl_ntlm_core_mk_nt_hash(struct SessionHandle *data, return CURLE_OK; } /* This returns the HMAC MD5 digest */ CURLcode Curl_hmac_md5(const unsigned char *key, unsigned int keylen, const unsigned char *data, unsigned int datalen, unsigned char *output) { HMAC_context *ctxt = Curl_HMAC_init(Curl_HMAC_MD5, key, keylen); if(!ctxt) return CURLE_OUT_OF_MEMORY; /* Update the digest with the given challenge */ Curl_HMAC_update(ctxt, data, datalen); /* Finalise the digest */ Curl_HMAC_final(ctxt, output); return CURLE_OK; } /* This creates the NTLMv2 hash by using NTLM hash as the key and Unicode * (uppercase UserName + Domain) as the data */ CURLcode Curl_ntlm_core_mk_ntlmv2_hash(const char *user, size_t userlen, const char *domain, size_t domlen, unsigned char *ntlmhash, unsigned char *ntlmv2hash) { /* Unicode representation */ size_t identity_len = (userlen + domlen) * 2; unsigned char *identity = malloc(identity_len); CURLcode res = CURLE_OK; if(!identity) return CURLE_OUT_OF_MEMORY; ascii_uppercase_to_unicode_le(identity, user, userlen); ascii_to_unicode_le(identity + (userlen << 1), domain, domlen); res = Curl_hmac_md5(ntlmhash, 16, identity, curlx_uztoui(identity_len), ntlmv2hash); Curl_safefree(identity); return res; } /* * Curl_ntlm_core_mk_ntlmv2_resp() * * This creates the NTLMv2 response as set in the ntlm type-3 message. * * Parameters: * * ntlmv2hash [in] - The ntlmv2 hash (16 bytes) * challenge_client [in] - The client nonce (8 bytes) * ntlm [in] - The ntlm data struct being used to read TargetInfo and Server challenge received in the type-2 message * ntresp [out] - The address where a pointer to newly allocated * memory holding the NTLMv2 response. * ntresp_len [out] - The length of the output message. * * Returns CURLE_OK on success. */ CURLcode Curl_ntlm_core_mk_ntlmv2_resp(unsigned char *ntlmv2hash, unsigned char *challenge_client, struct ntlmdata *ntlm, unsigned char **ntresp, unsigned int *ntresp_len) { /* NTLMv2 response structure : ------------------------------------------------------------------------------ 0 HMAC MD5 16 bytes ------BLOB-------------------------------------------------------------------- 16 Signature 0x01010000 20 Reserved long (0x00000000) 24 Timestamp LE, 64-bit signed value representing the number of tenths of a microsecond since January 1, 1601. 32 Client Nonce 8 bytes 40 Unknown 4 bytes 44 Target Info N bytes (from the type-2 message) 44+N Unknown 4 bytes ------------------------------------------------------------------------------ */ unsigned char *ptr = NULL; unsigned char hmac_output[NTLM_HMAC_MD5_LEN]; long long tw; CURLcode res = CURLE_OK; /* Calculate the timestamp */ tw = ((long long)time(NULL) + 11644473600ULL) * 10000000ULL; /* Calculate the response len */ *ntresp_len = NTLM_HMAC_MD5_LEN + NTLMv2_BLOB_LEN; /* Allocate the response */ *ntresp = malloc(*ntresp_len); if(!*ntresp) return CURLE_OUT_OF_MEMORY; ptr = *ntresp; memset(ptr, 0, *ntresp_len); /* Create the BLOB structure */ snprintf((char *)ptr + NTLM_HMAC_MD5_LEN, NTLMv2_BLOB_LEN, NTLMv2_BLOB_SIGNATURE "%c%c%c%c", /* Reserved = 0 */ 0, 0, 0, 0); memcpy(ptr + 24, &tw, 8); /*Re-Write this line for Big Endian*/ memcpy(ptr + 32, challenge_client, 8); memcpy(ptr + 44, ntlm->target_info, ntlm->target_info_len); /* Concatenate the Type 2 challenge with the BLOB and do HMAC MD5 */ memcpy(ptr + 8, &ntlm->nonce[0], 8); res = Curl_hmac_md5(ntlmv2hash, NTLM_HMAC_MD5_LEN, ptr + 8, NTLMv2_BLOB_LEN + 8, hmac_output); if(res) { Curl_safefree(*ntresp); *ntresp_len = 0; return res; } /* Concatenate the HMAC MD5 output with the BLOB */ memcpy(ptr, hmac_output, NTLM_HMAC_MD5_LEN); return res; } /* * Curl_ntlm_core_mk_lmv2_resp() * * This creates the LMv2 response as used in the ntlm type-3 message. * * Parameters: * * ntlmv2hash [in] - The ntlmv2 hash (16 bytes) * challenge_client [in] - The client nonce (8 bytes) * challenge_client [in] - The server challenge (8 bytes) * lmresp [out] - The LMv2 response (24 bytes) * * Returns CURLE_OK on success. */ CURLcode Curl_ntlm_core_mk_lmv2_resp(unsigned char *ntlmv2hash, unsigned char *challenge_client, unsigned char *challenge_server, unsigned char *lmresp) { unsigned char data[16]; unsigned char hmac_output[16]; CURLcode res = CURLE_OK; memcpy(&data[0], challenge_server, 8); memcpy(&data[8], challenge_client, 8); res = Curl_hmac_md5(ntlmv2hash, 16, &data[0], 16, hmac_output); if(res) return res; /* Concatenate the HMAC MD5 output with the client nonce */ memcpy(lmresp, hmac_output, 16); memcpy(lmresp+16, challenge_client, 8); return res; } #endif /* USE_NTRESPONSES */ #endif /* USE_NTLM && !USE_WINDOWS_SSPI */ lib/curl_ntlm_core.h +22 −1 Original line number Diff line number Diff line Loading @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms Loading Loading @@ -58,9 +58,30 @@ void 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 */); CURLcode Curl_ntlm_core_mk_ntlmv2_hash(const char *user, size_t userlen, const char *domain, size_t domlen, unsigned char *ntlmhash, unsigned char *ntlmv2hash); CURLcode Curl_ntlm_core_mk_ntlmv2_resp(unsigned char *ntlmv2hash, unsigned char *challenge_client, struct ntlmdata *ntlm, unsigned char **ntresp, unsigned int *ntresp_len); CURLcode Curl_ntlm_core_mk_lmv2_resp(unsigned char *ntlmv2hash, unsigned char *challenge_client, unsigned char *challenge_server, unsigned char *lmresp); #endif #endif /* USE_NTLM && !USE_WINDOWS_SSPI */ Loading lib/curl_ntlm_msgs.c +126 −13 Original line number Diff line number Diff line Loading @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms Loading Loading @@ -158,6 +158,68 @@ static unsigned int readint_le(unsigned char *buf) return ((unsigned int)buf[0]) | ((unsigned int)buf[1] << 8) | ((unsigned int)buf[2] << 16) | ((unsigned int)buf[3] << 24); } /* * This function converts from the little endian format used in the incoming * package to whatever endian format we're using natively. Argument is a * pointer to a 2 byte buffer. */ static unsigned int readshort_le(unsigned char *buf) { return ((unsigned int)buf[0]) | ((unsigned int)buf[1] << 8); } /* * Curl_ntlm_decode_type2_target() * * This is used to decode the "target info" in the ntlm type-2 message * received. * * Parameters: * * data [in] - Pointer to the session handle * buffer [in] - The decoded base64 ntlm header of Type 2 * size [in] - The input buffer size, atleast 32 bytes * ntlm [in] - Pointer to ntlm data struct being used and modified. * * Returns CURLE_OK on success. */ CURLcode Curl_ntlm_decode_type2_target(struct SessionHandle *data, unsigned char *buffer, size_t size, struct ntlmdata *ntlm) { unsigned int target_info_len = 0; unsigned int target_info_offset = 0; Curl_safefree(ntlm->target_info); ntlm->target_info_len = 0; if(size >= 48) { target_info_len = readshort_le(&buffer[40]); target_info_offset = readint_le(&buffer[44]); if(target_info_len > 0) { if(((target_info_offset + target_info_len) > size) || (target_info_offset < 48)) { infof(data, "NTLM handshake failure (bad type-2 message). " "Target Info Offset Len is set incorrect by the peer\n"); return CURLE_REMOTE_ACCESS_DENIED; } ntlm->target_info = malloc(target_info_len); if(!ntlm->target_info) return CURLE_OUT_OF_MEMORY; memcpy(ntlm->target_info, &buffer[target_info_offset], target_info_len); ntlm->target_info_len = target_info_len; } } return CURLE_OK; } #endif /* Loading Loading @@ -257,6 +319,15 @@ CURLcode Curl_ntlm_decode_type2_message(struct SessionHandle *data, ntlm->flags = readint_le(&buffer[20]); memcpy(ntlm->nonce, &buffer[24], 8); if(ntlm->flags & NTLMFLAG_NEGOTIATE_TARGET_INFO) { error = Curl_ntlm_decode_type2_target(data, buffer, size, ntlm); if(error) { free(buffer); infof(data, "NTLM handshake failure (bad type-2 message)\n"); return error; } } DEBUG_OUT({ fprintf(stderr, "**** TYPE2 header flags=0x%08.8lx ", ntlm->flags); ntlm_print_flags(stderr, ntlm->flags); Loading Loading @@ -645,7 +716,10 @@ CURLcode Curl_ntlm_create_type3_message(struct SessionHandle *data, unsigned char lmresp[24]; /* fixed-size */ #if USE_NTRESPONSES int ntrespoff; unsigned int ntresplen = 24; unsigned char ntresp[24]; /* fixed-size */ unsigned char *ptr_ntresp = &ntresp[0]; unsigned char *ntlmv2resp = NULL; #endif bool unicode = (ntlm->flags & NTLMFLAG_NEGOTIATE_UNICODE) ? TRUE : FALSE; char host[HOSTNAME_MAX + 1] = ""; Loading @@ -657,7 +731,7 @@ CURLcode Curl_ntlm_create_type3_message(struct SessionHandle *data, size_t hostlen = 0; size_t userlen = 0; size_t domlen = 0; CURLcode res; CURLcode res = CURLE_OK; user = strchr(userp, '\\'); if(!user) Loading @@ -684,11 +758,40 @@ CURLcode Curl_ntlm_create_type3_message(struct SessionHandle *data, hostlen = strlen(host); } if(unicode) { domlen = domlen * 2; userlen = userlen * 2; hostlen = hostlen * 2; #if USE_NTRESPONSES if(ntlm->target_info_len) { unsigned char ntbuffer[0x18]; unsigned char entropy[8]; unsigned char ntlmv2hash[0x18]; /* Need to create 8 bytes random client nonce */ Curl_ssl_random(data, entropy, sizeof(entropy)); res = Curl_ntlm_core_mk_nt_hash(data, passwdp, ntbuffer); if(res) return res; res = Curl_ntlm_core_mk_ntlmv2_hash(user, userlen, domain, domlen, ntbuffer, ntlmv2hash); if(res) return res; /* LMv2 response */ res = Curl_ntlm_core_mk_lmv2_resp(ntlmv2hash, entropy, &ntlm->nonce[0], lmresp); if(res) return res; /* NTLMv2 response */ res = Curl_ntlm_core_mk_ntlmv2_resp(ntlmv2hash, entropy, ntlm, &ntlmv2resp, &ntresplen); if(res) return res; ptr_ntresp = ntlmv2resp; } else #endif #if USE_NTLM2SESSION /* We don't support NTLM2 if we don't have USE_NTRESPONSES */ Loading Loading @@ -718,9 +821,11 @@ CURLcode Curl_ntlm_create_type3_message(struct SessionHandle *data, if(CURLE_OUT_OF_MEMORY == Curl_ntlm_core_mk_nt_hash(data, passwdp, ntbuffer)) return CURLE_OUT_OF_MEMORY; Curl_ntlm_core_lm_resp(ntbuffer, md5sum, ntresp); /* End of NTLM2 Session code */ } else #endif Loading @@ -745,10 +850,16 @@ CURLcode Curl_ntlm_create_type3_message(struct SessionHandle *data, * See http://davenport.sourceforge.net/ntlm.html#ntlmVersion2 */ } if(unicode) { domlen = domlen * 2; userlen = userlen * 2; hostlen = hostlen * 2; } lmrespoff = 64; /* size of the message header */ #if USE_NTRESPONSES ntrespoff = lmrespoff + 0x18; domoff = ntrespoff + 0x18; domoff = ntrespoff + ntresplen; #else domoff = lmrespoff + 0x18; #endif Loading Loading @@ -807,8 +918,8 @@ CURLcode Curl_ntlm_create_type3_message(struct SessionHandle *data, 0x0, 0x0, #if USE_NTRESPONSES SHORTPAIR(0x18), /* NT-response length, twice */ SHORTPAIR(0x18), SHORTPAIR(ntresplen), /* NT-response length, twice */ SHORTPAIR(ntresplen), SHORTPAIR(ntrespoff), 0x0, 0x0, #else Loading Loading @@ -854,17 +965,19 @@ CURLcode Curl_ntlm_create_type3_message(struct SessionHandle *data, }); #if USE_NTRESPONSES if(size < (NTLM_BUFSIZE - 0x18)) { if(size < (NTLM_BUFSIZE - ntresplen)) { DEBUGASSERT(size == (size_t)ntrespoff); memcpy(&ntlmbuf[size], ntresp, 0x18); size += 0x18; memcpy(&ntlmbuf[size], ptr_ntresp, ntresplen); size += ntresplen; } DEBUG_OUT({ fprintf(stderr, "\n ntresp="); ntlm_print_hex(stderr, (char *)&ntlmbuf[ntrespoff], 0x18); ntlm_print_hex(stderr, (char *)&ntlmbuf[ntrespoff], ntresplen); }); Curl_safefree(ntlmv2resp);/* Free the dynamic buffer allocated for NTLMv2 */ #endif DEBUG_OUT({ Loading lib/curl_ntlm_msgs.h +8 −1 Original line number Diff line number Diff line Loading @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms Loading Loading @@ -46,6 +46,13 @@ CURLcode Curl_ntlm_decode_type2_message(struct SessionHandle *data, const char* header, struct ntlmdata* ntlm); /* This is to decode target info received in NTLM type-2 message */ CURLcode Curl_ntlm_decode_type2_target(struct SessionHandle *data, unsigned char* buffer, size_t size, struct ntlmdata* ntlm); /* This is to clean up the ntlm data structure */ #ifdef USE_WINDOWS_SSPI void Curl_ntlm_sspi_cleanup(struct ntlmdata *ntlm); Loading Loading
lib/curl_ntlm.c +6 −0 Original line number Diff line number Diff line Loading @@ -235,6 +235,12 @@ void Curl_http_ntlm_cleanup(struct connectdata *conn) #else (void)conn; #endif #ifndef USE_WINDOWS_SSPI Curl_safefree(conn->ntlm.target_info); conn->ntlm.target_info_len = 0; #endif } #endif /* USE_NTLM */
lib/curl_ntlm_core.c +185 −1 Original line number Diff line number Diff line Loading @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms Loading Loading @@ -96,6 +96,9 @@ #include "rawstr.h" #include "curl_memory.h" #include "curl_ntlm_core.h" #include "curl_md5.h" #include "curl_hmac.h" #include "warnless.h" #define _MPRINTF_REPLACE /* use our functions only */ #include <curl/mprintf.h> Loading @@ -103,6 +106,10 @@ /* The last #include file should be: */ #include "memdebug.h" #define NTLM_HMAC_MD5_LEN (16) #define NTLMv2_BLOB_SIGNATURE "\x01\x01\x00\x00" #define NTLMv2_BLOB_LEN (44 -16 + ntlm->target_info_len + 4) #ifdef USE_SSLEAY /* * Turns a 56 bit key into the 64 bit, odd parity key and sets the key. The Loading Loading @@ -377,6 +384,16 @@ static void ascii_to_unicode_le(unsigned char *dest, const char *src, } } static void ascii_uppercase_to_unicode_le(unsigned char *dest, const char *src, size_t srclen) { size_t i; for(i = 0; i < srclen; i++) { dest[2 * i] = (unsigned char)(toupper(src[i])); dest[2 * i + 1] = '\0'; } } /* * Set up nt hashed passwords */ Loading Loading @@ -431,6 +448,173 @@ CURLcode Curl_ntlm_core_mk_nt_hash(struct SessionHandle *data, return CURLE_OK; } /* This returns the HMAC MD5 digest */ CURLcode Curl_hmac_md5(const unsigned char *key, unsigned int keylen, const unsigned char *data, unsigned int datalen, unsigned char *output) { HMAC_context *ctxt = Curl_HMAC_init(Curl_HMAC_MD5, key, keylen); if(!ctxt) return CURLE_OUT_OF_MEMORY; /* Update the digest with the given challenge */ Curl_HMAC_update(ctxt, data, datalen); /* Finalise the digest */ Curl_HMAC_final(ctxt, output); return CURLE_OK; } /* This creates the NTLMv2 hash by using NTLM hash as the key and Unicode * (uppercase UserName + Domain) as the data */ CURLcode Curl_ntlm_core_mk_ntlmv2_hash(const char *user, size_t userlen, const char *domain, size_t domlen, unsigned char *ntlmhash, unsigned char *ntlmv2hash) { /* Unicode representation */ size_t identity_len = (userlen + domlen) * 2; unsigned char *identity = malloc(identity_len); CURLcode res = CURLE_OK; if(!identity) return CURLE_OUT_OF_MEMORY; ascii_uppercase_to_unicode_le(identity, user, userlen); ascii_to_unicode_le(identity + (userlen << 1), domain, domlen); res = Curl_hmac_md5(ntlmhash, 16, identity, curlx_uztoui(identity_len), ntlmv2hash); Curl_safefree(identity); return res; } /* * Curl_ntlm_core_mk_ntlmv2_resp() * * This creates the NTLMv2 response as set in the ntlm type-3 message. * * Parameters: * * ntlmv2hash [in] - The ntlmv2 hash (16 bytes) * challenge_client [in] - The client nonce (8 bytes) * ntlm [in] - The ntlm data struct being used to read TargetInfo and Server challenge received in the type-2 message * ntresp [out] - The address where a pointer to newly allocated * memory holding the NTLMv2 response. * ntresp_len [out] - The length of the output message. * * Returns CURLE_OK on success. */ CURLcode Curl_ntlm_core_mk_ntlmv2_resp(unsigned char *ntlmv2hash, unsigned char *challenge_client, struct ntlmdata *ntlm, unsigned char **ntresp, unsigned int *ntresp_len) { /* NTLMv2 response structure : ------------------------------------------------------------------------------ 0 HMAC MD5 16 bytes ------BLOB-------------------------------------------------------------------- 16 Signature 0x01010000 20 Reserved long (0x00000000) 24 Timestamp LE, 64-bit signed value representing the number of tenths of a microsecond since January 1, 1601. 32 Client Nonce 8 bytes 40 Unknown 4 bytes 44 Target Info N bytes (from the type-2 message) 44+N Unknown 4 bytes ------------------------------------------------------------------------------ */ unsigned char *ptr = NULL; unsigned char hmac_output[NTLM_HMAC_MD5_LEN]; long long tw; CURLcode res = CURLE_OK; /* Calculate the timestamp */ tw = ((long long)time(NULL) + 11644473600ULL) * 10000000ULL; /* Calculate the response len */ *ntresp_len = NTLM_HMAC_MD5_LEN + NTLMv2_BLOB_LEN; /* Allocate the response */ *ntresp = malloc(*ntresp_len); if(!*ntresp) return CURLE_OUT_OF_MEMORY; ptr = *ntresp; memset(ptr, 0, *ntresp_len); /* Create the BLOB structure */ snprintf((char *)ptr + NTLM_HMAC_MD5_LEN, NTLMv2_BLOB_LEN, NTLMv2_BLOB_SIGNATURE "%c%c%c%c", /* Reserved = 0 */ 0, 0, 0, 0); memcpy(ptr + 24, &tw, 8); /*Re-Write this line for Big Endian*/ memcpy(ptr + 32, challenge_client, 8); memcpy(ptr + 44, ntlm->target_info, ntlm->target_info_len); /* Concatenate the Type 2 challenge with the BLOB and do HMAC MD5 */ memcpy(ptr + 8, &ntlm->nonce[0], 8); res = Curl_hmac_md5(ntlmv2hash, NTLM_HMAC_MD5_LEN, ptr + 8, NTLMv2_BLOB_LEN + 8, hmac_output); if(res) { Curl_safefree(*ntresp); *ntresp_len = 0; return res; } /* Concatenate the HMAC MD5 output with the BLOB */ memcpy(ptr, hmac_output, NTLM_HMAC_MD5_LEN); return res; } /* * Curl_ntlm_core_mk_lmv2_resp() * * This creates the LMv2 response as used in the ntlm type-3 message. * * Parameters: * * ntlmv2hash [in] - The ntlmv2 hash (16 bytes) * challenge_client [in] - The client nonce (8 bytes) * challenge_client [in] - The server challenge (8 bytes) * lmresp [out] - The LMv2 response (24 bytes) * * Returns CURLE_OK on success. */ CURLcode Curl_ntlm_core_mk_lmv2_resp(unsigned char *ntlmv2hash, unsigned char *challenge_client, unsigned char *challenge_server, unsigned char *lmresp) { unsigned char data[16]; unsigned char hmac_output[16]; CURLcode res = CURLE_OK; memcpy(&data[0], challenge_server, 8); memcpy(&data[8], challenge_client, 8); res = Curl_hmac_md5(ntlmv2hash, 16, &data[0], 16, hmac_output); if(res) return res; /* Concatenate the HMAC MD5 output with the client nonce */ memcpy(lmresp, hmac_output, 16); memcpy(lmresp+16, challenge_client, 8); return res; } #endif /* USE_NTRESPONSES */ #endif /* USE_NTLM && !USE_WINDOWS_SSPI */
lib/curl_ntlm_core.h +22 −1 Original line number Diff line number Diff line Loading @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * * Copyright (C) 1998 - 2011, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms Loading Loading @@ -58,9 +58,30 @@ void 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 */); CURLcode Curl_ntlm_core_mk_ntlmv2_hash(const char *user, size_t userlen, const char *domain, size_t domlen, unsigned char *ntlmhash, unsigned char *ntlmv2hash); CURLcode Curl_ntlm_core_mk_ntlmv2_resp(unsigned char *ntlmv2hash, unsigned char *challenge_client, struct ntlmdata *ntlm, unsigned char **ntresp, unsigned int *ntresp_len); CURLcode Curl_ntlm_core_mk_lmv2_resp(unsigned char *ntlmv2hash, unsigned char *challenge_client, unsigned char *challenge_server, unsigned char *lmresp); #endif #endif /* USE_NTLM && !USE_WINDOWS_SSPI */ Loading
lib/curl_ntlm_msgs.c +126 −13 Original line number Diff line number Diff line Loading @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms Loading Loading @@ -158,6 +158,68 @@ static unsigned int readint_le(unsigned char *buf) return ((unsigned int)buf[0]) | ((unsigned int)buf[1] << 8) | ((unsigned int)buf[2] << 16) | ((unsigned int)buf[3] << 24); } /* * This function converts from the little endian format used in the incoming * package to whatever endian format we're using natively. Argument is a * pointer to a 2 byte buffer. */ static unsigned int readshort_le(unsigned char *buf) { return ((unsigned int)buf[0]) | ((unsigned int)buf[1] << 8); } /* * Curl_ntlm_decode_type2_target() * * This is used to decode the "target info" in the ntlm type-2 message * received. * * Parameters: * * data [in] - Pointer to the session handle * buffer [in] - The decoded base64 ntlm header of Type 2 * size [in] - The input buffer size, atleast 32 bytes * ntlm [in] - Pointer to ntlm data struct being used and modified. * * Returns CURLE_OK on success. */ CURLcode Curl_ntlm_decode_type2_target(struct SessionHandle *data, unsigned char *buffer, size_t size, struct ntlmdata *ntlm) { unsigned int target_info_len = 0; unsigned int target_info_offset = 0; Curl_safefree(ntlm->target_info); ntlm->target_info_len = 0; if(size >= 48) { target_info_len = readshort_le(&buffer[40]); target_info_offset = readint_le(&buffer[44]); if(target_info_len > 0) { if(((target_info_offset + target_info_len) > size) || (target_info_offset < 48)) { infof(data, "NTLM handshake failure (bad type-2 message). " "Target Info Offset Len is set incorrect by the peer\n"); return CURLE_REMOTE_ACCESS_DENIED; } ntlm->target_info = malloc(target_info_len); if(!ntlm->target_info) return CURLE_OUT_OF_MEMORY; memcpy(ntlm->target_info, &buffer[target_info_offset], target_info_len); ntlm->target_info_len = target_info_len; } } return CURLE_OK; } #endif /* Loading Loading @@ -257,6 +319,15 @@ CURLcode Curl_ntlm_decode_type2_message(struct SessionHandle *data, ntlm->flags = readint_le(&buffer[20]); memcpy(ntlm->nonce, &buffer[24], 8); if(ntlm->flags & NTLMFLAG_NEGOTIATE_TARGET_INFO) { error = Curl_ntlm_decode_type2_target(data, buffer, size, ntlm); if(error) { free(buffer); infof(data, "NTLM handshake failure (bad type-2 message)\n"); return error; } } DEBUG_OUT({ fprintf(stderr, "**** TYPE2 header flags=0x%08.8lx ", ntlm->flags); ntlm_print_flags(stderr, ntlm->flags); Loading Loading @@ -645,7 +716,10 @@ CURLcode Curl_ntlm_create_type3_message(struct SessionHandle *data, unsigned char lmresp[24]; /* fixed-size */ #if USE_NTRESPONSES int ntrespoff; unsigned int ntresplen = 24; unsigned char ntresp[24]; /* fixed-size */ unsigned char *ptr_ntresp = &ntresp[0]; unsigned char *ntlmv2resp = NULL; #endif bool unicode = (ntlm->flags & NTLMFLAG_NEGOTIATE_UNICODE) ? TRUE : FALSE; char host[HOSTNAME_MAX + 1] = ""; Loading @@ -657,7 +731,7 @@ CURLcode Curl_ntlm_create_type3_message(struct SessionHandle *data, size_t hostlen = 0; size_t userlen = 0; size_t domlen = 0; CURLcode res; CURLcode res = CURLE_OK; user = strchr(userp, '\\'); if(!user) Loading @@ -684,11 +758,40 @@ CURLcode Curl_ntlm_create_type3_message(struct SessionHandle *data, hostlen = strlen(host); } if(unicode) { domlen = domlen * 2; userlen = userlen * 2; hostlen = hostlen * 2; #if USE_NTRESPONSES if(ntlm->target_info_len) { unsigned char ntbuffer[0x18]; unsigned char entropy[8]; unsigned char ntlmv2hash[0x18]; /* Need to create 8 bytes random client nonce */ Curl_ssl_random(data, entropy, sizeof(entropy)); res = Curl_ntlm_core_mk_nt_hash(data, passwdp, ntbuffer); if(res) return res; res = Curl_ntlm_core_mk_ntlmv2_hash(user, userlen, domain, domlen, ntbuffer, ntlmv2hash); if(res) return res; /* LMv2 response */ res = Curl_ntlm_core_mk_lmv2_resp(ntlmv2hash, entropy, &ntlm->nonce[0], lmresp); if(res) return res; /* NTLMv2 response */ res = Curl_ntlm_core_mk_ntlmv2_resp(ntlmv2hash, entropy, ntlm, &ntlmv2resp, &ntresplen); if(res) return res; ptr_ntresp = ntlmv2resp; } else #endif #if USE_NTLM2SESSION /* We don't support NTLM2 if we don't have USE_NTRESPONSES */ Loading Loading @@ -718,9 +821,11 @@ CURLcode Curl_ntlm_create_type3_message(struct SessionHandle *data, if(CURLE_OUT_OF_MEMORY == Curl_ntlm_core_mk_nt_hash(data, passwdp, ntbuffer)) return CURLE_OUT_OF_MEMORY; Curl_ntlm_core_lm_resp(ntbuffer, md5sum, ntresp); /* End of NTLM2 Session code */ } else #endif Loading @@ -745,10 +850,16 @@ CURLcode Curl_ntlm_create_type3_message(struct SessionHandle *data, * See http://davenport.sourceforge.net/ntlm.html#ntlmVersion2 */ } if(unicode) { domlen = domlen * 2; userlen = userlen * 2; hostlen = hostlen * 2; } lmrespoff = 64; /* size of the message header */ #if USE_NTRESPONSES ntrespoff = lmrespoff + 0x18; domoff = ntrespoff + 0x18; domoff = ntrespoff + ntresplen; #else domoff = lmrespoff + 0x18; #endif Loading Loading @@ -807,8 +918,8 @@ CURLcode Curl_ntlm_create_type3_message(struct SessionHandle *data, 0x0, 0x0, #if USE_NTRESPONSES SHORTPAIR(0x18), /* NT-response length, twice */ SHORTPAIR(0x18), SHORTPAIR(ntresplen), /* NT-response length, twice */ SHORTPAIR(ntresplen), SHORTPAIR(ntrespoff), 0x0, 0x0, #else Loading Loading @@ -854,17 +965,19 @@ CURLcode Curl_ntlm_create_type3_message(struct SessionHandle *data, }); #if USE_NTRESPONSES if(size < (NTLM_BUFSIZE - 0x18)) { if(size < (NTLM_BUFSIZE - ntresplen)) { DEBUGASSERT(size == (size_t)ntrespoff); memcpy(&ntlmbuf[size], ntresp, 0x18); size += 0x18; memcpy(&ntlmbuf[size], ptr_ntresp, ntresplen); size += ntresplen; } DEBUG_OUT({ fprintf(stderr, "\n ntresp="); ntlm_print_hex(stderr, (char *)&ntlmbuf[ntrespoff], 0x18); ntlm_print_hex(stderr, (char *)&ntlmbuf[ntrespoff], ntresplen); }); Curl_safefree(ntlmv2resp);/* Free the dynamic buffer allocated for NTLMv2 */ #endif DEBUG_OUT({ Loading
lib/curl_ntlm_msgs.h +8 −1 Original line number Diff line number Diff line Loading @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms Loading Loading @@ -46,6 +46,13 @@ CURLcode Curl_ntlm_decode_type2_message(struct SessionHandle *data, const char* header, struct ntlmdata* ntlm); /* This is to decode target info received in NTLM type-2 message */ CURLcode Curl_ntlm_decode_type2_target(struct SessionHandle *data, unsigned char* buffer, size_t size, struct ntlmdata* ntlm); /* This is to clean up the ntlm data structure */ #ifdef USE_WINDOWS_SSPI void Curl_ntlm_sspi_cleanup(struct ntlmdata *ntlm); Loading