Continue moving towards a working system:

- Move exception hook from config into util
 - Make config data conversion work for all used types
 - Make syslog work (still need to make it only work if specified)
This commit is contained in:
Scott Kitterman
2018-02-13 23:16:44 -05:00
parent 96223823e0
commit c523afe8e5
3 changed files with 53 additions and 73 deletions
+6 -31
View File
@@ -22,6 +22,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.""" 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA."""
import sys import sys
import syslog
import Milter import Milter
import dkim import dkim
from dkim.dnsplug import get_txt from dkim.dnsplug import get_txt
@@ -37,38 +38,11 @@ from Milter.config import MilterConfigParser
from Milter.utils import iniplist,parse_addr,parseaddr from Milter.utils import iniplist,parse_addr,parseaddr
import dkimpy_milter.config as config import dkimpy_milter.config as config
from dkimpy_milter.util import drop_privileges from dkimpy_milter.util import drop_privileges
from dkimpy_milter.util import setExceptHook
def read_config(list):
"Return new config object."
for fn in list:
if os.access(fn,os.R_OK):
logging.config.fileConfig(fn)
break
cp = MilterConfigParser()
cp.read(list)
if cp.has_option('milter','datadir'):
os.chdir(cp.get('milter','datadir'))
conf = Config()
conf.log = logging.getLogger('dkim-milter')
conf.log.info('logging started')
conf.socketname = cp.getdefault('milter','socketname', '/tmp/dkimmiltersock')
conf.miltername = cp.getdefault('milter','name','pydkimfilter')
conf.internal_connect = cp.getlist('milter','internal_connect')
# DKIM section
if cp.has_option('dkim','privkey'):
conf.keyfile = cp.getdefault('dkim','privkey')
conf.selector = cp.getdefault('dkim','selector','default')
conf.domain = cp.getdefault('dkim','domain')
conf.reject = cp.getdefault('dkim','reject')
if conf.keyfile and conf.domain:
try:
with open(conf.keyfile,'r') as kf:
conf.key = kf.read()
except:
conf.log.error('Unable to read: %s',conf.keyfile)
return conf
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."
@@ -272,8 +246,9 @@ def main():
print('usage: dkimpy-milter [<configfilename>]') print('usage: dkimpy-milter [<configfilename>]')
sys.exit(1) sys.exit(1)
configFile = sys.argv[1] configFile = sys.argv[1]
print('configfile', configFile)
milterconfig = config._processConfigFile(filename = configFile) milterconfig = config._processConfigFile(filename = configFile)
print('Socket', milterconfig.get('Socket'))
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)
+23 -42
View File
@@ -27,17 +27,17 @@
import syslog import syslog
import os import os
import sys import sys
import string
import re import re
import urllib import urllib
import stat import stat
import dkim
# default values # default values
defaultConfigData = { defaultConfigData = {
'Syslog' : 'yes', 'Syslog' : 'yes',
'SyslogFacility' : 'mail', 'SyslogFacility' : 'mail',
'UMask' : '007', 'UMask' : 007,
'Mode' : 'sv', 'Mode' : 'sv',
'Socket' : 'local:/var/run/dkimpy-milter/dkimpy-milter.sock', 'Socket' : 'local:/var/run/dkimpy-milter/dkimpy-milter.sock',
'PidFile' : '/var/run/dkimpy-milter/dkimpy-milter.pid', 'PidFile' : '/var/run/dkimpy-milter/dkimpy-milter.pid',
@@ -51,7 +51,6 @@ class ConfigException(Exception):
'''Exception raised when there's a configuration file error.''' '''Exception raised when there's a configuration file error.'''
pass pass
#################################################################### ####################################################################
def _processConfigFile(filename = None, configdata = None, useSyslog = 1, def _processConfigFile(filename = None, configdata = None, useSyslog = 1,
useStderr = 0): useStderr = 0):
@@ -62,8 +61,9 @@ def _processConfigFile(filename = None, configdata = None, useSyslog = 1,
if configdata == None: configdata = config.defaultConfigData if configdata == None: configdata = config.defaultConfigData
if filename != None: if filename != None:
try: try:
readConfigFile(filename, configdata) _readConfigFile(filename, configdata)
except Exception, e: except Exception, e:
raise
if useSyslog: if useSyslog:
syslog.syslog(e.args[0]) syslog.syslog(e.args[0])
if useStderr: if useStderr:
@@ -71,46 +71,22 @@ def _processConfigFile(filename = None, configdata = None, useSyslog = 1,
sys.exit(1) sys.exit(1)
return(configdata) return(configdata)
#################
# FIXME - still uses string, refactor
class ExceptHook:
def __init__(self, useSyslog = 1, useStderr = 0):
self.useSyslog = useSyslog
self.useStderr = useStderr
def __call__(self, etype, evalue, etb):
import traceback
tb = traceback.format_exception(*(etype, evalue, etb))
tb = map(string.rstrip, tb)
tb = string.join(tb, '\n')
for line in string.split(tb, '\n'):
if self.useSyslog:
syslog.syslog(line)
if self.useStderr:
sys.stderr.write(line + '\n')
#################### ####################
def setExceptHook(): def _find_boolean(item):
sys.excepthook = ExceptHook(useSyslog = 1, useStderr = 1) if type(item) == int:
item = str(item)
#################### if item[0] in ["T", "t", "Y", "y", "1"]:
def find_boolean(item): item = True
if type(item) == int: elif item[0] in ["F", "f", "N", "n", "0"]:
item = str(item) item = False
if item[0] in ["T", "t", "Y", "y", "1"]: else:
item = True raise dkim.ParameterError()
elif item[0] in ["F", "f", "N", "n", "0"]: return item
item = False
else:
raise dkim.ParameterError()
return item
############################################################### ###############################################################
commentRx = re.compile(r'^(.*)#.*$') commentRx = re.compile(r'^(.*)#.*$')
def readConfigFile(path, configData = None, configGlobal = {}): def _readConfigFile(path, configData = None, configGlobal = {}):
'''Reads a configuration file from the specified path, merging it '''Reads a configuration file from the specified path, merging it
with the configuration data specified in configData. Returns a with the configuration data specified in configData. Returns a
dictionary of name/value pairs based on configData and the values dictionary of name/value pairs based on configData and the values
@@ -124,7 +100,7 @@ def readConfigFile(path, configData = None, configGlobal = {}):
'Syslog' : 'bool', 'Syslog' : 'bool',
'SyslogFacility' : 'str', 'SyslogFacility' : 'str',
'SyslogSuccess' : 'bool', 'SyslogSuccess' : 'bool',
'UMask' : 'str', 'UMask' : 'int',
'Mode' : 'str', 'Mode' : 'str',
'Socket' : 'str', 'Socket' : 'str',
'PidFile' : 'str', 'PidFile' : 'str',
@@ -175,9 +151,14 @@ def readConfigFile(path, configData = None, configGlobal = {}):
if debugLevel >= 5: syslog.syslog('readConfigFile: Found entry "%s=%s"' if debugLevel >= 5: syslog.syslog('readConfigFile: Found entry "%s=%s"'
% ( name, value )) % ( name, value ))
if value == bool: if conversion == 'bool':
configData[name] = find_boolean(name) configData[name] = _find_boolean(value)
elif conversion == 'str':
configData[name] = str(value)
elif conversion == 'int':
configData[name] = int(value)
else: else:
syslog.syslog(str('name: ' + name + ' value: ' + value + ' conversion: ' + conversion))
configData[name] = conversion(value) configData[name] = conversion(value)
fp.close() fp.close()
+24
View File
@@ -50,3 +50,27 @@ def drop_privileges(milterconfig):
# Set umask # Set umask
old_umask = os.umask(milterconfig.get('UMask')) old_umask = os.umask(milterconfig.get('UMask'))
#################
# FIXME - still uses string, refactor
class ExceptHook:
def __init__(self, useSyslog = 1, useStderr = 0):
self.useSyslog = useSyslog
self.useStderr = useStderr
def __call__(self, etype, evalue, etb):
import traceback
import string
tb = traceback.format_exception(*(etype, evalue, etb))
tb = map(string.rstrip, tb)
tb = string.join(tb, '\n')
for line in string.split(tb, '\n'):
if self.useSyslog:
import syslog
syslog.syslog(line)
####################
def setExceptHook():
import sys
sys.excepthook = ExceptHook(useSyslog = 1, useStderr = 1)