Compare commits

..

14 Commits

Author SHA1 Message Date
Scott Kitterman abba014c5c Add release date for 1.1.4 2019-11-22 20:35:38 -05:00
Scott Kitterman 807b1391b2 - Delete own_socketfile to resolve race condition where the permissions
change fails on a Unix socket because it hasn't been created yet (libmilter
   will do this correctly on its own based on umask, the milter doesn't need
   to do it) (LP: #1849712)
2019-10-29 07:15:51 -04:00
Scott Kitterman dcb781c365 Make error logging more explicit to aid debugging 2019-10-18 23:31:34 -04:00
Scott Kitterman 577a971f1a Fix typo in README 2019-10-07 00:41:43 -04:00
Scott Kitterman 59296be0cf Bump version to 1.1.3 2019-10-06 00:14:54 -04:00
Scott Kitterman 4e1fa3c8ff Update README now that sysv init is tested 2019-10-06 00:14:27 -04:00
Scott Kitterman 99899062bb Fix sysv init so it works (LP: #1839487) 2019-10-05 21:48:44 -04:00
Scott Kitterman 6a1705926f Update version/release date for 1.1.2 2019-09-23 13:36:56 -04:00
Scott Kitterman e6f8db9f94 More reslience fixes 2019-09-23 11:36:10 -04:00
Scott Kitterman e63867d517 Merge branch 'stable1.1' of git+ssh://git.launchpad.net/dkimpy-milter into stable1.1 2019-09-23 11:27:33 -04:00
Scott Kitterman 209ad11661 Catch more ascii encoding errors to improve resilience against bad data
(LP: #1844189)
2019-09-23 11:26:10 -04:00
Scott Kitterman 795a914845 Catch more ascii encoding errors to improve resilience against bad data
(LP: #1844189)
2019-09-23 11:04:02 -04:00
Scott Kitterman be92e5c5b1 Catch more ascii encoding errors to improve resilience against bad data
(LP: #1844189)
2019-09-23 10:48:04 -04:00
Scott Kitterman 6910ff1f9a Fix variable initialization so mailformed mails missing body From do not
cause a traceback (LP: #1844161)
2019-09-16 20:08:34 -04:00
6 changed files with 57 additions and 42 deletions
+16
View File
@@ -1,3 +1,19 @@
1.1.4 2019-11-22
- Make error logging more explicit to aid debugging
- Delete own_socketfile to resolve race condition where the permissions
change fails on a Unix socket because it hasn't been created yet (libmilter
will do this correctly on its own based on umask, the milter doesn't need
to do it) (LP: #1849712)
1.1.3 2019-10-06
- Fix sysv init so it works (LP: #1839487)
1.1.2 2019-09-23
- Fix variable initialization so mailformed mails missing body From do not
cause a traceback (LP: #1844161)
- Catch more ascii encoding errors to improve resilience against bad data
(LP: #1844189)
1.1.1 2019-09-06
- Fix startup logging so it provides information at a useful time
- Fix verify processing so missing (optional) i= tag doesn't cause the milter
+3 -4
View File
@@ -37,7 +37,7 @@ an C compiler. Alternately, install these dependencies from distribution/OS
packages and then pip install dkimpy_milter.
The milter will work with either py3dns (DNS) or dnspython (dns), preferring
dnspython is both are available. The dkimpy DKIM module also works with
dnspython if both are available. The dkimpy DKIM module also works with
either.
@@ -84,9 +84,8 @@ MTA INTEGRATION
Both a systemd unit file and a sysv init file are provided. Both make
assumptions about defaults being used, e.g. if a non-standard pidfile name is
used, they will need to be updated. The sysv init file is Debian specific and
untested, since the developers are not using sysv init. Feedback/patches
welcome.
used, they will need to be updated. The sysv init file uses start-stop-deamon
from Debian. It is not portable to systems without that available.
The dkimpy-milter drops priviledges after setup to the user/group specified in
UserID. During initial setup, this system user needs to be manually created.
+29 -10
View File
@@ -37,7 +37,6 @@ from dkimpy_milter.util import drop_privileges
from dkimpy_milter.util import setExceptHook
from dkimpy_milter.util import write_pid
from dkimpy_milter.util import read_keyfile
from dkimpy_milter.util import own_socketfile
from dkimpy_milter.util import fold
__version__ = "1.0.1"
@@ -55,6 +54,7 @@ class dkimMilter(Milter.Base):
self.privatersa = privateRSA
self.privateed25519 = privateEd25519
self.fp = None
self.fdomain = ''
@Milter.noreply
def connect(self, hostname, unused, hostaddr):
@@ -136,14 +136,18 @@ class dkimMilter(Milter.Base):
try:
self.fdomain = self.author.split('@')[1].lower()
except IndexError as er:
self.fdomain = '' # self.author was not a proper email address
pass # self.author was not a proper email address
if (milterconfig.get('Syslog') and
milterconfig.get('debugLevel') >= 1):
syslog.syslog("{0}: {1}".format(name, val))
elif lname == 'authentication-results':
self.arheaders.append(val)
if self.fp:
self.fp.write(b"%s: %s\n" % (codecs.encode(name, 'ascii'), codecs.encode(val, 'ascii')))
try:
self.fp.write(b"%s: %s\n" % (codecs.encode(name, 'ascii'), codecs.encode(val, 'ascii')))
except:
# Don't choke on header fields with non-ascii garbage in them.
pass
return Milter.CONTINUE
@Milter.noreply
@@ -260,6 +264,7 @@ class dkimMilter(Milter.Base):
def check_dkim(self, txt):
res = False
self.header_a = None
for y in range(self.has_dkim): # Verify _ALL_ the signatures
d = dkim.DKIM(txt)
try:
@@ -287,14 +292,22 @@ class dkimMilter(Milter.Base):
except Exception as x:
self.dkim_comment = str(x)
if milterconfig.get('Syslog'):
syslog.syslog("check_dkim: {0}".format(x))
syslog.syslog("check_dkim: Internal program fault while verifying: {0}".format(x))
try:
# i= is optional and dkimpy is fine if it's not provided
self.header_i = codecs.decode(d.signature_fields.get(b'i'), 'ascii')
except TypeError as x:
self.header_i = None
self.header_d = codecs.decode(d.signature_fields.get(b'd'), 'ascii')
self.header_a = codecs.decode(d.signature_fields.get(b'a'), 'ascii')
try:
self.header_d = codecs.decode(d.signature_fields.get(b'd'), 'ascii')
self.header_a = codecs.decode(d.signature_fields.get(b'a'), 'ascii')
except Exception as x:
self.dkim_comment = str(x)
if milterconfig.get('Syslog'):
syslog.syslog("check_dkim: Internal proram fuault extracting header a or d: {0}".format(x))
self.header_d = None
if not self.header_a:
self.header_a = 'rsa-sha256'
if res:
if (milterconfig.get('Syslog') and
(milterconfig.get('SyslogSuccess') or
@@ -314,20 +327,27 @@ class dkimMilter(Milter.Base):
syslog.syslog('DKIM: Fail (saved as {0})'
.format(fname))
else:
syslog.syslog('DKIM: Fail ({0})'.format(d.domain.lower()))
if milterconfig.get('Syslog'):
if d.domain:
syslog.syslog('DKIM: Fail ({0})'
.format(d.domain.lower()))
else:
syslog.syslog('DKIM: Fail, unextractable domain')
if res:
result = 'pass'
else:
result = 'fail'
res = False
self.arresults.append(
authres.DKIMAuthenticationResult(result=result,
if self.header_d:
self.arresults.append(
authres.DKIMAuthenticationResult(result=result,
header_i=self.header_i,
header_d=self.header_d,
header_a=self.header_a,
result_comment=
self.dkim_comment)
)
self.header_a = None
return
# get parent domain to be signed for if fdomain is a subdomain
@@ -380,7 +400,6 @@ def main():
socketname = 'fd:3'
if socketname is None:
socketname = 'local:/var/run/dkimpy-milter/dkimpy-milter.sock'
own_socketfile(milterconfig, socketname)
drop_privileges(milterconfig)
sys.stdout.flush()
if milterconfig.get('Syslog'):
-21
View File
@@ -149,27 +149,6 @@ def write_pid(milterconfig):
return pid
def own_socketfile(milterconfig, sockname=None):
"""If socket is Unix socket, chown to UserID before dropping privileges"""
import os
user, group = user_group(milterconfig.get('UserID'))
offset = None
if sockname is None:
sockname = milterconfig.get('Socket')
if sockname is None:
return
if sockname[:1] == '/':
offset = 0
elif sockname[:6] == "local:":
offset = 6
elif sockname[:5] == "unix:":
offset = 5
if offset is not None:
if os.path.exists(sockname[offset:]):
os.chown(sockname[offset:], user, group)
def read_keyfile(milterconfig, keytype):
"""Read private key from file."""
import syslog
+1 -1
View File
@@ -30,7 +30,7 @@ except ImportError: # If PyDNS is not installed, prefer dnspython
setup(
name='dkimpy-milter',
version='1.1.1',
version='1.1.4',
author='Scott Kitterman',
author_email='scott@kitterman.com',
url='https://launchpad.net/dkimpy-milter',
+8 -6
View File
@@ -20,7 +20,7 @@
### END INIT INFO
prefix="/usr/local"
exec_prefix=${prefix}
sysconfdir="/etc/dkimpy-milter"
sysconfdir="/usr/local/etc"
bindir="${exec_prefix}/bin/"
RUNDIR="/run/dkimpy-milter"
DAEMON=${bindir}/dkimpy-milter
@@ -67,14 +67,14 @@ case "$1" in
fi
fi
fi
start-stop-daemon --start --quiet --pidfile $RUNDIR/$NAME.pid --startas \
$DAEMON $sysconfdir/$NAME.conf --name $NAME --test > /dev/null \
start-stop-daemon --start --background --quiet --pidfile \
$RUNDIR/$NAME.pid --exec $DAEMON $sysconfdir/$NAME.conf
echo "$NAME."
;;
stop)
echo -n "Stopping $DESC: "
if [ -f $RUNDIR/$NAME.pid ]; then
chown root:root $RUNDIR/$NAME.pid
start-stop-daemon --stop --pidfile $RUNDIR/$NAME.pid
rm $RUNDIR/$NAME.pid
#echo $SOCKET
@@ -87,6 +87,7 @@ case "$1" in
force-reload)
echo -n "Force reloading $DESC: "
if [ -f $RUNDIR/$NAME.pid ]; then
chown root:root $RUNDIR/$NAME.pid
start-stop-daemon --stop --pidfile $RUNDIR/$NAME.pid
rm $RUNDIR/$NAME.pid
#echo $SOCKET
@@ -95,7 +96,7 @@ case "$1" in
fi
fi
sleep 1
start-stop-daemon --start --chuid $USER --background --quiet --pidfile \
start-stop-daemon --start --background --quiet --pidfile \
$RUNDIR/$NAME.pid --exec $DAEMON $sysconfdir/$NAME.conf
echo "$NAME."
;;
@@ -103,6 +104,7 @@ case "$1" in
echo "Restarting $DESC: "
echo -n "Stopping $DESC: "
if [ -f $RUNDIR/$NAME.pid ]; then
chown root:root $RUNDIR/$NAME.pid
start-stop-daemon --stop --pidfile $RUNDIR/$NAME.pid
rm $RUNDIR/$NAME.pid
#echo $SOCKET
@@ -113,7 +115,7 @@ case "$1" in
echo "$NAME."
sleep 1
echo -n "Starting $DESC: "
start-stop-daemon --start --chuid $USER --background --quiet --pidfile \
start-stop-daemon --start --background --quiet --pidfile \
$RUNDIR/$NAME.pid --exec $DAEMON $sysconfdir/$NAME.conf
echo "$NAME."
;;