Al-HUWAITI Shell
Al-huwaiti


Server : LiteSpeed
System : Linux in-mum-web1949.main-hosting.eu 5.14.0-503.40.1.el9_5.x86_64 #1 SMP PREEMPT_DYNAMIC Mon May 5 06:06:04 EDT 2025 x86_64
User : u595547767 ( 595547767)
PHP Version : 7.4.33
Disable Function : NONE
Directory :  /opt/alt/python27/lib/python2.7/site-packages/postomaat/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Current File : //opt/alt/python27/lib/python2.7/site-packages/postomaat/scansession.py
# -*- coding: UTF-8 -*-
#   Copyright 2012-2018 Oli Schacher
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from postomaat.shared import DUNNO, Suspect, DEFER, REJECT, DISCARD
from postomaat.addrcheck import AddrException
from functools import reduce
import logging
import sys
import traceback
import time
import socket

class TrackTimings(object):
    def __init__(self, enable=False):
        """
        Constructor, setting function handles to real functions or dummies

        Args:
            enable (bool): enable/disable time tracker
        """
        self.timings_logger = logging.getLogger("%s.Timings" % __package__)

        # timings
        self._enabletimetracker= False
        self.enabletimetracker = enable

        self.timetracker = time.time()
        self.timings = []

    @property
    def enabletimetracker(self):
        return self._enabletimetracker

    @enabletimetracker.setter
    def enabletimetracker(self, enabled):

        if not enabled:
            self._enabletimetracker = False
            self.tracktime = self._dummy_noreturn
            self.gettime = self._dummy_returnlist
            self.sumtime = self._dummy_returnzero
            self.report_timings = self._dummy_noreturn
            self.report_plugintime = self._dummy_noreturn
        else:
            self._enabletimetracker = True
            self.tracktime = self._tracktime
            self.gettime = self._gettime
            self.sumtime = self._sumtime
            self.report_timings = self._report_timings
            self.report_plugintime = self._report_plugintime
            self.timetracker = time.time()
            self.timings = []


    def _tracktime(self, tagname, plugin=False):
        """
        Given a tag name, track and store time since last call of same function

        Args:
            tagname (str): String with tag name

        Keyword Args:
            plugin (bool): tag belongs to plugin timing
        """
        newtime = time.time()
        difftime = newtime - self.timetracker
        self.timetracker = newtime
        self.timings.append((tagname, difftime, plugin))

    def _dummy_noreturn(self, *args, **kwargs):
        return

    def _dummy_returnlist(self, *args, **kwargs):
        return []

    def _dummy_returnzero(self, *args, **kwargs):
        return 0.0

    def _gettime(self, plugins=None):
        """
        Get a list of timings stored (all/only plugins/exclude plugins)

        Keyword Args:
            plugins (bool or None): For 'None' return all timings, True: only plugin timings, False: all but plugin timings

        Returns:
            list of tuples (name, time)

        """
        if plugins is None:
            timing_list = [a[:2] for a in self.timings]
        else:
            timing_list = [a[:2] for a in self.timings if a[2] == plugins]
        return timing_list

    def _sumtime(self, plugins=None):
        """
        Get total time spent (all/only plugins/exclude plugins)

        Keyword Args:
            plugins (bool or None): For 'None' return total time, True: time spent in plugins, False: time spent outside plugins

        Returns:
            float: total time spent

        """
        puretimings = [a[1] for a in self.gettime(plugins)]
        if len(puretimings) == 0:
            return 0.0
        else:
            return reduce(lambda x, y: (x + y), puretimings)

    def _report_timings(self, suspectid):
        """
        Report all the timings collected
        Args:
            suspectid (id):  the suspect id

        """
        self.timings_logger.info('id: %s, total: %.3f' % (suspectid, self.sumtime()))
        self.timings_logger.info('id: %s, overhead: %.3f' % (suspectid, self.sumtime(plugins=False)))
        all_plugintimes = self.gettime(plugins=True)
        for plugintime in all_plugintimes:
            self.timings_logger.info('id: %s, (PLG) %s: %.3f' % (suspectid, plugintime[0], plugintime[1]))
        all_overheadtimes = self.gettime(plugins=False)
        for overheadtime in all_overheadtimes:
            self.timings_logger.debug('id: %s, %s: %.3f' % (suspectid, overheadtime[0], overheadtime[1]))

    def _report_plugintime(self,suspectid,pluginname, end=True):
        """
        Report timings inside plugin

        Args:
            suspectid (str): the id of the suspect
            pluginname (str): plugin name

        Keyword Args:
            end (bool): if true another timing called 'end' will be created before the report
        """
        if end:
            self.tracktime('end')
        all_timings = self.gettime()
        for itime in all_timings:
            self.timings_logger.debug('id: %s, [%s]-%s: %.3f' % (suspectid, pluginname, itime[0], itime[1]))


class SessionHandler(TrackTimings):

    """thread handling one message"""

    def __init__(self, incomingsocket, config, plugins):

        TrackTimings.__init__(self)

        self.incomingsocket = incomingsocket
        self.logger = logging.getLogger("%s.SessionHandler" % __package__)
        self.action = DUNNO
        self.arg = ""
        self.config = config
        self.plugins = plugins
        self.workerthread = None

        try:
            self.enabletimetracker = config.getboolean('main', 'scantimelogger')
        except Exception as e:
            self.enabletimetracker = False

        self.logger.debug("enabletimetracker = %s" % self.enabletimetracker)


    def defer(self,message):
        """
        Create a session and immediately close it sending a DEFER message to the server
        Args:
            message (str): additional information sent to the server

        """
        try:
            sess = PolicydSession(self.incomingsocket, self. config)
            sess.endsession(DEFER, message)
        except Exception as e:
            pass

    def set_threadinfo(self, status):
        if self.workerthread is not None:
            self.workerthread.threadinfo = status
    
    def handlesession(self, workerthread=None):
        self.workerthread = workerthread
        sess = None
        suspectid = 'undefinedundefinedundefinedundef'
        try:
            self.set_threadinfo('receiving message')
            self.tracktime("SessionHandler-Setup")
            sess = PolicydSession(self.incomingsocket, self. config)
            success = sess. getrequest()
            if not success:
                self.logger.error('incoming request did not finish')
                sess.closeconn()
            self.tracktime("Message-Receive")

            values = sess.values
            suspect = Suspect(values)
            suspectid = suspect.id

            # store incoming port to tag, could be used to disable plugins
            # based on port
            try:
                port = sess.socket . getsockname()[1]
                if port is not None:
                    suspect.tags['incomingport'] = port
            except Exception as e:
                self.logger.warning('Could not get incoming port: %s' % str(e))

            self.set_threadinfo("Handling message %s" % suspect)
            starttime = time.time()
            self.tracktime("Suspect-Init")
            self.run_plugins(suspect, self.plugins)

            # how long did it all take?
            difftime = time.time() - starttime
            suspect.tags['postomaat.scantime'] = "%.4f" % difftime

            # checks done.. print out suspect status
            self.logger.debug(suspect)
            self.set_threadinfo("Finishing message %s" % suspect)

        except KeyboardInterrupt:
            sys.exit(0)
        except AddrException as e:
            # Error in envelope send/receive address
            self.logger.warning('Address exception: %s' % str(e))
            try:
                address_compliance_fail_action = self.config.get('main','address_compliance_fail_action').lower()
            except Exception:
                address_compliance_fail_action = "defer"

            try:
                message = self.config.get('main','address_compliance_fail_message')
            except Exception:
                message = "invalid sender or recipient address"

            if address_compliance_fail_action   == "defer":
                self.action = DEFER
            elif address_compliance_fail_action == "reject":
                self.action = REJECT
            elif address_compliance_fail_action == "discard":
                self.action = DISCARD
            else:
                self.action = DEFER
            self.arg = message

        except Exception as e:
            self.logger.exception(e)
        finally:
            if sess is not None:
                sess.endsession(self.action, self.arg)
            self.logger.debug('Session finished')
            # ---------------#
            # report timings #
            # ---------------#
            self.tracktime("Ending")

            self.report_timings(suspectid)


    def run_plugins(self, suspect, pluglist):
        """Run scannerplugins on suspect"""
        for plugin in pluglist:
            try:
                self.logger.debug('Running plugin %s' % plugin)
                self.set_threadinfo(
                    "%s : Running Plugin %s" % (suspect, plugin))
                ans = plugin.examine(suspect)
                arg = None
                if isinstance(ans, tuple):
                    result, arg = ans
                else:
                    result = ans

                if result is None:
                    result = DUNNO
                else:
                    result = result.strip().lower()
                self.action = result
                self.arg = arg
                suspect.tags['decisions'].append((str(plugin), result))
                self.logger.debug('Plugin decission: %s (arg=%s)' % (result, arg))

                if result != DUNNO:
                    self.logger.debug(
                        'Plugin makes a decision other than DUNNO - not running any other plugins')
                    break

            except Exception:
                exc = traceback. format_exc()
                self.logger.error('Plugin %s failed: %s' % (str(plugin), exc))
            finally:
                self.tracktime(str(plugin),plugin=True)


class PolicydSession(object):

    def __init__(self, socket, config):
        self.config = config

        self.socket = socket
        self.logger = logging.getLogger("%s.policysession" % __package__)
        self.file = self.socket.makefile('r')
        self.values = {}

    def endsession(self, action, arg):
        ret = action
        if arg is not None and arg.strip() != "":
            ret = "%s %s" % (action, arg.strip())
        self.socket.send(('action=%s\n\n' % ret).encode())
        self.closeconn()

    def closeconn(self):
        try:
            self.socket.shutdown(socket.SHUT_RDWR)
        except (OSError, socket.error):
            pass
        finally:
            self.socket.close()

    def getrequest(self):
        """return true if mail got in, false on error Session will be kept open"""
        while True:
            line = self.file.readline()
            line = line.strip()
            if line == '':
                return True
            try:
                key, val = line.split('=', 1)
                self.values[key] = val
            except Exception:
                self.logger.error('Invalid Protocol line: %s' % line)
                break

        return False

Al-HUWAITI Shell