Esempio n. 1
0
    """Importer for Nord Pass in CSV format."""
    name = 'nordpass'
    url = 'https://nordpass.com/'
    hexport = 'Settings > Export Items'
    himport = 'pass import nordpass file.csv'
    keys = {
        'title': 'name',
        'password': '******',
        'login': '******',
        'url': 'url',
        'comments': 'note',
        'group': 'folder'
    }

    def parse(self):
        super().parse()
        # NordPass exports individual folders as their own
        # empty rows. This code removes the extra folder entries
        # from the parsed data.
        groups = []
        for entry in self.data:
            if entry['group']:
                groups.append(entry['group'])

        self.data = list(
            filter(lambda x: not (x['title'] in groups and not x['group']),
                   self.data))


register_managers(NordPassCSV)
Esempio n. 2
0
    html_header = 'body/div/div/textarea'
    keys = {'login': '******'}

    def parse(self):
        """Parse Clipperz HTML+JSON file."""
        # Extract the json from the html file.
        tree = ElementTree.XML(self.file.read())
        found = tree.find(self.html_header)
        if found is None:
            raise FormatError()

        # Parse JSON data
        keys = self.invkeys()
        for item in json.loads(found.text):
            entry = dict()
            label = item.get('label', ' \ue009').split(' \ue009')
            entry['title'] = label[0]
            if len(label) > 1:
                entry['group'] = label[1]

            fields = item.get('currentVersion', {}).get('fields', {})
            for uid in fields:
                label = fields[uid].get('label', '')
                entry[keys.get(label, label)] = fields[uid].get('value', '')

            entry['comments'] = item.get('data', {}).get('notes', '')
            self.data.append(entry)


register_managers(ClipperzHTML)
Esempio n. 3
0
from pass_import.core import register_managers
from pass_import.formats.csv import CSV


class Buttercup(CSV):
    """Importer for Buttercup in CSV format."""
    name = 'buttercup'
    url = 'https://buttercup.pw'
    hexport = 'File > Export > Export File to CSV'
    himport = 'pass import buttercup file.csv'
    ignore = {'!group_id', 'id'}
    keys = {
        'title': 'title',
        'password': '******',
        'login': '******',
        'url': 'URL',
        'comments': 'Notes',
        'group': '!group_name'
    }

    def parse(self):
        """Parse Buttercup CSV file."""
        super(Buttercup, self).parse()
        for entry in self.data:
            for key in self.ignore:
                entry.pop(key, None)


register_managers(Buttercup)
Esempio n. 4
0
    name = 'passpack'
    url = 'https://www.passpack.com'
    hexport = 'Settings > Export > Save to CSV'
    keys = {
        'title': 'Entry Name',
        'password': '******',
        'login': '******',
        'url': 'URL',
        'email': 'Email',
        'comments': 'Notes',
        'group': 'Tags'
    }

    def parse(self):
        """Parse Passpack CSV file."""
        super(Passpack, self).parse()
        for entry in self.data:
            groups = json.loads(entry.pop('group', '')).get('tags', [])
            for item in groups:
                field = json.loads(item)
                entry['group'] = field.get('tag', '')

            extra = json.loads(entry.pop('Extra Fields',
                                         '')).get('extraFields', [])
            for item in extra:
                field = json.loads(item)
                entry[field.get('name', '')] = field.get('data', '')


register_managers(Passpack)
Esempio n. 5
0
            for item in collection.get_all_items():
                entry = {}
                entry['group'] = group
                entry['title'] = item.get_label()
                entry['password'] = item.get_secret().decode('utf-8')
                entry['modified'] = item.get_modified()
                entry['created'] = item.get_created()
                for key, value in item.get_attributes().items():
                    entry[keys.get(key, key)] = value
                self.data.append(entry)

    # Context manager methods

    def exist(self):
        """Nothing to do."""
        return True

    @classmethod
    def isvalid(cls):
        """Nothing to do."""
        return True

    def open(self):
        """Nothing to open."""

    def close(self):
        """Nothing to close."""


register_managers(GnomeKeyring)
Esempio n. 6
0
from pass_import.core import register_managers
from pass_import.formats.csv import CSV
from pass_import.formats.kdbx import KDBX


class Keepassx2CSV(CSV):
    """Importer for KeepassX2 in CSV format."""
    name = 'keepassx2'
    default = False
    url = 'https://www.keepassx.org'
    hexport = 'Database > Export to CSV File'
    himport = 'pass import keepassx2 file.csv'
    keys = {
        'title': 'Title',
        'password': '******',
        'login': '******',
        'url': 'URL',
        'comments': 'Notes',
        'group': 'Group'
    }


class Keepassx2KDBX(KDBX):
    """Importer for KeepassX2 encrypted KDBX format."""
    name = 'keepassx2'
    url = 'https://www.keepassx.org'
    himport = 'pass import keepassx2 file.kdbx'


register_managers(Keepassx2CSV, Keepassx2KDBX)
Esempio n. 7
0
        'password': str,
        'url': str,
        'icon': dict,
        'custom_fields': list,
        'otp': dict,
        'compromised': bool
    }]

    def parse(self):
        """Parse Passman JSON file."""
        ignore = {'custom_fields', 'icon', 'tags'}
        keys = self.invkeys()
        jsons = json.loads(self.file.read())
        for item in jsons:
            entry = {}
            if item['tags']:
                group = item['tags'][0]['text']
                entry['group'] = group.replace('\\', os.sep)
            custom_fields = item.get('custom_fields', [])
            for field in custom_fields:
                item.update({field['label']: field['value']})

            for key, value in item.items():
                if key not in ignore:
                    entry[keys.get(key, key)] = value

            self.data.append(entry)


register_managers(PassmanCSV, PassmanJSON)
Esempio n. 8
0
    @classmethod
    def _getpath(cls, element, path=''):
        """Generate path name from elements title and current path."""
        title = ''
        if element.tag == 'Group':
            title = element.find('Name').text
        if title is None:
            title = ''
        return os.path.join(path, title)

    @classmethod
    def _getvalue(cls, element):
        xmlkey = value = ''
        for child in element.findall('Key'):
            xmlkey = child.text
            value = element.find('Value').text
        return xmlkey, value

    def _import(self, element, path=''):
        path = self._getpath(element, path)
        for group in element.findall(self.group):
            self._import(group, path)
        for xmlentry in element.findall(self.entry):
            entry = self._getentry(xmlentry)
            entry['group'] = path
            self.data.append(entry)


register_managers(Keepass, KeepassCSV, KeepassXML)
Esempio n. 9
0
# -*- encoding: utf-8 -*-
# pass import - Passwords importer swiss army knife
# Copyright (C) 2017-2020 Alexandre PUJOL <*****@*****.**>.
#

from pass_import.core import register_managers
from pass_import.formats.otp import OTP


class AndOTP(OTP):
    """Importer for AndOTP plain or encrypted JSON format."""
    name = 'andotp'
    format = 'json'
    url = 'https://github.com/andOTP/andOTP'
    hexport = 'Backups> Backup plain'
    himport = 'pass import andotp file.json'
    json_header = [{
        'secret': str,
        'label': str,
        'digits': int,
        'type': str,
        'algorithm': str,
        'thumbnail': str,
        'last_used': int,
        'tags': list
    }]


register_managers(AndOTP)
Esempio n. 10
0
# -*- encoding: utf-8 -*-
# pass import - Passwords importer swiss army knife
# Copyright (C) 2017-2020 Alexandre PUJOL <*****@*****.**>.
#

from pass_import.core import register_managers
from pass_import.formats.csv import CSV


class SaferPass(CSV):
    """Importer for SaferPass in CSV format."""
    name = 'saferpass'
    url = 'https://saferpass.net'
    hexport = 'Settings > Export Data: Export data'
    himport = 'pass import saferpass file.csv'
    encoding = 'utf-8-sig'
    keys = {
        'title': 'title',
        'password': '******',
        'login': '******',
        'url': 'url',
        'comments': 'notes',
        'favorite': 'favorite',
        'text': 'text',
        'modelType': 'modelType',
        'color': 'color'
    }


register_managers(SaferPass)
Esempio n. 11
0
    # Format recognition methods

    def is_format(self):
        """Check keychain file format."""
        try:
            self.yamls = self.keychain2yaml(self.file)
            if isinstance(self.yamls, str):
                return False
        except (yaml.scanner.ScannerError, yaml.parser.ParserError,
                UnicodeDecodeError):
            return False
        return True

    def checkheader(self, header, only=False):
        """Check keychain format."""
        if isinstance(self.yamls, list):
            self.yamls = self.yamls[0]
        for yamlkey in header:
            if yamlkey not in self.yamls:
                return False
        return True

    @classmethod
    def header(cls):
        """Get keychain format header."""
        return cls.keychain_format


register_managers(AppleKeychain)
register_detecters(AppleKeychain)
Esempio n. 12
0
    hexport = 'See this guide: https://support.1password.com/export'
    himport = 'pass import 1password file.csv'
    keys = {
        'title': 'title',
        'password': '******',
        'login': '******',
        'url': 'url',
        'comments': 'notes'
    }


class OnePassword4PIF(PIF):
    """Importer for 1password 4 in PIF format."""
    name = '1password'
    default = False
    version = '4'
    url = 'https://1password.com'
    hexport = 'See this guide: https://support.1password.com/export'
    himport = 'pass import 1password file.1pif'
    keys = {
        'title': 'title',
        'password': '******',
        'login': '******',
        'url': 'location',
        'comments': 'notesPlain',
        'group': 'folderUuid'
    }


register_managers(OnePasswordCSV, OnePassword4CSV, OnePassword4PIF)
Esempio n. 13
0
        keys are ignored.

        Binary attachment is not supported.

        """
        if self.all:
            self.writer.writerow(entry)
        else:
            res = dict()
            for key in self.keyslist:
                res[key] = entry.get(key, '')
            self.writer.writerow(res)

    # Context manager method

    def open(self):
        """Create/Re-create CSV exported file."""
        if self.action is Cap.IMPORT:
            super(GenericCSV, self).open()
        else:
            if os.path.isfile(self.prefix):
                if self.force:
                    self.file = open(self.prefix, 'w', encoding=self.encoding)
                else:
                    raise PMError("%s is already a file." % self.prefix)
            else:
                self.file = open(self.prefix, 'w', encoding=self.encoding)


register_managers(GenericCSV)
Esempio n. 14
0
# -*- encoding: utf-8 -*-
# pass import - Passwords importer swiss army knife
# Copyright (C) 2017-2020 Alexandre PUJOL <*****@*****.**>.
#

from pass_import.core import register_managers
from pass_import.managers import PasswordStore


class Gopass(PasswordStore):
    """Importer & Exporter for gopass."""
    name = 'gopass'
    format = 'gopass'
    command = 'gopass'
    url = 'https://www.gopass.pw/'
    himport = 'pass import gopass path/to/store'


register_managers(Gopass)
Esempio n. 15
0
            cipher = AESGCM(key)
            param = slot['key_params']
            try:
                nonce = bytes.fromhex(param['nonce'])
                data = bytes.fromhex(slot['key']) + bytes.fromhex(param['tag'])
                master_key = cipher.decrypt(nonce=nonce,
                                            data=data,
                                            associated_data=None)
            except InvalidTag:  # pragma: no cover
                pass

        if master_key is None:  # pragma: no cover
            raise FormatError("unable to decrypt the master key.")

        cipher = AESGCM(master_key)
        param = jsons['header']['params']
        content = base64.b64decode(jsons['db']) + bytes.fromhex(param['tag'])
        plain = cipher.decrypt(nonce=bytes.fromhex(param['nonce']),
                               data=content,
                               associated_data=None)
        return plain.decode('utf-8')

    def parse(self):
        """Parse Aegis encrypted JSON file."""
        self.content = self.decrypt(json.loads(self.content))
        super(AegisCipher, self).parse()


register_managers(Aegis, AegisCipher)
Esempio n. 16
0
class DashlaneJSON(JSON):
    """Importer for Dashlane in JSON format."""
    name = 'dashlane'
    default = False
    url = 'https://www.dashlane.com'
    hexport = 'File > Export > Unsecured Archive in JSON'
    himport = 'pass import dashlane file.json'
    keys = {
        'title': 'title',
        'password': '******',
        'email': 'email',
        'login': '******',
        'url': 'domain',
        'comments': 'note',
    }
    json_header = {'AUTHENTIFIANT': list, 'EMAIL': list}

    def parse(self):
        """Parse Dashlane JSON file."""
        jsons = json.loads(self.file.read())
        keys = self.invkeys()
        for item in jsons.get('AUTHENTIFIANT', {}):
            entry = dict()
            for key, value in item.items():
                entry[keys.get(key, key)] = value

            self.data.append(entry)


register_managers(DashlaneCSV, DashlaneJSON)
Esempio n. 17
0
# -*- encoding: utf-8 -*-
# pass import - Passwords importer swiss army knife
# Copyright (C) 2017-2020 Alexandre PUJOL <*****@*****.**>.
#

from pass_import.core import register_managers
from pass_import.formats.csv import CSV


class Myki(CSV):
    """Importer for Myki in CSV format."""
    name = 'myki'
    url = 'https://myki.com'
    hexport = ('See this guide: https://support.myki.com/myki-app/export'
               'ing-your-passwords-from-the-myki-app/how-to-export-your'
               '-passwords-account-data-from-myki')
    himport = 'pass import myki file.csv'
    keys = {
        'title': 'Name',
        'password': '******',
        'login': '******',
        'url': 'Url',
        'comments': 'Extra',
        'group': 'Grouping'
    }


register_managers(Myki)
Esempio n. 18
0
    url = 'https://support.google.com/chrome'
    hexport = ('See this guide: https://support.google.com/chrome/'
               'answer/95606#see')
    himport = 'pass import chrome file.csv'
    only = True
    keys = {
        'title': 'name',
        'password': '******',
        'login': '******',
        'url': 'url'
    }


class ChromeCSVSQLite(CSV):
    """Importer for Chrome SQLite in CSV format."""
    name = 'chrome'
    default = False
    url = 'https://support.google.com/chrome'
    hexport = ('See this guide: https://support.google.com/chrome/'
               'answer/95606#see')
    himport = 'pass import chrome file.csv'
    keys = {
        'title': 'display_name',
        'password': '******',
        'login': '******',
        'url': 'origin_url'
    }


register_managers(ChromeCSV, ChromeCSVSQLite)
Esempio n. 19
0
        for field in custom_fields:
            name = field['name']
            value = field['value']
            if name in destination_entry.keys():
                name = f'{name}_'
            if value:
                destination_entry[name] = value


class BitwardenOrgJSON(BitwardenJSON):
    """Importer for Bitwarden Organisation in JSON format."""
    key_group = 'collections'
    key_group_id = 'collectionIds'
    json_header = {
        'encrypted':
        False,
        'collections':
        list,
        'items': [{
            'id': str,
            'type': int,
            'name': str,
            'favorite': bool,
            'collectionIds': list,
        }],
    }


register_managers(BitwardenCSV, BitwardenJSON, BitwardenOrgCSV,
                  BitwardenOrgJSON)
Esempio n. 20
0
    json_header = {
        'tokenOrder':
        list,
        'tokens': [{
            'algo': str,
            'digits': int,
            'issuerExt': str,
            'label': str,
            'secret': list,
            'type': str
        }]
    }

    def parse(self):
        """Parse FreeOTP+ JSON file."""
        jsons = json.loads(self.content)
        for item in jsons['tokens']:
            item['label'] = item['issuerExt']
            item['algorithm'] = item['algo']
            item['secret'] = base64.b32encode(
                bytes(x & 0xff for x in item['secret'])).decode("utf8")

            entry = dict()
            entry['title'] = item['issuerExt']
            entry['otpauth'] = self._otp(item)
            entry['type'] = item['type'].lower()
            self.data.append(entry)


register_managers(FreeOTPPlus)
Esempio n. 21
0
import re

from pass_import.core import register_managers
from pass_import.formats.csv import CSV


class Gorilla(CSV):
    """Importer for Gorilla in CSV format."""
    name = 'gorilla'
    url = 'https://github.com/zdia/gorilla/wiki'
    hexport = 'File > Export: Yes: CSV Files'
    himport = 'pass import gorilla file.csv'
    keys = {
        'title': 'title',
        'password': '******',
        'login': '******',
        'url': 'url',
        'comments': 'notes',
        'group': 'group'
    }

    def parse(self):
        """Parse Gorilla CSV file."""
        super(Gorilla, self).parse()
        for entry in self.data:
            group = re.sub(r'(?<=[^\\])\.', os.sep, entry.get('group', ''))
            entry['group'] = re.sub(r'\\.', '.', group)


register_managers(Gorilla)
Esempio n. 22
0
# -*- encoding: utf-8 -*-
# pass import - Passwords importer swiss army knife
# Copyright (C) 2017-2020 Alexandre PUJOL <*****@*****.**>.
#

from pass_import.core import register_managers
from pass_import.formats.csv import CSV


class UPM(CSV):
    """Importer for Universal Password Manager (UPM) in CSV format."""
    name = 'upm'
    url = 'http://upm.sourceforge.net'
    hexport = 'Database > Export'
    himport = 'pass import upm file.csv'
    fieldnames = ['title', 'login', 'password', 'url', 'comments']
    keys = {
        'title': 'title',
        'password': '******',
        'login': '******',
        'url': 'url',
        'comments': 'comments'
    }


register_managers(UPM)
Esempio n. 23
0
# -*- encoding: utf-8 -*-
# pass import - Passwords importer swiss army knife
# Copyright (C) 2017-2020 Alexandre PUJOL <*****@*****.**>.
#

from pass_import.core import register_managers
from pass_import.formats.kdbx import KDBX
from pass_import.managers.keepassx2 import Keepassx2CSV


class KeepassxcCSV(Keepassx2CSV):
    """Importer for KeepassXC in CSV format."""
    name = 'keepassxc'
    default = False
    url = 'https://keepassxc.org'
    hexport = 'Database > Export to CSV File'
    himport = 'pass import keepassxc file.csv'


class KeepassxcKDBX(KDBX):
    """Importer for KeepassXC encrypted KDBX format."""
    name = 'keepassxc'
    url = 'https://keepassxc.org'
    himport = 'pass import keepassxc file.kdbx'


register_managers(KeepassxcCSV, KeepassxcKDBX)
Esempio n. 24
0
#

import os

from pass_import.core import register_managers
from pass_import.formats.csv import CSV


class LastpassCSV(CSV):
    """Importer for Lastpass in CSV format."""
    name = 'lastpass'
    url = 'https://www.lastpass.com'
    hexport = 'More Options > Advanced > Export'
    keys = {
        'title': 'name',
        'password': '******',
        'login': '******',
        'url': 'url',
        'comments': 'extra',
        'group': 'grouping'
    }

    def parse(self):
        """Parse Lastpass CSV file."""
        super(LastpassCSV, self).parse()
        for entry in self.data:
            entry['group'] = entry.get('group', '').replace('\\', os.sep)


register_managers(LastpassCSV)
Esempio n. 25
0
        'doctype': '<!DOCTYPE KEEPASSX_DATABASE>',
        'root': 'database'
    }
    keys = {
        'title': 'title',
        'password': '******',
        'login': '******',
        'url': 'url',
        'comments': 'comment'
    }

    @classmethod
    def _getpath(cls, element, path=''):
        title = ''
        if element.tag != 'database':
            if element.find('title').text:
                title = element.find('title').text
        return os.path.join(path, title)

    def _import(self, element, path=''):
        path = self._getpath(element, path)
        for group in element.findall(self.group):
            self._import(group, path)
        for xmlentry in element.findall(self.entry):
            entry = self._getentry(xmlentry)
            entry['group'] = path
            self.data.append(entry)


register_managers(KeepassxXML)
Esempio n. 26
0
import os

from pass_import.core import register_managers
from pass_import.formats.csv import CSV


class PadlockCSV(CSV):
    """Importer for Padloc CSV format."""
    name = 'padlock'
    url = 'https://padloc.app'
    hexport = 'Settings > Export Data and copy text into a .csv file'
    himport = 'pass import padlock file.csv'
    keys = {
        'title': 'name',
        'password': '******',
        'login': '******',
        'url': 'url',
        'comments': 'notes',
        'group': 'tags'
    }

    def parse(self):
        """Parse Padloc CSV file."""
        super(PadlockCSV, self).parse()
        for entry in self.data:
            entry['group'] = entry.get('group', '').replace('\\', os.sep)


register_managers(PadlockCSV)
Esempio n. 27
0
    def close(self):
        """Close all the opened files."""
        for file in self.files:
            file.close()

    # Format recognition methods

    def is_format(self):
        """Return True if the prefix has same format than the pm."""
        try:
            for file in self.files:
                ini = configparser.ConfigParser()
                ini.read_file(file)
        except:  # noqa
            return False
        return True

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

    @classmethod
    def header(cls):
        """No header for NetworkManager."""
        return ''


register_managers(NetworkManager)
register_detecters(NetworkManager)
Esempio n. 28
0
        return key, element.text

    def _import(self, element, path=''):
        for xmlentry in element.findall('entry'):
            if xmlentry.attrib.get('type', '') == 'folder':
                _path = os.path.join(path, xmlentry.find('name').text)
                self._import(xmlentry, _path)
            else:
                entry = self._getentry(xmlentry)
                entry['group'] = path

                host = entry.get('host', None)
                # Fix older Revelation storing Websites in Generic entries
                if host and 'url' not in entry:
                    for protocol in ['http://', 'https://']:
                        if host.startswith(protocol):
                            entry['url'] = entry.pop('host')
                            break
                domain = entry.pop('hostdomain', None)
                if domain:
                    if host:
                        if not host.endswith(domain):
                            entry['host'] = '%s.%s' % (host, domain)
                    else:
                        entry['host'] = domain

                self.data.append(entry)


register_managers(Revelation)
Esempio n. 29
0
    def open(self):
        """Ensure prefix is a path to a password repository."""
        if not os.path.isdir(self.prefix):
            raise PMError("%s is not a password repository." % self.prefix)

    def close(self):
        """There is no file to close."""

    # Format recognition methods

    def is_format(self):
        """Ensure the prefix is a directory than contain a .gpg-id file."""
        if os.path.isdir(self.prefix):
            path = os.path.join(self.prefix, '.gpg-id')
            if os.path.isfile(path):
                return True
        return False

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

    @classmethod
    def header(cls):
        """No header for pass."""
        return ''


register_managers(PasswordStore)
register_detecters(PasswordStore)
Esempio n. 30
0
# -*- encoding: utf-8 -*-
# pass import - Passwords importer swiss army knife
# Copyright (C) 2017-2020 Alexandre PUJOL <*****@*****.**>.
#

from pass_import.core import register_managers
from pass_import.formats.yaml import YAML


class Passpie(YAML):
    """Importer for Passpie in YAML format."""
    name = 'passpie'
    version = '1.0'
    url = 'https://www.enpass.io'
    hexport = '`passpie export file.yml`'
    himport = 'pass import passpie file.yml'
    yml_format = {'handler': 'passpie', 'version': 1.0}
    rootkey = 'credentials'
    keys = {
        'title': 'name',
        'password': '******',
        'login': '******',
        'comments': 'comment'
    }


register_managers(Passpie)