Skip to content

Commit 6c53f5d

Browse files
sydneyliohemorange
authored andcommitted
Turn off session tickets for versions of Nginx that support it (certbot#7092)
* Turn off session tickets for versions of Nginx that support it In line with Mozilla's security recommendations. * Changelog. * Set version before installing config files * lint: remove unused import * windows testfix * another windows testfix? * Testing path of updating src file with old nginx * Fix windows, and make config update tests fail if update doesn't happen
1 parent add90ce commit 6c53f5d

File tree

7 files changed

+77
-28
lines changed

7 files changed

+77
-28
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ Certbot adheres to [Semantic Versioning](https://semver.org/).
66

77
### Added
88

9-
*
9+
* Turn off session tickets for nginx plugin by default
1010

1111
### Changed
1212

certbot-nginx/MANIFEST.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@ include README.rst
33
recursive-include docs *
44
recursive-include certbot_nginx/tests/testdata *
55
include certbot_nginx/options-ssl-nginx.conf
6+
include certbot_nginx/options-ssl-nginx-old.conf

certbot-nginx/certbot_nginx/configurator.py

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
import tempfile
77
import time
88

9+
import pkg_resources
10+
911
import OpenSSL
1012
import zope.interface
1113

@@ -120,6 +122,14 @@ def __init__(self, *args, **kwargs):
120122

121123
self.reverter.recovery_routine()
122124

125+
@property
126+
def mod_ssl_conf_src(self):
127+
"""Full absolute path to SSL configuration file source."""
128+
config_filename = "options-ssl-nginx.conf"
129+
if self.version < (1, 5, 9):
130+
config_filename = "options-ssl-nginx-old.conf"
131+
return pkg_resources.resource_filename("certbot_nginx", config_filename)
132+
123133
@property
124134
def mod_ssl_conf(self):
125135
"""Full absolute path to SSL configuration file."""
@@ -130,6 +140,11 @@ def updated_mod_ssl_conf_digest(self):
130140
"""Full absolute path to digest of updated SSL configuration file."""
131141
return os.path.join(self.config.config_dir, constants.UPDATED_MOD_SSL_CONF_DIGEST)
132142

143+
def install_ssl_options_conf(self, options_ssl, options_ssl_digest):
144+
"""Copy Certbot's SSL options file into the system's config dir if required."""
145+
return common.install_version_controlled_file(options_ssl, options_ssl_digest,
146+
self.mod_ssl_conf_src, constants.ALL_SSL_OPTIONS_HASHES)
147+
133148
# This is called in determine_authenticator and determine_installer
134149
def prepare(self):
135150
"""Prepare the authenticator/installer.
@@ -148,14 +163,14 @@ def prepare(self):
148163

149164
self.parser = parser.NginxParser(self.conf('server-root'))
150165

151-
install_ssl_options_conf(self.mod_ssl_conf, self.updated_mod_ssl_conf_digest)
152-
153-
self.install_ssl_dhparams()
154-
155166
# Set Version
156167
if self.version is None:
157168
self.version = self.get_version()
158169

170+
self.install_ssl_options_conf(self.mod_ssl_conf, self.updated_mod_ssl_conf_digest)
171+
172+
self.install_ssl_dhparams()
173+
159174
# Prevent two Nginx plugins from modifying a config at once
160175
try:
161176
util.lock_dir_until_exit(self.conf('server-root'))
@@ -1131,12 +1146,6 @@ def nginx_restart(nginx_ctl, nginx_conf):
11311146
time.sleep(1)
11321147

11331148

1134-
def install_ssl_options_conf(options_ssl, options_ssl_digest):
1135-
"""Copy Certbot's SSL options file into the system's config dir if required."""
1136-
return common.install_version_controlled_file(options_ssl, options_ssl_digest,
1137-
constants.MOD_SSL_CONF_SRC, constants.ALL_SSL_OPTIONS_HASHES)
1138-
1139-
11401149
def _determine_default_server_root():
11411150
if os.environ.get("CERTBOT_DOCS") == "1":
11421151
default_server_root = "%s or %s" % (constants.LINUX_SERVER_ROOT,

certbot-nginx/certbot_nginx/constants.py

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
"""nginx plugin constants."""
22
import platform
33

4-
import pkg_resources
5-
64
FREEBSD_DARWIN_SERVER_ROOT = "/usr/local/etc/nginx"
75
LINUX_SERVER_ROOT = "/etc/nginx"
86

@@ -21,14 +19,13 @@
2119
MOD_SSL_CONF_DEST = "options-ssl-nginx.conf"
2220
"""Name of the mod_ssl config file as saved in `IConfig.config_dir`."""
2321

24-
MOD_SSL_CONF_SRC = pkg_resources.resource_filename(
25-
"certbot_nginx", "options-ssl-nginx.conf")
26-
"""Path to the nginx mod_ssl config file found in the Certbot
27-
distribution."""
28-
2922
UPDATED_MOD_SSL_CONF_DIGEST = ".updated-options-ssl-nginx-conf-digest.txt"
3023
"""Name of the hash of the updated or informed mod_ssl_conf as saved in `IConfig.config_dir`."""
3124

25+
SSL_OPTIONS_HASHES_NEW = [
26+
'63e2bddebb174a05c9d8a7cf2adf72f7af04349ba59a1a925fe447f73b2f1abf',
27+
]
28+
"""SHA256 hashes of the contents of versions of MOD_SSL_CONF_SRC for nginx >= 1.5.9"""
3229

3330
ALL_SSL_OPTIONS_HASHES = [
3431
'0f81093a1465e3d4eaa8b0c14e77b2a2e93568b0fc1351c2b87893a95f0de87c',
@@ -37,7 +34,7 @@
3734
'7f95624dd95cf5afc708b9f967ee83a24b8025dc7c8d9df2b556bbc64256b3ff',
3835
'394732f2bbe3e5e637c3fb5c6e980a1f1b90b01e2e8d6b7cff41dde16e2a756d',
3936
'4b16fec2bcbcd8a2f3296d886f17f9953ffdcc0af54582452ca1e52f5f776f16',
40-
]
37+
] + SSL_OPTIONS_HASHES_NEW
4138
"""SHA256 hashes of the contents of all versions of MOD_SSL_CONF_SRC"""
4239

4340
def os_constant(key):
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# This file contains important security parameters. If you modify this file
2+
# manually, Certbot will be unable to automatically provide future security
3+
# updates. Instead, Certbot will print and log an error message with a path to
4+
# the up-to-date file that you will need to refer to when manually updating
5+
# this file.
6+
7+
ssl_session_cache shared:le_nginx_SSL:1m;
8+
ssl_session_timeout 1440m;
9+
10+
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
11+
ssl_prefer_server_ciphers on;
12+
13+
ssl_ciphers "ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS";

certbot-nginx/certbot_nginx/options-ssl-nginx.conf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
ssl_session_cache shared:le_nginx_SSL:1m;
88
ssl_session_timeout 1440m;
9+
ssl_session_tickets off;
910

1011
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
1112
ssl_prefer_server_ciphers on;

certbot-nginx/certbot_nginx/tests/configurator_test.py

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
from certbot.compat import os
1414
from certbot.tests import util as certbot_test_util
1515

16-
from certbot_nginx import constants
1716
from certbot_nginx import obj
1817
from certbot_nginx import parser
1918
from certbot_nginx.configurator import _redirect_block_for_domain
@@ -883,12 +882,11 @@ def setUp(self):
883882
self.config_path, self.config_dir, self.work_dir, self.logs_dir)
884883

885884
def _call(self):
886-
from certbot_nginx.configurator import install_ssl_options_conf
887-
install_ssl_options_conf(self.config.mod_ssl_conf, self.config.updated_mod_ssl_conf_digest)
885+
self.config.install_ssl_options_conf(self.config.mod_ssl_conf,
886+
self.config.updated_mod_ssl_conf_digest)
888887

889888
def _current_ssl_options_hash(self):
890-
from certbot_nginx.constants import MOD_SSL_CONF_SRC
891-
return crypto_util.sha256sum(MOD_SSL_CONF_SRC)
889+
return crypto_util.sha256sum(self.config.mod_ssl_conf_src)
892890

893891
def _assert_current_file(self):
894892
self.assertTrue(os.path.isfile(self.config.mod_ssl_conf))
@@ -908,12 +906,32 @@ def test_current_file(self):
908906
self._call()
909907
self._assert_current_file()
910908

909+
def _mock_hash_except_ssl_conf_src(self, fake_hash):
910+
# Write a bad file in place so that update tests fail if no update occurs.
911+
# We're going to pretend this file (the currently installed conf file)
912+
# actually hashes to `fake_hash` for the update tests.
913+
with open(self.config.mod_ssl_conf, "w") as f:
914+
f.write("bogus")
915+
sha256 = crypto_util.sha256sum
916+
def _hash(filename):
917+
return sha256(filename) if filename == self.config.mod_ssl_conf_src else fake_hash
918+
return _hash
919+
911920
def test_prev_file_updates_to_current(self):
912921
from certbot_nginx.constants import ALL_SSL_OPTIONS_HASHES
913-
with mock.patch('certbot.crypto_util.sha256sum') as mock_sha256:
914-
mock_sha256.return_value = ALL_SSL_OPTIONS_HASHES[0]
922+
with mock.patch('certbot.crypto_util.sha256sum',
923+
new=self._mock_hash_except_ssl_conf_src(ALL_SSL_OPTIONS_HASHES[0])):
924+
self._call()
925+
self._assert_current_file()
926+
927+
def test_prev_file_updates_to_current_old_nginx(self):
928+
from certbot_nginx.constants import ALL_SSL_OPTIONS_HASHES, SSL_OPTIONS_HASHES_NEW
929+
self.config.version = (1, 5, 8)
930+
with mock.patch('certbot.crypto_util.sha256sum',
931+
new=self._mock_hash_except_ssl_conf_src(ALL_SSL_OPTIONS_HASHES[0])):
915932
self._call()
916933
self._assert_current_file()
934+
self.assertTrue(self._current_ssl_options_hash() not in SSL_OPTIONS_HASHES_NEW)
917935

918936
def test_manually_modified_current_file_does_not_update(self):
919937
with open(self.config.mod_ssl_conf, "a") as mod_ssl_conf:
@@ -922,7 +940,7 @@ def test_manually_modified_current_file_does_not_update(self):
922940
self._call()
923941
self.assertFalse(mock_logger.warning.called)
924942
self.assertTrue(os.path.isfile(self.config.mod_ssl_conf))
925-
self.assertEqual(crypto_util.sha256sum(constants.MOD_SSL_CONF_SRC),
943+
self.assertEqual(crypto_util.sha256sum(self.config.mod_ssl_conf_src),
926944
self._current_ssl_options_hash())
927945
self.assertNotEqual(crypto_util.sha256sum(self.config.mod_ssl_conf),
928946
self._current_ssl_options_hash())
@@ -937,7 +955,7 @@ def test_manually_modified_past_file_warns(self):
937955
self.assertEqual(mock_logger.warning.call_args[0][0],
938956
"%s has been manually modified; updated file "
939957
"saved to %s. We recommend updating %s for security purposes.")
940-
self.assertEqual(crypto_util.sha256sum(constants.MOD_SSL_CONF_SRC),
958+
self.assertEqual(crypto_util.sha256sum(self.config.mod_ssl_conf_src),
941959
self._current_ssl_options_hash())
942960
# only print warning once
943961
with mock.patch("certbot.plugins.common.logger") as mock_logger:
@@ -950,6 +968,16 @@ def test_current_file_hash_in_all_hashes(self):
950968
"Constants.ALL_SSL_OPTIONS_HASHES must be appended"
951969
" with the sha256 hash of self.config.mod_ssl_conf when it is updated.")
952970

971+
def test_old_nginx_version_uses_old_config(self):
972+
self.config.version = (1, 5, 8)
973+
self.assertEqual(os.path.basename(self.config.mod_ssl_conf_src),
974+
"options-ssl-nginx-old.conf")
975+
self._call()
976+
self._assert_current_file()
977+
self.config.version = (1, 5, 9)
978+
self.assertEqual(os.path.basename(self.config.mod_ssl_conf_src),
979+
"options-ssl-nginx.conf")
980+
953981

954982
class DetermineDefaultServerRootTest(certbot_test_util.ConfigTestCase):
955983
"""Tests for certbot_nginx.configurator._determine_default_server_root."""

0 commit comments

Comments
 (0)