pgp_keylist.py 3.85 KB
Newer Older
Philipp Hörist's avatar
Philipp Hörist committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
# Copyright (C) 2018 Philipp Hörist <philipp AT hoerist.com>
#
# This file is part of Gajim.
#
# Gajim is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published
# by the Free Software Foundation; version 3 only.
#
# Gajim is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Gajim. If not, see <http://www.gnu.org/licenses/>.

# XEP-0373: OpenPGP for XMPP

import logging
import time

import nbxmpp

from gajim.common import app
from gajim.common.exceptions import StanzaMalformed
from gajim.common.modules.pep import AbstractPEPModule, AbstractPEPData
from gajim.common.modules.date_and_time import parse_datetime

from openpgp.modules import util
from openpgp.modules.util import Key

log = logging.getLogger('gajim.plugin_system.openpgp.pep')

# Module name
name = 'PGPKeylist'
zeroconf = False


class PGPKeylistData(AbstractPEPData):

    type_ = 'openpgp-keylist'

    def __init__(self, keylist):
        self._pep_specific_data = keylist
        self.data = keylist


class PGPKeylist(AbstractPEPModule):
    '''
    <item>
        <public-keys-list xmlns='urn:xmpp:openpgp:0'>
          <pubkey-metadata
            v4-fingerprint='1357B01865B2503C18453D208CAC2A9678548E35'
            date='2018-03-01T15:26:12Z'
            />
          <pubkey-metadata
            v4-fingerprint='67819B343B2AB70DED9320872C6464AF2A8E4C02'
            date='1953-05-16T12:00:00Z'
            />
        </public-keys-list>
      </item>
    '''

    name = 'openpgp-keylist'
    namespace = util.NS_OPENPGP_PUBLIC_KEYS
    pep_class = PGPKeylistData
    store_publish = True
    _log = log

    def __init__(self, con):
        AbstractPEPModule.__init__(self, con, con.name)

        self.handlers = []

    def _extract_info(self, item):
        keylist_tag = item.getTag('public-keys-list',
                                  namespace=util.NS_OPENPGP)
        if keylist_tag is None:
            raise StanzaMalformed('No public-keys-list node')

        metadata = keylist_tag.getTags('pubkey-metadata')
        if not metadata:
            raise StanzaMalformed('No metadata found')

        keylist = []
        for data in metadata:
            attrs = data.getAttrs()

            if not attrs or 'v4-fingerprint' not in attrs:
                raise StanzaMalformed('No fingerprint in metadata')

            date = attrs.get('date', None)
            if date is None:
                raise StanzaMalformed('No date in metadata')
            else:
                timestamp = parse_datetime(date, epoch=True)
                if timestamp is None:
                    raise StanzaMalformed('Invalid date timestamp: %s', date)

Philipp Hörist's avatar
Philipp Hörist committed
100
            keylist.append(Key(attrs['v4-fingerprint'], int(timestamp)))
Philipp Hörist's avatar
Philipp Hörist committed
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
        return keylist

    def _notification_received(self, jid, keylist):
        con = app.connections[self._account]
        con.get_module('OpenPGP').key_list_received(keylist.data,
                                                    jid.getStripped())

    def _build_node(self, keylist):
        keylist_node = nbxmpp.Node('public-keys-list',
                                   {'xmlns': util.NS_OPENPGP})
        if keylist is None:
            return keylist_node
        for key in keylist:
            attrs = {'v4-fingerprint': key.fingerprint}
            if key.date is not None:
                date = time.strftime(
                    '%Y-%m-%dT%H:%M:%SZ', time.gmtime(key.date))
                attrs['date'] = date
            keylist_node.addChild('pubkey-metadata', attrs=attrs)
        return keylist_node


def get_instance(*args, **kwargs):
    return PGPKeylist(*args, **kwargs), 'PGPKeylist'