예제 #1
0
 def test_manually_modified_current_file_does_not_update(self):
     with open(self.config.mod_ssl_conf, "a") as mod_ssl_conf:
         mod_ssl_conf.write("a new line for the wrong hash\n")
     with mock.patch("certbot.plugins.common.logger") as mock_logger:
         self._call()
         self.assertFalse(mock_logger.warning.called)
     self.assertTrue(os.path.isfile(self.config.mod_ssl_conf))
     self.assertEqual(crypto_util.sha256sum(constants.MOD_SSL_CONF_SRC),
         self._current_ssl_options_hash())
     self.assertNotEqual(crypto_util.sha256sum(self.config.mod_ssl_conf),
         self._current_ssl_options_hash())
예제 #2
0
 def test_manually_modified_current_file_does_not_update(self):
     self._call()
     with open(self.dest_path, "a") as mod_ssl_conf:
         mod_ssl_conf.write("a new line for the wrong hash\n")
     with mock.patch("certbot.plugins.common.logger") as mock_logger:
         self._call()
         self.assertFalse(mock_logger.warning.called)
     self.assertTrue(os.path.isfile(self.dest_path))
     self.assertEqual(crypto_util.sha256sum(self.source_path),
         self._current_file_hash())
     self.assertNotEqual(crypto_util.sha256sum(self.dest_path),
         self._current_file_hash())
예제 #3
0
def install_ssl_options_conf(options_ssl, options_ssl_digest, mod_ssl_conf_src,
    all_ssl_options_hashes):
    """Copy Certbot's SSL options file into the system's config dir if required.

       :param str options_ssl: destination path for file containing ssl options
       :param str options_ssl_digest: path to save a digest of options_ssl in
       :param str mod_ssl_conf_src: path to file containing ssl options found in distribution
       :param list all_ssl_options_hashes: hashes of every released version of options_ssl
    """
    current_ssl_options_hash = crypto_util.sha256sum(mod_ssl_conf_src)

    def _write_current_hash():
        with open(options_ssl_digest, "w") as f:
            f.write(current_ssl_options_hash)

    def _install_current_file():
        shutil.copyfile(mod_ssl_conf_src, options_ssl)
        _write_current_hash()

    # Check to make sure options-ssl.conf is installed
    if not os.path.isfile(options_ssl):
        _install_current_file()
        return
    # there's already a file there. if it's up to date, do nothing. if it's not but
    # it matches a known file hash, we can update it.
    # otherwise, print a warning once per new version.
    active_file_digest = crypto_util.sha256sum(options_ssl)
    if active_file_digest == current_ssl_options_hash: # already up to date
        return
    elif active_file_digest in all_ssl_options_hashes: # safe to update
        _install_current_file()
    else: # has been manually modified, not safe to update
        # did they modify the current version or an old version?
        if os.path.isfile(options_ssl_digest):
            with open(options_ssl_digest, "r") as f:
                saved_digest = f.read()
            # they modified it after we either installed or told them about this version, so return
            if saved_digest == current_ssl_options_hash:
                return
        # there's a new version but we couldn't update the file, or they deleted the digest.
        # save the current digest so we only print this once, and print a warning
        _write_current_hash()
        logger.warning("%s has been manually modified; updated ssl configuration options "
            "saved to %s. We recommend updating %s for security purposes.",
            options_ssl, mod_ssl_conf_src, options_ssl)
예제 #4
0
def install_version_controlled_file(dest_path, digest_path, src_path, all_hashes):
    """Copy a file into an active location (likely the system's config dir) if required.

       :param str dest_path: destination path for version controlled file
       :param str digest_path: path to save a digest of the file in
       :param str src_path: path to version controlled file found in distribution
       :param list all_hashes: hashes of every released version of the file
    """
    current_hash = crypto_util.sha256sum(src_path)

    def _write_current_hash():
        with open(digest_path, "w") as f:
            f.write(current_hash)

    def _install_current_file():
        shutil.copyfile(src_path, dest_path)
        _write_current_hash()

    # Check to make sure options-ssl.conf is installed
    if not os.path.isfile(dest_path):
        _install_current_file()
        return
    # there's already a file there. if it's up to date, do nothing. if it's not but
    # it matches a known file hash, we can update it.
    # otherwise, print a warning once per new version.
    active_file_digest = crypto_util.sha256sum(dest_path)
    if active_file_digest == current_hash: # already up to date
        return
    elif active_file_digest in all_hashes: # safe to update
        _install_current_file()
    else: # has been manually modified, not safe to update
        # did they modify the current version or an old version?
        if os.path.isfile(digest_path):
            with open(digest_path, "r") as f:
                saved_digest = f.read()
            # they modified it after we either installed or told them about this version, so return
            if saved_digest == current_hash:
                return
        # there's a new version but we couldn't update the file, or they deleted the digest.
        # save the current digest so we only print this once, and print a warning
        _write_current_hash()
        logger.warning("%s has been manually modified; updated file "
            "saved to %s. We recommend updating %s for security purposes.",
            dest_path, src_path, dest_path)
예제 #5
0
 def setUp(self):
     super(InstallSslOptionsConfTest, self).setUp()
     self.hashes = ["someotherhash"]
     self.dest_path = os.path.join(self.tempdir, "options-ssl-dest.conf")
     self.hash_path = os.path.join(self.tempdir, ".options-ssl-conf.txt")
     self.old_path = os.path.join(self.tempdir, "options-ssl-old.conf")
     self.source_path = os.path.join(self.tempdir, "options-ssl-src.conf")
     for path in (self.source_path, self.old_path,):
         with open(path, "w") as f:
             f.write(path)
         self.hashes.append(crypto_util.sha256sum(path))
예제 #6
0
 def setUp(self):
     super().setUp()
     self.hashes = ["someotherhash"]
     self.dest_path = os.path.join(self.tempdir, "options-ssl-dest.conf")
     self.hash_path = os.path.join(self.tempdir, ".options-ssl-conf.txt")
     self.old_path = os.path.join(self.tempdir, "options-ssl-old.conf")
     self.source_path = os.path.join(self.tempdir, "options-ssl-src.conf")
     for path in (
             self.source_path,
             self.old_path,
     ):
         with open(path, "w") as f:
             f.write(path)
         self.hashes.append(crypto_util.sha256sum(path))
예제 #7
0
 def test_manually_modified_past_file_warns(self):
     with open(self.dest_path, "a") as mod_ssl_conf:
         mod_ssl_conf.write("a new line for the wrong hash\n")
     with open(self.hash_path, "w") as f:
         f.write("hashofanoldversion")
     with mock.patch("certbot.plugins.common.logger") as mock_logger:
         self._call()
         self.assertEqual(mock_logger.warning.call_args[0][0],
             "%s has been manually modified; updated file "
             "saved to %s. We recommend updating %s for security purposes.")
     self.assertEqual(crypto_util.sha256sum(self.source_path),
         self._current_file_hash())
     # only print warning once
     with mock.patch("certbot.plugins.common.logger") as mock_logger:
         self._call()
         self.assertFalse(mock_logger.warning.called)
예제 #8
0
 def test_manually_modified_past_file_warns(self):
     with open(self.config.mod_ssl_conf, "a") as mod_ssl_conf:
         mod_ssl_conf.write("a new line for the wrong hash\n")
     with open(self.config.updated_mod_ssl_conf_digest, "w") as f:
         f.write("hashofanoldversion")
     with mock.patch("certbot.plugins.common.logger") as mock_logger:
         self._call()
         self.assertEqual(mock_logger.warning.call_args[0][0],
             "%s has been manually modified; updated ssl configuration options "
             "saved to %s. We recommend updating %s for security purposes.")
     self.assertEqual(crypto_util.sha256sum(constants.MOD_SSL_CONF_SRC),
         self._current_ssl_options_hash())
     # only print warning once
     with mock.patch("certbot.plugins.common.logger") as mock_logger:
         self._call()
         self.assertFalse(mock_logger.warning.called)
예제 #9
0
 def test_manually_modified_past_file_warns(self):
     with open(self.config.mod_ssl_conf, "a") as mod_ssl_conf:
         mod_ssl_conf.write("a new line for the wrong hash\n")
     with open(self.config.updated_mod_ssl_conf_digest, "w") as f:
         f.write("hashofanoldversion")
     with mock.patch("certbot.plugins.common.logger") as mock_logger:
         self._call()
         self.assertEqual(mock_logger.warning.call_args[0][0],
             "%s has been manually modified; updated file "
             "saved to %s. We recommend updating %s for security purposes.")
     self.assertEqual(crypto_util.sha256sum(constants.MOD_SSL_CONF_SRC),
         self._current_ssl_options_hash())
     # only print warning once
     with mock.patch("certbot.plugins.common.logger") as mock_logger:
         self._call()
         self.assertFalse(mock_logger.warning.called)
예제 #10
0
    def test_foreign_webconfig_file_handling(self, mock_get_utility):
        mock_display = mock_get_utility()
        mock_display.menu.return_value = (
            display_util.OK,
            1,
        )

        challenge_path = os.path.join(self.path, ".well-known",
                                      "acme-challenge")
        filesystem.makedirs(challenge_path)

        webconfig_path = os.path.join(challenge_path, "web.config")
        with open(webconfig_path, "w") as file:
            file.write("something")
        self.auth.perform([self.achall])
        from certbot import crypto_util
        webconfig_hash = crypto_util.sha256sum(webconfig_path)
        from certbot._internal.plugins.webroot import _WEB_CONFIG_SHA256SUMS
        self.assertTrue(webconfig_hash not in _WEB_CONFIG_SHA256SUMS)
예제 #11
0
 def test_ssl_config_files_hash_in_all_hashes(self):
     """
     It is really critical that all TLS Nginx config files have their SHA256 hash registered in
     constants.ALL_SSL_OPTIONS_HASHES. Otherwise Certbot will mistakenly assume that the config
     file has been manually edited by the user, and will refuse to update it.
     This test ensures that all necessary hashes are present.
     """
     from certbot_nginx.constants import ALL_SSL_OPTIONS_HASHES
     import pkg_resources
     all_files = [
         pkg_resources.resource_filename("certbot_nginx", x)
         for x in ("options-ssl-nginx.conf", "options-ssl-nginx-old.conf",
                   "options-ssl-nginx-tls12-only.conf")
     ]
     self.assertTrue(all_files)
     for one_file in all_files:
         file_hash = crypto_util.sha256sum(one_file)
         self.assertTrue(
             file_hash in ALL_SSL_OPTIONS_HASHES,
             "Constants.ALL_SSL_OPTIONS_HASHES must be appended with the sha256 "
             "hash of {0} when it is updated.".format(one_file))
예제 #12
0
    def cleanup(self, achalls):  # pylint: disable=missing-function-docstring
        for achall in achalls:
            root_path = self.full_roots.get(achall.domain, None)
            if root_path is not None:
                validation_path = self._get_validation_path(root_path, achall)
                logger.debug("Removing %s", validation_path)
                os.remove(validation_path)
                self.performed[root_path].remove(achall)

                if not filesystem.POSIX_MODE:
                    web_config_path = os.path.join(root_path, "web.config")
                    if os.path.exists(web_config_path):
                        sha256sum = crypto_util.sha256sum(web_config_path)
                        if sha256sum in _WEB_CONFIG_SHA256SUMS:
                            logger.info(
                                "Cleaning web.config file generated by Certbot in %s.",
                                root_path)
                            os.remove(web_config_path)
                        else:
                            logger.info(
                                "Not cleaning up the web.config file in %s "
                                "because it is not generated by Certbot.",
                                root_path)

        not_removed: List[str] = []
        while self._created_dirs:
            path = self._created_dirs.pop()
            try:
                os.rmdir(path)
            except OSError as exc:
                not_removed.insert(0, path)
                logger.info(
                    "Challenge directory %s was not empty, didn't remove",
                    path)
                logger.debug("Error was: %s", exc)
        self._created_dirs = not_removed
        logger.debug("All challenges cleaned up")
예제 #13
0
 def _assert_current_file(self):
     self.assertTrue(os.path.isfile(self.dest_path))
     self.assertEqual(crypto_util.sha256sum(self.dest_path),
         self._current_ssl_options_hash())
예제 #14
0
 def _current_ssl_options_hash(self):
     from certbot_nginx.constants import MOD_SSL_CONF_SRC
     return crypto_util.sha256sum(MOD_SSL_CONF_SRC)
예제 #15
0
 def test_sha256sum(self):
     from certbot.crypto_util import sha256sum
     self.assertEqual(sha256sum(CERT_PATH),
         '914ffed8daf9e2c99d90ac95c77d54f32cbd556672facac380f0c063498df84e')
예제 #16
0
 def _current_ssl_dhparams_hash(self):
     from certbot.constants import SSL_DHPARAMS_SRC
     return crypto_util.sha256sum(SSL_DHPARAMS_SRC)
예제 #17
0
 def _current_file_hash(self):
     return crypto_util.sha256sum(self.source_path)
예제 #18
0
 def _assert_current_file(self):
     self.assertTrue(os.path.isfile(self.config.mod_ssl_conf))
     self.assertEqual(crypto_util.sha256sum(self.config.mod_ssl_conf),
         self._current_ssl_options_hash())
예제 #19
0
 def _assert_current_file(self):
     self.assertTrue(os.path.isfile(self.config.mod_ssl_conf))
     self.assertEqual(crypto_util.sha256sum(self.config.mod_ssl_conf),
                      self._current_ssl_options_hash())
예제 #20
0
 def test_sha256sum(self):
     from certbot.crypto_util import sha256sum
     self.assertEqual(
         sha256sum(CERT_PATH),
         '914ffed8daf9e2c99d90ac95c77d54f32cbd556672facac380f0c063498df84e')
예제 #21
0
 def _current_ssl_options_hash(self):
     return crypto_util.sha256sum(self.source_path)
예제 #22
0
 def _current_ssl_options_hash(self):
     return crypto_util.sha256sum(self.config.mod_ssl_conf_src)
예제 #23
0
 def _current_ssl_options_hash(self):
     return crypto_util.sha256sum(self.source_path)
예제 #24
0
 def _current_ssl_dhparams_hash(self):
     from certbot._internal.constants import SSL_DHPARAMS_SRC
     return crypto_util.sha256sum(SSL_DHPARAMS_SRC)
예제 #25
0
 def _current_ssl_options_hash(self):
     from certbot_nginx.constants import MOD_SSL_CONF_SRC
     return crypto_util.sha256sum(MOD_SSL_CONF_SRC)