diff --git a/libfreerdp-core/connection.c b/libfreerdp-core/connection.c index 6f170c41e..d5184a5af 100644 --- a/libfreerdp-core/connection.c +++ b/libfreerdp-core/connection.c @@ -502,11 +502,8 @@ boolean rdp_server_accept_nego(rdpRdp* rdp, STREAM* s) if (!nego_read_request(rdp->nego, s)) return false; - if (rdp->nego->requested_protocols == PROTOCOL_RDP) - { - printf("Standard RDP encryption is not supported.\n"); - return false; - } + + rdp->nego->selected_protocol = 0; printf("Requested protocols:"); if ((rdp->nego->requested_protocols & PROTOCOL_TLS)) @@ -531,6 +528,14 @@ boolean rdp_server_accept_nego(rdpRdp* rdp, STREAM* s) else printf("(n)"); } + printf(" RDP"); + if (rdp->settings->rdp_security && rdp->nego->selected_protocol == 0) + { + printf("(Y)"); + rdp->nego->selected_protocol = PROTOCOL_RDP; + } + else + printf("(n)"); printf("\n"); if (!nego_send_negotiation_response(rdp->nego)) @@ -632,8 +637,20 @@ boolean rdp_server_accept_mcs_channel_join_request(rdpRdp* rdp, STREAM* s) return true; } +boolean rdp_server_accept_client_keys(rdpRdp* rdp, STREAM* s) +{ + + if (!rdp_server_establish_keys(rdp, s)) + return false; + + rdp->state = CONNECTION_STATE_ESTABLISH_KEYS; + + return true; +} + boolean rdp_server_accept_client_info(rdpRdp* rdp, STREAM* s) { + if (!rdp_recv_client_info(rdp, s)) return false; diff --git a/libfreerdp-core/connection.h b/libfreerdp-core/connection.h index ebcae1f7b..eb5c0460f 100644 --- a/libfreerdp-core/connection.h +++ b/libfreerdp-core/connection.h @@ -39,6 +39,7 @@ enum CONNECTION_STATE CONNECTION_STATE_MCS_ERECT_DOMAIN, CONNECTION_STATE_MCS_ATTACH_USER, CONNECTION_STATE_MCS_CHANNEL_JOIN, + CONNECTION_STATE_ESTABLISH_KEYS, CONNECTION_STATE_LICENSE, CONNECTION_STATE_CAPABILITY, CONNECTION_STATE_FINALIZATION, @@ -59,6 +60,7 @@ boolean rdp_server_accept_mcs_connect_initial(rdpRdp* rdp, STREAM* s); boolean rdp_server_accept_mcs_erect_domain_request(rdpRdp* rdp, STREAM* s); boolean rdp_server_accept_mcs_attach_user_request(rdpRdp* rdp, STREAM* s); boolean rdp_server_accept_mcs_channel_join_request(rdpRdp* rdp, STREAM* s); +boolean rdp_server_accept_client_keys(rdpRdp* rdp, STREAM* s); boolean rdp_server_accept_client_info(rdpRdp* rdp, STREAM* s); boolean rdp_server_accept_confirm_active(rdpRdp* rdp, STREAM* s); boolean rdp_server_reactivate(rdpRdp* rdp); diff --git a/libfreerdp-core/nego.c b/libfreerdp-core/nego.c index 43ee42742..7eb810bba 100644 --- a/libfreerdp-core/nego.c +++ b/libfreerdp-core/nego.c @@ -521,8 +521,13 @@ void nego_process_negotiation_failure(rdpNego* nego, STREAM* s) boolean nego_send_negotiation_response(rdpNego* nego) { STREAM* s; + rdpSettings* settings; int length; uint8 *bm, *em; + boolean ret; + + ret = true; + settings = nego->transport->settings; s = transport_send_stream_init(nego->transport, 256); length = TPDU_CONNECTION_CONFIRM_LENGTH; @@ -538,6 +543,20 @@ boolean nego_send_negotiation_response(rdpNego* nego) stream_write_uint32(s, nego->selected_protocol); /* selectedProtocol */ length += 8; } + else if (!settings->rdp_security) + { + stream_write_uint8(s, TYPE_RDP_NEG_FAILURE); + stream_write_uint8(s, 0); /* flags */ + stream_write_uint16(s, 8); /* RDP_NEG_DATA length (8) */ + /* + * TODO: Check for other possibilities, + * like SSL_NOT_ALLOWED_BY_SERVER. + */ + printf("nego_send_negotiation_response: client supports only Standard RDP Security\n"); + stream_write_uint32(s, SSL_REQUIRED_BY_SERVER); + length += 8; + ret = false; + } stream_get_mark(s, em); stream_set_mark(s, bm); @@ -548,11 +567,42 @@ boolean nego_send_negotiation_response(rdpNego* nego) if (transport_write(nego->transport, s) < 0) return false; - /* update settings with negotiated protocol security */ - nego->transport->settings->requested_protocols = nego->requested_protocols; - nego->transport->settings->selected_protocol = nego->selected_protocol; + if (ret) + { + /* update settings with negotiated protocol security */ + settings->requested_protocols = nego->requested_protocols; + settings->selected_protocol = nego->selected_protocol; - return true; + if (settings->selected_protocol == PROTOCOL_RDP) + { + settings->tls_security = false; + settings->nla_security = false; + settings->rdp_security = true; + settings->encryption = true; + settings->encryption_method = ENCRYPTION_METHOD_40BIT | ENCRYPTION_METHOD_128BIT | ENCRYPTION_METHOD_FIPS; + settings->encryption_level = ENCRYPTION_LEVEL_CLIENT_COMPATIBLE; + } + else if (settings->selected_protocol == PROTOCOL_TLS) + { + settings->tls_security = true; + settings->nla_security = false; + settings->rdp_security = false; + settings->encryption = false; + settings->encryption_method = ENCRYPTION_METHOD_NONE; + settings->encryption_level = ENCRYPTION_LEVEL_NONE; + } + else if (settings->selected_protocol == PROTOCOL_NLA) + { + settings->tls_security = true; + settings->nla_security = true; + settings->rdp_security = false; + settings->encryption = false; + settings->encryption_method = ENCRYPTION_METHOD_NONE; + settings->encryption_level = ENCRYPTION_LEVEL_NONE; + } + } + + return ret; } /** diff --git a/libfreerdp-core/peer.c b/libfreerdp-core/peer.c index e5ca4990c..a7db7c9bb 100644 --- a/libfreerdp-core/peer.c +++ b/libfreerdp-core/peer.c @@ -236,6 +236,15 @@ static boolean peer_recv_callback(rdpTransport* transport, STREAM* s, void* extr break; case CONNECTION_STATE_MCS_CHANNEL_JOIN: + if (client->context->rdp->settings->encryption) { + if (!rdp_server_accept_client_keys(client->context->rdp, s)) + return false; + break; + } + client->context->rdp->state = CONNECTION_STATE_ESTABLISH_KEYS; + /* FALLTHROUGH */ + + case CONNECTION_STATE_ESTABLISH_KEYS: if (!rdp_server_accept_client_info(client->context->rdp, s)) return false; IFCALL(client->Capabilities, client);