def _create_challenge_dirs(self): path_map = self.conf("map") if not path_map: raise errors.PluginError( "Missing parts of webroot configuration; please set either " "--webroot-path and --domains, or --webroot-map. Run with " " --help webroot for examples.") for name, path in path_map.items(): self.full_roots[name] = os.path.join(path, os.path.normcase( challenges.HTTP01.URI_ROOT_PATH)) logger.debug("Creating root challenges validation dir at %s", self.full_roots[name]) # Change the permissions to be writable (GH #1389) # Umask is used instead of chmod to ensure the client can also # run as non-root (GH #1795) old_umask = filesystem.umask(0o022) try: # We ignore the last prefix in the next iteration, # as it does not correspond to a folder path ('/' or 'C:') for prefix in sorted(util.get_prefixes(self.full_roots[name])[:-1], key=len): if os.path.isdir(prefix): # Don't try to create directory if it already exists, as some filesystems # won't reliably raise EEXIST or EISDIR if directory exists. continue try: # Set owner as parent directory if possible, apply mode for Linux/Windows. # For Linux, this is coupled with the "umask" call above because # os.mkdir's "mode" parameter may not always work: # https://docs.python.org/3/library/os.html#os.mkdir filesystem.mkdir(prefix, 0o755) self._created_dirs.append(prefix) try: filesystem.copy_ownership_and_apply_mode( path, prefix, 0o755, copy_user=True, copy_group=True) except (OSError, AttributeError) as exception: logger.warning("Unable to change owner and uid of webroot directory") logger.debug("Error was: %s", exception) except OSError as exception: raise errors.PluginError( "Couldn't create root for {0} http-01 " "challenge responses: {1}".format(name, exception)) finally: filesystem.umask(old_umask) # On Windows, generate a local web.config file that allows IIS to serve expose # challenge files despite the fact they do not have a file extension. if not filesystem.POSIX_MODE: web_config_path = os.path.join(self.full_roots[name], "web.config") if os.path.exists(web_config_path): logger.info("A web.config file has not been created in " "%s because another one already exists.", self.full_roots[name]) continue logger.info("Creating a web.config file in %s to allow IIS " "to serve challenge files.", self.full_roots[name]) with safe_open(web_config_path, mode="w", chmod=0o644) as web_config: web_config.write(_WEB_CONFIG_CONTENT)
def test_makedirs_correct_permissions(self): path = os.path.join(self.tempdir, 'dir') subpath = os.path.join(path, 'subpath') previous_umask = filesystem.umask(0o022) try: filesystem.makedirs(subpath, 0o700) assert filesystem.check_mode(path, 0o700) assert filesystem.check_mode(subpath, 0o700) finally: filesystem.umask(previous_umask)
def _set_up_challenges(self): if not os.path.isdir(self.challenge_dir): old_umask = filesystem.umask(0o022) try: filesystem.makedirs(self.challenge_dir, 0o755) except OSError as exception: if exception.errno not in (errno.EEXIST, errno.EISDIR): raise errors.PluginError( "Couldn't create root for http-01 challenge") finally: filesystem.umask(old_umask) responses = [] for achall in self.achalls: responses.append(self._set_up_challenge(achall)) return responses
def _perform_single(self, achall): response, validation = achall.response_and_validation() root_path = self.full_roots[achall.domain] validation_path = self._get_validation_path(root_path, achall) logger.debug("Attempting to save validation to %s", validation_path) # Change permissions to be world-readable, owner-writable (GH #1795) old_umask = filesystem.umask(0o022) try: with safe_open(validation_path, mode="wb", chmod=0o644) as validation_file: validation_file.write(validation.encode()) finally: filesystem.umask(old_umask) self.performed[root_path].add(achall) return response
def test_umask_on_file(self): previous_umask = filesystem.umask(0o022) try: file1 = os.path.join(self.tempdir, 'probe1') UmaskTest._create_file(file1) self.assertTrue(filesystem.check_mode(file1, 0o755)) filesystem.umask(0o077) file2 = os.path.join(self.tempdir, 'probe2') UmaskTest._create_file(file2) self.assertTrue(filesystem.check_mode(file2, 0o700)) file3 = os.path.join(self.tempdir, 'probe3') UmaskTest._create_file(file3) self.assertTrue(filesystem.check_mode(file3, 0o700)) finally: filesystem.umask(previous_umask)
def test_umask_on_dir(self): previous_umask = filesystem.umask(0o022) try: dir1 = os.path.join(self.tempdir, 'probe1') filesystem.mkdir(dir1) self.assertTrue(filesystem.check_mode(dir1, 0o755)) filesystem.umask(0o077) dir2 = os.path.join(self.tempdir, 'dir2') filesystem.mkdir(dir2) self.assertTrue(filesystem.check_mode(dir2, 0o700)) dir3 = os.path.join(self.tempdir, 'dir3') filesystem.mkdir(dir3, mode=0o777) self.assertTrue(filesystem.check_mode(dir3, 0o700)) finally: filesystem.umask(previous_umask)