From 49fe7e2a32f11c782915d6d3eb845deb5e591578 Mon Sep 17 00:00:00 2001 From: James Kasten Date: Wed, 22 May 2013 16:56:52 -0400 Subject: [PATCH] Standardized safe directory creation, created trustify_util.py for common functions --- trustify/client/client.py | 36 +++++--------------------- trustify/client/configurator.py | 32 +++++------------------ trustify/client/trustify_util.py | 44 ++++++++++++++++++++++++++++++++ 3 files changed, 56 insertions(+), 56 deletions(-) create mode 100644 trustify/client/trustify_util.py diff --git a/trustify/client/client.py b/trustify/client/client.py index fe2a45ec9..b0b4c8e63 100644 --- a/trustify/client/client.py +++ b/trustify/client/client.py @@ -116,12 +116,12 @@ class Client(object): for chall in challenges: chall.cleanup() cert_chain_abspath = None - cert_fd, cert_fn = unique_file(cert_file, 644) + cert_fd, cert_fn = trustify_util.unique_file(cert_file, 644) cert_fd.write(r.success.certificate) cert_fd.close() logger.info("Server issued certificate; certificate written to %s" % cert_fn) if r.success.chain: - chain_fd, chain_fn = unique_file(chain_file, 644) + chain_fd, chain_fn = trustify_util.unique_file(chain_file, 644) chain_fd.write(r.success.chain) chain_fd.close() @@ -313,9 +313,8 @@ class Client(object): if not self.key_file: key_pem = self.make_key(RSA_KEY_SIZE) # Save file - if not os.path.isdir(KEY_DIR): - os.makedirs(KEY_DIR, 0700) - key_f, self.key_file = unique_file(KEY_DIR + "key-trustify.pem", 0600) + trustify_util.make_or_verify_dir(KEY_DIR, 0700) + key_f, self.key_file = trustify_util.unique_file(KEY_DIR + "key-trustify.pem", 0600) key_f.write(key_pem) key_f.close() logger.info("Generating key: %s" % self.key_file) @@ -329,9 +328,8 @@ class Client(object): if not self.csr_file: csr_pem = self.make_csr(self.names) # Save CSR - if not os.path.isdir(CERT_DIR): - os.makedirs(CERT_DIR, 0755) - csr_f, self.csr_file = unique_file(CERT_DIR + "csr-trustify.pem", 0644) + trustify_util.make_or_verify_dir(CERT_DIR, 0755) + csr_f, self.csr_file = trustify_util.unique_file(CERT_DIR + "csr-trustify.pem", 0644) csr_f.write(csr_pem) csr_f.close() logger.info("Creating CSR: %s" % self.csr_file) @@ -596,13 +594,6 @@ def sha256(m): # m.chocolateversion = 1 # m.session = "" -def drop_privs(): - nogroup = grp.getgrnam("nogroup").gr_gid - nobody = pwd.getpwnam("nobody").pw_uid - os.setgid(nogroup) - os.setgroups([]) - os.setuid(nobody) - # def make_request(server, m, csr, names, quiet=False): # m.request.recipient = server # m.request.timestamp = int(time.time()) @@ -667,21 +658,6 @@ def recognized_ca(issuer): def gen_req_from_cert(): return -def unique_file(default_name, mode = 0777): - """ - Safely finds a unique file for writing only (by default) - """ - count = 1 - f_parsed = os.path.splitext(default_name) - while 1: - try: - fd = os.open(default_name, os.O_CREAT|os.O_EXCL|os.O_RDWR, mode) - return os.fdopen(fd, 'w'), default_name - except OSError: - pass - default_name = f_parsed[0] + '_' + str(count) + f_parsed[1] - count += 1 - # def gen_https_names(domains): # """ # Returns a string of the domains formatted nicely with https:// prepended diff --git a/trustify/client/configurator.py b/trustify/client/configurator.py index 877287a74..e640052a2 100644 --- a/trustify/client/configurator.py +++ b/trustify/client/configurator.py @@ -38,7 +38,7 @@ from trustify.client import logger # TODO: Make IfModule completely case-insensitive # TODO: Checkpoints are not registering the creaton of enable_site -# This results in broken links in sites-enabled +# This results in broken links in sites-enabled on revert class VH(object): def __init__(self, filename_path, vh_path, vh_addrs, is_ssl, is_enabled): @@ -906,25 +906,9 @@ LogLevel warn \n\ Aim for defensive coding... make sure all input files have permissions of root ''' - self.__make_or_verify_restricted_dir(CONFIG_DIR) - self.__make_or_verify_restricted_dir(WORK_DIR) - self.__make_or_verify_restricted_dir(BACKUP_DIR) - - def __make_or_verify_restricted_dir(self, directory, permissions=0755): - if os.path.isdir(directory): - if not self.__check_permissions(directory, permissions): - logger.fatal(directory + " exists and does not contain the proper permissions or owner (root)") - sys.exit(57) - else: - # If this throws errors... meaning a race condition attack. - # Allow program to fail... - os.makedirs(directory, permissions) - - def __check_permissions(self, filepath, mode, uid=0): - file_stat = os.stat(filepath) - if stat.S_IMODE(file_stat.st_mode) != mode: - return False - return file_stat.st_uid == uid + trustify_util.make_or_verify_dir(CONFIG_DIR, 0755) + trustify_util.make_or_verify_dir(WORK_DIR, 0755) + trustify_util.make_or_verify_dir(BACKUP_DIR, 0755) def standardize_excl(self): """ @@ -1124,12 +1108,8 @@ LogLevel warn \n\ return True def __add_to_checkpoint(self, cp_dir, save_files): - try: - os.makedirs(cp_dir) - except OSError as exception: - if exception.errno != errno.EEXIST: - raise - + trustify_util.make_or_verify_dir(cp_dir, 0755) + existing_filepaths = [] op_fd = None # Open up FILEPATHS differently depending on if it already exists diff --git a/trustify/client/trustify_util.py b/trustify/client/trustify_util.py new file mode 100644 index 000000000..cc9e449ba --- /dev/null +++ b/trustify/client/trustify_util.py @@ -0,0 +1,44 @@ +# This file will contain functions useful for all Trustify Classes +import errno +import stat +import os, pwd, grp +from trustify.client import logger + +def make_or_verify_dir(directory, permissions=0755, uid=0): + try: + os.makedirs(directory, permissions) + except OSError as exception: + if exception.errno == errno.EEXIST: + if not check_permissions(directory, permissions, uid): + logger.fatal("%s exists and does not contain the proper permissions or owner" % directory) + sys.exit(57) + else: + raise + +def check_permissions(filepath, mode, uid=0): + file_stat = os.stat(filepath) + if stat.S_IMODE(file_stat.st_mode) != mode: + return False + return file_stat.st_uid == uid + +def unique_file(default_name, mode = 0777): + """ + Safely finds a unique file for writing only (by default) + """ + count = 1 + f_parsed = os.path.splitext(default_name) + while 1: + try: + fd = os.open(default_name, os.O_CREAT|os.O_EXCL|os.O_RDWR, mode) + return os.fdopen(fd, 'w'), default_name + except OSError: + pass + default_name = f_parsed[0] + '_' + str(count) + f_parsed[1] + count += 1 + +def drop_privs(): + nogroup = grp.getgrnam("nogroup").gr_gid + nobody = pwd.getpwnam("nobody").pw_uid + os.setgid(nogroup) + os.setgroups([]) + os.setuid(nobody)