/* * Curl_auth_decode_ntlm_type2_message() * * This is used to decode an already encoded NTLM type-2 message. 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] - The session handle. * type2msg [in] - The base64 encoded type-2 message. * ntlm [in/out] - The NTLM data struct being used and modified. * * Returns CURLE_OK on success. */ CURLcode Curl_auth_decode_ntlm_type2_message(struct Curl_easy *data, const char *type2msg, struct ntlmdata *ntlm) { static const char type2_marker[] = { 0x02, 0x00, 0x00, 0x00 }; /* 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 */ CURLcode result = CURLE_OK; unsigned char *type2 = NULL; size_t type2_len = 0; #if defined(NTLM_NEEDS_NSS_INIT) /* Make sure the crypto backend is initialized */ result = Curl_nss_force_init(data); if(result) return result; #elif defined(CURL_DISABLE_VERBOSE_STRINGS) (void)data; #endif /* Decode the base-64 encoded type-2 message */ if(strlen(type2msg) && *type2msg != '=') { result = Curl_base64_decode(type2msg, &type2, &type2_len); if(result) return result; } /* Ensure we have a valid type-2 message */ if(!type2) { infof(data, "NTLM handshake failure (empty type-2 message)\n"); return CURLE_BAD_CONTENT_ENCODING; } ntlm->flags = 0; if((type2_len < 32) || (memcmp(type2, NTLMSSP_SIGNATURE, 8) != 0) || (memcmp(type2 + 8, type2_marker, sizeof(type2_marker)) != 0)) { /* This was not a good enough type-2 message */ free(type2); infof(data, "NTLM handshake failure (bad type-2 message)\n"); return CURLE_BAD_CONTENT_ENCODING; } ntlm->flags = Curl_read32_le(&type2[20]); memcpy(ntlm->nonce, &type2[24], 8); if(ntlm->flags & NTLMFLAG_NEGOTIATE_TARGET_INFO) { result = ntlm_decode_type2_target(data, type2, type2_len, ntlm); if(result) { free(type2); infof(data, "NTLM handshake failure (bad type-2 message)\n"); return result; } } 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); });
/* * 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); });