diff options
-rw-r--r-- | src/leap/mx/alias_resolver.py | 18 | ||||
-rw-r--r-- | src/leap/mx/check_recipient_access.py | 35 | ||||
-rw-r--r-- | src/leap/mx/couchdbhelper.py | 73 | ||||
-rw-r--r-- | src/leap/mx/mail_receiver.py | 2 | ||||
-rw-r--r-- | src/leap/mx/tcp_map.py | 30 |
5 files changed, 81 insertions, 77 deletions
diff --git a/src/leap/mx/alias_resolver.py b/src/leap/mx/alias_resolver.py index dd631c8..752eac4 100644 --- a/src/leap/mx/alias_resolver.py +++ b/src/leap/mx/alias_resolver.py @@ -40,22 +40,26 @@ class LEAPPostfixTCPMapAliasServer(postfix.PostfixTCPMapServer): A postfix tcp map alias resolver server. """ - def _cbGot(self, address): + def _cbGot(self, user_data): """ Return a code and message depending on the result of the factory's get(). - :param address: The address returned by the factory. - :type address: str + :param user_data: The user's uuid and pgp public key. + :type user_data: list """ - if address is None: + uuid, _ = user_data + if uuid is None: self.sendCode( TCP_MAP_CODE_PERMANENT_FAILURE, postfix.quote("NOT FOUND SRY")) else: + # properly encode uuid, otherwise twisted complains when replying + if isinstance(uuid, unicode): + uuid = uuid.encode("utf8") self.sendCode( TCP_MAP_CODE_SUCCESS, - postfix.quote(address)) + postfix.quote(uuid)) class AliasResolverFactory(LEAPPostfixTCPMapServerFactory): @@ -64,3 +68,7 @@ class AliasResolverFactory(LEAPPostfixTCPMapServerFactory): """ protocol = LEAPPostfixTCPMapAliasServer + + @property + def _query_message(self): + return "Resolving alias for" diff --git a/src/leap/mx/check_recipient_access.py b/src/leap/mx/check_recipient_access.py index 3b61fe8..9f79dfe 100644 --- a/src/leap/mx/check_recipient_access.py +++ b/src/leap/mx/check_recipient_access.py @@ -23,7 +23,6 @@ Test this with postmap -v -q "foo" tcp:localhost:2244 """ from twisted.protocols import postfix -from twisted.internet import defer from leap.mx.tcp_map import LEAPPostfixTCPMapServerFactory from leap.mx.tcp_map import TCP_MAP_CODE_SUCCESS @@ -50,8 +49,8 @@ class LEAPPostFixTCPMapAccessServer(postfix.PostfixTCPMapServer): :param value: The uuid and public key. :type value: list """ - address, pubkey = value - if address is None: + uuid, pubkey = value + if uuid is None: self.sendCode( TCP_MAP_CODE_PERMANENT_FAILURE, postfix.quote("REJECT")) @@ -75,31 +74,7 @@ class CheckRecipientAccessFactory(LEAPPostfixTCPMapServerFactory): protocol = LEAPPostFixTCPMapAccessServer - def _getPubKey(self, address): - """ - Look up PGP public key based on email address. - - :param address: The email address. - :type address: str - - :return: A deferred that is fired with the address and the public key, if - each of them exists. - :rtype: DeferredList - """ - if not address: - return defer.succeed([None, None]) - return defer.gatherResults([ - defer.succeed(address), - self._cdb.getPubKey(address), - ]) - - def get(self, key): - """ - Look up uuid and PGP public key based on key. + @property + def _query_message(self): + return "Checking recipient access for" - :param key: The lookup key. - :type key: str - """ - d = LEAPPostfixTCPMapServerFactory.get(self, key) - d.addCallback(self._getPubKey) - return d diff --git a/src/leap/mx/couchdbhelper.py b/src/leap/mx/couchdbhelper.py index 7bcb5aa..1752b4e 100644 --- a/src/leap/mx/couchdbhelper.py +++ b/src/leap/mx/couchdbhelper.py @@ -71,56 +71,63 @@ class ConnectedCouchDB(client.CouchDB): """ pass - def queryByAddress(self, address): + def getUuidAndPubkey(self, address): """ - Check to see if a particular email or alias exists. + Query couch and return a deferred that will fire with the uuid and pgp + public key for address. :param address: A string representing the email or alias to check. :type address: str - :return: a deferred for this query + :return: A deferred that will fire with the user's uuid and pgp public + key. :rtype twisted.defer.Deferred """ # TODO: Cache results d = self.openView(docId="Identity", viewId="by_address/", key=address, - reduce=True, - include_docs=False) - - def _callback(result): - if len(result["rows"]): - return address - return None - - d.addCallbacks(_callback, log.err) - + reduce=False, + include_docs=True) + + def _get_uuid_and_pubkey_cbk(result): + uuid = None + pubkey = None + if result["rows"]: + doc = result["rows"][0]["doc"] + uuid = doc["user_id"] + if "keys" in doc: + pubkey = doc["keys"]["pgp"] + return uuid, pubkey + + d.addCallback(_get_uuid_and_pubkey_cbk) return d - def getPubKey(self, address): + def getPubkey(self, uuid): """ - Returns a deferred that will fire with the pubkey for the address. + Query couch and return a deferred that will fire with the pgp public + key for user with given uuid. - :param address: email address to query - :type address: str + :param uuid: The uuid of a user + :type uuid: str + :return: A deferred that will fire with the pgp public key for + the user. :rtype: Deferred """ d = self.openView(docId="Identity", - viewId="pgp_key_by_email/", - key=address, + viewId="by_user_id/", + key=uuid, reduce=False, - include_docs=False) - - def _callback(result): - if not result["rows"]: - log.msg("No PGP public key found for %s." % address) - return None - if len(result["rows"]) > 1: - log.msg("More than one PGP public key found for %s, " - "will pick the first one found." % address) - row = result["rows"].pop(0) - return row["value"] - - d.addCallbacks(_callback, log.err) - + include_docs=True) + + def _get_pubkey_cbk(result): + pubkey = None + try: + doc = result["rows"][0]["doc"] + pubkey = doc["keys"]["pgp"] + except (KeyError, IndexError): + pass + return pubkey + + d.addCallbacks(_get_pubkey_cbk, log.err) return d diff --git a/src/leap/mx/mail_receiver.py b/src/leap/mx/mail_receiver.py index 77909b0..f0b9c03 100644 --- a/src/leap/mx/mail_receiver.py +++ b/src/leap/mx/mail_receiver.py @@ -491,7 +491,7 @@ class MailReceiver(Service): log.msg("BUG: There was no uuid!") defer.returnValue(None) - pubkey = yield self._users_cdb.getPubKey(uuid) + pubkey = yield self._users_cdb.getPubkey(uuid) if pubkey is None or len(pubkey) == 0: log.msg("No public key, stopping the processing chain") bounce_reason = "Missing PubKey: There was a problem " \ diff --git a/src/leap/mx/tcp_map.py b/src/leap/mx/tcp_map.py index d8cd835..108c2aa 100644 --- a/src/leap/mx/tcp_map.py +++ b/src/leap/mx/tcp_map.py @@ -17,8 +17,11 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. -from twisted.python import log +from abc import ABCMeta +from abc import abstractproperty + from twisted.internet.protocol import ServerFactory +from twisted.python import log # For info on codes, see: http://www.postfix.org/tcp_table.5.html @@ -27,11 +30,14 @@ TCP_MAP_CODE_TEMPORARY_FAILURE = 400 TCP_MAP_CODE_PERMANENT_FAILURE = 500 -class LEAPPostfixTCPMapServerFactory(ServerFactory): +class LEAPPostfixTCPMapServerFactory(ServerFactory, object): """ A factory for postfix tcp map servers. """ + __metaclass__ = ABCMeta + + def __init__(self, couchdb): """ Initialize the factory. @@ -41,14 +47,22 @@ class LEAPPostfixTCPMapServerFactory(ServerFactory): """ self._cdb = couchdb - def get(self, key): + @abstractproperty + def _query_message(self): + pass + + def get(self, lookup_key): """ - Look up if address exists. + Look up user based on lookup_key. + + :param lookup_key: The lookup key. + :type lookup_key: str - :param key: The lookup key. - :type key: str + :return: A deferred that will be fired with the user's address, uuid + and pgp key. + :rtype: Deferred """ - log.msg("Query key: %s" % (key,)) - d = self._cdb.queryByAddress(key) + log.msg("%s %s" % (self._query_message, lookup_key,)) + d = self._cdb.getUuidAndPubkey(lookup_key) d.addErrback(log.err) return d |