diff options
author | Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen@kolabsys.com> | 2019-03-18 11:01:59 +0100 |
---|---|---|
committer | Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen@kolabsys.com> | 2019-03-18 11:01:59 +0100 |
commit | 3d3f9fb383026cbc164231365107fdb184c9db24 (patch) | |
tree | f4bebcea676cae51e62bca7132c493fbc6cc2177 | |
parent | a2cd81602266d415a429a5ced942b77dd907d446 (diff) | |
download | pykolab-3d3f9fb383026cbc164231365107fdb184c9db24.tar.gz |
Free lint issues
-rwxr-xr-x | bin/kolab_smtp_access_policy.py | 1119 |
1 files changed, 573 insertions, 546 deletions
diff --git a/bin/kolab_smtp_access_policy.py b/bin/kolab_smtp_access_policy.py index b351846..21169f8 100755 --- a/bin/kolab_smtp_access_policy.py +++ b/bin/kolab_smtp_access_policy.py @@ -20,15 +20,13 @@ import datetime import os +import sqlalchemy import sys import time from optparse import OptionParser from ConfigParser import SafeConfigParser -cache = None - -import sqlalchemy from sqlalchemy import Boolean from sqlalchemy import Column from sqlalchemy import Date @@ -50,8 +48,6 @@ except: from sqlalchemy.schema import Index from sqlalchemy.schema import UniqueConstraint -sys.path = ['..','.'] + sys.path - import pykolab from pykolab import utils @@ -59,6 +55,10 @@ from pykolab.auth import Auth from pykolab.constants import * from pykolab.translate import _ +cache = None + +sys.path = ['..', '.'] + sys.path + # TODO: Figure out how to make our logger do some syslogging as well. log = pykolab.getLogger('pykolab.smtp_access_policy') @@ -85,27 +85,28 @@ except: session = None policy_result_table = Table( - 'policy_result', metadata, - Column('id', Integer, Sequence('seq_id_result'), primary_key=True), - Column('key', String(16), nullable=False), - Column('value', Boolean, nullable=False), - Column('sender', String(254), nullable=True), - Column('recipient', String(254), nullable=False), - Column('sasl_username', String(64)), - Column('sasl_sender', String(64)), - Column('created', Integer, nullable=False), - Column('data', PickleType, nullable=True), - ) + 'policy_result', metadata, + Column('id', Integer, Sequence('seq_id_result'), primary_key=True), + Column('key', String(16), nullable=False), + Column('value', Boolean, nullable=False), + Column('sender', String(254), nullable=True), + Column('recipient', String(254), nullable=False), + Column('sasl_username', String(64)), + Column('sasl_sender', String(64)), + Column('created', Integer, nullable=False), + Column('data', PickleType, nullable=True), +) Index( - 'fsrss', - policy_result_table.c.key, - policy_result_table.c.sender, - policy_result_table.c.recipient, - policy_result_table.c.sasl_username, - policy_result_table.c.sasl_sender, - unique=True - ) + 'fsrss', + policy_result_table.c.key, + policy_result_table.c.sender, + policy_result_table.c.recipient, + policy_result_table.c.sasl_username, + policy_result_table.c.sasl_sender, + unique=True +) + class PolicyResult(object): def __init__( @@ -117,7 +118,7 @@ class PolicyResult(object): sasl_username=None, sasl_sender=None, data=None - ): + ): self.key = key self.value = value @@ -128,24 +129,26 @@ class PolicyResult(object): self.created = (int)(time.time()) self.data = data + mapper(PolicyResult, policy_result_table) statistic_table = Table( - 'statistic', metadata, - Column('id', Integer, Sequence('seq_id_statistic'), primary_key=True), - Column('sender', String(254), nullable=False), - Column('recipient', String(254), nullable=False), - Column('date', Date, nullable=False), - Column('count', Integer, nullable=False), - ) + 'statistic', metadata, + Column('id', Integer, Sequence('seq_id_statistic'), primary_key=True), + Column('sender', String(254), nullable=False), + Column('recipient', String(254), nullable=False), + Column('date', Date, nullable=False), + Column('count', Integer, nullable=False), +) Index( - 'srd', - statistic_table.c.sender, - statistic_table.c.recipient, - statistic_table.c.date, - unique=True - ) + 'srd', + statistic_table.c.sender, + statistic_table.c.recipient, + statistic_table.c.date, + unique=True +) + class Statistic(object): def __init__(self, sender, recipient, date=datetime.date.today(), count=0): @@ -154,10 +157,12 @@ class Statistic(object): self.date = date self.count = count + mapper(Statistic, statistic_table) + class PolicyRequest(object): - email_address_keys = [ 'sender', 'recipient' ] + email_address_keys = ['sender', 'recipient'] recipients = [] auth = None @@ -191,7 +196,9 @@ class PolicyRequest(object): else: if not policy_request['recipient'].strip() == '': - self.recipients = list(set(self.recipients + [policy_request['recipient']])) + self.recipients = list( + set(self.recipients + [policy_request['recipient']]) + ) def add_request(self, policy_request={}): """ @@ -211,18 +218,18 @@ class PolicyRequest(object): pass log.debug( - _("Adding policy request to instance %s") % (self.instance), - level=8 - ) + _("Adding policy request to instance %s") % (self.instance), + level=8 + ) # Normalize email addresses (they may contain recipient delimiters) - if policy_request.has_key('recipient'): - policy_request['recipient'] = normalize_address( - policy_request['recipient'] - ) + if 'recipient' in policy_request: + policy_request['recipient'] = normalize_address(policy_request['recipient']) if not policy_request['recipient'].strip() == '': - self.recipients = list(set(self.recipients + [policy_request['recipient']])) + self.recipients = list( + set(self.recipients + [policy_request['recipient']]) + ) def parse_ldap_dn(self, dn): """ @@ -244,19 +251,16 @@ class PolicyRequest(object): return None if len(ldap_dn) > 0: - search_attrs = conf.get_list( - 'kolab_smtp_access_policy', - 'address_search_attrs' - ) + search_attrs = conf.get_list('kolab_smtp_access_policy', 'address_search_attrs') rule_subject = self.auth.get_user_attributes( - self.sasl_domain, - { 'dn': dn }, - search_attrs + [ 'objectclass' ] - ) + self.sasl_domain, + {'dn': dn}, + search_attrs + ['objectclass'] + ) for search_attr in search_attrs: - if rule_subject.has_key(search_attr): + if search_attr in rule_subject: if isinstance(rule_subject[search_attr], basestring): values.append(rule_subject[search_attr]) else: @@ -274,30 +278,25 @@ class PolicyRequest(object): parsed_uri = utils.parse_ldap_uri(uri) - if parsed_uri == None: + if parsed_uri is None: return None - (_protocol, _server, _port, _base_dn, _attrs, _scope, _filter) = \ - parsed_uri + (_protocol, _server, _port, _base_dn, _attrs, _scope, _filter) = parsed_uri if len(_attrs) == 0: - search_attrs = conf.get_list( - 'kolab_smtp_access_policy', - 'address_search_attrs' - ) + search_attrs = conf.get_list('kolab_smtp_access_policy', 'address_search_attrs') else: - search_attrs = [ _attrs ] - - users = [] + search_attrs = [_attrs] self.auth._auth._bind() + _users = self.auth._auth._search( - _base_dn, - scope=LDAP_SCOPE[_scope], - filterstr=_filter, - attrlist=search_attrs + [ 'objectclass' ], - override_search="_regular_search" - ) + _base_dn, + scope=LDAP_SCOPE[_scope], + filterstr=_filter, + attrlist=search_attrs + ['objectclass'], + override_search="_regular_search" + ) for _user in _users: for search_attr in search_attrs: @@ -322,7 +321,7 @@ class PolicyRequest(object): '$mydomains': expand_mydomains } - rules = { 'allow': [], 'deny': [] } + rules = {'allow': [], 'deny': []} if isinstance(policy, basestring): policy = [policy] @@ -357,7 +356,7 @@ class PolicyRequest(object): # See if the value is an LDAP DN ldap_dn = self.parse_ldap_dn(_rule) - if not ldap_dn == None and len(ldap_dn) > 0: + if ldap_dn is not None and len(ldap_dn) > 0: if _prefix == '-': rules['deny'].extend(ldap_dn) else: @@ -365,7 +364,7 @@ class PolicyRequest(object): else: ldap_uri = self.parse_ldap_uri(_rule) - if not ldap_uri == None and len(ldap_uri) > 0: + if ldap_uri is not None and len(ldap_uri) > 0: if _prefix == '-': rules['deny'].extend(ldap_uri) else: @@ -421,46 +420,42 @@ class PolicyRequest(object): search_attrs = conf.get_list(self.sasl_domain, 'address_search_attrs') - if search_attrs == None or \ + if search_attrs is None or \ (isinstance(search_attrs, list) and len(search_attrs) == 0): search_attrs = conf.get_list(self.sasl_domain, 'mail_attributes') - if search_attrs == None or \ + if search_attrs is None or \ (isinstance(search_attrs, list) and len(search_attrs) == 0): - search_attrs = conf.get_list( - 'kolab_smtp_access_policy', - 'address_search_attrs' - ) + search_attrs = conf.get_list('kolab_smtp_access_policy', 'address_search_attrs') - if search_attrs == None or \ + if search_attrs is None or \ (isinstance(search_attrs, list) and len(search_attrs) == 0): - search_attrs = conf.get_list( - conf.get('kolab', 'auth_mechanism'), - 'mail_attributes' - ) + conf.get('kolab', 'auth_mechanism'), + 'mail_attributes' + ) want_attrs = [] for search_attr in search_attrs: - if not self.sasl_user.has_key(search_attr): + if search_attr not in self.sasl_user: want_attrs.append(search_attr) if len(want_attrs) > 0: self.sasl_user.update( - self.auth.get_user_attributes( - self.sasl_domain, - self.sasl_user, - want_attrs - ) + self.auth.get_user_attributes( + self.sasl_domain, + self.sasl_user, + want_attrs ) + ) # Catch a user using one of its own alias addresses. for search_attr in search_attrs: - if self.sasl_user.has_key(search_attr): + if search_attr in self.sasl_user: if isinstance(self.sasl_user[search_attr], list): if self.sender.lower() in [x.lower() for x in self.sasl_user[search_attr]]: return True @@ -479,7 +474,7 @@ class PolicyRequest(object): interested in. """ - if self.sasl_username == None: + if self.sasl_username is None: if not conf.allow_unauthenticated: reject(_("Unauthorized access not allowed")) else: @@ -491,93 +486,92 @@ class PolicyRequest(object): # If we have an sasl_username, find the user object in the # authentication database, along with the attributes we are # interested in. - if self.sasl_domain == None: + if self.sasl_domain is None: if len(self.sasl_username.split('@')) > 1: self.sasl_domain = self.sasl_username.split('@')[1] else: self.sasl_domain = conf.get('kolab', 'primary_domain') - sasl_username = "%s@%s" % (self.sasl_username, self.sasl_domain) + sasl_username = "%s@%s" % ( + self.sasl_username, self.sasl_domain + ) - if self.auth == None: + if self.auth is None: self.auth = Auth(self.sasl_domain) elif not self.auth.domain == self.sasl_domain: self.auth = Auth(self.sasl_domain) - sasl_users = self.auth.find_recipient( - sasl_username, - domain=self.sasl_domain - ) + sasl_users = self.auth.find_recipient(sasl_username, domain=self.sasl_domain) if isinstance(sasl_users, list): if len(sasl_users) == 0: log.error(_("Could not find recipient")) return False else: - self.sasl_user = { 'dn': sasl_users[0] } + self.sasl_user = {'dn': sasl_users[0]} elif isinstance(sasl_users, basestring): - self.sasl_user = { 'dn': sasl_users } + self.sasl_user = {'dn': sasl_users} if not self.sasl_user['dn']: # Got a final answer here, do the caching thing. cache_update( - function='verify_sender', - sender=self.sender, - recipients=self.recipients, - result=(int)(False), - sasl_username=self.sasl_username, - sasl_sender=self.sasl_sender - ) + function='verify_sender', + sender=self.sender, + recipients=self.recipients, + result=(int)(False), + sasl_username=self.sasl_username, + sasl_sender=self.sasl_sender + ) reject( - _("Could not find envelope sender user %s (511)") % ( - self.sasl_username - ) + _("Could not find envelope sender user %s (511)") % ( + self.sasl_username ) + ) attrs = conf.get_list(self.sasl_domain, 'auth_attributes') - if attrs == None or (isinstance(attrs, list) and len(attrs) == 0): + if attrs is None or (isinstance(attrs, list) and len(attrs) == 0): attrs = conf.get_list( - conf.get('kolab', 'auth_mechanism'), - 'auth_attributes' - ) + conf.get('kolab', 'auth_mechanism'), + 'auth_attributes' + ) mail_attrs = conf.get_list(self.sasl_domain, 'mail_attributes') - if mail_attrs == None or \ + if mail_attrs is None or \ (isinstance(mail_attrs, list) and len(mail_attrs) == 0): mail_attrs = conf.get_list( - conf.get('kolab', 'auth_mechanism'), - 'mail_attributes' - ) + conf.get('kolab', 'auth_mechanism'), + 'mail_attributes' + ) - if not mail_attrs == None: + if mail_attrs is not None: attrs.extend(mail_attrs) attrs.extend( - [ - 'kolabAllowSMTPRecipient', - 'kolabAllowSMTPSender' - ] - ) + [ + 'kolabAllowSMTPRecipient', + 'kolabAllowSMTPSender' + ] + ) attrs = list(set(attrs)) user_attrs = self.auth.get_user_attributes( - self.sasl_domain, - self.sasl_user, - attrs - ) + self.sasl_domain, + self.sasl_user, + attrs + ) user_attrs['dn'] = self.sasl_user['dn'] self.sasl_user = utils.normalize(user_attrs) log.debug( - _("Obtained authenticated user details for %r: %r") % ( - self.sasl_user['dn'], - self.sasl_user.keys() - ), - level=8 - ) + _("Obtained authenticated user details for %r: %r") % ( + self.sasl_user['dn'], + self.sasl_user.keys() + ), + level=8 + ) def verify_delegate(self): """ @@ -586,7 +580,7 @@ class PolicyRequest(object): """ sender_is_delegate = False - if self.sender_domain == None: + if self.sender_domain is None: if len(self.sender.split('@')) > 1: self.sender_domain = self.sender.split('@')[1] else: @@ -596,160 +590,159 @@ class PolicyRequest(object): return True search_attrs = conf.get_list(self.sender_domain, 'mail_attributes') - if search_attrs == None: + if search_attrs is None: search_attrs = conf.get_list( - conf.get('kolab', 'auth_mechanism'), - 'mail_attributes' - ) + conf.get('kolab', 'auth_mechanism'), + 'mail_attributes' + ) sender_users = self.auth.find_recipient( - self.sender, - domain=self.sender_domain - ) + self.sender, + domain=self.sender_domain + ) if isinstance(sender_users, list): if len(sender_users) > 1: # More then one sender user with this recipient address. # TODO: check each of the sender users found. - self.sender_user = { 'dn': sender_users[0] } + self.sender_user = {'dn': sender_users[0]} elif len(sender_users) == 1: - self.sender_user = { 'dn': sender_users } + self.sender_user = {'dn': sender_users} else: - self.sender_user = { 'dn': False } + self.sender_user = {'dn': False} elif isinstance(sender_users, basestring): - self.sender_user = { 'dn': sender_users } + self.sender_user = {'dn': sender_users} if not self.sender_user['dn']: cache_update( - function='verify_sender', - sender=self.sender, - recipients=self.recipients, - result=(int)(False), - sasl_username=self.sasl_username, - sasl_sender=self.sasl_sender - ) + function='verify_sender', + sender=self.sender, + recipients=self.recipients, + result=(int)(False), + sasl_username=self.sasl_username, + sasl_sender=self.sasl_sender + ) reject(_("Could not find envelope sender user %s") % (self.sender)) attrs = search_attrs attrs.extend( - [ - 'kolabAllowSMTPRecipient', - 'kolabAllowSMTPSender', - 'kolabDelegate' - ] - ) + [ + 'kolabAllowSMTPRecipient', + 'kolabAllowSMTPSender', + 'kolabDelegate' + ] + ) user_attrs = self.auth.get_user_attributes( - self.sender_domain, - self.sender_user, - attrs - ) + self.sender_domain, + self.sender_user, + attrs + ) user_attrs['dn'] = self.sender_user['dn'] self.sender_user = utils.normalize(user_attrs) - if not self.sender_user.has_key('kolabdelegate'): + if 'kolabdelegate' not in self.sender_user: # Got a final answer here, do the caching thing. - if not cache == False: - record_id = cache_update( - function='verify_sender', - sender=self.sender, - recipients=self.recipients, - result=(int)(False), - sasl_username=self.sasl_username, - sasl_sender=self.sasl_sender - ) + if cache is not False: + cache_update( + function='verify_sender', + sender=self.sender, + recipients=self.recipients, + result=(int)(False), + sasl_username=self.sasl_username, + sasl_sender=self.sasl_sender + ) reject( - _("%s is unauthorized to send on behalf of %s") % ( - self.sasl_user['dn'], - self.sender_user['dn'] - ) + _("%s is unauthorized to send on behalf of %s") % ( + self.sasl_user['dn'], + self.sender_user['dn'] ) + ) - elif self.sender_user['kolabdelegate'] == None: + elif self.sender_user['kolabdelegate'] is None: # No delegates for this sender could be found. The user is # definitely NOT a delegate of the sender. log.warning( _("User %s attempted to use envelope sender address %s without authorization") % ( - policy_request["sasl_username"], - policy_request["sender"] - ) + policy_request["sasl_username"], + policy_request["sender"] ) + ) # Got a final answer here, do the caching thing. - if not cache == False: - record_id = cache_update( - function='verify_sender', - sender=self.sender, - recipients=self.recipients, - result=(int)(False), - sasl_username=self.sasl_username, - sasl_sender=self.sasl_sender - ) + if cache is not False: + cache_update( + function='verify_sender', + sender=self.sender, + recipients=self.recipients, + result=(int)(False), + sasl_username=self.sasl_username, + sasl_sender=self.sasl_sender + ) reject( - _("%s is unauthorized to send on behalf of %s") % ( - self.sasl_user['dn'], - self.sender_user['dn'] - ) + _("%s is unauthorized to send on behalf of %s") % ( + self.sasl_user['dn'], + self.sender_user['dn'] ) + ) else: # See if we can match the value of the envelope sender delegates to # the actual sender sasl_username - if self.sasl_user == None: + if self.sasl_user is None: sasl_users = self.auth.find_recipient( - self.sasl_username, - domain=self.sasl_domain - ) + self.sasl_username, + domain=self.sasl_domain + ) if isinstance(sasl_users, list): if len(sasl_users) == 0: log.error(_("Could not find recipient")) return False else: - self.sasl_user = { 'dn': sasl_users[0] } + self.sasl_user = {'dn': sasl_users[0]} elif isinstance(sasl_users, basestring): - self.sasl_user = { 'dn': sasl_users } + self.sasl_user = {'dn': sasl_users} # Possible values for the kolabDelegate attribute are: # a 'uid', a 'dn'. - if not self.sasl_user.has_key('uid'): + if 'uid' not in self.sasl_user: self.sasl_user['uid'] = self.auth.get_user_attribute( - self.sasl_domain, - self.sasl_user, - 'uid' - ) - + self.sasl_domain, + self.sasl_user, + 'uid' + ) sender_delegates = self.sender_user['kolabdelegate'] if not type(sender_delegates) == list: - sender_delegates = [ sender_delegates ] + sender_delegates = [sender_delegates] for sender_delegate in sender_delegates: if self.sasl_user['dn'] == sender_delegate: log.debug( - _("Found user %s to be a delegate user of %s") % ( - policy_request["sasl_username"], - policy_request["sender"] - ), - level=8 - ) + _("Found user %s to be a delegate user of %s") % ( + policy_request["sasl_username"], + policy_request["sender"] + ), + level=8 + ) sender_is_delegate = True elif self.sasl_user['uid'] == sender_delegate: log.debug( - _("Found user %s to be a delegate user of %s") % ( - policy_request["sasl_username"], - policy_request["sender"] - ), - level=8 - ) + _("Found user %s to be a delegate user of %s") % ( + policy_request["sasl_username"], + policy_request["sender"] + ), + level=8 + ) sender_is_delegate = True @@ -763,31 +756,42 @@ class PolicyRequest(object): self.recipient = recipient - if not self.sasl_username == '' and not self.sasl_username == None: - log.debug(_("Verifying authenticated sender '%(sender)s' with sasl_username '%(sasl_username)s' for recipient '%(recipient)s'") % (self.__dict__) - ) + if not self.sasl_username == '' and self.sasl_username is not None: + log.debug( + _("Verifying authenticated sender '%(sender)s' with sasl_username '%(sasl_username)s' for recipient '%(recipient)s'") % ( + self.__dict__ + ), + level=8 + ) + else: - log.debug(_("Verifying unauthenticated sender '%(sender)s' for recipient '%(recipient)s'") % (self.__dict__) - ) + log.debug( + _( + "Verifying unauthenticated sender '%(sender)s' for recipient '%(recipient)s'" + ) % ( + self.__dict__ + ), + level=8 + ) recipient_verified = False - if not cache == False: + if cache is not False: records = cache_select( - function='verify_recipient', - sender=self.sender, - recipient=recipient, - sasl_username=self.sasl_username, - sasl_sender=self.sasl_sender, - ) + function='verify_recipient', + sender=self.sender, + recipient=recipient, + sasl_username=self.sasl_username, + sasl_sender=self.sasl_sender, + ) - if not records == None and len(records) == 1: + if records is not None and len(records) == 1: log.info( - _("Reproducing verify_recipient(%s, %s) from cache") % ( - self.sender, - recipient - ) + _("Reproducing verify_recipient(%s, %s) from cache") % ( + self.sender, + recipient ) + ) return records[0].value @@ -797,100 +801,94 @@ class PolicyRequest(object): sasl_domain = recipient.split('@')[1] else: sasl_domain = conf.get('kolab', 'primary_domain') - recipient = "%s@%s" % (recipient,sasl_domain) + recipient = "%s@%s" % (recipient, sasl_domain) if not verify_domain(sasl_domain): - if not cache == False: + if cache is not False: cache_update( - function='verify_recipient', - sender=self.sender, - recipient=recipient, - result=(int)(True), - sasl_username=self.sasl_username, - sasl_sender=self.sasl_sender - ) + function='verify_recipient', + sender=self.sender, + recipient=recipient, + result=(int)(True), + sasl_username=self.sasl_username, + sasl_sender=self.sasl_sender + ) return True - if self.auth == None: + if self.auth is None: self.auth = Auth(sasl_domain) elif not self.auth.domain == sasl_domain: self.auth = Auth(sasl_domain) if verify_domain(sasl_domain): - if not self.auth.domains == None and self.auth.domains.has_key(sasl_domain): + if self.auth.domains is not None and sasl_domain in self.auth.domains: log.debug( - _("Using authentication domain %s instead of %s") % ( - self.auth.domains[sasl_domain], - sasl_domain - ), - level=8 - ) + _("Using authentication domain %s instead of %s") % ( + self.auth.domains[sasl_domain], + sasl_domain + ), + level=8 + ) sasl_domain = self.auth.domains[sasl_domain] else: log.debug( - _("Domain %s is a primary domain") % ( - sasl_domain - ), - level=8 - ) + _("Domain %s is a primary domain") % (sasl_domain), + level=8 + ) else: log.warning( - _("Checking the recipient for domain %s that is not ours. This is probably a configuration error.") % ( - sasl_domain - ) - ) + _("Checking the recipient for domain %s that is not ours.") % (sasl_domain) + ) return True recipients = self.auth.find_recipient( - normalize_address(recipient), - domain=sasl_domain, - ) + normalize_address(recipient), + domain=sasl_domain, + ) if isinstance(recipients, list): if len(recipients) > 1: log.info( - _("This recipient address is related to multiple object entries and the SMTP Access Policy can therefore not restrict message flow") - ) + _("This recipient address is related to multiple object entries and the SMTP Access Policy can therefore not restrict message flow") + ) cache_update( - function='verify_recipient', - sender=self.sender, - recipient=normalize_address(recipient), - result=(int)(True), - sasl_username=self.sasl_username, - sasl_sender=self.sasl_sender - ) + function='verify_recipient', + sender=self.sender, + recipient=normalize_address(recipient), + result=(int)(True), + sasl_username=self.sasl_username, + sasl_sender=self.sasl_sender + ) return True elif len(recipients) == 1: - _recipient = { 'dn': recipients[0] } + _recipient = {'dn': recipients[0]} else: log.debug( - _("Recipient address %r not found. Allowing since the MTA was configured to accept the recipient.") % ( - normalize_address(recipient) - ), - level=3 - ) + _("Recipient address %r not found. Allowing since the MTA was configured to accept the recipient.") % ( + normalize_address(recipient) + ), + level=3 + ) cache_update( - function='verify_recipient', - sender=self.sender, - recipient=normalize_address(recipient), - result=(int)(True), - sasl_username=self.sasl_username, - sasl_sender=self.sasl_sender - ) + function='verify_recipient', + sender=self.sender, + recipient=normalize_address(recipient), + result=(int)(True), + sasl_username=self.sasl_username, + sasl_sender=self.sasl_sender + ) return True elif isinstance(recipients, basestring): - _recipient = { - 'dn': recipients - } + _recipient = {'dn': recipients} # We have gotten an invalid recipient. We need to catch this case, # because testing can input invalid recipients, and so can faulty @@ -898,45 +896,45 @@ class PolicyRequest(object): if not _recipient['dn']: if not conf.allow_unauthenticated: cache_update( - function='verify_recipient', - sender=self.sender, - recipient=normalize_address(recipient), - result=(int)(False), - sasl_username=self.sasl_username, - sasl_sender=self.sasl_sender - ) + function='verify_recipient', + sender=self.sender, + recipient=normalize_address(recipient), + result=(int)(False), + sasl_username=self.sasl_username, + sasl_sender=self.sasl_sender + ) reject(_("Invalid recipient")) else: cache_update( - function='verify_recipient', - sender=self.sender, - recipient=normalize_address(recipient), - result=(int)(True), - sasl_username=self.sasl_username, - sasl_sender=self.sasl_sender - ) + function='verify_recipient', + sender=self.sender, + recipient=normalize_address(recipient), + result=(int)(True), + sasl_username=self.sasl_username, + sasl_sender=self.sasl_sender + ) log.debug(_("Could not find this user, accepting"), level=8) return True - if not _recipient['dn'] == False: + if _recipient['dn'] is not False: recipient_policy = self.auth.get_entry_attribute( - sasl_domain, - _recipient['dn'], - 'kolabAllowSMTPSender' - ) + sasl_domain, + _recipient['dn'], + 'kolabAllowSMTPSender' + ) # If no such attribute has been specified, allow - if recipient_policy == None: + if recipient_policy is None: cache_update( - function='verify_recipient', - sender=self.sender, - recipient=normalize_address(recipient), - result=(int)(True), - sasl_username=self.sasl_username, - sasl_sender=self.sasl_sender - ) + function='verify_recipient', + sender=self.sender, + recipient=normalize_address(recipient), + result=(int)(True), + sasl_username=self.sasl_username, + sasl_sender=self.sasl_sender + ) recipient_verified = True @@ -945,19 +943,19 @@ class PolicyRequest(object): # sender. else: recipient_verified = self.parse_policy( - recipient, - self.sender, - recipient_policy - ) + recipient, + self.sender, + recipient_policy + ) cache_update( - function='verify_recipient', - sender=self.sender, - recipient=normalize_address(recipient), - result=(int)(recipient_verified), - sasl_username=self.sasl_username, - sasl_sender=self.sasl_sender - ) + function='verify_recipient', + sender=self.sender, + recipient=normalize_address(recipient), + result=(int)(recipient_verified), + sasl_username=self.sasl_username, + sasl_sender=self.sasl_sender + ) return recipient_verified @@ -972,16 +970,16 @@ class PolicyRequest(object): recipients_verified = True - if not cache == False: + if cache is not False: records = cache_select( - function='verify_recipient', - sender=self.sender, - recipients=self.recipients, - sasl_username=self.sasl_username, - sasl_sender=self.sasl_sender, - ) + function='verify_recipient', + sender=self.sender, + recipients=self.recipients, + sasl_username=self.sasl_username, + sasl_sender=self.sasl_sender, + ) - if not records == None and len(records) == len(self.recipients): + if records is not None and len(records) == len(self.recipients): log.debug("Euh, what am I doing here?") for record in records: recipient_found = False @@ -990,7 +988,12 @@ class PolicyRequest(object): recipient_found = True if not recipient_found: - reject(_("Sender %s is not allowed to send to recipient %s") % (self.sender,recipient)) + reject( + _("Sender %s is not allowed to send to recipient %s") % ( + self.sender, + recipient + ) + ) for recipient in self.recipients: recipient_verified = self.verify_recipient(recipient) @@ -1019,11 +1022,11 @@ class PolicyRequest(object): sender_verified = False - if self.sender == None: + if self.sender is None: # Trusted host? if not hasattr(self, 'client_address') or \ self.client_address == "" or \ - self.client_address == None: + self.client_address is None: # Nothing to compare to. return False @@ -1032,32 +1035,30 @@ class PolicyRequest(object): import netaddr networks = conf.get_list( - 'kolab_smtp_access_policy', - 'empty_sender_hosts' - ) + 'kolab_smtp_access_policy', + 'empty_sender_hosts' + ) - trusted = False for network in networks: if netaddr.IPNetwork(self.client_address) in netaddr.IPNetwork(network): return True - except ImportError, errmsg: + except ImportError as errmsg: return False - if not cache == False: + if cache is not False: records = cache_select( - sender=self.sender, - recipients=self.recipients, - sasl_username=self.sasl_username, - sasl_sender=self.sasl_sender, - function='verify_sender' - ) + sender=self.sender, + recipients=self.recipients, + sasl_username=self.sasl_username, + sasl_sender=self.sasl_sender, + function='verify_sender' + ) - if not records == None and len(records) == len(self.recipients): - log.info(_("Reproducing verify_sender(%r) from cache") % ( - self.__dict__ - ) - ) + if records is not None and len(records) == len(self.recipients): + log.info( + _("Reproducing verify_sender(%r) from cache") % (self.__dict__) + ) for record in records: recipient_found = False @@ -1067,16 +1068,22 @@ class PolicyRequest(object): if recipient_found: if not record.value: - reject(_("Sender %s is not allowed to send to recipient %s") % (self.sender,recipient)) + reject( + _("Sender %s is not allowed to send to recipient %s") % ( + self.sender, + recipient + ) + ) + if record.data is not None: self.__dict__.update(record.data) return True - if self.verify_authenticity() == False: + if self.verify_authenticity() is False: reject(_("Unverifiable sender.")) - if not self.sasl_user == None: + if self.sasl_user is not None: self.sasl_user_uses_alias = self.verify_alias() if not self.sasl_user_uses_alias: @@ -1085,20 +1092,19 @@ class PolicyRequest(object): # If the authenticated user is using delegate functionality, apply the # recipient policy attribute for the envelope sender. - if self.sasl_user_is_delegate == False and \ - self.sasl_user_uses_alias == False and \ - not conf.allow_unauthenticated: + if self.sasl_user_is_delegate is False: + if self.sasl_user_uses_alias is False: + if not conf.allow_unauthenticated: + reject(_("Sender uses unauthorized envelope sender address")) - reject(_("Sender uses unauthorized envelope sender address")) - - elif self.sasl_user_is_delegate: + if self.sasl_user_is_delegate: # Apply the recipient policy for the sender using the envelope # sender user object. recipient_policy_domain = self.sender_domain recipient_policy_sender = self.sender recipient_policy_user = self.sender_user - elif not self.sasl_user == None: + elif self.sasl_user is not None: # Apply the recipient policy from the authenticated user. recipient_policy_domain = self.sasl_domain recipient_policy_sender = self.sasl_username @@ -1113,84 +1119,88 @@ class PolicyRequest(object): recipient_policy_user = self.sender_user log.debug( - _("Verifying whether sender is allowed to send to recipient using sender policy"), - level=8 - ) + _("Verifying whether sender is allowed to send to recipient using sender policy"), + level=8 + ) - if recipient_policy_user.has_key('kolaballowsmtprecipient'): + if 'kolaballowsmtprecipient' in recipient_policy_user: recipient_policy = recipient_policy_user['kolaballowsmtprecipient'] else: recipient_policy = self.auth.get_user_attribute( - recipient_policy_domain, - recipient_policy_user, - 'kolabAllowSMTPRecipient' - ) + recipient_policy_domain, + recipient_policy_user, + 'kolabAllowSMTPRecipient' + ) log.debug(_("Result is %r") % (recipient_policy), level=8) # If no such attribute has been specified, allow - if recipient_policy == None: + if recipient_policy is None: log.debug( - _("No recipient policy restrictions exist for this sender"), - level=8 - ) + _("No recipient policy restrictions exist for this sender"), + level=8 + ) sender_verified = True # Otherwise,parse the policy obtained. else: log.debug( - _("Found a recipient policy to apply for this sender."), - level=8 - ) + _("Found a recipient policy to apply for this sender."), + level=8 + ) recipient_allowed = None for recipient in self.recipients: recipient_allowed = self.parse_policy( - recipient_policy_sender, - recipient, - recipient_policy - ) + recipient_policy_sender, + recipient, + recipient_policy + ) if not recipient_allowed: reject( - _("Sender %s not allowed to send to recipient %s") % (recipient_policy_user['dn'],recipient) + _("Sender %s not allowed to send to recipient %s") % ( + recipient_policy_user['dn'], + recipient ) + ) sender_verified = True - if not cache == False: + if cache is not False: data = { - 'sasl_user_uses_alias': self.sasl_user_uses_alias, - 'sasl_user_is_delegate': self.sasl_user_is_delegate, - 'sender_domain': self.sender_domain, - } + 'sasl_user_uses_alias': self.sasl_user_uses_alias, + 'sasl_user_is_delegate': self.sasl_user_is_delegate, + 'sender_domain': self.sender_domain, + } - record_id = cache_update( - function='verify_sender', - sender=self.sender, - recipients=self.recipients, - result=(int)(sender_verified), - sasl_username=self.sasl_username, - sasl_sender=self.sasl_sender, - data=data - ) + cache_update( + function='verify_sender', + sender=self.sender, + recipients=self.recipients, + result=(int)(sender_verified), + sasl_username=self.sasl_username, + sasl_sender=self.sasl_sender, + data=data + ) return sender_verified + def cache_cleanup(): - if not cache == True: + if cache is not True: return log.debug(_("Cleaning up the cache"), level=8) - session.query( - PolicyResult - ).filter( - PolicyResult.created < ((int)(time.time()) - cache_expire) - ).delete() + session.query(PolicyResult).filter( + PolicyResult.created < ((int)(time.time()) - cache_expire) + ).delete() + session.commit() + def cache_init(): global cache, cache_expire, session @@ -1200,17 +1210,15 @@ def cache_init(): cache = True if conf.has_option('kolab_smtp_access_policy', 'retention'): cache_expire = (int)( - conf.get( - 'kolab_smtp_access_policy', - 'retention' - ) + conf.get( + 'kolab_smtp_access_policy', + 'retention' ) - elif conf.has_option('kolab_smtp_access_policy', 'uri'): - log.warning(_("The 'uri' setting in the kolab_smtp_access_policy section is soon going to be deprecated in favor of 'cache_uri'")) - cache_uri = conf.get('kolab_smtp_access_policy', 'uri') - cache = True + ) + else: return False + else: return False @@ -1227,7 +1235,7 @@ def cache_init(): try: metadata.create_all(engine) - except sqlalchemy.exc.OperationalError, e: + except sqlalchemy.exc.OperationalError as e: log.error(_("Operational Error in caching: %s" % (e))) return False @@ -1237,34 +1245,34 @@ def cache_init(): return cache + def cache_select( function, sender, recipient='', recipients=[], sasl_username='', - sasl_sender='' - ): + sasl_sender=''): - if not cache == True: + if cache is not True: return None if not recipient == '' and recipients == []: recipients = [recipient] return session.query( - PolicyResult - ).filter_by( - key=function, - sender=sender, - sasl_username=sasl_username, - sasl_sender=sasl_sender - ).filter( - PolicyResult.recipient.in_(recipients) - ).filter( - PolicyResult.created >= \ - ((int)(time.time()) - cache_expire) - ).all() + PolicyResult + ).filter_by( + key=function, + sender=sender, + sasl_username=sasl_username, + sasl_sender=sasl_sender + ).filter( + PolicyResult.recipient.in_(recipients) + ).filter( + PolicyResult.created >= ((int)(time.time()) - cache_expire) + ).all() + def cache_insert( function, @@ -1274,37 +1282,37 @@ def cache_insert( result=None, sasl_username='', sasl_sender='', - data=None - ): + data=None): - if not cache == True: + if cache is notTrue: return [] log.debug( - _("Caching the policy result with timestamp %d") % ( - (int)(time.time()) - ), - level=8 - ) + _("Caching the policy result with timestamp %d") % ( + (int)(time.time()) + ), + level=8 + ) if not recipient == '' and recipients == []: recipients = [recipient] for recipient in recipients: session.add( - PolicyResult( - key=function, - value=result, - sender=sender, - recipient=recipient, - sasl_username=sasl_username, - sasl_sender=sasl_sender, - data=data - ) + PolicyResult( + key=function, + value=result, + sender=sender, + recipient=recipient, + sasl_username=sasl_username, + sasl_sender=sasl_sender, + data=data ) + ) session.commit() + def cache_update( function, sender, @@ -1313,26 +1321,25 @@ def cache_update( result=None, sasl_username='', sasl_sender='', - data=None - ): + data=None): """ Insert an updated set of rows into the cache depending on the necessity """ - if not cache == True: + if cache is not True: return records = [] _records = cache_select( - function, - sender, - recipient, - recipients, - sasl_username, - sasl_sender - ) + function, + sender, + recipient, + recipients, + sasl_username, + sasl_sender + ) for record in _records: if record.value == (int)(result): @@ -1348,48 +1355,52 @@ def cache_update( recipient_found = True if not recipient_found: cache_insert( - function=function, - sender=sender, - recipient=recipient, - result=result, - sasl_username=sasl_username, - sasl_sender=sasl_sender, - data=data - ) + function=function, + sender=sender, + recipient=recipient, + result=result, + sasl_username=sasl_username, + sasl_sender=sasl_sender, + data=data + ) + def defer_if_permit(message, policy_request=None): log.info(_("Returning action DEFER_IF_PERMIT: %s") % (message)) - print "action=DEFER_IF_PERMIT %s\n\n" % (message) + print("action=DEFER_IF_PERMIT %s\n\n" % (message)) sys.exit(0) + def dunno(message, policy_request=None): log.info(_("Returning action DUNNO: %s") % (message)) - print "action=DUNNO %s\n\n" % (message) + print("action=DUNNO %s\n\n" % (message)) sys.exit(0) + def hold(message, policy_request=None): log.info(_("Returning action HOLD: %s") % (message)) - print "action=HOLD %s\n\n" % (message) + print("action=HOLD %s\n\n" % (message)) sys.exit(0) + def permit(message, policy_request=None): log.info(_("Returning action PERMIT: %s") % (message)) # If we have no policy request, we have been called for a reason, # and everything relevant has been figured out already. - if policy_request == None: - print "action=PERMIT\n\n" + if policy_request is None: + print("action=PERMIT\n\n") sys.exit(0) # If the user is not authenticated, there's no reason to do # extra checks here -- to have been performed already. if not hasattr(policy_request, 'sasl_username'): - print "action=PERMIT\n\n" + print("action=PERMIT\n\n") sys.exit(0) # Same here. - if policy_request.sasl_username == None: - print "action=PERMIT\n\n" + if policy_request.sasl_username is None: + print("action=PERMIT\n\n") sys.exit(0) delegate_sender_header = None @@ -1403,15 +1414,15 @@ def permit(message, policy_request=None): # if policy_request.sasl_user_is_delegate: # Domain-specific setting? - if not policy_request.sender_domain == None: + if policy_request.sender_domain is not None: delegate_sender_header = conf.get(policy_request.sender_domain, 'delegate_sender_header') # Global setting? - if delegate_sender_header == None: + if delegate_sender_header is None: delegate_sender_header = conf.get('kolab_smtp_access_policy', 'delegate_sender_header') # Default - if delegate_sender_header == None: + if delegate_sender_header is None: delegate_sender_header = True # If the sender is using an alias as the envelope sender address, take @@ -1419,15 +1430,15 @@ def permit(message, policy_request=None): # and/or X-Sender headers. elif policy_request.sasl_user_uses_alias: # Domain-specific setting? - if not policy_request.sender_domain == None: + if policy_request.sender_domain is not None: alias_sender_header = conf.get(policy_request.sender_domain, 'alias_sender_header') # Global setting? - if alias_sender_header == None: + if alias_sender_header is None: alias_sender_header = conf.get('kolab_smtp_access_policy', 'alias_sender_header') # Default - if alias_sender_header == None: + if alias_sender_header is None: alias_sender_header = True # Make the values booleans @@ -1453,22 +1464,22 @@ def permit(message, policy_request=None): sender_header = conf.get(policy_request.sender_domain, 'sender_header') # Global setting? - if sender_header == None: + if sender_header is None: sender_header = conf.get('kolab_smtp_access_policy', 'sender_header') # Default - if sender_header == None: + if sender_header is None: sender_header = True # Domain specific? xsender_header = conf.get(policy_request.sender_domain, 'xsender_header') # Global setting? - if xsender_header == None: + if xsender_header is None: xsender_header = conf.get('kolab_smtp_access_policy', 'xsender_header') # Default - if xsender_header == None: + if xsender_header is None: xsender_header = True # Note that if the user is not a delegatee, and not using an alias, the sender @@ -1482,7 +1493,7 @@ def permit(message, policy_request=None): if sender_header or xsender_header: # Do the encoding, if any - if not enc_key == None: + if enc_key is not None: header = 'X-Authenticated-As' xheader = None sender = utils.encode(enc_key, policy_request.sasl_username) @@ -1492,27 +1503,29 @@ def permit(message, policy_request=None): sender = policy_request.sasl_username if sender_header: - print "action=PREPEND %s: %s" % (header, sender) + print("action=PREPEND %s: %s" % (header, sender)) - if xsender_header and not xheader == None: - print "action=PREPEND %s: %s" % (xheader, sender) + if xsender_header and xheader is not None: + print("action=PREPEND %s: %s" % (xheader, sender)) - print "action=PERMIT\n\n" + print("action=PERMIT\n\n") sys.exit(0) + def reject(message, policy_request=None): log.info(_("Returning action REJECT: %s") % (message)) - print "action=REJECT %s\n\n" % (message) + print("action=REJECT %s\n\n" % (message)) sys.exit(0) + def expand_mydomains(): """ Return a list of my domains. """ - global auth,mydomains + global auth, mydomains - if not mydomains == None: + if mydomains is not None: return mydomains auth.connect() @@ -1521,6 +1534,7 @@ def expand_mydomains(): return mydomains.keys() + def normalize_address(email_address): """ Parse an address; Strip off anything after a recipient delimiter. @@ -1531,14 +1545,16 @@ def normalize_address(email_address): # Take the first part split by recipient delimiter and the last part # split by '@'. return "%s@%s" % ( - email_address.split("+")[0].lower(), - # TODO: Under some conditions, the recipient may not be fully - # qualified. We'll cross that bridge when we get there, though. - email_address.split('@')[1].lower() - ) + email_address.split("+")[0].lower(), + # TODO: Under some conditions, the recipient may not be fully + # qualified. We'll cross that bridge when we get there, though. + email_address.split('@')[1].lower() + ) + else: return email_address.lower() + def read_request_input(): """ Read a single policy request from sys.stdin, and return a dictionary @@ -1553,13 +1569,13 @@ def read_request_input(): end_of_request = False while not end_of_request: - if (time.time()-start_time) >= conf.timeout: + if (time.time() - start_time) >= conf.timeout: log.warning(_("Timeout for policy request reading exceeded")) sys.exit(0) request_line = sys.stdin.readline() if request_line.strip() == '': - if policy_request.has_key('request'): + if 'request' in policy_request: log.debug(_("End of current request"), level=8) end_of_request = True else: @@ -1572,14 +1588,15 @@ def read_request_input(): return policy_request + def verify_domain(domain): """ Verify whether the domain is internal (mine) or external. """ - global auth,mydomains + global auth, mydomains - if not mydomains == None: + if mydomains is not None: return domain in mydomains.keys() auth.connect() @@ -1588,48 +1605,58 @@ def verify_domain(domain): mydomains = auth.list_domains() - if not mydomains == None and mydomains.has_key(domain): + if mydomains is not None and domain in mydomains: domain_verified = True else: domain_verified = False return domain_verified + if __name__ == "__main__": access_policy_group = conf.add_cli_parser_option_group( - _("Access Policy Options") - ) + _("Access Policy Options") + ) + + access_policy_group.add_option( + "--drop-tables", + dest="drop_tables", + action="store_true", + default=False, + help=_("Drop the caching tables from the database and exit.") + ) + + access_policy_group.add_option( + "--timeout", + dest="timeout", + action="store", + default=10, + help=_("SMTP Policy request timeout.") + ) - access_policy_group.add_option( "--drop-tables", - dest = "drop_tables", - action = "store_true", - default = False, - help = _("Drop the caching tables from the " + \ - "database and exit.")) - - access_policy_group.add_option( "--timeout", - dest = "timeout", - action = "store", - default = 10, - help = _("SMTP Policy request timeout.")) - - access_policy_group.add_option( "--verify-recipient", - dest = "verify_recipient", - action = "store_true", - default = False, - help = _("Verify the recipient access policy.")) - - access_policy_group.add_option( "--verify-sender", - dest = "verify_sender", - action = "store_true", - default = False, - help = _("Verify the sender access policy.")) - - access_policy_group.add_option( "--allow-unauthenticated", - dest = "allow_unauthenticated", - action = "store_true", - default = False, - help = _("Allow unauthenticated senders.")) + access_policy_group.add_option( + "--verify-recipient", + dest="verify_recipient", + action="store_true", + default=False, + help=_("Verify the recipient access policy.") + ) + + access_policy_group.add_option( + "--verify-sender", + dest="verify_sender", + action="store_true", + default=False, + help=_("Verify the sender access policy.") + ) + + access_policy_group.add_option( + "--allow-unauthenticated", + dest="allow_unauthenticated", + action="store_true", + default=False, + help=_("Allow unauthenticated senders.") + ) conf.finalize_conf() @@ -1647,7 +1674,8 @@ if __name__ == "__main__": policy_request = read_request_input() instance = policy_request['instance'] log.debug(_("Got request instance %s") % (instance)) - if policy_requests.has_key(instance): + + if instance in policy_requests: policy_requests[instance].add_request(policy_request) else: policy_requests[instance] = PolicyRequest(policy_request) @@ -1655,14 +1683,14 @@ if __name__ == "__main__": protocol_state = policy_request['protocol_state'].strip().lower() log.debug( - _("Request instance %s is in state %s") % ( - instance, - protocol_state - ) + _("Request instance %s is in state %s") % ( + instance, + protocol_state ) + ) if not protocol_state == 'data': - print "action=DUNNO\n\n" + print("action=DUNNO\n\n") sys.stdout.flush() # We can recognize being in the DATA part by the recipient_count being @@ -1679,13 +1707,12 @@ if __name__ == "__main__": sender_allowed = True if conf.verify_recipient: - recipient_allowed = \ - policy_requests[instance].verify_recipients() + recipient_allowed = policy_requests[instance].verify_recipients() else: recipient_allowed = True - except Exception, errmsg: + except Exception as errmsg: import traceback log.error(_("Unhandled exception caught: %r") % (errmsg)) log.error(traceback.format_exc()) |