summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordrebs <drebs@leap.se>2015-03-25 15:47:28 -0300
committerdrebs <drebs@leap.se>2015-03-25 17:07:27 -0300
commitb5309dc5910f35f5320c649be2ce2c6147030b39 (patch)
treeaa4f587ece5749e8ec719aacbc16717607caa250
parent5a45acd3486f4e7f830647953731353cda916d51 (diff)
[refactor] separate tcp map server code
Separate the common tcp map server code, used for both alias resolver and recipient access checker, to its own file.
-rw-r--r--src/leap/mx/alias_resolver.py84
-rw-r--r--src/leap/mx/check_recipient_access.py40
-rw-r--r--src/leap/mx/tcp_map.py76
3 files changed, 140 insertions, 60 deletions
diff --git a/src/leap/mx/alias_resolver.py b/src/leap/mx/alias_resolver.py
index 4247b57..9206ffb 100644
--- a/src/leap/mx/alias_resolver.py
+++ b/src/leap/mx/alias_resolver.py
@@ -24,65 +24,49 @@ Test this with postmap -v -q "foo" tcp:localhost:4242
TODO:
o Look into using twisted.protocols.postfix.policies classes for
controlling concurrent connections and throttling resource consumption.
+ o We should probably use twisted.mail.alias somehow.
"""
-try:
- # TODO: we should probably use the system alias somehow
- # from twisted.mail import alias
- from twisted.protocols import postfix
- from twisted.python import log
- from twisted.internet import defer
- from twisted.internet.protocol import ServerFactory
-except ImportError:
- print "This software requires Twisted. Please see the README file"
- print "for instructions on getting required dependencies."
+from twisted.protocols import postfix
-class LEAPPostFixTCPMapserver(postfix.PostfixTCPMapServer):
- def _cbGot(self, value):
- uuid, pubkey = value
- if uuid is None:
- self.sendCode(500, postfix.quote("NOT FOUND SRY"))
- elif pubkey is None:
- self.sendCode(400, postfix.quote("4.7.13 USER ACCOUNT DISABLED"))
- else:
- self.sendCode(200, postfix.quote(value))
-
+from leap.mx.tcp_map import LEAPostfixTCPMapServerFactory
+from leap.mx.tcp_map import TCP_MAP_CODE_SUCCESS
+from leap.mx.tcp_map import TCP_MAP_CODE_TEMPORARY_FAILURE
+from leap.mx.tcp_map import TCP_MAP_CODE_PERMANENT_FAILURE
-class AliasResolverFactory(ServerFactory):
- protocol = LEAPPostFixTCPMapserver
+class LEAPPostfixTCPMapAliasServer(postfix.PostfixTCPMapServer):
+ """
+ A postfix tcp map alias resolver server.
+ """
- def __init__(self, couchdb):
- self._cdb = couchdb
-
- def _to_str(self, result):
- """
- Properly encodes the result string if any.
+ def _cbGot(self, value):
"""
- if isinstance(result, unicode):
- result = result.encode("utf8")
- if result is None:
- log.msg("Result not found")
- return result
+ Return a code and message depending on the result of the factory's
+ get().
- def _getPubKey(self, uuid):
+ :param value: The uuid and public key.
+ :type value: list
+ """
+ uuid, pubkey = value
if uuid is None:
- return defer.succeed([None, None])
- d = defer.gatherResults([
- self._to_str(uuid),
- self._cdb.getPubKey(uuid),
- ])
- return d
+ self.sendCode(
+ TCP_MAP_CODE_PERMANENT_FAILURE,
+ postfix.quote("NOT FOUND SRY"))
+ elif pubkey is None:
+ self.sendCode(
+ TCP_MAP_CODE_TEMPORARY_FAILURE,
+ postfix.quote("4.7.13 USER ACCOUNT DISABLED"))
+ else:
+ self.sendCode(
+ TCP_MAP_CODE_SUCCESS,
+ postfix.quote(uuid))
- def get(self, key):
- """
- Looks up the passed key, but only up to the username id of the key.
- At some point we will have to consider the domain part too.
- """
- log.msg("Query key: %s" % (key,))
- d = self._cdb.queryByAddress(key)
- d.addCallback(self._getPubKey)
- d.addErrback(log.err)
- return d
+class AliasResolverFactory(LEAPostfixTCPMapServerFactory):
+ """
+ A factory for postfix tcp map alias resolver servers.
+ """
+
+ protocol = LEAPPostfixTCPMapAliasServer
diff --git a/src/leap/mx/check_recipient_access.py b/src/leap/mx/check_recipient_access.py
index d4ae339..cf172c7 100644
--- a/src/leap/mx/check_recipient_access.py
+++ b/src/leap/mx/check_recipient_access.py
@@ -24,22 +24,42 @@ Test this with postmap -v -q "foo" tcp:localhost:2244
from twisted.protocols import postfix
-from leap.mx.alias_resolver import AliasResolverFactory
+from leap.mx.tcp_map import LEAPPostfixTCPMapServerFactory
+from leap.mx.tcp_map import TCP_MAP_CODE_SUCCESS
+from leap.mx.tcp_map import TCP_MAP_CODE_TEMPORARY_FAILURE
+from leap.mx.tcp_map import TCP_MAP_CODE_PERMANENT_FAILURE
-class LEAPPostFixTCPMapserverAccess(postfix.PostfixTCPMapServer):
+class LEAPPostFixTCPMapAccessServer(postfix.PostfixTCPMapServer):
+ """
+ A postfix tcp map recipient access checker server.
+ """
+
def _cbGot(self, value):
- # For more info, see:
- # http://www.postfix.org/tcp_table.5.html
- # http://www.postfix.org/access.5.html
+ """
+ Return a code and message depending on the result of the factory's
+ get().
+
+ For more info, see: http://www.postfix.org/access.5.html
+
+ :param value: The uuid and public key.
+ :type value: list
+ """
uuid, pubkey = value
if uuid is None:
- self.sendCode(500, postfix.quote("REJECT"))
+ self.sendCode(
+ TCP_MAP_CODE_PERMANENT_FAILURE,
+ postfix.quote("REJECT"))
elif pubkey is None:
- self.sendCode(400, postfix.quote("4.7.13 USER ACCOUNT DISABLED"))
+ self.sendCode(
+ TCP_MAP_CODE_TEMPORARY_FAILURE,
+ postfix.quote("4.7.13 USER ACCOUNT DISABLED"))
else:
- self.sendCode(200, postfix.quote("OK"))
+ self.sendCode(
+ TCP_MAP_CODE_SUCCESS,
+ postfix.quote("OK"))
+
+class CheckRecipientAccessFactory(LEAPPostfixTCPMapServerFactory):
-class CheckRecipientAccessFactory(AliasResolverFactory):
- protocol = LEAPPostFixTCPMapserverAccess
+ protocol = LEAPPostFixTCPMapAccessServer
diff --git a/src/leap/mx/tcp_map.py b/src/leap/mx/tcp_map.py
new file mode 100644
index 0000000..b7066ff
--- /dev/null
+++ b/src/leap/mx/tcp_map.py
@@ -0,0 +1,76 @@
+#!/usr/bin/env python
+# -*- encoding: utf-8 -*-
+# tcpmap.py
+# Copyright (C) 2015 LEAP
+#
+# This program 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, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+
+
+from twisted.python import log
+from twisted.internet import defer
+from twisted.internet.protocol import ServerFactory
+
+
+# For info on codes, see: http://www.postfix.org/tcp_table.5.html
+TCP_MAP_CODE_SUCCESS = 200
+TCP_MAP_CODE_TEMPORARY_FAILURE = 400
+TCP_MAP_CODE_PERMANENT_FAILURE = 500
+
+
+class LEAPPostfixTCPMapServerFactory(ServerFactory):
+ """
+ A factory for postfix tcp map servers.
+ """
+
+ def __init__(self, couchdb):
+ """
+ Initialize the factory.
+
+ :param couchdb: A CouchDB client.
+ :type couchdb: leap.mx.couchdbhelper.ConnectedCouchDB
+ """
+ self._cdb = couchdb
+
+ def _getPubKey(self, uuid):
+ """
+ Look up PGP public key based on user uid.
+
+ :param uuid: The user uid.
+ :type uuid: str
+
+ :return: A deferred that is fired with the uuid and the public key, if
+ available.
+ :rtype: DeferredList
+ """
+ if uuid is None:
+ return defer.succeed([None, None])
+ return defer.gatherResults([
+ defer.succeed(uuid),
+ self._cdb.getPubKey(uuid),
+ ])
+
+ def get(self, key):
+ """
+ Look up uuid based on key, only up to the username id of the key.
+
+ At some point we will have to consider the domain part too.
+
+ :param key: The lookup key.
+ :type key: str
+ """
+ log.msg("Query key: %s" % (key,))
+ d = self._cdb.queryByAddress(key)
+ d.addCallback(self._getPubKey)
+ d.addErrback(log.err)
+ return d