Changeset View
Standalone View
saslauthd/__init__.py
# Copyright 2010-2013 Kolab Systems AG (http://www.kolabsys.com) | # Copyright 2010-2016 Kolab Systems AG (http://www.kolabsys.com) | ||||
# | # | ||||
# Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> | # Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen a kolabsys.com> | ||||
# | # | ||||
# This program is free software: you can redistribute it and/or modify | # This program is free software: you can redistribute it and/or modify | ||||
# it under the terms of the GNU General Public License as published by | # it under the terms of the GNU General Public License as published by | ||||
# the Free Software Foundation, either version 3 of the License, or | # the Free Software Foundation, either version 3 of the License, or | ||||
# (at your option) any later version. | # (at your option) any later version. | ||||
Show All 31 Lines | |||||
from pykolab import utils | from pykolab import utils | ||||
from pykolab.auth import Auth | from pykolab.auth import Auth | ||||
from pykolab.constants import * | from pykolab.constants import * | ||||
from pykolab.translate import _ | from pykolab.translate import _ | ||||
log = pykolab.getLogger('saslauthd') | log = pykolab.getLogger('saslauthd') | ||||
conf = pykolab.getConf() | conf = pykolab.getConf() | ||||
class SASLAuthDaemon(object): | class SASLAuthDaemon(object): | ||||
def __init__(self): | def __init__(self): | ||||
daemon_group = conf.add_cli_parser_option_group(_("Daemon Options")) | daemon_group = conf.add_cli_parser_option_group(_("Daemon Options")) | ||||
daemon_group.add_option( | daemon_group.add_option( | ||||
"--fork", | "--fork", | ||||
dest = "fork_mode", | dest = "fork_mode", | ||||
Lint: PEP8 E221: multiple spaces before operator | |||||
Lint: PEP8 E251 unexpected spaces around keyword / parameter equals Lint: PEP8 E251: unexpected spaces around keyword / parameter equals | |||||
Lint: PEP8 E251 unexpected spaces around keyword / parameter equals Lint: PEP8 E251: unexpected spaces around keyword / parameter equals | |||||
action = "store_true", | action = "store_true", | ||||
Lint: PEP8 E221 multiple spaces before operator Lint: PEP8 E221: multiple spaces before operator | |||||
Lint: PEP8 E251 unexpected spaces around keyword / parameter equals Lint: PEP8 E251: unexpected spaces around keyword / parameter equals | |||||
Lint: PEP8 E251 unexpected spaces around keyword / parameter equals Lint: PEP8 E251: unexpected spaces around keyword / parameter equals | |||||
default = False, | default = False, | ||||
Lint: PEP8 E251 unexpected spaces around keyword / parameter equals Lint: PEP8 E251: unexpected spaces around keyword / parameter equals | |||||
Lint: PEP8 E251 unexpected spaces around keyword / parameter equals Lint: PEP8 E251: unexpected spaces around keyword / parameter equals | |||||
help = _("Fork to the background.") | help = _("Fork to the background.") | ||||
Lint: PEP8 E221 multiple spaces before operator Lint: PEP8 E221: multiple spaces before operator | |||||
Lint: PEP8 E251 unexpected spaces around keyword / parameter equals Lint: PEP8 E251: unexpected spaces around keyword / parameter equals | |||||
Lint: PEP8 E251 unexpected spaces around keyword / parameter equals Lint: PEP8 E251: unexpected spaces around keyword / parameter equals | |||||
) | ) | ||||
daemon_group.add_option( | daemon_group.add_option( | ||||
"-p", | "-p", | ||||
"--pid-file", | "--pid-file", | ||||
dest = "pidfile", | dest = "pidfile", | ||||
Lint: PEP8 E221 multiple spaces before operator Lint: PEP8 E221: multiple spaces before operator | |||||
Lint: PEP8 E251 unexpected spaces around keyword / parameter equals Lint: PEP8 E251: unexpected spaces around keyword / parameter equals | |||||
Lint: PEP8 E251 unexpected spaces around keyword / parameter equals Lint: PEP8 E251: unexpected spaces around keyword / parameter equals | |||||
action = "store", | action = "store", | ||||
Lint: PEP8 E221 multiple spaces before operator Lint: PEP8 E221: multiple spaces before operator | |||||
Lint: PEP8 E251 unexpected spaces around keyword / parameter equals Lint: PEP8 E251: unexpected spaces around keyword / parameter equals | |||||
Lint: PEP8 E251 unexpected spaces around keyword / parameter equals Lint: PEP8 E251: unexpected spaces around keyword / parameter equals | |||||
default = "/var/run/kolab-saslauthd/kolab-saslauthd.pid", | default = "/var/run/kolab-saslauthd/kolab-saslauthd.pid", | ||||
Lint: PEP8 E251 unexpected spaces around keyword / parameter equals Lint: PEP8 E251: unexpected spaces around keyword / parameter equals | |||||
Lint: PEP8 E251 unexpected spaces around keyword / parameter equals Lint: PEP8 E251: unexpected spaces around keyword / parameter equals | |||||
help = _("Path to the PID file to use.") | help = _("Path to the PID file to use.") | ||||
Lint: PEP8 E221 multiple spaces before operator Lint: PEP8 E221: multiple spaces before operator | |||||
Lint: PEP8 E251 unexpected spaces around keyword / parameter equals Lint: PEP8 E251: unexpected spaces around keyword / parameter equals | |||||
Lint: PEP8 E251 unexpected spaces around keyword / parameter equals Lint: PEP8 E251: unexpected spaces around keyword / parameter equals | |||||
) | ) | ||||
daemon_group.add_option( | daemon_group.add_option( | ||||
"-s", | "-s", | ||||
"--socket", | "--socket", | ||||
dest = "socketfile", | dest = "socketfile", | ||||
Lint: PEP8 E221 multiple spaces before operator Lint: PEP8 E221: multiple spaces before operator | |||||
Lint: PEP8 E251 unexpected spaces around keyword / parameter equals Lint: PEP8 E251: unexpected spaces around keyword / parameter equals | |||||
Lint: PEP8 E251 unexpected spaces around keyword / parameter equals Lint: PEP8 E251: unexpected spaces around keyword / parameter equals | |||||
action = "store", | action = "store", | ||||
Lint: PEP8 E221 multiple spaces before operator Lint: PEP8 E221: multiple spaces before operator | |||||
Lint: PEP8 E251 unexpected spaces around keyword / parameter equals Lint: PEP8 E251: unexpected spaces around keyword / parameter equals | |||||
Lint: PEP8 E251 unexpected spaces around keyword / parameter equals Lint: PEP8 E251: unexpected spaces around keyword / parameter equals | |||||
default = "/var/run/saslauthd/mux", | default = "/var/run/saslauthd/mux", | ||||
Lint: PEP8 E251 unexpected spaces around keyword / parameter equals Lint: PEP8 E251: unexpected spaces around keyword / parameter equals | |||||
Lint: PEP8 E251 unexpected spaces around keyword / parameter equals Lint: PEP8 E251: unexpected spaces around keyword / parameter equals | |||||
help = _("Socket file to bind to.") | help = _("Socket file to bind to.") | ||||
Lint: PEP8 E221 multiple spaces before operator Lint: PEP8 E221: multiple spaces before operator | |||||
Lint: PEP8 E251 unexpected spaces around keyword / parameter equals Lint: PEP8 E251: unexpected spaces around keyword / parameter equals | |||||
Lint: PEP8 E251 unexpected spaces around keyword / parameter equals Lint: PEP8 E251: unexpected spaces around keyword / parameter equals | |||||
) | ) | ||||
daemon_group.add_option( | daemon_group.add_option( | ||||
"-u", | "-u", | ||||
"--user", | "--user", | ||||
dest = "process_username", | dest = "process_username", | ||||
Lint: PEP8 E221 multiple spaces before operator Lint: PEP8 E221: multiple spaces before operator | |||||
Lint: PEP8 E251 unexpected spaces around keyword / parameter equals Lint: PEP8 E251: unexpected spaces around keyword / parameter equals | |||||
Lint: PEP8 E251 unexpected spaces around keyword / parameter equals Lint: PEP8 E251: unexpected spaces around keyword / parameter equals | |||||
action = "store", | action = "store", | ||||
Lint: PEP8 E221 multiple spaces before operator Lint: PEP8 E221: multiple spaces before operator | |||||
Lint: PEP8 E251 unexpected spaces around keyword / parameter equals Lint: PEP8 E251: unexpected spaces around keyword / parameter equals | |||||
Lint: PEP8 E251 unexpected spaces around keyword / parameter equals Lint: PEP8 E251: unexpected spaces around keyword / parameter equals | |||||
default = "kolab", | default = "kolab", | ||||
Lint: PEP8 E251 unexpected spaces around keyword / parameter equals Lint: PEP8 E251: unexpected spaces around keyword / parameter equals | |||||
Lint: PEP8 E251 unexpected spaces around keyword / parameter equals Lint: PEP8 E251: unexpected spaces around keyword / parameter equals | |||||
help = _("Run as user USERNAME"), | help = _("Run as user USERNAME"), | ||||
Lint: PEP8 E221 multiple spaces before operator Lint: PEP8 E221: multiple spaces before operator | |||||
Lint: PEP8 E251 unexpected spaces around keyword / parameter equals Lint: PEP8 E251: unexpected spaces around keyword / parameter equals | |||||
Lint: PEP8 E251 unexpected spaces around keyword / parameter equals Lint: PEP8 E251: unexpected spaces around keyword / parameter equals | |||||
metavar = "USERNAME" | metavar = "USERNAME" | ||||
Lint: PEP8 E251 unexpected spaces around keyword / parameter equals Lint: PEP8 E251: unexpected spaces around keyword / parameter equals | |||||
Lint: PEP8 E251 unexpected spaces around keyword / parameter equals Lint: PEP8 E251: unexpected spaces around keyword / parameter equals | |||||
) | ) | ||||
daemon_group.add_option( | daemon_group.add_option( | ||||
"-g", | "-g", | ||||
"--group", | "--group", | ||||
dest = "process_groupname", | dest = "process_groupname", | ||||
Lint: PEP8 E221 multiple spaces before operator Lint: PEP8 E221: multiple spaces before operator | |||||
Lint: PEP8 E251 unexpected spaces around keyword / parameter equals Lint: PEP8 E251: unexpected spaces around keyword / parameter equals | |||||
Lint: PEP8 E251 unexpected spaces around keyword / parameter equals Lint: PEP8 E251: unexpected spaces around keyword / parameter equals | |||||
action = "store", | action = "store", | ||||
Lint: PEP8 E221 multiple spaces before operator Lint: PEP8 E221: multiple spaces before operator | |||||
Lint: PEP8 E251 unexpected spaces around keyword / parameter equals Lint: PEP8 E251: unexpected spaces around keyword / parameter equals | |||||
Lint: PEP8 E251 unexpected spaces around keyword / parameter equals Lint: PEP8 E251: unexpected spaces around keyword / parameter equals | |||||
default = "kolab", | default = "kolab", | ||||
Lint: PEP8 E251 unexpected spaces around keyword / parameter equals Lint: PEP8 E251: unexpected spaces around keyword / parameter equals | |||||
Lint: PEP8 E251 unexpected spaces around keyword / parameter equals Lint: PEP8 E251: unexpected spaces around keyword / parameter equals | |||||
help = _("Run as group GROUPNAME"), | help = _("Run as group GROUPNAME"), | ||||
Lint: PEP8 E221 multiple spaces before operator Lint: PEP8 E221: multiple spaces before operator | |||||
Lint: PEP8 E251 unexpected spaces around keyword / parameter equals Lint: PEP8 E251: unexpected spaces around keyword / parameter equals | |||||
Lint: PEP8 E251 unexpected spaces around keyword / parameter equals Lint: PEP8 E251: unexpected spaces around keyword / parameter equals | |||||
metavar = "GROUPNAME" | metavar = "GROUPNAME" | ||||
Lint: PEP8 E251 unexpected spaces around keyword / parameter equals Lint: PEP8 E251: unexpected spaces around keyword / parameter equals | |||||
Lint: PEP8 E251 unexpected spaces around keyword / parameter equals Lint: PEP8 E251: unexpected spaces around keyword / parameter equals | |||||
) | ) | ||||
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, 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)) | ||||
Lint: PEP8 E501 line too long (93 > 79 characters) Lint: PEP8 E501: line too long (93 > 79 characters) | |||||
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 20 Lines • Show All 44 Lines • ▼ Show 20 Lines | def run(self): | ||||
except SystemExit, e: | except SystemExit, 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, e: | ||||
exitcode = 1 | exitcode = 1 | ||||
traceback.print_exc() | traceback.print_exc() | ||||
print >> sys.stderr, _("Traceback occurred, please report a bug at https://issues.kolab.org") | print >> sys.stderr, _("Traceback occurred, please report a " + | ||||
"bug at https://issues.kolab.org") | |||||
except TypeError, e: | except TypeError, 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 bug at https://issues.kolab.org") | print >> sys.stderr, _("Traceback occurred, please report a " + | ||||
"bug at https://issues.kolab.org") | |||||
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 | ||||
Show All 23 Lines | def do_saslauthd(self): | ||||
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, 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) | ||||
time.sleep(1) | time.sleep(1) | ||||
received = clientsocket.recv(4096) | received = clientsocket.recv(4096) | ||||
login = [] | login = [] | ||||
start = 0 | start = 0 | ||||
end = 2 | end = 2 | ||||
while end < len(received): | while end < len(received): | ||||
(length,) = struct.unpack("!H", received[start:end]) | (length,) = struct.unpack("!H", received[start:end]) | ||||
start += 2 | start += 2 | ||||
end += length | end += length | ||||
(value,) = struct.unpack("!%ds" % (length), received[start:end]) | (value,) = struct.unpack("!%ds" % (length), received[start:end]) | ||||
Lint: PEP8 E501 line too long (80 > 79 characters) Lint: PEP8 E501: line too long (80 > 79 characters) | |||||
start += length | start += length | ||||
end = start + 2 | end = start + 2 | ||||
login.append(value) | login.append(value) | ||||
if len(login) == 4: | if len(login) == 4: | ||||
realm = login[3] | realm = login[3] | ||||
elif len(login[0].split('@')) > 1: | elif len(login[0].split('@')) > 1: | ||||
realm = login[0].split('@')[1] | realm = login[0].split('@')[1] | ||||
else: | else: | ||||
realm = conf.get('kolab', 'primary_domain') | realm = conf.get('kolab', 'primary_domain') | ||||
auth = Auth(domain=realm) | auth = Auth(domain=realm) | ||||
auth.connect() | auth.connect() | ||||
success = False | success = False | ||||
try: | try: | ||||
success = auth.authenticate(login) | success = auth.authenticate(login) | ||||
except: | except: | ||||
success = False | success = False | ||||
if success: | if success: | ||||
# #1170: Catch broken pipe error (incomplete authentication request) | # #1170: Catch broken pipe error (incomplete authentication request) | ||||
Lint: PEP8 E501 line too long (84 > 79 characters) Lint: PEP8 E501: line too long (84 > 79 characters) | |||||
try: | try: | ||||
clientsocket.send(struct.pack("!H2s", 2, "OK")) | clientsocket.send(struct.pack("!H2s", 2, "OK")) | ||||
except: | except: | ||||
pass | pass | ||||
else: | else: | ||||
# #1170: Catch broken pipe error (incomplete authentication request) | # #1170: Catch broken pipe error (incomplete authentication request) | ||||
Lint: PEP8 E501 line too long (84 > 79 characters) Lint: PEP8 E501: line too long (84 > 79 characters) | |||||
try: | try: | ||||
clientsocket.send(struct.pack("!H2s", 2, "NO")) | clientsocket.send(struct.pack("!H2s", 2, "NO")) | ||||
except: | except: | ||||
pass | pass | ||||
clientsocket.close() | clientsocket.close() | ||||
auth.disconnect() | auth.disconnect() | ||||
def reload_config(self, *args, **kw): | def reload_config(self, *args, **kw): | ||||
pass | pass | ||||
def remove_pid(self, *args, **kw): | def remove_pid(self, *args, **kw): | ||||
if os.access(conf.pidfile, os.R_OK): | if os.access(conf.pidfile, os.R_OK): | ||||
os.remove(conf.pidfile) | os.remove(conf.pidfile) | ||||
raise SystemExit | raise SystemExit | ||||
def set_signal_handlers(self): | def set_signal_handlers(self): | ||||
import signal | import signal | ||||
signal.signal(signal.SIGHUP, self.reload_config) | signal.signal(signal.SIGHUP, self.reload_config) | ||||
signal.signal(signal.SIGTERM, self.remove_pid) | signal.signal(signal.SIGTERM, self.remove_pid) | ||||
def write_pid(self): | def write_pid(self): | ||||
pid = os.getpid() | pid = os.getpid() | ||||
fp = open(conf.pidfile,'w') | fp = open(conf.pidfile, 'w') | ||||
fp.write("%d\n" % (pid)) | fp.write("%d\n" % (pid)) | ||||
fp.close() | fp.close() | ||||
def _ensure_socket_dir(self): | def _ensure_socket_dir(self): | ||||
utils.ensure_directory( | utils.ensure_directory( | ||||
os.path.dirname(conf.socketfile), | os.path.dirname(conf.socketfile), | ||||
conf.process_username, | conf.process_username, | ||||
conf.process_groupname | conf.process_groupname | ||||
Show All 25 Lines | def _drop_privileges(self): | ||||
conf.process_groupname | conf.process_groupname | ||||
) | ) | ||||
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") % ( | ||||
Lint: PEP8 E501 line too long (84 > 79 characters) Lint: PEP8 E501: line too long (84 > 79 characters) | |||||
group_gid | group_gid | ||||
), | ), | ||||
level=8 | level=8 | ||||
) | ) | ||||
os.setregid(group_gid, group_gid) | os.setregid(group_gid, group_gid) | ||||
if ruid == 0: | if ruid == 0: | ||||
Show All 11 Lines | def _drop_privileges(self): | ||||
except KeyError: | except KeyError: | ||||
print >> sys.stderr, _("User %s does not exist") % ( | print >> sys.stderr, _("User %s does not exist") % ( | ||||
conf.process_username | conf.process_username | ||||
) | ) | ||||
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") % ( | ||||
Lint: PEP8 E501 line too long (83 > 79 characters) Lint: PEP8 E501: line too long (83 > 79 characters) | |||||
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")) |
multiple spaces before operator