/* * 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; }
CURLntlm Curl_input_ntlm(struct connectdata *conn, bool proxy, /* if proxy or not */ const char *header) /* rest of the www-authenticate: header */ { /* point to the correct struct with this */ struct ntlmdata *ntlm; #ifndef USE_WINDOWS_SSPI static const char type2_marker[] = { 0x02, 0x00, 0x00, 0x00 }; #endif ntlm = proxy?&conn->proxyntlm:&conn->ntlm; /* skip initial whitespaces */ while(*header && ISSPACE(*header)) header++; if(checkprefix("NTLM", header)) { header += strlen("NTLM"); while(*header && ISSPACE(*header)) header++; if(*header) { /* We got a type-2 message here: Index Description Content 0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP" (0x4e544c4d53535000) 8 NTLM Message Type long (0x02000000) 12 Target Name security buffer(*) 20 Flags long 24 Challenge 8 bytes (32) Context (optional) 8 bytes (two consecutive longs) (40) Target Information (optional) security buffer(*) 32 (48) start of data block */ size_t size; unsigned char *buffer; size = Curl_base64_decode(header, &buffer); if(!buffer) return CURLNTLM_BAD; ntlm->state = NTLMSTATE_TYPE2; /* we got a type-2 */ #ifdef USE_WINDOWS_SSPI ntlm->type_2 = malloc(size+1); if(ntlm->type_2 == NULL) { free(buffer); return CURLE_OUT_OF_MEMORY; } ntlm->n_type_2 = size; memcpy(ntlm->type_2, buffer, size); #else ntlm->flags = 0; if((size < 32) || (memcmp(buffer, NTLMSSP_SIGNATURE, 8) != 0) || (memcmp(buffer+8, type2_marker, sizeof(type2_marker)) != 0)) { /* This was not a good enough type-2 message */ free(buffer); return CURLNTLM_BAD; } ntlm->flags = readint_le(&buffer[20]); memcpy(ntlm->nonce, &buffer[24], 8); DEBUG_OUT({ fprintf(stderr, "**** TYPE2 header flags=0x%08.8lx ", ntlm->flags); print_flags(stderr, ntlm->flags); fprintf(stderr, "\n nonce="); print_hex(stderr, (char *)ntlm->nonce, 8); fprintf(stderr, "\n****\n"); fprintf(stderr, "**** Header %s\n ", header); }); #endif free(buffer); }
/* * Curl_ntlm_decode_type2_message() * * This is used to decode a ntlm type-2 message received from a: HTTP, SMTP * or POP3 server. The message is first decoded from a base64 string into a * raw ntlm message and checked for validity before the appropriate data for * creating a type-3 message is written to the given ntlm data structure. * * Parameters: * * data [in] - Pointer to session handle. * header [in] - Pointer to the input buffer. * ntlm [in] - Pointer to ntlm data struct being used and modified. * * Returns CURLE_OK on success. */ CURLcode Curl_ntlm_decode_type2_message(struct SessionHandle *data, const char* header, struct ntlmdata* ntlm) { #ifndef USE_WINDOWS_SSPI static const char type2_marker[] = { 0x02, 0x00, 0x00, 0x00 }; #endif /* NTLM type-2 message structure: Index Description Content 0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP" (0x4e544c4d53535000) 8 NTLM Message Type long (0x02000000) 12 Target Name security buffer 20 Flags long 24 Challenge 8 bytes (32) Context 8 bytes (two consecutive longs) (*) (40) Target Information security buffer (*) (48) OS Version Structure 8 bytes (*) 32 (48) (56) Start of data block (*) (*) -> Optional */ size_t size = 0; unsigned char *buffer = NULL; CURLcode error; #if defined(CURL_DISABLE_VERBOSE_STRINGS) || defined(USE_WINDOWS_SSPI) (void)data; #endif error = Curl_base64_decode(header, &buffer, &size); if(error) return error; if(!buffer) { infof(data, "NTLM handshake failure (unhandled condition)\n"); return CURLE_REMOTE_ACCESS_DENIED; } #ifdef USE_WINDOWS_SSPI ntlm->type_2 = malloc(size + 1); if(ntlm->type_2 == NULL) { free(buffer); return CURLE_OUT_OF_MEMORY; } ntlm->n_type_2 = (unsigned long)size; memcpy(ntlm->type_2, buffer, size); #else ntlm->flags = 0; if((size < 32) || (memcmp(buffer, NTLMSSP_SIGNATURE, 8) != 0) || (memcmp(buffer + 8, type2_marker, sizeof(type2_marker)) != 0)) { /* This was not a good enough type-2 message */ free(buffer); infof(data, "NTLM handshake failure (bad type-2 message)\n"); return CURLE_REMOTE_ACCESS_DENIED; } ntlm->flags = readint_le(&buffer[20]); memcpy(ntlm->nonce, &buffer[24], 8); DEBUG_OUT({ fprintf(stderr, "**** TYPE2 header flags=0x%08.8lx ", ntlm->flags); ntlm_print_flags(stderr, ntlm->flags); fprintf(stderr, "\n nonce="); ntlm_print_hex(stderr, (char *)ntlm->nonce, 8); fprintf(stderr, "\n****\n"); fprintf(stderr, "**** Header %s\n ", header); });