diff --git a/common/ssl_calls.c b/common/ssl_calls.c index 0bae2f5e..9829a97b 100644 --- a/common/ssl_calls.c +++ b/common/ssl_calls.c @@ -535,7 +535,7 @@ ssl_tls_print_error(const char *func, SSL *connection, int value) /*****************************************************************************/ int APP_CC -ssl_tls_accept(struct ssl_tls *self, int disableSSLv3, +ssl_tls_accept(struct ssl_tls *self, long ssl_protocols, const char *tls_ciphers) { int connection_status; @@ -544,13 +544,14 @@ ssl_tls_accept(struct ssl_tls *self, int disableSSLv3, /** * SSL_OP_NO_SSLv2 * SSLv3 is used by, eg. Microsoft RDC for Mac OS X. - * No SSLv3 if disableSSLv3=yes so only tls used */ options |= SSL_OP_NO_SSLv2; - if (disableSSLv3) - { - options |= SSL_OP_NO_SSLv3; - } + + /** + * Disable SSL protocols not listed in ssl_protocols. + */ + options |= ssl_protocols; + #if defined(SSL_OP_NO_COMPRESSION) /** diff --git a/common/ssl_calls.h b/common/ssl_calls.h index 258e9848..c969ec43 100644 --- a/common/ssl_calls.h +++ b/common/ssl_calls.h @@ -96,7 +96,7 @@ struct ssl_tls struct ssl_tls *APP_CC ssl_tls_create(struct trans *trans, const char *key, const char *cert); int APP_CC -ssl_tls_accept(struct ssl_tls *self, int disableSSLv3, +ssl_tls_accept(struct ssl_tls *self, long ssl_protocols, const char *tls_ciphers); int APP_CC ssl_tls_disconnect(struct ssl_tls *self); diff --git a/common/trans.c b/common/trans.c index 4beaa56e..8f2c4376 100644 --- a/common/trans.c +++ b/common/trans.c @@ -882,7 +882,7 @@ trans_get_out_s(struct trans *self, int size) /* returns error */ int APP_CC trans_set_tls_mode(struct trans *self, const char *key, const char *cert, - int disableSSLv3, const char *tls_ciphers) + long ssl_protocols, const char *tls_ciphers) { self->tls = ssl_tls_create(self, key, cert); if (self->tls == NULL) @@ -891,7 +891,7 @@ trans_set_tls_mode(struct trans *self, const char *key, const char *cert, return 1; } - if (ssl_tls_accept(self->tls, disableSSLv3, tls_ciphers) != 0) + if (ssl_tls_accept(self->tls, ssl_protocols, tls_ciphers) != 0) { g_writeln("trans_set_tls_mode: ssl_tls_accept failed"); return 1; diff --git a/common/trans.h b/common/trans.h index 26d93dc2..fac1fcab 100644 --- a/common/trans.h +++ b/common/trans.h @@ -125,7 +125,7 @@ struct stream* APP_CC trans_get_out_s(struct trans* self, int size); int APP_CC trans_set_tls_mode(struct trans *self, const char *key, const char *cert, - int disableSSLv3, const char *tls_ciphers); + long ssl_protocols, const char *tls_ciphers); int APP_CC trans_shutdown_tls_mode(struct trans *self); int APP_CC diff --git a/common/xrdp_client_info.h b/common/xrdp_client_info.h index 0ef03cfc..00a56472 100644 --- a/common/xrdp_client_info.h +++ b/common/xrdp_client_info.h @@ -143,7 +143,7 @@ struct xrdp_client_info int use_frame_acks; int max_unacknowledged_frame_count; - int disableSSLv3; /* 0 = no, 1 = yes */ + long ssl_protocols; char tls_ciphers[64]; int client_os_major; diff --git a/libxrdp/xrdp_rdp.c b/libxrdp/xrdp_rdp.c index 5159ba5b..bdb552c8 100644 --- a/libxrdp/xrdp_rdp.c +++ b/libxrdp/xrdp_rdp.c @@ -18,6 +18,7 @@ * rdp layer */ +#include #include "libxrdp.h" #include "log.h" @@ -44,6 +45,8 @@ xrdp_rdp_read_config(struct xrdp_client_info *client_info) char *item = (char *)NULL; char *value = (char *)NULL; char cfg_file[256]; + char *tmp = (char *)NULL; + int tmp_length = 0; /* initialize (zero out) local variables: */ g_memset(cfg_file, 0, sizeof(char) * 256); @@ -160,9 +163,37 @@ xrdp_rdp_read_config(struct xrdp_client_info *client_info) client_info->use_fast_path = 0; } } - else if (g_strcasecmp(item, "disableSSLv3") == 0) + else if (g_strcasecmp(item, "ssl_protocols") == 0) { - client_info->disableSSLv3 = g_text2bool(value); + /* put leading/trailing space to properly detect "TLSv1" without regex */ + tmp_length = g_strlen(value) + 3; + tmp = g_new(char, tmp_length); + g_snprintf(tmp, tmp_length, "%s%s%s", " ", value, " "); + + /* disable all protocols first, enable later */ + client_info->ssl_protocols = + SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 | SSL_OP_NO_TLSv1_2; + + if (g_pos(tmp, " TLSv1.2 ") >= 0) + { + log_message(LOG_LEVEL_DEBUG, "TLSv1.2 enabled"); + client_info->ssl_protocols &= ~SSL_OP_NO_TLSv1_2; + } + if (g_pos(tmp, " TLSv1.1 ") >= 0) + { + log_message(LOG_LEVEL_DEBUG, "TLSv1.1 enabled"); + client_info->ssl_protocols &= ~SSL_OP_NO_TLSv1_1; + } + if (g_pos(tmp, " TLSv1 ") >= 0) + { + log_message(LOG_LEVEL_DEBUG, "TLSv1 enabled"); + client_info->ssl_protocols &= ~SSL_OP_NO_TLSv1; + } + if (g_pos(tmp, " SSLv3 ") >= 0) + { + log_message(LOG_LEVEL_DEBUG, "SSLv3 enabled"); + client_info->ssl_protocols &= ~SSL_OP_NO_SSLv3; + } } else if (g_strcasecmp(item, "tls_ciphers") == 0) { diff --git a/libxrdp/xrdp_sec.c b/libxrdp/xrdp_sec.c index 422acfe2..b5d33863 100644 --- a/libxrdp/xrdp_sec.c +++ b/libxrdp/xrdp_sec.c @@ -2254,7 +2254,7 @@ xrdp_sec_incoming(struct xrdp_sec *self) if (trans_set_tls_mode(self->mcs_layer->iso_layer->trans, self->rdp_layer->client_info.key_file, self->rdp_layer->client_info.certificate, - self->rdp_layer->client_info.disableSSLv3, + self->rdp_layer->client_info.ssl_protocols, self->rdp_layer->client_info.tls_ciphers) != 0) { g_writeln("xrdp_sec_incoming: trans_set_tls_mode failed"); diff --git a/xrdp/xrdp.ini b/xrdp/xrdp.ini index 70e7afb9..ce4df137 100644 --- a/xrdp/xrdp.ini +++ b/xrdp/xrdp.ini @@ -25,8 +25,9 @@ crypt_level=high ; openssl req -x509 -newkey rsa:2048 -nodes -keyout key.pem -out cert.pem -days 365 certificate= key_file= -; specify whether SSLv3 should be disabled -#disableSSLv3=true +; set SSL protocols +; can be space separated list of 'SSLv3', 'TLSv1', 'TLSv1.1', 'TLSv1.2' +ssl_protocols=TLSv1 TLSv1.1 TLSv1.2 ; set TLS cipher suites #tls_ciphers=HIGH