int rpc_recv_bind_ack_pdu(rdpRpc* rpc) { BYTE* p; STREAM* s; int status; BYTE* pdu; BYTE* auth_data; RPC_PDU_HEADER header; int pdu_length = 0x8FFF; pdu = malloc(pdu_length); if (pdu == NULL) return -1; status = rpc_out_read(rpc, pdu, pdu_length); if (status > 0) { s = stream_new(0); stream_attach(s, pdu, pdu_length); rpc_pdu_header_read(s, &header); stream_detach(s); stream_free(s); auth_data = malloc(header.auth_length); if (auth_data == NULL) { free(pdu); return -1; } p = (pdu + (header.frag_length - header.auth_length)); memcpy(auth_data, p, header.auth_length); rpc->ntlm->inputBuffer.pvBuffer = auth_data; rpc->ntlm->inputBuffer.cbBuffer = header.auth_length; ntlm_authenticate(rpc->ntlm); } free(pdu); return status; }
int rpc_out_read(rdpRpc* rpc, uint8* data, int length) { STREAM* s; int status; uint8* pdu; int content_length; RPC_PDU_HEADER header; if (rpc->VirtualConnection->DefaultOutChannel->ReceiverAvailableWindow < 0x00008FFF) /* Just a simple workaround */ rts_send_flow_control_ack_pdu(rpc); /* Send FlowControlAck every time AvailableWindow reaches the half */ pdu = xmalloc(0xFFFF); if (pdu == NULL) { printf("rpc_out_read error: memory allocation failed") ; return -1 ; } status = tls_read(rpc->tls_out, pdu, 16); /* read first 16 bytes to get RPC PDU Header */ if (status <= 0) { xfree(pdu); return status; } s = stream_new(0); stream_attach(s, pdu, 16); rpc_pdu_header_read(s, &header); stream_detach(s); stream_free(s); content_length = header.frag_length - 16; status = tls_read(rpc->tls_out, pdu + 16, content_length); if (status < 0) { xfree(pdu); return status; } if (header.ptype == PTYPE_RTS) /* RTS PDU */ { printf("rpc_out_read error: Unexpected RTS PDU\n"); xfree(pdu); return -1; } else { /* RTS PDUs are not subject to flow control */ rpc->VirtualConnection->DefaultOutChannel->BytesReceived += header.frag_length; rpc->VirtualConnection->DefaultOutChannel->ReceiverAvailableWindow -= header.frag_length; } if (length < header.frag_length) { printf("rpc_out_read error! receive buffer is not large enough\n"); xfree(pdu); return -1; } memcpy(data, pdu, header.frag_length); #ifdef WITH_DEBUG_RPC printf("rpc_out_read(): length: %d\n", header.frag_length); freerdp_hexdump(data, header.frag_length); printf("\n"); #endif xfree(pdu); return header.frag_length; }