68ecf8
From 6981475bbe11029d88de8294734d7cb29f1d0799 Mon Sep 17 00:00:00 2001
68ecf8
From: Andreas Schneider <asn@samba.org>
68ecf8
Date: Mon, 15 Jun 2020 11:50:16 +0200
68ecf8
Subject: [PATCH] s3:lib:tls: Use better priority lists for modern GnuTLS
68ecf8
68ecf8
We should use the default priority list. That is a good practice,
68ecf8
because TLS protocol hardening and phasing out of legacy algorithms,
68ecf8
is easier to co-ordinate when happens at a single place. See crypto
68ecf8
policies of Fedora.
68ecf8
68ecf8
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14408
68ecf8
68ecf8
Signed-off-by: Andreas Schneider <asn@samba.org>
68ecf8
Reviewed-by: Alexander Bokovoy <ab@samba.org>
68ecf8
(cherry picked from commit 53e3a959b958a3b099df6ecc5f6e294e96bd948e)
68ecf8
---
68ecf8
 docs-xml/smbdotconf/security/tlspriority.xml | 10 ++---
68ecf8
 lib/param/loadparm.c                         | 10 ++++-
68ecf8
 python/samba/tests/docs.py                   | 20 ++++++++++
68ecf8
 source3/param/loadparm.c                     | 11 +++++-
68ecf8
 source4/lib/tls/tls_tstream.c                | 40 +++++++++++++++-----
68ecf8
 wscript_configure_system_gnutls              |  3 ++
68ecf8
 6 files changed, 76 insertions(+), 18 deletions(-)
68ecf8
68ecf8
diff --git a/docs-xml/smbdotconf/security/tlspriority.xml b/docs-xml/smbdotconf/security/tlspriority.xml
68ecf8
index d7214a4c1ea..6d1f0dcb912 100644
68ecf8
--- a/docs-xml/smbdotconf/security/tlspriority.xml
68ecf8
+++ b/docs-xml/smbdotconf/security/tlspriority.xml
68ecf8
@@ -7,15 +7,15 @@
68ecf8
    to be supported in the parts of Samba that use GnuTLS, specifically
68ecf8
    the AD DC.
68ecf8
    </para>
68ecf8
-   <para>The default turns off SSLv3, as this protocol is no longer considered
68ecf8
-   secure after CVE-2014-3566 (otherwise known as POODLE) impacted SSLv3 use
68ecf8
-   in HTTPS applications.
68ecf8
-   </para>
68ecf8
+   <para>The string is appended to the default priority list of GnuTLS.</para>
68ecf8
    <para>The valid options are described in the
68ecf8
    <ulink url="http://gnutls.org/manual/html_node/Priority-Strings.html">GNUTLS
68ecf8
    Priority-Strings documentation at http://gnutls.org/manual/html_node/Priority-Strings.html</ulink>
68ecf8
    </para>
68ecf8
+   <para>By default it will try to find a config file matching "SAMBA", but if
68ecf8
+   that does not exist will use the entry for "SYSTEM" and last fallback to
68ecf8
+   NORMAL. In all cases the SSL3.0 protocol will be disabled.</para>
68ecf8
  </description>
68ecf8
 
68ecf8
- <value type="default">NORMAL:-VERS-SSL3.0</value>
68ecf8
+ <value type="default">@SAMBA,SYSTEM,NORMAL:!-VERS-SSL3.0</value>
68ecf8
 </samba:parameter>
68ecf8
diff --git a/lib/param/loadparm.c b/lib/param/loadparm.c
68ecf8
index 63291283905..8fdd844fbaa 100644
68ecf8
--- a/lib/param/loadparm.c
68ecf8
+++ b/lib/param/loadparm.c
68ecf8
@@ -2803,7 +2803,15 @@ struct loadparm_context *loadparm_init(TALLOC_CTX *mem_ctx)
68ecf8
 	lpcfg_do_global_parameter(lp_ctx, "tls keyfile", "tls/key.pem");
68ecf8
 	lpcfg_do_global_parameter(lp_ctx, "tls certfile", "tls/cert.pem");
68ecf8
 	lpcfg_do_global_parameter(lp_ctx, "tls cafile", "tls/ca.pem");
68ecf8
-	lpcfg_do_global_parameter(lp_ctx, "tls priority", "NORMAL:-VERS-SSL3.0");
68ecf8
+#ifdef HAVE_GNUTLS_SET_DEFAULT_PRIORITY_APPEND
68ecf8
+	lpcfg_do_global_parameter(lp_ctx,
68ecf8
+				  "tls priority",
68ecf8
+				  "@SAMBA,SYSTEM,NORMAL:!-VERS-SSL3.0");
68ecf8
+#else
68ecf8
+	lpcfg_do_global_parameter(lp_ctx,
68ecf8
+				  "tls priority",
68ecf8
+				  "NORMAL:-VERS-SSL3.0");
68ecf8
+#endif
68ecf8
 
68ecf8
 	lpcfg_do_global_parameter(lp_ctx, "nsupdate command", "/usr/bin/nsupdate -g");
68ecf8
 
68ecf8
diff --git a/python/samba/tests/docs.py b/python/samba/tests/docs.py
68ecf8
index 32a16a98fbc..789865221cb 100644
68ecf8
--- a/python/samba/tests/docs.py
68ecf8
+++ b/python/samba/tests/docs.py
68ecf8
@@ -26,6 +26,21 @@ import os
68ecf8
 import subprocess
68ecf8
 import xml.etree.ElementTree as ET
68ecf8
 
68ecf8
+config_h = os.path.join("bin/default/include/config.h")
68ecf8
+config_hash = dict()
68ecf8
+
68ecf8
+if os.path.exists(config_h):
68ecf8
+    config_hash = dict()
68ecf8
+    f = open(config_h, 'r')
68ecf8
+    try:
68ecf8
+        lines = f.readlines()
68ecf8
+        config_hash = dict((x[0], ' '.join(x[1:]))
68ecf8
+                           for x in map(lambda line: line.strip().split(' ')[1:],
68ecf8
+                                        list(filter(lambda line: (line[0:7] == '#define') and (len(line.split(' ')) > 2), lines))))
68ecf8
+    finally:
68ecf8
+        f.close()
68ecf8
+
68ecf8
+have_gnutls_system_config_support = ("HAVE_GNUTLS_SET_DEFAULT_PRIORITY_APPEND" in config_hash)
68ecf8
 
68ecf8
 class TestCase(samba.tests.TestCaseInTempDir):
68ecf8
 
68ecf8
@@ -127,6 +142,11 @@ class SmbDotConfTests(TestCase):
68ecf8
         'smbd max async dosmode',
68ecf8
     ])
68ecf8
 
68ecf8
+    # 'tls priority' has a legacy default value if we don't link against a
68ecf8
+    # modern GnuTLS version.
68ecf8
+    if not have_gnutls_system_config_support:
68ecf8
+        special_cases.add('tls priority')
68ecf8
+
68ecf8
     def setUp(self):
68ecf8
         super(SmbDotConfTests, self).setUp()
68ecf8
         # create a minimal smb.conf file for testparm
68ecf8
diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c
68ecf8
index d3d81f6ece5..2b1a63998d6 100644
68ecf8
--- a/source3/param/loadparm.c
68ecf8
+++ b/source3/param/loadparm.c
68ecf8
@@ -885,8 +885,15 @@ static void init_globals(struct loadparm_context *lp_ctx, bool reinit_globals)
68ecf8
 	lpcfg_string_set(Globals.ctx, &Globals._tls_keyfile, "tls/key.pem");
68ecf8
 	lpcfg_string_set(Globals.ctx, &Globals._tls_certfile, "tls/cert.pem");
68ecf8
 	lpcfg_string_set(Globals.ctx, &Globals._tls_cafile, "tls/ca.pem");
68ecf8
-	lpcfg_string_set(Globals.ctx, &Globals.tls_priority,
68ecf8
-			 "NORMAL:-VERS-SSL3.0");
68ecf8
+#ifdef HAVE_GNUTLS_SET_DEFAULT_PRIORITY_APPEND
68ecf8
+	lpcfg_string_set(Globals.ctx,
68ecf8
+			 &Globals.tls_priority,
68ecf8
+			 "@SAMBA,SYSTEM,NORMAL:!-VERS-SSL3.0");
68ecf8
+#else
68ecf8
+	lpcfg_string_set(Globals.ctx,
68ecf8
+			 &Globals.tls_priority,
68ecf8
+			 "NORMAL!-VERS-SSL3.0");
68ecf8
+#endif
68ecf8
 
68ecf8
 	lpcfg_string_set(Globals.ctx, &Globals.share_backend, "classic");
68ecf8
 
68ecf8
diff --git a/source4/lib/tls/tls_tstream.c b/source4/lib/tls/tls_tstream.c
68ecf8
index 55bca036776..d984addeec5 100644
68ecf8
--- a/source4/lib/tls/tls_tstream.c
68ecf8
+++ b/source4/lib/tls/tls_tstream.c
68ecf8
@@ -1035,16 +1035,26 @@ struct tevent_req *_tstream_tls_connect_send(TALLOC_CTX *mem_ctx,
68ecf8
 		return tevent_req_post(req, ev);
68ecf8
 	}
68ecf8
 
68ecf8
-	ret = gnutls_priority_set_direct(tlss->tls_session,
68ecf8
-					 tls_params->tls_priority,
68ecf8
-					 &error_pos);
68ecf8
+	ret = gnutls_set_default_priority(tlss->tls_session);
68ecf8
 	if (ret != GNUTLS_E_SUCCESS) {
68ecf8
-		DEBUG(0,("TLS %s - %s.  Check 'tls priority' option at '%s'\n",
68ecf8
-			 __location__, gnutls_strerror(ret), error_pos));
68ecf8
+		DBG_ERR("TLS %s - %s. Failed to set default priorities\n",
68ecf8
+			__location__, gnutls_strerror(ret));
68ecf8
 		tevent_req_error(req, EINVAL);
68ecf8
 		return tevent_req_post(req, ev);
68ecf8
 	}
68ecf8
 
68ecf8
+	if (strlen(tls_params->tls_priority) > 0) {
68ecf8
+		ret = gnutls_priority_set_direct(tlss->tls_session,
68ecf8
+						 tls_params->tls_priority,
68ecf8
+						 &error_pos);
68ecf8
+		if (ret != GNUTLS_E_SUCCESS) {
68ecf8
+			DEBUG(0,("TLS %s - %s.  Check 'tls priority' option at '%s'\n",
68ecf8
+				 __location__, gnutls_strerror(ret), error_pos));
68ecf8
+			tevent_req_error(req, EINVAL);
68ecf8
+			return tevent_req_post(req, ev);
68ecf8
+		}
68ecf8
+	}
68ecf8
+
68ecf8
 	ret = gnutls_credentials_set(tlss->tls_session,
68ecf8
 				     GNUTLS_CRD_CERTIFICATE,
68ecf8
 				     tls_params->x509_cred);
68ecf8
@@ -1284,16 +1294,26 @@ struct tevent_req *_tstream_tls_accept_send(TALLOC_CTX *mem_ctx,
68ecf8
 		return tevent_req_post(req, ev);
68ecf8
 	}
68ecf8
 
68ecf8
-	ret = gnutls_priority_set_direct(tlss->tls_session,
68ecf8
-					 tlsp->tls_priority,
68ecf8
-					 &error_pos);
68ecf8
+	ret = gnutls_set_default_priority(tlss->tls_session);
68ecf8
 	if (ret != GNUTLS_E_SUCCESS) {
68ecf8
-		DEBUG(0,("TLS %s - %s.  Check 'tls priority' option at '%s'\n",
68ecf8
-			 __location__, gnutls_strerror(ret), error_pos));
68ecf8
+		DBG_ERR("TLS %s - %s. Failed to set default priorities\n",
68ecf8
+			__location__, gnutls_strerror(ret));
68ecf8
 		tevent_req_error(req, EINVAL);
68ecf8
 		return tevent_req_post(req, ev);
68ecf8
 	}
68ecf8
 
68ecf8
+	if (strlen(tlsp->tls_priority) > 0) {
68ecf8
+		ret = gnutls_priority_set_direct(tlss->tls_session,
68ecf8
+						 tlsp->tls_priority,
68ecf8
+						 &error_pos);
68ecf8
+		if (ret != GNUTLS_E_SUCCESS) {
68ecf8
+			DEBUG(0,("TLS %s - %s.  Check 'tls priority' option at '%s'\n",
68ecf8
+				 __location__, gnutls_strerror(ret), error_pos));
68ecf8
+			tevent_req_error(req, EINVAL);
68ecf8
+			return tevent_req_post(req, ev);
68ecf8
+		}
68ecf8
+	}
68ecf8
+
68ecf8
 	ret = gnutls_credentials_set(tlss->tls_session, GNUTLS_CRD_CERTIFICATE,
68ecf8
 				     tlsp->x509_cred);
68ecf8
 	if (ret != GNUTLS_E_SUCCESS) {
68ecf8
diff --git a/wscript_configure_system_gnutls b/wscript_configure_system_gnutls
68ecf8
index b2b955f3c90..631405fa34c 100644
68ecf8
--- a/wscript_configure_system_gnutls
68ecf8
+++ b/wscript_configure_system_gnutls
68ecf8
@@ -20,6 +20,9 @@ conf.SET_TARGET_TYPE('gnutls', 'SYSLIB')
68ecf8
 # Check for gnutls_pkcs7_get_embedded_data_oid (>= 3.5.5) required by libmscat
68ecf8
 conf.CHECK_FUNCS_IN('gnutls_pkcs7_get_embedded_data_oid', 'gnutls')
68ecf8
 
68ecf8
+# Check for gnutls_set_default_priority_append (>= 3.6.3)
68ecf8
+conf.CHECK_FUNCS_IN('gnutls_set_default_priority_append', 'gnutls')
68ecf8
+
68ecf8
 # Check for gnutls_aead_cipher_encryptv2
68ecf8
 #
68ecf8
 # This is available since version 3.6.10, but 3.6.10 has a bug which got fixed
68ecf8
-- 
68ecf8
2.27.0
68ecf8