Changeset View
Standalone View
bin/kolab_smtp_access_policy.py
Show All 22 Lines | |||||
import sys | import sys | ||||
import time | import time | ||||
from optparse import OptionParser | from optparse import OptionParser | ||||
from ConfigParser import SafeConfigParser | from ConfigParser import SafeConfigParser | ||||
cache = None | cache = None | ||||
import sqlalchemy | import sqlalchemy | ||||
Lint: PEP8 E402: module level import not at top of file | |||||
from sqlalchemy import Boolean | from sqlalchemy import Boolean | ||||
Lint: PEP8 E402 module level import not at top of file Lint: PEP8 E402: module level import not at top of file | |||||
from sqlalchemy import Column | from sqlalchemy import Column | ||||
Lint: PEP8 E402 module level import not at top of file Lint: PEP8 E402: module level import not at top of file | |||||
from sqlalchemy import Date | from sqlalchemy import Date | ||||
Lint: PEP8 E402 module level import not at top of file Lint: PEP8 E402: module level import not at top of file | |||||
from sqlalchemy import DateTime | from sqlalchemy import DateTime | ||||
Lint: PEP8 E402 module level import not at top of file Lint: PEP8 E402: module level import not at top of file | |||||
from sqlalchemy import Integer | from sqlalchemy import Integer | ||||
Lint: PEP8 E402 module level import not at top of file Lint: PEP8 E402: module level import not at top of file | |||||
from sqlalchemy import MetaData | from sqlalchemy import MetaData | ||||
Lint: PEP8 E402 module level import not at top of file Lint: PEP8 E402: module level import not at top of file | |||||
from sqlalchemy import String | from sqlalchemy import String | ||||
Lint: PEP8 E402 module level import not at top of file Lint: PEP8 E402: module level import not at top of file | |||||
from sqlalchemy import Table | from sqlalchemy import Table | ||||
Lint: PEP8 E402 module level import not at top of file Lint: PEP8 E402: module level import not at top of file | |||||
from sqlalchemy import Sequence | from sqlalchemy import Sequence | ||||
Lint: PEP8 E402 module level import not at top of file Lint: PEP8 E402: module level import not at top of file | |||||
from sqlalchemy import create_engine | from sqlalchemy import create_engine | ||||
Lint: PEP8 E402 module level import not at top of file Lint: PEP8 E402: module level import not at top of file | |||||
from sqlalchemy.orm import mapper | from sqlalchemy.orm import mapper | ||||
Lint: PEP8 E402 module level import not at top of file Lint: PEP8 E402: module level import not at top of file | |||||
try: | try: | ||||
from sqlalchemy.orm import sessionmaker | from sqlalchemy.orm import sessionmaker | ||||
except: | except: | ||||
from sqlalchemy.orm import create_session | from sqlalchemy.orm import create_session | ||||
from sqlalchemy.schema import Index | from sqlalchemy.schema import Index | ||||
Lint: PEP8 E402 module level import not at top of file Lint: PEP8 E402: module level import not at top of file | |||||
from sqlalchemy.schema import UniqueConstraint | from sqlalchemy.schema import UniqueConstraint | ||||
Lint: PEP8 E402 module level import not at top of file Lint: PEP8 E402: module level import not at top of file | |||||
sys.path = ['..','.'] + sys.path | sys.path = ['..','.'] + sys.path | ||||
Lint: PEP8 E231 missing whitespace after ',' Lint: PEP8 E231: missing whitespace after ',' | |||||
import pykolab | import pykolab | ||||
Lint: PEP8 E402 module level import not at top of file Lint: PEP8 E402: module level import not at top of file | |||||
from pykolab import utils | from pykolab import utils | ||||
Lint: PEP8 E402 module level import not at top of file Lint: PEP8 E402: module level import not at top of file | |||||
from pykolab.auth import Auth | from pykolab.auth import Auth | ||||
Lint: PEP8 E402 module level import not at top of file Lint: PEP8 E402: module level import not at top of file | |||||
from pykolab.constants import * | from pykolab.constants import * | ||||
Lint: PEP8 E402 module level import not at top of file Lint: PEP8 E402: module level import not at top of file | |||||
from pykolab.translate import _ | from pykolab.translate import _ | ||||
Lint: PEP8 E402 module level import not at top of file Lint: PEP8 E402: module level import not at top of file | |||||
# TODO: Figure out how to make our logger do some syslogging as well. | # TODO: Figure out how to make our logger do some syslogging as well. | ||||
log = pykolab.getLogger('pykolab.smtp_access_policy') | log = pykolab.getLogger('pykolab.smtp_access_policy') | ||||
# TODO: Removing the stdout handler would mean one can no longer test by | # TODO: Removing the stdout handler would mean one can no longer test by | ||||
# means of manual execution in debug mode. | # means of manual execution in debug mode. | ||||
#log.remove_stdout_handler() | #log.remove_stdout_handler() | ||||
Lint: PEP8 E265 block comment should start with '# ' Lint: PEP8 E265: block comment should start with '# ' | |||||
conf = pykolab.getConf() | conf = pykolab.getConf() | ||||
auth = None | auth = None | ||||
mydomains = None | mydomains = None | ||||
# | # | ||||
# Caching routines using SQLAlchemy. | # Caching routines using SQLAlchemy. | ||||
# | # | ||||
# If creating the cache fails, we continue without any caching, significantly | # If creating the cache fails, we continue without any caching, significantly | ||||
# increasing the load on LDAP. | # increasing the load on LDAP. | ||||
# | # | ||||
cache_expire = 86400 | cache_expire = 86400 | ||||
try: | try: | ||||
metadata = MetaData() | metadata = MetaData() | ||||
except: | except: | ||||
cache = False | cache = False | ||||
session = None | session = None | ||||
policy_result_table = Table( | policy_result_table = Table( | ||||
'policy_result', metadata, | 'policy_result', metadata, | ||||
Column('id', Integer, Sequence('seq_id_result'), primary_key=True), | Column('id', Integer, Sequence('seq_id_result'), primary_key=True), | ||||
Column('key', String(16), nullable=False), | Column('key', String(16), nullable=False), | ||||
Column('value', Boolean, nullable=False), | Column('value', Boolean, nullable=False), | ||||
Column('sender', String(64), nullable=False), | Column('sender', String(64), nullable=True), | ||||
Column('recipient', String(64), nullable=False), | Column('recipient', String(64), nullable=False), | ||||
Column('sasl_username', String(64)), | Column('sasl_username', String(64)), | ||||
Column('sasl_sender', String(64)), | Column('sasl_sender', String(64)), | ||||
Column('created', Integer, nullable=False), | Column('created', Integer, nullable=False), | ||||
) | ) | ||||
Index( | Index( | ||||
'fsrss', | 'fsrss', | ||||
policy_result_table.c.key, | policy_result_table.c.key, | ||||
policy_result_table.c.sender, | policy_result_table.c.sender, | ||||
policy_result_table.c.recipient, | policy_result_table.c.recipient, | ||||
policy_result_table.c.sasl_username, | policy_result_table.c.sasl_username, | ||||
policy_result_table.c.sasl_sender, | policy_result_table.c.sasl_sender, | ||||
unique=True | unique=True | ||||
) | ) | ||||
class PolicyResult(object): | class PolicyResult(object): | ||||
Lint: PEP8 E302 expected 2 blank lines, found 1 Lint: PEP8 E302: expected 2 blank lines, found 1 | |||||
def __init__( | def __init__( | ||||
self, | self, | ||||
key=None, | key=None, | ||||
value=None, | value=None, | ||||
sender=None, | sender=None, | ||||
recipient=None, | recipient=None, | ||||
sasl_username=None, | sasl_username=None, | ||||
sasl_sender=None | sasl_sender=None | ||||
): | ): | ||||
Lint: PEP8 E125 continuation line with same indent as next logical line Lint: PEP8 E125: continuation line with same indent as next logical line | |||||
self.key = key | self.key = key | ||||
self.value = value | self.value = value | ||||
self.sender = sender | self.sender = sender | ||||
self.sasl_username = sasl_username | self.sasl_username = sasl_username | ||||
self.sasl_sender = sasl_sender | self.sasl_sender = sasl_sender | ||||
self.recipient = recipient | self.recipient = recipient | ||||
self.created = (int)(time.time()) | self.created = (int)(time.time()) | ||||
Show All 12 Lines | |||||
Index( | Index( | ||||
'srd', | 'srd', | ||||
statistic_table.c.sender, | statistic_table.c.sender, | ||||
statistic_table.c.recipient, | statistic_table.c.recipient, | ||||
statistic_table.c.date, | statistic_table.c.date, | ||||
unique=True | unique=True | ||||
) | ) | ||||
class Statistic(object): | class Statistic(object): | ||||
Lint: PEP8 E302 expected 2 blank lines, found 1 Lint: PEP8 E302: expected 2 blank lines, found 1 | |||||
def __init__(self, sender, recipient, date=datetime.date.today(), count=0): | def __init__(self, sender, recipient, date=datetime.date.today(), count=0): | ||||
self.sender = sender | self.sender = sender | ||||
self.recipient = recipient | self.recipient = recipient | ||||
self.date = date | self.date = date | ||||
self.count = count | self.count = count | ||||
mapper(Statistic, statistic_table) | mapper(Statistic, statistic_table) | ||||
class PolicyRequest(object): | class PolicyRequest(object): | ||||
Lint: PEP8 E302 expected 2 blank lines, found 1 Lint: PEP8 E302: expected 2 blank lines, found 1 | |||||
email_address_keys = [ 'sender', 'recipient' ] | email_address_keys = [ 'sender', 'recipient' ] | ||||
Lint: PEP8 E201 whitespace after '[' Lint: PEP8 E201: whitespace after '[' | |||||
Lint: PEP8 E202 whitespace before ']' Lint: PEP8 E202: whitespace before ']' | |||||
recipients = [] | recipients = [] | ||||
auth = None | auth = None | ||||
sasl_domain = None | sasl_domain = None | ||||
sasl_user = None | sasl_user = None | ||||
sender_domain = None | sender_domain = None | ||||
sender_user = None | sender_user = None | ||||
Show All 17 Lines | def __init__(self, policy_request={}): | ||||
if not key == 'recipient': | if not key == 'recipient': | ||||
if policy_request[key] == '': | if policy_request[key] == '': | ||||
setattr(self, key, None) | setattr(self, key, None) | ||||
else: | else: | ||||
setattr(self, key, policy_request[key]) | setattr(self, key, policy_request[key]) | ||||
else: | else: | ||||
if not policy_request['recipient'].strip() == '': | if not policy_request['recipient'].strip() == '': | ||||
self.recipients = list(set(self.recipients + [policy_request['recipient']])) | self.recipients = list(set(self.recipients + [policy_request['recipient']])) | ||||
Lint: PEP8 E501 line too long (96 > 79 characters) Lint: PEP8 E501: line too long (96 > 79 characters) | |||||
def add_request(self, policy_request={}): | def add_request(self, policy_request={}): | ||||
""" | """ | ||||
Add subsequent policy requests to the existing policy request. | Add subsequent policy requests to the existing policy request. | ||||
All data in the request should be the same as the initial policy | All data in the request should be the same as the initial policy | ||||
request, but for the recipient - with destination limits set over | request, but for the recipient - with destination limits set over | ||||
1, Postfix may attempt to deliver messages to more then one | 1, Postfix may attempt to deliver messages to more then one | ||||
Show All 14 Lines | def add_request(self, policy_request={}): | ||||
# Normalize email addresses (they may contain recipient delimiters) | # Normalize email addresses (they may contain recipient delimiters) | ||||
if policy_request.has_key('recipient'): | if policy_request.has_key('recipient'): | ||||
policy_request['recipient'] = normalize_address( | policy_request['recipient'] = normalize_address( | ||||
policy_request['recipient'] | policy_request['recipient'] | ||||
) | ) | ||||
if not policy_request['recipient'].strip() == '': | if not policy_request['recipient'].strip() == '': | ||||
self.recipients = list(set(self.recipients + [policy_request['recipient']])) | self.recipients = list(set(self.recipients + [policy_request['recipient']])) | ||||
Lint: PEP8 E501 line too long (92 > 79 characters) Lint: PEP8 E501: line too long (92 > 79 characters) | |||||
def parse_ldap_dn(self, dn): | def parse_ldap_dn(self, dn): | ||||
""" | """ | ||||
See if parameter 'dn' is a basestring LDAP dn, and if so, return | See if parameter 'dn' is a basestring LDAP dn, and if so, return | ||||
the results we can obtain from said DN. Return a list of relevant | the results we can obtain from said DN. Return a list of relevant | ||||
attribute values. | attribute values. | ||||
If not a DN, return None. | If not a DN, return None. | ||||
Show All 12 Lines | def parse_ldap_dn(self, dn): | ||||
if len(ldap_dn) > 0: | if len(ldap_dn) > 0: | ||||
search_attrs = conf.get_list( | search_attrs = conf.get_list( | ||||
'kolab_smtp_access_policy', | 'kolab_smtp_access_policy', | ||||
'address_search_attrs' | 'address_search_attrs' | ||||
) | ) | ||||
rule_subject = self.auth.get_user_attributes( | rule_subject = self.auth.get_user_attributes( | ||||
self.sasl_domain, | self.sasl_domain, | ||||
{ 'dn': dn }, | { 'dn': dn }, | ||||
Lint: PEP8 E201 whitespace after '{' Lint: PEP8 E201: whitespace after '{' | |||||
Lint: PEP8 E202 whitespace before '}' Lint: PEP8 E202: whitespace before '}' | |||||
search_attrs + [ 'objectclass' ] | search_attrs + [ 'objectclass' ] | ||||
Lint: PEP8 E201 whitespace after '[' Lint: PEP8 E201: whitespace after '[' | |||||
Lint: PEP8 E202 whitespace before ']' Lint: PEP8 E202: whitespace before ']' | |||||
) | ) | ||||
for search_attr in search_attrs: | for search_attr in search_attrs: | ||||
if rule_subject.has_key(search_attr): | if rule_subject.has_key(search_attr): | ||||
if isinstance(rule_subject[search_attr], basestring): | if isinstance(rule_subject[search_attr], basestring): | ||||
values.append(rule_subject[search_attr]) | values.append(rule_subject[search_attr]) | ||||
else: | else: | ||||
values.extend(rule_subject[search_attr]) | values.extend(rule_subject[search_attr]) | ||||
return values | return values | ||||
else: | else: | ||||
# ldap.dn.explode_dn didn't error out, but it also didn't split | # ldap.dn.explode_dn didn't error out, but it also didn't split | ||||
# the DN properly. | # the DN properly. | ||||
return None | return None | ||||
def parse_ldap_uri(self, uri): | def parse_ldap_uri(self, uri): | ||||
values = [] | values = [] | ||||
parsed_uri = utils.parse_ldap_uri(uri) | parsed_uri = utils.parse_ldap_uri(uri) | ||||
if parsed_uri == None: | if parsed_uri == None: | ||||
Lint: PEP8 E711 comparison to None should be 'if cond is None:' Lint: PEP8 E711: comparison to None should be 'if cond is None:' | |||||
return None | return None | ||||
(_protocol, _server, _port, _base_dn, _attrs, _scope, _filter) = \ | (_protocol, _server, _port, _base_dn, _attrs, _scope, _filter) = \ | ||||
parsed_uri | parsed_uri | ||||
Lint: PEP8 E127 continuation line over-indented for visual indent Lint: PEP8 E127: continuation line over-indented for visual indent | |||||
if len(_attrs) == 0: | if len(_attrs) == 0: | ||||
search_attrs = conf.get_list( | search_attrs = conf.get_list( | ||||
'kolab_smtp_access_policy', | 'kolab_smtp_access_policy', | ||||
'address_search_attrs' | 'address_search_attrs' | ||||
) | ) | ||||
else: | else: | ||||
search_attrs = [ _attrs ] | search_attrs = [ _attrs ] | ||||
Lint: PEP8 E201 whitespace after '[' Lint: PEP8 E201: whitespace after '[' | |||||
Lint: PEP8 E202 whitespace before ']' Lint: PEP8 E202: whitespace before ']' | |||||
users = [] | users = [] | ||||
self.auth._auth._bind() | self.auth._auth._bind() | ||||
_users = self.auth._auth._search( | _users = self.auth._auth._search( | ||||
_base_dn, | _base_dn, | ||||
scope=LDAP_SCOPE[_scope], | scope=LDAP_SCOPE[_scope], | ||||
filterstr=_filter, | filterstr=_filter, | ||||
attrlist=search_attrs + [ 'objectclass' ], | attrlist=search_attrs + [ 'objectclass' ], | ||||
Lint: PEP8 E201 whitespace after '[' Lint: PEP8 E201: whitespace after '[' | |||||
Lint: PEP8 E202 whitespace before ']' Lint: PEP8 E202: whitespace before ']' | |||||
override_search="_regular_search" | override_search="_regular_search" | ||||
) | ) | ||||
for _user in _users: | for _user in _users: | ||||
for search_attr in search_attrs: | for search_attr in search_attrs: | ||||
values.extend(_user[1][search_attr]) | values.extend(_user[1][search_attr]) | ||||
return values | return values | ||||
Show All 10 Lines | def parse_policy(self, _subject, _object, policy): | ||||
The _object is a recipient for kolabAllowSMTPRecipient checks, and | The _object is a recipient for kolabAllowSMTPRecipient checks, and | ||||
a sender for kolabAllowSMTPSender checks. | a sender for kolabAllowSMTPSender checks. | ||||
""" | """ | ||||
special_rule_values = { | special_rule_values = { | ||||
'$mydomains': expand_mydomains | '$mydomains': expand_mydomains | ||||
} | } | ||||
rules = { 'allow': [], 'deny': [] } | rules = { 'allow': [], 'deny': [] } | ||||
Lint: PEP8 E201 whitespace after '{' Lint: PEP8 E201: whitespace after '{' | |||||
Lint: PEP8 E202 whitespace before '}' Lint: PEP8 E202: whitespace before '}' | |||||
if isinstance(policy, basestring): | if isinstance(policy, basestring): | ||||
policy = [policy] | policy = [policy] | ||||
for rule in policy: | for rule in policy: | ||||
# Find rules that are actually special values, simply by | # Find rules that are actually special values, simply by | ||||
# mapping the rule onto a key in "special_rule_values", a | # mapping the rule onto a key in "special_rule_values", a | ||||
# dictionary with the corresponding value set to a function to | # dictionary with the corresponding value set to a function to | ||||
Show All 18 Lines | def parse_policy(self, _subject, _object, policy): | ||||
_rule = rule[1:] | _rule = rule[1:] | ||||
else: | else: | ||||
_prefix = '' | _prefix = '' | ||||
_rule = rule | _rule = rule | ||||
# See if the value is an LDAP DN | # See if the value is an LDAP DN | ||||
ldap_dn = self.parse_ldap_dn(_rule) | ldap_dn = self.parse_ldap_dn(_rule) | ||||
if not ldap_dn == None and len(ldap_dn) > 0: | if not ldap_dn == None and len(ldap_dn) > 0: | ||||
Lint: PEP8 E711 comparison to None should be 'if cond is None:' Lint: PEP8 E711: comparison to None should be 'if cond is None:' | |||||
if _prefix == '-': | if _prefix == '-': | ||||
rules['deny'].extend(ldap_dn) | rules['deny'].extend(ldap_dn) | ||||
else: | else: | ||||
rules['allow'].extend(ldap_dn) | rules['allow'].extend(ldap_dn) | ||||
else: | else: | ||||
ldap_uri = self.parse_ldap_uri(_rule) | ldap_uri = self.parse_ldap_uri(_rule) | ||||
if not ldap_uri == None and len(ldap_uri) > 0: | if not ldap_uri == None and len(ldap_uri) > 0: | ||||
Lint: PEP8 E711 comparison to None should be 'if cond is None:' Lint: PEP8 E711: comparison to None should be 'if cond is None:' | |||||
if _prefix == '-': | if _prefix == '-': | ||||
rules['deny'].extend(ldap_uri) | rules['deny'].extend(ldap_uri) | ||||
else: | else: | ||||
rules['allow'].extend(ldap_uri) | rules['allow'].extend(ldap_uri) | ||||
else: | else: | ||||
if rule.startswith("-"): | if rule.startswith("-"): | ||||
rules['deny'].append(rule[1:]) | rules['deny'].append(rule[1:]) | ||||
else: | else: | ||||
rules['allow'].append(rule) | rules['allow'].append(rule) | ||||
allowed = False | allowed = False | ||||
for rule in rules['allow']: | for rule in rules['allow']: | ||||
deny_override = False | deny_override = False | ||||
if _object.endswith(rule): | if _object is not None and _object.endswith(rule): | ||||
for deny_rule in rules['deny']: | for deny_rule in rules['deny']: | ||||
if deny_rule.endswith(rule): | if deny_rule.endswith(rule): | ||||
deny_override = True | deny_override = True | ||||
if not deny_override: | if not deny_override: | ||||
allowed = True | allowed = True | ||||
denied = False | denied = False | ||||
for rule in rules['deny']: | for rule in rules['deny']: | ||||
allow_override = False | allow_override = False | ||||
if _object.endswith(rule): | if _object is not None and _object.endswith(rule): | ||||
if not allowed: | if not allowed: | ||||
denied = True | denied = True | ||||
continue | continue | ||||
else: | else: | ||||
for allow_rule in rules['allow']: | for allow_rule in rules['allow']: | ||||
if allow_rule.endswith(rule): | if allow_rule.endswith(rule): | ||||
allow_override = True | allow_override = True | ||||
Show All 11 Lines | def verify_alias(self): | ||||
using an alias of its primary authentication ID / attribute. | using an alias of its primary authentication ID / attribute. | ||||
John.Doe@example.org (mail) for example could be sending with | John.Doe@example.org (mail) for example could be sending with | ||||
envelope sender jdoe@example.org (mailAlternateAddress, alias). | envelope sender jdoe@example.org (mailAlternateAddress, alias). | ||||
""" | """ | ||||
search_attrs = conf.get_list(self.sasl_domain, 'address_search_attrs') | search_attrs = conf.get_list(self.sasl_domain, 'address_search_attrs') | ||||
if search_attrs == None or \ | if search_attrs == None or \ | ||||
Lint: PEP8 E711 comparison to None should be 'if cond is None:' Lint: PEP8 E711: comparison to None should be 'if cond is None:' | |||||
(isinstance(search_attrs, list) and len(search_attrs) == 0): | (isinstance(search_attrs, list) and len(search_attrs) == 0): | ||||
search_attrs = conf.get_list(self.sasl_domain, 'mail_attributes') | search_attrs = conf.get_list(self.sasl_domain, 'mail_attributes') | ||||
if search_attrs == None or \ | if search_attrs == None or \ | ||||
Lint: PEP8 E711 comparison to None should be 'if cond is None:' Lint: PEP8 E711: comparison to None should be 'if cond is None:' | |||||
(isinstance(search_attrs, list) and len(search_attrs) == 0): | (isinstance(search_attrs, list) and len(search_attrs) == 0): | ||||
search_attrs = conf.get_list( | search_attrs = conf.get_list( | ||||
'kolab_smtp_access_policy', | 'kolab_smtp_access_policy', | ||||
'address_search_attrs' | 'address_search_attrs' | ||||
) | ) | ||||
if search_attrs == None or \ | if search_attrs == None or \ | ||||
Lint: PEP8 E711 comparison to None should be 'if cond is None:' Lint: PEP8 E711: comparison to None should be 'if cond is None:' | |||||
(isinstance(search_attrs, list) and len(search_attrs) == 0): | (isinstance(search_attrs, list) and len(search_attrs) == 0): | ||||
search_attrs = conf.get_list( | search_attrs = conf.get_list( | ||||
Lint: PEP8 E303 too many blank lines (2) Lint: PEP8 E303: too many blank lines (2) | |||||
conf.get('kolab', 'auth_mechanism'), | conf.get('kolab', 'auth_mechanism'), | ||||
'mail_attributes' | 'mail_attributes' | ||||
) | ) | ||||
want_attrs = [] | want_attrs = [] | ||||
for search_attr in search_attrs: | for search_attr in search_attrs: | ||||
if not self.sasl_user.has_key(search_attr): | if not self.sasl_user.has_key(search_attr): | ||||
want_attrs.append(search_attr) | want_attrs.append(search_attr) | ||||
if len(want_attrs) > 0: | if len(want_attrs) > 0: | ||||
self.sasl_user.update( | self.sasl_user.update( | ||||
self.auth.get_user_attributes( | self.auth.get_user_attributes( | ||||
self.sasl_domain, | self.sasl_domain, | ||||
self.sasl_user, | self.sasl_user, | ||||
want_attrs | want_attrs | ||||
) | ) | ||||
) | ) | ||||
# Catch a user using one of its own alias addresses. | # Catch a user using one of its own alias addresses. | ||||
for search_attr in search_attrs: | for search_attr in search_attrs: | ||||
if self.sasl_user.has_key(search_attr): | if self.sasl_user.has_key(search_attr): | ||||
if isinstance(self.sasl_user[search_attr], list): | if isinstance(self.sasl_user[search_attr], list): | ||||
if self.sender.lower() in [x.lower() for x in self.sasl_user[search_attr]]: | if self.sender.lower() in [x.lower() for x in self.sasl_user[search_attr]]: | ||||
Lint: PEP8 E501 line too long (95 > 79 characters) Lint: PEP8 E501: line too long (95 > 79 characters) | |||||
return True | return True | ||||
elif self.sasl_user[search_attr].lower() == self.sender.lower(): | elif self.sasl_user[search_attr].lower() == self.sender.lower(): | ||||
Lint: PEP8 E501 line too long (80 > 79 characters) Lint: PEP8 E501: line too long (80 > 79 characters) | |||||
return True | return True | ||||
return False | return False | ||||
def verify_authenticity(self): | def verify_authenticity(self): | ||||
""" | """ | ||||
Verify that the SASL username or lack thereof corresponds with | Verify that the SASL username or lack thereof corresponds with | ||||
allowing or disallowing authenticated users. | allowing or disallowing authenticated users. | ||||
If an SASL username is supplied, use it to obtain the authentication | If an SASL username is supplied, use it to obtain the authentication | ||||
Lint: PEP8 E501 line too long (80 > 79 characters) Lint: PEP8 E501: line too long (80 > 79 characters) | |||||
database user object including all attributes we may find ourselves | database user object including all attributes we may find ourselves | ||||
interested in. | interested in. | ||||
""" | """ | ||||
if self.sasl_username == None: | if self.sasl_username == None: | ||||
Lint: PEP8 E711 comparison to None should be 'if cond is None:' Lint: PEP8 E711: comparison to None should be 'if cond is None:' | |||||
if not conf.allow_unauthenticated: | if not conf.allow_unauthenticated: | ||||
reject(_("Unauthorized access not allowed")) | reject(_("Unauthorized access not allowed")) | ||||
else: | else: | ||||
# If unauthenticated is allowed, I have nothing to do here. | # If unauthenticated is allowed, I have nothing to do here. | ||||
return True | return True | ||||
sasl_username = self.sasl_username | sasl_username = self.sasl_username | ||||
# If we have an sasl_username, find the user object in the | # If we have an sasl_username, find the user object in the | ||||
# authentication database, along with the attributes we are | # authentication database, along with the attributes we are | ||||
# interested in. | # interested in. | ||||
if self.sasl_domain == None: | if self.sasl_domain == None: | ||||
Lint: PEP8 E711 comparison to None should be 'if cond is None:' Lint: PEP8 E711: comparison to None should be 'if cond is None:' | |||||
if len(self.sasl_username.split('@')) > 1: | if len(self.sasl_username.split('@')) > 1: | ||||
self.sasl_domain = self.sasl_username.split('@')[1] | self.sasl_domain = self.sasl_username.split('@')[1] | ||||
else: | else: | ||||
self.sasl_domain = conf.get('kolab', 'primary_domain') | 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) | ||||
Lint: PEP8 E501 line too long (80 > 79 characters) Lint: PEP8 E501: line too long (80 > 79 characters) | |||||
if self.auth == None: | if self.auth == None: | ||||
Lint: PEP8 E711 comparison to None should be 'if cond is None:' Lint: PEP8 E711: comparison to None should be 'if cond is None:' | |||||
self.auth = Auth(self.sasl_domain) | self.auth = Auth(self.sasl_domain) | ||||
elif not self.auth.domain == self.sasl_domain: | elif not self.auth.domain == self.sasl_domain: | ||||
self.auth = Auth(self.sasl_domain) | self.auth = Auth(self.sasl_domain) | ||||
sasl_users = self.auth.find_recipient( | sasl_users = self.auth.find_recipient( | ||||
sasl_username, | sasl_username, | ||||
domain=self.sasl_domain | domain=self.sasl_domain | ||||
) | ) | ||||
if isinstance(sasl_users, list): | if isinstance(sasl_users, list): | ||||
if len(sasl_users) == 0: | if len(sasl_users) == 0: | ||||
log.error(_("Could not find recipient")) | log.error(_("Could not find recipient")) | ||||
return False | return False | ||||
else: | else: | ||||
self.sasl_user = { 'dn': sasl_users[0] } | self.sasl_user = { 'dn': sasl_users[0] } | ||||
Lint: PEP8 E201 whitespace after '{' Lint: PEP8 E201: whitespace after '{' | |||||
Lint: PEP8 E202 whitespace before '}' Lint: PEP8 E202: whitespace before '}' | |||||
elif isinstance(sasl_users, basestring): | elif isinstance(sasl_users, basestring): | ||||
self.sasl_user = { 'dn': sasl_users } | self.sasl_user = { 'dn': sasl_users } | ||||
Lint: PEP8 E201 whitespace after '{' Lint: PEP8 E201: whitespace after '{' | |||||
Lint: PEP8 E202 whitespace before '}' Lint: PEP8 E202: whitespace before '}' | |||||
if not self.sasl_user['dn']: | if not self.sasl_user['dn']: | ||||
# Got a final answer here, do the caching thing. | # Got a final answer here, do the caching thing. | ||||
cache_update( | cache_update( | ||||
function='verify_sender', | function='verify_sender', | ||||
sender=self.sender, | sender=self.sender, | ||||
recipients=self.recipients, | recipients=self.recipients, | ||||
result=(int)(False), | result=(int)(False), | ||||
sasl_username=self.sasl_username, | sasl_username=self.sasl_username, | ||||
sasl_sender=self.sasl_sender | sasl_sender=self.sasl_sender | ||||
) | ) | ||||
reject( | reject( | ||||
_("Could not find envelope sender user %s (511)") % ( | _("Could not find envelope sender user %s (511)") % ( | ||||
self.sasl_username | self.sasl_username | ||||
) | ) | ||||
) | ) | ||||
attrs = conf.get_list(self.sasl_domain, 'auth_attributes') | attrs = conf.get_list(self.sasl_domain, 'auth_attributes') | ||||
if attrs == None or (isinstance(attrs, list) and len(attrs) == 0): | if attrs == None or (isinstance(attrs, list) and len(attrs) == 0): | ||||
Lint: PEP8 E711 comparison to None should be 'if cond is None:' Lint: PEP8 E711: comparison to None should be 'if cond is None:' | |||||
attrs = conf.get_list( | attrs = conf.get_list( | ||||
conf.get('kolab', 'auth_mechanism'), | conf.get('kolab', 'auth_mechanism'), | ||||
'auth_attributes' | 'auth_attributes' | ||||
) | ) | ||||
mail_attrs = conf.get_list(self.sasl_domain, 'mail_attributes') | mail_attrs = conf.get_list(self.sasl_domain, 'mail_attributes') | ||||
if mail_attrs == None or \ | if mail_attrs == None or \ | ||||
Lint: PEP8 E711 comparison to None should be 'if cond is None:' Lint: PEP8 E711: comparison to None should be 'if cond is None:' | |||||
(isinstance(mail_attrs, list) and len(mail_attrs) == 0): | (isinstance(mail_attrs, list) and len(mail_attrs) == 0): | ||||
mail_attrs = conf.get_list( | mail_attrs = conf.get_list( | ||||
conf.get('kolab', 'auth_mechanism'), | conf.get('kolab', 'auth_mechanism'), | ||||
'mail_attributes' | 'mail_attributes' | ||||
) | ) | ||||
if not mail_attrs == None: | if not mail_attrs == None: | ||||
Lint: PEP8 E711 comparison to None should be 'if cond is None:' Lint: PEP8 E711: comparison to None should be 'if cond is None:' | |||||
attrs.extend(mail_attrs) | attrs.extend(mail_attrs) | ||||
attrs.extend( | attrs.extend( | ||||
[ | [ | ||||
'kolabAllowSMTPRecipient', | 'kolabAllowSMTPRecipient', | ||||
'kolabAllowSMTPSender' | 'kolabAllowSMTPSender' | ||||
] | ] | ||||
) | ) | ||||
Show All 18 Lines | class PolicyRequest(object): | ||||
def verify_delegate(self): | def verify_delegate(self): | ||||
""" | """ | ||||
Verify whether the authenticated user is a delegate of the envelope | Verify whether the authenticated user is a delegate of the envelope | ||||
sender. | sender. | ||||
""" | """ | ||||
sender_is_delegate = False | sender_is_delegate = False | ||||
if self.sender_domain == None: | if self.sender_domain == None: | ||||
Lint: PEP8 E711 comparison to None should be 'if cond is None:' Lint: PEP8 E711: comparison to None should be 'if cond is None:' | |||||
if len(self.sender.split('@')) > 1: | if len(self.sender.split('@')) > 1: | ||||
self.sender_domain = self.sender.split('@')[1] | self.sender_domain = self.sender.split('@')[1] | ||||
else: | else: | ||||
self.sender_domain = conf.get('kolab', 'primary_domain') | self.sender_domain = conf.get('kolab', 'primary_domain') | ||||
if self.sender == self.sasl_username: | if self.sender == self.sasl_username: | ||||
return True | return True | ||||
search_attrs = conf.get_list(self.sender_domain, 'mail_attributes') | search_attrs = conf.get_list(self.sender_domain, 'mail_attributes') | ||||
if search_attrs == None: | if search_attrs == None: | ||||
Lint: PEP8 E711 comparison to None should be 'if cond is None:' Lint: PEP8 E711: comparison to None should be 'if cond is None:' | |||||
search_attrs = conf.get_list( | search_attrs = conf.get_list( | ||||
conf.get('kolab', 'auth_mechanism'), | conf.get('kolab', 'auth_mechanism'), | ||||
'mail_attributes' | 'mail_attributes' | ||||
) | ) | ||||
sender_users = self.auth.find_recipient( | sender_users = self.auth.find_recipient( | ||||
self.sender, | self.sender, | ||||
domain=self.sender_domain | domain=self.sender_domain | ||||
) | ) | ||||
if isinstance(sender_users, list): | if isinstance(sender_users, list): | ||||
if len(sender_users) > 1: | if len(sender_users) > 1: | ||||
# More then one sender user with this recipient address. | # More then one sender user with this recipient address. | ||||
# TODO: check each of the sender users found. | # TODO: check each of the sender users found. | ||||
self.sender_user = { 'dn': sender_users[0] } | self.sender_user = { 'dn': sender_users[0] } | ||||
Lint: PEP8 E201 whitespace after '{' Lint: PEP8 E201: whitespace after '{' | |||||
Lint: PEP8 E202 whitespace before '}' Lint: PEP8 E202: whitespace before '}' | |||||
elif len(sender_users) == 1: | elif len(sender_users) == 1: | ||||
self.sender_user = { 'dn': sender_users } | self.sender_user = { 'dn': sender_users } | ||||
Lint: PEP8 E201 whitespace after '{' Lint: PEP8 E201: whitespace after '{' | |||||
Lint: PEP8 E202 whitespace before '}' Lint: PEP8 E202: whitespace before '}' | |||||
else: | else: | ||||
self.sender_user = { 'dn': False } | self.sender_user = { 'dn': False } | ||||
Lint: PEP8 E201 whitespace after '{' Lint: PEP8 E201: whitespace after '{' | |||||
Lint: PEP8 E202 whitespace before '}' Lint: PEP8 E202: whitespace before '}' | |||||
elif isinstance(sender_users, basestring): | elif isinstance(sender_users, basestring): | ||||
self.sender_user = { 'dn': sender_users } | self.sender_user = { 'dn': sender_users } | ||||
Lint: PEP8 E201 whitespace after '{' Lint: PEP8 E201: whitespace after '{' | |||||
Lint: PEP8 E202 whitespace before '}' Lint: PEP8 E202: whitespace before '}' | |||||
if not self.sender_user['dn']: | if not self.sender_user['dn']: | ||||
cache_update( | cache_update( | ||||
function='verify_sender', | function='verify_sender', | ||||
sender=self.sender, | sender=self.sender, | ||||
recipients=self.recipients, | recipients=self.recipients, | ||||
result=(int)(False), | result=(int)(False), | ||||
sasl_username=self.sasl_username, | sasl_username=self.sasl_username, | ||||
Show All 17 Lines | def verify_delegate(self): | ||||
attrs | attrs | ||||
) | ) | ||||
user_attrs['dn'] = self.sender_user['dn'] | user_attrs['dn'] = self.sender_user['dn'] | ||||
self.sender_user = utils.normalize(user_attrs) | self.sender_user = utils.normalize(user_attrs) | ||||
if not self.sender_user.has_key('kolabdelegate'): | if not self.sender_user.has_key('kolabdelegate'): | ||||
# Got a final answer here, do the caching thing. | # Got a final answer here, do the caching thing. | ||||
if not cache == False: | if not cache == False: | ||||
Lint: PEP8 E712 comparison to False should be 'if cond is False:' or 'if not cond:' Lint: PEP8 E712: comparison to False should be 'if cond is False:' or 'if not cond:' | |||||
record_id = cache_update( | record_id = cache_update( | ||||
function='verify_sender', | function='verify_sender', | ||||
sender=self.sender, | sender=self.sender, | ||||
recipients=self.recipients, | recipients=self.recipients, | ||||
result=(int)(False), | result=(int)(False), | ||||
sasl_username=self.sasl_username, | sasl_username=self.sasl_username, | ||||
sasl_sender=self.sasl_sender | sasl_sender=self.sasl_sender | ||||
) | ) | ||||
reject( | reject( | ||||
_("%s is unauthorized to send on behalf of %s") % ( | _("%s is unauthorized to send on behalf of %s") % ( | ||||
self.sasl_user['dn'], | self.sasl_user['dn'], | ||||
self.sender_user['dn'] | self.sender_user['dn'] | ||||
) | ) | ||||
) | ) | ||||
elif self.sender_user['kolabdelegate'] == None: | elif self.sender_user['kolabdelegate'] == None: | ||||
Lint: PEP8 E711 comparison to None should be 'if cond is None:' Lint: PEP8 E711: comparison to None should be 'if cond is None:' | |||||
# No delegates for this sender could be found. The user is | # No delegates for this sender could be found. The user is | ||||
# definitely NOT a delegate of the sender. | # definitely NOT a delegate of the sender. | ||||
log.warning( | log.warning( | ||||
_("User %s attempted to use envelope sender address %s without authorization") % ( | _("User %s attempted to use envelope sender address %s without authorization") % ( | ||||
Lint: PEP8 E501 line too long (98 > 79 characters) Lint: PEP8 E501: line too long (98 > 79 characters) | |||||
policy_request["sasl_username"], | policy_request["sasl_username"], | ||||
policy_request["sender"] | policy_request["sender"] | ||||
) | ) | ||||
) | ) | ||||
# Got a final answer here, do the caching thing. | # Got a final answer here, do the caching thing. | ||||
if not cache == False: | if not cache == False: | ||||
Lint: PEP8 E712 comparison to False should be 'if cond is False:' or 'if not cond:' Lint: PEP8 E712: comparison to False should be 'if cond is False:' or 'if not cond:' | |||||
record_id = cache_update( | record_id = cache_update( | ||||
function='verify_sender', | function='verify_sender', | ||||
sender=self.sender, | sender=self.sender, | ||||
recipients=self.recipients, | recipients=self.recipients, | ||||
result=(int)(False), | result=(int)(False), | ||||
sasl_username=self.sasl_username, | sasl_username=self.sasl_username, | ||||
sasl_sender=self.sasl_sender | sasl_sender=self.sasl_sender | ||||
) | ) | ||||
reject( | reject( | ||||
_("%s is unauthorized to send on behalf of %s") % ( | _("%s is unauthorized to send on behalf of %s") % ( | ||||
self.sasl_user['dn'], | self.sasl_user['dn'], | ||||
self.sender_user['dn'] | self.sender_user['dn'] | ||||
) | ) | ||||
) | ) | ||||
else: | else: | ||||
# See if we can match the value of the envelope sender delegates to | # See if we can match the value of the envelope sender delegates to | ||||
# the actual sender sasl_username | # the actual sender sasl_username | ||||
if self.sasl_user == None: | if self.sasl_user == None: | ||||
Lint: PEP8 E711 comparison to None should be 'if cond is None:' Lint: PEP8 E711: comparison to None should be 'if cond is None:' | |||||
sasl_users = self.auth.find_recipient( | sasl_users = self.auth.find_recipient( | ||||
self.sasl_username, | self.sasl_username, | ||||
domain=self.sasl_domain | domain=self.sasl_domain | ||||
) | ) | ||||
if isinstance(sasl_users, list): | if isinstance(sasl_users, list): | ||||
if len(sasl_users) == 0: | if len(sasl_users) == 0: | ||||
log.error(_("Could not find recipient")) | log.error(_("Could not find recipient")) | ||||
return False | return False | ||||
else: | else: | ||||
self.sasl_user = { 'dn': sasl_users[0] } | self.sasl_user = { 'dn': sasl_users[0] } | ||||
Lint: PEP8 E201 whitespace after '{' Lint: PEP8 E201: whitespace after '{' | |||||
Lint: PEP8 E202 whitespace before '}' Lint: PEP8 E202: whitespace before '}' | |||||
elif isinstance(sasl_users, basestring): | elif isinstance(sasl_users, basestring): | ||||
self.sasl_user = { 'dn': sasl_users } | self.sasl_user = { 'dn': sasl_users } | ||||
Lint: PEP8 E201 whitespace after '{' Lint: PEP8 E201: whitespace after '{' | |||||
Lint: PEP8 E202 whitespace before '}' Lint: PEP8 E202: whitespace before '}' | |||||
# Possible values for the kolabDelegate attribute are: | # Possible values for the kolabDelegate attribute are: | ||||
# a 'uid', a 'dn'. | # a 'uid', a 'dn'. | ||||
if not self.sasl_user.has_key('uid'): | if not self.sasl_user.has_key('uid'): | ||||
self.sasl_user['uid'] = self.auth.get_user_attribute( | self.sasl_user['uid'] = self.auth.get_user_attribute( | ||||
self.sasl_domain, | self.sasl_domain, | ||||
self.sasl_user, | self.sasl_user, | ||||
'uid' | 'uid' | ||||
) | ) | ||||
sender_delegates = self.sender_user['kolabdelegate'] | sender_delegates = self.sender_user['kolabdelegate'] | ||||
Lint: PEP8 E303 too many blank lines (2) Lint: PEP8 E303: too many blank lines (2) | |||||
if not type(sender_delegates) == list: | if not type(sender_delegates) == list: | ||||
sender_delegates = [ sender_delegates ] | sender_delegates = [ sender_delegates ] | ||||
Lint: PEP8 E201 whitespace after '[' Lint: PEP8 E201: whitespace after '[' | |||||
Lint: PEP8 E202 whitespace before ']' Lint: PEP8 E202: whitespace before ']' | |||||
for sender_delegate in sender_delegates: | for sender_delegate in sender_delegates: | ||||
if self.sasl_user['dn'] == sender_delegate: | if self.sasl_user['dn'] == sender_delegate: | ||||
log.debug( | log.debug( | ||||
_("Found user %s to be a delegate user of %s") % ( | _("Found user %s to be a delegate user of %s") % ( | ||||
policy_request["sasl_username"], | policy_request["sasl_username"], | ||||
policy_request["sender"] | policy_request["sender"] | ||||
), | ), | ||||
Show All 18 Lines | class PolicyRequest(object): | ||||
def verify_recipient(self, recipient): | def verify_recipient(self, recipient): | ||||
""" | """ | ||||
Verify whether the sender is allowed send to this recipient, using | Verify whether the sender is allowed send to this recipient, using | ||||
the recipient's kolabAllowSMTPSender. | the recipient's kolabAllowSMTPSender. | ||||
""" | """ | ||||
self.recipient = recipient | self.recipient = recipient | ||||
if not self.sasl_username == '' and not self.sasl_username == None: | if not self.sasl_username == '' and not self.sasl_username == None: | ||||
Lint: PEP8 E711 comparison to None should be 'if cond is None:' Lint: PEP8 E711: comparison to None should be 'if cond is None:' | |||||
log.debug(_("Verifying authenticated sender '%(sender)s' with sasl_username '%(sasl_username)s' for recipient '%(recipient)s'") % (self.__dict__) | log.debug(_("Verifying authenticated sender '%(sender)s' with sasl_username '%(sasl_username)s' for recipient '%(recipient)s'") % (self.__dict__) | ||||
Lint: PEP8 E501 line too long (157 > 79 characters) Lint: PEP8 E501: line too long (157 > 79 characters) | |||||
) | ) | ||||
Lint: PEP8 E124 closing bracket does not match visual indentation Lint: PEP8 E124: closing bracket does not match visual indentation | |||||
else: | 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__) | ||||
Lint: PEP8 E501 line too long (120 > 79 characters) Lint: PEP8 E501: line too long (120 > 79 characters) | |||||
) | ) | ||||
Lint: PEP8 E124 closing bracket does not match visual indentation Lint: PEP8 E124: closing bracket does not match visual indentation | |||||
recipient_verified = False | recipient_verified = False | ||||
if not cache == False: | if not cache == False: | ||||
Lint: PEP8 E712 comparison to False should be 'if cond is False:' or 'if not cond:' Lint: PEP8 E712: comparison to False should be 'if cond is False:' or 'if not cond:' | |||||
records = cache_select( | records = cache_select( | ||||
function='verify_recipient', | function='verify_recipient', | ||||
sender=self.sender, | sender=self.sender, | ||||
recipient=recipient, | recipient=recipient, | ||||
sasl_username=self.sasl_username, | sasl_username=self.sasl_username, | ||||
sasl_sender=self.sasl_sender, | sasl_sender=self.sasl_sender, | ||||
) | ) | ||||
if not records == None and len(records) == 1: | if not records == None and len(records) == 1: | ||||
Lint: PEP8 E711 comparison to None should be 'if cond is None:' Lint: PEP8 E711: comparison to None should be 'if cond is None:' | |||||
log.info( | log.info( | ||||
_("Reproducing verify_recipient(%s, %s) from cache") % ( | _("Reproducing verify_recipient(%s, %s) from cache") % ( | ||||
Lint: PEP8 E501 line too long (80 > 79 characters) Lint: PEP8 E501: line too long (80 > 79 characters) | |||||
self.sender, | self.sender, | ||||
recipient | recipient | ||||
) | ) | ||||
) | ) | ||||
return records[0].value | return records[0].value | ||||
# TODO: Under some conditions, the recipient may not be fully qualified. | # TODO: Under some conditions, the recipient may not be fully qualified. | ||||
Lint: PEP8 E501 line too long (80 > 79 characters) Lint: PEP8 E501: line too long (80 > 79 characters) | |||||
# We'll cross that bridge when we get there, though. | # We'll cross that bridge when we get there, though. | ||||
if len(recipient.split('@')) > 1: | if len(recipient.split('@')) > 1: | ||||
sasl_domain = recipient.split('@')[1] | sasl_domain = recipient.split('@')[1] | ||||
else: | else: | ||||
sasl_domain = conf.get('kolab', 'primary_domain') | sasl_domain = conf.get('kolab', 'primary_domain') | ||||
recipient = "%s@%s" % (recipient,sasl_domain) | recipient = "%s@%s" % (recipient,sasl_domain) | ||||
Lint: PEP8 E231 missing whitespace after ',' Lint: PEP8 E231: missing whitespace after ',' | |||||
if not verify_domain(sasl_domain): | if not verify_domain(sasl_domain): | ||||
if not cache == False: | if not cache == False: | ||||
Lint: PEP8 E712 comparison to False should be 'if cond is False:' or 'if not cond:' Lint: PEP8 E712: comparison to False should be 'if cond is False:' or 'if not cond:' | |||||
cache_update( | cache_update( | ||||
function='verify_recipient', | function='verify_recipient', | ||||
sender=self.sender, | sender=self.sender, | ||||
recipient=recipient, | recipient=recipient, | ||||
result=(int)(True), | result=(int)(True), | ||||
sasl_username=self.sasl_username, | sasl_username=self.sasl_username, | ||||
sasl_sender=self.sasl_sender | sasl_sender=self.sasl_sender | ||||
) | ) | ||||
return True | return True | ||||
if self.auth == None: | if self.auth == None: | ||||
Lint: PEP8 E711 comparison to None should be 'if cond is None:' Lint: PEP8 E711: comparison to None should be 'if cond is None:' | |||||
self.auth = Auth(sasl_domain) | self.auth = Auth(sasl_domain) | ||||
elif not self.auth.domain == sasl_domain: | elif not self.auth.domain == sasl_domain: | ||||
self.auth = Auth(sasl_domain) | self.auth = Auth(sasl_domain) | ||||
if verify_domain(sasl_domain): | if verify_domain(sasl_domain): | ||||
if not self.auth.domains == None and self.auth.domains.has_key(sasl_domain): | if not self.auth.domains == None and self.auth.domains.has_key(sasl_domain): | ||||
Lint: PEP8 E711 comparison to None should be 'if cond is None:' Lint: PEP8 E711: comparison to None should be 'if cond is None:' | |||||
Lint: PEP8 E501 line too long (88 > 79 characters) Lint: PEP8 E501: line too long (88 > 79 characters) | |||||
log.debug( | log.debug( | ||||
_("Using authentication domain %s instead of %s") % ( | _("Using authentication domain %s instead of %s") % ( | ||||
self.auth.domains[sasl_domain], | self.auth.domains[sasl_domain], | ||||
sasl_domain | sasl_domain | ||||
), | ), | ||||
level=8 | level=8 | ||||
) | ) | ||||
sasl_domain = self.auth.domains[sasl_domain] | sasl_domain = self.auth.domains[sasl_domain] | ||||
else: | else: | ||||
log.debug( | log.debug( | ||||
_("Domain %s is a primary domain") % ( | _("Domain %s is a primary domain") % ( | ||||
sasl_domain | sasl_domain | ||||
), | ), | ||||
level=8 | level=8 | ||||
) | ) | ||||
else: | else: | ||||
log.warning( | log.warning( | ||||
_("Checking the recipient for domain %s that is not ours. This is probably a configuration error.") % ( | _("Checking the recipient for domain %s that is not ours. This is probably a configuration error.") % ( | ||||
Lint: PEP8 E501 line too long (123 > 79 characters) Lint: PEP8 E501: line too long (123 > 79 characters) | |||||
sasl_domain | sasl_domain | ||||
) | ) | ||||
) | ) | ||||
return True | return True | ||||
recipients = self.auth.find_recipient( | recipients = self.auth.find_recipient( | ||||
normalize_address(recipient), | normalize_address(recipient), | ||||
domain=sasl_domain, | domain=sasl_domain, | ||||
) | ) | ||||
if isinstance(recipients, list): | if isinstance(recipients, list): | ||||
if len(recipients) > 1: | if len(recipients) > 1: | ||||
log.info( | 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") | ||||
Lint: PEP8 E501 line too long (156 > 79 characters) Lint: PEP8 E501: line too long (156 > 79 characters) | |||||
) | ) | ||||
cache_update( | cache_update( | ||||
function='verify_recipient', | function='verify_recipient', | ||||
sender=self.sender, | sender=self.sender, | ||||
recipient=normalize_address(recipient), | recipient=normalize_address(recipient), | ||||
result=(int)(True), | result=(int)(True), | ||||
sasl_username=self.sasl_username, | sasl_username=self.sasl_username, | ||||
sasl_sender=self.sasl_sender | sasl_sender=self.sasl_sender | ||||
) | ) | ||||
return True | return True | ||||
elif len(recipients) == 1: | elif len(recipients) == 1: | ||||
_recipient = { 'dn': recipients[0] } | _recipient = { 'dn': recipients[0] } | ||||
Lint: PEP8 E201 whitespace after '{' Lint: PEP8 E201: whitespace after '{' | |||||
Lint: PEP8 E202 whitespace before '}' Lint: PEP8 E202: whitespace before '}' | |||||
else: | else: | ||||
log.debug( | log.debug( | ||||
_("Recipient address %r not found. Allowing since the MTA was configured to accept the recipient.") % ( | _("Recipient address %r not found. Allowing since the MTA was configured to accept the recipient.") % ( | ||||
Lint: PEP8 E501 line too long (127 > 79 characters) Lint: PEP8 E501: line too long (127 > 79 characters) | |||||
normalize_address(recipient) | normalize_address(recipient) | ||||
), | ), | ||||
level=3 | level=3 | ||||
) | ) | ||||
cache_update( | cache_update( | ||||
function='verify_recipient', | function='verify_recipient', | ||||
sender=self.sender, | sender=self.sender, | ||||
Show All 33 Lines | def verify_recipient(self, recipient): | ||||
result=(int)(True), | result=(int)(True), | ||||
sasl_username=self.sasl_username, | sasl_username=self.sasl_username, | ||||
sasl_sender=self.sasl_sender | sasl_sender=self.sasl_sender | ||||
) | ) | ||||
log.debug(_("Could not find this user, accepting"), level=8) | log.debug(_("Could not find this user, accepting"), level=8) | ||||
return True | return True | ||||
if not _recipient['dn'] == False: | if not _recipient['dn'] == False: | ||||
Lint: PEP8 E712 comparison to False should be 'if cond is False:' or 'if not cond:' Lint: PEP8 E712: comparison to False should be 'if cond is False:' or 'if not cond:' | |||||
recipient_policy = self.auth.get_entry_attribute( | recipient_policy = self.auth.get_entry_attribute( | ||||
sasl_domain, | sasl_domain, | ||||
_recipient['dn'], | _recipient['dn'], | ||||
'kolabAllowSMTPSender' | 'kolabAllowSMTPSender' | ||||
) | ) | ||||
# If no such attribute has been specified, allow | # If no such attribute has been specified, allow | ||||
if recipient_policy == None: | if recipient_policy == None: | ||||
Lint: PEP8 E711 comparison to None should be 'if cond is None:' Lint: PEP8 E711: comparison to None should be 'if cond is None:' | |||||
cache_update( | cache_update( | ||||
function='verify_recipient', | function='verify_recipient', | ||||
sender=self.sender, | sender=self.sender, | ||||
recipient=normalize_address(recipient), | recipient=normalize_address(recipient), | ||||
result=(int)(True), | result=(int)(True), | ||||
sasl_username=self.sasl_username, | sasl_username=self.sasl_username, | ||||
sasl_sender=self.sasl_sender | sasl_sender=self.sasl_sender | ||||
) | ) | ||||
Show All 27 Lines | def verify_recipients(self): | ||||
policy request, using each recipient's kolabAllowSMTPSender. | policy request, using each recipient's kolabAllowSMTPSender. | ||||
Note there may be multiple recipients in this policy request, and | Note there may be multiple recipients in this policy request, and | ||||
therefor self.recipients is a list - walk through that list. | therefor self.recipients is a list - walk through that list. | ||||
""" | """ | ||||
recipients_verified = True | recipients_verified = True | ||||
if not cache == False: | if not cache == False: | ||||
Lint: PEP8 E712 comparison to False should be 'if cond is False:' or 'if not cond:' Lint: PEP8 E712: comparison to False should be 'if cond is False:' or 'if not cond:' | |||||
records = cache_select( | records = cache_select( | ||||
function='verify_recipient', | function='verify_recipient', | ||||
sender=self.sender, | sender=self.sender, | ||||
recipients=self.recipients, | recipients=self.recipients, | ||||
sasl_username=self.sasl_username, | sasl_username=self.sasl_username, | ||||
sasl_sender=self.sasl_sender, | sasl_sender=self.sasl_sender, | ||||
) | ) | ||||
if not records == None and len(records) == len(self.recipients): | if not records == None and len(records) == len(self.recipients): | ||||
Lint: PEP8 E711 comparison to None should be 'if cond is None:' Lint: PEP8 E711: comparison to None should be 'if cond is None:' | |||||
log.debug("Euh, what am I doing here?") | log.debug("Euh, what am I doing here?") | ||||
for record in records: | for record in records: | ||||
recipient_found = False | recipient_found = False | ||||
for recipient in self.recipients: | for recipient in self.recipients: | ||||
if recipient == record.recipient: | if recipient == record.recipient: | ||||
recipient_found = True | recipient_found = True | ||||
if not recipient_found: | 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)) | ||||
Lint: PEP8 E501 line too long (111 > 79 characters) Lint: PEP8 E501: line too long (111 > 79 characters) | |||||
Lint: PEP8 E231 missing whitespace after ',' Lint: PEP8 E231: missing whitespace after ',' | |||||
for recipient in self.recipients: | for recipient in self.recipients: | ||||
recipient_verified = self.verify_recipient(recipient) | recipient_verified = self.verify_recipient(recipient) | ||||
if not recipient_verified: | if not recipient_verified: | ||||
recipients_verified = False | recipients_verified = False | ||||
return recipients_verified | return recipients_verified | ||||
Show All 12 Lines | def verify_sender(self): | ||||
A third potential action could be to check the recipient object to | A third potential action could be to check the recipient object to | ||||
see if the sender is allowed to send to the recipient by the | see if the sender is allowed to send to the recipient by the | ||||
recipient's kolabAllowSMTPSender, but this is done in | recipient's kolabAllowSMTPSender, but this is done in | ||||
verify_recipients(). | verify_recipients(). | ||||
""" | """ | ||||
sender_verified = False | sender_verified = False | ||||
if self.sender == None: | if self.sender == None: | ||||
Lint: PEP8 E711 comparison to None should be 'if cond is None:' Lint: PEP8 E711: comparison to None should be 'if cond is None:' | |||||
# Trusted host? | # Trusted host? | ||||
if not hasattr(self, 'client_address') or \ | if not hasattr(self, 'client_address') or \ | ||||
self.client_address == "" or \ | self.client_address == "" or \ | ||||
self.client_address == None: | self.client_address == None: | ||||
Lint: PEP8 E711 comparison to None should be 'if cond is None:' Lint: PEP8 E711: comparison to None should be 'if cond is None:' | |||||
# Nothing to compare to. | # Nothing to compare to. | ||||
return False | return False | ||||
try: | try: | ||||
import netaddr | import netaddr | ||||
networks = conf.get_list( | networks = conf.get_list( | ||||
'kolab_smtp_access_policy', | 'kolab_smtp_access_policy', | ||||
'empty_sender_hosts' | 'empty_sender_hosts' | ||||
) | ) | ||||
trusted = False | trusted = False | ||||
for network in networks: | for network in networks: | ||||
if netaddr.IPNetwork(self.client_address) in netaddr.IPNetwork(network): | if netaddr.IPNetwork(self.client_address) in netaddr.IPNetwork(network): | ||||
Lint: PEP8 E501 line too long (92 > 79 characters) Lint: PEP8 E501: line too long (92 > 79 characters) | |||||
return True | return True | ||||
except ImportError, errmsg: | except ImportError, errmsg: | ||||
return False | return False | ||||
if not cache == False: | if not cache == False: | ||||
Lint: PEP8 E712 comparison to False should be 'if cond is False:' or 'if not cond:' Lint: PEP8 E712: comparison to False should be 'if cond is False:' or 'if not cond:' | |||||
records = cache_select( | records = cache_select( | ||||
sender=self.sender, | sender=self.sender, | ||||
recipients=self.recipients, | recipients=self.recipients, | ||||
sasl_username=self.sasl_username, | sasl_username=self.sasl_username, | ||||
sasl_sender=self.sasl_sender, | sasl_sender=self.sasl_sender, | ||||
function='verify_sender' | function='verify_sender' | ||||
) | ) | ||||
if not records == None and len(records) == len(self.recipients): | if not records == None and len(records) == len(self.recipients): | ||||
Lint: PEP8 E711 comparison to None should be 'if cond is None:' Lint: PEP8 E711: comparison to None should be 'if cond is None:' | |||||
log.info(_("Reproducing verify_sender(%r) from cache") % ( | log.info(_("Reproducing verify_sender(%r) from cache") % ( | ||||
self.__dict__ | self.__dict__ | ||||
) | ) | ||||
) | ) | ||||
Lint: PEP8 E124 closing bracket does not match visual indentation Lint: PEP8 E124: closing bracket does not match visual indentation | |||||
for record in records: | for record in records: | ||||
recipient_found = False | recipient_found = False | ||||
for recipient in self.recipients: | for recipient in self.recipients: | ||||
if recipient == record.recipient: | if recipient == record.recipient: | ||||
recipient_found = True | recipient_found = True | ||||
if recipient_found and not record.value: | if recipient_found and 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)) | ||||
Lint: PEP8 E501 line too long (111 > 79 characters) Lint: PEP8 E501: line too long (111 > 79 characters) | |||||
Lint: PEP8 E231 missing whitespace after ',' Lint: PEP8 E231: missing whitespace after ',' | |||||
return True | return True | ||||
if self.verify_authenticity() == False: | if self.verify_authenticity() == False: | ||||
Lint: PEP8 E712 comparison to False should be 'if cond is False:' or 'if not cond:' Lint: PEP8 E712: comparison to False should be 'if cond is False:' or 'if not cond:' | |||||
reject(_("Unverifiable sender.")) | reject(_("Unverifiable sender.")) | ||||
self.sasl_user_uses_alias = self.verify_alias() | self.sasl_user_uses_alias = self.verify_alias() | ||||
if not self.sasl_user_uses_alias: | if not self.sasl_user_uses_alias: | ||||
log.debug(_("Sender is not using an alias"), level=8) | log.debug(_("Sender is not using an alias"), level=8) | ||||
self.sasl_user_is_delegate = self.verify_delegate() | self.sasl_user_is_delegate = self.verify_delegate() | ||||
# If the authenticated user is using delegate functionality, apply the | # If the authenticated user is using delegate functionality, apply the | ||||
# recipient policy attribute for the envelope sender. | # recipient policy attribute for the envelope sender. | ||||
if self.sasl_user_is_delegate == False and \ | if self.sasl_user_is_delegate == False and \ | ||||
Lint: PEP8 E712 comparison to False should be 'if cond is False:' or 'if not cond:' Lint: PEP8 E712: comparison to False should be 'if cond is False:' or 'if not cond:' | |||||
self.sasl_user_uses_alias == False: | self.sasl_user_uses_alias == False: | ||||
Lint: PEP8 E125 continuation line with same indent as next logical line Lint: PEP8 E125: continuation line with same indent as next logical line | |||||
reject(_("Sender uses unauthorized envelope sender address")) | reject(_("Sender uses unauthorized envelope sender address")) | ||||
elif self.sasl_user_is_delegate: | elif self.sasl_user_is_delegate: | ||||
# Apply the recipient policy for the sender using the envelope | # Apply the recipient policy for the sender using the envelope | ||||
# sender user object. | # sender user object. | ||||
recipient_policy_domain = self.sender_domain | recipient_policy_domain = self.sender_domain | ||||
recipient_policy_sender = self.sender | recipient_policy_sender = self.sender | ||||
recipient_policy_user = self.sender_user | recipient_policy_user = self.sender_user | ||||
elif not self.sasl_user == None: | elif not self.sasl_user == None: | ||||
Lint: PEP8 E711 comparison to None should be 'if cond is None:' Lint: PEP8 E711: comparison to None should be 'if cond is None:' | |||||
# Apply the recipient policy from the authenticated user. | # Apply the recipient policy from the authenticated user. | ||||
recipient_policy_domain = self.sasl_domain | recipient_policy_domain = self.sasl_domain | ||||
recipient_policy_sender = self.sasl_username | recipient_policy_sender = self.sasl_username | ||||
recipient_policy_user = self.sasl_user | recipient_policy_user = self.sasl_user | ||||
else: | else: | ||||
if not conf.allow_unauthenticated: | if not conf.allow_unauthenticated: | ||||
reject(_("Could not verify sender")) | reject(_("Could not verify sender")) | ||||
else: | else: | ||||
recipient_policy_domain = self.sender_domain | recipient_policy_domain = self.sender_domain | ||||
recipient_policy_sender = self.sender | recipient_policy_sender = self.sender | ||||
recipient_policy_user = self.sender_user | recipient_policy_user = self.sender_user | ||||
log.debug( | log.debug( | ||||
_("Verifying whether sender is allowed to send to recipient using sender policy"), | _("Verifying whether sender is allowed to send to recipient using sender policy"), | ||||
Lint: PEP8 E501 line too long (98 > 79 characters) Lint: PEP8 E501: line too long (98 > 79 characters) | |||||
level=8 | level=8 | ||||
) | ) | ||||
if recipient_policy_user.has_key('kolaballowsmtprecipient'): | if recipient_policy_user.has_key('kolaballowsmtprecipient'): | ||||
recipient_policy = recipient_policy_user['kolaballowsmtprecipient'] | recipient_policy = recipient_policy_user['kolaballowsmtprecipient'] | ||||
else: | else: | ||||
recipient_policy = self.auth.get_user_attribute( | recipient_policy = self.auth.get_user_attribute( | ||||
recipient_policy_domain, | recipient_policy_domain, | ||||
recipient_policy_user, | recipient_policy_user, | ||||
'kolabAllowSMTPRecipient' | 'kolabAllowSMTPRecipient' | ||||
) | ) | ||||
log.debug(_("Result is %r") % (recipient_policy), level=8) | log.debug(_("Result is %r") % (recipient_policy), level=8) | ||||
# If no such attribute has been specified, allow | # If no such attribute has been specified, allow | ||||
if recipient_policy == None: | if recipient_policy == None: | ||||
Lint: PEP8 E711 comparison to None should be 'if cond is None:' Lint: PEP8 E711: comparison to None should be 'if cond is None:' | |||||
log.debug( | log.debug( | ||||
_("No recipient policy restrictions exist for this sender"), | _("No recipient policy restrictions exist for this sender"), | ||||
Lint: PEP8 E501 line too long (80 > 79 characters) Lint: PEP8 E501: line too long (80 > 79 characters) | |||||
level=8 | level=8 | ||||
) | ) | ||||
sender_verified = True | sender_verified = True | ||||
# Otherwise,parse the policy obtained. | # Otherwise,parse the policy obtained. | ||||
else: | else: | ||||
log.debug( | log.debug( | ||||
_("Found a recipient policy to apply for this sender."), | _("Found a recipient policy to apply for this sender."), | ||||
level=8 | level=8 | ||||
) | ) | ||||
recipient_allowed = None | recipient_allowed = None | ||||
for recipient in self.recipients: | for recipient in self.recipients: | ||||
recipient_allowed = self.parse_policy( | recipient_allowed = self.parse_policy( | ||||
recipient_policy_sender, | recipient_policy_sender, | ||||
recipient, | recipient, | ||||
recipient_policy | recipient_policy | ||||
) | ) | ||||
if not recipient_allowed: | if not recipient_allowed: | ||||
reject( | 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) | ||||
Lint: PEP8 E501 line too long (120 > 79 characters) Lint: PEP8 E501: line too long (120 > 79 characters) | |||||
Lint: PEP8 E231 missing whitespace after ',' Lint: PEP8 E231: missing whitespace after ',' | |||||
) | ) | ||||
sender_verified = True | sender_verified = True | ||||
if not cache == False: | if not cache == False: | ||||
Lint: PEP8 E712 comparison to False should be 'if cond is False:' or 'if not cond:' Lint: PEP8 E712: comparison to False should be 'if cond is False:' or 'if not cond:' | |||||
record_id = cache_update( | record_id = cache_update( | ||||
function='verify_sender', | function='verify_sender', | ||||
sender=self.sender, | sender=self.sender, | ||||
recipients=self.recipients, | recipients=self.recipients, | ||||
result=(int)(sender_verified), | result=(int)(sender_verified), | ||||
sasl_username=self.sasl_username, | sasl_username=self.sasl_username, | ||||
sasl_sender=self.sasl_sender | sasl_sender=self.sasl_sender | ||||
) | ) | ||||
return sender_verified | return sender_verified | ||||
def cache_cleanup(): | def cache_cleanup(): | ||||
Lint: PEP8 E302 expected 2 blank lines, found 1 Lint: PEP8 E302: expected 2 blank lines, found 1 | |||||
if not cache == True: | if not cache == True: | ||||
Lint: PEP8 E712 comparison to True should be 'if cond is True:' or 'if cond:' Lint: PEP8 E712: comparison to True should be 'if cond is True:' or 'if cond:' | |||||
return | return | ||||
log.debug(_("Cleaning up the cache"), level=8) | log.debug(_("Cleaning up the cache"), level=8) | ||||
session.query( | session.query( | ||||
PolicyResult | PolicyResult | ||||
).filter( | ).filter( | ||||
PolicyResult.created < ((int)(time.time()) - cache_expire) | PolicyResult.created < ((int)(time.time()) - cache_expire) | ||||
).delete() | ).delete() | ||||
session.commit() | session.commit() | ||||
def cache_init(): | def cache_init(): | ||||
Lint: PEP8 E302 expected 2 blank lines, found 1 Lint: PEP8 E302: expected 2 blank lines, found 1 | |||||
global cache, cache_expire, session | global cache, cache_expire, session | ||||
if conf.has_section('kolab_smtp_access_policy'): | if conf.has_section('kolab_smtp_access_policy'): | ||||
if conf.has_option('kolab_smtp_access_policy', 'cache_uri'): | if conf.has_option('kolab_smtp_access_policy', 'cache_uri'): | ||||
cache_uri = conf.get('kolab_smtp_access_policy', 'cache_uri') | cache_uri = conf.get('kolab_smtp_access_policy', 'cache_uri') | ||||
cache = True | cache = True | ||||
if conf.has_option('kolab_smtp_access_policy', 'retention'): | if conf.has_option('kolab_smtp_access_policy', 'retention'): | ||||
cache_expire = (int)( | cache_expire = (int)( | ||||
conf.get( | conf.get( | ||||
'kolab_smtp_access_policy', | 'kolab_smtp_access_policy', | ||||
'retention' | 'retention' | ||||
) | ) | ||||
) | ) | ||||
elif conf.has_option('kolab_smtp_access_policy', 'uri'): | 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'")) | log.warning(_("The 'uri' setting in the kolab_smtp_access_policy section is soon going to be deprecated in favor of 'cache_uri'")) | ||||
Lint: PEP8 E501 line too long (142 > 79 characters) Lint: PEP8 E501: line too long (142 > 79 characters) | |||||
cache_uri = conf.get('kolab_smtp_access_policy', 'uri') | cache_uri = conf.get('kolab_smtp_access_policy', 'uri') | ||||
cache = True | cache = True | ||||
else: | else: | ||||
return False | return False | ||||
else: | else: | ||||
return False | return False | ||||
if conf.debuglevel > 8: | if conf.debuglevel > 8: | ||||
engine = create_engine(cache_uri, echo=True) | engine = create_engine(cache_uri, echo=True) | ||||
else: | else: | ||||
engine = create_engine(cache_uri, echo=False) | engine = create_engine(cache_uri, echo=False) | ||||
try: | try: | ||||
metadata.create_all(engine) | metadata.create_all(engine) | ||||
except sqlalchemy.exc.OperationalError, e: | except sqlalchemy.exc.OperationalError, e: | ||||
log.error(_("Operational Error in caching: %s" % (e))) | log.error(_("Operational Error in caching: %s" % (e))) | ||||
return False | return False | ||||
Session = sessionmaker(bind=engine) | Session = sessionmaker(bind=engine) | ||||
session = Session() | session = Session() | ||||
cache_cleanup() | cache_cleanup() | ||||
return cache | return cache | ||||
def cache_select( | def cache_select( | ||||
Lint: PEP8 E302 expected 2 blank lines, found 1 Lint: PEP8 E302: expected 2 blank lines, found 1 | |||||
function, | function, | ||||
sender, | sender, | ||||
recipient='', | recipient='', | ||||
recipients=[], | recipients=[], | ||||
sasl_username='', | sasl_username='', | ||||
sasl_sender='' | sasl_sender='' | ||||
): | ): | ||||
Lint: PEP8 E125 continuation line with same indent as next logical line Lint: PEP8 E125: continuation line with same indent as next logical line | |||||
if not cache == True: | if not cache == True: | ||||
Lint: PEP8 E712 comparison to True should be 'if cond is True:' or 'if cond:' Lint: PEP8 E712: comparison to True should be 'if cond is True:' or 'if cond:' | |||||
return None | return None | ||||
if not recipient == '' and recipients == []: | if not recipient == '' and recipients == []: | ||||
recipients = [recipient] | recipients = [recipient] | ||||
return session.query( | return session.query( | ||||
PolicyResult | PolicyResult | ||||
).filter_by( | ).filter_by( | ||||
key=function, | key=function, | ||||
sender=sender, | sender=sender, | ||||
sasl_username=sasl_username, | sasl_username=sasl_username, | ||||
sasl_sender=sasl_sender | sasl_sender=sasl_sender | ||||
).filter( | ).filter( | ||||
PolicyResult.recipient.in_(recipients) | PolicyResult.recipient.in_(recipients) | ||||
).filter( | ).filter( | ||||
PolicyResult.created >= \ | PolicyResult.created >= \ | ||||
Lint: PEP8 E502 the backslash is redundant between brackets Lint: PEP8 E502: the backslash is redundant between brackets | |||||
((int)(time.time()) - cache_expire) | ((int)(time.time()) - cache_expire) | ||||
Lint: PEP8 E131 continuation line unaligned for hanging indent Lint: PEP8 E131: continuation line unaligned for hanging indent | |||||
).all() | ).all() | ||||
def cache_insert( | def cache_insert( | ||||
Lint: PEP8 E302 expected 2 blank lines, found 1 Lint: PEP8 E302: expected 2 blank lines, found 1 | |||||
function, | function, | ||||
sender, | sender, | ||||
recipient='', | recipient='', | ||||
recipients=[], | recipients=[], | ||||
result=None, | result=None, | ||||
sasl_username='', | sasl_username='', | ||||
sasl_sender='' | sasl_sender='' | ||||
): | ): | ||||
Lint: PEP8 E125 continuation line with same indent as next logical line Lint: PEP8 E125: continuation line with same indent as next logical line | |||||
if not cache == True: | if not cache == True: | ||||
Lint: PEP8 E712 comparison to True should be 'if cond is True:' or 'if cond:' Lint: PEP8 E712: comparison to True should be 'if cond is True:' or 'if cond:' | |||||
return [] | return [] | ||||
log.debug( | log.debug( | ||||
_("Caching the policy result with timestamp %d") % ( | _("Caching the policy result with timestamp %d") % ( | ||||
(int)(time.time()) | (int)(time.time()) | ||||
), | ), | ||||
level=8 | level=8 | ||||
) | ) | ||||
Show All 10 Lines | for recipient in recipients: | ||||
recipient=recipient, | recipient=recipient, | ||||
sasl_username=sasl_username, | sasl_username=sasl_username, | ||||
sasl_sender=sasl_sender | sasl_sender=sasl_sender | ||||
) | ) | ||||
) | ) | ||||
session.commit() | session.commit() | ||||
def cache_update( | def cache_update( | ||||
Lint: PEP8 E302 expected 2 blank lines, found 1 Lint: PEP8 E302: expected 2 blank lines, found 1 | |||||
function, | function, | ||||
sender, | sender, | ||||
recipient='', | recipient='', | ||||
recipients=[], | recipients=[], | ||||
result=None, | result=None, | ||||
sasl_username='', | sasl_username='', | ||||
sasl_sender='' | sasl_sender='' | ||||
): | ): | ||||
Lint: PEP8 E125 continuation line with same indent as next logical line Lint: PEP8 E125: continuation line with same indent as next logical line | |||||
""" | """ | ||||
Insert an updated set of rows into the cache depending on the necessity | Insert an updated set of rows into the cache depending on the necessity | ||||
""" | """ | ||||
if not cache == True: | if not cache == True: | ||||
Lint: PEP8 E712 comparison to True should be 'if cond is True:' or 'if cond:' Lint: PEP8 E712: comparison to True should be 'if cond is True:' or 'if cond:' | |||||
return | return | ||||
records = [] | records = [] | ||||
_records = cache_select( | _records = cache_select( | ||||
function, | function, | ||||
sender, | sender, | ||||
recipient, | recipient, | ||||
Show All 19 Lines | for recipient in recipients: | ||||
function=function, | function=function, | ||||
sender=sender, | sender=sender, | ||||
recipient=recipient, | recipient=recipient, | ||||
result=result, | result=result, | ||||
sasl_username=sasl_username, | sasl_username=sasl_username, | ||||
sasl_sender=sasl_sender | sasl_sender=sasl_sender | ||||
) | ) | ||||
def defer_if_permit(message, policy_request=None): | def defer_if_permit(message, policy_request=None): | ||||
Lint: PEP8 E302 expected 2 blank lines, found 1 Lint: PEP8 E302: expected 2 blank lines, found 1 | |||||
log.info(_("Returning action DEFER_IF_PERMIT: %s") % (message)) | 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) | sys.exit(0) | ||||
def dunno(message, policy_request=None): | def dunno(message, policy_request=None): | ||||
Lint: PEP8 E302 expected 2 blank lines, found 1 Lint: PEP8 E302: expected 2 blank lines, found 1 | |||||
log.info(_("Returning action DUNNO: %s") % (message)) | log.info(_("Returning action DUNNO: %s") % (message)) | ||||
print "action=DUNNO %s\n\n" % (message) | print "action=DUNNO %s\n\n" % (message) | ||||
sys.exit(0) | sys.exit(0) | ||||
def hold(message, policy_request=None): | def hold(message, policy_request=None): | ||||
Lint: PEP8 E302 expected 2 blank lines, found 1 Lint: PEP8 E302: expected 2 blank lines, found 1 | |||||
log.info(_("Returning action HOLD: %s") % (message)) | log.info(_("Returning action HOLD: %s") % (message)) | ||||
print "action=HOLD %s\n\n" % (message) | print "action=HOLD %s\n\n" % (message) | ||||
sys.exit(0) | sys.exit(0) | ||||
def permit(message, policy_request=None): | def permit(message, policy_request=None): | ||||
Lint: PEP8 E302 expected 2 blank lines, found 1 Lint: PEP8 E302: expected 2 blank lines, found 1 | |||||
log.info(_("Returning action PERMIT: %s") % (message)) | log.info(_("Returning action PERMIT: %s") % (message)) | ||||
# If we have no policy request, we have been called for a reason, | # If we have no policy request, we have been called for a reason, | ||||
# and everything relevant has been figured out already. | # and everything relevant has been figured out already. | ||||
if policy_request == None: | if policy_request == None: | ||||
Lint: PEP8 E711 comparison to None should be 'if cond is None:' Lint: PEP8 E711: comparison to None should be 'if cond is None:' | |||||
print "action=PERMIT\n\n" | print "action=PERMIT\n\n" | ||||
sys.exit(0) | sys.exit(0) | ||||
# If the user is not authenticated, there's no reason to do | # If the user is not authenticated, there's no reason to do | ||||
# extra checks here -- to have been performed already. | # extra checks here -- to have been performed already. | ||||
if not hasattr(policy_request, 'sasl_username'): | if not hasattr(policy_request, 'sasl_username'): | ||||
print "action=PERMIT\n\n" | print "action=PERMIT\n\n" | ||||
sys.exit(0) | sys.exit(0) | ||||
# Same here. | # Same here. | ||||
if policy_request.sasl_username == None: | if policy_request.sasl_username == None: | ||||
Lint: PEP8 E711 comparison to None should be 'if cond is None:' Lint: PEP8 E711: comparison to None should be 'if cond is None:' | |||||
print "action=PERMIT\n\n" | print "action=PERMIT\n\n" | ||||
sys.exit(0) | sys.exit(0) | ||||
delegate_sender_header = None | delegate_sender_header = None | ||||
alias_sender_header = None | alias_sender_header = None | ||||
# If the sender is a delegate of the envelope sender address, take into | # If the sender is a delegate of the envelope sender address, take into | ||||
# account the preferred domain policy for appending the Sender and/or | # account the preferred domain policy for appending the Sender and/or | ||||
# X-Sender headers. | # X-Sender headers. | ||||
# | # | ||||
# Note that a delegatee by very definition is not using an alias. | # Note that a delegatee by very definition is not using an alias. | ||||
# | # | ||||
if policy_request.sasl_user_is_delegate: | if policy_request.sasl_user_is_delegate: | ||||
# Domain-specific setting? | # Domain-specific setting? | ||||
if not policy_request.sender_domain == None: | if not policy_request.sender_domain == None: | ||||
Lint: PEP8 E711 comparison to None should be 'if cond is None:' Lint: PEP8 E711: comparison to None should be 'if cond is None:' | |||||
delegate_sender_header = conf.get(policy_request.sender_domain, 'delegate_sender_header') | delegate_sender_header = conf.get(policy_request.sender_domain, 'delegate_sender_header') | ||||
Lint: PEP8 E501 line too long (101 > 79 characters) Lint: PEP8 E501: line too long (101 > 79 characters) | |||||
# Global setting? | # Global setting? | ||||
if delegate_sender_header == None: | if delegate_sender_header == None: | ||||
Lint: PEP8 E711 comparison to None should be 'if cond is None:' Lint: PEP8 E711: comparison to None should be 'if cond is None:' | |||||
delegate_sender_header = conf.get('kolab_smtp_access_policy', 'delegate_sender_header') | delegate_sender_header = conf.get('kolab_smtp_access_policy', 'delegate_sender_header') | ||||
Lint: PEP8 E501 line too long (99 > 79 characters) Lint: PEP8 E501: line too long (99 > 79 characters) | |||||
# Default | # Default | ||||
if delegate_sender_header == None: | if delegate_sender_header == None: | ||||
Lint: PEP8 E711 comparison to None should be 'if cond is None:' Lint: PEP8 E711: comparison to None should be 'if cond is None:' | |||||
delegate_sender_header = True | delegate_sender_header = True | ||||
# If the sender is using an alias as the envelope sender address, take | # If the sender is using an alias as the envelope sender address, take | ||||
# into account the preferred domain policy for appending the Sender | # into account the preferred domain policy for appending the Sender | ||||
# and/or X-Sender headers. | # and/or X-Sender headers. | ||||
elif policy_request.sasl_user_uses_alias: | elif policy_request.sasl_user_uses_alias: | ||||
# Domain-specific setting? | # Domain-specific setting? | ||||
if not policy_request.sender_domain == None: | if not policy_request.sender_domain == None: | ||||
Lint: PEP8 E711 comparison to None should be 'if cond is None:' Lint: PEP8 E711: comparison to None should be 'if cond is None:' | |||||
alias_sender_header = conf.get(policy_request.sender_domain, 'alias_sender_header') | alias_sender_header = conf.get(policy_request.sender_domain, 'alias_sender_header') | ||||
Lint: PEP8 E501 line too long (95 > 79 characters) Lint: PEP8 E501: line too long (95 > 79 characters) | |||||
# Global setting? | # Global setting? | ||||
if alias_sender_header == None: | if alias_sender_header == None: | ||||
Lint: PEP8 E711 comparison to None should be 'if cond is None:' Lint: PEP8 E711: comparison to None should be 'if cond is None:' | |||||
alias_sender_header = conf.get('kolab_smtp_access_policy', 'alias_sender_header') | alias_sender_header = conf.get('kolab_smtp_access_policy', 'alias_sender_header') | ||||
Lint: PEP8 E501 line too long (93 > 79 characters) Lint: PEP8 E501: line too long (93 > 79 characters) | |||||
# Default | # Default | ||||
if alias_sender_header == None: | if alias_sender_header == None: | ||||
Lint: PEP8 E711 comparison to None should be 'if cond is None:' Lint: PEP8 E711: comparison to None should be 'if cond is None:' | |||||
alias_sender_header = True | alias_sender_header = True | ||||
# Make the values booleans | # Make the values booleans | ||||
delegate_sender_header = utils.true_or_false(delegate_sender_header) | delegate_sender_header = utils.true_or_false(delegate_sender_header) | ||||
alias_sender_header = utils.true_or_false(alias_sender_header) | alias_sender_header = utils.true_or_false(alias_sender_header) | ||||
# Do we use a (simple) encryption key to obscure the headers' contents? | # Do we use a (simple) encryption key to obscure the headers' contents? | ||||
# Note that using an encryption key voids the actual use of proper Sender | # Note that using an encryption key voids the actual use of proper Sender | ||||
# and X-Sender headers such as they could be interpreted by a client | # and X-Sender headers such as they could be interpreted by a client | ||||
# application. | # application. | ||||
enc_key = conf.get(policy_request.sender_domain, 'sender_header_enc_key') | enc_key = conf.get(policy_request.sender_domain, 'sender_header_enc_key') | ||||
if enc_key == None: | if enc_key == None: | ||||
Lint: PEP8 E711 comparison to None should be 'if cond is None:' Lint: PEP8 E711: comparison to None should be 'if cond is None:' | |||||
enc_key = conf.get('kolab_smtp_access_policy', 'sender_header_enc_key') | enc_key = conf.get('kolab_smtp_access_policy', 'sender_header_enc_key') | ||||
sender_header = None | sender_header = None | ||||
xsender_header = None | xsender_header = None | ||||
if delegate_sender_header or alias_sender_header: | if delegate_sender_header or alias_sender_header: | ||||
# Domain specific? | # Domain specific? | ||||
sender_header = conf.get(policy_request.sender_domain, 'sender_header') | sender_header = conf.get(policy_request.sender_domain, 'sender_header') | ||||
# Global setting? | # Global setting? | ||||
if sender_header == None: | if sender_header == None: | ||||
Lint: PEP8 E711 comparison to None should be 'if cond is None:' Lint: PEP8 E711: comparison to None should be 'if cond is None:' | |||||
sender_header = conf.get('kolab_smtp_access_policy', 'sender_header') | sender_header = conf.get('kolab_smtp_access_policy', 'sender_header') | ||||
Lint: PEP8 E501 line too long (81 > 79 characters) Lint: PEP8 E501: line too long (81 > 79 characters) | |||||
# Default | # Default | ||||
if sender_header == None: | if sender_header == None: | ||||
Lint: PEP8 E711 comparison to None should be 'if cond is None:' Lint: PEP8 E711: comparison to None should be 'if cond is None:' | |||||
sender_header = True | sender_header = True | ||||
# Domain specific? | # Domain specific? | ||||
xsender_header = conf.get(policy_request.sender_domain, 'xsender_header') | xsender_header = conf.get(policy_request.sender_domain, 'xsender_header') | ||||
Lint: PEP8 E501 line too long (81 > 79 characters) Lint: PEP8 E501: line too long (81 > 79 characters) | |||||
# Global setting? | # Global setting? | ||||
if xsender_header == None: | if xsender_header == None: | ||||
Lint: PEP8 E711 comparison to None should be 'if cond is None:' Lint: PEP8 E711: comparison to None should be 'if cond is None:' | |||||
xsender_header = conf.get('kolab_smtp_access_policy', 'xsender_header') | xsender_header = conf.get('kolab_smtp_access_policy', 'xsender_header') | ||||
Lint: PEP8 E501 line too long (83 > 79 characters) Lint: PEP8 E501: line too long (83 > 79 characters) | |||||
# Default | # Default | ||||
if xsender_header == None: | if xsender_header == None: | ||||
Lint: PEP8 E711 comparison to None should be 'if cond is None:' Lint: PEP8 E711: comparison to None should be 'if cond is None:' | |||||
xsender_header = True | xsender_header = True | ||||
# Note that if the user is not a delegatee, and not using an alias, the sender | # Note that if the user is not a delegatee, and not using an alias, the sender | ||||
Lint: PEP8 E501 line too long (82 > 79 characters) Lint: PEP8 E501: line too long (82 > 79 characters) | |||||
# address is the envelope sender address, and the defaults for sender_header | # address is the envelope sender address, and the defaults for sender_header | ||||
Lint: PEP8 E501 line too long (80 > 79 characters) Lint: PEP8 E501: line too long (80 > 79 characters) | |||||
# and xsender_header being None, ultimately evaluating to False seems | # and xsender_header being None, ultimately evaluating to False seems | ||||
# appropriate. | # appropriate. | ||||
# Make the values booleans | # Make the values booleans | ||||
sender_header = utils.true_or_false(sender_header) | sender_header = utils.true_or_false(sender_header) | ||||
xsender_header = utils.true_or_false(xsender_header) | xsender_header = utils.true_or_false(xsender_header) | ||||
if sender_header or xsender_header: | if sender_header or xsender_header: | ||||
# Do the encoding, if any | # Do the encoding, if any | ||||
if not enc_key == None: | if not enc_key == None: | ||||
Lint: PEP8 E711 comparison to None should be 'if cond is None:' Lint: PEP8 E711: comparison to None should be 'if cond is None:' | |||||
header = 'X-Authenticated-As' | header = 'X-Authenticated-As' | ||||
xheader = None | xheader = None | ||||
sender = utils.encode(enc_key, policy_request.sasl_username) | sender = utils.encode(enc_key, policy_request.sasl_username) | ||||
else: | else: | ||||
header = 'Sender' | header = 'Sender' | ||||
xheader = 'X-Sender' | xheader = 'X-Sender' | ||||
sender = policy_request.sasl_username | sender = policy_request.sasl_username | ||||
if sender_header: | if sender_header: | ||||
print "action=PREPEND %s: %s" % (header, sender) | print "action=PREPEND %s: %s" % (header, sender) | ||||
if xsender_header and not xheader == None: | if xsender_header and not xheader == None: | ||||
Lint: PEP8 E711 comparison to None should be 'if cond is None:' Lint: PEP8 E711: comparison to None should be 'if cond is None:' | |||||
print "action=PREPEND %s: %s" % (xheader, sender) | print "action=PREPEND %s: %s" % (xheader, sender) | ||||
print "action=PERMIT\n\n" | print "action=PERMIT\n\n" | ||||
sys.exit(0) | sys.exit(0) | ||||
def reject(message, policy_request=None): | def reject(message, policy_request=None): | ||||
Lint: PEP8 E302 expected 2 blank lines, found 1 Lint: PEP8 E302: expected 2 blank lines, found 1 | |||||
log.info(_("Returning action REJECT: %s") % (message)) | log.info(_("Returning action REJECT: %s") % (message)) | ||||
print "action=REJECT %s\n\n" % (message) | print "action=REJECT %s\n\n" % (message) | ||||
sys.exit(0) | sys.exit(0) | ||||
def expand_mydomains(): | def expand_mydomains(): | ||||
Lint: PEP8 E302 expected 2 blank lines, found 1 Lint: PEP8 E302: expected 2 blank lines, found 1 | |||||
""" | """ | ||||
Return a list of my domains. | Return a list of my domains. | ||||
""" | """ | ||||
global auth,mydomains | global auth,mydomains | ||||
Lint: PEP8 E231 missing whitespace after ',' Lint: PEP8 E231: missing whitespace after ',' | |||||
if not mydomains == None: | if not mydomains == None: | ||||
Lint: PEP8 E711 comparison to None should be 'if cond is None:' Lint: PEP8 E711: comparison to None should be 'if cond is None:' | |||||
return mydomains | return mydomains | ||||
auth.connect() | auth.connect() | ||||
mydomains = auth.list_domains() | mydomains = auth.list_domains() | ||||
return mydomains.keys() | return mydomains.keys() | ||||
def normalize_address(email_address): | def normalize_address(email_address): | ||||
Lint: PEP8 E302 expected 2 blank lines, found 1 Lint: PEP8 E302: expected 2 blank lines, found 1 | |||||
""" | """ | ||||
Parse an address; Strip off anything after a recipient delimiter. | Parse an address; Strip off anything after a recipient delimiter. | ||||
""" | """ | ||||
# TODO: Recipient delimiter is configurable. | # TODO: Recipient delimiter is configurable. | ||||
if len(email_address.split("+")) > 1: | if len(email_address.split("+")) > 1: | ||||
# Take the first part split by recipient delimiter and the last part | # Take the first part split by recipient delimiter and the last part | ||||
# split by '@'. | # split by '@'. | ||||
return "%s@%s" % ( | return "%s@%s" % ( | ||||
email_address.split("+")[0].lower(), | email_address.split("+")[0].lower(), | ||||
# TODO: Under some conditions, the recipient may not be fully | # TODO: Under some conditions, the recipient may not be fully | ||||
# qualified. We'll cross that bridge when we get there, though. | # qualified. We'll cross that bridge when we get there, though. | ||||
email_address.split('@')[1].lower() | email_address.split('@')[1].lower() | ||||
) | ) | ||||
else: | else: | ||||
return email_address.lower() | return email_address.lower() | ||||
def read_request_input(): | def read_request_input(): | ||||
Lint: PEP8 E302 expected 2 blank lines, found 1 Lint: PEP8 E302: expected 2 blank lines, found 1 | |||||
""" | """ | ||||
Read a single policy request from sys.stdin, and return a dictionary | Read a single policy request from sys.stdin, and return a dictionary | ||||
containing the request. | containing the request. | ||||
""" | """ | ||||
start_time = time.time() | start_time = time.time() | ||||
log.debug(_("Starting to loop for new request")) | log.debug(_("Starting to loop for new request")) | ||||
Show All 16 Lines | while not end_of_request: | ||||
log.debug(_("Getting line: %s") % (request_line), level=8) | log.debug(_("Getting line: %s") % (request_line), level=8) | ||||
policy_request[request_line.split('=')[0]] = \ | policy_request[request_line.split('=')[0]] = \ | ||||
'='.join(request_line.split('=')[1:]).lower() | '='.join(request_line.split('=')[1:]).lower() | ||||
log.debug(_("Returning request")) | log.debug(_("Returning request")) | ||||
return policy_request | return policy_request | ||||
def verify_domain(domain): | def verify_domain(domain): | ||||
Lint: PEP8 E302 expected 2 blank lines, found 1 Lint: PEP8 E302: expected 2 blank lines, found 1 | |||||
""" | """ | ||||
Verify whether the domain is internal (mine) or external. | Verify whether the domain is internal (mine) or external. | ||||
""" | """ | ||||
global auth,mydomains | global auth,mydomains | ||||
Lint: PEP8 E231 missing whitespace after ',' Lint: PEP8 E231: missing whitespace after ',' | |||||
if not mydomains == None: | if not mydomains == None: | ||||
Lint: PEP8 E711 comparison to None should be 'if cond is None:' Lint: PEP8 E711: comparison to None should be 'if cond is None:' | |||||
return domain in mydomains.keys() | return domain in mydomains.keys() | ||||
auth.connect() | auth.connect() | ||||
domain_verified = False | domain_verified = False | ||||
mydomains = auth.list_domains() | mydomains = auth.list_domains() | ||||
if not mydomains == None and mydomains.has_key(domain): | if not mydomains == None and mydomains.has_key(domain): | ||||
Lint: PEP8 E711 comparison to None should be 'if cond is None:' Lint: PEP8 E711: comparison to None should be 'if cond is None:' | |||||
domain_verified = True | domain_verified = True | ||||
else: | else: | ||||
domain_verified = False | domain_verified = False | ||||
return domain_verified | return domain_verified | ||||
if __name__ == "__main__": | if __name__ == "__main__": | ||||
access_policy_group = conf.add_cli_parser_option_group( | access_policy_group = conf.add_cli_parser_option_group( | ||||
_("Access Policy Options") | _("Access Policy Options") | ||||
) | ) | ||||
access_policy_group.add_option( "--timeout", | access_policy_group.add_option( "--timeout", | ||||
Lint: PEP8 E201 whitespace after '(' Lint: PEP8 E201: whitespace after '(' | |||||
dest = "timeout", | dest = "timeout", | ||||
Lint: PEP8 E128 continuation line under-indented for visual indent Lint: PEP8 E128: continuation line under-indented for visual indent | |||||
Lint: PEP8 E251 unexpected spaces around keyword / parameter equals Lint: PEP8 E251: unexpected spaces around keyword / parameter equals | |||||
Lint: PEP8 E221 multiple spaces before operator Lint: PEP8 E221: multiple spaces before operator | |||||
Lint: PEP8 E251 unexpected spaces around keyword / parameter equals Lint: PEP8 E251: unexpected spaces around keyword / parameter equals | |||||
action = "store", | action = "store", | ||||
Lint: PEP8 E128 continuation line under-indented for visual indent Lint: PEP8 E128: continuation line under-indented for visual indent | |||||
Lint: PEP8 E221 multiple spaces before operator Lint: PEP8 E221: multiple spaces before operator | |||||
Lint: PEP8 E251 unexpected spaces around keyword / parameter equals Lint: PEP8 E251: unexpected spaces around keyword / parameter equals | |||||
Lint: PEP8 E251 unexpected spaces around keyword / parameter equals Lint: PEP8 E251: unexpected spaces around keyword / parameter equals | |||||
default = 10, | default = 10, | ||||
Lint: PEP8 E128 continuation line under-indented for visual indent Lint: PEP8 E128: continuation line under-indented for visual indent | |||||
Lint: PEP8 E251 unexpected spaces around keyword / parameter equals Lint: PEP8 E251: unexpected spaces around keyword / parameter equals | |||||
Lint: PEP8 E251 unexpected spaces around keyword / parameter equals Lint: PEP8 E251: unexpected spaces around keyword / parameter equals | |||||
help = _("SMTP Policy request timeout.")) | help = _("SMTP Policy request timeout.")) | ||||
Lint: PEP8 E128 continuation line under-indented for visual indent Lint: PEP8 E128: continuation line under-indented for visual indent | |||||
Lint: PEP8 E221 multiple spaces before operator Lint: PEP8 E221: multiple spaces before operator | |||||
Lint: PEP8 E251 unexpected spaces around keyword / parameter equals Lint: PEP8 E251: unexpected spaces around keyword / parameter equals | |||||
Lint: PEP8 E251 unexpected spaces around keyword / parameter equals Lint: PEP8 E251: unexpected spaces around keyword / parameter equals | |||||
access_policy_group.add_option( "--verify-recipient", | access_policy_group.add_option( "--verify-recipient", | ||||
Lint: PEP8 E201 whitespace after '(' Lint: PEP8 E201: whitespace after '(' | |||||
dest = "verify_recipient", | dest = "verify_recipient", | ||||
Lint: PEP8 E128 continuation line under-indented for visual indent Lint: PEP8 E128: continuation line under-indented for visual indent | |||||
Lint: PEP8 E221 multiple spaces before operator Lint: PEP8 E221: multiple spaces before operator | |||||
Lint: PEP8 E251 unexpected spaces around keyword / parameter equals Lint: PEP8 E251: unexpected spaces around keyword / parameter equals | |||||
Lint: PEP8 E251 unexpected spaces around keyword / parameter equals Lint: PEP8 E251: unexpected spaces around keyword / parameter equals | |||||
action = "store_true", | action = "store_true", | ||||
Lint: PEP8 E128 continuation line under-indented for visual indent Lint: PEP8 E128: continuation line under-indented for visual indent | |||||
Lint: PEP8 E221 multiple spaces before operator Lint: PEP8 E221: multiple spaces before operator | |||||
Lint: PEP8 E251 unexpected spaces around keyword / parameter equals Lint: PEP8 E251: unexpected spaces around keyword / parameter equals | |||||
Lint: PEP8 E251 unexpected spaces around keyword / parameter equals Lint: PEP8 E251: unexpected spaces around keyword / parameter equals | |||||
default = False, | default = False, | ||||
Lint: PEP8 E128 continuation line under-indented for visual indent Lint: PEP8 E128: continuation line under-indented for visual indent | |||||
Lint: PEP8 E251 unexpected spaces around keyword / parameter equals Lint: PEP8 E251: unexpected spaces around keyword / parameter equals | |||||
Lint: PEP8 E251 unexpected spaces around keyword / parameter equals Lint: PEP8 E251: unexpected spaces around keyword / parameter equals | |||||
help = _("Verify the recipient access policy.")) | help = _("Verify the recipient access policy.")) | ||||
Lint: PEP8 E128 continuation line under-indented for visual indent Lint: PEP8 E128: continuation line under-indented for visual indent | |||||
Lint: PEP8 E221 multiple spaces before operator Lint: PEP8 E221: multiple spaces before operator | |||||
Lint: PEP8 E251 unexpected spaces around keyword / parameter equals Lint: PEP8 E251: unexpected spaces around keyword / parameter equals | |||||
Lint: PEP8 E251 unexpected spaces around keyword / parameter equals Lint: PEP8 E251: unexpected spaces around keyword / parameter equals | |||||
access_policy_group.add_option( "--verify-sender", | access_policy_group.add_option( "--verify-sender", | ||||
Lint: PEP8 E201 whitespace after '(' Lint: PEP8 E201: whitespace after '(' | |||||
dest = "verify_sender", | dest = "verify_sender", | ||||
Lint: PEP8 E128 continuation line under-indented for visual indent Lint: PEP8 E128: continuation line under-indented for visual indent | |||||
Lint: PEP8 E221 multiple spaces before operator Lint: PEP8 E221: multiple spaces before operator | |||||
Lint: PEP8 E251 unexpected spaces around keyword / parameter equals Lint: PEP8 E251: unexpected spaces around keyword / parameter equals | |||||
Lint: PEP8 E251 unexpected spaces around keyword / parameter equals Lint: PEP8 E251: unexpected spaces around keyword / parameter equals | |||||
action = "store_true", | action = "store_true", | ||||
Lint: PEP8 E128 continuation line under-indented for visual indent Lint: PEP8 E128: continuation line under-indented for visual indent | |||||
Lint: PEP8 E221 multiple spaces before operator Lint: PEP8 E221: multiple spaces before operator | |||||
Lint: PEP8 E251 unexpected spaces around keyword / parameter equals Lint: PEP8 E251: unexpected spaces around keyword / parameter equals | |||||
Lint: PEP8 E251 unexpected spaces around keyword / parameter equals Lint: PEP8 E251: unexpected spaces around keyword / parameter equals | |||||
default = False, | default = False, | ||||
Lint: PEP8 E128 continuation line under-indented for visual indent Lint: PEP8 E128: continuation line under-indented for visual indent | |||||
Lint: PEP8 E251 unexpected spaces around keyword / parameter equals Lint: PEP8 E251: unexpected spaces around keyword / parameter equals | |||||
Lint: PEP8 E251 unexpected spaces around keyword / parameter equals Lint: PEP8 E251: unexpected spaces around keyword / parameter equals | |||||
help = _("Verify the sender access policy.")) | help = _("Verify the sender access policy.")) | ||||
Lint: PEP8 E128 continuation line under-indented for visual indent Lint: PEP8 E128: continuation line under-indented for visual indent | |||||
Lint: PEP8 E221 multiple spaces before operator Lint: PEP8 E221: multiple spaces before operator | |||||
Lint: PEP8 E251 unexpected spaces around keyword / parameter equals Lint: PEP8 E251: unexpected spaces around keyword / parameter equals | |||||
Lint: PEP8 E251 unexpected spaces around keyword / parameter equals Lint: PEP8 E251: unexpected spaces around keyword / parameter equals | |||||
access_policy_group.add_option( "--allow-unauthenticated", | access_policy_group.add_option( "--allow-unauthenticated", | ||||
Lint: PEP8 E201 whitespace after '(' Lint: PEP8 E201: whitespace after '(' | |||||
dest = "allow_unauthenticated", | dest = "allow_unauthenticated", | ||||
Lint: PEP8 E128 continuation line under-indented for visual indent Lint: PEP8 E128: continuation line under-indented for visual indent | |||||
Lint: PEP8 E221 multiple spaces before operator Lint: PEP8 E221: multiple spaces before operator | |||||
Lint: PEP8 E251 unexpected spaces around keyword / parameter equals Lint: PEP8 E251: unexpected spaces around keyword / parameter equals | |||||
Lint: PEP8 E251 unexpected spaces around keyword / parameter equals Lint: PEP8 E251: unexpected spaces around keyword / parameter equals | |||||
action = "store_true", | action = "store_true", | ||||
Lint: PEP8 E128 continuation line under-indented for visual indent Lint: PEP8 E128: continuation line under-indented for visual indent | |||||
Lint: PEP8 E221 multiple spaces before operator Lint: PEP8 E221: multiple spaces before operator | |||||
Lint: PEP8 E251 unexpected spaces around keyword / parameter equals Lint: PEP8 E251: unexpected spaces around keyword / parameter equals | |||||
Lint: PEP8 E251 unexpected spaces around keyword / parameter equals Lint: PEP8 E251: unexpected spaces around keyword / parameter equals | |||||
default = False, | default = False, | ||||
Lint: PEP8 E128 continuation line under-indented for visual indent Lint: PEP8 E128: continuation line under-indented for visual indent | |||||
Lint: PEP8 E251 unexpected spaces around keyword / parameter equals Lint: PEP8 E251: unexpected spaces around keyword / parameter equals | |||||
Lint: PEP8 E251 unexpected spaces around keyword / parameter equals Lint: PEP8 E251: unexpected spaces around keyword / parameter equals | |||||
help = _("Allow unauthenticated senders.")) | help = _("Allow unauthenticated senders.")) | ||||
Lint: PEP8 E128 continuation line under-indented for visual indent Lint: PEP8 E128: continuation line under-indented for visual indent | |||||
Lint: PEP8 E221 multiple spaces before operator Lint: PEP8 E221: multiple spaces before operator | |||||
Lint: PEP8 E251 unexpected spaces around keyword / parameter equals Lint: PEP8 E251: unexpected spaces around keyword / parameter equals | |||||
Lint: PEP8 E251 unexpected spaces around keyword / parameter equals Lint: PEP8 E251: unexpected spaces around keyword / parameter equals | |||||
conf.finalize_conf() | conf.finalize_conf() | ||||
auth = Auth() | auth = Auth() | ||||
cache = cache_init() | cache = cache_init() | ||||
policy_requests = {} | policy_requests = {} | ||||
▲ Show 20 Lines • Show All 63 Lines • Show Last 20 Lines |
module level import not at top of file