From e94ab10e14edd2f6ca021cb2c77b9f9031665452 Mon Sep 17 00:00:00 2001
From: Koichiro IWAO
Date: Tue, 13 Dec 2016 15:49:13 +0900
Subject: [PATCH] TLS: new method to specify SSL/TLS version
SSL/TLS protocols only listed in ssl_protocols should be used.
The name "ssl_protocols" comes from nginx.
Resolves #428.
---
common/ssl_calls.c | 13 +++++++------
common/ssl_calls.h | 2 +-
common/trans.c | 4 ++--
common/trans.h | 2 +-
common/xrdp_client_info.h | 2 +-
libxrdp/xrdp_rdp.c | 35 +++++++++++++++++++++++++++++++++--
libxrdp/xrdp_sec.c | 2 +-
xrdp/xrdp.ini | 5 +++--
8 files changed, 49 insertions(+), 16 deletions(-)
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