diff --git a/include/freerdp/peer.h b/include/freerdp/peer.h index 66efe4976..635bd4e38 100644 --- a/include/freerdp/peer.h +++ b/include/freerdp/peer.h @@ -26,6 +26,8 @@ #include #include +#include + typedef void (*psPeerContextNew)(freerdp_peer* client, rdpContext* context); typedef void (*psPeerContextFree)(freerdp_peer* client, rdpContext* context); @@ -37,6 +39,7 @@ typedef void (*psPeerDisconnect)(freerdp_peer* client); typedef boolean (*psPeerCapabilities)(freerdp_peer* client); typedef boolean (*psPeerPostConnect)(freerdp_peer* client); typedef boolean (*psPeerActivate)(freerdp_peer* client); +typedef boolean (*psPeerLogon)(freerdp_peer* client, SEC_WINNT_AUTH_IDENTITY* identity, boolean automatic); typedef int (*psPeerSendChannelData)(freerdp_peer* client, int channelId, uint8* data, int size); typedef int (*psPeerReceiveChannelData)(freerdp_peer* client, int channelId, uint8* data, int size, int flags, int total_size); @@ -64,13 +67,17 @@ struct rdp_freerdp_peer psPeerCapabilities Capabilities; psPeerPostConnect PostConnect; psPeerActivate Activate; + psPeerLogon Logon; psPeerSendChannelData SendChannelData; psPeerReceiveChannelData ReceiveChannelData; uint32 ack_frame_id; boolean local; + boolean connected; boolean activated; + boolean authenticated; + SEC_WINNT_AUTH_IDENTITY identity; }; FREERDP_API void freerdp_peer_context_new(freerdp_peer* client); diff --git a/libfreerdp/core/peer.c b/libfreerdp/core/peer.c index 353275e26..cd69938f8 100644 --- a/libfreerdp/core/peer.c +++ b/libfreerdp/core/peer.c @@ -102,25 +102,25 @@ static boolean peer_recv_data_pdu(freerdp_peer* client, STREAM* s) if (!rdp_server_accept_client_font_list_pdu(client->context->rdp, s)) return false; - if (client->PostConnect) + if (!client->connected) { - if (!client->PostConnect(client)) - return false; /** * PostConnect should only be called once and should not be called * after a reactivation sequence. */ - client->PostConnect = NULL; - } - if (client->Activate) - { - /* Activate will be called everytime after the client is activated/reactivated. */ - if (!client->Activate(client)) + IFCALLRET(client->PostConnect, client->connected, client); + + if (!client->connected) return false; } - client->activated = true; + /* Activate will be called everytime after the client is activated/reactivated. */ + + IFCALLRET(client->Activate, client->activated, client); + + if (!client->activated) + return false; break; @@ -244,55 +244,69 @@ static boolean peer_recv_pdu(freerdp_peer* client, STREAM* s) static boolean peer_recv_callback(rdpTransport* transport, STREAM* s, void* extra) { freerdp_peer* client = (freerdp_peer*) extra; + rdpRdp* rdp = client->context->rdp; - switch (client->context->rdp->state) + switch (rdp->state) { case CONNECTION_STATE_INITIAL: - if (!rdp_server_accept_nego(client->context->rdp, s)) + if (!rdp_server_accept_nego(rdp, s)) return false; + + if (rdp->nego->selected_protocol & PROTOCOL_NLA) + { + sspi_CopyAuthIdentity(&client->identity, &(rdp->nego->transport->credssp->identity)); + IFCALLRET(client->Logon, client->authenticated, client, &client->identity, true); + credssp_free(rdp->nego->transport->credssp); + } + else + { + IFCALLRET(client->Logon, client->authenticated, client, &client->identity, false); + } + break; case CONNECTION_STATE_NEGO: - if (!rdp_server_accept_mcs_connect_initial(client->context->rdp, s)) + if (!rdp_server_accept_mcs_connect_initial(rdp, s)) return false; break; case CONNECTION_STATE_MCS_CONNECT: - if (!rdp_server_accept_mcs_erect_domain_request(client->context->rdp, s)) + if (!rdp_server_accept_mcs_erect_domain_request(rdp, s)) return false; break; case CONNECTION_STATE_MCS_ERECT_DOMAIN: - if (!rdp_server_accept_mcs_attach_user_request(client->context->rdp, s)) + if (!rdp_server_accept_mcs_attach_user_request(rdp, s)) return false; break; case CONNECTION_STATE_MCS_ATTACH_USER: - if (!rdp_server_accept_mcs_channel_join_request(client->context->rdp, s)) + if (!rdp_server_accept_mcs_channel_join_request(rdp, s)) return false; break; case CONNECTION_STATE_MCS_CHANNEL_JOIN: - if (client->context->rdp->settings->encryption) { - if (!rdp_server_accept_client_keys(client->context->rdp, s)) + if (rdp->settings->encryption) + { + if (!rdp_server_accept_client_keys(rdp, s)) return false; break; } - client->context->rdp->state = CONNECTION_STATE_ESTABLISH_KEYS; + rdp->state = CONNECTION_STATE_ESTABLISH_KEYS; /* FALLTHROUGH */ case CONNECTION_STATE_ESTABLISH_KEYS: - if (!rdp_server_accept_client_info(client->context->rdp, s)) + if (!rdp_server_accept_client_info(rdp, s)) return false; IFCALL(client->Capabilities, client); - if (!rdp_send_demand_active(client->context->rdp)) + if (!rdp_send_demand_active(rdp)) return false; break; case CONNECTION_STATE_LICENSE: - if (!rdp_server_accept_confirm_active(client->context->rdp, s)) + if (!rdp_server_accept_confirm_active(rdp, s)) { /** * During reactivation sequence the client might sent some input or channel data @@ -309,7 +323,7 @@ static boolean peer_recv_callback(rdpTransport* transport, STREAM* s, void* extr break; default: - printf("Invalid state %d\n", client->context->rdp->state); + printf("Invalid state %d\n", rdp->state); return false; } diff --git a/libfreerdp/core/transport.c b/libfreerdp/core/transport.c index dee12e69f..c1d1b2637 100644 --- a/libfreerdp/core/transport.c +++ b/libfreerdp/core/transport.c @@ -263,7 +263,7 @@ boolean transport_accept_nla(rdpTransport* transport) return false; } - credssp_free(transport->credssp); + /* don't free credssp module yet, we need to copy the credentials from it first */ return true; } diff --git a/libfreerdp/core/transport.h b/libfreerdp/core/transport.h index e774cadce..e082fc44e 100644 --- a/libfreerdp/core/transport.h +++ b/libfreerdp/core/transport.h @@ -35,6 +35,7 @@ typedef struct rdp_transport rdpTransport; #include #include +#include #include #include diff --git a/libfreerdp/crypto/nla.c b/libfreerdp/crypto/nla.c index 0d53991f5..89035cf06 100644 --- a/libfreerdp/crypto/nla.c +++ b/libfreerdp/crypto/nla.c @@ -547,7 +547,7 @@ int credssp_server_authenticate(rdpCredssp* credssp) return -1; } - //sspi_SecBufferFree(&credssp->negoToken); + sspi_SecBufferFree(&credssp->negoToken); credssp->negoToken.pvBuffer = NULL; credssp->negoToken.cbBuffer = 0; @@ -568,7 +568,7 @@ int credssp_server_authenticate(rdpCredssp* credssp) #endif credssp_send(credssp); - //credssp_buffer_free(credssp); + credssp_buffer_free(credssp); if (status != SEC_I_CONTINUE_NEEDED) break; @@ -581,7 +581,11 @@ int credssp_server_authenticate(rdpCredssp* credssp) if (credssp_recv(credssp) < 0) return -1; - credssp_decrypt_ts_credentials(credssp); + if (credssp_decrypt_ts_credentials(credssp) != SEC_E_OK) + { + printf("Could not decrypt TSCredentials status: 0x%08X\n", status); + return 0; + } if (status != SEC_E_OK) { @@ -833,6 +837,8 @@ void credssp_read_ts_password_creds(rdpCredssp* credssp, STREAM* s) CopyMemory(credssp->identity.Password, s->p, credssp->identity.PasswordLength); stream_seek(s, credssp->identity.PasswordLength); credssp->identity.PasswordLength /= 2; + + credssp->identity.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE; } void credssp_write_ts_password_creds(rdpCredssp* credssp, STREAM* s) @@ -1300,6 +1306,6 @@ void credssp_free(rdpCredssp* credssp) free(credssp->identity.User); free(credssp->identity.Domain); free(credssp->identity.Password); - //free(credssp); + free(credssp); } } diff --git a/libfreerdp/utils/thread.c b/libfreerdp/utils/thread.c index 5b8783a0c..2e11046bb 100644 --- a/libfreerdp/utils/thread.c +++ b/libfreerdp/utils/thread.c @@ -57,11 +57,7 @@ void freerdp_thread_start(freerdp_thread* thread, void* func, void* arg) #ifdef _WIN32 { -# ifdef _MSC_VER - CloseHandle((HANDLE)_beginthreadex(NULL, 0, func, arg, 0, NULL)); -#else - CloseHandle(CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)func, arg, 0, NULL)); -#endif + CloseHandle(CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) func, arg, 0, NULL)); } #else { diff --git a/server/Windows/cli/wfreerdp.c b/server/Windows/cli/wfreerdp.c index b4e7849d7..a90c50b75 100644 --- a/server/Windows/cli/wfreerdp.c +++ b/server/Windows/cli/wfreerdp.c @@ -41,10 +41,14 @@ int main(int argc, char* argv[]) if (argc == 2) server->port = (DWORD) atoi(argv[1]); + printf("Starting server\n"); + wfreerdp_server_start(server); WaitForSingleObject(server->thread, INFINITE); + printf("Stopping server\n"); + wfreerdp_server_stop(server); wfreerdp_server_free(server); diff --git a/server/Windows/wf_interface.c b/server/Windows/wf_interface.c index a3e323d5d..b144a5655 100644 --- a/server/Windows/wf_interface.c +++ b/server/Windows/wf_interface.c @@ -95,9 +95,10 @@ BOOL wfreerdp_server_start(wfServer* server) if (instance->Open(instance, NULL, (uint16) server->port)) { server->thread = CreateThread(NULL, 0, wf_server_main_loop, (void*) instance, 0, NULL); + return TRUE; } - return TRUE; + return FALSE; } BOOL wfreerdp_server_stop(wfServer* server) diff --git a/server/Windows/wf_interface.h b/server/Windows/wf_interface.h index 8d3e8f65b..178b5ce5c 100644 --- a/server/Windows/wf_interface.h +++ b/server/Windows/wf_interface.h @@ -40,7 +40,6 @@ struct wf_info int bitsPerPixel; HDC driverDC; int peerCount; - BOOL activated; void* changeBuffer; int framesPerSecond; LPTSTR deviceKey; diff --git a/server/Windows/wf_peer.c b/server/Windows/wf_peer.c index 510f1eb0f..88b02dfdb 100644 --- a/server/Windows/wf_peer.c +++ b/server/Windows/wf_peer.c @@ -93,9 +93,16 @@ boolean wf_peer_post_connect(freerdp_peer* client) boolean wf_peer_activate(freerdp_peer* client) { - wfPeerContext* context = (wfPeerContext*) client->context; + return true; +} - context->activated = true; +boolean wf_peer_logon(freerdp_peer* client, SEC_WINNT_AUTH_IDENTITY* identity, boolean automatic) +{ + if (automatic) + { + _tprintf(_T("Logon: User:%s Domain:%s Password:%s\n"), + identity->User, identity->Domain, identity->Password); + } return true; } @@ -190,6 +197,7 @@ DWORD WINAPI wf_peer_main_loop(LPVOID lpParam) client->PostConnect = wf_peer_post_connect; client->Activate = wf_peer_activate; + client->Logon = wf_peer_logon; client->input->SynchronizeEvent = wf_peer_synchronize_event; client->input->KeyboardEvent = wf_peer_keyboard_event; diff --git a/winpr/libwinpr/sspi/sspi.c b/winpr/libwinpr/sspi/sspi.c index 3322c8f7b..bcea44f7c 100644 --- a/winpr/libwinpr/sspi/sspi.c +++ b/winpr/libwinpr/sspi/sspi.c @@ -348,6 +348,7 @@ void sspi_CopyAuthIdentity(SEC_WINNT_AUTH_IDENTITY* identity, SEC_WINNT_AUTH_IDE { identity->User = (UINT16*) malloc((identity->UserLength + 1) * sizeof(WCHAR)); CopyMemory(identity->User, srcIdentity->User, identity->UserLength * sizeof(WCHAR)); + identity->User[identity->UserLength] = 0; } identity->DomainLength = srcIdentity->DomainLength; @@ -356,6 +357,7 @@ void sspi_CopyAuthIdentity(SEC_WINNT_AUTH_IDENTITY* identity, SEC_WINNT_AUTH_IDE { identity->Domain = (UINT16*) malloc((identity->DomainLength + 1) * sizeof(WCHAR)); CopyMemory(identity->Domain, srcIdentity->Domain, identity->DomainLength * sizeof(WCHAR)); + identity->Domain[identity->DomainLength] = 0; } identity->PasswordLength = srcIdentity->PasswordLength; @@ -364,6 +366,7 @@ void sspi_CopyAuthIdentity(SEC_WINNT_AUTH_IDENTITY* identity, SEC_WINNT_AUTH_IDE { identity->Password = (UINT16*) malloc((identity->PasswordLength + 1) * sizeof(WCHAR)); CopyMemory(identity->Password, srcIdentity->Password, identity->PasswordLength * sizeof(WCHAR)); + identity->Password[identity->PasswordLength] = 0; } }