Example #1
0
File: rabf.py Project: hax404/rabf
  def envrcpt(self, to, *str):
    rcptinfo = to,Milter.dictfromlist(str)
    self.R.append(rcptinfo)
    self.log("to: ", parse_addr(to)[0])

    a = 23
    b = 42
    addr = parse_addr(to)[0]
    euser = addr[0:2]
    ecsum = addr[2:4]
    eitext = addr[4:]
    edomain = parse_addr(to)[1]
    genitext = ''.join((euser, eitext, edomain))
    gencsum = hashlib.sha512(genitext.encode('utf-8')).hexdigest()
    posa = int(a)-1
    posb = int(b)-1
    csuma = gencsum[posa:(posa+1)]
    csumb = gencsum[posb:(posb+1)]

    self.log(addr, euser, ecsum, eitext, edomain, genitext, gencsum, posa, posb, csuma, csumb)

    if(ecsum != "".join((csuma,csumb))):
      self.log("Computer sagt nein.")
      return Milter.REJECT

    self.log("Computer sagt ja.")
    return Milter.CONTINUE
Example #2
0
def searchInRoundCube(fromAddress, recipients, debug, dbConnection):
    """Search for an address in the RoundCube database."""

    try:
        # Nothing found
        if not dbConnection:
            GlobalLogQueue.put("Could not connect to the database")
            return []

        sources = []

        for rec in recipients:
            parts = parse_addr(rec[0])
            uid = parts[0]

            # First, get all the address books from this user
            tablesCursor = dbConnection.cursor()
            abQuery = ("select cg.name from contacts as c"
                       " left join contactgroupmembers as cgm"
                       " on cgm.contact_id = c.contact_id"
                       " left join contactgroups as cg"
                       " on cg.contactgroup_id=cgm.contactgroup_id"
                       " left join users as u"
                       " on u.user_id = c.user_id"
                       " where u.username='******' and "
                       " c.words like '%{}%' and"
                       " c.del = 0"
                       .format(uid, fromAddress))

            tablesCursor.execute(abQuery)

            abooks = tablesCursor.fetchall()

            # End to search in this recipient
            tablesCursor.close()

            # Store the address book name, or "default" when no name
            for abResult in abooks:
                # Get the first cell as a result
                abName = abResult[0]

                if abName:
                    source = "Roundcube:{}".format(abName)
                else:
                    source = "Roundcube:default"

                # Insert if not already inside.
                if not source in sources:
                    sources.append(source)

        if debug:
            GlobalLogQueue.put("Searched address {} for user {}: {} result(s)".format(
                fromAddress, uid, len(sources)))

    # Make sure to not prevent the message to pass if something happen,
    # but log the error
    except Exception as error:
        GlobalLogQueue.put("Error when searching in address database: {}".format(error.message))

    return sources
Example #3
0
 def envfrom(self, mailfrom, *str):
     self.recipients = []  # list of recipients
     self.messageToParse = StringIO.StringIO()
     self.canon_from = '@'.join(parse_addr(mailfrom))
     self.messageToParse.write('From %s %s\n' %
                               (self.canon_from, time.ctime()))
     return Milter.CONTINUE
Example #4
0
 def envfrom(self, fromAddress, *extra):
     self.mailFrom = '@'.join(parse_addr(fromAddress))
     self.recipients = []
     self.fromparms = Milter.dictfromlist(extra) # ESMTP parms
     self.user = self.getsymval('{auth_authen}') # authenticated user
     self.fp = StringIO.StringIO()
     return Milter.CONTINUE
Example #5
0
 def envfrom(self, mailfrom, *str):
     self.fromparms = Milter.param2dict(str)  # ESMTP parms
     self.user = self.getsymval('{auth_authen}')  # authenticated user
     self.canon_from = '@'.join(parse_addr(mailfrom))
     self.R = []
     self.fp = BytesIO()
     self.fp.write(b"From %s %s\n" % (codecs.encode(self.canon_from, 'utf-8'), codecs.encode(time.ctime(), 'utf-8')))
     return Milter.CONTINUE
Example #6
0
 def envfrom(self, mailfrom, *str):
     self.F = mailfrom
     self.R = []  # list of recipients
     self.fromparms = Milter.dictfromlist(str)  # ESMTP parms
     self.user = self.getsymval('{auth_authen}')  # authenticated user
     self.fp = StringIO.StringIO()
     self.canon_from = '@'.join(parse_addr(mailfrom))
     #self.fp.write('From %s %s\n' % (self.canon_from,time.ctime()))
     return Milter.CONTINUE
Example #7
0
 def envfrom(self, mail_from, *esmtp_params):
     self.log('debug', log_called(module_name=__name__, function_name='envfrom', params={
         'mail_from': str(mail_from)
     }))
     try:
         self.mail_from = parse_addr(mail_from)[0]
     except Exception:
         self.mail_from = str(mail_from)
     return Milter.CONTINUE
Example #8
0
 def envfrom(self, mailfrom, *str):
     self.F = mailfrom
     self.R = []
     self.fromparms = Milter.dictfromlist(str)
     self.user = self.getsymval('{auth_authen}')
     self.fp = StringIO()
     self.canon_from = '@'.join(parse_addr(mailfrom))
     self.fp.write('From %s %s\n' % (self.canon_from, time.ctime()))
     return Milter.CONTINUE
Example #9
0
    def envrcpt(self, to, *str):
        try:
            self.rcpts.add("@".join(parse_addr(to)).lower())
        except Exception as e:
            self.logger.exception(
                f"an exception occured in envrcpt method: {e}")
            return Milter.TEMPFAIL

        return Milter.CONTINUE
Example #10
0
    def envfrom(self, mailfrom, *str):
        try:
            self.mailfrom = "@".join(parse_addr(mailfrom)).lower()
            self.rcpts = set()
        except Exception as e:
            self.logger.exception(
                f"an exception occured in envfrom method: {e}")
            return Milter.TEMPFAIL

        return Milter.CONTINUE
 def envfrom(self, mailfrom, *str):
     self.log("mail from: %s  -  %s" % (mailfrom, str))
     self.fromparms = Milter.dictfromlist(str)
     # NOTE: self.fp is only an *internal* copy of message data.  You
     # must use addheader, chgheader, replacebody to change the message
     # on the MTA.
     self.fp = StringIO.StringIO()
     self.canon_from = "@".join(parse_addr(mailfrom))
     self.fp.write("From %s %s\n" % (self.canon_from, time.ctime()))
     return Milter.CONTINUE
Example #12
0
 def envrcpt(self, mail_recip, *esmtp_params):
     self.log('debug', log_called(module_name=__name__, function_name='envrcpt', params={
         'mail_recip': str(mail_recip)
     }))
     try:
         recip = parse_addr(mail_recip)[0]
     except Exception:
         recip = str(mail_recip)
     self.recipients.append(recip)
     return Milter.CONTINUE
Example #13
0
 def envfrom(self, mailfrom, *str):
   self.mailfrom = mailfrom
   self.domains = []
   t = parse_addr(mailfrom)
   if len(t) > 1:
     self.domains.append(t[1])
   else:
     self.domains.append('local')
   self.internal = False
   return Milter.CONTINUE
Example #14
0
 def envfrom(self, mailfrom, *str):
     self.log("mail from: %s  -  %s" % (mailfrom, str))
     self.fromparms = Milter.dictfromlist(str)
     # NOTE: self.fp is only an *internal* copy of message data.  You
     # must use addheader, chgheader, replacebody to change the message
     # on the MTA.
     self.fp = StringIO.StringIO()
     self.canon_from = '@'.join(parse_addr(mailfrom))
     self.fp.write('From %s %s\n' % (self.canon_from, time.ctime()))
     return Milter.CONTINUE
Example #15
0
    def envfrom(self, f, *str):
        self.log("mail from", f, str)
        self.new_headers = []
        if not self.hello_name:
            self.log('REJECT: missing HELO')
            self.setreply('550', '5.7.1', "It's polite to say helo first.")
            return Milter.REJECT
        self.mailfrom = f
        t = parse_addr(f)
        if len(t) == 2:
            t[1] = t[1].lower()
            domain = t[1]
        else:
            domain = 'localhost.localdomain'
        self.canon_from = '@'.join(t)

        # Check SMTP AUTH, also available:
        #   auth_authen  authenticated user
        #   auth_author  (ESMTP AUTH= param)
        #   auth_ssf     (connection security, 0 = unencrypted)
        #   auth_type    (authentication method, CRAM-MD5, DIGEST-MD5, PLAIN, etc)
        # cipher_bits  SSL encryption strength
        # cert_subject SSL cert subject
        # verify       SSL cert verified

        self.user = self.getsymval('{auth_authen}')
        if self.user:
            # Very simple SMTP AUTH policy by default:
            #   any successful authentication is considered INTERNAL
            # Detailed authorization policy is configured in the access file below.
            self.internal_connection = True
            self.log("SMTP AUTH:", self.user, self.getsymval('{auth_type}'),
                     "sslbits =", self.getsymval('{cipher_bits}'), "ssf =",
                     self.getsymval('{auth_ssf}'), "INTERNAL")
            # Restrict SMTP AUTH users to authorized domains
            authsend = '@'.join((self.user, domain))
            with SPFPolicy(authsend, self.conf) as p:
                policy = p.getPolicy('smtp-auth:')
            if policy:
                if policy != 'OK':
                    self.log("REJECT: SMTP user", self.user, "at",
                             self.connectip, "not authorized for domain",
                             domain)
                    self.setreply(
                        '550', '5.7.1',
                        'SMTP user %s is not authorized to send from domain %s.'
                        % (self.user, domain))
                    return Milter.REJECT
            self.log("SMTP authorized user", self.user, "sending from domain",
                     domain)

        if not (self.internal_connection
                or self.trusted_relay) and self.connectip:
            return self.check_spf()
        return Milter.CONTINUE
Example #16
0
    def envfrom(self, mailfrom, *str):
        self.F = mailfrom
        self.R = []  
        self.fromparms = Milter.dictfromlist(str)  
        self.user = self.getsymval('{auth_authen}')  
       

        self.fp = StringIO.StringIO()
        self.canon_from = '@'.join(parse_addr(mailfrom))
        self.fp.write('From %s %s\n' % (self.canon_from, time.ctime()))
        return Milter.CONTINUE
Example #17
0
  def envfrom(self,f,*str):
    self.log("mail from",f,str)
    self.new_headers = []
    if not self.hello_name:
      self.log('REJECT: missing HELO')
      self.setreply('550','5.7.1',"It's polite to say helo first.")
      return Milter.REJECT
    self.mailfrom = f
    t = parse_addr(f)
    if len(t) == 2:
      t[1] = t[1].lower()
      domain = t[1]
    else:
      domain = 'localhost.localdomain'
    self.canon_from = '@'.join(t)

    # Check SMTP AUTH, also available:
    #   auth_authen  authenticated user
    #   auth_author  (ESMTP AUTH= param)
    #   auth_ssf     (connection security, 0 = unencrypted)
    #   auth_type    (authentication method, CRAM-MD5, DIGEST-MD5, PLAIN, etc)
    # cipher_bits  SSL encryption strength
    # cert_subject SSL cert subject
    # verify       SSL cert verified

    self.user = self.getsymval('{auth_authen}')
    if self.user:
      # Very simple SMTP AUTH policy by default:
      #   any successful authentication is considered INTERNAL
      # Detailed authorization policy is configured in the access file below.
      self.internal_connection = True
      self.log(
        "SMTP AUTH:",self.user, self.getsymval('{auth_type}'),
        "sslbits =",self.getsymval('{cipher_bits}'),
        "ssf =",self.getsymval('{auth_ssf}'), "INTERNAL"
      )
      # Restrict SMTP AUTH users to authorized domains
      authsend = '@'.join((self.user,domain))
      with SPFPolicy(authsend,self.conf) as p:
        policy = p.getPolicy('smtp-auth:')
      if policy:
        if policy != 'OK':
          self.log("REJECT: SMTP user",self.user,
              "at",self.connectip,"not authorized for domain",domain)
          self.setreply('550','5.7.1',
            'SMTP user %s is not authorized to send from domain %s.' %
            (self.user,domain)
          )
          return Milter.REJECT
      self.log("SMTP authorized user",self.user,"sending from domain",domain)

    if not (self.internal_connection or self.trusted_relay) and self.connectip:
      return self.check_spf()
    return Milter.CONTINUE
Example #18
0
 def envfrom(self, mailfrom, *str):
     self.log("mail from: %s  -  %s" % (mailfrom, str))
     self.fromparms = Milter.dictfromlist(str)
     # NOTE: self.fp is only an *internal* copy of message data.  You
     # must use addheader, chgheader, replacebody to change the message
     # on the MTA.
     self.fp = BytesIO()
     self.canon_from = "@".join(parse_addr(mailfrom))
     from_txt = "From %s %s\n" % (self.canon_from, time.ctime())
     self.fp.write(from_txt.encode("utf-8"))
     return Milter.CONTINUE
Example #19
0
def searchInSOGo(fromAddress, recipients, debug, dbConnection):
    """Search for an address in the SOGo database."""

    try:
        # Nothing found
        if not dbConnection:
            GlobalLogQueue.put("Could not connect to the database")
            return []

        sources = []

        for rec in recipients:
            parts = parse_addr(rec[0])
            uid = parts[0]

            # First, get all the address books from this user
            tablesCursor = dbConnection.cursor()
            abQuery = ("select c_foldername, regexp_replace(c_location, '.*/sogo', 'sogo')"
                       " from sogo_folder_info where"
                       " c_folder_type='Contact' and c_location like '%sogo{}%';".format(uid))

            tablesCursor.execute(abQuery)

            tables = tablesCursor.fetchall()

            # End to search in this address book
            tablesCursor.close()

            # For each table, run a query to check if the address is inside
            for tableInfo in tables:
                abName = tableInfo[0]
                tableName = tableInfo[1]
                cursor = dbConnection.cursor()
                countQuery = "select count(*) from {} where c_content LIKE '%EMAIL%:{}%';".format(tableName, fromAddress)
                if debug:
                    GlobalLogQueue.put("Searching in table {} ({})".format(tableName, abName))
                cursor.execute(countQuery)
                result = cursor.fetchone()
                cursor.close()

                # Store the address book sources when found
                if int(result[0]) > 0:
                    sources.append('SOGo:{}'.format(abName))

        if debug:
            GlobalLogQueue.put("Searched address {} for user {}: {} result(s)".format(
                fromAddress, uid, len(sources)))

    # Make sure to not prevent the message to pass if something happen,
    # but log the error
    except Exception as error:
        GlobalLogQueue.put("Error when searching in address database: {}".format(error.message))

    return sources
Example #20
0
 def envfrom(self, mailfrom, *str):
   self.F = mailfrom
   self.R = []  # list of recipients
   self.fromparms = Milter.dictfromlist(str)	# ESMTP parms
   self.user = self.getsymval('{auth_authen}')	# authenticated user
   self.log("mail from:", mailfrom, *str)
   # NOTE: self.fp is only an *internal* copy of message data.  You
   # must use addheader, chgheader, replacebody to change the message
   # on the MTA.
   self.fp = StringIO()
   self.canon_from = '@'.join(parse_addr(mailfrom))
   self.fp.write('From %s %s\n' % (self.canon_from,time.ctime()))
   return Milter.CONTINUE
Example #21
0
 def envfrom(self, mailfrom, *str):
     self.F = mailfrom
     self.R = []  # list of recipients
     self.fromparms = Milter.dictfromlist(str)  # ESMTP parms
     self.user = self.getsymval('{auth_authen}')  # authenticated user
     self.log("mail from:", mailfrom, *str)
     # NOTE: self.fp is only an *internal* copy of message data.  You
     # must use addheader, chgheader, replacebody to change the message
     # on the MTA.
     self.fp = BytesIO()
     self.canon_from = '@'.join(parse_addr(mailfrom))
     #self.fp.write('From %s %s\n' % (self.canon_from,time.ctime()))
     return Milter.CONTINUE
Example #22
0
 def envfrom(self, f, *str):
     self.log("mail from", f, str)
     self.mailfrom = f
     t = parse_addr(f)
     if len(t) == 2: t[1] = t[1].lower()
     self.canon_from = '@'.join(t)
     self.srsrcpt = []
     self.nosrsrcpt = []
     self.redirect_list = []
     self.discard_list = []
     self.is_bounce = (f == '<>' or t[0].lower() in self.conf.banned_users)
     self.data_allowed = True
     return Milter.CONTINUE
Example #23
0
  def envrcpt(self, to, *str):
    self.R.append(to)
    t = parse_addr(to)
    if len(t) > 1:
      self.domains.append(t[1])
    else:
      self.domains.append('local')

    if are_mixed(self.domains):
      # FIXME: log recipients collected in self.mailfrom and self.R
      self.setreply('550','5.7.1','Mixing internal and external TLDs')
      return Milter.REJECT
        
    return Milter.CONTINUE
Example #24
0
 def envrcpt(self, to, *params):
     conf = self.conf
     t = parse_addr(to)
     if len(t) == 2:
         t[1] = t[1].lower()
         user, domain = t
         if self.is_bounce and domain in conf.srs_domain:
             # require valid signed recipient
             oldaddr = '@'.join(t)
             try:
                 if conf.ses:
                     ses = self.conf.ses
                     newaddr = ses.verify(oldaddr)
                 else:
                     newaddr = oldaddr,
                 if len(newaddr) > 1:
                     newaddr = newaddr[0]
                     self.log("ses rcpt:", newaddr)
                 else:
                     srs = self.conf.srs
                     newaddr = srs.reverse(oldaddr)
                     self.log("srs rcpt:", newaddr)
                 self.del_recipient(to)
                 self.add_recipient('<%s>' % newaddr, params)
             except:
                 # no valid SRS signature
                 if not (self.internal_connection or self.trusted_relay):
                     # reject specific recipients with bad sig
                     if self.srsre.match(oldaddr):
                         self.log("REJECT: srs spoofed:", oldaddr)
                         self.setreply('550', '5.7.1',
                                       'Invalid SRS signature')
                         return Milter.REJECT
                     if oldaddr.startswith('SES='):
                         self.log("REJECT: ses spoofed:", oldaddr)
                         self.setreply('550', '5.7.1',
                                       'Invalid SES signature')
                         return Milter.REJECT
                     # reject message for any missing sig
                     self.data_allowed = not conf.srs_reject_spoofed
         else:
             # sign "outgoing" from
             if domain in self.conf.nosrsdomain:
                 self.nosrsrcpt.append(to)
             else:
                 self.srsrcpt.append(to)
     else:  # no SRS for unqualified recipients
         self.nosrsrcpt.append(to)
     return Milter.CONTINUE
Example #25
0
 def envfrom(self, f, *str):
     if milterconfig.get('Syslog') and milterconfig.get('debugLevel') >= 2:
         syslog.syslog("mail from: {0} {1}".format(f, str))
     self.fp = io.BytesIO()
     self.mailfrom = f
     t = parse_addr(f)
     if len(t) == 2:
         t[1] = t[1].lower()
     self.mailfromdom = t[1]
     self.canon_from = '@'.join(t)
     self.has_dkim = 0
     self.author = None
     self.arheaders = []
     self.arresults = []
     return Milter.CONTINUE
Example #26
0
 def envfrom(self, mailfrom, *rest):
     '''
     Mail From - Called at the beginning of each message within a connection
     :param mailfrom:
     :param str:
     :return: Milter.CONTINUE
     '''
     self.message = io.BytesIO()
     # NOTE: self.message is only an *internal* copy of message data.  You
     # must use addheader, chgheader, replacebody to change the message
     # on the MTA.
     self.canon_from = '@'.join(parse_addr(mailfrom))
     self.message.write('From %s %s\n' % (self.canon_from, time.ctime()))
     logging.debug('[%d] Mail From %s %s\n' % (self.id, self.canon_from, time.ctime()))
     logging.debug('[%d] mailfrom=%r, rest=%r' % (self.id, mailfrom, rest))
     return Milter.CONTINUE
Example #27
0
 def envfrom(self, mailfrom, *rest):
     '''
     Mail From - Called at the beginning of each message within a connection
     :param mailfrom:
     :param str:
     :return: Milter.CONTINUE
     '''
     self.message = io.BytesIO()
     # NOTE: self.message is only an *internal* copy of message data.  You
     # must use addheader, chgheader, replacebody to change the message
     # on the MTA.
     self.canon_from = '@'.join(parse_addr(mailfrom))
     self.message.write('From %s %s\n' % (self.canon_from, time.ctime()))
     log.debug('[%d] Mail From %s %s\n' % (self.id, self.canon_from, time.ctime()))
     log.debug('[%d] mailfrom=%r, rest=%r' % (self.id, mailfrom, rest))
     return Milter.CONTINUE
Example #28
0
def searchInSQLite(fromAddress, recipients, debug):
    """Search for an address in a local sqlite database. Only email hashes are stored (sha256)"""
    sources = []

    try:

        import sqlite3
        import hashlib

        query = 'select source,abook from addresses where uid="{0}" and email_hash="{1}"'
        sqliteDatabase = configParser.get('sqlite', 'path')
        db = sqlite3.connect(sqliteDatabase)

        # Check if the email address is in the user's address book
        cursor = db.cursor()

        # get the from email address signature
        emailHash = hashlib.sha256(fromAddress).hexdigest()

        for rec in recipients:
            parts = parse_addr(rec[0])
            uid = parts[0]
            cursor.execute(query.format(uid, emailHash))

            # Store the address book sources when found
            for row in cursor:
                sources.append('{0}:{1}'.format(row[0], row[1]))

        if debug:
            GlobalLogQueue.put("Searched address hash {} for user {}: {} result(s)".format(
                emailHash, uid, len(sources)))

    # Make sure to not prevent the message to pass if something happen,
    # but log the error
    except Exception as error:
        GlobalLogQueue.put("Error when searching in address database: {}".format(error.message))

    # Cleanup: close the db connection if needed
    finally:
        if db:
            db.close()

    return sources
Example #29
0
 def envrcpt(self, to, *str):
     self.recipients.add("@".join(parse_addr(to)).lower())
     return Milter.CONTINUE
Example #30
0
 def envfrom(self, mailfrom, *str):
     self.mailfrom = "@".join(parse_addr(mailfrom)).lower()
     self.recipients = set()
     return Milter.CONTINUE
Example #31
0
 def envfrom(self, mailfrom, *str):
     user_from, domain_from = parse_addr(mailfrom)
     user_from = user_from.split("+", 1)[0]
     mail_from = "@".join((user_from, domain_from))
     self.mail.append("From %s %s\n" % (mail_from, time.ctime()))
     return Milter.CONTINUE
Example #32
0
 def envrcpt(self, to, *str):
     if not self.to:
         self.to = "@".join(parse_addr(to))
         return Milter.CONTINUE
     else:
         return Milter.TEMPFAIL
Example #33
0
 def envrcpt(self, to, *str):
     if not self.to:
         self.to = "@".join(parse_addr(to))
         return Milter.CONTINUE
     else:
         return Milter.TEMPFAIL
Example #34
0
 def envfrom(self, mailfrom, *str):
     user_from, domain_from = parse_addr(mailfrom)
     user_from = user_from.split("+", 1)[0]
     mail_from = "@".join((user_from, domain_from))
     self.mail.append("From %s %s\n" % (mail_from, time.ctime()))
     return Milter.CONTINUE
Example #35
0
	def envfrom(self, mailfrom, *str):
		self.messageToParse = StringIO.StringIO()
		self.canon_from = '@'.join(parse_addr(mailfrom))
		self.messageToParse.write('From %s %s\n' % (self.canon_from, time.ctime()))
		return Milter.CONTINUE