Beispiel #1
0
    def command(self):
        session, config, idx = self.session, self.session.config, self._idx()
        args = list(self.args)
        if args and args[-1][0] == "#":
            attid = args.pop()
        else:
            attid = self.data.get("att", 'application/pgp-keys')
        args.extend(["=%s" % x for x in self.data.get("mid", [])])
        eids = self._choose_messages(args)
        if len(eids) < 0:
            return self._error("No messages selected", None)
        elif len(eids) > 1:
            return self._error("One message at a time, please", None)

        email = Email(idx, list(eids)[0])
        fn, attr = email.extract_attachment(session, attid, mode='inline')
        if attr and attr["data"]:
            res = self._gnupg().import_keys(attr["data"])

            # Previous crypto evaluations may now be out of date, so we
            # clear the cache so users can see results right away.
            ClearParseCache(pgpmime=True)

            return self._success("Imported key", res)

        return self._error("No results found", None)
Beispiel #2
0
    def command(self):
        args = list(self.args)
        if args:
            address, fprints, origins = args[0], args[1].split(','), args[2:]
        else:
            address = self.data.get('address', [''])[0]
            fprints = self.data.get('fingerprints', [])
            origins = self.data.get('origins', [])
        safe_assert(address or fprints or origins)

        result = lookup_crypto_keys(self.session, address,
                                    get=[f.strip() for f in fprints],
                                    origins=origins,
                                    event=self.event)

        if len(result) > 0:
            # Update the VCards!
            PGPKeysImportAsVCards(self.session,
                                  arg=[k['fingerprint'] for k in result]
                                  ).run()
            # Previous crypto evaluations may now be out of date, so we
            # clear the cache so users can see results right away.
            ClearParseCache(pgpmime=True)

        return self._success(_n('Imported %d encryption key',
                                'Imported %d encryption keys',
                                len(result)) % len(result),
                             result=result)
Beispiel #3
0
    def command(self):
        key_files = self.data.get("key_file", []) + [a for a in self.args
                                                     if not '://' in a]
        key_urls = self.data.get("key_url", []) + [a for a in self.args
                                                   if '://' in a]
        key_data = []
        key_data.extend(self.data.get("key_data", []))
        for key_file in key_files:
            with open(key_file) as file:
                key_data.append(file.read())
        for key_url in key_urls:
            with ConnBroker.context(need=[ConnBroker.OUTGOING_HTTP]):
                uo = urllib2.urlopen(key_url)
            key_data.append(uo.read())

        rv = self._gnupg().import_keys('\n'.join(key_data))

        # Previous crypto evaluations may now be out of date, so we
        # clear the cache so users can see results right away.
        ClearParseCache(pgpmime=True)

        # Update the VCards!
        PGPKeysImportAsVCards(self.session,
                              arg=([i['fingerprint'] for i in rv['updated']] +
                                   [i['fingerprint'] for i in rv['imported']])
                              ).run()

        return self._success(_("Imported %d keys") % len(key_data), rv)
Beispiel #4
0
    def command(self):
        keyid = self.data.get("keyid", self.args)
        res = []
        for key in keyid:
            res.append(self._gnupg().recv_key(key))

        # Previous crypto evaluations may now be out of date, so we
        # clear the cache so users can see results right away.
        ClearParseCache(pgpmime=True)

        return res
Beispiel #5
0
    def command(self):
        signingkey = None
        keyid = None
        args = list(self.args)
        try: keyid = args.pop(0)
        except: keyid = self.data.get("keyid", None)
        try: signingkey = args.pop(0)
        except: signingkey = self.data.get("signingkey", None)

        print keyid
        if not keyid:
            return self._error("You must supply a keyid", None)
        rv = self._gnupg().sign_key(keyid, signingkey)

        # Previous crypto evaluations may now be out of date, so we
        # clear the cache so users can see results right away.
        ClearParseCache(pgpmime=True)

        return rv
Beispiel #6
0
    def command(self):
        args = list(self.args)
        if args:
            pin_key = False
            address, fprints, origins = args[0], args[1].split(','), args[2:]
        else:
            pin_key = self.data.get('pinned',
                                    [''])[0].lower()[:1] in ('y', 't')
            address = self.data.get('address', [''])[0]
            fprints = self.data.get('fingerprints', [])
            origins = self.data.get('origins', [])
        safe_assert(address or fprints or origins)

        result = lookup_crypto_keys(self.session,
                                    address,
                                    get=[f.strip() for f in fprints],
                                    pin_key=pin_key,
                                    vcard=self._get_or_create_vcard(address),
                                    origins=origins,
                                    event=self.event)

        if len(result) > 0:
            # Update the VCards!
            PGPKeysImportAsVCards(self.session,
                                  arg=[k['fingerprint']
                                       for k in result]).run()

            # The key was looked up based on the given address, so it must have
            # a user id containing that address, so when it is imported to
            # VCards, the VCard for that address will list the key.
            for k in result:
                k.in_vcards = True
            # Previous crypto evaluations may now be out of date, so we
            # clear the cache so users can see results right away.
            ClearParseCache(pgpmime=True)

        return self._success(
            _n('Imported %d encryption key', 'Imported %d encryption keys',
               len(result)) % len(result),
            result=result)
Beispiel #7
0
    def command(self):
        emails = set(list(self.args)) | set(self.data.get('email', []))
        safe_assert(emails)

        idx = self._idx()
        gnupg = self._gnupg(dry_run=True)
        missing, old, status = [], {}, {}

        for email in emails:
            vc = self.session.config.vcards.get_vcard(email)
            fp = vc.pgp_key if vc else None
            if vc and fp:
                if self._key_can_encrypt(gnupg, fp):
                    old[email] = fp
                    status[email] = 'Key is already on our key-chain'
                else:
                    # FIXME: Should we remove the bad key from the vcard?
                    # FIXME: Should we blacklist the bad key?
                    missing.append(email)
                    status[email] = 'Obsolete key is on our key-chain'
            else:
                missing.append(email)
                status[email] = 'We have no key for this person'

        should_import = {}
        for email in missing:
            if self._uses_crypto(idx, email):
                keys = lookup_crypto_keys(self.session, email,
                                          origins=self.TOFU_ORIGINS,
                                          strict_email_match=True,
                                          event=self.event)
                for keyinfo in (keys or []):
                    if self._seen_enough_signatures(idx, email, keyinfo):
                        should_import[email] = keyinfo['fingerprint']
                        break
                if keys and 'email' not in should_import:
                    status[email] = 'Found keys, but none in active use'
            else:
                status[email] = 'Have not seen enough PGP messages'

        imported = {}
        for email, fingerprint in should_import.iteritems():
            keys = lookup_crypto_keys(
                self.session, email,
                get=[fingerprint],
                origins=self.TOFU_ORIGINS,
                strict_email_match=True,
                event=self.event)
            if keys:
                imported[email] = keys
                status[email] = 'Imported key!'
            else:
                status[email] = 'Failed to import key'

        for email in imported:
            if email in missing:
                missing.remove(email)

        if len(imported) > 0:
            # Update the VCards!
            fingerprints = []
            for keys in imported.values():
                fingerprints.extend([k['fingerprint'] for k in keys])
            PGPKeysImportAsVCards(self.session, arg=fingerprints).run()
            # Previous crypto evaluations may now be out of date, so we
            # clear the cache so users can see results right away.
            ClearParseCache(pgpmime=True)

        # i18n note: Not translating things here, since messages are not
        #            generally use-facing and we want to reduce load on our
        #            translators.
        return self._success('Evaluated key TOFU', result={
            'missing_keys': missing,
            'imported_keys': imported,
            'status': status,
            'on_keychain': old})
Beispiel #8
0
    def command(self):
        tofu_cfg = self.session.config.prefs.key_tofu
        if not (tofu_cfg.autocrypt or tofu_cfg.historic):
            return self._success(
                'Key TOFU disabled. Check prefs.key_tofu.* settings.')

        args = list(self.args)
        if args and (args[0] == '--dry'):
            dry_run = args.pop(0)
        else:
            dry_run = 'keytofudry' in self.session.config.sys.debug

        if args and (args[0] == '--should'):
            should_encrypt = args.pop(0)
        else:
            should_encrypt = self.data.get('should-encrypt', ['N'])[0]
            should_encrypt = should_encrypt.lower()[:1] in ('y', 't')

        emails = set(args) | set(self.data.get('email', []))
        if not emails:
            return self._success('Nothing Happened')

        if tofu_cfg.autocrypt:
            from mailpile.plugins.crypto_autocrypt import get_Autocrypt_DB, save_Autocrypt_DB, AutocryptRecord, AutocryptKeyLookupHandler
            acState = get_Autocrypt_DB(self.session.config)['state']
        else:
            acState = None

        idx = self._idx()
        gnupg = self._gnupg()
        known_keys_list = _mailpile_key_list(gnupg.list_keys())

        missing, old, status = [], {}, {}
        for email in emails:
            vc = self.session.config.vcards.get_vcard(email)
            fp = vc.pgp_key if vc else None
            if vc and fp:
                if self._key_can_encrypt(gnupg, fp):
                    old[email] = fp
                    status[email] = 'Key is already on our key-chain'
                    if vc.pgp_key_pinned:
                        status[email] = 'Key is pinned'
                    elif self._key_is_trusted(fp, known_keys_list):
                        status[email] = 'Key is trusted by GnuPG'
                    elif acState:
                        acr = AutocryptRecord.Load(acState, email, _raise=None)
                        if acr and acr.should_encrypt(
                        ) and not acr.imported_ts:
                            missing.append(email)
                            status[email] = 'Obsolete key is on our key-chain'
                else:
                    # FIXME: Should we remove the bad key from the vcard?
                    # FIXME: Should we blacklist the bad key?
                    # FIXME: Should this trigger a notification, per. #1869?
                    missing.append(email)
                    status[email] = 'Obsolete key is on our key-chain'
            else:
                missing.append(email)
                status[email] = 'We have no key for this person'

        global TOFU_CHECK_HISTORY
        now = time.time()
        interval_cutoff = now - tofu_cfg.min_interval
        for k in TOFU_CHECK_HISTORY.keys():
            if TOFU_CHECK_HISTORY.get(k, now) < interval_cutoff:
                del TOFU_CHECK_HISTORY[k]

        should_import = {}
        hist_origins = [o.strip() for o in tofu_cfg.hist_origins.split(',')]
        for email in missing:
            checking = '%s/%s' % (email, tofu_cfg)
            last_check = TOFU_CHECK_HISTORY.get(checking, 0)
            if (not should_encrypt
                ) and last_check and last_check > interval_cutoff:
                status[email] += ' (checked recently)'
                continue
            elif not dry_run:
                TOFU_CHECK_HISTORY[checking] = now

            if tofu_cfg.autocrypt and acState:
                acr = AutocryptRecord.Load(acState, email, _raise=None)
                if acr and acr.should_encrypt() and not acr.imported_ts:
                    should_import[email] = (acr.key_sig,
                                            AutocryptKeyLookupHandler.NAME)

            if tofu_cfg.historic and hist_origins and email not in should_import:
                count = self._recently_used_crypto(tofu_cfg, idx, email)
                if count or should_encrypt:
                    keys = lookup_crypto_keys(self.session,
                                              email,
                                              origins=hist_origins,
                                              strict_email_match=True,
                                              known_keys_list=known_keys_list,
                                              event=self.event,
                                              only_good=True) or []
                    for keyinfo in keys:
                        if should_encrypt or self._seen_enough_signatures(
                                tofu_cfg, idx, email, keyinfo):
                            should_import[email] = (keyinfo['fingerprint'],
                                                    hist_origins)
                            break
                    if keys and 'email' not in should_import:
                        status[email] = 'Found keys, but none in active use'
                else:
                    status[email] = 'Have not seen enough PGP messages'

        imported = {}
        for email, (key_id, origins) in should_import.iteritems():
            if 'keytofu' in self.session.config.sys.debug:
                self.session.ui.debug('keytofu(%s): importing %s from %s' %
                                      (email, key_id, origins))
            if dry_run:
                status[email] = 'Should import %s from %s' % (key_id, origins)
            else:
                keys = lookup_crypto_keys(
                    self.session,
                    email,
                    get=[key_id],
                    vcard=self.session.config.vcards.get_vcard(email),
                    strict_email_match=True,
                    origins=origins,
                    known_keys_list=known_keys_list,
                    event=self.event)
                if keys:
                    # FIXME: This should trigger a notification, per. #1869
                    imported[email] = keys
                    status[email] = 'Imported key!'
                    vc = self.session.config.vcards.get_vcard(email)
                    if vc and key_id in keys:
                        with vc:
                            vc.pgp_key = keys[key_id].fingerprint
                            vc.save()
                else:
                    status[email] = 'Failed to import key'

        for email in imported:
            if email in missing:
                missing.remove(email)

        if len(imported) > 0:
            # Update the VCards!
            fingerprints = []
            for keys in imported.values():
                fingerprints.extend(k['fingerprint'] for k in keys)
            PGPKeysImportAsVCards(self.session, arg=fingerprints).run()
            # Previous crypto evaluations may now be out of date, so we
            # clear the cache so users can see results right away.
            ClearParseCache(pgpmime=True)

        # i18n note: Not translating things here, since messages are not
        #            generally user-facing and we want to reduce load on
        #            our translators.
        return self._success('Evaluated key TOFU',
                             result={
                                 'missing_keys': missing,
                                 'imported_keys': imported,
                                 'status': status,
                                 'on_keychain': old
                             })