Ejemplo n.º 1
0
 def setUp(self):
     self.kdb_orig = libkeepass.open(kdbf_t0, password="******")
     self.kdb_dest = libkeepass.open(kdbf_t0, password="******")
     self.kdb_src = libkeepass.open(kdbf_t0, password="******")
     self.kdbm = libkeepass.utils.merge.KDB4UUIDMerge(self.kdb_orig,
                                                      self.kdb_orig,
                                                      debug=False)
Ejemplo n.º 2
0
 def setUp(self):
     self.kdb_dest = libkeepass.open(kdbf_t0,
                                     password="******",
                                     unprotect=True)
     self.kdb_src = libkeepass.open(kdbf_t1,
                                    password="******",
                                    unprotect=True)
Ejemplo n.º 3
0
    def test_write_file(self):
        # valid password and plain keyfile, compressed kdb
        with libkeepass.open(absfile1, password="******") as kdb:
            self.assertEquals(kdb.opened, True)
            self.assertEquals(kdb.read(32),
                              b'<?xml version="1.0" encoding="ut')
            kdb.set_compression(0)
            # kdb.set_comment("this is pretty cool!")
            kdb.clear_credentials()
            kdb.add_credentials(password="******")
            with open(output1, 'wb') as outfile:
                kdb.write_to(outfile)
        with libkeepass.open(output1, password="******") as kdb:
            self.assertEquals(kdb.read(32),
                              b"<?xml version='1.0' encoding='ut")

        with libkeepass.open(absfile4, password="******",
                             keyfile=keyfile4) as kdb:
            self.assertEquals(kdb.opened, True)
            self.assertEquals(kdb.read(32),
                              b'<?xml version="1.0" encoding="ut')
            with open(output4, 'wb') as outfile:
                kdb.write_to(outfile)
        with libkeepass.open(output4, password="******",
                             keyfile=keyfile4) as kdb:
            self.assertEquals(kdb.read(32),
                              b"<?xml version='1.0' encoding='ut")
Ejemplo n.º 4
0
    def get_entry(self, title):
        if self.databasefile == None or self.password == None:
            self._logger.error('Not initialized...')
            return None

        with libkeepass.open(self.databasefile, password = self.password) as kdb:
            found = False
            for entry in kdb.obj_root.findall('.//Entry'):
                for string in entry.findall('.//String'):
                    if string.find('.//Key') != 'Title':
                        continue
                    if string.find('.//Value') == title:
                        found = True
                        break

                if found:
                    for sting in entry.findall('.//String'):
                        if sting.find('.//Key') == 'Notes':
                            notes = sting.find('.//Value')
                        elif sting.find('.//Key') == 'Password':
                            password = sting.find('.//Value')
                        elif sting.find('.//Key') == 'Title':
                            title = sting.find('.//Value')
                        elif sting.find('.//Key') == 'URL':
                            url = sting.find('.//Value')
                        elif sting.find('.//Key') == 'UserName':
                            username = sting.find('.//Value')
                    return KeePassEntry(notes, password, title, url, username)

            return None
Ejemplo n.º 5
0
    def get_entry(self, title):
        if self.databasefile == None or self.password == None:
            print 'Not initalized'
            return None

        with libkeepass.open(self.databasefile, password = self.password) as kdb:
            found = False
            for entry in kdb.obj_root.findall('.//Entry'):
                for string in entry.findall('.//String'):
                    if string.find('.//Key') != 'Title':
                        continue
                    if string.find('.//Value') == title:
                        found = True
                        break

                if found:
                    for sting in entry.findall('.//String'):
                        if sting.find('.//Key') == 'Notes':
                            notes = sting.find('.//Value')
                        elif sting.find('.//Key') == 'Password':
                            password = sting.find('.//Value')
                        elif sting.find('.//Key') == 'Title':
                            title = sting.find('.//Value')
                        elif sting.find('.//Key') == 'URL':
                            url = sting.find('.//Value')
                        elif sting.find('.//Key') == 'UserName':
                            username = sting.find('.//Value')
                    return KeePassEntry(notes, password, title, url, username)

            return None
Ejemplo n.º 6
0
def keepass(kpfile, keyfile, password):
  
  if os.path.exists(kpfile) and os.access(kpfile, os.R_OK) and
     os.path.exists(keyfile) and os.access(keyfile, os.R_OK):
      with libkeepass.open(kpfile, password=password, keyfile=keyfile) as kp:
          result = kp.pretty_print()
          kp.protect()
Ejemplo n.º 7
0
def try_open_db(db, key):
    try:
        return libkeepass.open(db, password=key)
    except IOError as e:
        if 'Master key invalid' in e.message:
            return None
        else:
            raise IOError(e.message)
Ejemplo n.º 8
0
    def test_open_file_protected(self):
        # old kdb file
        with warnings.catch_warnings(record=True) as w:
            warnings.simplefilter("always")
            with libkeepass.open(absfile2, password="******", unprotect=False) as kdb:
                self.assertIsNotNone(kdb)
            self.assertEqual(w[0].category, UserWarning)
            self.assertTrue("KDB3 files do not support protected reading, " \
							"the keyword will be ignored." in str(w[0].message))
Ejemplo n.º 9
0
	def run(self, software_name = None):
		# password found on the memory dump class
		if constant.keepass:
			try:
				with libkeepass.open(constant.keepass['Database'], password=constant.keepass['Password'], keyfile=constant.keepass['KeyFilePath']) as kdb:
					pwdFound = kdb.to_dic()
				return pwdFound
			except:
				pass
Ejemplo n.º 10
0
    def test_merge_self(self):
        """Test direct KDB4Reader class usage"""
        with libkeepass.open(kdbf_t0, password="******") as kdb_dest, \
             libkeepass.open(kdbf_t0, password="******") as kdb_src:
            kdbm = libkeepass.utils.merge.KDB4UUIDMerge(kdb_dest,
                                                        kdb_src,
                                                        debug=False)
            kdbm.merge()
            # Merging file into itself, should have no effect
            self.assertEqual(kdb_dest.pretty_print(), kdb_src.pretty_print())

            # Check using KDBEqual with all checks on
            eq = libkeepass.utils.check.KDBEqual(metadata=True,
                                                 history=True,
                                                 ignore_attrs=False,
                                                 ignore_times=True)
            is_eq = eq.equal(kdb_dest, kdb_src)
            self.assertTrue(is_eq, msg="KDB not equal: %r" % (eq.error.msg, ))
Ejemplo n.º 11
0
    def test_merge_t0_into_t1(self):
        with libkeepass.open(kdbf_t1, password="******") as kdb_orig, \
             libkeepass.open(kdbf_t1, password="******") as kdb_dest, \
             libkeepass.open(kdbf_t0, password="******") as kdb_src:
            dest_kdbxml_orig = kdb_dest.pretty_print()
            kdbm = libkeepass.utils.merge.KDB4UUIDMerge(kdb_dest,
                                                        kdb_src,
                                                        debug=False)
            kdbm.merge()
            # Merging ancestor into decendant should have no effect
            self.assertEqual(kdb_dest.pretty_print(), dest_kdbxml_orig)

            # Check using KDBEqual with all checks on
            eq = libkeepass.utils.check.KDBEqual(metadata=True,
                                                 history=True,
                                                 ignore_attrs=False)
            is_eq = eq.equal(kdb_dest, kdb_orig)
            self.assertTrue(is_eq, msg="KDB not equal: %r" % (eq.error.msg, ))
Ejemplo n.º 12
0
def kdbfile_shell(args):
    open_args = {}
    if 'keyfile' in args:
        open_args['keyfile'] = args.keyfile
    if 'passwords' in args:
        open_args['unprotect'] = args.passwords
    with OpenKDBXFiles(args.kdbfiles) as kdbfiles:
        code.interact(local=dict(kdbfiles=kdbfiles))
    return

    kdbfiles = []
    creds_list = []

    prompt = 'Password: '******''
                    if ntry > 0:
                        tries_s = ' (try {})'.format(ntry)
                    prompt = '{} Password{}: '.format(kdbfile, tries_s)

                creds = {}
                if crlist:
                    creds = crlist.pop()
                else:
                    # Only increment ntry, when the user actually inputs a
                    # password
                    ntry += 1
                    creds = {'password': getpass.getpass(prompt=prompt)}
                    if 'keyfile' in args:
                        creds['keyfile'] = args.keyfile
                kwargs = creds
                kwargs['unprotect'] = args.passwords

                with libkeepass.open(os.path.expanduser(kdbfile),
                                     mode='rb',
                                     **kwargs) as kdb:
                    kdb.pretty_print()
                    if isinstance(kdb, libkeepass.kdb3.KDB3File):
                        for g in kdb.groups:
                            print(g['title'], g['group_id'], g['level'],
                                  g.get('groups', None), g.get('path', '!'))
                    kdbfiles.append(kdb)
                    creds_list.append(creds)
                break
            except OSError as ex:
                print(ex)
    else:
        del creds_list
        code.interact(local=dict(kdbfiles=kdbfiles))
Ejemplo n.º 13
0
 def read(self, filename=None, password=None, keyfile=None):
     if not filename:
         filename = self.kdb_filename
     credentials = {}
     if password:
         credentials['password'] = password
     if keyfile:
         credentials['keyfile'] = keyfile
     assert filename, 'Filename should not be empty'
     logger.debug('Open file {}'.format(filename))
     return libkeepass.open(filename, **credentials).__enter__()
Ejemplo n.º 14
0
    def test_write_file(self):
        # valid password and plain keyfile, compressed kdb
        with libkeepass.open(absfile1, password="******") as kdb:
            self.assertEquals(kdb.opened, True)
            self.assertEquals(kdb.read(32), b'<?xml version="1.0" encoding="ut')
            kdb.set_compression(0)
            #kdb.set_comment("this is pretty cool!")
            kdb.clear_credentials()
            kdb.add_credentials(password="******")
            with open(output1, 'wb') as outfile:
                kdb.write_to(outfile)
        with libkeepass.open(output1, password="******") as kdb:
            self.assertEquals(kdb.read(32), b"<?xml version='1.0' encoding='ut")

        with libkeepass.open(absfile4, password="******", keyfile=keyfile4) as kdb:
            self.assertEquals(kdb.opened, True)
            self.assertEquals(kdb.read(32), b'<?xml version="1.0" encoding="ut')
            with open(output4, 'wb') as outfile:
                kdb.write_to(outfile)
        with libkeepass.open(output4, password="******", keyfile=keyfile4) as kdb:
            self.assertEquals(kdb.read(32), b"<?xml version='1.0' encoding='ut")
Ejemplo n.º 15
0
 def load_kpx_db(self):
     """
     Returns KPX DB data
     """
     try:
         with libkeepass.open(self.kpx_db_path,
                              password=self.kpx_db_password) as kpx_db:
             data = bf.data(fromstring(kpx_db.pretty_print()))
     except Exception:
         print("Script wasn't able to read KPX DB")
         raise
     else:
         return data
Ejemplo n.º 16
0
 def run(self):
     # password found on the memory dump class
     if constant.keepass:
         res = []
         for db in constant.keepass:
             try:
                 with libkeepass.open(db.values()[0][u'Database'],
                                      password=db.get(u"KcpPassword", {}).get(u'Password'),
                                      keyfile=db.get(u"KcpKeyFile", {}).get(u'KeyFilePath')) as kdb:
                     res.extend(kdb.to_dic())
             except Exception:
                 self.debug(traceback.format_exc())
         return res
Ejemplo n.º 17
0
def kdbfile_dump(args):
    kdbfile = args.kdbfile
    kdbxmlfile = args.outfile

    pwd = getpass.getpass()
    try:
        with libkeepass.open(os.path.expanduser(kdbfile), password=pwd) as kdb:
            if kdbxmlfile == '-':
                print(kdb.pretty_print(True))
            else:
                with open(kdbxmlfile, 'wb') as wf:
                    wf.write(kdb.pretty_print())
    except OSError as ex:
        print(ex)
Ejemplo n.º 18
0
 def do_open(self, arg):
     """Open a file"""
     pwd = getpass.getpass()
     try:
         with libkeepass.open(os.path.expanduser(arg), password=pwd) as kdb:
             kdbx_data = kdb.pretty_print()
             self.root = lxml.etree.fromstring(kdbx_data)
             self.tree = lxml.etree.ElementTree(self.root)
             self.current_group = self.tree.xpath("/KeePassFile/Root/Group")[0]
             self.current_path = '/' + self.current_group.find('Name').text
             self.filename = arg
             self.prompt = self._prompt()
     except OSError as ex:
         print(ex)
Ejemplo n.º 19
0
 def test_verify_kdb3(self):
     with libkeepass.open(absfile2, password="******") as kdb:
         self.assertEqual([e['title'] for e in kdb.groups], ['Internet', 'eMail'])
         self.assertEqual(len(kdb.entries), 1)
         verify_entry = kdb.entries[0].copy()
         verify_entry.update({
             'username': '******',
             'password': '******',
             'url': 'asdf',
             'title': 'asdf',
             'group_id': 623687138,
             'group': 'Internet',
             'modified': datetime.datetime(2012, 7, 20, 20, 27, 2),
         })
         self.assertEqual(kdb.entries[0], verify_entry)
Ejemplo n.º 20
0
 def do_open(self, arg):
     """Open a file"""
     pwd = getpass.getpass()
     try:
         with libkeepass.open(os.path.expanduser(arg), password=pwd) as kdb:
             kdbx_data = kdb.pretty_print()
             self.root = lxml.etree.fromstring(kdbx_data)
             self.tree = lxml.etree.ElementTree(self.root)
             self.current_group = self.tree.xpath(
                 "/KeePassFile/Root/Group")[0]
             self.current_path = '/' + self.current_group.find('Name').text
             self.filename = arg
             self.prompt = self._prompt()
     except OSError as ex:
         print(ex)
Ejemplo n.º 21
0
def human_readable_dump():
    with libkeepass.open(filename=sys.argv[1], password=sys.argv[2]) as kdb:
        root = kdb.tree.getroot()
        for group in root.Root.iter('Group'):
            try:
                print "GROUP:", group.Name
                for Entry in group.iter('Entry'):
                    print "\t" + "=" * 80
                    for string in Entry.iter('String'):
                        print "\t\t" + "-" * 80
                        print "\t\t" + string['Key'] + ":" + string['Value']

            except:
                pass
        print "=" * 80
Ejemplo n.º 22
0
def export_entries(filename, password, keyfile=None, force_lowercase=False,
                   skip_root=False):
    with libkeepass.open(filename, password=password, keyfile=keyfile) as kdb:
        xmldata = lxml.etree.fromstring(kdb.pretty_print())
        tree = lxml.etree.ElementTree(xmldata)
        root_group = tree.xpath('/KeePassFile/Root/Group')[0]
        all_entries = export_entries_from_group(
            xmldata, root_group, force_lowercase=force_lowercase
        )
        if skip_root:
            regex = re.compile(r'^{}/?'.format(get_group_name(root_group)))
            for e in all_entries:
                e['_path'] = regex.sub('', e['_path'])

        logger.info('Total entries: {}'.format(len(all_entries)))
        return all_entries
Ejemplo n.º 23
0
def main():
    args = build_parser().parse_args()

    with libkeepass.open(args.kdbx, password=getpass.getpass(), mode='rb') as kdb:
        for entry in kdb.obj_root.findall('.//Group/Entry'):
            uuid = entry.find('./UUID').text
            kv = {string.find('./Key').text: string.find('./Value').text for string in entry.findall('./String')}
            if not kv['Password']:
                continue
            r = check_hash(kv['Password'])
            if r > 0:
                m = 'Password for %s (%s) seen %d times before' % (kv['Title'], uuid, r)
                if args.show_user:
                    m += ' - %s' % kv.get('UserName')
                if args.show_password:
                    m += ' - %s' % kv['Password']
                print(m)
    def get_host_vars(self, host, vault_password=None):
        """ Get host specific variables. """
#        print "Host Invoke for %s " % host.name 
        if "--ask-su-pass" in sys.argv: 
            x_auth_system = host.get_variables().get("x_auth_system")
            x_auth_system_kdb = host.get_variables().get("x_auth_system_kdb")
            x_auth_system_master_key = host.get_variables().get("x_auth_system_master_key")
            passwd = ""
            ps  = host.get_variables().get("ansible_su_pass")
            if ps is None:
                if x_auth_system == "keepass":
                    x_auth_system_kdb = host.get_variables().get("x_auth_system_kdb")
                    x_auth_system_master_key = host.get_variables().get("x_auth_system_master_key")
                    if x_auth_system_kdb is None:
                        x_auth_system_kdb = raw_input( "Provide full path to keepass kdb file: ")
                        host.set_variable('x_auth_system_kdb', x_auth_system_kdb)

                    if x_auth_system_master_key is None:
                        prmt = "Enter keepass vault password for host "+host.name+": "
                        x_auth_system_master_key = getpass.getpass(prompt = prmt)
                        host.set_variable('x_auth_system_master_key', x_auth_system_master_key)

                    rez = {}
                    with libkeepass.open( x_auth_system_kdb , password = x_auth_system_master_key ) as kdb:
                        xmldata = ET.fromstring(kdb.pretty_print())
                        for history in xmldata.xpath(".//History"):
                            history.getparent().remove(history)

                        for el in xmldata.findall('.//Entry'):
                            uuid =  el.find('./UUID').text
                            rez[uuid] = {}
                            for elem in el.findall('./String'):
                                key = elem.find('./Key').text
                                val = elem.find('./Value').text
                                rez[uuid][key] = val
                    for elem in rez.keys():
                        if rez[elem]['Title'] == host.name and rez[elem]['UserName'] == 'root' :
                            passwd = rez[elem]['Password']
#                           print passwd, host.name

                else:
                    raise Exception("Unknown Authentication System %s for host %s" % (x_auth_system, host.name))
                if passwd == "":
                    passwd = getpass.getpass(prompt="%s su password: " % host.name)
                host.set_variable('ansible_su_pass', passwd)
Ejemplo n.º 25
0
def get_keepass_pw(dbpath, title="", username=""):
    if os.path.isfile(dbpath):
        with libkeepass.open(
                os.path.expanduser(dbpath),
                password=getpass.getpass("Master password for '" + dbpath +    "': ")) as kdb:
            entry = kdb.tree.xpath(
                './/Entry'
                '/String/Key[.="Title"]/../Value[.="{title}"]/../..'
                '/String/Key[.="UserName"]/../Value[.="{username}"]/../..'
                '/String/Key[.="Password"]/../Value'.format(
                    title=title,
                    username=username
                )
            )[0]
            return entry.text
    else:
        print("Error: '" + dbpath + "' does not exist.")
        return
def export_entries(filename, password, keyfile=None):
    """
    Get total entries exported from keepass file.
    """
    with libkeepass.open(filename, password=password, keyfile=keyfile) as kdb:
        xmldata = lxml.etree.fromstring(
            kdb.pretty_print())  # Get keepass data in xml format

        tree = lxml.etree.ElementTree(
            xmldata)  # Get the xml object of keepass data

        root_group = tree.xpath('/KeePassFile/Root/Group')[
            0]  # Get the keepass file's root group

        all_entries = export_entries_from_group(
            xmldata, root_group)  # Get all entries from keepass

        return all_entries
Ejemplo n.º 27
0
def kdbfile_convert4(args):
    kdbinfile = args.kdbinfile
    kdboutfile = args.kdboutfile

    pwd = getpass.getpass()
    try:
        with libkeepass.open(os.path.expanduser(kdbinfile),
                             password=pwd) as kdb3:
            assert isinstance(kdb3, libkeepass.kdb3.KDB3File)
            with open(kdboutfile, 'wb') as wf:
                kdb4 = libkeepass.utils.convert_kdb3_to_kdb4(kdb3)
                kdb4.write_to(wf)
            if args.debugfile:
                with open(args.debugfile, 'wb') as wf:
                    wf.write(kdb4.pretty_print())
            if args.debug:
                code.interact(local=dict(kdb3=kdb3, kdb4=kdb4))
    except OSError as ex:
        print(ex)
Ejemplo n.º 28
0
def get_keepass_pw(dbpath, title="", username=""):
    if os.path.isfile(dbpath):
        with libkeepass.open(
            os.path.expanduser(dbpath),
            password=getpass.getpass(
                "Master password for '" + dbpath + "': ")) as kdb:
            entry = kdb.tree.xpath(
                './/Entry'
                                '/String/Key[.="Title"]/../Value[.="{title}"]/../..'
                                '/String/Key[.="UserName"]/../Value[.="{username}"]/../..'
                                '/String/Key[.="Password"]/../Value'.format(
                                    title=title,
                                                        username=username
                                                    )
                            )[0]
            return entry.text
    else:
        print "Error: Bad input filename."
        return
Ejemplo n.º 29
0
 def load_cache(self):
     with libkeepass.open(self.kee_pass_file,
                          password=self.session.session) as kpdb:
         self.session.write()
         self.entries = []
         for kpEntry in kpdb.obj_root.findall('.//Entry'):
             simple_entry = SimpleEntry(None, [], None)
             for s in kpEntry.findall('./String'):
                 key = s.find('./Key').text
                 val = s.find('./Value').text
                 if val is not None and val != '':
                     if key == 'URL':
                         simple_entry.addresses.append(val)
                     elif key == 'Password':
                         simple_entry.password = val
                     elif key == 'UserName':
                         simple_entry.username = val
                     elif key == 'Title':
                         simple_entry.name = val
             if simple_entry.name is not None and simple_entry.password is not None:
                 self.entries.append(simple_entry)
Ejemplo n.º 30
0
    def __enter__(self):
        creds_list = []
        prompt = 'Password: '******''
                        if ntry > 0:
                            tries_s = ' (try {})'.format(ntry)
                        prompt = '{} Password{}: '.format(kdbfile, tries_s)

                    creds = {}
                    if crlist:
                        creds = crlist.pop()
                    else:
                        # Only increment ntry, when the user actually inputs a
                        # password
                        ntry += 1
                        creds = {'password': getpass.getpass(prompt=prompt)}
                        if self.keyfiles:
                            creds['keyfile'] = self.keyfiles
                    kwargs = creds
                    kwargs['unprotect'] = self.unprotect

                    with libkeepass.open(os.path.expanduser(kdbfile),
                                         mode='rb',
                                         **kwargs) as kdb:
                        self.kdbs.append(kdb)
                        creds_list.append(creds)
                    break
                except OSError as ex:
                    print(ex)
        else:
            del creds_list
        return self.kdbs
    def get_host_vars(self, host, vault_password=None):
        """ Get host specific variables. """
        print "Host Invoke for %s" % host.name
        if "--ask-su-pass" in sys.argv:
            x_auth_system = host.get_variables().get("x_auth_system")
            x_auth_system_kdb = host.get_variables().get("x_auth_system_kdb")
            x_auth_system_master_key = host.get_variables().get("x_auth_system_master_key")

            ps = host.get_variables().get("ansible_su_pass")
            if ps is None:
                if x_auth_system == "keepass":
                    x_auth_system_kdb = host.get_variables().get("x_auth_system_kdb")
                    x_auth_system_master_key = host.get_variables().get("x_auth_system_master_key")
                    if x_auth_system_kdb is None:
                        x_auth_system_kdb = raw_input("Provide full path to keepass kdb file: ")
                        host.set_variable("x_auth_system_kdb", x_auth_system_kdb)

                    if x_auth_system_master_key is None:
                        x_auth_system_master_key = getpass.getpass(prompt="Enter keepass vault password: "******"x_auth_system_master_key", x_auth_system_master_key)

                    rez = {}
                    with libkeepass.open(x_auth_system_kdb, password=x_auth_system_master_key) as kdb:
                        for el in kdb.obj_root.findall(".//Entry"):
                            uuid = el.find("UUID").text
                            rez[uuid] = {}
                            for elem in el.findall(".//String"):
                                key = elem.find("Key").text
                                val = elem.find("Value").text
                                rez[uuid][key] = val
                    for elem in rez.keys():
                        if rez[elem]["Title"] == host.name and rez[elem]["UserName"] == "root":
                            passwd = rez[elem]["Password"]
                #                            print passwd, host.name

                else:
                    raise Exception("Unknown Authentication System %s for host %s" % (x_auth_system, host.name))
                if passwd is None:
                    passwd = getpass.getpass(prompt="%s: su password" % x_auth_system)
                host.set_variable("ansible_su_pass", passwd)
Ejemplo n.º 32
0
def scan_kdb(file, password, compare):
    '''Returns a dict with all Groups/Entries in a KDB file.'''
    paths = {'/KeePassFile/Root': ['']}
    items = {}

    with libkeepass.open(file, password=password) as kdb:
        for item in itertools.chain(kdb.obj_root.findall('.//Group'),
                                    kdb.obj_root.findall('.//Group/Entry')):
            parent = item.getroottree().getpath(item.getparent())
            strings = find_item_strings(item)

            if item.tag == 'Group':
                name = item.find('./Name').text
            elif item.tag == 'Entry':
                name = strings['Title']
            path = paths[parent] + [name]

            paths[item.getroottree().getpath(item)] = path

            path_display = '/'.join(path)
            if item.tag == 'Group':
                path_display += '/'

            key = path
            if compare == 'uuid':
                key = item.find('./UUID').text
                parent_id = ''
                if len(paths[parent]) > 1:
                    parent_id = item.getparent().find('./UUID').text
            elif compare == 'path':
                key = tuple(path)
                parent_id = '/'.join(paths[parent]) + '/'
            else:
                raise NotImplementedError("Unrecognized compare method")

            items[key] = Node(item, path_display,
                              item.find('./UUID').text, strings, parent_id)

    return items
Ejemplo n.º 33
0
    def setUp(self):
        self.kdb_orig = libkeepass.open(kdbf_t0, password="******")
        self.kdbm = libkeepass.utils.merge.KDB4UUIDMerge(self.kdb_orig,
                                                         self.kdb_orig,
                                                         debug=False)
        uuid = 'spHmZwBbGUuqvbi/mVCknw=='
        self.entry = self.kdb_orig.obj_root.find(".//Entry[UUID='" + uuid +
                                                 "']")

        # Add some more history elements
        self.entry.History.clear()
        n = 10
        for i in range(n):
            ce = copy.deepcopy(self.entry)
            ce.remove(ce.History)
            modtime = libkeepass.utils.parse_timestamp(
                ce.Times.LastModificationTime.text)
            modtime_str = "{:%Y-%m-%dT%H:%M:%S}Z".format(
                modtime - datetime.timedelta(n - i - 1, 60))
            ce.Times.LastModificationTime._setText(modtime_str)
            self.entry.History.append(ce)

        self.entry2 = copy.deepcopy(self.entry)
Ejemplo n.º 34
0
    def do_import(self, filename):
        password = getpass.getpass(prompt='...' +
                                   'Keepass Password'.rjust(20) + ': ',
                                   stream=None)

        with libkeepass.open(filename, password=password) as kdb:
            root = kdb.obj_root.find('Root/Group')
            if root is not None:
                groups = [root]
                pos = 0
                while pos < len(groups):
                    g = groups[pos]
                    groups.extend(g.findall('Group'))
                    pos = pos + 1

                # Shared Folders
                for group in groups:
                    if hasattr(group, 'Keeper'):
                        keeper = group.Keeper
                        if hasattr(keeper, 'IsShared'):
                            if keeper.IsShared:
                                sf = SharedFolder()
                                sf.uid = base64.urlsafe_b64encode(
                                    base64.b64decode(
                                        group.UUID.text)).decode().rstrip('=')
                                sf.path = KeepassImporter.get_folder(group)
                                for sn in keeper.iterchildren():
                                    if sn.tag == 'ManageUsers':
                                        sf.manage_users = sn == True
                                    elif sn.tag == 'ManageRecords':
                                        sf.manage_records = sn == True
                                    elif sn.tag == 'CanEdit':
                                        sf.can_edit = sn == True
                                    elif sn.tag == 'CanShare':
                                        sf.can_share = sn == True
                                    elif sn.tag == 'Permission':
                                        perm = Permission()
                                        if sf.permissions is None:
                                            sf.permissions = []
                                        sf.permissions.append(perm)

                                        for p in sn.iterchildren():
                                            if p.tag == 'UUID':
                                                perm.uid = base64.urlsafe_b64encode(
                                                    base64.b64decode(p.text)
                                                ).decode().rstrip('=')
                                            elif p.tag == 'Name':
                                                perm.name = p.text
                                            elif p.tag == 'ManageUsers':
                                                perm.manage_users = p == True
                                            elif p.tag == 'ManageRecords':
                                                perm.manage_records = p == True
                                yield sf

                for group in groups:
                    entries = group.findall('Entry')
                    if len(entries) > 0:
                        folder = KeepassImporter.get_folder(group)
                        for entry in entries:
                            record = Record()
                            fol = Folder()
                            fol.path = folder
                            record.folders = [fol]
                            if hasattr(entry, 'UUID'):
                                record.record_uid = base64.urlsafe_b64encode(
                                    base64.b64decode(
                                        entry.UUID.text)).decode().rstrip('=')
                            if hasattr(entry, 'Keeper'):
                                for sn in entry.Keeper.iterchildren():
                                    if sn.tag == 'CanEdit':
                                        fol.can_edit = sn == True
                                    elif sn.tag == 'CanShare':
                                        fol.can_share = sn == True
                                    elif sn.tag == 'Link':
                                        f = Folder()
                                        for p in sn:
                                            if p.tag == 'Domain':
                                                f.domain = p.text
                                            elif p.tag == 'Path':
                                                f.path = p.text
                                            elif p.tag == 'CanEdit':
                                                f.can_edit = p == True
                                            elif p.tag == 'CanShare':
                                                f.can_share = p == True
                                        if f.domain or f.path:
                                            record.folders.append(f)

                            for node in entry.findall('String'):
                                sn = node.find('Key')
                                if sn is None:
                                    continue
                                key = sn.text
                                sn = node.find('Value')
                                if sn is None:
                                    continue
                                value = sn.text
                                if key == 'Title':
                                    record.title = value
                                elif key == 'UserName':
                                    record.login = value
                                elif key == 'Password':
                                    record.password = value
                                elif key == 'URL':
                                    record.login_url = value
                                elif key == 'Notes':
                                    record.notes = value
                                else:
                                    record.custom_fields[key] = value

                            if hasattr(kdb.obj_root.Meta, 'Binaries'):
                                for bin in entry.findall('Binary'):
                                    try:
                                        ref = bin.Value.get('Ref')
                                        if ref:
                                            binary = kdb.obj_root.Meta.Binaries.find(
                                                'Binary[@ID="{0}"]'.format(
                                                    ref))
                                            if binary:
                                                if record.attachments is None:
                                                    record.attachments = []
                                                atta = KeepassAttachment(
                                                    binary)
                                                atta.name = bin.Key.text
                                                record.attachments.append(atta)
                                    except:
                                        pass

                            yield record
Ejemplo n.º 35
0
    def do_export(self, filename, records):
        print('Choose password for your Keepass file')
        master_password = getpass.getpass(prompt='...' +
                                          'Keepass Password'.rjust(20) + ': ',
                                          stream=None)

        sfs = []  # type: [SharedFolder]
        rs = []  # type: [Record]
        for x in records:
            if type(x) is Record:
                rs.append(x)
            elif type(x) is SharedFolder:
                sfs.append(x)

        template_file = os.path.join(os.path.dirname(__file__),
                                     'template.kdbx')

        with libkeepass.open(template_file, password='******') as kdb:
            root = kdb.obj_root.Root.Group
            for sf in sfs:
                comps = list(path_components(sf.path))
                node = root
                for i in range(len(comps)):
                    comp = comps[i]
                    sub_node = node.find('Group[Name=\'{0}\']'.format(comp))
                    if sub_node is None:
                        sub_node = objectify.Element('Group')
                        sub_node.UUID = base64.b64encode(
                            os.urandom(16)).decode()
                        sub_node.Name = comp
                        node.append(sub_node)
                    if i == len(comps) - 1:  # store Keeper specific info
                        keeper = sub_node.find('Keeper')
                        if keeper is None:
                            keeper = objectify.Element('Keeper')
                            sub_node.append(keeper)
                        else:
                            keeper.clear()
                        keeper.IsShared = True
                        keeper.ManageUsers = sf.manage_users
                        keeper.ManageRecords = sf.manage_records
                        keeper.CanEdit = sf.can_edit
                        keeper.CanShare = sf.can_share
                        if sf.permissions:
                            for perm in sf.permissions:
                                permission = objectify.Element('Permission')
                                if perm.uid:
                                    permission.UUID = base64.b64encode(
                                        base64.urlsafe_b64decode(
                                            perm.uid + '==')).decode()
                                permission.Name = perm.name
                                permission.ManageUsers = perm.manage_users
                                permission.ManageRecords = perm.manage_records
                                keeper.append(permission)
                    node = sub_node

            for r in rs:
                try:
                    node = kdb.obj_root.Root.Group
                    fol = None
                    if r.folders:
                        fol = r.folders[0]
                        for is_shared in [True, False]:
                            path = fol.domain if is_shared else fol.path
                            if path:
                                comps = list(path_components(path))
                                for i in range(len(comps)):
                                    comp = comps[i]
                                    sub_node = node.find(
                                        'Group[Name=\'{0}\']'.format(comp))
                                    if sub_node is None:
                                        sub_node = objectify.Element('Group')
                                        sub_node.UUID = base64.b64encode(
                                            os.urandom(16)).decode()
                                        sub_node.Name = comp
                                        node.append(sub_node)
                                    node = sub_node
                    entry = None
                    entries = node.findall('Entry')
                    if len(entries) > 0:
                        for en in entries:
                            title = ''
                            login = ''
                            password = ''
                            if hasattr(en, 'String'):
                                for sn in en.String:
                                    if hasattr(sn, 'Key') and hasattr(
                                            sn, 'Value'):
                                        key = sn.Key.text
                                        value = sn.Value.text
                                        if key == 'Title':
                                            title = value
                                        elif key == 'UserName':
                                            login = value
                                        elif key == 'Password':
                                            password = value
                            if title == r.title and login == r.login and password == r.password:
                                entry = node
                                break

                    strings = {'URL': r.login_url, 'Notes': r.notes}
                    if r.custom_fields:
                        for cf in r.custom_fields:
                            strings[cf] = r.custom_fields[cf]

                    if entry is None:
                        entry = objectify.Element('Entry')
                        if r.uid:
                            entry.UUID = base64.b64encode(
                                base64.urlsafe_b64decode(r.uid +
                                                         '==')).decode()
                        else:
                            entry.UUID = base64.b64encode(
                                os.urandom(16)).decode()
                        node.append(entry)

                        strings['Title'] = r.title,
                        strings['UserName'] = r.login,
                        strings['Password'] = r.password,
                    else:
                        for str_node in entry.findall('String'):
                            if hasattr(str_node, 'Key'):
                                key = str_node.Key
                                if key in strings:
                                    value = strings[key]
                                    if value:
                                        str_node.Value = value
                                        strings.pop(key)
                    if not fol is None:
                        if fol.domain:
                            keeper = entry.find('Keeper')
                            if keeper is None:
                                keeper = objectify.Element('Keeper')
                                entry.append(keeper)
                            else:
                                keeper.clear()

                            keeper.CanEdit = fol.can_edit
                            keeper.CanShare = fol.can_share
                            for f in r.folders[1:]:
                                link = objectify.Element('Link')
                                keeper.append(link)
                                if f.domain:
                                    link.Domain = f.domain
                                    link.CanEdit = f.can_edit
                                    link.CanShare = f.can_share
                                if f.path:
                                    link.Path = f.Path

                    for key in strings:
                        value = strings[key]
                        if value:
                            s_node = objectify.Element('String')
                            s_node.Key = key
                            s_node.Value = value
                            entry.append(s_node)

                    if r.attachments:
                        for atta in r.attachments:
                            max_size = 1024 * 1024
                            if atta.size < max_size:
                                bins = None
                                bId = 0
                                if hasattr(kdb.obj_root.Meta, 'Binaries'):
                                    bins = kdb.obj_root.Meta.Binaries
                                    elems = bins.findall('Binary')
                                    bId = len(elems)
                                else:
                                    bins = objectify.Element('Binaries')
                                    kdb.obj_root.Meta.append(bins)
                                    bId = 0
                                with atta.open() as s:
                                    buffer = s.read(max_size)
                                    if len(buffer) >= 32:
                                        iv = buffer[:16]
                                        cipher = AES.new(
                                            atta.key, AES.MODE_CBC, iv)
                                        buffer = cipher.decrypt(buffer[16:])
                                        if len(buffer) > 0:
                                            buffer = unpad_binary(buffer)
                                            out = io.BytesIO()
                                            with gzip.GzipFile(fileobj=out,
                                                               mode='w') as gz:
                                                gz.write(buffer)
                                            bin = objectify.E.Binary(
                                                base64.b64encode(
                                                    out.getvalue()).decode(),
                                                Compressed=str(True),
                                                ID=str(bId))
                                            bins.append(bin)

                                            bin = objectify.Element('Binary')
                                            bin.Key = atta.name
                                            bin.Value = objectify.Element(
                                                'Value', Ref=str(bId))
                                            entry.append(bin)
                            else:
                                print(
                                    'Warning: File \'{0}\' was skipped because it exceeds the 1MB Keepass filesize limit.'
                                    .format(atta.name))

                except Exception as e:
                    pass

            objectify.deannotate(root, xsi_nil=True)
            etree.cleanup_namespaces(root)

            kdb.clear_credentials()
            kdb.add_credentials(password=master_password)
            with open(filename, 'wb') as output:
                kdb.write_to(output)
Ejemplo n.º 36
0
    def test_open_file(self):
        # file not found, proper exception gets re-raised
        with self.assertRaisesRegexp(IOError, "No such file or directory"):
            with libkeepass.open(filename1, password="******"):
                pass
        # invalid password
        with self.assertRaisesRegexp(IndexError, "No credentials found."):
            with libkeepass.open(absfile1):
                pass
        # invalid password
        with self.assertRaisesRegexp(IOError, "Master key invalid."):
            with libkeepass.open(absfile1, password="******"):
                pass
        # invalid keyfile
        with self.assertRaisesRegexp(IOError, "Master key invalid."):
            with libkeepass.open(absfile1, password="******", keyfile="invalid"):
                pass

        # old kdb file
        with libkeepass.open(absfile2, password="******") as kdb:
            self.assertIsNotNone(kdb)
            self.assertEquals(kdb.opened, True)

        # valid password
        with libkeepass.open(absfile1, password="******") as kdb:
            self.assertIsNotNone(kdb)
            self.assertEquals(kdb.opened, True)
            self.assertIsInstance(kdb, libkeepass.kdb4.KDB4Reader)

        # valid password and xml keyfile
        with libkeepass.open(absfile3, password="******", keyfile=keyfile3) as kdb:
            self.assertIsNotNone(kdb)
            self.assertEquals(kdb.opened, True)
            self.assertIsInstance(kdb, libkeepass.kdb4.KDB4Reader)

        # valid password and plain keyfile, compressed kdb
        with libkeepass.open(absfile4, password="******", keyfile=keyfile4) as kdb:
            self.assertIsNotNone(kdb)
            self.assertEquals(kdb.opened, True)
            self.assertIsInstance(kdb, libkeepass.kdb4.KDB4Reader)

            # read raw data
            tmp1 = kdb.read(32)
            tmp2 = kdb.read(32)
            self.assertIsNotNone(tmp1)
            self.assertEquals(tmp1, b'<?xml version="1.0" encoding="ut')
            self.assertIsNotNone(tmp2)
            self.assertEquals(tmp2, b'f-8" standalone="yes"?>\n<KeePass')
            self.assertNotEquals(tmp1, tmp2)
            self.assertEquals(kdb.tell(), 64)
            kdb.seek(0)
            tmp3 = kdb.read(32)
            self.assertEquals(tmp1, tmp3)
            self.assertNotEquals(tmp2, tmp3)

            # read xml
            xml1 = kdb.obj_root.Root.Group.Entry.String[1].Value
            self.assertEquals(xml1, "Password")
            xml2 = kdb.obj_root.Root.Group.Entry.String[1].Value.get('ProtectedValue')
            kdb.protect()  # re-encrypt protected values again
            xml3 = kdb.obj_root.Root.Group.Entry.String[1].Value
            self.assertEquals(xml2, xml3)
            kdb.unprotect()  # and make passwords clear again
            xml4 = kdb.obj_root.Root.Group.Entry.String[1].Value
            self.assertEquals(xml1, xml4)

            self.assertIsNotNone(kdb.pretty_print())
 def open_database(self):
     try:
         with libkeepass.open(self.database_path, password=self.passphrase) as kdb:
             return kdb
     except IOError:
         raise WrongPassword("Incorrect password")
Ejemplo n.º 38
0
filename = input(
    "Please enter file name with Address for example : D:\Keepass\Yavarich.kdbx \n"
)
if filename == "":
    print("File not found")
    sys.exit()

fdA = input(
    "Please enter password list name with Address for example : D:\Keepass\dic.txt \n"
)
if fdA == "":
    print("File not found")
    sys.exit()
else:
    fd = open(fdA, 'r')
print("Please wait... \n")
lines = []
for line in fd:
    lines.append(line.replace("\n", ""))
for x in lines:
    try:
        with libkeepass.open(filename, password=x) as kdb:
            str = kdb.pretty_print()
            print("Password is : ", x)
            break
    except BaseException as e:
        logging.info(x)
else:
    print("Password is not found!, please try with other password list")
def kdb_inventory():
    filename = os.environ["KDB_PATH"]
    credentials = {'password': os.environ["KDB_PASS"]}
    vgroups = ['product', 'stage', 'tier', 'type', 'ansible_ssh_host']
    hosts = {}
    inventory = {}
    inventory_vars = {}
    with libkeepass.open(filename, **credentials) as kdb:
        xmldata = ET.fromstring(kdb.pretty_print())
        for history in xmldata.xpath(".//History"):
            history.getparent().remove(history)
        for group in xmldata.findall(".//Group"):
            group_name_raw = group.find("./Name").text
            group_name = re.sub('\s|=',
                                '_',
                                group_name_raw,
                                flags=re.IGNORECASE).lower()
            if re.match('^recycle.bin.*', group_name):
                continue
            group_uuid = group.find("./UUID").text
            group_uuid = base64.b16encode(
                base64.b64decode(group_uuid)).decode('utf-8')
            group_name_uuid = group_name + "_" + group_uuid
            inventory[group_name_uuid] = {}
            inventory[group_name_uuid]["hosts"] = []
            subgroups = []
            for subgroup in group.findall("./Group"):
                subgroup_name_raw = subgroup.find("./Name").text
                subgroup_name = re.sub('\s|=',
                                       '_',
                                       subgroup_name_raw,
                                       flags=re.IGNORECASE).lower()
                subgroup_uuid = subgroup.find("./UUID").text
                subgroup_uuid = base64.b16encode(
                    base64.b64decode(subgroup_uuid)).decode('utf-8')
                subgroup_name_uuid = subgroup_name + "_" + subgroup_uuid
                subgroups.append(subgroup_name_uuid)
            if subgroups:
                inventory[group_name_uuid]["children"] = subgroups
            for entry in group.findall("./Entry"):
                hostvars = {}
                hostgroups = []
                hostname = None
                for string in entry.findall("./String"):
                    key = string.findtext("./Key").lower()
                    value = string.findtext("./Value")
                    if key and value:
                        if key == 'title':
                            hostname = re.sub('\s|=',
                                              '_',
                                              value,
                                              flags=re.IGNORECASE)
                        elif key == 'url':
                            if re.match('^ssh://', value, flags=re.IGNORECASE):
                                hostvars['ansible_host'] = re.sub(
                                    '^ssh://', '', value, flags=re.IGNORECASE)
                            else:
                                hostname = None  # ignore entry with non-ssh url
                        elif key == 'username':
                            hostvars['ansible_user'] = value
                        elif key == 'password':
                            if re.match(
                                    '^{REF:', value, flags=re.IGNORECASE
                            ):  # KeePass can put a reference to another cell - ignore that
                                hostname = None
                            else:
                                hostvars['ansible_ssh_pass'] = value
                                hostvars['ansible_become_pass'] = value
                        elif re.match('^---\n', value):
                            hostvars[key] = yaml.safe_load(value)
                        elif value in ['True', 'true']:
                            hostvars[key] = True
                        elif value in ['False', 'false']:
                            hostvars[key] = False
                        else:
                            hostvars[key] = value
                if hostname == "group_vars":
                    inventory[group_name_uuid]["vars"] = hostvars
                elif hostname:
                    hosts[hostname] = hostvars
                    hostgroups.append(group_name_uuid)
                    groups = {
                        group.find('Name').text.lower()
                        for group in entry.xpath('ancestor::Group')
                    }
                    for group in groups:
                        hostgroups.append(group)
                    for vgroup in vgroups:
                        if vgroup in hostvars:
                            hostgroups.append(hostvars[vgroup])
                    tags_raw = entry.findtext("./Tags")
                    tags = re.sub('\s|=', '_', tags_raw,
                                  flags=re.IGNORECASE).split(';')
                    for tag in tags:
                        if tag:
                            hostgroups.append(tag)
                    for hostgroup in hostgroups:
                        try:
                            inventory[hostgroup]["hosts"].append(hostname)
                        except KeyError:
                            try:
                                inventory[hostgroup]["hosts"] = [hostname]
                            except KeyError:
                                inventory[hostgroup] = {}
                                inventory[hostgroup]["hosts"] = [hostname]

        inventory_vars["hostvars"] = hosts
        inventory["_meta"] = inventory_vars
        print(json.dumps(inventory, indent=2, sort_keys=True))
Ejemplo n.º 40
0
#!/usr/bin/env python3
import libkeepass
import getpass
import sys

try:
    filename = sys.argv[1]
    entry_title = sys.argv[2]
except IndexError:
    print('query.py <kdbx file name> <entry title>')
    sys.exit(1)

try:
    with libkeepass.open(filename, password=getpass.getpass()) as kdb:
        found = {}
        for entry in kdb.obj_root.findall('.//Group/Entry'):
            uuid = entry.find('./UUID').text
            kv = {string.find('./Key').text : string.find('./Value').text for string in entry.findall('./String')}
            if kv['Title'] == entry_title:
                found[uuid] = kv['Password']

        removed_uuids = {uuid.text for uuid in kdb.obj_root.findall('.//DeletedObject/UUID')}

    for password in { found[k] for k in found.keys() if k not in removed_uuids }:
        print(password)
except Exception as e:
    print('Could not query KeePass Database %s:\n%s' % (filename, str(e)), file=sys.stderr)
    sys.exit(2)

Ejemplo n.º 41
0
def kdb_inventory():
  filename = os.environ["KDB_PATH"]
  credentials = { 'password' : os.environ["KDB_PASS"] }
  vgroups = ['product', 'stage', 'tier', 'type']
  hosts = {}
  inventory = {}
  inventory_vars = {}
  with libkeepass.open(filename, **credentials) as kdb:
    xmldata = ET.fromstring(kdb.pretty_print())
    for history in xmldata.xpath(".//History"):
      history.getparent().remove(history)
    for group in xmldata.findall(".//Group"):
      group_name = group.find("./Name").text.lower()
      group_uuid = group.find("./UUID").text
      group_uuid = base64.b16encode(base64.b64decode(group_uuid))
      group_name_uuid = group_name + "_" + group_uuid
      inventory[group_name_uuid] = {}
      subgroups = []
      for subgroup in group.findall("./Group"):
        subgroup_name = subgroup.find("./Name").text.lower()
        subgroup_uuid = subgroup.find("./UUID").text
        subgroup_uuid = base64.b16encode(base64.b64decode(subgroup_uuid))
        subgroup_name_uuid = subgroup_name + "_" + subgroup_uuid
        subgroups.append(subgroup_name_uuid)
      if subgroups:
        inventory[group_name_uuid]["children"] = subgroups
      for entry in group.findall("./Entry"):
        hostvars = {}
        hostgroups = []
        hostname = None
        for string in entry.findall("./String"):
          key   = string.findtext("./Key").lower()
          value = string.findtext("./Value")
          if key == 'title' and ' ' not in value:
            hostname = value.lower()
          if value and key != "title":
            hostvars[key] = value
        if hostname and hostname != "group_vars" and ' ' not in hostname:
          hostgroups.append(group_name_uuid)
          groups = {
            group.find('Name').text.lower()
            for group in entry.xpath('ancestor::Group')
          }
          for group in groups:
            hostgroups.append(group)
          for vgroup in vgroups:
            if vgroup in hostvars:
              vgroup = hostvars[vgroup]
              hostgroups.append(vgroup)
          tags = entry.findtext("./Tags").split(';')
          for tag in tags:
            if tag:
              tag = tag.translate(maketrans('=','_'))
              hostgroups.append(tag)
          for hostgroup in hostgroups:
            try:
              inventory[hostgroup]["hosts"].append(hostname)
            except KeyError:
              try:
                inventory[hostgroup]["hosts"] = [hostname]
              except KeyError:
                inventory[hostgroup] = {}
                inventory[hostgroup]["hosts"] = [hostname]
        if hostname and hostname != "group_vars":
          hosts[hostname] = hostvars
        if hostname == "group_vars":
          inventory[group_name_uuid]["vars"] = hostvars

    inventory_vars["hostvars"] = hosts
    inventory["_meta"] = inventory_vars
    print json.dumps(inventory, indent=2, sort_keys=True)
Ejemplo n.º 42
0
#!/usr/bin/env python3
import libkeepass
import getpass
import sys

try:
    filename = sys.argv[1]
    password = sys.argv[2] if len(sys.argv) == 3 else getpass.getpass()
except IndexError:
    print('prettyprint.py <kdbx file name> [password]')
    sys.exit(1)

try:
    with libkeepass.open(filename, password=password) as kdb:
        print(kdb.pretty_print().decode('unicode_escape'))
except Exception as e:
    print('Could not prettyprint KeePass Database %s:\n%s' % (filename, str(e)), file=sys.stderr)
    sys.exit(2)