diff --git a/Makefile b/Makefile index b9f4ebf..46cf1ea 100644 --- a/Makefile +++ b/Makefile @@ -1,24 +1,24 @@ tmpfile := $(shell mktemp /tmp/epfl_roaming.XXXXXX) .PHONY: install install: test -d /usr/local || mkdir -p /usr/local test -d /usr/local/bin || mkdir /usr/local/bin test -d /usr/local/etc || mkdir /usr/local/etc test -d /usr/local/lib || mkdir /usr/local/lib test -d /usr/local/lib/manage_cred || mkdir -m 700 /usr/local/lib/manage_cred test -d /etc/skel/.config/autostart || mkdir -p /etc/skel/.config/autostart test -d /etc/systemd/system || mkdir -p /etc/systemd/system apt-get -y install python-ldap grep -v 'manage_cred.py' /etc/pam.d/common-auth > $(tmpfile) cat $(tmpfile) root/etc/pam.d/common-auth > /etc/pam.d/common-auth grep -v 'epfl_roaming.py' /etc/pam.d/common-session > $(tmpfile) cat $(tmpfile) root/etc/pam.d/common-session > /etc/pam.d/common-session rm -f $(tmpfile) install -o root -g root -m 755 root/usr/local/bin/manage_cred.py /usr/local/bin install -o root -g root -m 755 root/usr/local/bin/epfl_roaming.py /usr/local/bin - install -o root -g root -m 755 root/usr/local/lib/manage_cred/ext_epfl_roaming.py /usr/local/lib/manage_cred + install -o root -g root -m 600 root/usr/local/lib/manage_cred/ext_epfl_roaming.py /usr/local/lib/manage_cred install -o root -g root -m 644 root/usr/local/etc/epfl_roaming.conf /usr/local/etc install -o root -g root -m 644 root/etc/skel/.config/autostart/epfl_roaming.desktop /etc/skel/.config/autostart install -o root -g root -m 644 root/etc/systemd/system/epfl_roaming_on_shutdown.service /etc/systemd/system systemctl enable epfl_roaming_on_shutdown.service diff --git a/root/usr/local/bin/manage_cred.py b/root/usr/local/bin/manage_cred.py index f736676..0e2938d 100755 --- a/root/usr/local/bin/manage_cred.py +++ b/root/usr/local/bin/manage_cred.py @@ -1,111 +1,130 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- """ manage_cred : receives user credentials during pam auth. It keeps it until MANAGE_CRED_TIMEOUT. Other applications (extensions) can ask it to do operations that need credentials. Extensions have to configure themselves with an /usr/local/lib/manage_cred/app.py They have to implement : + FLAG_FILE : the file that flags it's epfl_roaming that sent USR1 signal to manage_cred + run(username, password) method that does the job """ import os import sys import time +import stat import signal import importlib MANAGE_CRED_TIMEOUT = 20 # sec EXT_FOLDER = "/usr/local/lib/manage_cred" VAR_RUN = "/var/run/manage_cred" PID_FILE = "/var/run/manage_cred/manage_cred_{username}.pid" class PID(): def __init__(self): self.pid_file = PID_FILE.format(username=USERNAME) def __enter__(self): with open(self.pid_file, "w") as f: f.write("%s\n" % os.getpid()) def __exit__(self, typ, val, tb): os.unlink(self.pid_file) def fork_and_wait(): def signal_USR1_handler(signum, frame): an_ext_was_run = False for ext in extensions: if os.path.exists(extensions[ext].FLAG_FILE): an_ext_was_run = True print "Running extension %s." % ext extensions[ext].run(USERNAME, PASSWORD) try: os.unlink(extensions[ext].FLAG_FILE) except: pass print "done." if not an_ext_was_run: print "got USR1 signal, but no extension were run." def signal_KILL_handler(signum, frame): print "got TERM signal, gonna exit." sys.exit(0) if os.fork() != 0: return with PID(): extensions = {} # SIGUSR1 and SIGTERM handling signal.signal(signal.SIGUSR1, signal_USR1_handler) signal.signal(signal.SIGTERM, signal_KILL_handler) + # Check that Extension folder has correct rights : root:root 0x700 + ext_folder_stat = os.stat(EXT_FOLDER) + if (ext_folder_stat.st_uid != 0 or + ext_folder_stat.st_gid != 0 or + ext_folder_stat.st_mode & (stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO) != stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR): + print "Error, extensions folder %s doesn't have correct rights : root:root 0x700.\nAborting." % EXT_FOLDER + sys.exit(1) + sys.path.insert(0, EXT_FOLDER) for f in os.listdir(EXT_FOLDER): if f == "__init__.py" or not f.endswith(".py"): continue + + # check extension has correct rights : root:root 0x600 + ext_path = os.path.join(EXT_FOLDER, f) + ext_stat = os.stat(ext_path) + if (ext_stat.st_uid != 0 or + ext_stat.st_gid != 0 or + ext_stat.st_mode & (stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO) != stat.S_IRUSR | stat.S_IWUSR): + print "Error, extensions %s doesn't have correct rights : root:root 0x600.\nSkipping." % ext_path + continue + try: ext_name = f[:-3] mod = importlib.import_module(ext_name) if ("FLAG_FILE" in dir(mod) and "run" in dir(mod) and type(mod.FLAG_FILE) == str and callable(mod.run)): extensions[ext_name] = mod else: print "Error, %s doesn't implement required variables and functions; Skipping." % ext_name except Exception, e: print "Error, could not import %s; Skipping." % ext_name print e for i in range(MANAGE_CRED_TIMEOUT): time.sleep(1) print "Finished to wait for %i seconds; exiting." % MANAGE_CRED_TIMEOUT if __name__ == "__main__": USERNAME = os.environ["PAM_USER"] SERVICE = os.environ["PAM_SERVICE"] TYPE = os.environ["PAM_TYPE"] print "USERNAME %s" % USERNAME print "SERVICE %s" % SERVICE print "TYPE %s" % TYPE if TYPE != "auth": sys.exit(0) PASSWORD = sys.stdin.readline().rstrip(chr(0)) try: os.makedirs(VAR_RUN) except OSError: pass fork_and_wait() sys.exit(0)