Source

iredapd / iredapd.py

Zhang Huangbin e85694f 










Zhang Huangbin c39c38a 

Zhang Huangbin e85694f 


Zhang Huangbin c39c38a 
Zhang Huangbin 6962a9a 
Zhang Huangbin c39c38a 
Zhang Huangbin 6962a9a 
Zhang Huangbin e85694f 





Zhang Huangbin c39c38a 
Zhang Huangbin 3cd5f78 








Zhang Huangbin e85694f 

Zhang Huangbin 6a6022a 
Zhang Huangbin e85694f 
Zhang Huangbin 3cd5f78 






Zhang Huangbin e85694f 













Zhang Huangbin 6a6022a 

Zhang Huangbin e85694f 
Zhang Huangbin c39c38a 
Zhang Huangbin 6a6022a 
Zhang Huangbin 3cd5f78 






Zhang Huangbin e85694f 





Zhang Huangbin 3cd5f78 
Zhang Huangbin e85694f 

Zhang Huangbin 6a6022a 


Zhang Huangbin e85694f 








Zhang Huangbin 3cd5f78 
Zhang Huangbin e85694f 



Zhang Huangbin c39c38a 
Zhang Huangbin bd05693 
Zhang Huangbin e85694f 





Zhang Huangbin c39c38a 
Zhang Huangbin 3cd5f78 




























Zhang Huangbin e85694f 


Zhang Huangbin 3cd5f78 








Zhang Huangbin e85694f 






Zhang Huangbin c39c38a 
Zhang Huangbin e85694f 

Zhang Huangbin c39c38a 

Zhang Huangbin e85694f 
Zhang Huangbin c39c38a 




Zhang Huangbin e85694f 

Zhang Huangbin c39c38a 



Zhang Huangbin e85694f 

Zhang Huangbin c39c38a 
Zhang Huangbin e85694f 

Zhang Huangbin c39c38a 
Zhang Huangbin e85694f 


Zhang Huangbin c39c38a 
Zhang Huangbin e85694f 


Zhang Huangbin c39c38a 
Zhang Huangbin e85694f 











# Author: Zhang Huangbin <zhb _at_ iredmail.org>

import os
import os.path
import sys
import pwd
import socket
import asyncore
import asynchat
import logging

import settings

# Append plugin directory.
sys.path.append(os.path.abspath(os.path.dirname(__file__)) + '/plugins')

if settings.backend == 'ldap':
    from libs.ldaplib.modeler import Modeler
elif settings.backend in ['mysql', 'pgsql']:
    from libs.sql.modeler import Modeler
else:
    sys.exit('Invalid backend, it must be ldap, mysql or pgsql.')

from libs import __version__, SMTP_ACTIONS, daemon


class PolicyChannel(asynchat.async_chat):
    def __init__(self,
                 conn,
                 plugins=[],
                 plugins_for_sender=[],
                 plugins_for_recipient=[],
                 plugins_for_misc=[],
                 sender_search_attrlist=None,
                 recipient_search_attrlist=None,
                ):
        asynchat.async_chat.__init__(self, conn)
        self.buffer = []
        self.smtp_session_data = {}
        self.set_terminator('\n')

        self.plugins = plugins
        self.plugins_for_sender = plugins_for_sender
        self.plugins_for_recipient = plugins_for_recipient
        self.plugins_for_misc = plugins_for_misc
        self.sender_search_attrlist = sender_search_attrlist
        self.recipient_search_attrlist = recipient_search_attrlist

    def push(self, msg):
        asynchat.async_chat.push(self, msg + '\n')

    def collect_incoming_data(self, data):
        self.buffer.append(data)

    def found_terminator(self):
        if self.buffer:
            line = self.buffer.pop()
            logging.debug("smtp session: " + line)
            if line.find('=') != -1:
                key = line.split('=')[0]
                value = line.split('=', 1)[1]
                self.smtp_session_data[key] = value
        elif len(self.smtp_session_data) != 0:
            try:
                modeler = Modeler()
                result = modeler.handle_data(smtp_session_data=self.smtp_session_data,
                                             plugins=self.plugins,
                                             plugins_for_sender=self.plugins_for_sender,
                                             plugins_for_recipient=self.plugins_for_recipient,
                                             plugins_for_misc=self.plugins_for_misc,
                                             sender_search_attrlist=self.sender_search_attrlist,
                                             recipient_search_attrlist=self.recipient_search_attrlist,
                                            )
                if result:
                    action = result
                else:
                    action = SMTP_ACTIONS['default']
            except Exception, e:
                action = SMTP_ACTIONS['default']
                logging.debug('Unexpected error: %s. Fallback to default action: %s' % (str(e), str(action)))

            # Log final action.
            logging.info('[%s] %s -> %s, %s' % (self.smtp_session_data['client_address'],
                                                self.smtp_session_data['sender'],
                                                self.smtp_session_data['recipient'],
                                                action,
                                               ))

            self.push('action=' + action + '\n')
            asynchat.async_chat.handle_close(self)
            logging.debug("Connection closed")
        else:
            action = SMTP_ACTIONS['defer']
            logging.debug("replying: " + action)
            self.push('action=' + action + '\n')
            asynchat.async_chat.handle_close(self)
            logging.debug("Connection closed")


class DaemonSocket(asyncore.dispatcher):
    def __init__(self, localaddr):
        asyncore.dispatcher.__init__(self)
        self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
        self.set_reuse_addr()
        self.bind(localaddr)
        self.listen(5)
        ip, port = localaddr
        logging.info("Starting iRedAPD (version %s, %s backend), listening on %s:%d." % (__version__, settings.backend, ip, port))

        # Load plugins.
        self.loaded_plugins = []
        for plugin in settings.plugins:
            try:
                self.loaded_plugins.append(__import__(plugin))
                logging.info('Loading plugin: %s' % (plugin))
            except Exception, e:
                logging.error('Error while loading plugin (%s): %s' % (plugin, str(e)))

        self.plugins_for_sender = [plugin
                                   for plugin in self.loaded_plugins
                                   if plugin.REQUIRE_LOCAL_SENDER]

        self.plugins_for_recipient = [plugin
                                   for plugin in self.loaded_plugins
                                   if plugin.REQUIRE_LOCAL_RECIPIENT]

        self.plugins_for_misc = [plugin for plugin in self.loaded_plugins
                                 if plugin not in self.plugins_for_sender
                                 and plugin not in self.plugins_for_recipient]

        self.sender_search_attrlist = ['objectClass']
        for plugin in self.plugins_for_sender:
            self.sender_search_attrlist += plugin.SENDER_SEARCH_ATTRLIST

        self.recipient_search_attrlist = ['objectClass']
        for plugin in self.plugins_for_recipient:
            self.recipient_search_attrlist += plugin.RECIPIENT_SEARCH_ATTRLIST

    def handle_accept(self):
        conn, remote_addr = self.accept()
        logging.debug("Connect from %s, port %s." % remote_addr)
        channel = PolicyChannel(conn,
                                plugins=self.loaded_plugins,
                                plugins_for_sender=self.plugins_for_sender,
                                plugins_for_recipient=self.plugins_for_recipient,
                                plugins_for_misc=self.plugins_for_misc,
                                sender_search_attrlist=self.sender_search_attrlist,
                                recipient_search_attrlist=self.recipient_search_attrlist,
                               )


def main():
    # Set umask.
    os.umask(0077)

    # Get log level.
    log_level = getattr(logging, str(settings.log_level).upper())

    # Initialize file based logger.
    if settings.log_type == 'file':
        if settings.run_as_daemon:
            logging.basicConfig(
                level=log_level,
                format='%(asctime)s %(levelname)s %(message)s',
                datefmt='%Y-%m-%d %H:%M:%S',
                filename=settings.log_file,
            )
        else:
            logging.basicConfig(
                level=log_level,
                format='%(asctime)s %(levelname)s %(message)s',
                datefmt='%Y-%m-%d %H:%M:%S',
            )

    # Initialize policy daemon.
    socket_daemon = DaemonSocket((settings.listen_address, settings.listen_port))

    # Run this program as daemon.
    if settings.run_as_daemon:
        daemon.daemonize()

    # Run as a low privileged user.
    uid = pwd.getpwnam(settings.run_as_user)[2]

    try:
        # Write pid number into pid file.
        f = open(settings.pid_file, 'w')
        f.write(str(os.getpid()))
        f.close()

        # Set uid.
        os.setuid(uid)

        # Starting loop.
        asyncore.loop()
    except KeyboardInterrupt:
        pass

if __name__ == '__main__':
    main()
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.