better filtering
[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         return True
11
12 def allowRSync(run):
13         if len(run) < 3: return False
14         if run[0] != "rsync": return False
15         if run[1] != "--server": return False
16         return True
17
18 def allowSFTP(run):
19         if len(run) != 1: return False
20         return run[0] == "/usr/lib/openssh/sftp-server"
21
22 allowCommands = [allowSCP, allowRSync, allowSFTP]
23 commandPaths = ["/usr/bin", "/bin"]
24
25 # END of Configuration
26 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
27 # DO NOT TOUCH ANYTHING BELOW THIS LINE
28
29 import logging, logging.handlers
30 import os, sys, shlex, pwd
31
32 logger = logging.getLogger("schsh")
33 logger.setLevel(logging.INFO)
34 logger.addHandler(logging.handlers.SysLogHandler(address = '/dev/log',
35                                                 facility = logging.handlers.SysLogHandler.LOG_AUTH))
36
37 def get_username():
38     return pwd.getpwuid(os.getuid()).pw_name
39
40 def log(msg, lvl = logging.INFO):
41         logger.log(lvl, "%s[%d]: <%s> %s" % ("schsh", os.getpid(), get_username(), msg))
42
43 def logquit(msg):
44         log(msg, logging.ERROR)
45         sys.exit(1)
46
47 def commandAllowed(run):
48         for allowed in allowCommands:
49                 if allowed(run):
50                         return True
51         return False
52
53 def addPath(prog):
54         if prog.startswith("/"):
55                 return prog
56         # look for it in the paths
57         for path in commandPaths:
58                 fullprog = os.path.join(path, prog)
59                 if os.path.exists(fullprog):
60                         return fullprog
61         return None
62
63 # parse arguments
64 run = []
65 if len(sys.argv) == 1:
66         if shell is None:
67                 print "No shell for you!"
68                 logquit("Shell access not allowed")
69         else:
70                 run = [shell]
71 elif len(sys.argv) == 3 and sys.argv[1] == "-c":
72         # check if the command is allowed, and add path
73         run = shlex.split(sys.argv[2])
74         if commandAllowed(run):
75                 run[0] = addPath(run[0])
76                 log("Running '"+str(run)+"'")
77         else:
78                 print "You are not allowed to run this command."
79                 logquit("Attempt to run invalid command '"+sys.argv[2]+"'")
80 else:
81         logquit("Invalid arguments for schsh: "+str(sys.argv))
82
83 assert len(run) > 0
84 os.execl("/usr/bin/schroot", "/usr/bin/schroot", "-c", "schsh-"+get_username(), "-d", "/data", "--", *run)