示例#1
0
class PyKeePassTests3(KDBX3Tests):
    def setUp(self):
        shutil.copy(os.path.join(base_dir, self.database),
                    os.path.join(base_dir, 'change_creds.kdbx'))
        self.kp = PyKeePass(os.path.join(base_dir, self.database),
                            password=self.password,
                            keyfile=os.path.join(base_dir, self.keyfile))
        self.kp_tmp = PyKeePass(os.path.join(base_dir, 'change_creds.kdbx'),
                                password=self.password,
                                keyfile=os.path.join(base_dir, self.keyfile))

    def test_set_credentials(self):
        self.kp_tmp.password = '******'
        self.kp_tmp.keyfile = os.path.join(base_dir, 'change.key')
        self.kp_tmp.save()
        self.kp_tmp = PyKeePass(os.path.join(base_dir, 'change_creds.kdbx'),
                                password='******',
                                keyfile=os.path.join(base_dir, 'change.key'))

        results = self.kp.find_entries_by_username('foobar_user', first=True)
        self.assertEqual('foobar_user', results.username)

    def test_dump_xml(self):
        self.kp.dump_xml('db_dump.xml')
        with open('db_dump.xml') as f:
            first_line = f.readline()
            self.assertEqual(
                first_line,
                '<?xml version=\'1.0\' encoding=\'utf-8\' standalone=\'yes\'?>\n'
            )

    def tearDown(self):
        os.remove(os.path.join(base_dir, 'change_creds.kdbx'))
def process():
    args = get_args()
    print(args.dbpath)
    if not os.path.exists(args.dbpath):
        print("DB file path does not exist", file=sys.stderr)
        sys.exit(1)
    password = getpass()
    try:
        db = KP(args.dbpath, password=password)
    except FileNotFoundError:
        print("DB file path does not exist", file=sys.stderr)
        sys.exit(1)
    except OSError:
        print("Invalid password", file=sys.stderr)
        sys.exit(1)
    except Exception:
        print("Misc error", file=sys.stderr)
        sys.exit(1)
    groups = db.find_groups_by_name(args.groupname)
    if len(groups) == 0:
        print("Group does not exist", file=sys.stderr)
        sys.exit(1)
    if len(groups) > 1:
        print("Multiple groups of that name exist. Cannot continue",
              file=sys.stderr)
        sys.exit(1)
    group = groups[0]
    ## Only grab from root
    path = "".join([db.root_group.path, args.entrytitle])
    entries = db.find_entries_by_path(path)
    if len(entries) == 0:
        print("Entry by that title does not exist", file=sys.stderr)
    for entry in entries:
        group.append(entry)
    db.save()
示例#3
0
class AttachmentTests3(KDBX3Tests):
    # get some things ready before testing
    def setUp(self):
        shutil.copy(
            os.path.join(base_dir, self.database),
            os.path.join(base_dir, 'test_attachment.kdbx')
        )
        self.open()

    def open(self):
        self.kp = PyKeePass(
            os.path.join(base_dir, 'test_attachment.kdbx'),
            password=self.password,
            keyfile=os.path.join(base_dir, self.keyfile)
        )

    def test_create_delete_binary(self):
        with self.assertRaises(BinaryError):
            self.kp.delete_binary(999)
        with self.assertRaises(BinaryError):
            e = self.kp.entries[0]
            e.add_attachment(filename='foo.txt', id=123)
            e.attachments[0].binary

        binary_id = self.kp.add_binary(b'Ronald McDonald Trump')
        self.kp.save()
        self.open()
        self.assertEqual(self.kp.binaries[binary_id], b'Ronald McDonald Trump')
        self.assertEqual(len(self.kp.attachments), 1)

        num_attach = len(self.kp.binaries)
        self.kp.delete_binary(binary_id)
        self.kp.save()
        self.open()
        self.assertEqual(len(self.kp.binaries), num_attach - 1)

    def test_attachment_reference_decrement(self):
        e = self.kp.entries[0]

        binary_id1 = self.kp.add_binary(b'foobar')
        binary_id2 = self.kp.add_binary(b'foobar2')

        attachment1 = e.add_attachment(binary_id1, 'foo.txt')
        attachment2 = e.add_attachment(binary_id2, 'foo.txt')

        self.kp.delete_binary(binary_id1)

        self.assertEqual(attachment2.id, binary_id2 - 1)

    def test_fields(self):
        e = self.kp.entries[0]
        binary_id = self.kp.add_binary(b'foobar')
        a = e.add_attachment(filename='test.txt', id=binary_id)
        self.assertEqual(a.data, b'foobar')
        self.assertEqual(a.id, binary_id)
        self.assertEqual(a.filename, 'test.txt')

    def tearDown(self):
        os.remove(os.path.join(base_dir, 'test_attachment.kdbx'))
示例#4
0
def main(fullpath):
    password = getpass()
    try:
        db = PyKeePass(fullpath, password)
    except:
        print("Wrong path/password")
        return

    for entry in db.entries:
        entry.title = parse(entry.url)

    db.save()
示例#5
0
class AlteraKeePass:
    def __init__(self, arquivo_kdbx, senha):
        self.kp = PyKeePass(arquivo_kdbx, password=senha)

    def cria_entrada(self, grupo, nome, usuario, senha, url, icone, ip, porta):
        self.group = self.kp.find_groups(name=grupo, first=True)
        self.kp.add_entry(self.group,
                          nome,
                          usuario,
                          senha,
                          url=url,
                          icon=icone)
        self.entry = self.kp.find_entries(title=nome, first=True)
        self.entry.set_custom_property('IP', ip)
        self.entry.set_custom_property('PORT', porta)
        self.kp.save()
示例#6
0
def write_entry(kdbx_file,
                kdbx_password,
                group_path,
                entry_title,
                entry_username,
                entry_password,
                entry_url,
                entry_notes,
                entry_tags,
                kdbx_keyfile=None,
                force_creation=False,
                outfile=None):
    logging.info('Attempt to write entry "{}: {}:{}" to {}'.format(
        entry_title, entry_username, entry_password, group_path))
    samba_db = False
    if kdbx_file.startswith('smb://'):
        samba_db = True
        smb_kdbx_file = smb_retrieve(kdbx_file)
    kp = PyKeePass(smb_kdbx_file if samba_db else kdbx_file,
                   password=kdbx_password,
                   keyfile=kdbx_keyfile)
    dest_group = kp.find_groups_by_path(group_path, first=True)
    kp.add_entry(destination_group=dest_group,
                 title=entry_title,
                 username=entry_username,
                 password=entry_password,
                 url=entry_url,
                 notes=entry_notes,
                 tags=entry_tags,
                 force_creation=force_creation)

    if outfile:
        if outfile.startswith('smb://'):
            file_written = kp.save()
            smb_send(file_written.name, outfile)
            logging.info('Sent database file to {}'.format(outfile))
        else:
            file_written = kp.save(kdbx_file)
            logging.info('KeePass DB written to {}'.format(file_written.name))
    else:
        if samba_db:
            file_written = kp.save()
            smb_send(file_written.name, kdbx_file)
            logging.info('Sent database file to {}'.format(kdbx_file))
        else:
            file_written = kp.save(kdbx_file)
            logging.info('KeePass DB written to {}'.format(file_written.name))
示例#7
0
def keepassxc_new_ssh_key(db_name,
                          db_password,
                          passphrase="",
                          title="",
                          username=""):
    kp = PyKeePass(db_name, password=db_password)

    keyname = title.replace(" ", "-")

    ssh_group = kp.find_groups(name="SSH", first=True)
    if not ssh_group:
        ssh_group = kp.add_group(kp.root_group, "SSH")

    entry = kp.add_entry(ssh_group,
                         title=title,
                         username=username,
                         password=passphrase)

    pub, priv = generate_keys(passphrase)

    entry_ssh_settings = f"""\
<?xml version="1.0" encoding="UTF-16"?>
<EntrySettings xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <AllowUseOfSshKey>true</AllowUseOfSshKey>
  <AddAtDatabaseOpen>true</AddAtDatabaseOpen>
  <RemoveAtDatabaseClose>true</RemoveAtDatabaseClose>
  <UseConfirmConstraintWhenAdding>false</UseConfirmConstraintWhenAdding>
  <UseLifetimeConstraintWhenAdding>true</UseLifetimeConstraintWhenAdding>
  <LifetimeConstraintDuration>600</LifetimeConstraintDuration>
  <Location>
    <SelectedType>attachment</SelectedType>
    <AttachmentName>{keyname}</AttachmentName>
    <SaveAttachmentToTempFile>false</SaveAttachmentToTempFile>
  </Location>
</EntrySettings>"""

    attach(kp,
           entry,
           "KeeAgent.settings",
           entry_ssh_settings,
           encoding="utf-16")

    attach(kp, entry, keyname, priv)
    attach(kp, entry, f"{keyname}.pub", pub)

    kp.save()
示例#8
0
文件: tests.py 项目: mhild/pykeepass
class AttachmentTests3(KDBX3Tests):
    # get some things ready before testing
    def setUp(self):
        shutil.copy(
            os.path.join(base_dir, self.database),
            os.path.join(base_dir, 'test_attachment.kdbx')
        )
        self.open()

    def open(self):
        self.kp = PyKeePass(
            os.path.join(base_dir, 'test_attachment.kdbx'),
            password=self.password,
            keyfile=os.path.join(base_dir, self.keyfile)
        )

    def test_create_delete_attachment(self):
        attachment_id = self.kp.add_binary(b'Ronald McDonald Trump')
        self.kp.save()
        self.open()
        self.assertEqual(self.kp.binaries[-1], b'Ronald McDonald Trump')

        num_attach = len(self.kp.binaries)
        self.kp.delete_binary(len(self.kp.binaries) - 1)
        self.kp.save()
        self.open()
        self.assertEqual(len(self.kp.binaries), num_attach - 1)

    def test_attachment_reference_decrement(self):
        e = self.kp.entries[0]

        attachment_id1 = self.kp.add_binary(b'foobar')
        attachment_id2 = self.kp.add_binary(b'foobar2')

        attachment1 = e.add_attachment(attachment_id1, 'foo.txt')
        attachment2 = e.add_attachment(attachment_id2, 'foo.txt')

        self.kp.delete_binary(attachment_id1)

        self.assertEqual(attachment2.id, attachment_id2 - 1)

    def tearDown(self):
        os.remove(os.path.join(base_dir, 'test_attachment.kdbx'))
    def merge_two_databases(self, file_database1,
                       file_database2,
                       file_output_database,
                       master_password,
                       debug=False):
        try:
            kp1 = PyKeePass(file_database1, password=master_password)
        except CredentialsError:
            raise DB1WrongPasswordError
        try:
            kp2 = PyKeePass(file_database2, password=master_password)
        except CredentialsError:
            raise DB2WrongPasswordError

        self.sync_groups(kp2,kp1, debug=debug)
        self.sync_entries(kp2,kp1, debug=debug)
        self.sync_custom_properties(kp2,kp1, debug=debug)

        kp1.save(filename=file_output_database)
示例#10
0
class KeePass():
    def __init__(self, password, cfgfile='pass.yml'):
        keyfile = None
        with open(cfgfile, 'r') as ymlfile:
            cfg = yaml.safe_load(ymlfile)['keepass']
            dbfile = cfg['dbfile']
            group = cfg['group']
            newentry = cfg['newentry']
            oldentry = cfg['oldentry']
            if 'keyfile' in cfg:
                keyfile = cfg['keyfile']
        self.keepass = PyKeePass(dbfile, password=password, keyfile=keyfile)
        self.group = self.keepass.find_groups(name=group, first=True)
        self.oldentry = self.keepass.find_entries(
            title=oldentry, group=self.group, first=True)
        self.newentry = self.keepass.find_entries(
            title=newentry, group=self.group, first=True)

    def get_hosts(self):
        hosts = self.oldentry.url
        ret = []
        for host in re.split(r'\s+', hosts):
            ret.append(Host(
                host, self.newentry.username, self.oldentry.password,
                self.newentry.password))
        return ret

    def add_to_url(self, host):
        if self.newentry.url is not None:
            self.newentry.url = self.newentry.url + ' ' + host
        else:
            self.newentry.url = host
        self.keepass.save()

    def add_to_notes(self, msg):
        if self.newentry.notes is not None:
            self.newentry.notes = self.newentry.notes + '\n' + msg
        else:
            self.newentry.notes = msg
        self.keepass.save()
示例#11
0
文件: kdbx.py 项目: sgn/pass-import
class KDBX(Formatter, PasswordImporter, PasswordExporter):
    """Base class for KDBX based importer & exporter.

    The importer supports binary attachments. It requires PyKeePass to run.

    :param PyKeePass keepass: The keepass repository to work on.
    :param list attributes: List of the attributes of PyKeePass to import.

    """
    cap = Cap.FORMAT | Cap.IMPORT | Cap.EXPORT
    name = 'keepass'
    format = 'kdbx'
    magic = b'\x03\xd9\xa2\x9a'
    keys = {'login': '******', 'comments': 'notes', 'group': 'path'}
    attributes = {
        'title', 'username', 'password', 'url', 'notes', 'icon', 'tags',
        'autotype_enabled', 'autotype_sequence', 'path', 'is_a_history_entry'
    }

    def __init__(self, prefix=None, settings=None):
        self.keepass = None
        settings = {} if settings is None else settings
        keyfile = settings.get('key', '')
        self.keyfile = None if keyfile == '' else keyfile
        super(KDBX, self).__init__(prefix, settings)

    # Import methods

    def _getentry(self, kpentry):
        entry = dict()
        keys = self.invkeys()
        for attr in self.attributes:
            if hasattr(kpentry, attr):
                entry[keys.get(attr, attr)] = getattr(kpentry, attr)
        for key, value in kpentry.custom_properties.items():
            entry[key] = value
        return entry

    def parse(self):
        """Parse Keepass KDBX3 and KDBX4 files."""
        for kpentry in self.keepass.entries:
            if self.root not in kpentry.path:
                continue
            entry = self._getentry(kpentry)
            entry['group'] = os.path.dirname(entry['group'])

            if kpentry.history:
                for hentry in kpentry.history:
                    history = self._getentry(hentry)
                    history['group'] = os.path.join('History', entry['group'])
                    self.data.append(history)

            for att in kpentry.attachments:
                attachment = dict()
                attachment['group'] = entry['group']
                attachment['title'] = att.filename
                attachment['data'] = att.data
                self.data.append(attachment)
                if entry.get('attachments', None):
                    entry['attachments'] += ", %s" % att.filename
                else:
                    entry['attachments'] = att.filename
            self.data.append(entry)

    # Export methods

    def insert(self, entry):
        """Insert a password entry into KDBX encrypted vault file."""
        ignore = {'password', 'path', 'title', 'group', 'data'}
        path = os.path.join(self.root, entry.get('path'))
        title = os.path.basename(path)
        group = os.path.dirname(path)

        root_group = self.keepass.root_group
        kpgroup = self.keepass.find_groups(path=group)
        if not kpgroup:
            for grp in group.split('/'):
                kpgroup = self.keepass.find_groups(path=grp)
                if not kpgroup:
                    kpgroup = self.keepass.add_group(root_group, grp)
                root_group = kpgroup

        if not self.force:
            pkentry = self.keepass.find_entries(title=title,
                                                group=kpgroup,
                                                recursive=False,
                                                first=True)
            if pkentry is not None:
                raise PMError("An entry already exists for %s." % path)

        kpentry = self.keepass.add_entry(destination_group=kpgroup,
                                         title=title,
                                         username=entry.pop('login', ''),
                                         password=entry.pop('password', ''),
                                         url=entry.pop('url', None),
                                         notes=entry.pop('comments', None),
                                         tags=entry.pop('tags', None),
                                         expiry_time=entry.pop(
                                             'expiry_time', None),
                                         icon=entry.pop('icon', None),
                                         force_creation=True)

        for key, value in entry.items():
            if key in ignore:
                continue
            kpentry.set_custom_property(key, str(value))

        if 'data' in entry:
            attid = self.keepass.add_binary(entry['data'])
            kpentry.add_attachment(attid, title)

    # Context manager methods

    def open(self):
        """Open the keepass repository."""
        if not PYKEEPASS:
            raise ImportError(name='pykeepass')

        try:
            self.keepass = PyKeePass(self.prefix,
                                     password=getpassword(self.prefix),
                                     keyfile=self.keyfile)
        except CredentialsIntegrityError as error:
            raise PMError(error)

    def close(self):
        """Close the keepass repository."""
        self.keepass.save()

    # Format recognition methods

    def detecter_open(self):
        """Enter the tryformat context manager."""
        self.file = open(self.prefix, 'rb')

    def detecter_close(self):
        """Leave the tryformat context manager."""
        self.file.close()

    def is_format(self):
        """Return True if the file is a KDBX file."""
        sign = self.file.read(4)
        if sign != self.magic:
            return False
        return True

    def checkheader(self, header, only=False):
        """No header check."""
        return True

    @classmethod
    def header(cls):
        """No header for KDBX file."""
        return ''
def bitwarden_to_keepass(args):
    try:
        kp = PyKeePass(args.database_path,
                       password=args.database_password,
                       keyfile=args.database_keyfile)
    except FileNotFoundError:
        logging.info('KeePass database does not exist, creating a new one.')
        kp = create_database(args.database_path,
                             password=args.database_password,
                             keyfile=args.database_keyfile)
    except CredentialsError as e:
        logging.error(f'Wrong password for KeePass database: {e}')
        return

    folders = subprocess.check_output(
        f'{quote(args.bw_path)} list folders --session {quote(args.bw_session)}',
        shell=True,
        encoding='utf8')
    folders = json.loads(folders)
    # sort folders so that in the case of nested folders, the parents would be guaranteed to show up before the children
    folders.sort(key=lambda x: x['name'])
    groups_by_id = {}
    groups_by_name = {}
    for folder in folders:
        # entries not associated with a folder should go under the root group
        if folder['id'] is None:
            groups_by_id[folder['id']] = kp.root_group
            continue

        parent_group = kp.root_group
        target_name = folder['name']

        # check if this is a nested folder; set appropriate parent group if so
        folder_path_split = target_name.rsplit('/', maxsplit=1)
        if len(folder_path_split) > 1:
            parent_group = groups_by_name[folder_path_split[0]]
            target_name = folder_path_split[1]

        new_group = kp.add_group(parent_group, target_name)

        groups_by_id[folder['id']] = new_group
        groups_by_name[folder['name']] = new_group
    logging.info(f'Folders done ({len(groups_by_id)}).')

    items = subprocess.check_output(
        f'{quote(args.bw_path)} list items --session {quote(args.bw_session)}',
        shell=True,
        encoding='utf8')
    items = json.loads(items)
    logging.info(f'Starting to process {len(items)} items.')
    for item in items:
        bw_item = Item(item)

        is_duplicate_title = False
        try:
            while True:
                entry_title = bw_item.get_name(
                ) if not is_duplicate_title else '{name} - ({item_id}'.format(
                    name=bw_item.get_name(), item_id=bw_item.get_id())
                try:
                    entry = kp.add_entry(destination_group=groups_by_id[
                        bw_item.get_folder_id()],
                                         title=entry_title,
                                         username=bw_item.get_username(),
                                         password=bw_item.get_password(),
                                         notes=bw_item.get_notes())
                    break
                except Exception as e:
                    if 'already exists' in str(e):
                        is_duplicate_title = True
                        continue
                    raise

            totp_secret, totp_settings = bw_item.get_totp()
            if totp_secret and totp_settings:
                entry.set_custom_property('TOTP Seed', totp_secret)
                entry.set_custom_property('TOTP Settings', totp_settings)

            for uri in bw_item.get_uris():
                entry.url = uri['uri']
                break  # todo append additional uris to notes?

            for field in bw_item.get_custom_fields():
                entry.set_custom_property(field['name'], field['value'])

            for card_field_name, card_field_val in bw_item.get_card().items():
                if card_field_val is not None:
                    entry.set_custom_property(
                        f"{CUSTOM_FIELD_PREFIX}_CARD_{card_field_name}",
                        card_field_val)

            for identity_field_name, identity_field_val in bw_item.get_identity(
            ).items():
                if identity_field_val is not None:
                    entry.set_custom_property(
                        f"{CUSTOM_FIELD_PREFIX}_IDENTITY_{identity_field_name}",
                        identity_field_val)

            for attachment in bw_item.get_attachments():
                attachment_tmp_path = f'{args.tmp_path}/attachment/{attachment["fileName"]}'
                attachment_path = subprocess.check_output(
                    f'{quote(args.bw_path)} get attachment'
                    f' --raw {quote(attachment["id"])} '
                    f'--itemid {quote(bw_item.get_id())} '
                    f'--output {quote(attachment_tmp_path)} --session {quote(args.bw_session)}',
                    shell=True,
                    encoding='utf8').rstrip()
                attachment_id = kp.add_binary(
                    open(attachment_path, 'rb').read())
                entry.add_attachment(attachment_id, attachment['fileName'])
                os.remove(attachment_path)

        except Exception as e:
            logging.warning(
                f'Skipping item named "{item["name"]}" because of this error: {repr(e)}'
            )
            continue

    logging.info('Saving changes to KeePass database.')
    kp.save()
    logging.info('Export completed.')
示例#13
0
def bitwarden_to_keepass(args):
    try:
        kp = PyKeePass(args.database_path,
                       password=args.database_password,
                       keyfile=args.database_keyfile)
    except FileNotFoundError:
        logging.info('KeePass database does not exist, creating a new one.')
        kp = create_database(args.database_path,
                             password=args.database_password,
                             keyfile=args.database_keyfile)
    except CredentialsError as e:
        logging.error(f'Wrong password for KeePass database: {e}')
        return

    folders = subprocess.check_output(
        f'{quote(args.bw_path)} list folders --session {quote(args.bw_session)}',
        shell=True,
        encoding='utf8')
    folders = json.loads(folders)
    groups = {}
    for folder in folders:
        groups[folder['id']] = kp.add_group(kp.root_group, folder['name'])
    logging.info(f'Folders done ({len(groups)}).')

    items = subprocess.check_output(
        f'{quote(args.bw_path)} list items --session {quote(args.bw_session)}',
        shell=True,
        encoding='utf8')
    items = json.loads(items)
    logging.info(f'Starting to process {len(items)} items.')
    for item in items:
        if item['type'] in [ItemTypes.CARD, ItemTypes.IDENTITY]:
            logging.warning(
                f'Skipping credit card or identity item "{item["name"]}".')
            continue

        bw_item = Item(item)

        is_duplicate_title = False
        try:
            while True:
                entry_title = bw_item.get_name(
                ) if not is_duplicate_title else '{name} - ({item_id}'.format(
                    name=bw_item.get_name(), item_id=bw_item.get_id())
                try:
                    entry = kp.add_entry(
                        destination_group=groups[bw_item.get_folder_id()],
                        title=entry_title,
                        username=bw_item.get_username(),
                        password=bw_item.get_password(),
                        notes=bw_item.get_notes())
                    break
                except Exception as e:
                    if 'already exists' in str(e):
                        is_duplicate_title = True
                        continue
                    raise

            totp_secret, totp_settings = bw_item.get_totp()
            if totp_secret and totp_settings:
                entry.set_custom_property('TOTP Seed', totp_secret)
                entry.set_custom_property('TOTP Settings', totp_settings)

            for uri in bw_item.get_uris():
                entry.url = uri['uri']
                break  # todo append additional uris to notes?

            for field in bw_item.get_custom_fields():
                entry.set_custom_property(field['name'], field['value'])

            for attachment in bw_item.get_attachments():
                attachment_tmp_path = f'/tmp/attachment/{attachment["fileName"]}'
                attachment_path = subprocess.check_output(
                    f'{quote(args.bw_path)} get attachment'
                    f' --raw {quote(attachment["id"])} '
                    f'--itemid {quote(bw_item.get_id())} '
                    f'--output {quote(attachment_tmp_path)} --session {quote(args.bw_session)}',
                    shell=True,
                    encoding='utf8').rstrip()
                attachment_id = kp.add_binary(
                    open(attachment_path, 'rb').read())
                entry.add_attachment(attachment_id, attachment['fileName'])
                os.remove(attachment_path)

        except Exception as e:
            logging.warning(
                f'Skipping item named "{item["name"]}" because of this error: {repr(e)}'
            )
            continue

    logging.info('Saving changes to KeePass database.')
    kp.save()
    logging.info('Export completed.')
示例#14
0
class KeepassVault(Vault):
    def __init__(self, vault_configs):

        validate(vault_configs, "yac/schema/vaults/keepass.json")

        self.vault_path = search('"vault-path"', vault_configs)
        vault_pwd_path = search('"vault-pwd-path"', vault_configs)
        self.vault_pwd = search('"vault-pwd"', vault_configs)

        if not self.vault_pwd and vault_pwd_path and os.path.exists(
                vault_pwd_path):
            self.vault_pwd = read_pwd_file(vault_pwd_path)

        self.ready = False
        self.initialized = False
        self.kp = None

    def get_type(self):
        return "keepass"

    def initialize(self, params):

        servicefile_path = params.get("servicefile-path", "")

        # apply intrinsics in the vault password
        vault_pwd = apply_intrinsics(self.vault_pwd, params)

        full_path = os.path.join(servicefile_path, self.vault_path)

        if os.path.exists(full_path):

            if vault_pwd:
                try:
                    self.kp = PyKeePass(full_path, password=vault_pwd)
                    self.ready = True
                    self.initialized = True

                except IOError as e:
                    print(e)
            else:
                self.ready = False
                self.initialized = False

    def is_ready(self):
        return self.ready

    def is_initialized(self):
        return self.initialized

    def get(self, lookup_config):

        entry = self.kp.find_entries(path=lookup_config['path'], first=True)

        value = ""

        if entry:
            field_name = lookup_config['field']
            if field_name == "password":
                value = entry.password
            elif field_name == "username":
                value = entry.username
            elif field_name == "url":
                value = entry.url
            elif field_name == "notes":
                value = entry.notes

        return value

    def set(self, lookup_config, secret_value):

        entry = self.kp.find_entries(path=lookup_config['path'], first=True)

        if entry:
            field_name = lookup_config['field']
            if field_name == "password":
                entry.password = secret_value
            elif field_name == "username":
                entry.username = secret_value
            elif field_name == "url":
                entry.url = secret_value

        self.kp.save()

    def load_cached_vault_path(self):

        vault_path = get_cache_value('keepass-vault-path')

        if not vault_path:

            vault_path = string_validation(
                "KeePass Vault Path",
                "Path to the KeePass vault file for secrets lookup", [],
                path_validation, True)

            set_cache_value_ms('keepass-vault-path', vault_path)

        return vault_path

    def load_cached_vault_pwd(self):

        vault_pwd = get_cache_value('keepass-vault-pwd')

        if not vault_pwd:

            vault_pwd = string_validation(
                "KeePass Vault Password",
                "The master key for the KeePass vault", [], string_validation,
                True, 100, True)

            set_cache_value_ms('keepass-vault-pwd', vault_pwd)

        return vault_pwd

    def clear_secrets_cache(self):
        set_cache_value_ms('keepass-vault-path', "")
        set_cache_value_ms('keepass-vault-pwd', "")
示例#15
0
def bitwarden_to_keepass(args):
    try:
        kp = PyKeePass(args.database_path,
                       password=args.database_password,
                       keyfile=args.database_keyfile)
    except FileNotFoundError:
        logging.info('KeePass database does not exist, creating a new one.')
        kp = create_database(args.database_path,
                             password=args.database_password,
                             keyfile=args.database_keyfile)
    except CredentialsIntegrityError as e:
        logging.error(f'Wrong password for KeePass database: {e}')
        return

    folders = subprocess.check_output(
        f'{quote(args.bw_path)} list folders --session {quote(args.bw_session)}',
        shell=True,
        encoding='utf8')
    folders = json.loads(folders)
    groups = {}
    for folder in folders:
        groups[folder['id']] = kp.add_group(kp.root_group, folder['name'])
    logging.info(f'Folders done ({len(groups)}).')

    items = subprocess.check_output(
        f'{quote(args.bw_path)} list items --session {quote(args.bw_session)}',
        shell=True,
        encoding='utf8')
    items = json.loads(items)
    logging.info(f'Starting to process {len(items)} items.')
    for item in items:
        if item['type'] == ItemTypes.CARD:
            logging.warning(f'Skipping credit card item "{item["name"]}".')
            continue

        bw_item = Item(item)

        e = kp.add_entry(groups[bw_item.get_folder_id()],
                         title=bw_item.get_name(),
                         username=bw_item.get_username(),
                         password=bw_item.get_password(),
                         notes=bw_item.get_notes())

        totp_secret, totp_settings = bw_item.get_totp()
        if totp_secret and totp_settings:
            e.set_custom_property('TOTP Seed', totp_secret)
            e.set_custom_property('TOTP Settings', totp_settings)

        for uri in bw_item.get_uris():
            e.url = uri['uri']
            break  # todo append additional uris to notes?

        for field in bw_item.get_custom_fields():
            e.set_custom_property(str(field['name']), field['value'])

        for attachment in bw_item.get_attachments():
            attachment_tmp_path = f'./attachment_tmp/{attachment["fileName"]}'
            attachment_path = subprocess.check_output(
                f'{quote(args.bw_path)} get attachment'
                f' --raw {quote(attachment["id"])} '
                f'--itemid {quote(bw_item.get_id())} '
                f'--output {quote(attachment_tmp_path)} --session {quote(args.bw_session)}',
                shell=True,
                encoding='utf8').rstrip()
            attachment_id = kp.add_binary(open(attachment_path, 'rb').read())
            e.add_attachment(attachment_id, attachment['fileName'])
            os.remove(attachment_path)

    logging.info('Saving changes to KeePass database.')
    kp.save()
    logging.info('Export completed.')
示例#16
0
    def test_open_save(self):
        """try to open all databases, save them, then open the result"""

        with open(os.path.join(base_dir, 'test3.kdbx'), 'rb') as file:
            stream = BytesIO(file.read())

        filenames_in = [
            os.path.join(base_dir, 'test3.kdbx'),           # KDBX v3 test
            os.path.join(base_dir, 'test4.kdbx'),           # KDBX v4 test
            os.path.join(base_dir, 'test4_aes.kdbx'),       # KDBX v4 AES test
            os.path.join(base_dir, 'test4_aeskdf.kdbx'),    # KDBX v3 AESKDF test
            os.path.join(base_dir, 'test4_chacha20.kdbx'),  # KDBX v4 ChaCha test
            os.path.join(base_dir, 'test4_twofish.kdbx'),   # KDBX v4 Twofish test
            os.path.join(base_dir, 'test4_hex.kdbx'),       # legacy 64 byte hexadecimal keyfile test
            os.path.join(base_dir, 'test3.kdbx'),           # KDBX v3 transformed_key open test
            os.path.join(base_dir, 'test4_hex.kdbx'),       # KDBX v4 transformed_key open test
            stream,
            os.path.join(base_dir, 'test4_aes_uncompressed.kdbx')    # KDBX v4 AES uncompressed test
        ]
        filenames_out = [
            os.path.join(base_dir, 'test3.kdbx.out'),
            os.path.join(base_dir, 'test4.kdbx.out'),
            os.path.join(base_dir, 'test4_aes.kdbx.out'),
            os.path.join(base_dir, 'test4_aeskdf.kdbx.out'),
            os.path.join(base_dir, 'test4_chacha20.kdbx.out'),
            os.path.join(base_dir, 'test4_twofish.kdbx.out'),
            os.path.join(base_dir, 'test4_hex.kdbx.out'),
            os.path.join(base_dir, 'test3.kdbx.out'),
            os.path.join(base_dir, 'test4_hex.kdbx.out'),
            BytesIO(),
            os.path.join(base_dir, 'test4_aes_uncompressed.kdbx.out'),
            os.path.join(base_dir, 'test4_twofish_uncompressed.kdbx.out'),
            os.path.join(base_dir, 'test4_chacha20_uncompressed.kdbx.out'),
        ]
        passwords = [
            'password',
            'password',
            'password',
            'password',
            'password',
            'password',
            'password',
            None,
            None,
            'password',
            'password',
            'password',
            'password',
        ]
        transformed_keys = [
            None,
            None,
            None,
            None,
            None,
            None,
            None,
            b'\xfb\xb1!\x0e0\x94\xd4\x868\xa5\x04\xe6T\x9b<\xf9+\xb8\x82EN\xbc\xbe\xbc\xc8\xd3\xbbf\xfb\xde\xff.',
            b'M\xb7\x08\xf6\xa7\xd1v\xb1{&\x06\x8f\xae\xe9\r\xeb\x9a\x1b\x02b\xce\xf2\x8aR\xaea)7\x1fs\xe9\xc0',
            None,
            None,
            None,
            None,
        ]
        keyfiles = [
            'test3.key',
            'test4.key',
            'test4.key',
            'test4.key',
            'test4.key',
            'test4.key',
            'test4_hex.key',
            None,
            None,
            'test3.key',
            None,
            None,
            None,
        ]
        encryption_algorithms = [
            'aes256',
            'chacha20',
            'aes256',
            'aes256',
            'chacha20',
            'twofish',
            'chacha20',
            'aes256',
            'chacha20',
            'aes256',
            'aes256',
            'twofish',
            'chacha20',
        ]
        kdf_algorithms = [
            'aeskdf',
            'argon2',
            'argon2',
            'aeskdf',
            'argon2',
            'argon2',
            'argon2',
            'aeskdf',
            'argon2',
            'aeskdf',
            'argon2',
            'argon2',
            'argon2',
        ]
        versions = [
            (3, 1),
            (4, 0),
            (4, 0),
            (4, 0),
            (4, 0),
            (4, 0),
            (4, 0),
            (3, 1),
            (4, 0),
            (3, 1),
            (4, 0),
            (4, 0),
            (4, 0),
        ]

        for (filename_in, filename_out, password, transformed_key,
             keyfile, encryption_algorithm, kdf_algorithm, version) in zip(
                 filenames_in, filenames_out, passwords, transformed_keys,
                 keyfiles, encryption_algorithms, kdf_algorithms, versions
        ):
            kp = PyKeePass(
                filename_in,
                password,
                None if keyfile is None else os.path.join(base_dir, keyfile),
                transformed_key=transformed_key
            )
            self.assertEqual(kp.encryption_algorithm, encryption_algorithm)
            self.assertEqual(kp.kdf_algorithm, kdf_algorithm)
            self.assertEqual(kp.version, version)

            kp.save(
                filename_out,
                transformed_key=transformed_key
            )

            if hasattr(filename_out, "seek"):
                # rewind so PyKeePass can read from the same stream
                filename_out.seek(0)

            kp = PyKeePass(
                filename_out,
                password,
                None if keyfile is None else os.path.join(base_dir, keyfile),
                transformed_key=transformed_key
            )

        for filename in os.listdir(base_dir):
            if filename.endswith('.out'):
                os.remove(os.path.join(base_dir, filename))
示例#17
0
    print("Modo de empleo: {} <input.geco>")
    sys.exit()

input_file = sys.argv[1]
output_file = 'db.kdbx'
master = getpass.getpass("Contraseña maestra: ")

aes = CustomAES()
kp = PyKeePass('database.kdbx', password="******")
kp.password = master

groups = {}

with open(input_file, 'r') as f:
    for p in f.readlines():
        name, type, description, account, password, cypher_method, updated, expiration = p.split("|")
        expiration = datetime.datetime.fromtimestamp(float(expiration))
        updated = datetime.datetime.fromtimestamp(float(updated))
        name, type, description, account =\
                map(lambda x: x.replace("\\n", "\n"), (name, type, description, account))

        clear = aes.decrypt(password, master)

        if type and not type in groups:
            group = kp.add_group(kp.root_group, type)
            groups[type] = group
        group = groups.get(type, kp.root_group)

        kp.add_entry(group, name, account, clear, notes=description)
    kp.save(output_file)
示例#18
0
class P2KP2:
    """Convert a Pass db into a Keepass2 one."""

    db: PyKeePass

    def __init__(self,
                 password: str,
                 destination: str = None,
                 overwrite: bool = False):
        """Constructor for P2KP2

        :param password: the password for the new Keepass db
        :param destination: the final db path
        :param overwrite: force writing over existing database
        """
        if destination is None:
            destination = "pass.kdbx"
        if not os.path.exists(destination) or overwrite:
            copyfile(empty_db_path, destination)
        else:
            raise DbAlreadyExistsException()
        self.db = PyKeePass(destination)
        self.db.password = password
        self.db.save()
        self.event_stream = Subject()

    def populate_db(self, pass_reader: PassReader):
        """Populate the keepass db with data from the PassReader."""
        i = 0
        for pass_entry in pass_reader.entries:
            self.add_entry(pass_entry)
            i = i + 1
            self.event_stream.on_next(i)
        self.db.save()

    def add_entry(self, pass_entry: PassEntry) -> Entry:
        """Add a keepass entry to the db containing all data from the relative pass entry. Create the group if needed.

        :param pass_entry: the original pass entry
        :return: the newly added keepass entry
        """
        # find the correct group for the entry. If not there, create it
        entry_group = self.db.root_group  # start from the root group
        if len(pass_entry.groups) > 0:
            for group_name in pass_entry.groups:
                # since pass folder names are unique, the possible first result is also the only one
                group = self.db.find_groups(name=group_name,
                                            recursive=False,
                                            group=entry_group,
                                            first=True)
                if group is None:
                    # the group is not already there, let's create it
                    group = self.db.add_group(destination_group=entry_group,
                                              group_name=group_name)
                entry_group = group
        # create the entry, setting group, title, user and pass
        entry = self.db.add_entry(entry_group, pass_entry.title,
                                  pass_entry.user, pass_entry.password)
        # set the url and the notes
        entry.url = pass_entry.url
        entry.notes = pass_entry.notes
        # add all custom fields
        for pass_entry, value in pass_entry.custom_properties.items():
            entry.set_custom_property(pass_entry, value)
        return entry
示例#19
0
class KDBX(Formatter, PasswordImporter, PasswordExporter):
    """Base class for KDBX based importer & exporter.

    The importer supports binary attachments. It requires PyKeePass to run.

    :param PyKeePass keepass: The keepass repository to work on.
    :param list attributes: List of the attributes of PyKeePass to import.

    """
    cap = Cap.FORMAT | Cap.IMPORT | Cap.EXPORT
    name = 'keepass'
    format = 'kdbx'
    magic = b'\x03\xd9\xa2\x9a'
    keys = {'login': '******', 'comments': 'notes', 'group': 'path'}
    attributes = {
        'title', 'username', 'password', 'url', 'notes', 'icon', 'tags',
        'autotype_enabled', 'autotype_sequence', 'is_a_history_entry'
    }
    reference = re.compile(r'\{REF:([A-Z])@I:([0-9A-F]{32})\}')

    def __init__(self, prefix=None, settings=None):
        self.keepass = None
        settings = {} if settings is None else settings
        keyfile = settings.get('key', '')
        self.keyfile = None if keyfile == '' else keyfile
        super(KDBX, self).__init__(prefix, settings)

    # Import methods

    def _getentry(self, kpentry):
        entry = dict()
        entry['group'] = os.sep.join(kpentry.path)
        keys = self.invkeys()
        for attr in self.attributes:
            if hasattr(kpentry, attr):
                value = getattr(kpentry, attr)
                if isinstance(value, str):
                    value = self._subref(value)
                entry[keys.get(attr, attr)] = value
        for key, value in kpentry.custom_properties.items():
            if isinstance(value, str):
                value = self._subref(value)
            entry[key] = value
        otpauth = self._getotpauth(kpentry.custom_properties)
        if otpauth:
            entry['otpauth'] = otpauth
        return entry

    def _getotpauth(self, properties):
        # KeeWeb style
        if 'otp' in properties:
            return properties['otp']

        issuer = 'Imported'
        # KeePass 2.47 {TIMEOTP} style
        if 'TimeOtp-Secret-Base32' in properties:
            seed = properties['TimeOtp-Secret-Base32']
            # TODO: support other secret formats, or actually specifying settings
            digits = '6'
        # KeeTrayTOTP style
        elif 'TOTP Seed' in properties:
            seed = properties['TOTP Seed']
            # Special-case Steam
            if 'TOTP Settings' in properties and properties[
                    'TOTP Settings'] == '30;S':
                # Android Password Store checks for digits==s
                # https://github.com/android-password-store/Android-Password-Store/blob/5e66d99c852ea67a88b650c03b0e8d55e83eccde/app/src/main/java/dev/msfjarvis/aps/util/totp/Otp.kt#L41
                digits = 's'
                # pass-otp, via Pass::Otp, checks for issuer=~Steam
                # https://github.com/tadfisher/pass-otp/issues/97
                # https://github.com/baierjan/Pass-OTP-perl/blob/10242388a9ce6633a3f39697e1a4b2af079b7f77/lib/Pass/OTP.pm#L140
                issuer = 'Steam'
            else:
                # TODO: parse non-'30;6' settings
                digits = '6'
        else:
            return None

        # Many sites print the secret with spaces
        seed = seed.replace(' ', '')

        return f'otpauth://totp/totp-secret?secret={seed}&issuer={issuer}&digits={digits}&period=30'

    def _subref(self, value):
        while True:
            match = self.reference.search(value)
            if match is None:
                break
            cat, attid = match.group(1, 2)
            if cat not in ('U', 'P'):
                break
            start, end = match.start(0), match.end(0)
            kpentry = self.keepass.find_entries(uuid=uuid.UUID(attid))[0]
            if kpentry is None:
                value = value[:start] + value[end:]
            else:
                attr = 'password' if cat == 'P' else 'username'
                if hasattr(kpentry, attr):
                    attr = getattr(kpentry, attr)
                    value = value[:start] + \
                        (attr if attr is not None else '') + value[end:]
                else:
                    value = value[:start] + value[end:]
        return value

    def parse(self):
        """Parse Keepass KDBX3 and KDBX4 files."""
        for kpentry in self.keepass.entries:
            if self.root not in os.sep.join(kpentry.path):
                continue
            entry = self._getentry(kpentry)
            entry['group'] = os.path.dirname(entry['group'])

            if kpentry.history:
                for hentry in kpentry.history:
                    history = self._getentry(hentry)
                    history['group'] = os.path.join('History', entry['group'])
                    self.data.append(history)

            for att in kpentry.attachments:
                attachment = dict()
                attachment['group'] = entry['group']
                attachment['title'] = att.filename
                attachment['data'] = att.data
                self.data.append(attachment)
                if entry.get('attachments', None):
                    entry['attachments'] += ", %s" % att.filename
                else:
                    entry['attachments'] = att.filename
            self.data.append(entry)

    # Export methods

    def insert(self, entry):
        """Insert a password entry into KDBX encrypted vault file."""
        ignore = {'password', 'path', 'title', 'group', 'data'}
        path = os.path.join(self.root, entry.get('path'))
        title = os.path.basename(path)
        group = os.path.dirname(path)

        root_group = self.keepass.root_group
        kpgroup = self.keepass.find_groups(path=group)
        if not kpgroup:
            for grp in group.split('/'):
                kpgroup = self.keepass.find_groups(path=grp)
                if not kpgroup:
                    kpgroup = self.keepass.add_group(root_group, grp)
                root_group = kpgroup

        if not self.force:
            pkentry = self.keepass.find_entries(title=title,
                                                group=kpgroup,
                                                recursive=False,
                                                first=True)
            if pkentry is not None:
                raise PMError("An entry already exists for %s." % path)

        kpentry = self.keepass.add_entry(destination_group=kpgroup,
                                         title=title,
                                         username=entry.pop('login', ''),
                                         password=entry.pop('password', ''),
                                         url=entry.pop('url', None),
                                         notes=entry.pop('comments', None),
                                         tags=entry.pop('tags', None),
                                         expiry_time=entry.pop(
                                             'expiry_time', None),
                                         icon=entry.pop('icon', None),
                                         force_creation=True)

        for key, value in entry.items():
            if key in ignore:
                continue
            kpentry.set_custom_property(key, str(value))

        if 'data' in entry:
            attid = self.keepass.add_binary(entry['data'])
            kpentry.add_attachment(attid, title)

    # Context manager methods

    def open(self):
        """Open the keepass repository."""
        if not PYKEEPASS:
            raise ImportError(name='pykeepass')

        try:
            self.keepass = PyKeePass(self.prefix,
                                     password=getpassword(self.prefix),
                                     keyfile=self.keyfile)
        except (CredentialsError, PayloadChecksumError,
                HeaderChecksumError) as error:  # pragma: no cover
            raise PMError(error)

    def close(self):
        """Close the keepass repository."""
        self.keepass.save()

    # Format recognition methods

    def detecter_open(self):
        """Enter the tryformat context manager."""
        self.file = open(self.prefix, 'rb')

    def detecter_close(self):
        """Leave the tryformat context manager."""
        self.file.close()

    def is_format(self):
        """Return True if the file is a KDBX file."""
        sign = self.file.read(4)
        if sign != self.magic:
            return False
        return True

    def checkheader(self, header, only=False):
        """No header check."""
        return True

    @classmethod
    def header(cls):
        """No header for KDBX file."""
        return ''
示例#20
0
parser.add_argument('-i', '--input-password', type=str, help='input keepass password', metavar='password')
parser.add_argument('-o', '--output-password', type=str, help='output keepass password', metavar='password')
parser.add_argument('-a', '--attribute', type=str, default='extract_to', help='attribute for getting entries', metavar='attribute')
args = parser.parse_args()
search_attribute = args.attribute
input_path = args.input_keepass
output_path = args.output_keepass
# ask for passwort if not passed by command line
input_password = args.input_password if args.input_password else getpass(prompt='Input KeePass password:'******'Output KeePass password:'******'.*'
for entry in input_keepass.find_entries(string=searchstring, regex=True):
    _add_entry(output_keepass, entry)

# finally, save the output keepass
output_keepass.save()
示例#21
0
# load database
kp = PyKeePass(dbfile, password=os.environ['PASSWORD'])
group = kp.find_groups(name=groupname, first=True)

count = 1
with open(tempfile, "r") as rd:
    # Read lines in loop
    for line in rd:
        # All lines (besides the last) will include  newline, so strip it
        data = line.strip()
        data = data.split(';;;')

        if len(data) != 4:
            print("Fehlerhafte Eingabe! Zeile: " + str(count))
            print(data)
            sys.exit()

        # Variablen setzen
        title = str(data[0])
        user = str(data[1])
        password = str(data[2])
        notes = str(data[3])

        # Eintrag in KeePassDB schreiben (temporär, nicht gespeichert)
        kp.add_entry(group, title, user, password, None, notes)
        count += 1

kp.save()

sys.exit()
示例#22
0
文件: passhole.py 项目: vdng/passhole
def init_database(args):
    """Create database"""
    # from pykeepass.pykeepass import PyKeePass

    # ----- setup config -----

    c = ConfigParser()
    if os.path.exists(args.config):
        c.read(args.config)

    if args.name is None:
        database_name = editable_input("Database name (no spaces)", "passhole")
    else:
        database_name = args.name

    if database_name in c.sections():
        log.error(
            red("There is already a database named ") + bold(database_name) +
            red(" in ") + bold(args.config))
        sys.exit(1)
    else:
        c.add_section(database_name)

    if not os.path.exists(args.config):
        c.set(database_name, 'default', 'True')

    # ----- database prompt -----

    if args.name is None:
        database_path = editable_input("Desired database path",
                                       default_database.format(database_name))
    else:
        database_path = args.database.format(database_name)

    # quit if database already exists
    if os.path.exists(database_path):
        log.error(red("Found database at ") + bold(database_path))
        sys.exit(1)
    else:
        c.set(database_name, 'database', database_path)

    # ----- password prompt -----

    if args.name is None:
        use_password = boolean_input("Password protect database?")
        if use_password:
            password = getpass(green('Password: '******'Confirm: '))

            if not password == password_confirm:
                log.error(red("Passwords do not match"))
                sys.exit(1)
        else:
            password = None
            c.set(database_name, 'no-password', 'True')
    else:
        password = args.password
        if password is None:
            c.set(database_name, 'no-password', 'True')

    # ----- keyfile prompt -----

    if args.name is None:
        use_keyfile = boolean_input("Use a keyfile?")
        if use_keyfile:
            keyfile = editable_input("Desired keyfile path",
                                     default_keyfile.format(database_name))
        else:
            keyfile = None
    else:
        keyfile = args.keyfile

    # ----- create keyfile/database/config -----
    # create keyfile
    if keyfile is not None:

        keyfile = realpath(expanduser(keyfile))

        log.debug("Looking for keyfile at {}".format(keyfile))
        if os.path.exists(keyfile):
            print("Found existing keyfile at {}  Exiting".format(
                bold(keyfile)))
            sys.exit(1)

        print("Creating keyfile at " + bold(keyfile))
        os.makedirs(dirname(keyfile), exist_ok=True)
        c.set(database_name, 'keyfile', keyfile)
        with open(keyfile, 'w') as f:
            log.debug("keyfile contents {}".format(keyfile_contents))
            f.write(keyfile_contents.format(
                b64encode(os.urandom(32)).decode()))

    database_path = realpath(expanduser(database_path))
    # create database
    print("Creating database at {}".format(bold(database_path)))
    os.makedirs(dirname(database_path), exist_ok=True)
    shutil.copy(template_database_file, database_path)

    from pykeepass import PyKeePass
    kp = PyKeePass(database_path, password='******')
    kp.password = password
    kp.keyfile = keyfile
    kp.save()

    config = realpath(expanduser(args.config))
    # create config
    print("Creating config at {}".format(bold(config)))
    os.makedirs(dirname(config), exist_ok=True)
    with open(config, 'w') as f:
        c.write(f)
示例#23
0
class KeepassLoader:

    kp = NotImplemented
    database_path = ""
    password_try = ""
    password_check = ""
    password = ""
    group_list = []

    def __init__(self, database_path, password):
        self.kp = PyKeePass(database_path, password)
        self.database_path = database_path

    def add_group(self, name, icon, note, parent_group):
        group = Group(name, icon, note, parent_group)
        self.kp.add_group(group.get_parent_group(), group.get_name())
        self.group_list.append(group)

    def add_entry(self, group_path, entry_name, username, password, url, notes,
                  icon):
        entry = Entry(group_path, entry_name, username, password, url, notes,
                      icon)
        self.kp.add_entry(self.kp.find_groups_by_path(entry.get_group_path()),
                          entry.get_entry_name(),
                          entry.get_username(),
                          entry.get_password(),
                          url=entry.get_url(),
                          notes=entry.get_notes(),
                          icon=entry.get_icon())

    def get_entries(self, group_path):
        group = self.kp.find_groups_by_path(group_path, first=True)
        #group = self.kp.find_groups(name="Untergruppe", first=True)
        print(group)
        print(group.entries)
        entry_list = []
        for entry in group.entries:
            entry_list.append(
                Entry(group, entry.title, entry.username, entry.password,
                      entry.url, entry.notes, entry.icon))
        return entry_list

    def get_groups(self):
        group_list = []
        groups = self.kp.groups
        for group in groups:
            if group.path != "/":
                group_list.append(
                    Group(group.name,
                          group.path,
                          icon=group.icon,
                          notes="",
                          parent_group=group.parent_group))
        return group_list

    #we wanted to turn off the automatic saving after each action and connect it instead to a button
    def save(self):
        self.kp.save()

    #this method sets the initial password for the newly created database
    def set_database_password(self, new_password):
        self.kp.set_credentials(new_password)
        self.save()

    #this method changes the password of existing database (therefore the old password must be typed in to prevent others changing your password)
    def change_database_password(self, old_password, new_password):
        if self.password == old_password:
            self.kp.set_credentials(new_password)
            self.save()

    #
    # Return the database filesystem path
    #

    def get_database(self):
        print(self.database_path)
        return self.database_path

    #
    # Return the root group of the database instance
    #

    def get_root_group(self):
        return self.kp.root_group

    #
    # Set the first password entered by the user (for comparing reasons)
    #

    def set_password_try(self, password):
        self.password_try = password

    #
    # Set the second password entered by the user (for comparing reasons)
    #

    def set_password_check(self, password):
        self.password_check = password

    #
    # Compare the first password entered by the user with the second one
    #

    def compare_passwords(self):
        if self.password_try == self.password_check:
            if self.password_try == "" and self.password_check == "":
                return False
            else:
                return True
        else:
            return False
def main(input_file, target_file, password):
    def matches(query, card):
        try:
            if query is None:
                return True

            query = query.lower()
            if query in card['@title'].lower():
                return True

            # for field in card['field']:
            #     if query in field['@name'].lower():
            #         return True

            #     if '#text' in field and query in field['#text'].lower():
            #         return True
        except:
            pass

        return False

    if len(sys.argv) == 2:
        search = sys.argv[1]
    else:
        search = None

    db = Decrypter(input_file, password)
    kp = PyKeePass('New3.kdbx', password='******')
    kp.root_group.name = "test_title"
    kp.password = password
    entries = []
    try:
        xml = db.decrypt()
        xml = parseString(xml)
    except:
        print("cannot decrypt, maybe wrong password?")
        sys.exit(1)

    for node in xml.getElementsByTagName('card'):
        is_template = False
        if node.hasAttribute('template'):
            is_template = (node.attributes['template'].value == 'true')

        if not is_template:
            entries.append(Entry(node))

    duplicate_check = set()
    for entry in entries:

        password = ""
        login = ""
        url = ""
        notes = ""
        # extract all types the fields and their value
        type_value = {
            entry.fields[x].type: entry.fields[x].value
            for x in entry.fields
        }
        # map the type of the field in safeincloud to the field type in pykeepass
        map_types = {
            "password": "******",
            "login": "******",
            "website": "url",
            "notes": "notes"
        }
        # username and password are required fields
        mapped_type_value = {"username": "", "password": ""}
        # add all other fields with the new names
        mapped_type_value.update({
            map_types[x]: type_value[x]
            for x in type_value if x in map_types
        })

        # ensure that the title is unique
        title = entry.title
        if title in duplicate_check:
            i = 2
            while title + str(i) in duplicate_check:
                i = i + 1
            title = title + str(i)
            assert title not in duplicate_check

        # add entry to keepass file
        kp.add_entry(kp.root_group, title, **mapped_type_value)
        # add title to duplicate check
        duplicate_check.add(title)

    kp.save(target_file)
    print("file successful mapped")
示例#25
0
def write_token_data(entry_name,
                     kps_group,
                     token_data,
                     kps_pswd,
                     history_group=None):
    try:
        kp = PyKeePass(kps_file, password=kps_pswd)
        entry = kp.find_entries(title=entry_name, first=True)

        if entry is not None:
            notes = entry._get_string_field('Notes')
            updated_notes = ''
            current_envs = dict()

            for env in notes.split('\n'):
                try:
                    splitted = env.split(':')
                    current_envs.update({splitted[0]: splitted[1]})
                except:
                    pass

            for updated_environment in token_data.keys():
                if history_group:
                    if updated_environment == history_group:
                        entry.notes = updated_notes
                        entry.expiry_time = datetime.now() + timedelta(
                            days=365)
                        entry.expires = True

                else:
                    entry.notes = updated_notes
                    entry.expiry_time = datetime.now() + timedelta(days=365)
                    entry.expires = True

            for current_env_name, current_env_token in current_envs.items():
                if current_env_name not in token_data.keys():
                    token_data.update({current_env_name: current_env_token})

            for env_name, env_token in token_data.items():
                updated_notes += env_name + ': ' + env_token + '\n'

        else:
            group = kp.find_groups(name=kps_group, first=True)
            entry = kp.add_entry(group, entry_name, '', '')
            notes = ''

            for env_name, env_token in token_data.items():
                notes += env_name + ': ' + env_token + '\n'

            entry.notes = notes
            entry.expiry_time = datetime.now() + timedelta(days=365)
            entry.expires = True

        kp.save()

        return True

    except Exception as e:
        print('[ERRO] - Erro ao gravar dados no Keepass %s:\n%s' %
              (kps_file, str(e)),
              file=sys.stderr)
        pass