Wrappers for safely calling commands in a new PAG
authorAlex Dehnert <adehnert@mit.edu>
Sun, 16 Sep 2012 01:53:40 +0000 (21:53 -0400)
committerAlex Dehnert <adehnert@mit.edu>
Sun, 16 Sep 2012 01:53:40 +0000 (21:53 -0400)
The usual mechanism for starting a new PAG is pagsh(1). Unfortunately, because
it basically just execvp(3) /bin/sh passing the appropriate arguments, it isn't
immediately obvious how to safely pass arguments that may contain shell
metacharacters. By using the shell's exec and taking advantage of the fact that
later arguments to /bin/sh end up in $@ we can safely avoid shell
metacharacters. We wrap subprocess.check_{call,output} in
pag_check_{call,output}, which perform appropriate contortions to establish the
PAG before safely executing the passed commands without evaluating any
metacharacters.

__init__.py

index 62ec848eea86c20692bfbdd13bf0bafa15b4a54d..8f9356d04f4e774aa48ab88b9456a44a9798450a 100644 (file)
@@ -1,3 +1,4 @@
+import os
 import subprocess
 import ldap
 import ldap.filter
@@ -29,6 +30,32 @@ def UrlOrAfsValidator(value):
         except ValidationError:
             raise ValidationError('Provide a valid URL or AFS path')
 
+def pag_check_helper(fn, args, aklog=False, ccname=None, **kwargs):
+    if 'executable' in kwargs:
+        raise ValueError('"executable" not supported with pag_check_*')
+
+    env = None
+    if 'env' in kwargs:
+        env = kwargs['env']
+        del kwargs['env']
+    if ccname:
+        if env is not None:
+            env = dict(env)
+        else:
+            env = dict(os.environ)
+        env['KRB5CCNAME'] = ccname
+
+    pagsh_cmd = 'exec "$@"'
+    if aklog: pagsh_cmd = "aklog && " + pagsh_cmd
+    args = ['pagsh', '-c', pagsh_cmd, 'exec', ] + args
+
+    return fn(args, env=env, **kwargs)
+
+def pag_check_call(args, **kwargs):
+    return pag_check_helper(subprocess.check_call, args, **kwargs)
+def pag_check_output(args, **kwargs):
+    return pag_check_helper(subprocess.check_output, args, **kwargs)
+
 class ScriptsRemoteUserMiddleware(RemoteUserMiddleware):
     header = 'SSL_CLIENT_S_DN_Email'