def get_password(self, service, username): """ Read the password from the file. """ service = escape_for_ini(service) username = escape_for_ini(username) assoc = (service + '\0' + username).encode() # load the passwords from the file config = configparser.RawConfigParser() if os.path.exists(self.file_path): config.read(self.file_path) # fetch the password try: password_base64 = config.get(service, username).encode() # decode with base64 password_encrypted = decodebytes(password_base64) # decrypt the password with associated data try: password = self.decrypt(password_encrypted, assoc).decode('utf-8') except ValueError: # decrypt the password without associated data password = self.decrypt(password_encrypted).decode('utf-8') except (configparser.NoOptionError, configparser.NoSectionError): password = None return password
def set_password(self, service, username, password): """Write the password in the file. """ service = escape_for_ini(service) username = escape_for_ini(username) # encrypt the password password_encrypted = self.encrypt(password.encode('utf-8')) # encode with base64 password_base64 = base64.encodestring(password_encrypted).decode() # ensure the file exists self._ensure_file_path() # load the keyring from the disk config = configparser.RawConfigParser() config.read(self.file_path) # update the keyring with the password if not config.has_section(service): config.add_section(service) config.set(service, username, password_base64) # save the keyring back to the file with open(self.file_path, 'w') as config_file: config.write(config_file)
def config(self): """load the passwords from the config file """ if not hasattr(self, '_config'): raw_config = configparser.RawConfigParser() f = self._open() if f: raw_config.readfp(f) f.close() self._config = raw_config return self._config
def delete_password(self, service, username): """Delete the password for the username of the service. """ service = escape_for_ini(service) username = escape_for_ini(username) config = configparser.RawConfigParser() if os.path.exists(self.file_path): config.read(self.file_path) try: if not config.remove_option(service, username): raise PasswordDeleteError("Password not found") except configparser.NoSectionError: raise PasswordDeleteError("Password not found") # update the file with open(self.file_path, 'w') as config_file: config.write(config_file)
def _check_file(self): """ Check if the file exists and has the expected password reference. """ if not os.path.exists(self.file_path): return False self._migrate() config = configparser.RawConfigParser() config.read(self.file_path) try: config.get( escape_for_ini('keyring-setting'), escape_for_ini('password reference'), ) except (configparser.NoSectionError, configparser.NoOptionError): return False return True
def _write_config_value(self, service, key, value): # ensure the file exists self._ensure_file_path() # load the keyring from the disk config = configparser.RawConfigParser() config.read(self.file_path) service = escape_for_ini(service) key = escape_for_ini(key) # update the keyring with the password if not config.has_section(service): config.add_section(service) config.set(service, key, value) # save the keyring back to the file with open(self.file_path, 'w') as config_file: config.write(config_file)
def get_password(self, service, username): """ Read the password from the file. """ service = escape_for_ini(service) username = escape_for_ini(username) # load the passwords from the file config = configparser.RawConfigParser() if os.path.exists(self.file_path): config.read(self.file_path) # fetch the password try: password_base64 = config.get(service, username).encode() # decode with base64 password_encrypted = base64.decodestring(password_base64) # decrypted the password password = self.decrypt(password_encrypted).decode('utf-8') except (configparser.NoOptionError, configparser.NoSectionError): password = None return password
def run(self, argv): # parse args, setup logging and prepare keyrings args = self.parser.parse_args(argv) self.setup_logging(args.verbose) inkr = CryptFileKeyring() outkr = CryptFileKeyring() outkr.aesmode = args.aesmode # prepare infile infile = args.infile if not infile: infile = inkr.file_path else: inkr.file_path = infile inkr.filename = os.path.basename(infile) if not os.path.exists(infile): self.errexit('%s not found' % infile) if not inkr._check_file(): self.errexit('Failed to parse %s' % infile) log.info('infile %s: %s', infile, inkr.scheme) # prepare outfile outfile = args.outfile if not outfile: outfile = infile + '.%d' % os.getpid() if os.path.exists(outfile): if os.path.samefile(infile, outfile): self.errexit('infile and outfile must NOT be the same file') # outfile exists: rename os.rename(outfile, outfile + '~') log.info('%s renamed to %s~', outfile, outfile) outkr.file_path = outfile outkr.filename = os.path.basename(outfile) log.info('outfile %s: %s', outfile, outkr.scheme) # unlock the infile keyring try: inkr.keyring_key except ValueError as e: self.errexit('Unlock %s: %s' % (infile, e)) # keep old password or request password for new keyring if args.keep: outkr._get_new_password = lambda: inkr.keyring_key else: outkr.keyring_key # process infile config = configparser.RawConfigParser() config.read(infile) for section in config.sections(): log.debug('process section: [%s]', section) if section != escape('keyring-setting'): for username in config.options(section): username = unescape(username) section = unescape(section) log.info('process: [%s] %s', section, username) password = inkr.get_password(section, username) if password: outkr.set_password(section, username, password) log.debug('[%s] %s: %s', section, username, password) else: log.error('invalid entry: [%s]%s', section, username) return 0
def get_config(self): # setting a password triggers keyring file creation config = configparser.RawConfigParser() config.read(self.keyring.file_path) return config