def register_file_creation(self, temporary, *files):
        """Register the creation of all files during letsencrypt execution.

        Call this method before writing to the file to make sure that the
        file will be cleaned up if the program exits unexpectedly.
        (Before a save occurs)

        :param bool temporary: If the file creation registry is for
            a temp or permanent save.

        :param \*files: file paths (str) to be registered

        """
        if temporary:
            cp_dir = self.direc["temp"]
        else:
            cp_dir = self.direc["progress"]

        le_util.make_or_verify_dir(cp_dir)
        try:
            with open(os.path.join(cp_dir, "NEW_FILES"), 'a') as new_fd:
                for file_path in files:
                    new_fd.write("%s\n" % file_path)
        except (IOError, OSError):
            logging.error("ERROR: Unable to register file creation")
def init_save_key(key_size, key_dir, keyname="key-letsencrypt.pem"):
    """Initializes and saves a privkey.

    Inits key and saves it in PEM format on the filesystem.

    .. note:: keyname is the attempted filename, it may be different if a file
        already exists at the path.

    :param int key_size: RSA key size in bits
    :param str key_dir: Key save directory.
    :param str keyname: Filename of key

    :returns: Key
    :rtype: :class:`letsencrypt.client.le_util.Key`

    :raises ValueError: If unable to generate the key given key_size.

    """
    try:
        key_pem = make_key(key_size)
    except ValueError as err:
        logging.fatal(str(err))
        raise err

    # Save file
    le_util.make_or_verify_dir(key_dir, 0o700, os.geteuid())
    key_f, key_path = le_util.unique_file(
        os.path.join(key_dir, keyname), 0o600)
    key_f.write(key_pem)
    key_f.close()

    logging.info("Generating key (%d bits): %s", key_size, key_path)

    return le_util.Key(key_path, key_pem)
    def add_to_checkpoint(self, cp_dir, save_files):
        """Add save files to checkpoint directory.

        :param str cp_dir: Checkpoint directory filepath
        :param set save_files: set of files to save

        """
        le_util.make_or_verify_dir(cp_dir, 0o755, os.geteuid())

        existing_filepaths = []
        op_fd = None
        filepaths_path = os.path.join(cp_dir, "FILEPATHS")

        # Open up FILEPATHS differently depending on if it already exists
        if os.path.isfile(filepaths_path):
            op_fd = open(filepaths_path, 'r+')
            existing_filepaths = op_fd.read().splitlines()
        else:
            op_fd = open(filepaths_path, 'w')

        idx = len(existing_filepaths)
        for filename in save_files:
            if filename not in existing_filepaths:
                # Tag files with index so multiple files can
                # have the same filename
                logging.debug("Creating backup of %s", filename)
                shutil.copy2(filename, os.path.join(
                    cp_dir, os.path.basename(filename) + "_" + str(idx)))
                op_fd.write(filename + '\n')
                idx += 1
        op_fd.close()

        with open(os.path.join(cp_dir, "CHANGES_SINCE"), 'a') as notes_fd:
            notes_fd.write(self.save_notes)
示例#4
0
def init_key(key_size, key_dir):
    """Initializes privkey.

    Inits key and CSR using provided files or generating new files
    if necessary. Both will be saved in PEM format on the
    filesystem. The CSR is placed into DER format to allow
    the namedtuple to easily work with the protocol.

    :param str key_dir: Key save directory.

    """
    try:
        key_pem = crypto_util.make_key(key_size)
    except ValueError as err:
        logging.fatal(str(err))
        sys.exit(1)

    # Save file
    le_util.make_or_verify_dir(key_dir, 0o700)
    key_f, key_filename = le_util.unique_file(
        os.path.join(key_dir, "key-letsencrypt.pem"), 0o600)
    key_f.write(key_pem)
    key_f.close()

    logging.info("Generating key (%d bits): %s", key_size, key_filename)

    return le_util.Key(key_filename, key_pem)
    def add_to_checkpoint(self, cp_dir, save_files):
        le_util.make_or_verify_dir(cp_dir, 0755)

        existing_filepaths = []
        op_fd = None
        # Open up FILEPATHS differently depending on if it already exists
        if os.path.isfile(cp_dir + "FILEPATHS"):
            op_fd = open(cp_dir + "FILEPATHS", 'r+')
            existing_filepaths = op_fd.read().splitlines()
        else:
            op_fd = open(cp_dir + "FILEPATHS", 'w')

        idx = len(existing_filepaths)
        for filename in save_files:
            if filename not in existing_filepaths:
                # Tag files with index so multiple files can
                # have the same filename
                logger.debug("Creating backup of %s" % filename)
                shutil.copy2(filename, cp_dir + os.path.basename(filename)
                             + "_" + str(idx))
                op_fd.write(filename + '\n')
                idx += 1
        op_fd.close()

        with open(cp_dir + "CHANGES_SINCE", 'a') as notes_fd:
            notes_fd.write(self.save_notes)
    def save(self):
        """Save account to disk."""
        le_util.make_or_verify_dir(self.config.accounts_dir, 0o700,
                                   os.geteuid())

        acc_config = configobj.ConfigObj()
        acc_config.filename = os.path.join(
            self.config.accounts_dir, self._get_config_filename(self.email))

        acc_config.initial_comment = [
            "DO NOT EDIT THIS FILE",
            "Account information for %s under %s" %
            (self._get_config_filename(self.email), self.config.server),
        ]

        acc_config["key"] = self.key.file
        acc_config["phone"] = self.phone

        if self.regr is not None:
            acc_config["RegistrationResource"] = {}
            acc_config["RegistrationResource"]["uri"] = self.uri
            acc_config["RegistrationResource"]["new_authzr_uri"] = (
                self.new_authzr_uri)
            acc_config["RegistrationResource"]["terms_of_service"] = (
                self.terms_of_service)

            regr_dict = self.regr.body.to_json()
            acc_config["RegistrationResource"]["body"] = regr_dict

        acc_config.write()
    def register_file_creation(self, temporary, *files):
        """Register the creation of all files during letsencrypt execution.

        Call this method before writing to the file to make sure that the
        file will be cleaned up if the program exits unexpectedly.
        (Before a save occurs)

        :param bool temporary: If the file creation registry is for
            a temp or permanent save.

        :param \*files: file paths (str) to be registered

        """
        if temporary:
            cp_dir = self.direc["temp"]
        else:
            cp_dir = self.direc["progress"]

        le_util.make_or_verify_dir(cp_dir)
        try:
            with open(os.path.join(cp_dir, "NEW_FILES"), 'a') as new_fd:
                for file_path in files:
                    new_fd.write("%s\n" % file_path)
        except (IOError, OSError):
            logging.error("ERROR: Unable to register file creation")
def init_save_csr(privkey, names, cert_dir, csrname="csr-letsencrypt.pem"):
    """Initialize a CSR with the given private key.

    :param privkey: Key to include in the CSR
    :type privkey: :class:`letsencrypt.client.le_util.Key`

    :param set names: `str` names to include in the CSR

    :param str cert_dir: Certificate save directory.

    :returns: CSR
    :rtype: :class:`letsencrypt.client.le_util.CSR`

    """
    csr_pem, csr_der = make_csr(privkey.pem, names)

    # Save CSR
    le_util.make_or_verify_dir(cert_dir, 0o755)
    csr_f, csr_filename = le_util.unique_file(
        os.path.join(cert_dir, csrname), 0o644)
    csr_f.write(csr_pem)
    csr_f.close()

    logging.info("Creating CSR: %s", csr_filename)

    return le_util.CSR(csr_filename, csr_der, "der")
示例#9
0
def init_key(key_size, key_dir):
    """Initializes privkey.

    Inits key and CSR using provided files or generating new files
    if necessary. Both will be saved in PEM format on the
    filesystem. The CSR is placed into DER format to allow
    the namedtuple to easily work with the protocol.

    :param str key_dir: Key save directory.

    """
    try:
        key_pem = crypto_util.make_key(key_size)
    except ValueError as err:
        logging.fatal(str(err))
        sys.exit(1)

    # Save file
    le_util.make_or_verify_dir(key_dir, 0o700)
    key_f, key_filename = le_util.unique_file(
        os.path.join(key_dir, "key-letsencrypt.pem"), 0o600)
    key_f.write(key_pem)
    key_f.close()

    logging.info("Generating key (%d bits): %s", key_size, key_filename)

    return le_util.Key(key_filename, key_pem)
示例#10
0
    def store_cert_key(self, encrypt = False):
        list_file = CERT_KEY_BACKUP + "LIST"
        le_util.make_or_verify_dir(CERT_KEY_BACKUP, 0700)
        idx = 0

        if encrypt:
            logger.error("Unfortunately securely storing the certificates/keys \
            is not yet available. Stay tuned for the next update!")
            return False

        if os.path.isfile(list_file):
            with open(list_file, 'r+b') as csvfile:
                csvreader = csv.reader(csvfile)
                for r in csvreader:
                    idx = int(r[0]) + 1
                csvwriter = csv.writer(csvfile)
                csvwriter.writerow([str(idx), self.cert_file, self.key_file])

        else:
            with open(list_file, 'wb') as csvfile:
                csvwriter = csv.writer(csvfile)
                csvwriter.writerow(["0", self.cert_file, self.key_file])

        shutil.copy2(self.key_file,
                     CERT_KEY_BACKUP + os.path.basename(self.key_file) +
                     "_" + str(idx))
        shutil.copy2(self.cert_file,
                     CERT_KEY_BACKUP + os.path.basename(self.cert_file) +
                     "_" + str(idx))
示例#11
0
    def register_file_creation(self, temporary, *files):
        """Register the creation of all files during letsencrypt execution.

        Call this method before writing to the file to make sure that the
        file will be cleaned up if the program exits unexpectedly.
        (Before a save occurs)

        :param temporary: If the file creation registry is for a temp or
        permanent save.
        :type temporary: bool

        :param *files: file paths to be registered
        :type *files: str

        """
        if temporary:
            cp_dir = CONFIG.TEMP_CHECKPOINT_DIR
        else:
            cp_dir = CONFIG.IN_PROGRESS_DIR

        le_util.make_or_verify_dir(cp_dir)
        try:
            with open(cp_dir + "NEW_FILES", 'a') as fd:
                for file_path in files:
                    fd.write("%s\n" % file_path)
        except:
            logger.error("ERROR: Unable to register file creation")
示例#12
0
    def add_to_checkpoint(self, cp_dir, save_files):
        """Add save files to checkpoint directory.

        :param cp_dir: Checkpoint directory filepath
        :type cp_dir: str

        :param save_files: set of files to save
        :type save_files: set

        """
        le_util.make_or_verify_dir(cp_dir, 0o755)

        existing_filepaths = []
        op_fd = None
        # Open up FILEPATHS differently depending on if it already exists
        if os.path.isfile(cp_dir + "FILEPATHS"):
            op_fd = open(cp_dir + "FILEPATHS", 'r+')
            existing_filepaths = op_fd.read().splitlines()
        else:
            op_fd = open(cp_dir + "FILEPATHS", 'w')

        idx = len(existing_filepaths)
        for filename in save_files:
            if filename not in existing_filepaths:
                # Tag files with index so multiple files can
                # have the same filename
                logger.debug("Creating backup of %s" % filename)
                shutil.copy2(filename, cp_dir + os.path.basename(filename)
                             + "_" + str(idx))
                op_fd.write(filename + '\n')
                idx += 1
        op_fd.close()

        with open(cp_dir + "CHANGES_SINCE", 'a') as notes_fd:
            notes_fd.write(self.save_notes)
示例#13
0
    def save(self):
        """Save account to disk."""
        le_util.make_or_verify_dir(
            self.config.accounts_dir, 0o700, os.geteuid())

        acc_config = configobj.ConfigObj()
        acc_config.filename = os.path.join(
            self.config.accounts_dir, self._get_config_filename(self.email))

        acc_config.initial_comment = [
            "DO NOT EDIT THIS FILE",
            "Account information for %s under %s" % (
                self._get_config_filename(self.email), self.config.server),
        ]

        acc_config["key"] = self.key.file
        acc_config["phone"] = self.phone

        if self.regr is not None:
            acc_config["RegistrationResource"] = {}
            acc_config["RegistrationResource"]["uri"] = self.uri
            acc_config["RegistrationResource"]["new_authzr_uri"] = (
                self.new_authzr_uri)
            acc_config["RegistrationResource"]["terms_of_service"] = (
                self.terms_of_service)

            regr_dict = self.regr.body.to_json()
            acc_config["RegistrationResource"]["body"] = regr_dict

        acc_config.write()
示例#14
0
    def get_key_csr_pem(self, csr_return_format='der'):
        """Return key and CSR, generate if necessary.

        Returns key and CSR using provided files or generating new files
        if necessary. Both will be saved in PEM format on the
        filesystem. The CSR can optionally be returned in DER format as
        the CSR cannot be loaded back into M2Crypto.

        :param csr_return_format: If "der" returned CSR is in DER format,
                                  PEM otherwise.
        :param csr_return_format: str

        :returns: A pair of `(key, csr)`, where `key` is PEM encoded `str`
                  and `csr` is PEM/DER (depedning on `csr_return_format`
                  encoded `str`.
        :rtype: tuple

        """
        key_pem = None
        csr_pem = None
        if not self.key_file:
            key_pem = crypto_util.make_key(CONFIG.RSA_KEY_SIZE)
            # Save file
            le_util.make_or_verify_dir(CONFIG.KEY_DIR, 0o700)
            key_f, self.key_file = le_util.unique_file(
                os.path.join(CONFIG.KEY_DIR, "key-letsencrypt.pem"), 0o600)
            key_f.write(key_pem)
            key_f.close()
            logger.info("Generating key: %s" % self.key_file)
        else:
            try:
                key_pem = open(self.key_file).read().replace("\r", "")
            except:
                logger.fatal("Unable to open key file: %s" % self.key_file)
                sys.exit(1)

        if not self.csr_file:
            csr_pem, csr_der = crypto_util.make_csr(self.key_file, self.names)
            # Save CSR
            le_util.make_or_verify_dir(CONFIG.CERT_DIR, 0o755)
            csr_f, self.csr_file = le_util.unique_file(
                os.path.join(CONFIG.CERT_DIR, "csr-letsencrypt.pem"), 0o644)
            csr_f.write(csr_pem)
            csr_f.close()
            logger.info("Creating CSR: %s" % self.csr_file)
        else:
            try:
                csr = M2Crypto.X509.load_request(self.csr_file)
                csr_pem, csr_der = csr.as_pem(), csr.as_der()
            except:
                logger.fatal("Unable to open CSR file: %s" % self.csr_file)
                sys.exit(1)

        if csr_return_format == 'der':
            return key_pem, csr_der
        else:
            return key_pem, csr_pem
示例#15
0
    def get_key_csr_pem(self, csr_return_format='der'):
        """Return key and CSR, generate if necessary.

        Returns key and CSR using provided files or generating new files
        if necessary. Both will be saved in PEM format on the
        filesystem. The CSR can optionally be returned in DER format as
        the CSR cannot be loaded back into M2Crypto.

        :param csr_return_format: If "der" returned CSR is in DER format,
                                  PEM otherwise.
        :param csr_return_format: str

        :returns: A pair of `(key, csr)`, where `key` is PEM encoded `str`
                  and `csr` is PEM/DER (depedning on `csr_return_format`
                  encoded `str`.
        :rtype: tuple

        """
        key_pem = None
        csr_pem = None
        if not self.key_file:
            key_pem = crypto_util.make_key(CONFIG.RSA_KEY_SIZE)
            # Save file
            le_util.make_or_verify_dir(CONFIG.KEY_DIR, 0o700)
            key_f, self.key_file = le_util.unique_file(
                os.path.join(CONFIG.KEY_DIR, "key-letsencrypt.pem"), 0o600)
            key_f.write(key_pem)
            key_f.close()
            logger.info("Generating key: %s" % self.key_file)
        else:
            try:
                key_pem = open(self.key_file).read().replace("\r", "")
            except:
                logger.fatal("Unable to open key file: %s" % self.key_file)
                sys.exit(1)

        if not self.csr_file:
            csr_pem, csr_der = crypto_util.make_csr(self.key_file, self.names)
            # Save CSR
            le_util.make_or_verify_dir(CONFIG.CERT_DIR, 0o755)
            csr_f, self.csr_file = le_util.unique_file(
                os.path.join(CONFIG.CERT_DIR, "csr-letsencrypt.pem"), 0o644)
            csr_f.write(csr_pem)
            csr_f.close()
            logger.info("Creating CSR: %s" % self.csr_file)
        else:
            try:
                csr = M2Crypto.X509.load_request(self.csr_file)
                csr_pem, csr_der = csr.as_pem(), csr.as_der()
            except:
                logger.fatal("Unable to open CSR file: %s" % self.csr_file)
                sys.exit(1)

        if csr_return_format == 'der':
            return key_pem, csr_der
        else:
            return key_pem, csr_pem
示例#16
0
    def __init__(self, config, key, email=None, phone=None, regr=None):
        le_util.make_or_verify_dir(config.accounts_dir, 0o700, os.geteuid())
        self.key = key
        self.config = config
        if email is not None and self.safe_email(email):
            self.email = email
        else:
            self.email = None
        self.phone = phone

        self.regr = regr
    def store_token(self, domain, token):
        """Store token for later automatic use.

        :param str domain: domain associated with the token
        :param str token: token from authorization

        """
        le_util.make_or_verify_dir(self.token_dir, 0o700, os.geteuid())

        with open(os.path.join(self.token_dir, domain), 'w') as token_fd:
            token_fd.write(str(token))
示例#18
0
    def store_token(self, domain, token):
        """Store token for later automatic use.

        :param str domain: domain associated with the token
        :param str token: token from authorization

        """
        le_util.make_or_verify_dir(self.token_dir, 0o700, os.geteuid())

        with open(os.path.join(self.token_dir, domain), 'w') as token_fd:
            token_fd.write(str(token))
示例#19
0
    def __init__(self, installer, config, no_confirm=False):
        self.network = network.Network(config.server)
        self.installer = installer
        self.config = config
        self.no_confirm = no_confirm

        le_util.make_or_verify_dir(config.cert_key_backup, 0o700, os.geteuid())

        # TODO: Find a better solution for this...
        self.list_path = os.path.join(config.cert_key_backup, "LIST")
        # Make sure that the file is available for use for rest of class
        open(self.list_path, "a").close()
示例#20
0
    def __init__(self, installer, config, no_confirm=False):
        self.network = network.Network(config.server)
        self.installer = installer
        self.config = config
        self.no_confirm = no_confirm

        le_util.make_or_verify_dir(config.cert_key_backup, 0o700, os.geteuid())

        # TODO: Find a better solution for this...
        self.list_path = os.path.join(config.cert_key_backup, "LIST")
        # Make sure that the file is available for use for rest of class
        open(self.list_path, "a").close()
示例#21
0
    def __init__(self, config, key, email=None, phone=None, regr=None):
        le_util.make_or_verify_dir(
            config.accounts_dir, 0o700, os.geteuid())
        self.key = key
        self.config = config
        if email is not None and self.safe_email(email):
            self.email = email
        else:
            self.email = None
        self.phone = phone

        self.regr = regr
示例#22
0
    def store_cert_key(cls, cert_path, key_path, config):
        """Store certificate key. (Used to allow quick revocation)

        :param str cert_path: Path to a certificate file.
        :param str key_path: Path to authorized key for certificate

        :ivar config: Configuration.
        :type config: :class:`~letsencrypt.client.interfaces.IConfig`

        """
        list_path = os.path.join(config.cert_key_backup, "LIST")
        le_util.make_or_verify_dir(config.cert_key_backup, 0o700, os.geteuid())

        cls._catalog_files(
            config.cert_key_backup, cert_path, key_path, list_path)
示例#23
0
    def store_cert_key(cls, cert_path, key_path, config):
        """Store certificate key. (Used to allow quick revocation)

        :param str cert_path: Path to a certificate file.
        :param str key_path: Path to authorized key for certificate

        :ivar config: Configuration.
        :type config: :class:`~letsencrypt.client.interfaces.IConfig`

        """
        list_path = os.path.join(config.cert_key_backup, "LIST")
        le_util.make_or_verify_dir(config.cert_key_backup, 0o700, os.geteuid())

        cls._catalog_files(config.cert_key_backup, cert_path, key_path,
                           list_path)
示例#24
0
    def register_file_creation(self, temporary, *files):
        r"""Register the creation of all files during letsencrypt execution.

        Call this method before writing to the file to make sure that the
        file will be cleaned up if the program exits unexpectedly.
        (Before a save occurs)

        :param bool temporary: If the file creation registry is for
            a temp or permanent save.
        :param \*files: file paths (str) to be registered

        :raises letsencrypt.client.errors.LetsEncryptReverterError: If
            call does not contain necessary parameters or if the file creation
            is unable to be registered.

        """
        # Make sure some files are provided... as this is an error
        # Made this mistake in my initial implementation of apache.dvsni.py
        if not files:
            raise errors.LetsEncryptReverterError(
                "Forgot to provide files to registration call")

        if temporary:
            cp_dir = self.config.temp_checkpoint_dir
        else:
            cp_dir = self.config.in_progress_dir

        le_util.make_or_verify_dir(
            cp_dir, constants.CONFIG_DIRS_MODE, os.geteuid())

        # Append all new files (that aren't already registered)
        new_fd = None
        try:
            new_fd, ex_files = self._read_and_append(
                os.path.join(cp_dir, "NEW_FILES"))

            for path in files:
                if path not in ex_files:
                    new_fd.write("{0}{1}".format(path, os.linesep))
        except (IOError, OSError):
            logging.error("Unable to register file creation(s) - %s", files)
            raise errors.LetsEncryptReverterError(
                "Unable to register file creation(s) - {0}".format(files))
        finally:
            if new_fd is not None:
                new_fd.close()
示例#25
0
    def _add_to_checkpoint_dir(self, cp_dir, save_files, save_notes):
        """Add save files to checkpoint directory.

        :param str cp_dir: Checkpoint directory filepath
        :param set save_files: set of files to save
        :param str save_notes: notes about changes made during the save

        :raises IOError: If unable to open cp_dir + FILEPATHS file
        :raises letsencrypt.client.errors.LetsEncryptReverterError: If
            unable to add checkpoint

        """
        le_util.make_or_verify_dir(cp_dir, 0o755, os.geteuid())

        op_fd, existing_filepaths = self._read_and_append(
            os.path.join(cp_dir, "FILEPATHS"))

        idx = len(existing_filepaths)

        for filename in save_files:
            # No need to copy/index already existing files
            # The oldest copy already exists in the directory...
            if filename not in existing_filepaths:
                # Tag files with index so multiple files can
                # have the same filename
                logging.debug("Creating backup of %s", filename)
                try:
                    shutil.copy2(
                        filename,
                        os.path.join(
                            cp_dir,
                            os.path.basename(filename) + "_" + str(idx)))
                    op_fd.write(filename + os.linesep)
                # http://stackoverflow.com/questions/4726260/effective-use-of-python-shutil-copy2
                except IOError:
                    op_fd.close()
                    logging.error("Unable to add file %s to checkpoint %s",
                                  filename, cp_dir)
                    raise errors.LetsEncryptReverterError(
                        "Unable to add file {0} to checkpoint "
                        "{1}".format(filename, cp_dir))
                idx += 1
        op_fd.close()

        with open(os.path.join(cp_dir, "CHANGES_SINCE"), "a") as notes_fd:
            notes_fd.write(save_notes)
示例#26
0
    def get_key_csr_pem(self, csr_return_format = 'der'):
        """
        Returns key and CSR using provided files or generating new files if
        necessary. Both will be saved in pem format on the filesystem.
        The CSR can optionally be returned in DER format as the CSR cannot be
        loaded back into M2Crypto.
        """
        key_pem = None
        csr_pem = None
        if not self.key_file:
            key_pem = crypto_util.make_key(RSA_KEY_SIZE)
            # Save file
            le_util.make_or_verify_dir(KEY_DIR, 0700)
            key_f, self.key_file = le_util.unique_file(
                KEY_DIR + "key-letsencrypt.pem", 0600)
            key_f.write(key_pem)
            key_f.close()
            logger.info("Generating key: %s" % self.key_file)
        else:
            try:
                key_pem = open(self.key_file).read().replace("\r", "")
            except:
                logger.fatal("Unable to open key file: %s" % self.key_file)
                sys.exit(1)

        if not self.csr_file:
            csr_pem, csr_der = crypto_util.make_csr(self.key_file, self.names)
            # Save CSR
            le_util.make_or_verify_dir(CERT_DIR, 0755)
            csr_f, self.csr_file = le_util.unique_file(
                CERT_DIR + "csr-letsencrypt.pem", 0644)
            csr_f.write(csr_pem)
            csr_f.close()
            logger.info("Creating CSR: %s" % self.csr_file)
        else:
            #TODO fix this der situation
            try:
                csr_pem = open(self.csr_file).read().replace("\r", "")
            except:
                logger.fatal("Unable to open CSR file: %s" % self.csr_file)
                sys.exit(1)

        if csr_return_format == 'der':
            return key_pem, csr_der

        return key_pem, csr_pem
示例#27
0
    def store_cert_key(self, cert_file, encrypt=False):
        """Store certificate key.

        :param str cert_file: Path to a certificate file.

        :param bool encrypt: Should the certificate key be encrypted?

        :returns: True if key file was stored successfully, False otherwise.
        :rtype: bool

        """
        list_file = os.path.join(CONFIG.CERT_KEY_BACKUP, "LIST")
        le_util.make_or_verify_dir(CONFIG.CERT_KEY_BACKUP, 0o700)
        idx = 0

        if encrypt:
            logging.error(
                "Unfortunately securely storing the certificates/"
                "keys is not yet available. Stay tuned for the "
                "next update!")
            return False

        if os.path.isfile(list_file):
            with open(list_file, 'r+b') as csvfile:
                csvreader = csv.reader(csvfile)
                for row in csvreader:
                    idx = int(row[0]) + 1
                csvwriter = csv.writer(csvfile)
                csvwriter.writerow([str(idx), cert_file, self.privkey.file])

        else:
            with open(list_file, 'wb') as csvfile:
                csvwriter = csv.writer(csvfile)
                csvwriter.writerow(["0", cert_file, self.privkey.file])

        shutil.copy2(self.privkey.file,
                     os.path.join(
                         CONFIG.CERT_KEY_BACKUP,
                         os.path.basename(self.privkey.file) + "_" + str(idx)))
        shutil.copy2(cert_file,
                     os.path.join(
                         CONFIG.CERT_KEY_BACKUP,
                         os.path.basename(cert_file) + "_" + str(idx)))

        return True
示例#28
0
    def _add_to_checkpoint_dir(self, cp_dir, save_files, save_notes):
        """Add save files to checkpoint directory.

        :param str cp_dir: Checkpoint directory filepath
        :param set save_files: set of files to save
        :param str save_notes: notes about changes made during the save

        :raises IOError: If unable to open cp_dir + FILEPATHS file
        :raises letsencrypt.client.errors.LetsEncryptReverterError: If
            unable to add checkpoint

        """
        le_util.make_or_verify_dir(
            cp_dir, constants.CONFIG_DIRS_MODE, os.geteuid())

        op_fd, existing_filepaths = self._read_and_append(
            os.path.join(cp_dir, "FILEPATHS"))

        idx = len(existing_filepaths)

        for filename in save_files:
            # No need to copy/index already existing files
            # The oldest copy already exists in the directory...
            if filename not in existing_filepaths:
                # Tag files with index so multiple files can
                # have the same filename
                logging.debug("Creating backup of %s", filename)
                try:
                    shutil.copy2(filename, os.path.join(
                        cp_dir, os.path.basename(filename) + "_" + str(idx)))
                    op_fd.write(filename + os.linesep)
                # http://stackoverflow.com/questions/4726260/effective-use-of-python-shutil-copy2
                except IOError:
                    op_fd.close()
                    logging.error(
                        "Unable to add file %s to checkpoint %s",
                        filename, cp_dir)
                    raise errors.LetsEncryptReverterError(
                        "Unable to add file {0} to checkpoint "
                        "{1}".format(filename, cp_dir))
                idx += 1
        op_fd.close()

        with open(os.path.join(cp_dir, "CHANGES_SINCE"), "a") as notes_fd:
            notes_fd.write(save_notes)
示例#29
0
def init_csr(privkey, names, cert_dir):
    """Initialize a CSR with the given private key.

    :param str cert_dir: Certificate save directory.

    """
    csr_pem, csr_der = crypto_util.make_csr(privkey.pem, names)

    # Save CSR
    le_util.make_or_verify_dir(cert_dir, 0o755)
    csr_f, csr_filename = le_util.unique_file(
        os.path.join(cert_dir, "csr-letsencrypt.pem"), 0o644)
    csr_f.write(csr_pem)
    csr_f.close()

    logging.info("Creating CSR: %s", csr_filename)

    return le_util.CSR(csr_filename, csr_der, "der")
示例#30
0
def init_csr(privkey, names, cert_dir):
    """Initialize a CSR with the given private key.

    :param str cert_dir: Certificate save directory.

    """
    csr_pem, csr_der = crypto_util.make_csr(privkey.pem, names)

    # Save CSR
    le_util.make_or_verify_dir(cert_dir, 0o755)
    csr_f, csr_filename = le_util.unique_file(
        os.path.join(cert_dir, "csr-letsencrypt.pem"), 0o644)
    csr_f.write(csr_pem)
    csr_f.close()

    logging.info("Creating CSR: %s", csr_filename)

    return le_util.CSR(csr_filename, csr_der, "der")
示例#31
0
    def store_cert_key(self, cert_file, encrypt=False):
        """Store certificate key. (Used to allow quick revocation)

        :param str cert_file: Path to a certificate file.

        :param bool encrypt: Should the certificate key be encrypted?

        :returns: True if key file was stored successfully, False otherwise.
        :rtype: bool

        """
        list_file = os.path.join(self.config.cert_key_backup, "LIST")
        le_util.make_or_verify_dir(self.config.cert_key_backup, 0o700)
        idx = 0

        if encrypt:
            logging.error("Unfortunately securely storing the certificates/"
                          "keys is not yet available. Stay tuned for the "
                          "next update!")
            return False

        if os.path.isfile(list_file):
            with open(list_file, 'r+b') as csvfile:
                csvreader = csv.reader(csvfile)
                for row in csvreader:
                    idx = int(row[0]) + 1
                csvwriter = csv.writer(csvfile)
                csvwriter.writerow([str(idx), cert_file, self.authkey.file])

        else:
            with open(list_file, 'wb') as csvfile:
                csvwriter = csv.writer(csvfile)
                csvwriter.writerow(["0", cert_file, self.authkey.file])

        shutil.copy2(
            self.authkey.file,
            os.path.join(self.config.cert_key_backup,
                         os.path.basename(self.authkey.file) + "_" + str(idx)))
        shutil.copy2(
            cert_file,
            os.path.join(self.config.cert_key_backup,
                         os.path.basename(cert_file) + "_" + str(idx)))

        return True
示例#32
0
    def init_key_csr(self):
        """Initializes privkey and csr.

        Inits key and CSR using provided files or generating new files
        if necessary. Both will be saved in PEM format on the
        filesystem. The CSR is placed into DER format to allow
        the namedtuple to easily work with the protocol.

        """
        if not self.privkey.file:
            key_pem = crypto_util.make_key(CONFIG.RSA_KEY_SIZE)

            # Save file
            le_util.make_or_verify_dir(CONFIG.KEY_DIR, 0o700)
            key_f, key_filename = le_util.unique_file(
                os.path.join(CONFIG.KEY_DIR, "key-letsencrypt.pem"), 0o600)
            key_f.write(key_pem)
            key_f.close()

            logger.info("Generating key: %s" % key_filename)

            self.privkey = Client.Key(key_filename, key_pem)

        if not self.csr.file:
            csr_pem, csr_der = crypto_util.make_csr(
                self.privkey.pem, self.names)

            # Save CSR
            le_util.make_or_verify_dir(CONFIG.CERT_DIR, 0o755)
            csr_f, csr_filename = le_util.unique_file(
                os.path.join(CONFIG.CERT_DIR, "csr-letsencrypt.pem"), 0o644)
            csr_f.write(csr_pem)
            csr_f.close()

            logger.info("Creating CSR: %s" % csr_filename)

            self.csr = Client.CSR(csr_filename, csr_der, "der")
        elif self.csr.type != "der":
            # The user is going to pass in a pem format file
            # That is why we must conver it to der since the
            # protocol uses der exclusively.
            csr_obj = M2Crypto.X509.load_request_string(self.csr.data)
            self.csr = Client.CSR(self.csr.file, csr_obj.as_der(), "der")
    def register_file_creation(self, temporary, *files):
        """
        This is used to register the creation of all files during Letsencrypt
        execution. Call this method before writing to the file to make sure
        that the file will be cleaned up if the program exits unexpectedly.
        (Before a save occurs)
        """
        if temporary:
            cp_dir = TEMP_CHECKPOINT_DIR
        else:
            cp_dir = IN_PROGRESS_DIR

        le_util.make_or_verify_dir(cp_dir)
        try:
            with open(cp_dir + "NEW_FILES", 'a') as fd:
                for f in files:
                    fd.write("%s\n" % f)
        except:
            logger.error("ERROR: Unable to register file creation")
示例#34
0
    def store_cert_key(self, cert_file, encrypt=False):
        """Store certificate key.

        :param cert_file: Path to a certificate file.
        :type cert_file: str

        :param encrypt: Should the certificate key be encrypted?
        :type encrypt: bool

        """
        list_file = os.path.join(CONFIG.CERT_KEY_BACKUP, "LIST")
        le_util.make_or_verify_dir(CONFIG.CERT_KEY_BACKUP, 0o700)
        idx = 0

        if encrypt:
            logger.error("Unfortunately securely storing the certificates/"
                         "keys is not yet available. Stay tuned for the "
                         "next update!")
            return False

        if os.path.isfile(list_file):
            with open(list_file, 'r+b') as csvfile:
                csvreader = csv.reader(csvfile)
                for row in csvreader:
                    idx = int(row[0]) + 1
                csvwriter = csv.writer(csvfile)
                csvwriter.writerow([str(idx), cert_file, self.key_file])

        else:
            with open(list_file, 'wb') as csvfile:
                csvwriter = csv.writer(csvfile)
                csvwriter.writerow(["0", cert_file, self.key_file])

        shutil.copy2(
            self.key_file,
            os.path.join(CONFIG.CERT_KEY_BACKUP,
                         os.path.basename(self.key_file) + "_" + str(idx)))
        shutil.copy2(
            cert_file,
            os.path.join(CONFIG.CERT_KEY_BACKUP,
                         os.path.basename(cert_file) + "_" + str(idx)))
示例#35
0
    def from_email(cls, config, email):
        """Generate a new account from an email address.

        :param config: Configuration
        :type config: :class:`letsencrypt.client.interfaces.IConfig`

        :param str email: Email address

        :raises letsencrypt.client.errors.LetsEncryptClientError: If invalid
            email address is given.

        """
        if not email or cls.safe_email(email):
            email = email if email else None

            le_util.make_or_verify_dir(config.account_keys_dir, 0o700,
                                       os.geteuid())
            key = crypto_util.init_save_key(config.rsa_key_size,
                                            config.account_keys_dir,
                                            cls._get_config_filename(email))
            return cls(config, key, email)

        raise errors.LetsEncryptClientError("Invalid email address.")
示例#36
0
    def from_email(cls, config, email):
        """Generate a new account from an email address.

        :param config: Configuration
        :type config: :class:`letsencrypt.client.interfaces.IConfig`

        :param str email: Email address

        :raises letsencrypt.client.errors.LetsEncryptClientError: If invalid
            email address is given.

        """
        if not email or cls.safe_email(email):
            email = email if email else None

            le_util.make_or_verify_dir(
                config.account_keys_dir, 0o700, os.geteuid())
            key = crypto_util.init_save_key(
                config.rsa_key_size, config.account_keys_dir,
                cls._get_config_filename(email))
            return cls(config, key, email)

        raise errors.LetsEncryptClientError("Invalid email address.")
示例#37
0
    def _verify_setup(self):
        """Verify the setup to ensure safe operating environment.

        Make sure that files/directories are setup with appropriate permissions
        Aim for defensive coding... make sure all input files
        have permissions of root.

        """
        uid = os.geteuid()
        le_util.make_or_verify_dir(self.config.work_dir, 0o755, uid)
        le_util.make_or_verify_dir(self.config.backup_dir, 0o755, uid)
        le_util.make_or_verify_dir(self.config.config_dir, 0o755, uid)
    def verify_setup(self):
        """Verify the setup to ensure safe operating environment.

        Make sure that files/directories are setup with appropriate permissions
        Aim for defensive coding... make sure all input files
        have permissions of root

        """
        uid = os.geteuid()
        le_util.make_or_verify_dir(self.config.config_dir, 0o755, uid)
        le_util.make_or_verify_dir(self.config.work_dir, 0o755, uid)
        le_util.make_or_verify_dir(self.config.backup_dir, 0o755, uid)
 def _call(self, directory, mode):
     from letsencrypt.client.le_util import make_or_verify_dir
     return make_or_verify_dir(directory, mode, self.uid)
 def _call(self, directory, mode):
     from letsencrypt.client.le_util import make_or_verify_dir
     return make_or_verify_dir(directory, mode, self.uid)
示例#41
0
def main():  # pylint: disable=too-many-branches, too-many-statements
    """Command line argument parsing and main script execution."""
    # note: arg parser internally handles --help (and exits afterwards)
    args = create_parser().parse_args()
    config = configuration.NamespaceConfig(args)

    # note: check is done after arg parsing as --help should work w/o root also.
    if not os.geteuid() == 0:
        sys.exit(
            "{0}Root is required to run letsencrypt.  Please use sudo.{0}"
            .format(os.linesep))

    # Set up logging
    logger = logging.getLogger()
    logger.setLevel(logging.INFO)
    if args.use_curses:
        logger.addHandler(log.DialogHandler())
        displayer = display_util.NcursesDisplay()
    else:
        displayer = display_util.FileDisplay(sys.stdout)

    zope.component.provideUtility(displayer)

    if args.view_config_changes:
        client.view_config_changes(config)
        sys.exit()

    if args.revoke or args.rev_cert is not None or args.rev_key is not None:
        # This depends on the renewal config and cannot be completed yet.
        zope.component.getUtility(interfaces.IDisplay).notification(
            "Revocation is not available with the new Boulder server yet.")

        # client.revoke(config, args.no_confirm, args.rev_cert, args.rev_key)
        sys.exit()

    if args.rollback > 0:
        client.rollback(args.rollback, config)
        sys.exit()

    le_util.make_or_verify_dir(
        config.config_dir, constants.CONFIG_DIRS_MODE, os.geteuid())

    # Prepare for init of Client
    if args.email is None:
        acc = client.determine_account(config)
    else:
        try:
            # The way to get the default would be args.email = ""
            # First try existing account
            acc = account.Account.from_existing_account(config, args.email)
        except errors.LetsEncryptClientError:
            try:
                # Try to make an account based on the email address
                acc = account.Account.from_email(config, args.email)
            except errors.LetsEncryptClientError:
                sys.exit(1)

    if acc is None:
        sys.exit(0)

    all_auths = init_auths(config)
    logging.debug('Initialized authenticators: %s', all_auths.keys())
    try:
        auth = client.determine_authenticator(all_auths, config)
        logging.debug("Selected authenticator: %s", auth)
    except errors.LetsEncryptClientError as err:
        logging.critical(str(err))
        sys.exit(1)

    if auth is None:
        sys.exit(0)

    # Use the same object if possible
    if interfaces.IInstaller.providedBy(auth):  # pylint: disable=no-member
        installer = auth
    else:
        # This is simple and avoids confusion right now.
        installer = None

    if args.domains is None:
        doms = display_ops.choose_names(installer)
    else:
        doms = args.domains

    if not doms:
        sys.exit(0)

    acme = client.Client(config, acc, auth, installer)

    # Validate the key and csr
    client.validate_key_csr(acc.key)

    # This more closely mimics the capabilities of the CLI
    # It should be possible for reconfig only, install-only, no-install
    # I am not sure the best way to handle all of the unimplemented abilities,
    # but this code should be safe on all environments.
    cert_file = None
    if auth is not None:
        if acc.regr is None:
            try:
                acme.register()
            except errors.LetsEncryptClientError:
                sys.exit(0)
        cert_key, cert_file, chain_file = acme.obtain_certificate(doms)
    if installer is not None and cert_file is not None:
        acme.deploy_certificate(doms, cert_key, cert_file, chain_file)
    if installer is not None:
        acme.enhance_config(doms, args.redirect)
示例#42
0
def main():  # pylint: disable=too-many-branches, too-many-statements
    """Command line argument parsing and main script execution."""
    # note: arg parser internally handles --help (and exits afterwards)
    args = create_parser().parse_args()
    config = configuration.NamespaceConfig(args)

    # note: check is done after arg parsing as --help should work w/o root also.
    if not os.geteuid() == 0:
        sys.exit(
            "{0}Root is required to run letsencrypt.  Please use sudo.{0}".
            format(os.linesep))

    # Set up logging
    logger = logging.getLogger()
    logger.setLevel(logging.INFO)
    if args.use_curses:
        logger.addHandler(log.DialogHandler())
        displayer = display_util.NcursesDisplay()
    else:
        displayer = display_util.FileDisplay(sys.stdout)

    zope.component.provideUtility(displayer)

    if args.view_config_changes:
        client.view_config_changes(config)
        sys.exit()

    if args.revoke or args.rev_cert is not None or args.rev_key is not None:
        # This depends on the renewal config and cannot be completed yet.
        zope.component.getUtility(interfaces.IDisplay).notification(
            "Revocation is not available with the new Boulder server yet.")

        # client.revoke(config, args.no_confirm, args.rev_cert, args.rev_key)
        sys.exit()

    if args.rollback > 0:
        client.rollback(args.rollback, config)
        sys.exit()

    le_util.make_or_verify_dir(config.config_dir, constants.CONFIG_DIRS_MODE,
                               os.geteuid())

    # Prepare for init of Client
    if args.email is None:
        acc = client.determine_account(config)
    else:
        try:
            # The way to get the default would be args.email = ""
            # First try existing account
            acc = account.Account.from_existing_account(config, args.email)
        except errors.LetsEncryptClientError:
            try:
                # Try to make an account based on the email address
                acc = account.Account.from_email(config, args.email)
            except errors.LetsEncryptClientError:
                sys.exit(1)

    if acc is None:
        sys.exit(0)

    all_auths = init_auths(config)
    logging.debug('Initialized authenticators: %s', all_auths.keys())
    try:
        auth = client.determine_authenticator(all_auths, config)
        logging.debug("Selected authenticator: %s", auth)
    except errors.LetsEncryptClientError as err:
        logging.critical(str(err))
        sys.exit(1)

    if auth is None:
        sys.exit(0)

    # Use the same object if possible
    if interfaces.IInstaller.providedBy(auth):  # pylint: disable=no-member
        installer = auth
    else:
        # This is simple and avoids confusion right now.
        installer = None

    if args.domains is None:
        doms = display_ops.choose_names(installer)
    else:
        doms = args.domains

    if not doms:
        sys.exit(0)

    acme = client.Client(config, acc, auth, installer)

    # Validate the key and csr
    client.validate_key_csr(acc.key)

    # This more closely mimics the capabilities of the CLI
    # It should be possible for reconfig only, install-only, no-install
    # I am not sure the best way to handle all of the unimplemented abilities,
    # but this code should be safe on all environments.
    cert_file = None
    if auth is not None:
        if acc.regr is None:
            try:
                acme.register()
            except errors.LetsEncryptClientError:
                sys.exit(0)
        cert_key, cert_file, chain_file = acme.obtain_certificate(doms)
    if installer is not None and cert_file is not None:
        acme.deploy_certificate(doms, cert_key, cert_file, chain_file)
    if installer is not None:
        acme.enhance_config(doms, args.redirect)