From 5e2cff5e5dd4d5a3604a65f183192572449a6432 Mon Sep 17 00:00:00 2001 From: Scott Kitterman Date: Fri, 2 Mar 2018 16:14:46 -0500 Subject: [PATCH] - Fold added authres header fields - Fix pidfile permissions - Fix socket setup sequence so Unix sockets work --- CHANGES | 5 ++++- dkimpy_milter/__init__.py | 9 +++++--- dkimpy_milter/util.py | 46 +++++++++++++++++++++++++-------------- 3 files changed, 40 insertions(+), 20 deletions(-) diff --git a/CHANGES b/CHANGES index 7c3a926..c40cc5e 100644 --- a/CHANGES +++ b/CHANGES @@ -1,8 +1,11 @@ -0.9.3 UNRELEASED +0.9.3 2018-03-02 - Fixup csl dataset processing for single item lists - file: dataset support - Bump minimum authres version to 1.1.0 due to known issues with 1.0.2 - Ignore errors parsing broken authres header fields + - Fold added authres header fields + - Fix pidfile permissions + - Fix socket setup sequence so Unix sockets work 0.9.2 2018-02-19 - Improved package requirements definition diff --git a/dkimpy_milter/__init__.py b/dkimpy_milter/__init__.py index 39beb15..bb3becc 100644 --- a/dkimpy_milter/__init__.py +++ b/dkimpy_milter/__init__.py @@ -39,6 +39,7 @@ 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 __version__ = "0.9.3" FWS = re.compile(r'\r?\n[ \t]+') @@ -171,6 +172,7 @@ class dkimMilter(Milter.Base): if self.arresults: h = authres.AuthenticationResultsHeader(authserv_id = self.receiver, results=self.arresults) + h = dkim.fold(str(h)) if milterconfig.get('Syslog'): syslog.syslog(str(h)) name,val = str(h).split(': ',1) @@ -273,15 +275,16 @@ def main(): privateRSA = read_keyfile(milterconfig, 'RSA') if milterconfig.get('KeyFileEd25519'): privateEd25519 = read_keyfile(milterconfig, 'Ed25519') - drop_privileges(milterconfig) - if milterconfig.get('Syslog'): - syslog.syslog('dkimpy-milter started:{0} user:{1}'.format(pid,milterconfig.get('UserID'))) Milter.factory = dkimMilter Milter.set_flags(Milter.CHGHDRS + Milter.ADDHDRS) miltername = 'dkimpy-filter' socketname = milterconfig.get('Socket') + if milterconfig.get('Syslog'): + syslog.syslog('dkimpy-milter started:{0} user:{1}'.format(pid,milterconfig.get('UserID'))) sys.stdout.flush() Milter.runmilter(miltername,socketname,240) + own_socketfile(milterconfig) + drop_privileges(milterconfig) if __name__ == "__main__": main() diff --git a/dkimpy_milter/util.py b/dkimpy_milter/util.py index d8473da..57c476c 100644 --- a/dkimpy_milter/util.py +++ b/dkimpy_milter/util.py @@ -16,10 +16,23 @@ # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -def drop_privileges(milterconfig): - import os +def user_group(userid): + """Return user and group from UserID""" import grp import pwd + + userlist = userid.split(':') + if len(userlist) == 1: + gidname = userlist[0] + else: + gidname = userlist[1] + # Get the uid/gid from the name + running_uid = pwd.getpwnam(userlist[0]).pw_uid + running_gid = grp.getgrnam(gidname).gr_gid + return running_uid, running_gid + +def drop_privileges(milterconfig): + import os import syslog if os.getuid() != 0: @@ -27,25 +40,15 @@ def drop_privileges(milterconfig): syslog.syslog('drop_privileges: Not running as root. Cannot drop permissions.') return - # Figure out if user and group are specified - userstr = milterconfig.get('UserID') - userlist = userstr.split(':') - if len(userlist) == 1: - gidname = userlist[0] - else: - gidname = userlist[1] - uidname = userlist[0] - - # Get the uid/gid from the name - running_uid = pwd.getpwnam(uidname).pw_uid - running_gid = grp.getgrnam(gidname).gr_gid + # Get user and group + uid, gid = user_group(milterconfig.get('UserID')) # Remove group privileges os.setgroups([]) # Try setting the new uid/gid - os.setgid(running_gid) - os.setuid(running_uid) + os.setgid(gid) + os.setuid(uid) # Set umask old_umask = os.umask(milterconfig.get('UMask')) @@ -88,12 +91,23 @@ def write_pid(milterconfig): raise f.write(pid) f.close() + user, group = user_group(milterconfig.get('UserID')) + os.chown(milterconfig.get('PidFile'), user, group) else: if milterconfig.get('Syslog'): syslog.syslog('Unable to write pidfle {0}. File exists.'.format(milterconfig.get('PidFile'))) raise RuntimeError('Unable to write pidfle {0}. File exists.'.format(milterconfig.get('PidFile'))) 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."""