import os as OS; ENV = OS.environ
import shlex as SL
import sys as SYS
+import syslog as L
from auto import HOME, VERSION
import cgi as CGI
'default': ENV.get('CHPWD_CONFIG',
OS.path.join(HOME, 'chpwd.conf')),
'help': 'read configuration from FILE.' }),
+ ('-i', '--ignore-policy', {
+ 'dest': 'ignpol', 'default': False, 'action': 'store_true',
+ 'help': 'ignore the operation policy (for administrators)' }),
('-s', '--ssl', {
'dest': 'sslp', 'action': 'store_true',
'help': 'pretend CGI connection is carried over SSL/TLS' }),
'help': "impersonate USER, and default context to `userv'." })]:
OPTPARSE.add_option(short, long, **props)
+def parse_options():
+ """
+ Parse the main command-line options, returning the positional arguments.
+ """
+ global OPTS
+ OPTS, args = OPTPARSE.parse_args()
+ OPTPARSE.show_global_opts = False
+ CFG.OPTS = OPTS
+ ## It's tempting to load the configuration here. Don't do that. Some
+ ## contexts will want to check that the command line was handled properly
+ ## upstream before believing it for anything, such as executing arbitrary
+ ## Python code.
+ return args
+
###--------------------------------------------------------------------------
### CGI dispatch.
## issuing redirects in the early setup phase fails because we don't know
## the script name. So package the setup here.
def cgi_setup(ctx = 'cgi-noauth'):
- global OPTS
if OPTS: return
OPTPARSE.context = ctx
- OPTS, args = OPTPARSE.parse_args()
+ args = parse_options()
if args: raise U.ExpectedError, (500, 'Unexpected arguments to CGI')
CONF.loadconfig(OPTS.config)
D.opendb()
if __name__ == '__main__':
+ L.openlog(OS.path.basename(SYS.argv[0]), 0, L.LOG_AUTH)
+
if 'REQUEST_METHOD' in ENV:
## This looks like a CGI request. The heavy lifting for authentication
## over HTTP is done in `dispatch_cgi'.
with OUT.redirect_to(CGI.HTTPOutput()):
- with CGI.cgi_errors(cgi_setup): dispatch_cgi()
+ with U.Escape() as CGI.HEADER_DONE:
+ with CGI.cgi_errors(cgi_setup):
+ dispatch_cgi()
elif 'USERV_SERVICE' in ENV:
## This is a Userv request. The caller's user name is helpfully in the
## `USERV_USER' environment variable.
with cli_errors():
- OPTS, args = OPTPARSE.parse_args()
- CONF.loadconfig(OPTS.config)
- try: CU.set_user(ENV['USERV_USER'])
- except KeyError: raise ExpectedError, (500, 'USERV_USER unset')
with OUT.redirect_to(O.FileOutput()):
- OPTPARSE.dispatch('userv', [ENV['USERV_SERVICE']] + args)
+ args = parse_options()
+ if not args or args[0] != 'userv':
+ raise U.ExpectedError, (500, 'missing userv token')
+ CONF.loadconfig(OPTS.config)
+ try: CU.set_user(ENV['USERV_USER'])
+ except KeyError: raise ExpectedError, (500, 'USERV_USER unset')
+ OPTPARSE.dispatch('userv', [ENV['USERV_SERVICE']] + args[1:])
elif 'SSH_ORIGINAL_COMMAND' in ENV:
## This looks like an SSH request; but we present two different
def ssh_setup():
"""Extract and parse the client's request from where SSH left it."""
- global OPTS
- OPTS, args = OPTPARSE.parse_args()
+ args = parse_options()
CONF.loadconfig(OPTS.config)
cmd = SL.split(ENV['SSH_ORIGINAL_COMMAND'])
if args: raise U.ExpectedError, (500, 'Unexpected arguments via SSH')
## of telling us that this is a user request, so treat it like Userv.
with cli_errors():
- cmd = ssh_setup()
- CU.set_user(ENV['CHPWD_SSH_USER'])
- S.SERVICES['master'].find(CU.USER)
with OUT.redirect_to(O.FileOutput()):
+ cmd = ssh_setup()
+ CU.set_user(ENV['CHPWD_SSH_USER'])
OPTPARSE.dispatch('userv', cmd)
elif 'CHPWD_SSH_MASTER' in ENV:
## a user.
try:
- cmd = ssh_setup()
with OUT.redirect_to(O.RemoteOutput()):
+ cmd = ssh_setup()
OPTPARSE.dispatch('remote', map(CGI.urldecode, cmd))
except U.ExpectedError, e:
print 'ERR', e.code, e.msg
## as we are.
with cli_errors():
- OPTS, args = OPTPARSE.parse_args()
- CONF.loadconfig(OPTS.config)
- CGI.SSLP = OPTS.sslp
- ctx = OPTS.context
- if OPTS.user:
- CU.set_user(OPTS.user)
- CGI.STATE.kw['user'] = OPTS.user
- if ctx is None: ctx = 'userv'
- else:
- D.opendb()
- if ctx is None: ctx = 'admin'
with OUT.redirect_to(O.FileOutput()):
+ args = parse_options()
+ CONF.loadconfig(OPTS.config)
+ CGI.SSLP = OPTS.sslp
+ ctx = OPTS.context
+ if OPTS.user:
+ CU.set_user(OPTS.user)
+ CGI.STATE.kw['user'] = OPTS.user
+ if ctx is None: ctx = 'userv'
+ else:
+ D.opendb()
+ if ctx is None:
+ ctx = 'admin'
+ OPTPARSE.show_global_opts = True
OPTPARSE.dispatch(ctx, args)
###----- That's all, folks --------------------------------------------------