Esempio n. 1
0
    def command(self):
        args = list(self.args)
        for q in self.data.get("q", []):
            args.extend(q.split())

        g = GnuPG()
        return g.search_key(" ".join(args))
Esempio n. 2
0
    def get_vcards(self):
        if not self.config.active:
            return []

        gnupg = GnuPG()
        keys = gnupg.list_keys()
        results = []
        vcards = {}
        for key_id, key in keys.iteritems():
            vcls = [VCardLine(name='KEY', value=self.VCL_KEY_FMT % key_id)]
            card = None
            emails = []
            for uid in key.get('uids', []):
                if uid.get('email'):
                    vcls.append(VCardLine(name='email', value=uid['email']))
                    card = card or vcards.get(uid['email'])
                    emails.append(uid['email'])
                if uid.get('name'):
                    name = uid['name']
                    vcls.append(VCardLine(name='fn', value=name))
            if card and emails:
                card.add(*vcls)
            elif emails:
                # This is us taking care to only create one card for each
                # set of e-mail addresses.
                card = MailpileVCard(*vcls)
                for email in emails:
                    vcards[email] = card
                results.append(card)

        return results
Esempio n. 3
0
    def command(self):
        args = self.args[:]
        for q in self.data.get('q', []):
            args.extend(q.split())

        g = GnuPG()
        return g.search_key(" ".join(args))
Esempio n. 4
0
def lookup_crypto_keys(session, address):
    x = {}
    scores = []
    for handler in KEY_LOOKUP_HANDLERS:
        h = handler(session)
        r, s = h.lookup(address)
        for key, value in r.iteritems():
            if key in x:
                x[key].update(value)
            else:
                x[key] = value
                x[key]["origin"] = []
            x[key]["origin"].append(h.NAME)
        scores.append(s)

    for scoreset in scores:
        for key, value in scoreset.iteritems():
            if key not in x:
                continue
            if "score" not in x[key]:
                x[key]["score"] = 0
            x[key]["score"] += value

    g = GnuPG()
    known_keys_list = g.list_keys()
    for key in x.keys():
        x[key]["fingerprint"] = key
        x[key]["score"] += crypto_keys_scorer(known_keys_list, key)

    x = [i for i in x.values()]
    x.sort(key=lambda k: -k["score"])
    return x
Esempio n. 5
0
    def get_vcards(self):
        if not self.config.active:
            return []

        gnupg = GnuPG()
        keys = gnupg.list_keys()
        results = []
        vcards = {}
        for key in keys.values():
            vcls = [VCardLine(name="KEY",
                              value=self.VCL_KEY_FMT % key)]
            card = None
            emails = []
            for uid in key["uids"]:
                if "email" in uid and uid["email"]:
                    vcls.append(VCardLine(name="email", value=uid["email"]))
                    card = card or vcards.get(uid['email'])
                    emails.append(uid["email"])
                if "name" in uid and uid["name"]:
                    name = uid["name"]
                    vcls.append(VCardLine(name="fn", value=name))
            if card and emails:
                card.add(*vcls)
            elif emails:
                # This is us taking care to only create one card for each
                # set of e-mail addresses.
                card = SimpleVCard(*vcls)
                for email in emails:
                    vcards[email] = card
                results.append(card)

        return results
Esempio n. 6
0
    def evaluate_pgp(self, tree, check_sigs=True, decrypt=False):
        if 'text_parts' not in tree:
            return tree

        pgpdata = []
        for part in tree['text_parts']:
            if 'crypto' not in part:
                part['crypto'] = {}

            ei = si = None
            if check_sigs:
                if part['type'] == 'pgpbeginsigned':
                    pgpdata = [part]
                elif part['type'] == 'pgpsignedtext':
                    pgpdata.append(part)
                elif part['type'] == 'pgpsignature':
                    pgpdata.append(part)
                    try:
                        gpg = GnuPG()
                        message = ''.join([p['data'].encode(p['charset'])
                                           for p in pgpdata])
                        si = pgpdata[1]['crypto']['signature'
                                                  ] = gpg.verify(message)
                        pgpdata[0]['data'] = ''
                        pgpdata[2]['data'] = ''

                    except Exception, e:
                        print e

            if decrypt:
                if part['type'] in ('pgpbegin', 'pgptext'):
                    pgpdata.append(part)
                elif part['type'] == 'pgpend':
                    pgpdata.append(part)

                    gpg = GnuPG()
                    (signature_info, encryption_info, text
                     ) = gpg.decrypt(''.join([p['data'] for p in pgpdata]))

                    # FIXME: If the data is binary, we should provide some
                    #        sort of download link or maybe leave the PGP
                    #        blob entirely intact, undecoded.
                    text, charset = self.decode_text(text, binary=False)

                    ei = pgpdata[1]['crypto']['encryption'] = encryption_info
                    si = pgpdata[1]['crypto']['signature'] = signature_info
                    if encryption_info["status"] == "decrypted":
                        pgpdata[1]['data'] = text
                        pgpdata[0]['data'] = ""
                        pgpdata[2]['data'] = ""

            # Bubbling up!
            if (si or ei) and 'crypto' not in tree:
                tree['crypto'] = {'signature': SignatureInfo(),
                                  'encryption': EncryptionInfo()}
            if si:
                tree['crypto']['signature'].mix(si)
            if ei:
                tree['crypto']['encryption'].mix(ei)
Esempio n. 7
0
    def command(self):
        keyid = self.data.get("keyid", self.args)
        g = GnuPG()
        res = []
        for key in keyid:
            res.append(g.recv_key(key))

        return res
Esempio n. 8
0
    def command(self):
        args = self.args[:]
        for q in self.data.get('terms', []):
            args.extend(q.split())

        print "Querying PGP keyservers for: '%s'" % " ".join(args)
        g = GnuPG()
        return g.search_key(" ".join(args))
Esempio n. 9
0
 def _import_key(self, result, keytype):
     if keytype == "openpgp":
         g = GnuPG(self.config)
         res = g.import_keys(result[keytype])
         if len(res["updated"]):
             self._managed_keys_add(result["address"], keytype)
         return res
     else:
         # We currently only support OpenPGP keys
         return False
Esempio n. 10
0
    def evaluate_pgp(self, tree, check_sigs=True, decrypt=False):
        if "text_parts" not in tree:
            return tree

        pgpdata = []
        for part in tree["text_parts"]:
            if "crypto" not in part:
                part["crypto"] = {}

            ei = si = None
            if check_sigs:
                if part["type"] == "pgpbeginsigned":
                    pgpdata = [part]
                elif part["type"] == "pgpsignedtext":
                    pgpdata.append(part)
                elif part["type"] == "pgpsignature":
                    pgpdata.append(part)
                    try:
                        gpg = GnuPG()
                        message = "".join([p["data"].encode(p["charset"]) for p in pgpdata])
                        si = pgpdata[1]["crypto"]["signature"] = gpg.verify(message)
                        pgpdata[0]["data"] = ""
                        pgpdata[2]["data"] = ""

                    except Exception, e:
                        print e

            if decrypt:
                if part["type"] in ("pgpbegin", "pgptext"):
                    pgpdata.append(part)
                elif part["type"] == "pgpend":
                    pgpdata.append(part)

                    gpg = GnuPG()
                    (signature_info, encryption_info, text) = gpg.decrypt("".join([p["data"] for p in pgpdata]))

                    # FIXME: If the data is binary, we should provide some
                    #        sort of download link or maybe leave the PGP
                    #        blob entirely intact, undecoded.
                    text, charset = self.decode_text(text, binary=False)

                    ei = pgpdata[1]["crypto"]["encryption"] = encryption_info
                    si = pgpdata[1]["crypto"]["signature"] = signature_info
                    if encryption_info["status"] == "decrypted":
                        pgpdata[1]["data"] = text
                        pgpdata[0]["data"] = ""
                        pgpdata[2]["data"] = ""

            # Bubbling up!
            if (si or ei) and "crypto" not in tree:
                tree["crypto"] = {"signature": SignatureInfo(), "encryption": EncryptionInfo()}
            if si:
                tree["crypto"]["signature"].mix(si)
            if ei:
                tree["crypto"]["encryption"].mix(ei)
Esempio n. 11
0
 def _check_password(self, password, account=None, fingerprint=None):
     if account:
         # We're going to keep punting on this for a while...
         return True
     elif fingerprint:
         sps = SecurePassphraseStorage(password)
         gpg = GnuPG(self.session.config)
         status, sig = gpg.sign('OK', fromkey=fingerprint, passphrase=sps)
         return (status == 0)
     else:
         return True
Esempio n. 12
0
def lookup_crypto_keys(session, address, event=None, allowremote=True):
    def _calc_scores(x, scores):
        for key in x.keys():
            x[key]["score"] = 0

        for scoreset in scores:
            for key, value in scoreset.iteritems():
                if key not in x:
                    continue
                if "score" not in x[key]:
                    x[key]["score"] = 0
                x[key]["score"] += value
        return x

    x = {}
    scores = []
    lastresult = {}

    for handler in KEY_LOOKUP_HANDLERS:
        h = handler(session)
        if not allowremote and not h.LOCAL:
            continue

        if event:
            m = _calc_scores(x, scores)
            m = [i for i in m.values()]
            m.sort(key=lambda k: -k["score"])
            event.private_data = {"result": m, "runningsearch": h.NAME}
            session.config.event_log.log_event(event)

        r, s = h.lookup(address)
        for key, value in r.iteritems():
            if key in x:
                x[key].update(value)
            else:
                x[key] = value
                x[key]["origin"] = []
            x[key]["origin"].append(h.NAME)
        scores.append(s)

    x = _calc_scores(x, scores)

    g = GnuPG()
    known_keys_list = g.list_keys()
    for key in x.keys():
        x[key]["fingerprint"] = key
        x[key]["score"] += crypto_keys_scorer(known_keys_list, key)

    x = [i for i in x.values()]
    x.sort(key=lambda k: -k["score"])
    if event:
        event.private_data = {"result": x, "runningsearch": None}
        session.config.event_log.log_event(event)
    return x
Esempio n. 13
0
 def _import_key(self, result, keytype):
     if keytype == "openpgp":
         g = GnuPG()
         if self.config:
             g.passphrase = self.config.gnupg_passphrase.get_reader()
         res = g.import_keys(result[keytype])
         if len(res["updated"]):
             self._managed_keys_add(result["address"], keytype)
         return res
     else:
         # We currently only support OpenPGP keys
         return False
Esempio n. 14
0
 def command(self):
     key_data = ""
     if len(self.args) != 0:
         key_file = self.data.get("key_file", self.args[0])
         with  open(key_file) as file:
             key_data = file.read()
     if "key_data" in self.data:
         key_data = self.data.get("key_data")
     elif "key_file" in self.data:
         pass
     g = GnuPG()
     return g.import_keys(key_data)
Esempio n. 15
0
    def command(self):
        args = list(self.args)
        if len(args) >= 0:
            addr = args[0]
        else:
            addr = self.data.get("address", None)

        if addr is None:
            return self._error("Must supply e-mail address", None)

        g = GnuPG()
        res = g.address_to_keys(args[0])
        return self._success("Searched for keys for e-mail address", res)
Esempio n. 16
0
    def _do_login(self, user, password, load_index=False, redirect=False):
        session, config = self.session, self.session.config
        session_id = self.session.ui.html_variables.get('http_session')

        # This prevents folks from sending us a DEFAULT user (upper case),
        # which is an internal security bypass below.
        user = user and user.lower()

        if not user:
            from mailpile.config import SecurePassphraseStorage
            sps = SecurePassphraseStorage(password)
            password = ''
            try:
                # Verify the passphrase
                gpg = GnuPG(use_agent=False)
                if gpg.is_available():
                    gpg.passphrase = sps.get_reader()
                    assert(gpg.sign('Sign This!')[0] == 0)

                    # Store the varified passphrase
                    config.gnupg_passphrase.data = sps.data

                    # Load the config and index, if necessary
                    if not config.loaded_config:
                        self._config()
                        if load_index:
                            self._idx()
                        else:
                            pass  # FIXME: Start load in background

                    session.ui.debug('Good passphrase for %s' % session_id)
                    return self._logged_in(redirect=redirect)
                else:
                    session.ui.debug('No GnuPG, checking DEFAULT user')
                    # No GnuPG, see if there is a DEFAULT user in the config
                    user = '******'

            except (AssertionError, IOError):
                session.ui.debug('Bad passphrase for %s' % session_id)
                return self._error(_('Invalid passphrase, please try again'))

        if user in config.logins or user == 'DEFAULT':
            # FIXME: Salt and hash the password, check if it matches
            #        the entry in our user/password list (TODO).
            # NOTE:  This hack effectively disables auth without GnUPG
            if user == 'DEFAULT':
                session.ui.debug('FIXME: Unauthorized login allowed')
                return self._logged_in(redirect=redirect)
            raise Exception('FIXME')

        self._error(_('Incorrect username or password'))
Esempio n. 17
0
    def TransformOutgoing(self, sender, rcpts, msg, **kwargs):
        matched = False
        keydata = mutual = sender_keyid = key_binary = None

        gnupg = GnuPG(self.config, event=GetThreadEvent())
        profile = self._get_sender_profile(sender, kwargs)
        vcard = profile['vcard']
        if vcard is not None:
            crypto_format = vcard.crypto_format
            sender_keyid = vcard.pgp_key
            if sender_keyid and 'autocrypt' in crypto_format:
                key_binary = gnupg.get_minimal_key(key_id=sender_keyid,
                                                   user_id=sender)

            if key_binary:
                mutual = 'E' in crypto_format.split('+')[0].split(':')[-1]
                msg["Autocrypt"] = make_autocrypt_header(
                    sender, key_binary, prefer_encrypt_mutual=mutual)

                if 'encrypt' in msg.get('Encryption', '').lower():
                    gossip_list = []
                    for rcpt in rcpts:
                        # FIXME: Check if any of the recipients are in the BCC
                        #        header; omit their keys if so?
                        try:
                            # This *should* always succeed: if we are encrypting,
                            # then the key we encrypt to should already be in
                            # the keychain.
                            if '#' in rcpt:
                                rcpt, rcpt_keyid = rcpt.split('#')
                            else:
                                # This happens when composing in the CLI.
                                rcpt_keyid = rcpt
                            if (rcpt != sender) and rcpt_keyid:
                                kb = gnupg.get_minimal_key(key_id=rcpt_keyid,
                                                           user_id=rcpt)
                                if kb:
                                    gossip_list.append(make_autocrypt_header(
                                        rcpt, kb, prefix='Autocrypt-Gossip'))
                        except (ValueError, IndexError):
                            pass
                    if len(gossip_list) > 1:
                        # No point gossiping peoples keys back to them alone.
                        for hdr in gossip_list:
                            msg.add_header('Autocrypt-Gossip', hdr)

                matched = True

        return sender, rcpts, msg, matched, True
Esempio n. 18
0
File: auth.py Progetto: dkm/Mailpile
def VerifyAndStorePassphrase(config, passphrase=None, sps=None):
    if passphrase and not sps:
        from mailpile.config import SecurePassphraseStorage
        sps = SecurePassphraseStorage(passphrase)
        passphrase = 'this probably does not really overwrite :-( '

    assert(sps is not None)
    gpg = GnuPG(use_agent=False)
    if gpg.is_available():
        gpg.passphrase = sps.get_reader()
        gpgr = config.prefs.gpg_recipient
        gpgr = gpgr if (gpgr not in (None, '', '!CREATE')) else None
        assert(gpg.sign('Sign This!', fromkey=gpgr)[0] == 0)

    return sps
Esempio n. 19
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)

        g = GnuPG()
        return g.sign_key(keyid, signingkey)
Esempio n. 20
0
def decrypt_gpg(lines, fd):
    for line in fd:
        lines.append(line)
        if line.startswith(GPG_END_MESSAGE):
            break

    gpg = GnuPG()
    _, encryption_info, plaintext = gpg.decrypt(''.join(lines))

    if encryption_info['status'] != 'decrypted':
        gpg_exec = distutils.spawn.find_executable('gpg')
        gpg_version = gpg.version()
        raise AccessError("GPG (version: %s, location: %s) was unable to decrypt the data: %s" % (gpg_version, gpg_exec, encryption_info['status']))

    return plaintext.splitlines(True)
Esempio n. 21
0
    def command(self):
        if self.session.config.sys.lockdown:
            return self._error(_('In lockdown, doing nothing.'))

        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)

        g = GnuPG()
        return g.sign_key(keyid, signingkey)
Esempio n. 22
0
def VerifyAndStorePassphrase(config, passphrase=None, sps=None,
                                     key=None):
    if passphrase and not sps:
        from mailpile.config import SecurePassphraseStorage
        sps = SecurePassphraseStorage(passphrase)
        passphrase = 'this probably does not really overwrite :-( '

    assert(sps is not None)
    gpg = GnuPG(None, use_agent=False)
    if gpg.is_available():
        gpg.passphrase = sps.get_reader()
        gpgr = config.prefs.gpg_recipient
        gpgr = key or (gpgr if (gpgr not in (None, '', '!CREATE')) else None)
        assert(gpg.sign('Sign This!', fromkey=gpgr)[0] == 0)

    # Fun side effect: changing the passphrase invalidates the message cache
    import mailpile.mailutils
    mailpile.mailutils.ClearParseCache(full=True)

    return sps
Esempio n. 23
0
def scorer_trust(key):
    global known_keys_list
    score = 0
    if known_keys_list == None:
        g = GnuPG()
        known_keys_list = g.list_keys()

    if key in known_keys_list:
        if "e" in known_keys_list[key]["validity"]:
            score += -100
        elif "r" in known_keys_list[key]["validity"]:
            score += -10000
        elif "d" in known_keys_list[key]["validity"]:
            score += -10000
        elif ("f" in known_keys_list[key]["validity"] 
           or "u" in known_keys_list[key]["validity"]):
            score += 50
        else:
            score += 10

    return score
Esempio n. 24
0
 def _getkey(self, key):
     if key["fingerprint"] and not key["url"]:
         g = GnuPG()
         res = g.recv_key(key["fingerprint"])
     elif key["url"]:
         r = urllib2.urlopen(key["url"])
         result = r.readlines()
         start = 0
         end = len(result)
         # Hack to deal with possible HTML results from keyservers:
         for i in range(len(result)):
             if result[i].startswith("-----BEGIN PGP"):
                 start = i
             elif result[i].startswith("-----END PGP"):
                 end = i
         result = "".join(result[start:end])
         g = GnuPG()
         res = g.import_keys(result)
         return res
     else:
         raise ValueError("Need a fingerprint or a URL")
Esempio n. 25
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"]:
            g = GnuPG()
            res = g.import_keys(attr["data"])
            return self._success("Imported key", res)

        return self._error("No results found", None)
Esempio n. 26
0
	def _getkey(self, entry):
		pkaver = None
		fingerprint = None
		url = None

		for stmt in entry.split(";"):
			key, value = stmt.split("=", 1)
			if key == "v":
				pkaver = value
			elif key == "fpr":
				fingerprint = value
			elif key == "uri":
				url = value

		if pkaver != "pka1":
			raise ValueError("We only know how to deal with pka version 1")

		if fingerprint and not url:
			g = GnuPG()
			res = g.recv_key(fingerprint)
		elif url:
			r = urllib2.urlopen(url)
			result = r.readlines()
			start = 0
			end = len(result)
			# Hack to deal with possible HTML results from keyservers:
			for i in range(len(result)):
				if result[i].startswith("-----BEGIN PGP"):
					start = i
				elif result[i].startswith("-----END PGP"):
					end = i
			result = "".join(result[start:end])
			g = GnuPG()
			res = g.import_keys(result)
			return res
		else:
			raise ValueError("Need a fingerprint or a URL")
Esempio n. 27
0
def lookup_crypto_keys(session,
                       address,
                       event=None,
                       strict_email_match=False,
                       allowremote=True,
                       origins=None,
                       get=None,
                       vcard=None,
                       only_good=False,
                       pin_key=False,
                       known_keys_list=None):
    config = (session and session.config)
    found_keys = {}
    ordered_keys = []
    known_keys_list = known_keys_list or _mailpile_key_list(
        GnuPG(config or None).list_keys())

    if origins:
        handlers = [
            h for h in KEY_LOOKUP_HANDLERS if (h.NAME in origins) or (
                h.NAME.lower() in origins) or (h.SHORTNAME in origins)
        ]
    else:
        handlers = KEY_LOOKUP_HANDLERS

    ungotten = get and get[:] or []
    progress = []

    # If the user has disabled "web content", only allow local requests
    if config and allowremote and config.prefs.web_content == 'off':
        if ('keylookup' in config.sys.debug or 'keytofu' in config.sys.debug):
            session.ui.debug(
                "Remote key lookups disabled by prefs.web_content.")
        allowremote = False

    for handler in handlers:
        if get and not ungotten:
            # We have all the keys!
            break

        try:
            h = handler(session, known_keys_list)
            if not allowremote and not h.LOCAL:
                continue

            if allowremote and config and config.prefs.web_content == 'anon':
                if (config.sys.proxy.protocol not in ('tor', 'tor-risky')
                        or not h.PRIVACY_FRIENDLY):
                    if ('keylookup' in config.sys.debug
                            or 'keytofu' in config.sys.debug):
                        session.ui.debug(
                            "Origin %s disabled by prefs.web_content" % h.NAME)
                    continue

            if found_keys and (not h.PRIVACY_FRIENDLY) and (not origins):
                # We only try the privacy-hostile methods if we haven't
                # found any keys (unless origins were specified).
                if not ungotten:
                    continue

            progress.append(h.NAME)
            if event and config:
                ordered_keys.sort(key=lambda k: -k["score"])
                event.message = _('Searching for encryption keys in: %s') % _(
                    h.NAME)
                event.private_data = {
                    "result": ordered_keys,
                    "progress": progress,
                    "runningsearch": h.NAME
                }
                config.event_log.log_event(event)

            # We allow for more time when importing keys
            timeout = h.TIMEOUT
            if ungotten:
                timeout *= 4

            # h.lookup will remove found keys from the wanted list,
            # but we have to watch out for the effects of timeouts.
            wanted = ungotten[:]
            results = RunTimed(timeout,
                               h.lookup,
                               address,
                               strict_email_match=strict_email_match,
                               get=(wanted if (get is not None) else None))
            ungotten[:] = wanted
        except KeyboardInterrupt:
            raise
        except:
            if config and config.sys.debug:
                traceback.print_exc()
            results = {}

        # FIXME: This merging of info about keys is probably misguided.
        for key_id, key_info in results.iteritems():
            if key_id in found_keys:
                old_scores = found_keys[key_id].scores
                old_uids = found_keys[key_id].uids
                found_keys[key_id].update(key_info)
                found_keys[key_id].scores.update(old_scores)

                # Merge in the old UIDs
                uid_emails = [u.email for u in key_info.uids]
                for uid in old_uids:
                    email = uid.email
                    if email and email not in uid_emails:
                        found_keys[key_id].uids.append(uid)
            else:
                found_keys[key_id] = key_info
            found_keys[key_id].origins.append(h.NAME)

        for key_id in found_keys.keys():
            _normalize_key(session, found_keys[key_id])
            _update_scores(session, key_id, found_keys[key_id],
                           known_keys_list)

        # This updates and sorts ordered_keys in place. This will magically
        # also update the data on the viewable event, because Python.
        ordered_keys[:] = found_keys.values()
        ordered_keys.sort(key=lambda k: -k.score)

    if only_good:
        ordered_keys = [k for k in ordered_keys if k.score > 0]

    if get and vcard and ordered_keys:
        with vcard:
            vcard.pgp_key = ordered_keys[0].fingerprint
            vcard.pgp_key_pinned = 'true' if pin_key else 'false'
            vcard.save()
        ordered_keys[0].is_preferred = True
        ordered_keys[0].is_pinned = pin_key
        for k in ordered_keys[1:]:
            k.is_preferred = k.is_pinned = False

    if event and config:
        event.private_data = {"result": ordered_keys, "runningsearch": False}
        config.event_log.log_event(event)
    return ordered_keys
Esempio n. 28
0
 def command(self):
     keyid = self.data.get("keyid", self.args[0])
     g = GnuPG()
     return g.recv_key(keyid)
Esempio n. 29
0
def PrepareMessage(config, msg, sender=None, rcpts=None, events=None):
    msg = copy.deepcopy(msg)

    # Short circuit if this message has already been prepared.
    if 'x-mp-internal-sender' in msg and 'x-mp-internal-rcpts' in msg:
        return (sender or msg['x-mp-internal-sender'], rcpts
                or [r.strip() for r in msg['x-mp-internal-rcpts'].split(',')],
                msg, events)

    crypto_policy = config.prefs.crypto_policy.lower()
    rcpts = rcpts or []

    # Iterate through headers to figure out what we want to do...
    need_rcpts = not rcpts
    for hdr, val in msg.items():
        lhdr = hdr.lower()
        if lhdr == 'from':
            sender = sender or val
        elif lhdr == 'encryption':
            crypto_policy = val.lower()
        elif need_rcpts and lhdr in ('to', 'cc', 'bcc'):
            rcpts += ExtractEmails(val, strip_keys=False)

    # Are we sane?
    if not sender:
        raise NoFromAddressError()
    if not rcpts:
        raise NoRecipientError()

    # Are we encrypting? Signing?
    if crypto_policy == 'default':
        crypto_policy = config.prefs.crypto_policy

    # This is the BCC hack that Brennan hates!
    rcpts += [sender]

    sender = ExtractEmails(sender, strip_keys=False)[0]
    sender_keyid = None
    if config.prefs.openpgp_header:
        try:
            gnupg = GnuPG()
            seckeys = dict([(x["email"], y["fingerprint"])
                            for y in gnupg.list_secret_keys().values()
                            for x in y["uids"]])
            sender_keyid = seckeys[sender]
        except:
            pass

    rcpts, rr = [sender], rcpts
    for r in rr:
        for e in ExtractEmails(r, strip_keys=False):
            if e not in rcpts:
                rcpts.append(e)

    # Add headers we require
    if 'date' not in msg:
        msg['Date'] = email.utils.formatdate()

    if sender_keyid and config.prefs.openpgp_header:
        msg["OpenPGP"] = "id=%s; preference=%s" % (sender_keyid,
                                                   config.prefs.openpgp_header)

    if 'openpgp' in crypto_policy:

        # FIXME: Make a more efficient sign+encrypt wrapper

        cleaner = lambda m: CleanMessage(config, m)
        if 'sign' in crypto_policy:
            msg = OpenPGPMimeSigningWrapper(config,
                                            sender=sender,
                                            cleaner=cleaner,
                                            recipients=rcpts).wrap(msg)
        if 'encrypt' in crypto_policy:
            msg = OpenPGPMimeEncryptingWrapper(config,
                                               sender=sender,
                                               cleaner=cleaner,
                                               recipients=rcpts).wrap(msg)

    rcpts = set([r.rsplit('#', 1)[0] for r in rcpts])
    msg['x-mp-internal-readonly'] = str(int(time.time()))
    msg['x-mp-internal-sender'] = sender
    msg['x-mp-internal-rcpts'] = ', '.join(rcpts)
    return (sender, rcpts, msg, events)
Esempio n. 30
0
    def evaluate_pgp(self, tree, check_sigs=True, decrypt=False):
        if 'text_parts' not in tree:
            return tree

        pgpdata = []
        for part in tree['text_parts']:
            if 'crypto' not in part:
                part['crypto'] = {}

            ei = si = None
            if check_sigs:
                if part['type'] == 'pgpbeginsigned':
                    pgpdata = [part]
                elif part['type'] == 'pgpsignedtext':
                    pgpdata.append(part)
                elif part['type'] == 'pgpsignature':
                    pgpdata.append(part)
                    try:
                        gpg = GnuPG()
                        message = ''.join(
                            [p['data'].encode(p['charset']) for p in pgpdata])
                        si = pgpdata[1]['crypto']['signature'] = gpg.verify(
                            message)
                        pgpdata[0]['data'] = ''
                        pgpdata[2]['data'] = ''

                    except Exception, e:
                        print e

            if decrypt:
                if part['type'] in ('pgpbegin', 'pgptext'):
                    pgpdata.append(part)
                elif part['type'] == 'pgpend':
                    pgpdata.append(part)

                    gpg = GnuPG()
                    (signature_info, encryption_info,
                     text) = gpg.decrypt(''.join([p['data'] for p in pgpdata]))

                    # FIXME: If the data is binary, we should provide some
                    #        sort of download link or maybe leave the PGP
                    #        blob entirely intact, undecoded.
                    text, charset = self.decode_text(text, binary=False)

                    ei = pgpdata[1]['crypto']['encryption'] = encryption_info
                    si = pgpdata[1]['crypto']['signature'] = signature_info
                    if encryption_info["status"] == "decrypted":
                        pgpdata[1]['data'] = text
                        pgpdata[0]['data'] = ""
                        pgpdata[2]['data'] = ""

            # Bubbling up!
            if (si or ei) and 'crypto' not in tree:
                tree['crypto'] = {
                    'signature': SignatureInfo(),
                    'encryption': EncryptionInfo()
                }
            if si:
                tree['crypto']['signature'].mix(si)
            if ei:
                tree['crypto']['encryption'].mix(ei)
Esempio n. 31
0
def PrepareMessage(config, msg, sender=None, rcpts=None):
    msg = copy.deepcopy(msg)

    # Short circuit if this message has already been prepared.
    if 'x-mp-internal-sender' in msg and 'x-mp-internal-rcpts' in msg:
        return (sender or msg['x-mp-internal-sender'],
                rcpts or [r.strip()
                          for r in msg['x-mp-internal-rcpts'].split(',')],
                msg)

    crypto_policy = config.prefs.crypto_policy.lower()
    rcpts = rcpts or []

    # Iterate through headers to figure out what we want to do...
    need_rcpts = not rcpts
    for hdr, val in msg.items():
        lhdr = hdr.lower()
        if lhdr == 'from':
            sender = sender or val
        elif lhdr == 'encryption':
            crypto_policy = val.lower()
        elif need_rcpts and lhdr in ('to', 'cc', 'bcc'):
            rcpts += ExtractEmails(val, strip_keys=False)

    # Are we sane?
    if not sender:
        raise NoFromAddressError()
    if not rcpts:
        raise NoRecipientError()

    # Are we encrypting? Signing?
    if crypto_policy == 'default':
        crypto_policy = config.prefs.crypto_policy

    # This is the BCC hack that Brennan hates!
    rcpts += [sender]

    sender = ExtractEmails(sender, strip_keys=False)[0]
    sender_keyid = None
    if config.prefs.openpgp_header:
        try:
            gnupg = GnuPG()
            seckeys = dict([(x["email"], y["fingerprint"])
                            for y in gnupg.list_secret_keys().values()
                            for x in y["uids"]])
            sender_keyid = seckeys[sender]
        except:
            pass

    rcpts, rr = [sender], rcpts
    for r in rr:
        for e in ExtractEmails(r, strip_keys=False):
            if e not in rcpts:
                rcpts.append(e)

    # Add headers we require
    if 'date' not in msg:
        msg['Date'] = email.utils.formatdate()

    if sender_keyid and config.prefs.openpgp_header:
        msg["OpenPGP"] = "id=%s; preference=%s" % (sender_keyid,
                                                   config.prefs.openpgp_header)

    if 'openpgp' in crypto_policy:

        # FIXME: Make a more efficient sign+encrypt wrapper

        cleaner = lambda m: CleanMessage(config, m)
        if 'sign' in crypto_policy:
            msg = OpenPGPMimeSigningWrapper(config,
                                            sender=sender,
                                            cleaner=cleaner,
                                            recipients=rcpts).wrap(msg)
        if 'encrypt' in crypto_policy:
            msg = OpenPGPMimeEncryptingWrapper(config,
                                               sender=sender,
                                               cleaner=cleaner,
                                               recipients=rcpts).wrap(msg)

    rcpts = set([r.rsplit('#', 1)[0] for r in rcpts])
    msg['x-mp-internal-readonly'] = str(int(time.time()))
    msg['x-mp-internal-sender'] = sender
    msg['x-mp-internal-rcpts'] = ', '.join(rcpts)
    return (sender, rcpts, msg)
Esempio n. 32
0
 def _gnupg(self, **kwargs):
     return GnuPG(self.session.config, event=self.event, **kwargs)
Esempio n. 33
0
 def command(self):
     keyid = self.data.get("keyid", self.args[0])
     g = GnuPG()
     return g.recv_key(keyid)
Esempio n. 34
0
    def TransformOutgoing(self, sender, rcpts, msg, **kwargs):
        matched = False
        gnupg = None
        sender_keyid = None

        # Prefer to just get everything from the profile VCard, in the
        # common case...
        profile = self.config.vcards.get_vcard(sender)
        if profile:
            sender_keyid = profile.pgp_key
            crypto_format = profile.crypto_format or 'none'
        else:
            crypto_format = 'none'

        # Parse the openpgp_header data from the crypto_format
        openpgp_header = [
            p.split(':')[-1] for p in crypto_format.split('+')
            if p.startswith('openpgp_header:')
        ]
        if not openpgp_header:
            openpgp_header = self.config.prefs.openpgp_header and ['CFG']

        if openpgp_header[0] != 'N' and not sender_keyid:
            # This is a fallback: this shouldn't happen much in normal use
            try:
                gnupg = gnupg or GnuPG(self.config)
                seckeys = dict([
                    (uid["email"], fp)
                    for fp, key in gnupg.list_secret_keys().iteritems()
                    if key["capabilities_map"].get("encrypt")
                    and key["capabilities_map"].get("sign")
                    for uid in key["uids"]
                ])
                sender_keyid = seckeys.get(sender)
            except (KeyError, TypeError, IndexError, ValueError):
                traceback.print_exc()

        if sender_keyid and openpgp_header:
            preference = {
                'ES': 'signencrypt',
                'SE': 'signencrypt',
                'E': 'encrypt',
                'S': 'sign',
                'N': 'unprotected',
                'CFG': self.config.prefs.openpgp_header
            }[openpgp_header[0].upper()]
            msg["OpenPGP"] = ("id=%s; preference=%s" %
                              (sender_keyid, preference))

        if ('attach-pgp-pubkey' in msg
                and msg['attach-pgp-pubkey'][:3].lower() in ('yes', 'tru')):
            gnupg = gnupg or GnuPG(self.config)
            if sender_keyid:
                keys = gnupg.list_keys(selectors=[sender_keyid])
            else:
                keys = gnupg.address_to_keys(ExtractEmails(sender)[0])

            key_count = 0
            for fp, key in keys.iteritems():
                if not any(key["capabilities_map"].values()):
                    continue
                # We should never really hit this more than once. But if we
                # do, should still be fine.
                keyid = key["keyid"]
                data = gnupg.get_pubkey(keyid)

                try:
                    from_name = key["uids"][0]["name"]
                    filename = _('Encryption key for %s.asc') % from_name
                except:
                    filename = _('My encryption key.asc')
                att = MIMEBase('application', 'pgp-keys')
                att.set_payload(data)
                encoders.encode_base64(att)
                del att['MIME-Version']
                att.add_header('Content-Id', MakeContentID())
                att.add_header('Content-Disposition',
                               'attachment',
                               filename=filename)
                att.signature_info = SignatureInfo(parent=msg.signature_info)
                att.encryption_info = EncryptionInfo(
                    parent=msg.encryption_info)
                msg.attach(att)
                key_count += 1

            if key_count > 0:
                msg['x-mp-internal-pubkeys-attached'] = "Yes"

        return sender, rcpts, msg, matched, True
Esempio n. 35
0
    def command(self):
        session = self.session

        if session.config.sys.lockdown:
            return self._error(_('In lockdown, doing nothing.'))

        # Perform any required migrations
        Migrate(session).run()

        # Create local mailboxes
        session.config.open_local_mailbox(session)

        # Create standard tags and filters
        created = []
        for t in self.TAGS:
            if not session.config.get_tag_id(t):
                AddTag(session, arg=[t]).run(save=False)
                created.append(t)
            session.config.get_tag(t).update(self.TAGS[t])
        for stype, statuses in (('sig', SignatureInfo.STATUSES),
                                ('enc', EncryptionInfo.STATUSES)):
            for status in statuses:
                tagname = 'mp_%s-%s' % (stype, status)
                if not session.config.get_tag_id(tagname):
                    AddTag(session, arg=[tagname]).run(save=False)
                    created.append(tagname)
                session.config.get_tag(tagname).update({
                    'type': 'attribute',
                    'display': 'invisible',
                    'label': False,
                })

        if 'New' in created:
            Filter(session,
                   arg=[
                       'new', '@incoming', '+Inbox', '+New',
                       'Incoming mail filter'
                   ]).run(save=False)
            session.ui.notify(_('Created default tags'))

        # Import all the basic plugins
        for plugin in PLUGINS:
            if plugin not in session.config.sys.plugins:
                session.config.sys.plugins.append(plugin)
        try:
            # If spambayes is not installed, this will fail
            import mailpile.plugins.autotag_sb
            if 'autotag_sb' not in session.config.sys.plugins:
                session.config.sys.plugins.append('autotag_sb')
                session.ui.notify(_('Enabling spambayes autotagger'))
        except ImportError:
            session.ui.warning(
                _('Please install spambayes '
                  'for super awesome spam filtering'))
        session.config.save()
        session.config.load(session)

        vcard_importers = session.config.prefs.vcard.importers
        if not vcard_importers.gravatar:
            vcard_importers.gravatar.append({'active': True})
            session.ui.notify(_('Enabling gravatar image importer'))

        gpg_home = os.path.expanduser('~/.gnupg')
        if os.path.exists(gpg_home) and not vcard_importers.gpg:
            vcard_importers.gpg.append({'active': True, 'gpg_home': gpg_home})
            session.ui.notify(_('Importing contacts from GPG keyring'))

        if ('autotag_sb' in session.config.sys.plugins
                and len(session.config.prefs.autotag) == 0):
            session.config.prefs.autotag.append({
                'match_tag': 'spam',
                'unsure_tag': 'maybespam',
                'tagger': 'spambayes',
                'trainer': 'spambayes'
            })
            session.config.prefs.autotag[0].exclude_tags[0] = 'ham'

        # Assumption: If you already have secret keys, you want to
        #             use the associated addresses for your e-mail.
        #             If you don't already have secret keys, you should have
        #             one made for you, if GnuPG is available.
        #             If GnuPG is not available, you should be warned.
        gnupg = GnuPG()
        if gnupg.is_available():
            keys = gnupg.list_secret_keys()
            if len(keys) == 0:
                # FIXME: Start background process generating a key once a user
                #        has supplied a name and e-mail address.
                pass
            else:
                for key, details in keys.iteritems():
                    # Ignore revoked/expired keys.
                    if ("revocation-date" in details
                            and details["revocation-date"] <=
                            date.today().strftime("%Y-%m-%d")):
                        continue

                    for uid in details["uids"]:
                        if "email" not in uid or uid["email"] == "":
                            continue

                        if uid["email"] in [
                                x["email"] for x in session.config.profiles
                        ]:
                            # Don't set up the same e-mail address twice.
                            continue

                        # FIXME: Add route discovery mechanism.
                        profile = {
                            "email": uid["email"],
                            "name": uid["name"],
                        }
                        session.config.profiles.append(profile)
                    if not session.config.prefs.gpg_recipient:
                        session.config.prefs.gpg_recipient = key
                        session.ui.notify(_('Encrypting config to %s') % key)
                    if session.config.prefs.crypto_policy == 'none':
                        session.config.prefs.crypto_policy = 'openpgp-sign'
        else:
            session.ui.warning(_('Oh no, PGP/GPG support is unavailable!'))

        if (session.config.prefs.gpg_recipient
                and not (self._idx() and self._idx().INDEX)
                and not session.config.prefs.obfuscate_index):
            randcrap = sha512b64(
                open('/dev/urandom').read(1024),
                session.config.prefs.gpg_recipient, '%s' % time.time())
            session.config.prefs.obfuscate_index = randcrap
            session.config.prefs.index_encrypted = True
            session.ui.notify(
                _('Obfuscating search index and enabling '
                  'indexing of encrypted e-mail. '))

        session.config.save()
        return self._success(_('Performed initial Mailpile setup'))
Esempio n. 36
0
    def setup_command(self, session, do_gpg_stuff=False):
        do_gpg_stuff = do_gpg_stuff or ('do_gpg_stuff' in self.args)

        # Stop the workers...
        want_daemons = session.config.cron_worker is not None
        session.config.stop_workers()

        # Perform any required migrations
        Migrate(session).run(before_setup=True, after_setup=False)

        # Basic app config, tags, plugins, etc.
        self.basic_app_config(session,
                              save_and_update_workers=False,
                              want_daemons=want_daemons)

        # Assumption: If you already have secret keys, you want to
        #             use the associated addresses for your e-mail.
        #             If you don't already have secret keys, you should have
        #             one made for you, if GnuPG is available.
        #             If GnuPG is not available, you should be warned.
        if do_gpg_stuff:
            gnupg = GnuPG()
            accepted_keys = []
            if gnupg.is_available():
                keys = gnupg.list_secret_keys()
                for key, details in keys.iteritems():
                    # Ignore revoked/expired keys.
                    if ("revocation-date" in details and
                        details["revocation-date"] <=
                            date.today().strftime("%Y-%m-%d")):
                        continue

                    accepted_keys.append(key)
                    for uid in details["uids"]:
                        if "email" not in uid or uid["email"] == "":
                            continue

                        if uid["email"] in [x["email"]
                                            for x in session.config.profiles]:
                            # Don't set up the same e-mail address twice.
                            continue

                        # FIXME: Add route discovery mechanism.
                        profile = {
                            "email": uid["email"],
                            "name": uid["name"],
                        }
                        session.config.profiles.append(profile)
                    if (session.config.prefs.gpg_recipient in (None, '', '!CREATE')
                           and details["capabilities_map"][0]["encrypt"]):
                        session.config.prefs.gpg_recipient = key
                        session.ui.notify(_('Encrypting config to %s') % key)
                    if session.config.prefs.crypto_policy == 'none':
                        session.config.prefs.crypto_policy = 'openpgp-sign'

                if len(accepted_keys) == 0:
                    # FIXME: Start background process generating a key once a user
                    #        has supplied a name and e-mail address.
                    pass

            else:
                session.ui.warning(_('Oh no, PGP/GPG support is unavailable!'))

        # If we have a GPG key, but no master key, create it
        self.make_master_key()

        # Perform any required migrations
        Migrate(session).run(before_setup=False, after_setup=True)

        session.config.save()
        session.config.prepare_workers(session, daemons=want_daemons)

        return self._success(_('Performed initial Mailpile setup'))
Esempio n. 37
0
def lookup_crypto_keys(session,
                       address,
                       event=None,
                       strict_email_match=False,
                       allowremote=True,
                       origins=None,
                       get=None):
    known_keys_list = GnuPG(session and session.config or None).list_keys()
    found_keys = {}
    ordered_keys = []

    if origins:
        handlers = [
            h for h in KEY_LOOKUP_HANDLERS
            if (h.NAME in origins) or (h.NAME.lower() in origins)
        ]
    else:
        handlers = KEY_LOOKUP_HANDLERS

    ungotten = get and get[:] or []
    progress = []

    for handler in handlers:
        if get and not ungotten:
            # We have all the keys!
            break

        try:
            h = handler(session, known_keys_list)
            if not allowremote and not h.LOCAL:
                continue

            if found_keys and (not h.PRIVACY_FRIENDLY) and (not origins):
                # We only try the privacy-hostile methods if we haven't
                # found any keys (unless origins were specified).
                if not ungotten:
                    continue

            progress.append(h.NAME)
            if event:
                ordered_keys.sort(key=lambda k: -k["score"])
                event.message = _('Searching for encryption keys in: %s') % _(
                    h.NAME)
                event.private_data = {
                    "result": ordered_keys,
                    "progress": progress,
                    "runningsearch": h.NAME
                }
                session.config.event_log.log_event(event)

            # We allow for more time when importing keys
            timeout = h.TIMEOUT
            if ungotten:
                timeout *= 4

            # h.lookup will remove found keys from the wanted list,
            # but we have to watch out for the effects of timeouts.
            wanted = ungotten[:]
            results = RunTimed(timeout,
                               h.lookup,
                               address,
                               strict_email_match=strict_email_match,
                               get=(wanted if (get is not None) else None))
            ungotten[:] = wanted
        except KeyboardInterrupt:
            raise
        except:
            if session.config.sys.debug:
                traceback.print_exc()
            results = {}

        for key_id, key_info in results.iteritems():
            if key_id in found_keys:
                old_scores = found_keys[key_id].get('scores', {})
                old_uids = found_keys[key_id].get('uids', [])[:]
                found_keys[key_id].update(key_info)
                if 'scores' in found_keys[key_id]:
                    found_keys[key_id]['scores'].update(old_scores)
                    # No need for an else, as old_scores will be empty

                # Merge in the old UIDs
                uid_emails = [u['email'] for u in key_info.get('uids', [])]
                if 'uids' not in found_keys[key_id]:
                    found_keys[key_id]['uids'] = []
                for uid in old_uids:
                    email = uid.get('email')
                    if email and email not in uid_emails:
                        found_keys[key_id]['uids'].append(uid)
            else:
                found_keys[key_id] = key_info
                found_keys[key_id]["origins"] = []
            found_keys[key_id]["origins"].append(h.NAME)
            _update_scores(session, key_id, found_keys[key_id],
                           known_keys_list)
            _normalize_key(session, found_keys[key_id])

        # This updates and sorts ordered_keys in place. This will magically
        # also update the data on the viewable event, because Python.
        ordered_keys[:] = found_keys.values()
        ordered_keys.sort(key=lambda k: -k["score"])

    if event:
        event.private_data = {"result": ordered_keys, "runningsearch": False}
        session.config.event_log.log_event(event)
    return ordered_keys
Esempio n. 38
0
 def _gnupg(self):
     return GnuPG(self.session and self.session.config or None)
Esempio n. 39
0
    def setup_command(self, session):
        # Stop the workers...
        want_daemons = session.config.cron_worker is not None
        session.config.stop_workers()

        # Perform any required migrations
        Migrate(session).run(before_setup=True, after_setup=False)

        # Create local mailboxes
        session.config.open_local_mailbox(session)

        # Create standard tags and filters
        created = []
        for t in self.TAGS:
            if not session.config.get_tag_id(t):
                AddTag(session, arg=[t]).run(save=False)
                created.append(t)
            session.config.get_tag(t).update(self.TAGS[t])
        for stype, statuses in (('sig', SignatureInfo.STATUSES),
                                ('enc', EncryptionInfo.STATUSES)):
            for status in statuses:
                tagname = 'mp_%s-%s' % (stype, status)
                if not session.config.get_tag_id(tagname):
                    AddTag(session, arg=[tagname]).run(save=False)
                    created.append(tagname)
                session.config.get_tag(tagname).update({
                    'type': 'attribute',
                    'display': 'invisible',
                    'label': False,
                })

        if 'New' in created:
            session.ui.notify(_('Created default tags'))

        # Import all the basic plugins
        for plugin in PLUGINS:
            if plugin not in session.config.sys.plugins:
                session.config.sys.plugins.append(plugin)
        try:
            # If spambayes is not installed, this will fail
            import mailpile.plugins.autotag_sb
            if 'autotag_sb' not in session.config.sys.plugins:
                session.config.sys.plugins.append('autotag_sb')
                session.ui.notify(_('Enabling spambayes autotagger'))
        except ImportError:
            session.ui.warning(_('Please install spambayes '
                                 'for super awesome spam filtering'))

        session.config.save()
        session.config.load(session)

        vcard_importers = session.config.prefs.vcard.importers
        if not vcard_importers.gravatar:
            vcard_importers.gravatar.append({'active': True})
            session.ui.notify(_('Enabling gravatar image importer'))

        gpg_home = os.path.expanduser('~/.gnupg')
        if os.path.exists(gpg_home) and not vcard_importers.gpg:
            vcard_importers.gpg.append({'active': True,
                                        'gpg_home': gpg_home})
            session.ui.notify(_('Importing contacts from GPG keyring'))

        if ('autotag_sb' in session.config.sys.plugins and
                len(session.config.prefs.autotag) == 0):
            session.config.prefs.autotag.append({
                'match_tag': 'spam',
                'unsure_tag': 'maybespam',
                'tagger': 'spambayes',
                'trainer': 'spambayes'
            })
            session.config.prefs.autotag[0].exclude_tags[0] = 'ham'

        # Assumption: If you already have secret keys, you want to
        #             use the associated addresses for your e-mail.
        #             If you don't already have secret keys, you should have
        #             one made for you, if GnuPG is available.
        #             If GnuPG is not available, you should be warned.
        gnupg = GnuPG()
        accepted_keys = []
        if gnupg.is_available():
            keys = gnupg.list_secret_keys()
            for key, details in keys.iteritems():
                # Ignore revoked/expired keys.
                if ("revocation-date" in details and
                    details["revocation-date"] <=
                        date.today().strftime("%Y-%m-%d")):
                    continue

                accepted_keys.append(key)
                for uid in details["uids"]:
                    if "email" not in uid or uid["email"] == "":
                        continue

                    if uid["email"] in [x["email"]
                                        for x in session.config.profiles]:
                        # Don't set up the same e-mail address twice.
                        continue

                    # FIXME: Add route discovery mechanism.
                    profile = {
                        "email": uid["email"],
                        "name": uid["name"],
                    }
                    session.config.profiles.append(profile)
                if (not session.config.prefs.gpg_recipient
                   and details["capabilities_map"][0]["encrypt"]):
                    session.config.prefs.gpg_recipient = key
                    session.ui.notify(_('Encrypting config to %s') % key)
                if session.config.prefs.crypto_policy == 'none':
                    session.config.prefs.crypto_policy = 'openpgp-sign'

            if len(accepted_keys) == 0:
                # FIXME: Start background process generating a key once a user
                #        has supplied a name and e-mail address.
                pass

        else:
            session.ui.warning(_('Oh no, PGP/GPG support is unavailable!'))

        if (session.config.prefs.gpg_recipient
                and not (self._idx() and self._idx().INDEX)
                and not session.config.prefs.obfuscate_index):
            randcrap = sha512b64(open('/dev/urandom').read(1024),
                                 session.config.prefs.gpg_recipient,
                                 '%s' % time.time())
            session.config.prefs.obfuscate_index = randcrap
            session.config.prefs.index_encrypted = True
            session.ui.notify(_('Obfuscating search index and enabling '
                                'indexing of encrypted e-mail. '))

        # Perform any required migrations
        Migrate(session).run(before_setup=False, after_setup=True)

        session.config.save()
        session.config.prepare_workers(session, daemons=want_daemons)

        return self._success(_('Performed initial Mailpile setup'))
Esempio n. 40
0
 def _gnupg(self):
     return GnuPG(self.session.config, event=self.event)
Esempio n. 41
0
    def setup_command(self, session, do_gpg_stuff=False):
        do_gpg_stuff = do_gpg_stuff or ('do_gpg_stuff' in self.args)

        # Stop the workers...
        want_daemons = session.config.cron_worker is not None
        session.config.stop_workers()

        # Perform any required migrations
        Migrate(session).run(before_setup=True, after_setup=False)

        # Basic app config, tags, plugins, etc.
        self.basic_app_config(session,
                              save_and_update_workers=False,
                              want_daemons=want_daemons)

        # Assumption: If you already have secret keys, you want to
        #             use the associated addresses for your e-mail.
        #             If you don't already have secret keys, you should have
        #             one made for you, if GnuPG is available.
        #             If GnuPG is not available, you should be warned.
        if do_gpg_stuff:
            gnupg = GnuPG(None)
            accepted_keys = []
            if gnupg.is_available():
                keys = gnupg.list_secret_keys()
                for key, details in keys.iteritems():
                    # Ignore revoked/expired keys.
                    if ("revocation-date" in details and
                        details["revocation-date"] <=
                            date.today().strftime("%Y-%m-%d")):
                        continue

                    accepted_keys.append(key)
                    for uid in details["uids"]:
                        if "email" not in uid or uid["email"] == "":
                            continue

                        if uid["email"] in [x["email"]
                                            for x in session.config.profiles]:
                            # Don't set up the same e-mail address twice.
                            continue

                        # FIXME: Add route discovery mechanism.
                        profile = {
                            "email": uid["email"],
                            "name": uid["name"],
                        }
                        session.config.profiles.append(profile)
                    if (session.config.prefs.gpg_recipient in (None, '', '!CREATE')
                           and details["capabilities_map"][0]["encrypt"]):
                        session.config.prefs.gpg_recipient = key
                        session.ui.notify(_('Encrypting config to %s') % key)
                    if session.config.prefs.crypto_policy == 'none':
                        session.config.prefs.crypto_policy = 'openpgp-sign'

                if len(accepted_keys) == 0:
                    # FIXME: Start background process generating a key once a user
                    #        has supplied a name and e-mail address.
                    pass

            else:
                session.ui.warning(_('Oh no, PGP/GPG support is unavailable!'))

        # If we have a GPG key, but no master key, create it
        self.make_master_key()

        # Perform any required migrations
        Migrate(session).run(before_setup=False, after_setup=True)

        session.config.save()
        session.config.prepare_workers(session, daemons=want_daemons)

        return self._success(_('Performed initial Mailpile setup'))