make sure scp does not get an additional parameter as last argument
[schsh.git] / schsh
1 #!/usr/bin/python
2 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
3 # Configuration
4 shell = None # set to "/bin/bash" or similar to allow shell access
5
6 def allowSCP(run):
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         return True
12
13 def allowRSync(run):
14         if len(run) < 3: return False
15         if run[0] != "rsync": return False
16         if run[1] != "--server": return False
17         return True
18
19 def allowSFTP(run):
20         if len(run) != 1: return False
21         return run[0] == "/usr/lib/openssh/sftp-server"
22
23 allowCommands = [allowSCP, allowRSync, allowSFTP]
24 commandPaths = ["/usr/bin", "/bin"]
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):
49         for allowed in allowCommands:
50                 if allowed(run):
51                         return True
52         return False
53
54 def addPath(prog):
55         if prog.startswith("/"):
56                 return prog
57         # look for it in the paths
58         for path in commandPaths:
59                 fullprog = os.path.join(path, prog)
60                 if os.path.exists(fullprog):
61                         return fullprog
62         return None
63
64 # parse arguments
65 run = []
66 if len(sys.argv) == 1:
67         if shell is None:
68                 print "No shell for you!"
69                 logquit("Shell access not allowed")
70         else:
71                 run = [shell]
72 elif len(sys.argv) == 3 and sys.argv[1] == "-c":
73         # check if the command is allowed, and add path
74         run = shlex.split(sys.argv[2])
75         if commandAllowed(run):
76                 run[0] = addPath(run[0])
77                 log("Running '"+str(run)+"'")
78         else:
79                 print "You are not allowed to run this command."
80                 logquit("Attempt to run invalid command '"+sys.argv[2]+"'")
81 else:
82         logquit("Invalid arguments for schsh: "+str(sys.argv))
83
84 assert len(run) > 0
85 os.execl("/usr/bin/schroot", "/usr/bin/schroot", "-c", "schsh-"+get_username(), "-d", "/data", "--", *run)