From 1bf69d644efaebfcd325c601c844b6d7f1fe9e32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Fri, 15 Jun 2012 22:39:12 -0400 Subject: [PATCH] libfreerdp-crypto: NLA debug output improvements --- libfreerdp-core/CMakeLists.txt | 5 +- libfreerdp-crypto/nla.c | 186 ++++++++++++++++----------------- 2 files changed, 92 insertions(+), 99 deletions(-) diff --git a/libfreerdp-core/CMakeLists.txt b/libfreerdp-core/CMakeLists.txt index 64059bc5c..f559739d1 100644 --- a/libfreerdp-core/CMakeLists.txt +++ b/libfreerdp-core/CMakeLists.txt @@ -109,7 +109,10 @@ target_link_libraries(freerdp-core freerdp-locale) target_link_libraries(freerdp-core winpr-utils) target_link_libraries(freerdp-core winpr-rpc) target_link_libraries(freerdp-core winpr-sspi) -target_link_libraries(freerdp-core winpr-registry) + +if(NOT WIN32) + target_link_libraries(freerdp-core winpr-registry) +endif() target_link_libraries(freerdp-core freerdp-crypto) target_link_libraries(freerdp-core ${OPENSSL_LIBRARIES}) diff --git a/libfreerdp-crypto/nla.c b/libfreerdp-crypto/nla.c index b3e1024d7..7114c38bd 100644 --- a/libfreerdp-crypto/nla.c +++ b/libfreerdp-crypto/nla.c @@ -82,7 +82,8 @@ void credssp_send(rdpCredssp* credssp); int credssp_recv(rdpCredssp* credssp); void credssp_buffer_print(rdpCredssp* credssp); void credssp_buffer_free(rdpCredssp* credssp); -SECURITY_STATUS credssp_verify_public_key_echo(rdpCredssp* credssp); +SECURITY_STATUS credssp_encrypt_public_key_echo(rdpCredssp* credssp); +SECURITY_STATUS credssp_decrypt_public_key_echo(rdpCredssp* credssp); void credssp_encode_ts_credentials(rdpCredssp* credssp); SECURITY_STATUS credssp_encrypt_ts_credentials(rdpCredssp* credssp); SECURITY_STATUS credssp_decrypt_ts_credentials(rdpCredssp* credssp); @@ -216,12 +217,11 @@ int credssp_client_authenticate(rdpCredssp* credssp) 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)); + ZeroMemory(&input_buffer, sizeof(SecBuffer)); + ZeroMemory(&output_buffer, sizeof(SecBuffer)); + ZeroMemory(&credssp->ContextSizes, sizeof(SecPkgContext_Sizes)); - fContextReq = ISC_REQ_CONFIDENTIALITY | ISC_REQ_INTEGRITY | ISC_REQ_IDENTIFY | - ISC_REQ_EXTENDED_ERROR | ISC_REQ_SEQUENCE_DETECT | ISC_REQ_REPLAY_DETECT; + fContextReq = ISC_REQ_CONFIDENTIALITY | ISC_REQ_REPLAY_DETECT | ISC_REQ_EXTENDED_ERROR; while (true) { @@ -257,52 +257,7 @@ int credssp_client_authenticate(rdpCredssp* credssp) return 0; } - if (have_pub_key_auth) - { - BYTE* p; - SecBuffer Buffers[2]; - SecBufferDesc Message; - SECURITY_STATUS encrypt_status; - - Buffers[0].BufferType = SECBUFFER_TOKEN; /* Signature */ - Buffers[1].BufferType = SECBUFFER_DATA; /* TLS Public Key */ - - Buffers[0].cbBuffer = credssp->ContextSizes.cbMaxSignature; - Buffers[0].pvBuffer = xzalloc(Buffers[0].cbBuffer); - - Buffers[1].cbBuffer = credssp->PublicKey.cbBuffer; - Buffers[1].pvBuffer = malloc(Buffers[1].cbBuffer); - CopyMemory(Buffers[1].pvBuffer, credssp->PublicKey.pvBuffer, Buffers[1].cbBuffer); - - Message.cBuffers = 2; - Message.ulVersion = SECBUFFER_VERSION; - Message.pBuffers = (PSecBuffer) &Buffers; - - sspi_SecBufferAlloc(&credssp->pubKeyAuth, Buffers[0].cbBuffer + Buffers[1].cbBuffer); - - encrypt_status = credssp->table->EncryptMessage(&credssp->context, 0, &Message, 0); - - if (encrypt_status != SEC_E_OK) - { - printf("EncryptMessage status: 0x%08X\n", encrypt_status); - return 0; - } - -#ifdef WITH_DEBUG_CREDSSP - printf("CredSSP.Signature: (%d)\n", (int) Buffers[0].cbBuffer); - winpr_HexDump((BYTE*) Buffers[0].pvBuffer, Buffers[0].cbBuffer); - printf("CredSSP.PublicKey: (%d)\n", (int) credssp->PublicKey.cbBuffer); - winpr_HexDump((BYTE*) credssp->PublicKey.pvBuffer, credssp->PublicKey.cbBuffer); - printf("CredSSP.PublicKey (encrypted) (%d):\n", (int) Buffers[1].cbBuffer); - winpr_HexDump((BYTE*) Buffers[1].pvBuffer, Buffers[1].cbBuffer); -#endif - - p = (BYTE*) credssp->pubKeyAuth.pvBuffer; - CopyMemory(p, Buffers[0].pvBuffer, Buffers[0].cbBuffer); /* Message Signature */ - CopyMemory(&p[Buffers[0].cbBuffer], Buffers[1].pvBuffer, Buffers[1].cbBuffer); /* Encrypted Public Key */ - free(Buffers[0].pvBuffer); - free(Buffers[1].pvBuffer); - } + credssp_encrypt_public_key_echo(credssp); if (status == SEC_I_COMPLETE_NEEDED) status = SEC_E_OK; @@ -360,11 +315,14 @@ int credssp_client_authenticate(rdpCredssp* credssp) /* Verify Server Public Key Echo */ - status = credssp_verify_public_key_echo(credssp); + status = credssp_decrypt_public_key_echo(credssp); credssp_buffer_free(credssp); if (status != SEC_E_OK) - return 0; + { + printf("Could not verify public key echo!\n"); + return -1; + } /* Send encrypted credentials */ @@ -422,7 +380,7 @@ int credssp_server_authenticate(rdpCredssp* credssp) INIT_SECURITY_INTERFACE InitSecurityInterface; PSecurityFunctionTable pSecurityInterface = NULL; - hSSPI = LoadLibrary(_T("secur32.dll")); + hSSPI = LoadLibrary(_T("security.dll")); #ifdef UNICODE InitSecurityInterface = (INIT_SECURITY_INTERFACE) GetProcAddress(hSSPI, "InitSecurityInterfaceW"); @@ -446,7 +404,7 @@ int credssp_server_authenticate(rdpCredssp* credssp) cbMaxToken = pPackageInfo->cbMaxToken; status = credssp->table->AcquireCredentialsHandle(NULL, NTLMSP_NAME, - SECPKG_CRED_INBOUND, NULL, &credssp->identity, NULL, NULL, &credentials, &expiration); + SECPKG_CRED_INBOUND, NULL, NULL, NULL, NULL, &credentials, &expiration); if (status != SEC_E_OK) { @@ -461,8 +419,7 @@ int credssp_server_authenticate(rdpCredssp* credssp) ZeroMemory(&output_buffer, sizeof(SecBuffer)); ZeroMemory(&credssp->ContextSizes, sizeof(SecPkgContext_Sizes)); - fContextReq = ASC_REQ_REPLAY_DETECT | ASC_REQ_SEQUENCE_DETECT | - ASC_REQ_CONFIDENTIALITY | ASC_REQ_DELEGATE; + fContextReq = ASC_REQ_CONFIDENTIALITY | ASC_REQ_INTEGRITY | ASC_REQ_EXTENDED_ERROR; while (true) { @@ -505,7 +462,7 @@ int credssp_server_authenticate(rdpCredssp* credssp) status = credssp->table->AcceptSecurityContext(&credentials, have_context? &credssp->context: NULL, - &input_buffer_desc, fContextReq, SECURITY_NETWORK_DREP, &credssp->context, + &input_buffer_desc, fContextReq, SECURITY_NATIVE_DREP, &credssp->context, &output_buffer_desc, &pfContextAttr, &expiration); if (input_buffer.pvBuffer != NULL) @@ -531,43 +488,15 @@ int credssp_server_authenticate(rdpCredssp* credssp) return 0; } - credssp_verify_public_key_echo(credssp); + printf("verifying public key echo\n"); + + credssp_decrypt_public_key_echo(credssp); sspi_SecBufferFree(&credssp->negoToken); credssp->negoToken.pvBuffer = NULL; credssp->negoToken.cbBuffer = 0; - if (have_pub_key_auth) - { - BYTE* 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 = malloc(Buffers[0].cbBuffer); - CopyMemory(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 = (BYTE*) 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 = (BYTE*) credssp->pubKeyAuth.pvBuffer; - CopyMemory(p, Buffers[1].pvBuffer, Buffers[1].cbBuffer); /* Message Signature */ - CopyMemory(&p[Buffers[1].cbBuffer], Buffers[0].pvBuffer, Buffers[0].cbBuffer); /* Encrypted Public Key */ - } + credssp_encrypt_public_key_echo(credssp); if (status == SEC_I_COMPLETE_NEEDED) status = SEC_E_OK; @@ -641,7 +570,54 @@ int credssp_authenticate(rdpCredssp* credssp) return credssp_client_authenticate(credssp); } -SECURITY_STATUS credssp_verify_public_key_echo(rdpCredssp* credssp) +SECURITY_STATUS credssp_encrypt_public_key_echo(rdpCredssp* credssp) +{ + BYTE* p; + SecBuffer Buffers[2]; + SecBufferDesc Message; + SECURITY_STATUS status; + + Buffers[0].BufferType = SECBUFFER_TOKEN; /* Signature */ + Buffers[1].BufferType = SECBUFFER_DATA; /* TLS Public Key */ + + Buffers[0].cbBuffer = credssp->ContextSizes.cbMaxSignature; + Buffers[0].pvBuffer = malloc(Buffers[0].cbBuffer); + ZeroMemory(Buffers[0].pvBuffer, Buffers[0].cbBuffer); + + Buffers[1].cbBuffer = credssp->PublicKey.cbBuffer; + Buffers[1].pvBuffer = malloc(Buffers[1].cbBuffer); + CopyMemory(Buffers[1].pvBuffer, credssp->PublicKey.pvBuffer, Buffers[1].cbBuffer); + + if (credssp->server) + { + p = (BYTE*) Buffers[1].pvBuffer; + p[0]++; /* server echos the public key +1 */ + } + + Message.cBuffers = 2; + Message.ulVersion = SECBUFFER_VERSION; + Message.pBuffers = (PSecBuffer) &Buffers; + + sspi_SecBufferAlloc(&credssp->pubKeyAuth, Buffers[0].cbBuffer + Buffers[1].cbBuffer); + + status = credssp->table->EncryptMessage(&credssp->context, 0, &Message, credssp->send_seq_num++); + + if (status != SEC_E_OK) + { + printf("EncryptMessage status: 0x%08X\n", status); + return status; + } + + p = (BYTE*) credssp->pubKeyAuth.pvBuffer; + CopyMemory(p, Buffers[0].pvBuffer, Buffers[0].cbBuffer); /* Message Signature */ + CopyMemory(&p[Buffers[0].cbBuffer], Buffers[1].pvBuffer, Buffers[1].cbBuffer); /* Encrypted Public Key */ + free(Buffers[0].pvBuffer); + free(Buffers[1].pvBuffer); + + return status; +} + +SECURITY_STATUS credssp_decrypt_public_key_echo(rdpCredssp* credssp) { int length; ULONG pfQOP; @@ -672,7 +648,7 @@ SECURITY_STATUS credssp_verify_public_key_echo(rdpCredssp* credssp) Message.ulVersion = SECBUFFER_VERSION; Message.pBuffers = (PSecBuffer) &Buffers; - status = credssp->table->DecryptMessage(&credssp->context, &Message, 0, &pfQOP); + status = credssp->table->DecryptMessage(&credssp->context, &Message, credssp->recv_seq_num++, &pfQOP); if (status != SEC_E_OK) { @@ -902,7 +878,7 @@ SECURITY_STATUS credssp_encrypt_ts_credentials(rdpCredssp* credssp) sspi_SecBufferAlloc(&credssp->authInfo, Buffers[0].cbBuffer + Buffers[1].cbBuffer); - status = credssp->table->EncryptMessage(&credssp->context, 0, &Message, 1); + status = credssp->table->EncryptMessage(&credssp->context, 0, &Message, credssp->send_seq_num++); if (status != SEC_E_OK) return status; @@ -920,6 +896,7 @@ SECURITY_STATUS credssp_encrypt_ts_credentials(rdpCredssp* credssp) SECURITY_STATUS credssp_decrypt_ts_credentials(rdpCredssp* credssp) { BYTE* p; + ULONG pfQOP; SecBuffer Buffers[2]; SecBufferDesc Message; SECURITY_STATUS status; @@ -927,6 +904,12 @@ SECURITY_STATUS credssp_decrypt_ts_credentials(rdpCredssp* credssp) Buffers[0].BufferType = SECBUFFER_TOKEN; /* Signature */ Buffers[1].BufferType = SECBUFFER_DATA; /* TSCredentials */ + if (credssp->authInfo.cbBuffer < 1) + { + printf("credssp_decrypt_ts_credentials missing authInfo buffer\n"); + return SEC_E_INVALID_TOKEN; + } + Buffers[0].cbBuffer = 16; Buffers[0].pvBuffer = malloc(Buffers[0].cbBuffer); CopyMemory(Buffers[0].pvBuffer, credssp->authInfo.pvBuffer, Buffers[0].cbBuffer); @@ -942,7 +925,7 @@ SECURITY_STATUS credssp_decrypt_ts_credentials(rdpCredssp* credssp) sspi_SecBufferAlloc(&credssp->authInfo, Buffers[0].cbBuffer + Buffers[1].cbBuffer); - status = credssp->table->DecryptMessage(&credssp->context, &Message, 1, 0); + status = credssp->table->DecryptMessage(&credssp->context, &Message, credssp->recv_seq_num++, &pfQOP); if (status != SEC_E_OK) return status; @@ -1049,6 +1032,9 @@ void credssp_send(rdpCredssp* credssp) ber_write_octet_string(s, credssp->pubKeyAuth.pvBuffer, length); } + //printf("Sending TSRequest: (%d)\n", stream_get_length(s)); + //freerdp_hexdump(s->data, stream_get_length(s)); + tls_write(credssp->tls, s->data, stream_get_length(s)); stream_free(s); } @@ -1069,6 +1055,7 @@ int credssp_recv(rdpCredssp* credssp) s = stream_new(4096); status = tls_read_all(credssp->tls, s->p, stream_get_left(s)); + s->size = status; if (status < 0) { @@ -1077,6 +1064,9 @@ int credssp_recv(rdpCredssp* credssp) return -1; } + //printf("Receiving TSRequest: (%d)\n", s->size); + //freerdp_hexdump(s->data, s->size); + /* TSRequest */ ber_read_sequence_tag(s, &length); ber_read_contextual_tag(s, 0, &length, true); @@ -1165,9 +1155,9 @@ rdpCredssp* credssp_new(freerdp* instance, rdpTls* tls, rdpSettings* settings) credssp->tls = tls; credssp->send_seq_num = 0; credssp->recv_seq_num = 0; - memset(&credssp->negoToken, 0, sizeof(SecBuffer)); - memset(&credssp->pubKeyAuth, 0, sizeof(SecBuffer)); - memset(&credssp->authInfo, 0, sizeof(SecBuffer)); + ZeroMemory(&credssp->negoToken, sizeof(SecBuffer)); + ZeroMemory(&credssp->pubKeyAuth, sizeof(SecBuffer)); + ZeroMemory(&credssp->authInfo, sizeof(SecBuffer)); } return credssp;