From 807db80a3e637f5a8e7083a79e174827ae2339d1 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 13 Feb 2014 15:35:32 +0100 Subject: [PATCH] Initial commit --- Makefile | 7 ++++ makeschsh | 74 +++++++++++++++++++++++++++++++++++++++ schroot/user/copyfiles | 4 +++ schroot/user/nssdatabases | 1 + schsh | 61 ++++++++++++++++++++++++++++++++ sshd_config | 4 +++ 6 files changed, 151 insertions(+) create mode 100644 Makefile create mode 100755 makeschsh create mode 100644 schroot/user/copyfiles create mode 100644 schroot/user/nssdatabases create mode 100755 schsh create mode 100644 sshd_config diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..bd9e5b0 --- /dev/null +++ b/Makefile @@ -0,0 +1,7 @@ +TARGET := /usr/local +SCHROOT := /etc/schroot + +install: + install -o root -g root schsh makeschsh $(TARGET)/bin/ + install -o root -g root -d $(SCHROOT)/user/ + install -o root -g root -m 644 schroot/user/* $(SCHROOT)/user/ diff --git a/makeschsh b/makeschsh new file mode 100755 index 0000000..0dbb0aa --- /dev/null +++ b/makeschsh @@ -0,0 +1,74 @@ +#!/usr/bin/python +#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~# +# Configuration +schsh = "/usr/local/bin/schsh" +group = "schsh" +chroots = "/var/lib/schsh" + +# END of Configuration +#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~# +# DO NOT TOUCH ANYTHING BELOW THIS LINE + +import os, sys, subprocess, pwd, grp + +if os.getuid() != 0: + print "Run this a root, please." + sys.exit(1) + + +def setup(name): + chroot = os.path.join(chroots, name) + if os.path.exists(chroot): + raise Exception(chroot+" already exists, please remove it first") + userpw = pwd.getpwnam(name) + + # schroot configuration + with open("/etc/schroot/chroot.d/user-"+name, "w") as f: + print >>f, """[user-{0}] +type=directory +directory={1} +users={0} +profile=user +setup.fstab=user/user-{0}.fstab +""".format(name, chroot) + with open("/etc/schroot/user/user-"+name+".fstab", "w") as f: + print >>f, """# +/bin \t/bin \tnone \trw,bind \t0 \t0 +/lib \t/lib \tnone \trw,bind \t0 \t0 +/usr/bin \t/usr/bin \tnone \trw,bind \t0 \t0 +/usr/lib \t/usr/lib \tnone \trw,bind \t0 \t0 +/home/{0}/data\t/data \tnone \trw,bind \t0 \t0 +""".replace(' ', '').format(name) # need to remove spaces so schroot does not complain + + # setup the schroot directory + os.mkdir(chroot) + for folder in ["etc", "dev", "bin", "usr", "data"]: + os.mkdir(os.path.join(chroot, folder)) + + # setup /etc/passwd and /etc/group + with open(os.path.join(chroot, "etc", "passwd"), "w") as f: + print >>f, "root:x:0:0:root:/root:/bin/bash" + print >>f, "{0}:x:{1}:{2}:,,,:/data:/bin/false".format(name, userpw.pw_uid, userpw.pw_gid) + with open(os.path.join(chroot, "etc", "group"), "w") as f: + print >>f, "root:x:0:" + usergrp = grp.getgrgid(userpw.pw_gid) + print >>f, "{0}:x:{1}:".format(usergrp.gr_name, usergrp.gr_gid) + if group: + groupgrp = grp.getgrnam(group) + assert usergrp.gr_gid != groupgrp.gr_gid + print >>f, "{0}:x:{1}:{2}".format(groupgrp.gr_name, groupgrp.gr_gid, name) + + # user configuration + if userpw.pw_shell != schsh: + subprocess.check_output(["usermod", "--shell", schsh, name]) + if group: + subprocess.check_output(["adduser", name, "schsh"]) + + # done! + +if len(sys.argv) <= 1: + print "Usage: %s " % sys.argv[0] +else: + for name in sys.argv[1:]: + print "Setting up",name + setup(name) diff --git a/schroot/user/copyfiles b/schroot/user/copyfiles new file mode 100644 index 0000000..f888968 --- /dev/null +++ b/schroot/user/copyfiles @@ -0,0 +1,4 @@ +# Files to copy into the chroot from the host system. +# +# +/dev/null diff --git a/schroot/user/nssdatabases b/schroot/user/nssdatabases new file mode 100644 index 0000000..6f800d9 --- /dev/null +++ b/schroot/user/nssdatabases @@ -0,0 +1 @@ +# Do not copy anything. diff --git a/schsh b/schsh new file mode 100755 index 0000000..270691e --- /dev/null +++ b/schsh @@ -0,0 +1,61 @@ +#!/usr/bin/python +#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~# +# Configuration +shell = None # set to "/bin/bash" or similar to allow shell access +allowCommands = ["scp", "rsync", "/usr/lib/openssh/sftp-server"] +commandPaths = ["/usr/bin", "/bin"] + +# END of Configuration +#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~# +# DO NOT TOUCH ANYTHING BELOW THIS LINE + +import logging, logging.handlers +import os, sys, shlex, pwd + +logger = logging.getLogger("schsh") +logger.setLevel(logging.INFO) +logger.addHandler(logging.handlers.SysLogHandler(address = '/dev/log', + facility = logging.handlers.SysLogHandler.LOG_AUTH)) + +def get_username(): + return pwd.getpwuid(os.getuid()).pw_name + +def log(msg, lvl = logging.INFO): + logger.log(lvl, "%s[%d]: <%s> %s" % ("schsh", os.getpid(), get_username(), msg)) + +def logquit(msg): + log(msg, logging.ERROR) + sys.exit(1) + +def addPath(prog): + if prog.startswith("/"): + return prog + # look for it in the paths + for path in commandPaths: + fullprog = os.path.join(path, prog) + if os.path.exists(fullprog): + return fullprog + return None + +# parse arguments +run = [] +if len(sys.argv) == 1: + if shell is None: + print "No shell for you!" + logquit("Shell access not allowed") + else: + run = [shell] +elif len(sys.argv) == 3 and sys.argv[1] == "-c": + # check if the command is allowed, and add path + run = shlex.split(sys.argv[2]) + if len(run) > 0 and run[0] in allowCommands: + run[0] = addPath(run[0]) + log("Running '"+str(run)+"'") + else: + print "You are not allowed to run this command." + logquit("Attempt to run invalid command '"+sys.argv[2]+"'") +else: + logquit("Invalid arguments for schsh: "+str(sys.argv)) + +assert len(run) > 0 +os.execl("/usr/bin/schroot", "/usr/bin/schroot", "-c", "user-"+get_username(), "-d", "/data", "--", *run) diff --git a/sshd_config b/sshd_config new file mode 100644 index 0000000..7abe96a --- /dev/null +++ b/sshd_config @@ -0,0 +1,4 @@ +Match Group schsh + AllowTcpForwarding no + AllowAgentForwarding no + X11Forwarding no -- 2.30.2