Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
"""Validators to determine the current webserver configuration"""
import logging
import socket
import requests
import zope.interface
from acme import crypto_util
from acme import errors as acme_errors
from certbot import interfaces
logger = logging.getLogger(__name__)
@zope.interface.implementer(interfaces.IValidator)
class Validator(object):
# pylint: disable=no-self-use
"""Collection of functions to test a live webserver's configuration"""
def certificate(self, cert, name, alt_host=None, port=443):
"""Verifies the certificate presented at name is cert"""
host = alt_host if alt_host else socket.gethostbyname(name)
try:
presented_cert = crypto_util.probe_sni(name, host, port)
except acme_errors.Error as error:
logger.exception(error)
return False
return presented_cert.digest("sha256") == cert.digest("sha256")
def redirect(self, name, port=80, headers=None):
def load_config(self):
"""Returns the next config directory to be tested"""
shutil.rmtree(self.le_config.work_dir, ignore_errors=True)
backup = os.path.join(self.le_config.work_dir, constants.BACKUP_DIR)
os.makedirs(backup)
return self._configs.pop()
def get_version(self):
"""Return version of Apache Server.
Version is returned as tuple. (ie. 2.4.7 = (2, 4, 7))
:returns: version
:rtype: tuple
:raises .PluginError: if unable to find Apache version
"""
try:
stdout, _ = le_util.run_script(
constants.os_constant("version_cmd"))
except errors.SubprocessError:
raise errors.PluginError(
"Unable to run %s -v" %
constants.os_constant("version_cmd"))
regex = re.compile(r"Apache/([0-9\.]*)", re.IGNORECASE)
matches = regex.findall(stdout)
if len(matches) != 1:
raise errors.PluginError("Unable to find Apache version")
return tuple([int(i) for i in matches[0].split(".")])
ssl_matches = ssl_regex.findall(text)
if not version_matches:
raise errors.PluginError("Unable to find Nginx version")
if not ssl_matches:
raise errors.PluginError(
"Nginx build is missing SSL module (--with-http_ssl_module).")
if not sni_matches:
raise errors.PluginError("Nginx build doesn't support SNI")
nginx_version = tuple([int(i) for i in version_matches[0].split(".")])
# nginx < 0.8.48 uses machine hostname as default server_name instead of
# the empty string
if nginx_version < (0, 8, 48):
raise errors.NotSupportedError("Nginx version must be 0.8.48+")
return nginx_version
multiple candidates are found.
:param list ifaces: Interfaces that plugins must provide.
:returns: Initialized plugin.
:rtype: IPlugin
"""
if default is not None:
# throw more UX-friendly error if default not in plugins
filtered = plugins.filter(lambda p_ep: p_ep.name == default)
else:
if config.noninteractive_mode:
# it's really bad to auto-select the single available plugin in
# non-interactive mode, because an update could later add a second
# available plugin
raise errors.MissingCommandlineFlag(
"Missing command line flags. For non-interactive execution, "
"you will need to specify a plugin on the command line. Run "
"with '--help plugins' to see a list of options, and see "
"https://eff.org/letsencrypt-plugins for more detail on what "
"the plugins do and how to use them.")
filtered = plugins.visible().ifaces(ifaces)
filtered.init(config)
verified = filtered.verify(ifaces)
verified.prepare()
prepared = verified.available()
if len(prepared) > 1:
logger.debug("Multiple candidate plugins: %s", prepared)
plugin_ep = choose_plugin(list(six.itervalues(prepared)), question)
def config_test(self): # pylint: disable=no-self-use
"""Check the configuration of Nginx for errors.
:raises .errors.MisconfigurationError: If config_test fails
"""
try:
util.run_script([self.conf('ctl'), "-c", self.nginx_conf, "-t"])
except errors.SubprocessError as err:
raise errors.MisconfigurationError(str(err))
def config_test(self): # pylint: disable=no-self-use
"""Check the configuration of Apache for errors.
:raises .errors.MisconfigurationError: If config_test fails
"""
try:
util.run_script(self.option("conftest_cmd"))
except errors.SubprocessError as err:
raise errors.MisconfigurationError(str(err))
def test(self):
"""Make sure the configuration is valid.
:raises .MisconfigurationError: if the config is invalid
"""
try:
self._call(["check"])
except subprocess.CalledProcessError as e:
print e
raise errors.MisconfigurationError(
"Postfix failed internal configuration check.")
def _try_restart_fedora(self):
"""
Tries to restart httpd using systemctl to generate the self signed keypair.
"""
try:
util.run_script(['systemctl', 'restart', 'httpd'])
except errors.SubprocessError as err:
raise errors.MisconfigurationError(str(err))
# Finish with actual config check to see if systemctl restart helped
super(CentOSConfigurator, self).config_test()
def _lock_config_dir(self):
"""Stop two Postfix plugins from modifying the config at once.
:raises .PluginError: if unable to acquire the lock
"""
try:
certbot_util.lock_dir_until_exit(self.config_dir)
except (OSError, errors.LockError) as e:
logger.debug("Encountered error:", exc_info=True)
raise errors.PluginError(
"Unable to lock %s", self.config_dir)