int rdp_client_connect_demand_active(rdpRdp* rdp, wStream* s) { BYTE* mark; UINT16 width; UINT16 height; width = rdp->settings->DesktopWidth; height = rdp->settings->DesktopHeight; Stream_GetPointer(s, mark); if (!rdp_recv_demand_active(rdp, s)) { UINT16 channelId; Stream_SetPointer(s, mark); rdp_recv_get_active_header(rdp, s, &channelId); /* Was Stream_Seek(s, RDP_PACKET_HEADER_MAX_LENGTH); * but the headers aren't always that length, * so that could result in a bad offset. */ return rdp_recv_out_of_sequence_pdu(rdp, s); } if (freerdp_shall_disconnect(rdp->instance)) return 0; if (!rdp_send_confirm_active(rdp)) return -1; if (!input_register_client_callbacks(rdp->input)) { WLog_ERR(TAG, "error registering client callbacks"); return -1; } /** * The server may request a different desktop size during Deactivation-Reactivation sequence. * In this case, the UI should be informed and do actual window resizing at this point. */ if (width != rdp->settings->DesktopWidth || height != rdp->settings->DesktopHeight) { BOOL status = TRUE; IFCALLRET(rdp->update->DesktopResize, status, rdp->update->context); if (!status) { WLog_ERR(TAG, "client desktop resize callback failed"); return -1; } } rdp_client_transition_to_state(rdp, CONNECTION_STATE_FINALIZATION); return rdp_client_connect_finalize(rdp); }
BOOL rdp_client_connect_mcs_attach_user_confirm(rdpRdp* rdp, wStream* s) { if (!mcs_recv_attach_user_confirm(rdp->mcs, s)) return FALSE; if (!mcs_send_channel_join_request(rdp->mcs, rdp->mcs->userId)) return FALSE; rdp_client_transition_to_state(rdp, CONNECTION_STATE_MCS_CHANNEL_JOIN); return TRUE; }
BOOL rdp_client_disconnect(rdpRdp* rdp) { BOOL status; status = nego_disconnect(rdp->nego); rdp_reset(rdp); rdp_client_transition_to_state(rdp, CONNECTION_STATE_INITIAL); return status; }
BOOL rdp_recv_deactivate_all(rdpRdp* rdp, wStream* s) { UINT16 lengthSourceDescriptor; if (rdp->state == CONNECTION_STATE_ACTIVE) rdp->deactivation_reactivation = TRUE; else rdp->deactivation_reactivation = FALSE; /* * Windows XP can send short DEACTIVATE_ALL PDU that doesn't contain * the following fields. */ if (Stream_GetRemainingLength(s) > 0) { do { if (Stream_GetRemainingLength(s) < 4) break; Stream_Read_UINT32(s, rdp->settings->ShareId); /* shareId (4 bytes) */ if (Stream_GetRemainingLength(s) < 2) break; Stream_Read_UINT16(s, lengthSourceDescriptor); /* lengthSourceDescriptor (2 bytes) */ if (Stream_GetRemainingLength(s) < lengthSourceDescriptor) break; Stream_Seek(s, lengthSourceDescriptor); /* sourceDescriptor (should be 0x00) */ } while (0); } rdp_client_transition_to_state(rdp, CONNECTION_STATE_CAPABILITIES_EXCHANGE); while (rdp->state != CONNECTION_STATE_ACTIVE) { if (rdp_check_fds(rdp) < 0) return FALSE; if (freerdp_shall_disconnect(rdp->instance)) break; SwitchToThread(); } return TRUE; }
BOOL rdp_client_disconnect(rdpRdp* rdp) { BOOL rc; if (rdp->settingsCopy) { freerdp_settings_free(rdp->settingsCopy); rdp->settingsCopy = NULL; } rc = nego_disconnect(rdp->nego); rdp_reset(rdp); rdp_client_transition_to_state(rdp, CONNECTION_STATE_INITIAL); return rc; }
BOOL rdp_client_connect_mcs_connect_response(rdpRdp* rdp, wStream* s) { if (!mcs_recv_connect_response(rdp->mcs, s)) { fprintf(stderr, "rdp_client_connect_mcs_connect_response: mcs_recv_connect_response failed\n"); return FALSE; } if (!mcs_send_erect_domain_request(rdp->mcs)) return FALSE; if (!mcs_send_attach_user_request(rdp->mcs)) return FALSE; rdp_client_transition_to_state(rdp, CONNECTION_STATE_MCS_ATTACH_USER); return TRUE; }
BOOL transport_connect_nla(rdpTransport* transport) { rdpContext* context = transport->context; rdpSettings* settings = context->settings; freerdp* instance = context->instance; rdpRdp* rdp = context->rdp; if (!transport_connect_tls(transport)) return FALSE; if (!settings->Authentication) return TRUE; rdp->nla = nla_new(instance, transport, settings); if (!rdp->nla) return FALSE; transport_set_nla_mode(transport, TRUE); if (settings->AuthenticationServiceClass) { rdp->nla->ServicePrincipalName = nla_make_spn(settings->AuthenticationServiceClass, settings->ServerHostname); if (!rdp->nla->ServicePrincipalName) return FALSE; } if (nla_client_begin(rdp->nla) < 0) { if (!freerdp_get_last_error(context)) freerdp_set_last_error(context, FREERDP_ERROR_AUTHENTICATION_FAILED); transport_set_nla_mode(transport, FALSE); return FALSE; } rdp_client_transition_to_state(rdp, CONNECTION_STATE_NLA); return TRUE; }
int rdp_client_connect_license(rdpRdp* rdp, wStream* s) { int status; status = license_recv(rdp->license, s); if (status < 0) return status; if (rdp->license->state == LICENSE_STATE_ABORTED) { fprintf(stderr, "license connection sequence aborted.\n"); return -1; } if (rdp->license->state == LICENSE_STATE_COMPLETED) { rdp_client_transition_to_state(rdp, CONNECTION_STATE_CAPABILITIES_EXCHANGE); } return 0; }
BOOL rdp_client_connect_mcs_channel_join_confirm(rdpRdp* rdp, wStream* s) { UINT32 i; UINT16 channelId; BOOL allJoined = TRUE; rdpMcs* mcs = rdp->mcs; if (!mcs_recv_channel_join_confirm(mcs, s, &channelId)) return FALSE; if (!mcs->userChannelJoined) { if (channelId != mcs->userId) return FALSE; mcs->userChannelJoined = TRUE; if (!mcs_send_channel_join_request(mcs, MCS_GLOBAL_CHANNEL_ID)) return FALSE; } else if (!mcs->globalChannelJoined) { if (channelId != MCS_GLOBAL_CHANNEL_ID) return FALSE; mcs->globalChannelJoined = TRUE; if (mcs->messageChannelId != 0) { if (!mcs_send_channel_join_request(mcs, mcs->messageChannelId)) return FALSE; allJoined = FALSE; } else { if (mcs->channelCount > 0) { if (!mcs_send_channel_join_request(mcs, mcs->channels[0].ChannelId)) return FALSE; allJoined = FALSE; } } } else if ((mcs->messageChannelId != 0) && !mcs->messageChannelJoined) { if (channelId != mcs->messageChannelId) return FALSE; mcs->messageChannelJoined = TRUE; if (mcs->channelCount > 0) { if (!mcs_send_channel_join_request(mcs, mcs->channels[0].ChannelId)) return FALSE; allJoined = FALSE; } } else { for (i = 0; i < mcs->channelCount; i++) { if (mcs->channels[i].joined) continue; if (mcs->channels[i].ChannelId != channelId) return FALSE; mcs->channels[i].joined = TRUE; break; } if (i + 1 < mcs->channelCount) { if (!mcs_send_channel_join_request(mcs, mcs->channels[i + 1].ChannelId)) return FALSE; allJoined = FALSE; } } if (mcs->userChannelJoined && mcs->globalChannelJoined && allJoined) { if (!rdp_client_establish_keys(rdp)) return FALSE; if (!rdp_send_client_info(rdp)) return FALSE; rdp_client_transition_to_state(rdp, CONNECTION_STATE_LICENSING); } return TRUE; }
BOOL rdp_client_connect(rdpRdp* rdp) { rdpSettings* settings = rdp->settings; if (rdp->settingsCopy) { freerdp_settings_free(rdp->settingsCopy); rdp->settingsCopy = NULL; } rdp->settingsCopy = freerdp_settings_clone(settings); nego_init(rdp->nego); nego_set_target(rdp->nego, settings->ServerHostname, settings->ServerPort); if (settings->GatewayEnabled) { char* user = NULL; char* domain = NULL; char* cookie = NULL; int user_length = 0; int domain_length = 0; int cookie_length = 0; if (settings->Username) { user = settings->Username; user_length = strlen(settings->Username); } if (settings->Domain) domain = settings->Domain; else domain = settings->ComputerName; domain_length = strlen(domain); cookie_length = domain_length + 1 + user_length; cookie = (char*) malloc(cookie_length + 1); CopyMemory(cookie, domain, domain_length); CharUpperBuffA(cookie, domain_length); cookie[domain_length] = '\\'; if (settings->Username) CopyMemory(&cookie[domain_length + 1], user, user_length); cookie[cookie_length] = '\0'; nego_set_cookie(rdp->nego, cookie); free(cookie); } else { nego_set_cookie(rdp->nego, settings->Username); } nego_set_send_preconnection_pdu(rdp->nego, settings->SendPreconnectionPdu); nego_set_preconnection_id(rdp->nego, settings->PreconnectionId); nego_set_preconnection_blob(rdp->nego, settings->PreconnectionBlob); nego_set_negotiation_enabled(rdp->nego, settings->NegotiateSecurityLayer); nego_set_restricted_admin_mode_required(rdp->nego, settings->RestrictedAdminModeRequired); nego_enable_rdp(rdp->nego, settings->RdpSecurity); nego_enable_tls(rdp->nego, settings->TlsSecurity); nego_enable_nla(rdp->nego, settings->NlaSecurity); nego_enable_ext(rdp->nego, settings->ExtSecurity); if (settings->MstscCookieMode) settings->CookieMaxLength = MSTSC_COOKIE_MAX_LENGTH; nego_set_cookie_max_length(rdp->nego, settings->CookieMaxLength); if (settings->LoadBalanceInfo) nego_set_routing_token(rdp->nego, settings->LoadBalanceInfo, settings->LoadBalanceInfoLength); if (!nego_connect(rdp->nego)) { fprintf(stderr, "Error: protocol security negotiation or connection failure\n"); return FALSE; } if ((rdp->nego->selected_protocol & PROTOCOL_TLS) || (rdp->nego->selected_protocol == PROTOCOL_RDP)) { if ((settings->Username != NULL) && ((settings->Password != NULL) || (settings->RedirectionPassword != NULL && settings->RedirectionPasswordLength > 0))) settings->AutoLogonEnabled = TRUE; } rdp_set_blocking_mode(rdp, FALSE); rdp_client_transition_to_state(rdp, CONNECTION_STATE_NEGO); rdp->finalize_sc_pdus = 0; if (!mcs_send_connect_initial(rdp->mcs)) { if (!connectErrorCode) { connectErrorCode = MCSCONNECTINITIALERROR; } fprintf(stderr, "Error: unable to send MCS Connect Initial\n"); return FALSE; } while (rdp->state != CONNECTION_STATE_ACTIVE) { if (rdp_check_fds(rdp) < 0) return FALSE; } return TRUE; }
static int rdp_recv_callback(rdpTransport* transport, wStream* s, void* extra) { int status = 0; rdpRdp* rdp = (rdpRdp*) extra; /* * At any point in the connection sequence between when all * MCS channels have been joined and when the RDP connection * enters the active state, an auto-detect PDU can be received * on the MCS message channel. */ if ((rdp->state > CONNECTION_STATE_MCS_CHANNEL_JOIN) && (rdp->state < CONNECTION_STATE_ACTIVE)) { if (rdp_client_connect_auto_detect(rdp, s)) return 0; } switch (rdp->state) { case CONNECTION_STATE_NEGO: if (!rdp_client_connect_mcs_connect_response(rdp, s)) status = -1; break; case CONNECTION_STATE_MCS_ATTACH_USER: if (!rdp_client_connect_mcs_attach_user_confirm(rdp, s)) status = -1; break; case CONNECTION_STATE_MCS_CHANNEL_JOIN: if (!rdp_client_connect_mcs_channel_join_confirm(rdp, s)) status = -1; break; case CONNECTION_STATE_LICENSING: status = rdp_client_connect_license(rdp, s); break; case CONNECTION_STATE_CAPABILITIES_EXCHANGE: status = rdp_client_connect_demand_active(rdp, s); break; case CONNECTION_STATE_FINALIZATION: status = rdp_recv_pdu(rdp, s); if ((status >= 0) && (rdp->finalize_sc_pdus == FINALIZE_SC_COMPLETE)) rdp_client_transition_to_state(rdp, CONNECTION_STATE_ACTIVE); break; case CONNECTION_STATE_ACTIVE: status = rdp_recv_pdu(rdp, s); break; default: DEBUG_WARN( "Invalid state %d\n", rdp->state); status = -1; break; } return status; }
BOOL rdp_client_connect(rdpRdp* rdp) { BOOL status; rdpSettings* settings = rdp->settings; if (rdp->settingsCopy) { freerdp_settings_free(rdp->settingsCopy); rdp->settingsCopy = NULL; } rdp->settingsCopy = freerdp_settings_clone(settings); if (!rdp->settingsCopy) return FALSE; nego_init(rdp->nego); nego_set_target(rdp->nego, settings->ServerHostname, settings->ServerPort); if (settings->GatewayEnabled) { char* user = NULL; char* domain = NULL; char* cookie = NULL; int user_length = 0; int domain_length = 0; int cookie_length = 0; if (settings->Username) { user = settings->Username; user_length = strlen(settings->Username); } if (settings->Domain) domain = settings->Domain; else domain = settings->ComputerName; domain_length = strlen(domain); cookie_length = domain_length + 1 + user_length; cookie = (char*) malloc(cookie_length + 1); if (!cookie) return FALSE; CopyMemory(cookie, domain, domain_length); CharUpperBuffA(cookie, domain_length); cookie[domain_length] = '\\'; if (settings->Username) CopyMemory(&cookie[domain_length + 1], user, user_length); cookie[cookie_length] = '\0'; status = nego_set_cookie(rdp->nego, cookie); free(cookie); } else { status = nego_set_cookie(rdp->nego, settings->Username); } if (!status) return FALSE; nego_set_send_preconnection_pdu(rdp->nego, settings->SendPreconnectionPdu); nego_set_preconnection_id(rdp->nego, settings->PreconnectionId); nego_set_preconnection_blob(rdp->nego, settings->PreconnectionBlob); nego_set_negotiation_enabled(rdp->nego, settings->NegotiateSecurityLayer); nego_set_restricted_admin_mode_required(rdp->nego, settings->RestrictedAdminModeRequired); nego_set_gateway_enabled(rdp->nego, settings->GatewayEnabled); nego_set_gateway_bypass_local(rdp->nego, settings->GatewayBypassLocal); nego_enable_rdp(rdp->nego, settings->RdpSecurity); nego_enable_tls(rdp->nego, settings->TlsSecurity); nego_enable_nla(rdp->nego, settings->NlaSecurity); nego_enable_ext(rdp->nego, settings->ExtSecurity); if (settings->MstscCookieMode) settings->CookieMaxLength = MSTSC_COOKIE_MAX_LENGTH; nego_set_cookie_max_length(rdp->nego, settings->CookieMaxLength); if (settings->LoadBalanceInfo) { if (!nego_set_routing_token(rdp->nego, settings->LoadBalanceInfo, settings->LoadBalanceInfoLength)) return FALSE; } rdp_client_transition_to_state(rdp, CONNECTION_STATE_NEGO); if (!nego_connect(rdp->nego)) { if (!freerdp_get_last_error(rdp->context)) freerdp_set_last_error(rdp->context, FREERDP_ERROR_SECURITY_NEGO_CONNECT_FAILED); WLog_ERR(TAG, "Error: protocol security negotiation or connection failure"); return FALSE; } if ((rdp->nego->SelectedProtocol & PROTOCOL_TLS) || (rdp->nego->SelectedProtocol == PROTOCOL_RDP)) { if ((settings->Username != NULL) && ((settings->Password != NULL) || (settings->RedirectionPassword != NULL && settings->RedirectionPasswordLength > 0))) settings->AutoLogonEnabled = TRUE; } /* everything beyond this point is event-driven and non blocking */ rdp->transport->ReceiveCallback = rdp_recv_callback; rdp->transport->ReceiveExtra = rdp; transport_set_blocking_mode(rdp->transport, FALSE); if (rdp->state != CONNECTION_STATE_NLA) { if (!mcs_client_begin(rdp->mcs)) return FALSE; } while (rdp->state != CONNECTION_STATE_ACTIVE) { if (rdp_check_fds(rdp) < 0) { if (!freerdp_get_last_error(rdp->context)) freerdp_set_last_error(rdp->context, FREERDP_ERROR_CONNECT_TRANSPORT_FAILED); return FALSE; } } return TRUE; }
BOOL rdp_client_connect(rdpRdp* rdp) { BOOL status; rdpSettings* settings = rdp->settings; /* make sure SSL is initialize for earlier enough for crypto, by taking advantage of winpr SSL FIPS flag for openssl initialization */ DWORD flags = WINPR_SSL_INIT_DEFAULT; if (settings->FIPSMode) flags |= WINPR_SSL_INIT_ENABLE_FIPS; winpr_InitializeSSL(flags); /* FIPS Mode forces the following and overrides the following(by happening later */ /* in the command line processing): */ /* 1. Disables NLA Security since NLA in freerdp uses NTLM(no Kerberos support yet) which uses algorithms */ /* not allowed in FIPS for sensitive data. So, we disallow NLA when FIPS is required. */ /* 2. Forces the only supported RDP encryption method to be FIPS. */ if (settings->FIPSMode || winpr_FIPSMode()) { settings->NlaSecurity = FALSE; settings->EncryptionMethods = ENCRYPTION_METHOD_FIPS; } nego_init(rdp->nego); nego_set_target(rdp->nego, settings->ServerHostname, settings->ServerPort); if (settings->GatewayEnabled) { char* user = NULL; char* domain = NULL; char* cookie = NULL; int user_length = 0; int domain_length = 0; int cookie_length = 0; if (settings->Username) { user = settings->Username; user_length = strlen(settings->Username); } if (settings->Domain) domain = settings->Domain; else domain = settings->ComputerName; domain_length = strlen(domain); cookie_length = domain_length + 1 + user_length; cookie = (char*) malloc(cookie_length + 1); if (!cookie) return FALSE; CopyMemory(cookie, domain, domain_length); CharUpperBuffA(cookie, domain_length); cookie[domain_length] = '\\'; if (settings->Username) CopyMemory(&cookie[domain_length + 1], user, user_length); cookie[cookie_length] = '\0'; status = nego_set_cookie(rdp->nego, cookie); free(cookie); } else { status = nego_set_cookie(rdp->nego, settings->Username); } if (!status) return FALSE; nego_set_send_preconnection_pdu(rdp->nego, settings->SendPreconnectionPdu); nego_set_preconnection_id(rdp->nego, settings->PreconnectionId); nego_set_preconnection_blob(rdp->nego, settings->PreconnectionBlob); nego_set_negotiation_enabled(rdp->nego, settings->NegotiateSecurityLayer); nego_set_restricted_admin_mode_required(rdp->nego, settings->RestrictedAdminModeRequired); nego_set_gateway_enabled(rdp->nego, settings->GatewayEnabled); nego_set_gateway_bypass_local(rdp->nego, settings->GatewayBypassLocal); nego_enable_rdp(rdp->nego, settings->RdpSecurity); nego_enable_tls(rdp->nego, settings->TlsSecurity); nego_enable_nla(rdp->nego, settings->NlaSecurity); nego_enable_ext(rdp->nego, settings->ExtSecurity); if (settings->MstscCookieMode) settings->CookieMaxLength = MSTSC_COOKIE_MAX_LENGTH; nego_set_cookie_max_length(rdp->nego, settings->CookieMaxLength); if (settings->LoadBalanceInfo) { if (!nego_set_routing_token(rdp->nego, settings->LoadBalanceInfo, settings->LoadBalanceInfoLength)) return FALSE; } rdp_client_transition_to_state(rdp, CONNECTION_STATE_NEGO); if (!nego_connect(rdp->nego)) { if (!freerdp_get_last_error(rdp->context)) freerdp_set_last_error(rdp->context, FREERDP_ERROR_SECURITY_NEGO_CONNECT_FAILED); WLog_ERR(TAG, "Error: protocol security negotiation or connection failure"); return FALSE; } if ((rdp->nego->SelectedProtocol & PROTOCOL_TLS) || (rdp->nego->SelectedProtocol == PROTOCOL_RDP)) { if ((settings->Username != NULL) && ((settings->Password != NULL) || (settings->RedirectionPassword != NULL && settings->RedirectionPasswordLength > 0))) settings->AutoLogonEnabled = TRUE; } /* everything beyond this point is event-driven and non blocking */ rdp->transport->ReceiveCallback = rdp_recv_callback; rdp->transport->ReceiveExtra = rdp; transport_set_blocking_mode(rdp->transport, FALSE); if (rdp->state != CONNECTION_STATE_NLA) { if (!mcs_client_begin(rdp->mcs)) return FALSE; } while (rdp->state != CONNECTION_STATE_ACTIVE) { if (rdp_check_fds(rdp) < 0) { if (!freerdp_get_last_error(rdp->context)) freerdp_set_last_error(rdp->context, FREERDP_ERROR_CONNECT_TRANSPORT_FAILED); return FALSE; } } return TRUE; }