Changeset View
Changeset View
Standalone View
Standalone View
bin/kolab_smtp_access_policy.py
Show All 32 Lines | |||||
from sqlalchemy import Column | from sqlalchemy import Column | ||||
from sqlalchemy import Date | from sqlalchemy import Date | ||||
from sqlalchemy import DateTime | from sqlalchemy import DateTime | ||||
from sqlalchemy import Integer | from sqlalchemy import Integer | ||||
from sqlalchemy import MetaData | from sqlalchemy import MetaData | ||||
from sqlalchemy import String | from sqlalchemy import String | ||||
from sqlalchemy import Table | from sqlalchemy import Table | ||||
from sqlalchemy import Sequence | from sqlalchemy import Sequence | ||||
from sqlalchemy import PickleType | |||||
from sqlalchemy import create_engine | from sqlalchemy import create_engine | ||||
from sqlalchemy.orm import mapper | from sqlalchemy.orm import mapper | ||||
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 | ||||
Show All 39 Lines | policy_result_table = Table( | ||||
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=True), | 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), | ||||
Column('data', PickleType, nullable=True), | |||||
) | ) | ||||
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): | ||||
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, | ||||
data=None | |||||
): | ): | ||||
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()) | ||||
self.data = data | |||||
mapper(PolicyResult, policy_result_table) | mapper(PolicyResult, policy_result_table) | ||||
statistic_table = Table( | statistic_table = Table( | ||||
'statistic', metadata, | 'statistic', metadata, | ||||
Column('id', Integer, Sequence('seq_id_statistic'), primary_key=True), | Column('id', Integer, Sequence('seq_id_statistic'), primary_key=True), | ||||
Column('sender', String(64), nullable=False), | Column('sender', String(64), nullable=False), | ||||
Column('recipient', String(64), nullable=False), | Column('recipient', String(64), nullable=False), | ||||
▲ Show 20 Lines • Show All 922 Lines • ▼ Show 20 Lines | def verify_sender(self): | ||||
) | ) | ||||
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: | ||||
if not record.value: | |||||
reject(_("Sender %s is not allowed to send to recipient %s") % (self.sender,recipient)) | reject(_("Sender %s is not allowed to send to recipient %s") % (self.sender,recipient)) | ||||
if record.data is not None: | |||||
self.__dict__.update(record.data) | |||||
return True | return True | ||||
if self.verify_authenticity() == False: | if self.verify_authenticity() == False: | ||||
reject(_("Unverifiable sender.")) | reject(_("Unverifiable sender.")) | ||||
self.sasl_user_uses_alias = self.verify_alias() | self.sasl_user_uses_alias = self.verify_alias() | ||||
▲ Show 20 Lines • Show All 73 Lines • ▼ Show 20 Lines | def verify_sender(self): | ||||
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) | ||||
) | ) | ||||
sender_verified = True | sender_verified = True | ||||
if not cache == False: | if not cache == False: | ||||
data = { | |||||
'sasl_user_uses_alias': self.sasl_user_uses_alias, | |||||
'sasl_user_is_delegate': self.sasl_user_is_delegate, | |||||
'sender_domain': self.sender_domain, | |||||
} | |||||
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, | ||||
data=data | |||||
) | ) | ||||
return sender_verified | return sender_verified | ||||
def cache_cleanup(): | def cache_cleanup(): | ||||
if not cache == True: | if not cache == True: | ||||
return | return | ||||
▲ Show 20 Lines • Show All 76 Lines • ▼ Show 20 Lines | |||||
def cache_insert( | def cache_insert( | ||||
function, | function, | ||||
sender, | sender, | ||||
recipient='', | recipient='', | ||||
recipients=[], | recipients=[], | ||||
result=None, | result=None, | ||||
sasl_username='', | sasl_username='', | ||||
sasl_sender='' | sasl_sender='', | ||||
data=None | |||||
): | ): | ||||
if not cache == True: | if not cache == True: | ||||
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 | ||||
) | ) | ||||
if not recipient == '' and recipients == []: | if not recipient == '' and recipients == []: | ||||
recipients = [recipient] | recipients = [recipient] | ||||
for recipient in recipients: | for recipient in recipients: | ||||
session.add( | session.add( | ||||
PolicyResult( | PolicyResult( | ||||
key=function, | key=function, | ||||
value=result, | value=result, | ||||
sender=sender, | sender=sender, | ||||
recipient=recipient, | recipient=recipient, | ||||
sasl_username=sasl_username, | sasl_username=sasl_username, | ||||
sasl_sender=sasl_sender | sasl_sender=sasl_sender, | ||||
data=data | |||||
) | ) | ||||
) | ) | ||||
session.commit() | session.commit() | ||||
def cache_update( | def cache_update( | ||||
function, | function, | ||||
sender, | sender, | ||||
recipient='', | recipient='', | ||||
recipients=[], | recipients=[], | ||||
result=None, | result=None, | ||||
sasl_username='', | sasl_username='', | ||||
sasl_sender='' | sasl_sender='', | ||||
data=None | |||||
): | ): | ||||
""" | """ | ||||
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: | ||||
return | return | ||||
Show All 23 Lines | for recipient in recipients: | ||||
recipient_found = True | recipient_found = True | ||||
if not recipient_found: | if not recipient_found: | ||||
cache_insert( | cache_insert( | ||||
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, | ||||
data=data | |||||
) | ) | ||||
def defer_if_permit(message, policy_request=None): | def defer_if_permit(message, policy_request=None): | ||||
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): | ||||
▲ Show 20 Lines • Show All 67 Lines • ▼ Show 20 Lines | def permit(message, policy_request=None): | ||||
# 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 = None | |||||
if policy_request.sender_domain is not None: | |||||
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 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') | ||||
▲ Show 20 Lines • Show All 193 Lines • ▼ Show 20 Lines | while True: | ||||
log.debug( | log.debug( | ||||
_("Request instance %s is in state %s") % ( | _("Request instance %s is in state %s") % ( | ||||
instance, | instance, | ||||
protocol_state | protocol_state | ||||
) | ) | ||||
) | ) | ||||
if not protocol_state == 'data': | if not protocol_state == 'data': | ||||
log.debug( | |||||
_("Request instance %s is not yet in DATA state") % ( | |||||
instance | |||||
) | |||||
) | |||||
print "action=DUNNO\n\n" | print "action=DUNNO\n\n" | ||||
sys.stdout.flush() | sys.stdout.flush() | ||||
# We can recognize being in the DATA part by the recipient_count being | # We can recognize being in the DATA part by the recipient_count being | ||||
# set to a non-zero value and the protocol_state being set to 'data'. | # set to a non-zero value and the protocol_state being set to 'data'. | ||||
# Note that the input we're getting is a string, not an integer. | # Note that the input we're getting is a string, not an integer. | ||||
else: | else: | ||||
log.debug(_("Request instance %s reached DATA state") % (instance)) | |||||
sender_allowed = False | sender_allowed = False | ||||
recipient_allowed = False | recipient_allowed = False | ||||
try: | try: | ||||
if conf.verify_sender: | if conf.verify_sender: | ||||
sender_allowed = policy_requests[instance].verify_sender() | sender_allowed = policy_requests[instance].verify_sender() | ||||
else: | else: | ||||
sender_allowed = True | sender_allowed = True | ||||
Show All 19 Lines |