int ntlm_compute_lm_v2_response(NTLM_CONTEXT* context) { BYTE* response; BYTE value[WINPR_MD5_DIGEST_LENGTH]; if (context->LmCompatibilityLevel < 2) { if (!sspi_SecBufferAlloc(&context->LmChallengeResponse, 24)) return -1; ZeroMemory(context->LmChallengeResponse.pvBuffer, 24); return 1; } /* Compute the NTLMv2 hash */ if (ntlm_compute_ntlm_v2_hash(context, context->NtlmV2Hash) < 0) return -1; /* Concatenate the server and client challenges */ CopyMemory(value, context->ServerChallenge, 8); CopyMemory(&value[8], context->ClientChallenge, 8); if (!sspi_SecBufferAlloc(&context->LmChallengeResponse, 24)) return -1; response = (BYTE*) context->LmChallengeResponse.pvBuffer; /* Compute the HMAC-MD5 hash of the resulting value using the NTLMv2 hash as the key */ winpr_HMAC(WINPR_MD_MD5, (void*) context->NtlmV2Hash, WINPR_MD5_DIGEST_LENGTH, (BYTE*) value, WINPR_MD5_DIGEST_LENGTH, (BYTE*) response, WINPR_MD5_DIGEST_LENGTH); /* Concatenate the resulting HMAC-MD5 hash and the client challenge, giving us the LMv2 response (24 bytes) */ CopyMemory(&response[16], context->ClientChallenge, 8); return 1; }
void ntlm_compute_lm_v2_response(NTLM_CONTEXT* context) { char* response; char value[16]; char ntlm_v2_hash[16]; if (context->LmCompatibilityLevel < 2) { sspi_SecBufferAlloc(&context->LmChallengeResponse, 24); ZeroMemory(context->LmChallengeResponse.pvBuffer, 24); return; } /* Compute the NTLMv2 hash */ ntlm_compute_ntlm_v2_hash(context, ntlm_v2_hash); /* Concatenate the server and client challenges */ CopyMemory(value, context->ServerChallenge, 8); CopyMemory(&value[8], context->ClientChallenge, 8); sspi_SecBufferAlloc(&context->LmChallengeResponse, 24); response = (char*) context->LmChallengeResponse.pvBuffer; /* Compute the HMAC-MD5 hash of the resulting value using the NTLMv2 hash as the key */ HMAC(EVP_md5(), (void*) ntlm_v2_hash, 16, (void*) value, 16, (void*) response, NULL); /* Concatenate the resulting HMAC-MD5 hash and the client challenge, giving us the LMv2 response (24 bytes) */ CopyMemory(&response[16], context->ClientChallenge, 8); }
int credssp_recv(rdpCredssp* credssp) { STREAM* s; int length; int status; uint32 version; s = stream_new(2048); status = tls_read(credssp->tls, s->data, stream_get_left(s)); if (status < 0) return -1; /* TSRequest */ ber_read_sequence_tag(s, &length); ber_read_contextual_tag(s, 0, &length, true); ber_read_integer(s, &version); /* [1] negoTokens (NegoData) */ if (ber_read_contextual_tag(s, 1, &length, true) != false) { ber_read_sequence_tag(s, &length); /* SEQUENCE OF NegoDataItem */ ber_read_sequence_tag(s, &length); /* NegoDataItem */ ber_read_contextual_tag(s, 0, &length, true); /* [0] negoToken */ ber_read_octet_string(s, &length); /* OCTET STRING */ sspi_SecBufferAlloc(&credssp->negoToken, length); stream_read(s, credssp->negoToken.pvBuffer, length); credssp->negoToken.cbBuffer = length; } /* [2] authInfo (OCTET STRING) */ if (ber_read_contextual_tag(s, 2, &length, true) != false) { ber_read_octet_string(s, &length); /* OCTET STRING */ sspi_SecBufferAlloc(&credssp->authInfo, length); stream_read(s, credssp->authInfo.pvBuffer, length); credssp->authInfo.cbBuffer = length; } /* [3] pubKeyAuth (OCTET STRING) */ if (ber_read_contextual_tag(s, 3, &length, true) != false) { ber_read_octet_string(s, &length); /* OCTET STRING */ sspi_SecBufferAlloc(&credssp->pubKeyAuth, length); stream_read(s, credssp->pubKeyAuth.pvBuffer, length); credssp->pubKeyAuth.cbBuffer = length; } stream_free(s); return 0; }
SECURITY_STATUS credssp_encrypt_ts_credentials(rdpCredssp* credssp) { SecBuffer Buffers[2]; SecBufferDesc Message; SECURITY_STATUS status; credssp_encode_ts_credentials(credssp); Buffers[0].BufferType = SECBUFFER_TOKEN; /* Signature */ Buffers[1].BufferType = SECBUFFER_DATA; /* TSCredentials */ sspi_SecBufferAlloc(&credssp->authInfo, credssp->ContextSizes.cbMaxSignature + credssp->ts_credentials.cbBuffer); Buffers[0].cbBuffer = credssp->ContextSizes.cbMaxSignature; Buffers[0].pvBuffer = credssp->authInfo.pvBuffer; ZeroMemory(Buffers[0].pvBuffer, Buffers[0].cbBuffer); Buffers[1].cbBuffer = credssp->ts_credentials.cbBuffer; Buffers[1].pvBuffer = &((BYTE*) credssp->authInfo.pvBuffer)[Buffers[0].cbBuffer]; CopyMemory(Buffers[1].pvBuffer, credssp->ts_credentials.pvBuffer, Buffers[1].cbBuffer); Message.cBuffers = 2; Message.ulVersion = SECBUFFER_VERSION; Message.pBuffers = (PSecBuffer) &Buffers; status = credssp->table->EncryptMessage(&credssp->context, 0, &Message, credssp->send_seq_num++); if (status != SEC_E_OK) return status; return SEC_E_OK; }
void ntlm_populate_server_av_pairs(NTLM_CONTEXT* context) { int length; AV_PAIRS* av_pairs = context->av_pairs; av_pairs->NbDomainName.length = strlen(test_NbDomainName) * 2; av_pairs->NbDomainName.value = (BYTE*) malloc(av_pairs->NbDomainName.length); MultiByteToWideChar(CP_ACP, 0, test_NbDomainName, strlen(test_NbDomainName), (LPWSTR) av_pairs->NbDomainName.value, av_pairs->NbDomainName.length / 2); av_pairs->NbComputerName.length = strlen(test_NbDomainName) * 2; av_pairs->NbComputerName.value = (BYTE*) malloc(av_pairs->NbComputerName.length); MultiByteToWideChar(CP_ACP, 0, test_NbComputerName, strlen(test_NbComputerName), (LPWSTR) av_pairs->NbComputerName.value, av_pairs->NbComputerName.length / 2); av_pairs->DnsDomainName.length = strlen(test_DnsDomainName) * 2; av_pairs->DnsDomainName.value = (BYTE*) malloc(av_pairs->DnsDomainName.length); MultiByteToWideChar(CP_ACP, 0, test_DnsDomainName, strlen(test_DnsDomainName), (LPWSTR) av_pairs->DnsDomainName.value, av_pairs->DnsDomainName.length / 2); av_pairs->DnsComputerName.length = strlen(test_DnsComputerName) * 2; av_pairs->DnsComputerName.value = (BYTE*) malloc(av_pairs->DnsComputerName.length); MultiByteToWideChar(CP_ACP, 0, test_DnsComputerName, strlen(test_DnsComputerName), (LPWSTR) av_pairs->DnsComputerName.value, av_pairs->DnsComputerName.length / 2); length = ntlm_compute_av_pairs_length(context) + 4; sspi_SecBufferAlloc(&context->TargetInfo, length); ntlm_output_av_pairs(context, &context->TargetInfo); }
void ntlm_construct_challenge_target_info(NTLM_CONTEXT* context) { int length; ULONG AvPairsCount; ULONG AvPairsLength; LONG AvPairListSize; NTLM_AV_PAIR* pAvPairList; UNICODE_STRING NbDomainName; UNICODE_STRING NbComputerName; UNICODE_STRING DnsDomainName; UNICODE_STRING DnsComputerName; ntlm_get_target_computer_name(&NbDomainName, ComputerNameNetBIOS); ntlm_get_target_computer_name(&NbComputerName, ComputerNameNetBIOS); ntlm_get_target_computer_name(&DnsDomainName, ComputerNameDnsDomain); ntlm_get_target_computer_name(&DnsComputerName, ComputerNameDnsHostname); AvPairsCount = 5; AvPairsLength = NbDomainName.Length + NbComputerName.Length + DnsDomainName.Length + DnsComputerName.Length + 8; length = ntlm_av_pair_list_size(AvPairsCount, AvPairsLength); sspi_SecBufferAlloc(&context->ChallengeTargetInfo, length); pAvPairList = (NTLM_AV_PAIR*) context->ChallengeTargetInfo.pvBuffer; AvPairListSize = (ULONG) context->ChallengeTargetInfo.cbBuffer; ntlm_av_pair_list_init(pAvPairList); ntlm_av_pair_add(pAvPairList, MsvAvNbDomainName, (PBYTE) NbDomainName.Buffer, NbDomainName.Length); ntlm_av_pair_add(pAvPairList, MsvAvNbComputerName, (PBYTE) NbComputerName.Buffer, NbComputerName.Length); ntlm_av_pair_add(pAvPairList, MsvAvDnsDomainName, (PBYTE) DnsDomainName.Buffer, DnsDomainName.Length); ntlm_av_pair_add(pAvPairList, MsvAvDnsComputerName, (PBYTE) DnsComputerName.Buffer, DnsComputerName.Length); ntlm_av_pair_add(pAvPairList, MsvAvTimestamp, context->Timestamp, sizeof(context->Timestamp)); }
int credssp_ntlm_server_init(rdpCredssp* credssp) { freerdp* instance; rdpSettings* settings = credssp->settings; instance = (freerdp*) settings->instance; sspi_SecBufferAlloc(&credssp->PublicKey, credssp->transport->TlsIn->PublicKeyLength); CopyMemory(credssp->PublicKey.pvBuffer, credssp->transport->TlsIn->PublicKey, credssp->transport->TlsIn->PublicKeyLength); return 1; }
int credssp_ntlm_server_init(rdpCredssp* credssp) { freerdp* instance; rdpSettings* settings = credssp->settings; instance = (freerdp*) settings->instance; credssp_SetContextIdentity(credssp, test_User, NULL, test_Password); sspi_SecBufferAlloc(&credssp->PublicKey, credssp->tls->public_key.length); memcpy(credssp->PublicKey.pvBuffer, credssp->tls->public_key.data, credssp->tls->public_key.length); return 1; }
void credssp_encode_ts_credentials(rdpCredssp* credssp) { wStream* s; int length; length = ber_sizeof_sequence(credssp_sizeof_ts_credentials(credssp)); sspi_SecBufferAlloc(&credssp->ts_credentials, length); s = Stream_New(credssp->ts_credentials.pvBuffer, length); credssp_write_ts_credentials(credssp, s); Stream_Free(s, FALSE); }
void credssp_encode_ts_credentials(rdpCredssp* credssp) { STREAM* s; int length; s = stream_new(0); length = credssp_skip_ts_credentials(credssp); sspi_SecBufferAlloc(&credssp->ts_credentials, length); stream_attach(s, credssp->ts_credentials.pvBuffer, length); credssp_write_ts_credentials(credssp, s); stream_detach(s); stream_free(s); }
BOOL nla_encode_ts_credentials(rdpNla* nla) { wStream* s; int length; int DomainLength = 0; int UserLength = 0; int PasswordLength = 0; if (nla->identity) { DomainLength = nla->identity->DomainLength; UserLength = nla->identity->UserLength; PasswordLength = nla->identity->PasswordLength; } if (nla->settings->DisableCredentialsDelegation && nla->identity) { nla->identity->DomainLength = 0; nla->identity->UserLength = 0; nla->identity->PasswordLength = 0; } length = ber_sizeof_sequence(nla_sizeof_ts_credentials(nla)); if (!sspi_SecBufferAlloc(&nla->tsCredentials, length)) { WLog_ERR(TAG, "sspi_SecBufferAlloc failed!"); return FALSE; } s = Stream_New((BYTE*) nla->tsCredentials.pvBuffer, length); if (!s) { sspi_SecBufferFree(&nla->tsCredentials); WLog_ERR(TAG, "Stream_New failed!"); return FALSE; } nla_write_ts_credentials(nla, s); if (nla->settings->DisableCredentialsDelegation) { nla->identity->DomainLength = DomainLength; nla->identity->UserLength = UserLength; nla->identity->PasswordLength = PasswordLength; } Stream_Free(s, FALSE); return TRUE; }
int credssp_ntlm_client_init(rdpCredssp* credssp) { char* spn; int length; freerdp* instance; rdpSettings* settings; settings = credssp->settings; instance = (freerdp*) settings->instance; if ((settings->Password == NULL) || (settings->Username == NULL)) { if (instance->Authenticate) { BOOL proceed = instance->Authenticate(instance, &settings->Username, &settings->Password, &settings->Domain); if (!proceed) return 0; } } sspi_SetAuthIdentity(&(credssp->identity), settings->Username, settings->Domain, settings->Password); #ifdef WITH_DEBUG_NLA _tprintf(_T("User: %s Domain: %s Password: %s\n"), (char*) credssp->identity.User, (char*) credssp->identity.Domain, (char*) credssp->identity.Password); #endif sspi_SecBufferAlloc(&credssp->PublicKey, credssp->transport->TlsIn->PublicKeyLength); CopyMemory(credssp->PublicKey.pvBuffer, credssp->transport->TlsIn->PublicKey, credssp->transport->TlsIn->PublicKeyLength); length = sizeof(TERMSRV_SPN_PREFIX) + strlen(settings->ServerHostname); spn = (SEC_CHAR*) malloc(length + 1); sprintf(spn, "%s%s", TERMSRV_SPN_PREFIX, settings->ServerHostname); #ifdef UNICODE credssp->ServicePrincipalName = (LPTSTR) malloc(length * 2 + 2); MultiByteToWideChar(CP_UTF8, 0, spn, length, (LPWSTR) credssp->ServicePrincipalName, length); free(spn); #else credssp->ServicePrincipalName = spn; #endif return 1; }
SECURITY_STATUS nla_encrypt_public_key_echo(rdpNla* nla) { SecBuffer Buffers[2]; SecBufferDesc Message; SECURITY_STATUS status; int public_key_length; public_key_length = nla->PublicKey.cbBuffer; if (!sspi_SecBufferAlloc(&nla->pubKeyAuth, nla->ContextSizes.cbSecurityTrailer + public_key_length)) return SEC_E_INSUFFICIENT_MEMORY; Buffers[0].BufferType = SECBUFFER_TOKEN; /* Signature */ Buffers[0].cbBuffer = nla->ContextSizes.cbSecurityTrailer; Buffers[0].pvBuffer = nla->pubKeyAuth.pvBuffer; Buffers[1].BufferType = SECBUFFER_DATA; /* TLS Public Key */ Buffers[1].cbBuffer = public_key_length; Buffers[1].pvBuffer = ((BYTE*) nla->pubKeyAuth.pvBuffer) + nla->ContextSizes.cbSecurityTrailer; CopyMemory(Buffers[1].pvBuffer, nla->PublicKey.pvBuffer, Buffers[1].cbBuffer); if (nla->server) { /* server echos the public key +1 */ ap_integer_increment_le((BYTE*) Buffers[1].pvBuffer, Buffers[1].cbBuffer); } Message.cBuffers = 2; Message.ulVersion = SECBUFFER_VERSION; Message.pBuffers = (PSecBuffer) &Buffers; status = nla->table->EncryptMessage(&nla->context, 0, &Message, nla->sendSeqNum++); if (status != SEC_E_OK) { WLog_ERR(TAG, "EncryptMessage status %s [%08X]", GetSecurityStatusString(status), status); return status; } if (Buffers[0].cbBuffer < nla->ContextSizes.cbSecurityTrailer) { /* EncryptMessage may not use all the signature space, so we need to shrink the excess */ MoveMemory(((BYTE*)nla->pubKeyAuth.pvBuffer) + Buffers[0].cbBuffer, Buffers[1].pvBuffer, Buffers[1].cbBuffer); nla->pubKeyAuth.cbBuffer = Buffers[0].cbBuffer + Buffers[1].cbBuffer; } return status; }
int credssp_ntlmssp_client_init(rdpCredssp* credssp) { freerdp* instance; SEC_AUTH_IDENTITY identity; rdpSettings* settings = credssp->settings; instance = (freerdp*) settings->instance; if ((settings->password == NULL) || (settings->username == NULL)) { if (instance->Authenticate) { boolean proceed = instance->Authenticate(instance, &settings->username, &settings->password, &settings->domain); if (!proceed) return 0; } } identity.User = (uint16*) xstrdup(settings->username); identity.UserLength = strlen(settings->username); if (settings->domain) { identity.Domain = (uint16*) xstrdup(settings->domain); identity.DomainLength = strlen(settings->domain); } else { identity.Domain = (uint16*) NULL; identity.DomainLength = 0; } identity.Password = (uint16*) xstrdup(settings->password); identity.PasswordLength = strlen(settings->password); identity.Flags = SEC_AUTH_IDENTITY_ANSI; credssp_SetContextIdentity(credssp, &identity); sspi_SecBufferAlloc(&credssp->PublicKey, credssp->tls->public_key.length); memcpy(credssp->PublicKey.pvBuffer, credssp->tls->public_key.data, credssp->tls->public_key.length); return 1; }
SECURITY_STATUS ntlm_computeMicValue(NTLM_CONTEXT* ntlm, SecBuffer* micvalue) { BYTE* blob; ULONG msgSize = ntlm->NegotiateMessage.cbBuffer + ntlm->ChallengeMessage.cbBuffer + ntlm->AuthenticateMessage.cbBuffer; if (!sspi_SecBufferAlloc(micvalue, msgSize)) return SEC_E_INSUFFICIENT_MEMORY; blob = (BYTE*) micvalue->pvBuffer; CopyMemory(blob, ntlm->NegotiateMessage.pvBuffer, ntlm->NegotiateMessage.cbBuffer); blob += ntlm->NegotiateMessage.cbBuffer; CopyMemory(blob, ntlm->ChallengeMessage.pvBuffer, ntlm->ChallengeMessage.cbBuffer); blob += ntlm->ChallengeMessage.cbBuffer; CopyMemory(blob, ntlm->AuthenticateMessage.pvBuffer, ntlm->AuthenticateMessage.cbBuffer); blob += ntlm->MessageIntegrityCheckOffset; ZeroMemory(blob, 16); return SEC_E_OK; }
int ntlm_generate_sealing_key(BYTE* exported_session_key, PSecBuffer seal_magic, BYTE* sealing_key) { BYTE* p; WINPR_MD5_CTX md5; SecBuffer buffer; if (!sspi_SecBufferAlloc(&buffer, WINPR_MD5_DIGEST_LENGTH + seal_magic->cbBuffer)) return -1; p = (BYTE*) buffer.pvBuffer; /* Concatenate ExportedSessionKey with seal magic */ CopyMemory(p, exported_session_key, WINPR_MD5_DIGEST_LENGTH); CopyMemory(&p[WINPR_MD5_DIGEST_LENGTH], seal_magic->pvBuffer, seal_magic->cbBuffer); winpr_MD5_Init(&md5); winpr_MD5_Update(&md5, buffer.pvBuffer, buffer.cbBuffer); winpr_MD5_Final(&md5, sealing_key, WINPR_MD5_DIGEST_LENGTH); sspi_SecBufferFree(&buffer); return 1; }
void ntlm_generate_sealing_key(BYTE* exported_session_key, PSecBuffer seal_magic, BYTE* sealing_key) { BYTE* p; MD5_CTX md5; SecBuffer buffer; sspi_SecBufferAlloc(&buffer, 16 + seal_magic->cbBuffer); p = (BYTE*) buffer.pvBuffer; /* Concatenate ExportedSessionKey with seal magic */ CopyMemory(p, exported_session_key, 16); CopyMemory(&p[16], seal_magic->pvBuffer, seal_magic->cbBuffer); MD5_Init(&md5); MD5_Update(&md5, buffer.pvBuffer, buffer.cbBuffer); MD5_Final(sealing_key, &md5); sspi_SecBufferFree(&buffer); }
SECURITY_STATUS nla_encrypt_ts_credentials(rdpNla* nla) { SecBuffer Buffers[2]; SecBufferDesc Message; SECURITY_STATUS status; if (!nla_encode_ts_credentials(nla)) return SEC_E_INSUFFICIENT_MEMORY; if (!sspi_SecBufferAlloc(&nla->authInfo, nla->ContextSizes.cbSecurityTrailer + nla->tsCredentials.cbBuffer)) return SEC_E_INSUFFICIENT_MEMORY; Buffers[0].BufferType = SECBUFFER_TOKEN; /* Signature */ Buffers[0].cbBuffer = nla->ContextSizes.cbSecurityTrailer; Buffers[0].pvBuffer = nla->authInfo.pvBuffer; ZeroMemory(Buffers[0].pvBuffer, Buffers[0].cbBuffer); Buffers[1].BufferType = SECBUFFER_DATA; /* TSCredentials */ Buffers[1].cbBuffer = nla->tsCredentials.cbBuffer; Buffers[1].pvBuffer = &((BYTE*) nla->authInfo.pvBuffer)[Buffers[0].cbBuffer]; CopyMemory(Buffers[1].pvBuffer, nla->tsCredentials.pvBuffer, Buffers[1].cbBuffer); Message.cBuffers = 2; Message.ulVersion = SECBUFFER_VERSION; Message.pBuffers = (PSecBuffer) &Buffers; status = nla->table->EncryptMessage(&nla->context, 0, &Message, nla->sendSeqNum++); if (status != SEC_E_OK) { WLog_ERR(TAG, "EncryptMessage failure %s [%08X]", GetSecurityStatusString(status), status); return status; } if (Buffers[0].cbBuffer < nla->ContextSizes.cbSecurityTrailer) { /* EncryptMessage may not use all the signature space, so we need to shrink the excess */ MoveMemory(((BYTE*)nla->authInfo.pvBuffer) + Buffers[0].cbBuffer, Buffers[1].pvBuffer, Buffers[1].cbBuffer); nla->authInfo.cbBuffer = Buffers[0].cbBuffer + Buffers[1].cbBuffer; } return SEC_E_OK; }
SECURITY_STATUS ntlm_computeProofValue(NTLM_CONTEXT* ntlm, SecBuffer* ntproof) { BYTE* blob; SecBuffer* target = &ntlm->ChallengeTargetInfo; if (!sspi_SecBufferAlloc(ntproof, 36 + target->cbBuffer)) return SEC_E_INSUFFICIENT_MEMORY; blob = (BYTE*)ntproof->pvBuffer; CopyMemory(blob, ntlm->ServerChallenge, 8); /* Server challenge. */ blob[8] = 1; /* Response version. */ blob[9] = 1; /* Highest response version understood by the client. */ /* Reserved 6B. */ CopyMemory(&blob[16], ntlm->Timestamp, 8); /* Time. */ CopyMemory(&blob[24], ntlm->ClientChallenge, 8); /* Client challenge. */ /* Reserved 4B. */ /* Server name. */ CopyMemory(&blob[36], target->pvBuffer, target->cbBuffer); return SEC_E_OK; }
SECURITY_STATUS credssp_encrypt_public_key_echo(rdpCredssp* credssp) { SecBuffer Buffers[2]; SecBufferDesc Message; SECURITY_STATUS status; int public_key_length; public_key_length = credssp->PublicKey.cbBuffer; Buffers[0].BufferType = SECBUFFER_TOKEN; /* Signature */ Buffers[1].BufferType = SECBUFFER_DATA; /* TLS Public Key */ sspi_SecBufferAlloc(&credssp->pubKeyAuth, credssp->ContextSizes.cbMaxSignature + public_key_length); Buffers[0].cbBuffer = credssp->ContextSizes.cbMaxSignature; Buffers[0].pvBuffer = credssp->pubKeyAuth.pvBuffer; Buffers[1].cbBuffer = public_key_length; Buffers[1].pvBuffer = ((BYTE*) credssp->pubKeyAuth.pvBuffer) + credssp->ContextSizes.cbMaxSignature; CopyMemory(Buffers[1].pvBuffer, credssp->PublicKey.pvBuffer, Buffers[1].cbBuffer); if (credssp->server) { /* server echos the public key +1 */ ap_integer_increment_le((BYTE*) Buffers[1].pvBuffer, Buffers[1].cbBuffer); } Message.cBuffers = 2; Message.ulVersion = SECBUFFER_VERSION; Message.pBuffers = (PSecBuffer) &Buffers; status = credssp->table->EncryptMessage(&credssp->context, 0, &Message, credssp->send_seq_num++); if (status != SEC_E_OK) { fprintf(stderr, "EncryptMessage status: 0x%08X\n", status); return status; } return status; }
void ntlm_populate_av_pairs(NTLM_CONTEXT* context) { int length; AV_PAIRS* av_pairs = context->av_pairs; /* MsvAvFlags */ av_pairs->Flags = 0x00000002; /* Indicates the present of a Message Integrity Check (MIC) */ /* Restriction_Encoding */ ntlm_output_restriction_encoding(context); /* TargetName */ ntlm_output_target_name(context); /* ChannelBindings */ ntlm_output_channel_bindings(context); length = ntlm_compute_av_pairs_length(context); sspi_SecBufferAlloc(&context->TargetInfo, length); ntlm_output_av_pairs(context, &context->TargetInfo); }
SECURITY_STATUS credssp_encrypt_ts_credentials(rdpCredssp* credssp) { uint8* p; SecBuffer Buffers[2]; SecBufferDesc Message; SECURITY_STATUS status; credssp_encode_ts_credentials(credssp); Buffers[0].BufferType = SECBUFFER_DATA; /* TSCredentials */ Buffers[1].BufferType = SECBUFFER_TOKEN; /* Signature */ Buffers[0].cbBuffer = credssp->ts_credentials.cbBuffer; Buffers[0].pvBuffer = xmalloc(Buffers[0].cbBuffer); memcpy(Buffers[0].pvBuffer, credssp->ts_credentials.pvBuffer, Buffers[0].cbBuffer); Buffers[1].cbBuffer = 16; Buffers[1].pvBuffer = xzalloc(Buffers[1].cbBuffer); Message.cBuffers = 2; Message.ulVersion = SECBUFFER_VERSION; Message.pBuffers = (PSecBuffer) &Buffers; sspi_SecBufferAlloc(&credssp->authInfo, Buffers[0].cbBuffer + Buffers[1].cbBuffer); status = credssp->table->EncryptMessage(&credssp->context, 0, &Message, 1); if (status != SEC_E_OK) return status; p = (uint8*) credssp->authInfo.pvBuffer; memcpy(p, Buffers[1].pvBuffer, Buffers[1].cbBuffer); /* Message Signature */ memcpy(&p[Buffers[1].cbBuffer], Buffers[0].pvBuffer, Buffers[0].cbBuffer); /* Encrypted TSCredentials */ xfree(Buffers[0].pvBuffer); xfree(Buffers[1].pvBuffer); return SEC_E_OK; }
void ntlm_populate_server_av_pairs(NTLM_CONTEXT* context) { int length; size_t size; AV_PAIRS* av_pairs = context->av_pairs; av_pairs->NbDomainName.value = (uint8*) freerdp_uniconv_out(context->uniconv, test_NbDomainName, &size); av_pairs->NbDomainName.length = (uint16) size; av_pairs->NbComputerName.value = (uint8*) freerdp_uniconv_out(context->uniconv, test_NbComputerName, &size); av_pairs->NbComputerName.length = (uint16) size; av_pairs->DnsDomainName.value = (uint8*) freerdp_uniconv_out(context->uniconv, test_DnsDomainName, &size); av_pairs->DnsDomainName.length = (uint16) size; av_pairs->DnsComputerName.value = (uint8*) freerdp_uniconv_out(context->uniconv, test_DnsComputerName, &size); av_pairs->DnsComputerName.length = (uint16) size; length = ntlm_compute_av_pairs_length(context) + 4; sspi_SecBufferAlloc(&context->TargetInfo, length); ntlm_output_av_pairs(context, &context->TargetInfo); }
int ntlm_generate_sealing_key(BYTE* exported_session_key, PSecBuffer seal_magic, BYTE* sealing_key) { BYTE* p; SecBuffer buffer; if (!sspi_SecBufferAlloc(&buffer, WINPR_MD5_DIGEST_LENGTH + seal_magic->cbBuffer)) return -1; p = (BYTE*) buffer.pvBuffer; /* Concatenate ExportedSessionKey with seal magic */ CopyMemory(p, exported_session_key, WINPR_MD5_DIGEST_LENGTH); CopyMemory(&p[WINPR_MD5_DIGEST_LENGTH], seal_magic->pvBuffer, seal_magic->cbBuffer); if (!winpr_Digest(WINPR_MD_MD5, buffer.pvBuffer, buffer.cbBuffer, sealing_key, WINPR_MD5_DIGEST_LENGTH)) { sspi_SecBufferFree(&buffer); return -1; } sspi_SecBufferFree(&buffer); return 1; }
int credssp_ntlm_client_init(rdpCredssp* credssp) { freerdp* instance; rdpSettings* settings = credssp->settings; instance = (freerdp*) settings->instance; if ((settings->password == NULL) || (settings->username == NULL)) { if (instance->Authenticate) { boolean proceed = instance->Authenticate(instance, &settings->username, &settings->password, &settings->domain); if (!proceed) return 0; } } credssp_SetContextIdentity(credssp, settings->username, settings->domain, settings->password); sspi_SecBufferAlloc(&credssp->PublicKey, credssp->tls->public_key.length); memcpy(credssp->PublicKey.pvBuffer, credssp->tls->public_key.data, credssp->tls->public_key.length); return 1; }
int ntlm_compute_ntlm_v2_response(NTLM_CONTEXT* context) { BYTE* blob; BYTE nt_proof_str[WINPR_MD5_DIGEST_LENGTH]; SecBuffer ntlm_v2_temp; SecBuffer ntlm_v2_temp_chal; PSecBuffer TargetInfo; SSPI_CREDENTIALS* credentials; credentials = context->credentials; TargetInfo = &context->ChallengeTargetInfo; if (!sspi_SecBufferAlloc(&ntlm_v2_temp, TargetInfo->cbBuffer + 28)) return -1; ZeroMemory(ntlm_v2_temp.pvBuffer, ntlm_v2_temp.cbBuffer); blob = (BYTE*) ntlm_v2_temp.pvBuffer; /* Compute the NTLMv2 hash */ if (ntlm_compute_ntlm_v2_hash(context, (BYTE*) context->NtlmV2Hash) < 0) return -1; #ifdef WITH_DEBUG_NTLM WLog_DBG(TAG, "Password (length = %d)", credentials->identity.PasswordLength * 2); winpr_HexDump(TAG, WLOG_DEBUG, (BYTE*) credentials->identity.Password, credentials->identity.PasswordLength * 2); WLog_DBG(TAG, "Username (length = %d)", credentials->identity.UserLength * 2); winpr_HexDump(TAG, WLOG_DEBUG, (BYTE*) credentials->identity.User, credentials->identity.UserLength * 2); WLog_DBG(TAG, "Domain (length = %d)", credentials->identity.DomainLength * 2); winpr_HexDump(TAG, WLOG_DEBUG, (BYTE*) credentials->identity.Domain, credentials->identity.DomainLength * 2); WLog_DBG(TAG, "Workstation (length = %d)", context->Workstation.Length); winpr_HexDump(TAG, WLOG_DEBUG, (BYTE*) context->Workstation.Buffer, context->Workstation.Length); WLog_DBG(TAG, "NTOWFv2, NTLMv2 Hash"); winpr_HexDump(TAG, WLOG_DEBUG, context->NtlmV2Hash, WINPR_MD5_DIGEST_LENGTH); #endif /* Construct temp */ blob[0] = 1; /* RespType (1 byte) */ blob[1] = 1; /* HighRespType (1 byte) */ /* Reserved1 (2 bytes) */ /* Reserved2 (4 bytes) */ CopyMemory(&blob[8], context->Timestamp, 8); /* Timestamp (8 bytes) */ CopyMemory(&blob[16], context->ClientChallenge, 8); /* ClientChallenge (8 bytes) */ /* Reserved3 (4 bytes) */ CopyMemory(&blob[28], TargetInfo->pvBuffer, TargetInfo->cbBuffer); #ifdef WITH_DEBUG_NTLM WLog_DBG(TAG, "NTLMv2 Response Temp Blob"); winpr_HexDump(TAG, WLOG_DEBUG, ntlm_v2_temp.pvBuffer, ntlm_v2_temp.cbBuffer); #endif /* Concatenate server challenge with temp */ if (!sspi_SecBufferAlloc(&ntlm_v2_temp_chal, ntlm_v2_temp.cbBuffer + 8)) return -1; blob = (BYTE*) ntlm_v2_temp_chal.pvBuffer; CopyMemory(blob, context->ServerChallenge, 8); CopyMemory(&blob[8], ntlm_v2_temp.pvBuffer, ntlm_v2_temp.cbBuffer); winpr_HMAC(WINPR_MD_MD5, (BYTE*) context->NtlmV2Hash, WINPR_MD5_DIGEST_LENGTH, (BYTE*) ntlm_v2_temp_chal.pvBuffer, ntlm_v2_temp_chal.cbBuffer, (BYTE*) nt_proof_str, WINPR_MD5_DIGEST_LENGTH); /* NtChallengeResponse, Concatenate NTProofStr with temp */ if (!sspi_SecBufferAlloc(&context->NtChallengeResponse, ntlm_v2_temp.cbBuffer + 16)) return -1; blob = (BYTE*) context->NtChallengeResponse.pvBuffer; CopyMemory(blob, nt_proof_str, 16); CopyMemory(&blob[16], ntlm_v2_temp.pvBuffer, ntlm_v2_temp.cbBuffer); /* Compute SessionBaseKey, the HMAC-MD5 hash of NTProofStr using the NTLMv2 hash as the key */ winpr_HMAC(WINPR_MD_MD5, (BYTE*) context->NtlmV2Hash, WINPR_MD5_DIGEST_LENGTH, (BYTE*) nt_proof_str, WINPR_MD5_DIGEST_LENGTH, (BYTE*) context->SessionBaseKey, WINPR_MD5_DIGEST_LENGTH); sspi_SecBufferFree(&ntlm_v2_temp); sspi_SecBufferFree(&ntlm_v2_temp_chal); return 1; }
int credssp_server_authenticate(rdpCredssp* credssp) { uint32 cbMaxToken; uint32 fContextReq; uint32 pfContextAttr; SECURITY_STATUS status; CredHandle credentials; TimeStamp expiration; SecPkgInfo* pPackageInfo; PSecBuffer p_buffer; SecBuffer input_buffer; SecBuffer output_buffer; SecBufferDesc input_buffer_desc; SecBufferDesc output_buffer_desc; boolean have_context; boolean have_input_buffer; boolean have_pub_key_auth; sspi_GlobalInit(); if (credssp_ntlm_server_init(credssp) == 0) return 0; credssp->table = InitSecurityInterface(); status = QuerySecurityPackageInfo(NTLM_PACKAGE_NAME, &pPackageInfo); if (status != SEC_E_OK) { printf("QuerySecurityPackageInfo status: 0x%08X\n", status); return 0; } cbMaxToken = pPackageInfo->cbMaxToken; status = credssp->table->AcquireCredentialsHandle(NULL, NTLM_PACKAGE_NAME, SECPKG_CRED_INBOUND, NULL, &credssp->identity, NULL, NULL, &credentials, &expiration); if (status != SEC_E_OK) { printf("AcquireCredentialsHandle status: 0x%08X\n", status); return 0; } have_context = false; have_input_buffer = false; have_pub_key_auth = false; memset(&input_buffer, 0, sizeof(SecBuffer)); memset(&output_buffer, 0, sizeof(SecBuffer)); memset(&credssp->ContextSizes, 0, sizeof(SecPkgContext_Sizes)); fContextReq = ISC_REQ_REPLAY_DETECT | ISC_REQ_SEQUENCE_DETECT | ISC_REQ_CONFIDENTIALITY | ISC_REQ_DELEGATE; while (true) { input_buffer_desc.ulVersion = SECBUFFER_VERSION; input_buffer_desc.cBuffers = 1; input_buffer_desc.pBuffers = &input_buffer; input_buffer.BufferType = SECBUFFER_TOKEN; /* receive authentication token */ input_buffer_desc.ulVersion = SECBUFFER_VERSION; input_buffer_desc.cBuffers = 1; input_buffer_desc.pBuffers = &input_buffer; input_buffer.BufferType = SECBUFFER_TOKEN; if (credssp_recv(credssp) < 0) return -1; #ifdef WITH_DEBUG_CREDSSP printf("Receiving Authentication Token\n"); credssp_buffer_print(credssp); #endif p_buffer = &input_buffer_desc.pBuffers[0]; p_buffer->pvBuffer = credssp->negoToken.pvBuffer; p_buffer->cbBuffer = credssp->negoToken.cbBuffer; output_buffer_desc.ulVersion = SECBUFFER_VERSION; output_buffer_desc.cBuffers = 1; output_buffer_desc.pBuffers = &output_buffer; output_buffer.BufferType = SECBUFFER_TOKEN; output_buffer.cbBuffer = cbMaxToken; output_buffer.pvBuffer = xmalloc(output_buffer.cbBuffer); status = credssp->table->AcceptSecurityContext(&credentials, have_context? &credssp->context: NULL, &input_buffer_desc, 0, SECURITY_NATIVE_DREP, &credssp->context, &output_buffer_desc, &pfContextAttr, &expiration); if (input_buffer.pvBuffer != NULL) { xfree(input_buffer.pvBuffer); input_buffer.pvBuffer = NULL; } p_buffer = &output_buffer_desc.pBuffers[0]; credssp->negoToken.pvBuffer = p_buffer->pvBuffer; credssp->negoToken.cbBuffer = p_buffer->cbBuffer; if ((status == SEC_I_COMPLETE_AND_CONTINUE) || (status == SEC_I_COMPLETE_NEEDED)) { if (credssp->table->CompleteAuthToken != NULL) credssp->table->CompleteAuthToken(&credssp->context, &output_buffer_desc); have_pub_key_auth = true; sspi_SecBufferFree(&credssp->negoToken); credssp->negoToken.pvBuffer = NULL; credssp->negoToken.cbBuffer = 0; if (credssp->table->QueryContextAttributes(&credssp->context, SECPKG_ATTR_SIZES, &credssp->ContextSizes) != SEC_E_OK) { printf("QueryContextAttributes SECPKG_ATTR_SIZES failure\n"); return 0; } if (have_pub_key_auth) { uint8* p; SecBuffer Buffers[2]; SecBufferDesc Message; Buffers[0].BufferType = SECBUFFER_DATA; /* TLS Public Key */ Buffers[1].BufferType = SECBUFFER_TOKEN; /* Signature */ Buffers[0].cbBuffer = credssp->PublicKey.cbBuffer; Buffers[0].pvBuffer = xmalloc(Buffers[0].cbBuffer); memcpy(Buffers[0].pvBuffer, credssp->PublicKey.pvBuffer, Buffers[0].cbBuffer); Buffers[1].cbBuffer = credssp->ContextSizes.cbMaxSignature; Buffers[1].pvBuffer = xzalloc(Buffers[1].cbBuffer); Message.cBuffers = 2; Message.ulVersion = SECBUFFER_VERSION; Message.pBuffers = (PSecBuffer) &Buffers; p = (uint8*) Buffers[0].pvBuffer; p[0]++; /* Public Key +1 */ sspi_SecBufferAlloc(&credssp->pubKeyAuth, Buffers[0].cbBuffer + Buffers[1].cbBuffer); credssp->table->EncryptMessage(&credssp->context, 0, &Message, 0); p = (uint8*) credssp->pubKeyAuth.pvBuffer; memcpy(p, Buffers[1].pvBuffer, Buffers[1].cbBuffer); /* Message Signature */ memcpy(&p[Buffers[1].cbBuffer], Buffers[0].pvBuffer, Buffers[0].cbBuffer); /* Encrypted Public Key */ } if (status == SEC_I_COMPLETE_NEEDED) status = SEC_E_OK; else if (status == SEC_I_COMPLETE_AND_CONTINUE) status = SEC_I_CONTINUE_NEEDED; } /* send authentication token */ #ifdef WITH_DEBUG_CREDSSP printf("Sending Authentication Token\n"); credssp_buffer_print(credssp); #endif credssp_send(credssp); credssp_buffer_free(credssp); if (status != SEC_I_CONTINUE_NEEDED) break; have_context = true; } /* Receive encrypted credentials */ if (credssp_recv(credssp) < 0) return -1; if (status != SEC_E_OK) { printf("AcceptSecurityContext status: 0x%08X\n", status); return 0; } status = credssp->table->ImpersonateSecurityContext(&credssp->context); if (status != SEC_E_OK) { printf("ImpersonateSecurityContext status: 0x%08X\n", status); return 0; } else { status = credssp->table->RevertSecurityContext(&credssp->context); if (status != SEC_E_OK) { printf("RevertSecurityContext status: 0x%08X\n", status); return 0; } } FreeContextBuffer(pPackageInfo); return 1; }
void ntlm_compute_ntlm_v2_response(NTLM_CONTEXT* context) { BYTE* blob; BYTE ntlm_v2_hash[16]; BYTE nt_proof_str[16]; SecBuffer ntlm_v2_temp; SecBuffer ntlm_v2_temp_chal; sspi_SecBufferAlloc(&ntlm_v2_temp, context->ChallengeTargetInfo.cbBuffer + 28); ZeroMemory(ntlm_v2_temp.pvBuffer, ntlm_v2_temp.cbBuffer); blob = (BYTE*) ntlm_v2_temp.pvBuffer; /* Compute the NTLMv2 hash */ ntlm_compute_ntlm_v2_hash(context, (char*) ntlm_v2_hash); #ifdef WITH_DEBUG_NTLM printf("Password (length = %d)\n", context->identity.PasswordLength * 2); winpr_HexDump((BYTE*) context->identity.Password, context->identity.PasswordLength * 2); printf("\n"); printf("Username (length = %d)\n", context->identity.UserLength * 2); winpr_HexDump((BYTE*) context->identity.User, context->identity.UserLength * 2); printf("\n"); printf("Domain (length = %d)\n", context->identity.DomainLength * 2); winpr_HexDump((BYTE*) context->identity.Domain, context->identity.DomainLength * 2); printf("\n"); printf("Workstation (length = %d)\n", context->Workstation.Length); winpr_HexDump((BYTE*) context->Workstation.Buffer, context->Workstation.Length); printf("\n"); printf("NTOWFv2, NTLMv2 Hash\n"); winpr_HexDump(ntlm_v2_hash, 16); printf("\n"); #endif /* Construct temp */ blob[0] = 1; /* RespType (1 byte) */ blob[1] = 1; /* HighRespType (1 byte) */ /* Reserved1 (2 bytes) */ /* Reserved2 (4 bytes) */ CopyMemory(&blob[8], context->Timestamp, 8); /* Timestamp (8 bytes) */ CopyMemory(&blob[16], context->ClientChallenge, 8); /* ClientChallenge (8 bytes) */ /* Reserved3 (4 bytes) */ CopyMemory(&blob[28], context->ChallengeTargetInfo.pvBuffer, context->ChallengeTargetInfo.cbBuffer); #ifdef WITH_DEBUG_NTLM printf("NTLMv2 Response Temp Blob\n"); winpr_HexDump(ntlm_v2_temp.pvBuffer, ntlm_v2_temp.cbBuffer); printf("\n"); #endif /* Concatenate server challenge with temp */ sspi_SecBufferAlloc(&ntlm_v2_temp_chal, ntlm_v2_temp.cbBuffer + 8); blob = (BYTE*) ntlm_v2_temp_chal.pvBuffer; CopyMemory(blob, context->ServerChallenge, 8); CopyMemory(&blob[8], ntlm_v2_temp.pvBuffer, ntlm_v2_temp.cbBuffer); HMAC(EVP_md5(), (void*) ntlm_v2_hash, 16, ntlm_v2_temp_chal.pvBuffer, ntlm_v2_temp_chal.cbBuffer, (void*) nt_proof_str, NULL); /* NtChallengeResponse, Concatenate NTProofStr with temp */ sspi_SecBufferAlloc(&context->NtChallengeResponse, ntlm_v2_temp.cbBuffer + 16); blob = (BYTE*) context->NtChallengeResponse.pvBuffer; CopyMemory(blob, nt_proof_str, 16); CopyMemory(&blob[16], ntlm_v2_temp.pvBuffer, ntlm_v2_temp.cbBuffer); /* Compute SessionBaseKey, the HMAC-MD5 hash of NTProofStr using the NTLMv2 hash as the key */ HMAC(EVP_md5(), (void*) ntlm_v2_hash, 16, (void*) nt_proof_str, 16, (void*) context->SessionBaseKey, NULL); sspi_SecBufferFree(&ntlm_v2_temp); sspi_SecBufferFree(&ntlm_v2_temp_chal); }
int nla_server_init(rdpNla* nla) { rdpTls* tls = nla->transport->tls; if (!sspi_SecBufferAlloc(&nla->PublicKey, tls->PublicKeyLength)) { WLog_ERR(TAG, "Failed to allocate SecBuffer for public key"); return -1; } CopyMemory(nla->PublicKey.pvBuffer, tls->PublicKey, tls->PublicKeyLength); if (nla->SspiModule) { HMODULE hSSPI; INIT_SECURITY_INTERFACE pInitSecurityInterface; hSSPI = LoadLibrary(nla->SspiModule); if (!hSSPI) { WLog_ERR(TAG, "Failed to load SSPI module: %s", nla->SspiModule); return -1; } #ifdef UNICODE pInitSecurityInterface = (INIT_SECURITY_INTERFACE) GetProcAddress(hSSPI, "InitSecurityInterfaceW"); #else pInitSecurityInterface = (INIT_SECURITY_INTERFACE) GetProcAddress(hSSPI, "InitSecurityInterfaceA"); #endif nla->table = pInitSecurityInterface(); } else { nla->table = InitSecurityInterfaceEx(0); } nla->status = nla->table->QuerySecurityPackageInfo(NLA_PKG_NAME, &nla->pPackageInfo); if (nla->status != SEC_E_OK) { WLog_ERR(TAG, "QuerySecurityPackageInfo status %s [%08X]", GetSecurityStatusString(nla->status), nla->status); return -1; } nla->cbMaxToken = nla->pPackageInfo->cbMaxToken; nla->status = nla->table->AcquireCredentialsHandle(NULL, NLA_PKG_NAME, SECPKG_CRED_INBOUND, NULL, NULL, NULL, NULL, &nla->credentials, &nla->expiration); if (nla->status != SEC_E_OK) { WLog_ERR(TAG, "AcquireCredentialsHandle status %s [%08X]", GetSecurityStatusString(nla->status), nla->status); return -1; } nla->haveContext = FALSE; nla->haveInputBuffer = FALSE; nla->havePubKeyAuth = FALSE; ZeroMemory(&nla->inputBuffer, sizeof(SecBuffer)); ZeroMemory(&nla->outputBuffer, sizeof(SecBuffer)); ZeroMemory(&nla->inputBufferDesc, sizeof(SecBufferDesc)); ZeroMemory(&nla->outputBufferDesc, sizeof(SecBufferDesc)); ZeroMemory(&nla->ContextSizes, sizeof(SecPkgContext_Sizes)); /* * from tspkg.dll: 0x00000112 * ASC_REQ_MUTUAL_AUTH * ASC_REQ_CONFIDENTIALITY * ASC_REQ_ALLOCATE_MEMORY */ nla->fContextReq = 0; nla->fContextReq |= ASC_REQ_MUTUAL_AUTH; nla->fContextReq |= ASC_REQ_CONFIDENTIALITY; nla->fContextReq |= ASC_REQ_CONNECTION; nla->fContextReq |= ASC_REQ_USE_SESSION_KEY; nla->fContextReq |= ASC_REQ_REPLAY_DETECT; nla->fContextReq |= ASC_REQ_SEQUENCE_DETECT; nla->fContextReq |= ASC_REQ_EXTENDED_ERROR; return 1; }
int nla_decode_ts_request(rdpNla* nla, wStream* s) { int length; /* TSRequest */ if (!ber_read_sequence_tag(s, &length) || !ber_read_contextual_tag(s, 0, &length, TRUE) || !ber_read_integer(s, &nla->version)) { return -1; } /* [1] negoTokens (NegoData) */ if (ber_read_contextual_tag(s, 1, &length, TRUE) != FALSE) { if (!ber_read_sequence_tag(s, &length) || /* SEQUENCE OF NegoDataItem */ !ber_read_sequence_tag(s, &length) || /* NegoDataItem */ !ber_read_contextual_tag(s, 0, &length, TRUE) || /* [0] negoToken */ !ber_read_octet_string_tag(s, &length) || /* OCTET STRING */ ((int) Stream_GetRemainingLength(s)) < length) { return -1; } if (!sspi_SecBufferAlloc(&nla->negoToken, length)) return -1; Stream_Read(s, nla->negoToken.pvBuffer, length); nla->negoToken.cbBuffer = length; } /* [2] authInfo (OCTET STRING) */ if (ber_read_contextual_tag(s, 2, &length, TRUE) != FALSE) { if (!ber_read_octet_string_tag(s, &length) || /* OCTET STRING */ ((int) Stream_GetRemainingLength(s)) < length) return -1; if (!sspi_SecBufferAlloc(&nla->authInfo, length)) return -1; Stream_Read(s, nla->authInfo.pvBuffer, length); nla->authInfo.cbBuffer = length; } /* [3] pubKeyAuth (OCTET STRING) */ if (ber_read_contextual_tag(s, 3, &length, TRUE) != FALSE) { if (!ber_read_octet_string_tag(s, &length) || /* OCTET STRING */ ((int) Stream_GetRemainingLength(s)) < length) return -1; if (!sspi_SecBufferAlloc(&nla->pubKeyAuth, length)) return -1; Stream_Read(s, nla->pubKeyAuth.pvBuffer, length); nla->pubKeyAuth.cbBuffer = length; } /* [4] errorCode (INTEGER) */ if (nla->version >= 3) { if (ber_read_contextual_tag(s, 4, &length, TRUE) != FALSE) { if (!ber_read_integer(s, &nla->errorCode)) return -1; } } return 1; }