switch to Python 3; allow command verifiers to change the command
[schsh.git] / schsh
1 #!/usr/bin/python3
2 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
3 # Configuration
4 shell = None # set to "/bin/bash" or similar to allow shell access
5
6 def allowSCP(run, runstr):
7         if len(run) != 3: return False
8         if run[0] != "scp": return False
9         if run[1] not in ("-f", "-t"): return False
10         if run[2].startswith('-'): return False
11         run[0] = "/usr/bin/scp"
12         return True
13
14 def allowRSync(run, runstr):
15         if len(run) < 3: return False
16         if run[0] != "rsync": return False
17         if run[1] != "--server": return False
18         run[0] = "/usr/bin/rsync"
19         return True
20
21 def allowSFTP(run, runstr):
22         return runstr == "/usr/lib/openssh/sftp-server"
23
24 allowCommands = [allowSCP, allowRSync, allowSFTP]
25
26 # END of Configuration
27 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
28 # DO NOT TOUCH ANYTHING BELOW THIS LINE
29
30 import logging, logging.handlers
31 import os, sys, shlex, pwd
32
33 logger = logging.getLogger("schsh")
34 logger.setLevel(logging.INFO)
35 logger.addHandler(logging.handlers.SysLogHandler(address = '/dev/log',
36                                                 facility = logging.handlers.SysLogHandler.LOG_AUTH))
37
38 def get_username():
39     return pwd.getpwuid(os.getuid()).pw_name
40
41 def log(msg, lvl = logging.INFO):
42         logger.log(lvl, "%s[%d]: <%s> %s" % ("schsh", os.getpid(), get_username(), msg))
43
44 def logquit(msg):
45         log(msg, logging.ERROR)
46         sys.exit(1)
47
48 def commandAllowed(run, runstr):
49         for allowed in allowCommands:
50                 if allowed(run, runstr):
51                         return True
52         return False
53
54 # parse arguments
55 run = []
56 if len(sys.argv) == 1:
57         if shell is None:
58                 print("No shell for you!")
59                 logquit("Shell access not allowed")
60         else:
61                 run = [shell]
62 elif len(sys.argv) == 3 and sys.argv[1] == "-c":
63         # check if the command is allowed, and add path
64         run = shlex.split(sys.argv[2])
65         if commandAllowed(run, sys.argv[2]): # this may change run, but that's okay
66                 log("Running '"+str(run)+"'")
67         else:
68                 print("You are not allowed to run this command.")
69                 logquit("Attempt to run invalid command '"+sys.argv[2]+"'")
70 else:
71         logquit("Invalid arguments for schsh: "+str(sys.argv))
72
73 assert len(run) > 0
74 os.execl("/usr/bin/schroot", "/usr/bin/schroot", "-c", "schsh-"+get_username(), "-d", "/data", "--", *run)