def matchRules(self, ruleset, obj, suspect, attachmentname=None): if attachmentname == None: attachmentname = "" attachmentname = self.asciionly(attachmentname) if obj == None: self.logger.warning( "%s: message has unknown name or content-type attachment %s" % (suspect.id, attachmentname)) return ATTACHMENT_DUNNO # remove non ascii chars asciirep = self.asciionly(obj) displayname = attachmentname if asciirep == attachmentname: displayname = '' if ruleset == None: return ATTACHMENT_DUNNO for action, regex, description in ruleset: # database description may be unicode description = description.encode("utf-8", "ignore") prog = re.compile(regex, re.I) if self.extremeverbosity: self.logger.debug('Attachment %s Rule %s' % (obj, regex)) if isinstance(obj, bytes) and sys.version_info > (3,): obj = obj.decode('UTF-8', 'ignore') if prog.search(obj): self.logger.debug('Rulematch: Attachment=%s Rule=%s Description=%s Action=%s' % ( obj, regex, description, action)) suspect.debug('Rulematch: Attachment=%s Rule=%s Description=%s Action=%s' % ( obj, regex, description, action)) if action == 'deny': self.logger.info('suspect %s contains blocked attachment %s %s' % ( suspect.id, displayname, asciirep)) blockinfo = "%s %s: %s" % ( displayname, asciirep, description) suspect.tags['FiletypePlugin.errormessage'] = blockinfo if self.config.getboolean(self.section, 'sendbounce'): if suspect.is_spam() or suspect.is_virus(): self.logger.info( "backscatter prevention: not sending attachment block bounce to %s - the message is tagged spam or virus" % suspect.from_address) else: self.logger.info( "Sending attachment block bounce to %s" % suspect.from_address) bounce = Bounce(self.config) bounce.send_template_file( suspect.from_address, self.blockedfiletemplate, suspect, dict(blockinfo=blockinfo)) return ATTACHMENT_BLOCK if action == 'delete': self.logger.info( 'suspect %s contains blocked attachment %s %s -- SILENT DELETE! --' % (suspect.id, displayname, asciirep)) return ATTACHMENT_SILENTDELETE if action == 'allow': return ATTACHMENT_OK return ATTACHMENT_DUNNO
def matchRules(self, ruleset, obj, suspect, attachmentname=None): if attachmentname is None: attachmentname = "" attachmentname = self.asciionly(attachmentname) if obj is None: self.logger.warning( "%s: message has unknown name or content-type attachment %s" % (suspect.id, attachmentname)) return ATTACHMENT_DUNNO # remove non ascii chars asciirep = self.asciionly(obj) displayname = attachmentname if asciirep == attachmentname: displayname = '' if ruleset is None: return ATTACHMENT_DUNNO for action, regex, description in ruleset: # database description may be unicode description = description.encode("utf-8", "ignore") prog = re.compile(regex, re.I) if self.extremeverbosity: self.logger.debug('Attachment %s Rule %s' % (obj, regex)) if isinstance(obj, bytes) and sys.version_info > (3,): obj = obj.decode('UTF-8', 'ignore') if prog.search(obj): self.logger.debug('Rulematch: Attachment=%s Rule=%s Description=%s Action=%s' % ( obj, regex, description, action)) suspect.debug('Rulematch: Attachment=%s Rule=%s Description=%s Action=%s' % ( obj, regex, description, action)) if action == 'deny': self.logger.info('suspect %s contains blocked attachment %s %s' % ( suspect.id, displayname, asciirep)) suspect.tags['blocked']['FiletypePlugin'] = True blockinfo = ("%s %s: %s" % (displayname, asciirep, description)).strip() suspect.tags['FiletypePlugin.errormessage'] = blockinfo if self.config.getboolean(self.section, 'sendbounce'): if suspect.is_spam() or suspect.is_virus(): self.logger.info( "backscatter prevention: not sending attachment block bounce to %s - the message is tagged spam or virus" % suspect.from_address) else: self.logger.info( "Sending attachment block bounce to %s" % suspect.from_address) bounce = Bounce(self.config) bounce.send_template_file( suspect.from_address, self.blockedfiletemplate, suspect, dict(blockinfo=blockinfo)) return ATTACHMENT_BLOCK if action == 'delete': self.logger.info( 'suspect %s contains blocked attachment %s %s -- SILENT DELETE! --' % (suspect.id, displayname, asciirep)) return ATTACHMENT_SILENTDELETE if action == 'allow': return ATTACHMENT_OK return ATTACHMENT_DUNNO
def test_bounce(self): """Test bounce message, especially the encoding""" suspect = Suspect('*****@*****.**', '*****@*****.**', '/dev/null') # include non-ascii charset unicode characters to make sure the encoding/decoding # works correctly displayname = u"((testing placeholder for displayname -> äää))" asciirep = u"((testing placeholder for asciirep -> üüü))" description = u"((testing placeholder for description -> ööö))" blockinfo = ("%s %s: %s" % (displayname, asciirep, description)).strip() blockedfiletemplate = os.path.join( *[CONFDIR, "templates", "blockedfile.tmpl.dist"]) bounce = Bounce(self.config) bounce.send_template_file(suspect.from_address, blockedfiletemplate, suspect, dict(blockinfo=blockinfo)) # might be needed to wait for a bit to make sure answer is available counter = 0 while self.smtp.suspect is None and counter < 20: counter = counter + 1 time.sleep(0.05) # sleep is needed to gotback = self.smtp.suspect self.assertFalse(gotback == None, "Did not get message from dummy smtp server") # get message received by dummy smtp server msg = gotback.get_message_rep() receivedMsg = msg.get_payload(decode='utf-8') # Build the message according to what Bounce is doing so it can be compared # to what was received from DummySMTPServer with open(blockedfiletemplate) as fp: templatecontent = fp.read() blockinfo = ("%s %s: %s" % (displayname, asciirep, description)).strip() message = apply_template(templatecontent, suspect, dict(blockinfo=blockinfo)) messageB = force_bString(message) # modify received message to add header parts from template messageToCompare = force_bString("To: " + msg['To'] + "\nSubject: " + msg['Subject'] + "\n\n") + force_bString(receivedMsg) # make sure comparison will not fail because of newlines # For example, Python 2.6 has only one "\n" at the end of the received message, whereas Python 2.7 and 3 have to messageToCompare = messageToCompare.replace(b"\r", b"\n").replace( b"\n\n", b"\n") messageB = messageB.replace(b"\r", b"\n").replace(b"\n\n", b"\n") self.assertEqual(messageB, messageToCompare)
def matchRules(self,ruleset,obj,suspect,attachmentname=None): if attachmentname==None: attachmentname="" attachmentname=self.asciionly(attachmentname) if obj==None: self.logger.warning("%s: message has unknown name or content-type attachment %s"%(suspect.id,attachmentname)) return ATTACHMENT_DUNNO # remove non ascii chars asciirep=self.asciionly(obj) displayname=attachmentname if asciirep==attachmentname: displayname='' if ruleset==None: return ATTACHMENT_DUNNO for regex in ruleset.keys(): prog=re.compile(regex,re.I) if self.extremeverbosity: self.logger.debug('Attachment %s Rule %s'%(obj,regex)) if prog.search( obj): info=ruleset[regex] action=info[0] description=info[2] self.logger.debug('Rulematch: Attachment=%s Rule=%s Description=%s Action=%s'%(obj,regex,description,action)) suspect.debug('Rulematch: Attachment=%s Rule=%s Description=%s Action=%s'%(obj,regex,description,action)) if action=='deny': self.logger.info('suspect %s contains blocked attachment %s %s'%(suspect.id,displayname,asciirep)) blockinfo="%s %s: %s"%(displayname,asciirep,description) suspect.tags['FiletypePlugin.errormessage']=blockinfo if self.config.getboolean(self.section,'sendbounce'): self.logger.info("Sending attachment block bounce to %s"%suspect.from_address) bounce=Bounce(self.config) bounce.send_template_file(suspect.from_address, self.blockedfiletemplate, suspect,dict(blockinfo=blockinfo)) return ATTACHMENT_BLOCK if action=='delete': self.logger.info('suspect %s contains blocked attachment %s %s -- SILENT DELETE! --'%(suspect.id,displayname,asciirep)) return ATTACHMENT_SILENTDELETE if action=='allow': return ATTACHMENT_OK return ATTACHMENT_DUNNO