Add initial support for Syslog option
This commit is contained in:
@@ -10,7 +10,7 @@ Mode implemented
|
|||||||
PidFile
|
PidFile
|
||||||
Selector implemented
|
Selector implemented
|
||||||
Socket implemented verified
|
Socket implemented verified
|
||||||
Syslog
|
Syslog implemented partly tested
|
||||||
UMask
|
UMask
|
||||||
UserID implemented verified
|
UserID implemented verified
|
||||||
|
|
||||||
|
|||||||
+32
-23
@@ -28,8 +28,6 @@ import dkim
|
|||||||
from dkim.dnsplug import get_txt
|
from dkim.dnsplug import get_txt
|
||||||
from dkim.util import parse_tag_value
|
from dkim.util import parse_tag_value
|
||||||
import authres
|
import authres
|
||||||
import logging
|
|
||||||
import logging.config
|
|
||||||
import os
|
import os
|
||||||
import tempfile
|
import tempfile
|
||||||
import StringIO
|
import StringIO
|
||||||
@@ -41,15 +39,10 @@ from dkimpy_milter.util import drop_privileges
|
|||||||
from dkimpy_milter.util import setExceptHook
|
from dkimpy_milter.util import setExceptHook
|
||||||
|
|
||||||
FWS = re.compile(r'\r?\n[ \t]+')
|
FWS = re.compile(r'\r?\n[ \t]+')
|
||||||
syslog.openlog(os.path.basename(sys.argv[0]), syslog.LOG_PID, syslog.LOG_MAIL)
|
|
||||||
setExceptHook()
|
|
||||||
|
|
||||||
class dkimMilter(Milter.Base):
|
class dkimMilter(Milter.Base):
|
||||||
"Milter to check and sign DKIM. Each connection gets its own instance."
|
"Milter to check and sign DKIM. Each connection gets its own instance."
|
||||||
|
|
||||||
def log(self,*msg):
|
|
||||||
self.conf.log.info('[%d] %s' % (self.id,' '.join([str(m) for m in msg])))
|
|
||||||
|
|
||||||
def __init__(self, milterconfig):
|
def __init__(self, milterconfig):
|
||||||
self.mailfrom = None
|
self.mailfrom = None
|
||||||
self.id = Milter.uniqueID()
|
self.id = Milter.uniqueID()
|
||||||
@@ -73,7 +66,8 @@ class dkimMilter(Milter.Base):
|
|||||||
connecttype = 'INTERNAL'
|
connecttype = 'INTERNAL'
|
||||||
else:
|
else:
|
||||||
connecttype = 'EXTERNAL'
|
connecttype = 'EXTERNAL'
|
||||||
self.log("connect from %s at %s %s" % (hostname,hostaddr,connecttype))
|
if milterconfig.get('Syslog'):
|
||||||
|
syslog.syslog("connect from %s at %s %s" % (hostname,hostaddr,connecttype))
|
||||||
return Milter.CONTINUE
|
return Milter.CONTINUE
|
||||||
|
|
||||||
# multiple messages can be received on a single connection
|
# multiple messages can be received on a single connection
|
||||||
@@ -81,7 +75,8 @@ class dkimMilter(Milter.Base):
|
|||||||
# of each message.
|
# of each message.
|
||||||
@Milter.noreply
|
@Milter.noreply
|
||||||
def envfrom(self,f,*str):
|
def envfrom(self,f,*str):
|
||||||
self.log("mail from",f,str)
|
if milterconfig.get('Syslog'):
|
||||||
|
syslog.syslog("mail from",f,str)
|
||||||
self.fp = StringIO.StringIO()
|
self.fp = StringIO.StringIO()
|
||||||
self.mailfrom = f
|
self.mailfrom = f
|
||||||
t = parse_addr(f)
|
t = parse_addr(f)
|
||||||
@@ -98,7 +93,8 @@ class dkimMilter(Milter.Base):
|
|||||||
self.internal_connection = True
|
self.internal_connection = True
|
||||||
auth_type = self.getsymval('{auth_type}')
|
auth_type = self.getsymval('{auth_type}')
|
||||||
ssl_bits = self.getsymval('{cipher_bits}')
|
ssl_bits = self.getsymval('{cipher_bits}')
|
||||||
self.log(
|
if milterconfig.get('Syslog'):
|
||||||
|
syslog.syslog(
|
||||||
"SMTP AUTH:",self.user,"sslbits =",ssl_bits, auth_type,
|
"SMTP AUTH:",self.user,"sslbits =",ssl_bits, auth_type,
|
||||||
"ssf =",self.getsymval('{auth_ssf}'), "INTERNAL"
|
"ssf =",self.getsymval('{auth_ssf}'), "INTERNAL"
|
||||||
)
|
)
|
||||||
@@ -113,11 +109,13 @@ class dkimMilter(Milter.Base):
|
|||||||
def header(self,name,val):
|
def header(self,name,val):
|
||||||
lname = name.lower()
|
lname = name.lower()
|
||||||
if lname == 'dkim-signature':
|
if lname == 'dkim-signature':
|
||||||
self.log("%s: %s" % (name,val))
|
if milterconfig.get('Syslog'):
|
||||||
|
syslog.syslog("%s: %s" % (name,val))
|
||||||
self.has_dkim += 1
|
self.has_dkim += 1
|
||||||
if lname == 'from':
|
if lname == 'from':
|
||||||
fname,self.author = parseaddr(val)
|
fname,self.author = parseaddr(val)
|
||||||
self.log("%s: %s" % (name,val))
|
if milterconfig.get('Syslog'):
|
||||||
|
syslog.syslog("%s: %s" % (name,val))
|
||||||
elif lname == 'authentication-results':
|
elif lname == 'authentication-results':
|
||||||
self.arheaders.append(val)
|
self.arheaders.append(val)
|
||||||
if self.fp:
|
if self.fp:
|
||||||
@@ -147,7 +145,8 @@ class dkimMilter(Milter.Base):
|
|||||||
ar = authres.AuthenticationResultsHeader.parse_value(FWS.sub('',val))
|
ar = authres.AuthenticationResultsHeader.parse_value(FWS.sub('',val))
|
||||||
if ar.authserv_id == self.receiver:
|
if ar.authserv_id == self.receiver:
|
||||||
self.chgheader('authentication-results',i,'')
|
self.chgheader('authentication-results',i,'')
|
||||||
self.log('REMOVE: ',val)
|
if milterconfig.get('Syslog'):
|
||||||
|
syslog.syslog('REMOVE: ',val)
|
||||||
# Check or sign DKIM
|
# Check or sign DKIM
|
||||||
self.fp.seek(0)
|
self.fp.seek(0)
|
||||||
if self.internal_connection or conf.get('Mode') == 's' or conf.get('Mode') == 'sv':
|
if self.internal_connection or conf.get('Mode') == 's' or conf.get('Mode') == 'sv':
|
||||||
@@ -162,7 +161,8 @@ class dkimMilter(Milter.Base):
|
|||||||
if self.arresults:
|
if self.arresults:
|
||||||
h = authres.AuthenticationResultsHeader(authserv_id = self.receiver,
|
h = authres.AuthenticationResultsHeader(authserv_id = self.receiver,
|
||||||
results=self.arresults)
|
results=self.arresults)
|
||||||
self.log(h)
|
if milterconfig.get('Syslog'):
|
||||||
|
syslog.syslog(h)
|
||||||
name,val = str(h).split(': ',1)
|
name,val = str(h).split(': ',1)
|
||||||
self.addheader(name,val,0)
|
self.addheader(name,val,0)
|
||||||
return Milter.CONTINUE
|
return Milter.CONTINUE
|
||||||
@@ -170,20 +170,22 @@ class dkimMilter(Milter.Base):
|
|||||||
def sign_dkim(self,txt):
|
def sign_dkim(self,txt):
|
||||||
conf = self.conf
|
conf = self.conf
|
||||||
try:
|
try:
|
||||||
d = dkim.DKIM(txt,logger=conf.log)
|
d = dkim.DKIM(txt)
|
||||||
h = d.sign(conf.selector,conf.domain,conf.key,
|
h = d.sign(conf.get('Selector'),conf.get('Domain'),conf.get('KeyFile'),
|
||||||
canonicalize=('relaxed','simple'))
|
canonicalize=('relaxed','simple'))
|
||||||
name,val = h.split(': ',1)
|
name,val = h.split(': ',1)
|
||||||
self.addheader(name,val.strip().replace('\r\n','\n'),0)
|
self.addheader(name,val.strip().replace('\r\n','\n'),0)
|
||||||
except dkim.DKIMException as x:
|
except dkim.DKIMException as x:
|
||||||
self.log('DKIM: %s'%x)
|
if milterconfig.get('Syslog'):
|
||||||
|
syslog.syslog('DKIM: %s'%x)
|
||||||
except Exception as x:
|
except Exception as x:
|
||||||
conf.log.error("sign_dkim: %s",x,exc_info=True)
|
if milterconfig.get('Syslog'):
|
||||||
|
syslog.syslog("sign_dkim: %s",x,exc_info=True)
|
||||||
|
|
||||||
def check_dkim(self,txt):
|
def check_dkim(self,txt):
|
||||||
res = False
|
res = False
|
||||||
conf = self.conf
|
conf = self.conf
|
||||||
d = dkim.DKIM(txt,logger=conf.log)
|
d = dkim.DKIM(txt)
|
||||||
for y in range(self.has_dkim): # Verify _ALL_ the signatures
|
for y in range(self.has_dkim): # Verify _ALL_ the signatures
|
||||||
try:
|
try:
|
||||||
res = d.verify(idx=y)
|
res = d.verify(idx=y)
|
||||||
@@ -193,20 +195,24 @@ class dkimMilter(Milter.Base):
|
|||||||
self.dkim_comment = 'Bad %d bit signature.' % d.keysize
|
self.dkim_comment = 'Bad %d bit signature.' % d.keysize
|
||||||
except dkim.DKIMException as x:
|
except dkim.DKIMException as x:
|
||||||
self.dkim_comment = str(x)
|
self.dkim_comment = str(x)
|
||||||
#self.log('DKIM: %s'%x)
|
if milterconfig.get('Syslog'):
|
||||||
|
syslog.syslog('DKIM: %s'%x)
|
||||||
except Exception as x:
|
except Exception as x:
|
||||||
self.dkim_comment = str(x)
|
self.dkim_comment = str(x)
|
||||||
conf.log.error("check_dkim: %s",x,exc_info=True)
|
if milterconfig.get('Syslog'):
|
||||||
|
syslog.syslog("check_dkim: %s",x,exc_info=True)
|
||||||
self.header_i = d.signature_fields.get(b'i')
|
self.header_i = d.signature_fields.get(b'i')
|
||||||
self.header_d = d.signature_fields.get(b'd')
|
self.header_d = d.signature_fields.get(b'd')
|
||||||
if res:
|
if res:
|
||||||
#self.log('DKIM: Pass (%s)'%d.domain)
|
if milterconfig.get('Syslog'):
|
||||||
|
syslog.syslog('DKIM: Pass (%s)'%d.domain)
|
||||||
self.dkim_domain = d.domain
|
self.dkim_domain = d.domain
|
||||||
else:
|
else:
|
||||||
fd,fname = tempfile.mkstemp(".dkim")
|
fd,fname = tempfile.mkstemp(".dkim")
|
||||||
with os.fdopen(fd,"w+b") as fp:
|
with os.fdopen(fd,"w+b") as fp:
|
||||||
fp.write(txt)
|
fp.write(txt)
|
||||||
self.log('DKIM: Fail (saved as %s)'%fname)
|
if milterconfig.get('Syslog'):
|
||||||
|
syslog.syslog('DKIM: Fail (saved as %s)'%fname)
|
||||||
if res:
|
if res:
|
||||||
result = 'pass'
|
result = 'pass'
|
||||||
else:
|
else:
|
||||||
@@ -226,6 +232,9 @@ def main():
|
|||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
configFile = sys.argv[1]
|
configFile = sys.argv[1]
|
||||||
milterconfig = config._processConfigFile(filename = configFile)
|
milterconfig = config._processConfigFile(filename = configFile)
|
||||||
|
if milterconfig.get('Syslog'):
|
||||||
|
syslog.openlog(os.path.basename(sys.argv[0]), syslog.LOG_PID, syslog.LOG_MAIL)
|
||||||
|
setExceptHook()
|
||||||
drop_privileges(milterconfig)
|
drop_privileges(milterconfig)
|
||||||
Milter.factory = dkimMilter(milterconfig)
|
Milter.factory = dkimMilter(milterconfig)
|
||||||
Milter.set_flags(Milter.CHGHDRS + Milter.ADDHDRS)
|
Milter.set_flags(Milter.CHGHDRS + Milter.ADDHDRS)
|
||||||
|
|||||||
Reference in New Issue
Block a user