Changeset View
Changeset View
Standalone View
Standalone View
saslauthd/__init__.py
Show All 19 Lines | """ | ||||
SASL authentication daemon for multi-domain Kolab deployments. | SASL authentication daemon for multi-domain Kolab deployments. | ||||
The SASL authentication daemon can use the domain name space or realm | The SASL authentication daemon can use the domain name space or realm | ||||
in the login credentials to determine the backend authentication | in the login credentials to determine the backend authentication | ||||
database, and authenticate the credentials supplied against that | database, and authenticate the credentials supplied against that | ||||
backend. | backend. | ||||
""" | """ | ||||
from __future__ import print_function | |||||
from optparse import OptionParser | from optparse import OptionParser | ||||
from ConfigParser import SafeConfigParser | from ConfigParser import SafeConfigParser | ||||
import grp | import grp | ||||
import os | import os | ||||
import pwd | import pwd | ||||
import shutil | import shutil | ||||
import sys | import sys | ||||
▲ Show 20 Lines • Show All 64 Lines • ▼ Show 20 Lines | def __init__(self): | ||||
conf.finalize_conf() | conf.finalize_conf() | ||||
try: | try: | ||||
utils.ensure_directory( | utils.ensure_directory( | ||||
os.path.dirname(conf.pidfile), | os.path.dirname(conf.pidfile), | ||||
conf.process_username, | conf.process_username, | ||||
conf.process_groupname | conf.process_groupname | ||||
) | ) | ||||
except Exception, errmsg: | except Exception as errmsg: | ||||
log.error(_("Could not create %r: %r") % (os.path.dirname(conf.pidfile), errmsg)) | log.error(_("Could not create %r: %r") % (os.path.dirname(conf.pidfile), errmsg)) | ||||
sys.exit(1) | sys.exit(1) | ||||
self.thread_count = 0 | self.thread_count = 0 | ||||
def run(self): | def run(self): | ||||
""" | """ | ||||
Run the SASL authentication daemon. | Run the SASL authentication daemon. | ||||
Show All 39 Lines | def run(self): | ||||
os.umask(old_umask) | os.umask(old_umask) | ||||
self.thread_count += 1 | self.thread_count += 1 | ||||
log.remove_stdout_handler() | log.remove_stdout_handler() | ||||
self.set_signal_handlers() | self.set_signal_handlers() | ||||
self.write_pid() | self.write_pid() | ||||
self.do_saslauthd() | self.do_saslauthd() | ||||
except SystemExit, e: | except SystemExit as e: | ||||
exitcode = e | exitcode = e | ||||
except KeyboardInterrupt: | except KeyboardInterrupt: | ||||
exitcode = 1 | exitcode = 1 | ||||
log.info(_("Interrupted by user")) | log.info(_("Interrupted by user")) | ||||
except AttributeError, e: | except AttributeError: | ||||
exitcode = 1 | exitcode = 1 | ||||
traceback.print_exc() | traceback.print_exc() | ||||
print >> sys.stderr, _("Traceback occurred, please report a " + | print(_("Traceback occurred, please report a " + | ||||
"bug at https://issues.kolab.org") | "bug at https://issues.kolab.org"), | ||||
except TypeError, e: | file=sys.stderr) | ||||
except TypeError as e: | |||||
exitcode = 1 | exitcode = 1 | ||||
traceback.print_exc() | traceback.print_exc() | ||||
log.error(_("Type Error: %s") % e) | log.error(_("Type Error: %s") % e) | ||||
except: | except: | ||||
exitcode = 2 | exitcode = 2 | ||||
traceback.print_exc() | traceback.print_exc() | ||||
print >> sys.stderr, _("Traceback occurred, please report a " + | print(_("Traceback occurred, please report a " + | ||||
"bug at https://issues.kolab.org") | "bug at https://issues.kolab.org"), | ||||
file=sys.stderr) | |||||
sys.exit(exitcode) | sys.exit(exitcode) | ||||
def do_saslauthd(self): | def do_saslauthd(self): | ||||
""" | """ | ||||
Create the actual listener socket, and handle the authentication. | Create the actual listener socket, and handle the authentication. | ||||
The actual authentication handling is passed on to the appropriate | The actual authentication handling is passed on to the appropriate | ||||
backend authentication classes through the more generic Auth(). | backend authentication classes through the more generic Auth(). | ||||
""" | """ | ||||
import binascii | import binascii | ||||
import socket | import socket | ||||
import struct | import struct | ||||
s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) | s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) | ||||
# TODO: The saslauthd socket path could be a setting. | # TODO: The saslauthd socket path could be a setting. | ||||
try: | try: | ||||
os.remove(conf.socketfile) | os.remove(conf.socketfile) | ||||
except: | except: | ||||
# TODO: Do the "could not remove, could not start" dance | # TODO: Do the "could not remove, could not start" dance | ||||
pass | pass | ||||
s.bind(conf.socketfile) | s.bind(conf.socketfile) | ||||
os.chmod(conf.socketfile, 0777) | os.chmod(conf.socketfile, 0o777) | ||||
s.listen(5) | s.listen(5) | ||||
while 1: | while 1: | ||||
max_tries = 20 | max_tries = 20 | ||||
cur_tries = 0 | cur_tries = 0 | ||||
bound = False | bound = False | ||||
while not bound: | while not bound: | ||||
cur_tries += 1 | cur_tries += 1 | ||||
try: | try: | ||||
(clientsocket, address) = s.accept() | (clientsocket, address) = s.accept() | ||||
bound = True | bound = True | ||||
except Exception, errmsg: | except Exception as errmsg: | ||||
log.error( | log.error( | ||||
_("kolab-saslauthd could not accept " + | _("kolab-saslauthd could not accept " + | ||||
"connections on socket: %r") % (errmsg) | "connections on socket: %r") % (errmsg) | ||||
) | ) | ||||
if cur_tries >= max_tries: | if cur_tries >= max_tries: | ||||
log.fatal(_("Maximum tries exceeded, exiting")) | log.fatal(_("Maximum tries exceeded, exiting")) | ||||
sys.exit(1) | sys.exit(1) | ||||
▲ Show 20 Lines • Show All 75 Lines • ▼ Show 20 Lines | def _ensure_socket_dir(self): | ||||
conf.process_groupname | conf.process_groupname | ||||
) | ) | ||||
def _drop_privileges(self): | def _drop_privileges(self): | ||||
try: | try: | ||||
try: | try: | ||||
(ruid, euid, suid) = os.getresuid() | (ruid, euid, suid) = os.getresuid() | ||||
(rgid, egid, sgid) = os.getresgid() | (rgid, egid, sgid) = os.getresgid() | ||||
except AttributeError, errmsg: | except AttributeError: | ||||
ruid = os.getuid() | ruid = os.getuid() | ||||
rgid = os.getgid() | rgid = os.getgid() | ||||
if ruid == 0: | if ruid == 0: | ||||
# Means we can setreuid() / setregid() / setgroups() | # Means we can setreuid() / setregid() / setgroups() | ||||
if rgid == 0: | if rgid == 0: | ||||
# Get group entry details | # Get group entry details | ||||
try: | try: | ||||
( | ( | ||||
group_name, | group_name, | ||||
group_password, | group_password, | ||||
group_gid, | group_gid, | ||||
group_members | group_members | ||||
) = grp.getgrnam(conf.process_groupname) | ) = grp.getgrnam(conf.process_groupname) | ||||
except KeyError: | except KeyError: | ||||
print >> sys.stderr, _("Group %s does not exist") % ( | print(_("Group %s does not exist") % ( | ||||
conf.process_groupname | conf.process_groupname | ||||
) | ), file=sys.stderr) | ||||
sys.exit(1) | sys.exit(1) | ||||
# Set real and effective group if not the same as current. | # Set real and effective group if not the same as current. | ||||
if not group_gid == rgid: | if not group_gid == rgid: | ||||
log.debug( | log.debug( | ||||
_("Switching real and effective group id to %d") % ( | _("Switching real and effective group id to %d") % ( | ||||
group_gid | group_gid | ||||
Show All 12 Lines | def _drop_privileges(self): | ||||
user_uid, | user_uid, | ||||
user_gid, | user_gid, | ||||
user_gecos, | user_gecos, | ||||
user_homedir, | user_homedir, | ||||
user_shell | user_shell | ||||
) = pwd.getpwnam(conf.process_username) | ) = pwd.getpwnam(conf.process_username) | ||||
except KeyError: | except KeyError: | ||||
print >> sys.stderr, _("User %s does not exist") % ( | print(_("User %s does not exist") % ( | ||||
conf.process_username | conf.process_username | ||||
) | ), file=sys.stderr) | ||||
sys.exit(1) | sys.exit(1) | ||||
# Set real and effective user if not the same as current. | # Set real and effective user if not the same as current. | ||||
if not user_uid == ruid: | if not user_uid == ruid: | ||||
log.debug( | log.debug( | ||||
_("Switching real and effective user id to %d") % ( | _("Switching real and effective user id to %d") % ( | ||||
user_uid | user_uid | ||||
), | ), | ||||
level=8 | level=8 | ||||
) | ) | ||||
os.setreuid(user_uid, user_uid) | os.setreuid(user_uid, user_uid) | ||||
except: | except: | ||||
log.error(_("Could not change real and effective uid and/or gid")) | log.error(_("Could not change real and effective uid and/or gid")) |