server: accept TLS connection from the client.
This commit is contained in:
parent
601254727f
commit
10f8aab40b
@ -203,6 +203,9 @@ struct rdp_settings
|
||||
char* directory;
|
||||
uint32 performance_flags;
|
||||
|
||||
char* cert_file;
|
||||
char* privatekey_file;
|
||||
|
||||
boolean autologon;
|
||||
boolean compression;
|
||||
|
||||
|
@ -110,6 +110,10 @@ boolean rdp_client_connect(rdpRdp* rdp)
|
||||
|
||||
boolean rdp_server_accept_nego(rdpRdp* rdp, STREAM* s)
|
||||
{
|
||||
boolean ret;
|
||||
|
||||
transport_set_blocking_mode(rdp->transport, True);
|
||||
|
||||
if (!nego_recv_request(rdp->nego, s))
|
||||
return False;
|
||||
if (rdp->nego->requested_protocols == PROTOCOL_RDP)
|
||||
@ -145,6 +149,19 @@ boolean rdp_server_accept_nego(rdpRdp* rdp, STREAM* s)
|
||||
|
||||
nego_send_negotiation_response(rdp->nego);
|
||||
|
||||
ret = False;
|
||||
if (rdp->nego->selected_protocol & PROTOCOL_NLA)
|
||||
ret = transport_accept_nla(rdp->transport);
|
||||
else if (rdp->nego->selected_protocol & PROTOCOL_TLS)
|
||||
ret = transport_accept_tls(rdp->transport);
|
||||
else if (rdp->nego->selected_protocol & PROTOCOL_RDP)
|
||||
ret = transport_accept_rdp(rdp->transport);
|
||||
|
||||
if (!ret)
|
||||
return False;
|
||||
|
||||
transport_set_blocking_mode(rdp->transport, False);
|
||||
|
||||
rdp->state = CONNECTION_STATE_NEGO;
|
||||
|
||||
return True;
|
||||
|
@ -136,6 +136,8 @@ void settings_free(rdpSettings* settings)
|
||||
xfree(settings->shell);
|
||||
xfree(settings->directory);
|
||||
xfree(settings->client_dir);
|
||||
xfree(settings->cert_file);
|
||||
xfree(settings->privatekey_file);
|
||||
xfree(settings);
|
||||
}
|
||||
}
|
||||
|
@ -26,6 +26,24 @@ boolean tls_connect(rdpTls* tls)
|
||||
{
|
||||
int connection_status;
|
||||
|
||||
tls->ctx = SSL_CTX_new(TLSv1_client_method());
|
||||
|
||||
if (tls->ctx == NULL)
|
||||
{
|
||||
printf("SSL_CTX_new failed\n");
|
||||
return False;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is necessary, because the Microsoft TLS implementation is not perfect.
|
||||
* SSL_OP_ALL enables a couple of workarounds for buggy TLS implementations,
|
||||
* but the most important workaround being SSL_OP_TLS_BLOCK_PADDING_BUG.
|
||||
* As the size of the encrypted payload may give hints about its contents,
|
||||
* block padding is normally used, but the Microsoft TLS implementation
|
||||
* won't recognize it and will disconnect you after sending a TLS alert.
|
||||
*/
|
||||
SSL_CTX_set_options(tls->ctx, SSL_OP_ALL);
|
||||
|
||||
tls->ssl = SSL_new(tls->ctx);
|
||||
|
||||
if (tls->ssl == NULL)
|
||||
@ -40,24 +58,9 @@ boolean tls_connect(rdpTls* tls)
|
||||
return False;
|
||||
}
|
||||
|
||||
while (1)
|
||||
{
|
||||
connection_status = SSL_connect(tls->ssl);
|
||||
connection_status = SSL_connect(tls->ssl);
|
||||
|
||||
/*
|
||||
* SSL_WANT_READ and SSL_WANT_WRITE errors are normal,
|
||||
* just try again if it happens
|
||||
*/
|
||||
|
||||
if (connection_status == SSL_ERROR_WANT_READ)
|
||||
continue;
|
||||
else if (connection_status == SSL_ERROR_WANT_WRITE)
|
||||
continue;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
if (connection_status < 0)
|
||||
if (connection_status <= 0)
|
||||
{
|
||||
if (tls_print_error("SSL_connect", tls->ssl, connection_status))
|
||||
return False;
|
||||
@ -68,6 +71,57 @@ boolean tls_connect(rdpTls* tls)
|
||||
return True;
|
||||
}
|
||||
|
||||
boolean tls_accept(rdpTls* tls, const char* cert_file, const char* privatekey_file)
|
||||
{
|
||||
int connection_status;
|
||||
|
||||
tls->ctx = SSL_CTX_new(TLSv1_server_method());
|
||||
|
||||
if (tls->ctx == NULL)
|
||||
{
|
||||
printf("SSL_CTX_new failed\n");
|
||||
return False;
|
||||
}
|
||||
|
||||
if (SSL_CTX_use_RSAPrivateKey_file(tls->ctx, privatekey_file, SSL_FILETYPE_PEM) <= 0)
|
||||
{
|
||||
printf("SSL_CTX_use_RSAPrivateKey_file failed\n");
|
||||
return False;
|
||||
}
|
||||
|
||||
tls->ssl = SSL_new(tls->ctx);
|
||||
|
||||
if (tls->ssl == NULL)
|
||||
{
|
||||
printf("SSL_new failed\n");
|
||||
return False;
|
||||
}
|
||||
|
||||
if (SSL_use_certificate_file(tls->ssl, cert_file, SSL_FILETYPE_PEM) <= 0)
|
||||
{
|
||||
printf("SSL_use_certificate_file failed\n");
|
||||
return False;
|
||||
}
|
||||
|
||||
if (SSL_set_fd(tls->ssl, tls->sockfd) < 1)
|
||||
{
|
||||
printf("SSL_set_fd failed\n");
|
||||
return False;
|
||||
}
|
||||
|
||||
connection_status = SSL_accept(tls->ssl);
|
||||
|
||||
if (connection_status <= 0)
|
||||
{
|
||||
if (tls_print_error("SSL_accept", tls->ssl, connection_status))
|
||||
return False;
|
||||
}
|
||||
|
||||
printf("TLS connection accepted\n");
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
boolean tls_disconnect(rdpTls* tls)
|
||||
{
|
||||
return True;
|
||||
@ -85,10 +139,12 @@ int tls_read(rdpTls* tls, uint8* data, int length)
|
||||
break;
|
||||
|
||||
case SSL_ERROR_WANT_READ:
|
||||
case SSL_ERROR_WANT_WRITE:
|
||||
status = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
tls_print_error("SSL_read", tls->ssl, status);
|
||||
status = -1;
|
||||
break;
|
||||
}
|
||||
@ -107,6 +163,7 @@ int tls_write(rdpTls* tls, uint8* data, int length)
|
||||
case SSL_ERROR_NONE:
|
||||
break;
|
||||
|
||||
case SSL_ERROR_WANT_READ:
|
||||
case SSL_ERROR_WANT_WRITE:
|
||||
status = 0;
|
||||
break;
|
||||
@ -180,29 +237,11 @@ rdpTls* tls_new()
|
||||
if (tls != NULL)
|
||||
{
|
||||
tls->connect = tls_connect;
|
||||
tls->accept = tls_accept;
|
||||
tls->disconnect = tls_disconnect;
|
||||
|
||||
SSL_load_error_strings();
|
||||
SSL_library_init();
|
||||
|
||||
tls->ctx = SSL_CTX_new(TLSv1_client_method());
|
||||
|
||||
if (tls->ctx == NULL)
|
||||
{
|
||||
printf("SSL_CTX_new failed\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is necessary, because the Microsoft TLS implementation is not perfect.
|
||||
* SSL_OP_ALL enables a couple of workarounds for buggy TLS implementations,
|
||||
* but the most important workaround being SSL_OP_TLS_BLOCK_PADDING_BUG.
|
||||
* As the size of the encrypted payload may give hints about its contents,
|
||||
* block padding is normally used, but the Microsoft TLS implementation
|
||||
* won't recognize it and will disconnect you after sending a TLS alert.
|
||||
*/
|
||||
|
||||
SSL_CTX_set_options(tls->ctx, SSL_OP_ALL);
|
||||
}
|
||||
|
||||
return tls;
|
||||
|
@ -30,6 +30,7 @@
|
||||
|
||||
typedef struct rdp_tls rdpTls;
|
||||
typedef boolean (*TlsConnect) (rdpTls* tls);
|
||||
typedef boolean (*TlsAccept) (rdpTls* tls, const char* cert_file, const char* privatekey_file);
|
||||
typedef boolean (*TlsDisconnect) (rdpTls* tls);
|
||||
|
||||
struct rdp_tls
|
||||
@ -38,10 +39,12 @@ struct rdp_tls
|
||||
int sockfd;
|
||||
SSL_CTX* ctx;
|
||||
TlsConnect connect;
|
||||
TlsAccept accept;
|
||||
TlsDisconnect disconnect;
|
||||
};
|
||||
|
||||
boolean tls_connect(rdpTls* tls);
|
||||
boolean tls_accept(rdpTls* tls, const char* cert_file, const char* privatekey_file);
|
||||
boolean tls_disconnect(rdpTls* tls);
|
||||
int tls_read(rdpTls* tls, uint8* data, int length);
|
||||
int tls_write(rdpTls* tls, uint8* data, int length);
|
||||
|
@ -131,6 +131,52 @@ boolean transport_connect_nla(rdpTransport* transport)
|
||||
return True;
|
||||
}
|
||||
|
||||
boolean transport_accept_rdp(rdpTransport* transport)
|
||||
{
|
||||
transport->state = TRANSPORT_STATE_RDP;
|
||||
|
||||
/* RDP encryption */
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
boolean transport_accept_tls(rdpTransport* transport)
|
||||
{
|
||||
if (transport->tls == NULL)
|
||||
transport->tls = tls_new();
|
||||
|
||||
transport->layer = TRANSPORT_LAYER_TLS;
|
||||
transport->state = TRANSPORT_STATE_TLS;
|
||||
transport->tls->sockfd = transport->tcp->sockfd;
|
||||
|
||||
if (tls_accept(transport->tls, transport->settings->cert_file, transport->settings->privatekey_file) != True)
|
||||
return False;
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
boolean transport_accept_nla(rdpTransport* transport)
|
||||
{
|
||||
if (transport->tls == NULL)
|
||||
transport->tls = tls_new();
|
||||
|
||||
transport->layer = TRANSPORT_LAYER_TLS;
|
||||
transport->state = TRANSPORT_STATE_NLA;
|
||||
transport->tls->sockfd = transport->tcp->sockfd;
|
||||
|
||||
if (tls_accept(transport->tls, transport->settings->cert_file, transport->settings->privatekey_file) != True)
|
||||
return False;
|
||||
|
||||
/* Network Level Authentication */
|
||||
|
||||
if (transport->settings->authentication != True)
|
||||
return True;
|
||||
|
||||
/* Blocking here until NLA is complete */
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
int transport_read(rdpTransport* transport, STREAM* s)
|
||||
{
|
||||
int status = -1;
|
||||
|
@ -74,6 +74,9 @@ boolean transport_disconnect(rdpTransport* transport);
|
||||
boolean transport_connect_rdp(rdpTransport* transport);
|
||||
boolean transport_connect_tls(rdpTransport* transport);
|
||||
boolean transport_connect_nla(rdpTransport* transport);
|
||||
boolean transport_accept_rdp(rdpTransport* transport);
|
||||
boolean transport_accept_tls(rdpTransport* transport);
|
||||
boolean transport_accept_nla(rdpTransport* transport);
|
||||
int transport_read(rdpTransport* transport, STREAM* s);
|
||||
int transport_write(rdpTransport* transport, STREAM* s);
|
||||
int transport_check_fds(rdpTransport* transport);
|
||||
|
@ -40,6 +40,8 @@ static void* test_peer_mainloop(void* arg)
|
||||
|
||||
printf("We've got a client %s\n", client->settings->hostname);
|
||||
|
||||
client->settings->cert_file = xstrdup("server.crt");
|
||||
client->settings->privatekey_file = xstrdup("server.key");
|
||||
client->Initialize(client);
|
||||
|
||||
while (1)
|
||||
|
17
server/test/server.crt
Normal file
17
server/test/server.crt
Normal file
@ -0,0 +1,17 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIICyzCCAbOgAwIBAgIJANbqtAWwlQZuMA0GCSqGSIb3DQEBBQUAMBIxEDAOBgNV
|
||||
BAMTB0ZyZWVSRFAwHhcNMDkxMDI5MDA0MTQ5WhcNMDkxMTI4MDA0MTQ5WjASMRAw
|
||||
DgYDVQQDEwdGcmVlUkRQMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
|
||||
q7mxFgRbS2FYJZX7BzpNd4T/n4nEVDBY6YaObLjGpaB1TptzXTcmfDrDslTGwcEY
|
||||
hTFAC4ZvY6yOURExqbph4LSgvkoa6J722RjVPfshGa4mlh2SXvTiaV26VPPxddGb
|
||||
o6fbs2u029lbtBlpIVbhx5RN9vstNkll26oSZ6wfEdBNHQJLd2SU4ItWHj8zjz1f
|
||||
eGxjgChHihUlwcBYKDJsKFkzHZmLrMgB37KsGlXi/WV+eEsjgvz4yP7I3TL8+GsN
|
||||
MjV8fRGVEKTbKSmgunO67d5u+IaqUQb0Ad1ha1jzDQ+a6hdymrulJSIhoOVfKkwi
|
||||
ptTe43FgwxVRIygJP9HjHQIDAQABoyQwIjATBgNVHSUEDDAKBggrBgEFBQcDATAL
|
||||
BgNVHQ8EBAMCBDAwDQYJKoZIhvcNAQEFBQADggEBAIOdEDhOX2kbl02znltd9hCr
|
||||
nV4kRPKm979RKwBNkrEuwYSlcsjAHg5MZ5itH3wFOUo2s5pjt7/vMOAg+6rOBbIa
|
||||
nqr22/gKBtOmuaJLG1yjxDC2vfez7f3B26pKgxa/krM8oxiFdT9n8QbdxdkN7/D9
|
||||
3RLU/aCfgrMzXxRus7eq3kR00jnSs6ggnAfE1E9gric3vFgr1wCzdcriRXmXDfUb
|
||||
hRq+4VG+ZWk16TwCofV5GVU39XWCv5HNO2swAdjkNXgI5e3tQbV3wWLZLqqYzBco
|
||||
iWulAXtoCGmE81+u1Ms7hLLzpXitLZSGPu1r+sDdkKPLCmOvkAaljDQ4nBz7fIA=
|
||||
-----END CERTIFICATE-----
|
27
server/test/server.key
Normal file
27
server/test/server.key
Normal file
@ -0,0 +1,27 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEogIBAAKCAQEAq7mxFgRbS2FYJZX7BzpNd4T/n4nEVDBY6YaObLjGpaB1Tptz
|
||||
XTcmfDrDslTGwcEYhTFAC4ZvY6yOURExqbph4LSgvkoa6J722RjVPfshGa4mlh2S
|
||||
XvTiaV26VPPxddGbo6fbs2u029lbtBlpIVbhx5RN9vstNkll26oSZ6wfEdBNHQJL
|
||||
d2SU4ItWHj8zjz1feGxjgChHihUlwcBYKDJsKFkzHZmLrMgB37KsGlXi/WV+eEsj
|
||||
gvz4yP7I3TL8+GsNMjV8fRGVEKTbKSmgunO67d5u+IaqUQb0Ad1ha1jzDQ+a6hdy
|
||||
mrulJSIhoOVfKkwiptTe43FgwxVRIygJP9HjHQIDAQABAoIBAAVv5K54xtc1JtBR
|
||||
1lfdPbSqDlnjx8aOnVIPg5TnqMp3sR8jBt0NsPc/+RA9ZOmfjoIxFAEJaZ9zSDJC
|
||||
5BqmnxC5R1mfCQkSd2haQ+4pdFvWyrv4Bblh8YU6hXrJGn0LfO0KlIcywtAvKpsi
|
||||
LtTyZkWmaW2HeF/+pO32jYygw38R1wd8Tl6GwjOXwTF6lFACJXOT4YAzcfp3FKSB
|
||||
AiKBIGuMzozoSND7KPFNRrhGhNumJpdS5A8Fb8D2c/ZMv6Cq5IbwOgTfKun+Bz+s
|
||||
mFbnzeb1uWRqQbsVXOBBW/zHfuG3SU5qeZsaAyuu4DTy+LE1oAHF9uhBSHuT5C6i
|
||||
vCJ8A8ECgYEA1iaOmiEJYBrs25iAc4SjCKqhY0mwR3wtu3I06vmgUoML5fhPMv36
|
||||
SvYQIqDyNw3p7TE6mZtw9+G+kK3PqhuJhogwSwg0a6o51RdKnhXH3/68oNWtKCLC
|
||||
1AmR8q/Gd3FwAR3b49CuOIZ9uOiJrc/ejzKdFEJTDR1/TX1frWfZznECgYEAzUiz
|
||||
XxFf7YrGel7JgmfRD2eZRYngOoteFlg5Tee42UjeAY2Pt2aiDLk+2TqQEdI9+Xg7
|
||||
LcFdBqcSNd8bh33xSzgNthIkX+lTDzx0SmKGfyxfFBJcY8nzsLvvnNt3YeuMeaJQ
|
||||
CPszwoZ0jcD46jTCjbrKhaLyEWmUkDp1O71NTW0CgYAXKF49Xpsz8FVyvcAOPeaf
|
||||
dkwzf3F3mX8ciRId4taqdY9g1AREgGCDoK5IAF2RBIkqZCtxFvUVaS0BWjpdq9Ko
|
||||
YKvQQVfh2KueVoF0LOjLWTGutsydzXyCD3Lf6pAstHCnPkJcFWHxrOGFkGfrCtKH
|
||||
a7K+0RlIDsuIZqllCBjukQKBgA31+MTpYJW+D1t5IMkumEgs6n6RLt+sZLyuSU9k
|
||||
B+03CGogn3qAj1rAKmcJlYywuKhDpfqpoNL3/8QMJUokpYlRCZWtTC39pzltCheY
|
||||
9b6mXNz3lrLupBUL4vLO9iKBq28GO90wgEelbz3ItuTuq6CJ6IYIG+BVRtY8M4bZ
|
||||
i+1NAoGANXZjYnJYDnh8Je9SDxDSc5byzK7ddkQoId64RCIfNHqNKH63P81vjgnH
|
||||
YBIPtagY75ZVVNxujCF7m8Rety+d8tEFwfQKDin2EVI7PD2rOJra385/izp7HuBR
|
||||
vqxvLzG9Xv3cNOU2l7PttVw4Pa2i5E37atKi3V3Zp2kMW+KaKPQ=
|
||||
-----END RSA PRIVATE KEY-----
|
Loading…
x
Reference in New Issue
Block a user