Compare commits

..

13 Commits

Author SHA1 Message Date
Scott Kitterman 539d50325b Fix typo in log message 2020-01-15 09:17:53 -05:00
Scott Kitterman 04dd916ab2 Add release date for 1.0.3 2019-11-22 20:40:13 -05:00
Scott Kitterman 34b2edbb50 - 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:34:26 -04:00
Scott Kitterman d117330113 Make error logging more explicit to aid debugging 2019-10-18 23:33:36 -04:00
Scott Kitterman 2528632ba6 Release 1.0.2 2019-10-07 00:14:20 -04:00
Scott Kitterman 3ea22f1529 Spelling fix 2019-10-07 00:14:03 -04:00
Scott Kitterman 097e053309 Update README now that sysv init is tested 2019-10-06 00:15:30 -04:00
Scott Kitterman 419d2b54ea Set version in setup.py to 1.0.2~rc1 2019-10-05 21:51:43 -04:00
Scott Kitterman 3ff685205c Fix sysv init so it works (LP: #1839487) 2019-10-05 21:50:47 -04:00
Scott Kitterman 7986de6629 - Catch more ascii encoding errors to improve resilience against bad data
(LP: #1844189)
2019-09-23 11:52:17 -04:00
Scott Kitterman 5322c81027 0Fix variable initialization so mailformed mails missing body From do not
cause a traceback (LP: #1844161)
2019-09-16 20:09:55 -04:00
Scott Kitterman 94538ffa6b Fix startup logging so it provides information at a useful time 2019-09-06 00:44:04 -04:00
Scott Kitterman 721da801fe - Fix message extraction so that signing in the same pass through the milter
as verifying works correctly
2019-09-05 23:57:36 -04:00
6 changed files with 67 additions and 38 deletions
+17
View File
@@ -1,3 +1,20 @@
1.0.3 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.0.2 2019-10-07
- Fix startup logging so it provides information at a useful time
- Fix message extraction so that signing in the same pass through the milter
as verifying works correctly
- 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)
- Fix sysv init so it works (LP: #1839487)
1.0.1 2019-02-11
* Reorder milter start and dropping privileges so permissions on Unix socket
are correct (LP: 1797720)
+3 -4
View File
@@ -37,7 +37,7 @@ an C compiler. Alternately, install these dependencies from dsitribution/OS
packages and then pip install dkimpy_milter.
The milter will work with either pydns (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.
+37 -16
View File
@@ -36,7 +36,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"
@@ -54,6 +53,7 @@ class dkimMilter(Milter.Base):
self.privatersa = privateRSA
self.privateed25519 = privateEd25519
self.fp = None
self.fdomain = ''
@Milter.noreply
def connect(self, hostname, unused, hostaddr):
@@ -133,14 +133,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("%s: %s\n" % (name, val))
try:
self.fp.write("%s: %s\n" % (name, val))
except:
# Don't choke on header fields with garbage in them.
pass
return Milter.CONTINUE
@Milter.noreply
@@ -174,20 +178,19 @@ class dkimMilter(Milter.Base):
except:
# Don't error out on unparseable AR header fiels
pass
# Check or sign DKIM
# Check and/or sign DKIM
self.fp.seek(0)
txt = self.fp.read()
if milterconfig.get('Domain'):
domain = milterconfig.get('Domain')
else:
domain = ''
if ((self.fdomain in domain) and not milterconfig.get('Mode') == 'v'
and not self.external_connection):
txt = self.fp.read()
self.sign_dkim(txt)
if ((self.has_dkim) and (not self.internal_connection) and
(milterconfig.get('Mode') == 'v' or
milterconfig.get('Mode') == 'sv')):
txt = self.fp.read()
self.check_dkim(txt)
if self.arresults:
h = authres.AuthenticationResultsHeader(authserv_id=
@@ -255,6 +258,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:
@@ -280,10 +284,21 @@ class dkimMilter(Milter.Base):
except Exception as x:
self.dkim_comment = str(x)
if milterconfig.get('Syslog'):
syslog.syslog("check_dkim: {0}".format(x))
self.header_i = d.signature_fields.get(b'i')
self.header_d = d.signature_fields.get(b'd')
self.header_a = d.signature_fields.get(b'a')
syslog.syslog("check_dkim: Internal program fault while verifying: {0}".format(x))
try:
self.header_i = d.signature_fields.get(b'i')
except TypeError as x:
self.header_i = None
try:
self.header_d = d.signature_fields.get(b'd')
self.header_a = d.signature_fields.get(b'a')
except Exception as x:
self.dkim_comment = str(x)
if milterconfig.get('Syslog'):
syslog.syslog("check_dkim: Internal proram fault 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
@@ -303,20 +318,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
@@ -348,13 +370,12 @@ def main():
Milter.set_flags(Milter.CHGHDRS + Milter.ADDHDRS)
miltername = 'dkimpy-filter'
socketname = milterconfig.get('Socket')
own_socketfile(milterconfig)
drop_privileges(milterconfig)
sys.stdout.flush()
Milter.runmilter(miltername, socketname, 240)
if milterconfig.get('Syslog'):
syslog.syslog('dkimpy-milter started:{0} user:{1}'
syslog.syslog('dkimpy-milter starting:{0} user:{1}'
.format(pid, milterconfig.get('UserID')))
Milter.runmilter(miltername, socketname, 240)
if __name__ == "__main__":
main()
-10
View File
@@ -146,16 +146,6 @@ def write_pid(milterconfig):
return pid
def own_socketfile(milterconfig):
"""If socket is Unix socket, chown to UserID before dropping privileges"""
import os
user, group = user_group(milterconfig.get('UserID'))
if milterconfig.get('Socket')[:1] == '/':
os.chown(milterconfig.get('Socket')[1:], user, group)
if milterconfig.get('Socket')[:6] == "local:":
os.chown(milterconfig.get('Socket')[6:], 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.0.1',
version='1.0.3',
author='Scott Kitterman',
author_email='scott@kitterman.com',
url='https://launchpad.net/dkimpy-milter',
+9 -7
View File
@@ -20,9 +20,9 @@
### END INIT INFO
prefix="/usr/local"
exec_prefix=${prefix}
sysconfdir="/etc/dkimpy-milter"
sysconfdir="/usr/local/etc"
bindir="${exec_prefix}/bin/"
RUNDIR="/var/run/dkimpy-milter"
RUNDIR="/run/dkimpy-milter"
DAEMON=${bindir}/dkimpy-milter
PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin:
NAME=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."
;;