int credssp_authenticate(rdpCredssp* credssp) { NTLMSSP* ntlmssp = credssp->ntlmssp; STREAM* s = stream_new(0); uint8* negoTokenBuffer = (uint8*) xmalloc(2048); if (credssp_ntlmssp_init(credssp) == 0) return 0; if (credssp_get_public_key(credssp) == 0) return 0; /* NTLMSSP NEGOTIATE MESSAGE */ s->p = s->data = negoTokenBuffer; ntlmssp_send(ntlmssp, s); credssp->negoToken.data = s->data; credssp->negoToken.length = s->p - s->data; credssp_send(credssp, &credssp->negoToken, NULL, NULL); /* NTLMSSP CHALLENGE MESSAGE */ if (credssp_recv(credssp, &credssp->negoToken, NULL, NULL) < 0) return -1; s->p = s->data = credssp->negoToken.data; ntlmssp_recv(ntlmssp, s); freerdp_blob_free(&credssp->negoToken); /* NTLMSSP AUTHENTICATE MESSAGE */ s->p = s->data = negoTokenBuffer; ntlmssp_send(ntlmssp, s); /* The last NTLMSSP message is sent with the encrypted public key */ credssp->negoToken.data = s->data; credssp->negoToken.length = s->p - s->data; credssp_encrypt_public_key(credssp, &credssp->pubKeyAuth); credssp_send(credssp, &credssp->negoToken, NULL, &credssp->pubKeyAuth); /* Encrypted Public Key +1 */ if (credssp_recv(credssp, &credssp->negoToken, NULL, &credssp->pubKeyAuth) < 0) return -1; if (credssp_verify_public_key(credssp, &credssp->pubKeyAuth) == 0) { /* Failed to verify server public key echo */ return 0; /* DO NOT SEND CREDENTIALS! */ } freerdp_blob_free(&credssp->negoToken); freerdp_blob_free(&credssp->pubKeyAuth); /* Send encrypted credentials */ credssp_encode_ts_credentials(credssp); credssp_encrypt_ts_credentials(credssp, &credssp->authInfo); credssp_send(credssp, NULL, &credssp->authInfo, NULL); xfree(s); return 1; }
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; }
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; }