diff -r cceaf7af4c9e hgext/largefiles/uisetup.py --- a/hgext/largefiles/uisetup.py Sat Jun 01 17:09:41 2013 -0500 +++ b/hgext/largefiles/uisetup.py Tue Jul 03 11:25:06 2018 +0200 @@ -11,7 +11,7 @@ from mercurial import archival, cmdutil, commands, extensions, filemerge, hg, \ httppeer, localrepo, merge, scmutil, sshpeer, wireproto, revset from mercurial.i18n import _ -from mercurial.hgweb import hgweb_mod, webcommands +from mercurial.hgweb import webcommands from mercurial.subrepo import hgsubrepo import overrides @@ -134,9 +134,10 @@ # make putlfile behave the same as push and {get,stat}lfile behave # the same as pull w.r.t. permissions checks - hgweb_mod.perms['putlfile'] = 'push' - hgweb_mod.perms['getlfile'] = 'pull' - hgweb_mod.perms['statlfile'] = 'pull' + wireproto.permissions['putlfile'] = 'push' + wireproto.permissions['getlfile'] = 'pull' + wireproto.permissions['statlfile'] = 'pull' + wireproto.permissions['lheads'] = 'pull' extensions.wrapfunction(webcommands, 'decodepath', overrides.decodepath) diff -r cceaf7af4c9e mercurial/hgweb/hgweb_mod.py --- a/mercurial/hgweb/hgweb_mod.py Sat Jun 01 17:09:41 2013 -0500 +++ b/mercurial/hgweb/hgweb_mod.py Tue Jul 03 11:25:06 2018 +0200 @@ -7,7 +7,7 @@ # GNU General Public License version 2 or any later version. import os -from mercurial import ui, hg, hook, error, encoding, templater, util, repoview +from mercurial import ui, hg, hook, error, encoding, templater, util, repoview, wireproto from mercurial.templatefilters import websub from mercurial.i18n import _ from common import get_stat, ErrorResponse, permhooks, caching @@ -16,15 +16,8 @@ from request import wsgirequest import webcommands, protocol, webutil, re -perms = { - 'changegroup': 'pull', - 'changegroupsubset': 'pull', - 'getbundle': 'pull', - 'stream_out': 'pull', - 'listkeys': 'pull', - 'unbundle': 'push', - 'pushkey': 'push', -} +# Aliased for API compatibility. +perms = wireproto.permissions def makebreadcrumb(url, prefix=''): '''Return a 'URL breadcrumb' list @@ -165,8 +158,13 @@ try: if query: raise ErrorResponse(HTTP_NOT_FOUND) - if cmd in perms: - self.check_perm(req, perms[cmd]) + + req.checkperm = lambda op: self.check_perm(req, op) + # Assume commands with no defined permissions are writes / + # for pushes. This is the safest from a security perspective + # because it doesn't allow commands with undefined semantics + # from bypassing permissions checks. + req.checkperm(perms.get(cmd, 'push')) return protocol.call(self.repo, req, cmd) except ErrorResponse, inst: # A client that sends unbundle without 100-continue will diff -r cceaf7af4c9e mercurial/hgweb/protocol.py --- a/mercurial/hgweb/protocol.py Sat Jun 01 17:09:41 2013 -0500 +++ b/mercurial/hgweb/protocol.py Tue Jul 03 11:25:06 2018 +0200 @@ -17,6 +17,7 @@ self.req = req self.response = '' self.ui = ui + self.checkperm = req.checkperm def getargs(self, args): knownargs = self._args() data = {} diff -r cceaf7af4c9e mercurial/wireproto.py --- a/mercurial/wireproto.py Sat Jun 01 17:09:41 2013 -0500 +++ b/mercurial/wireproto.py Tue Jul 03 11:25:06 2018 +0200 @@ -11,6 +11,10 @@ import changegroup as changegroupmod import peer, error, encoding, util, store +# Maps wire protocol name to operation type. This is used for permissions +# checking. +permissions = {} + # abstract batching support class future(object): @@ -361,6 +365,15 @@ % (cmd, ",".join(others))) return opts +def wireprotocommand(name, args=''): + """decorator for wire protocol command""" + def register(func): + commands[name] = (func, args) + return func + return register + +# TODO define a more appropriate permissions type to use for this. +permissions['batch'] = 'pull' def batch(repo, proto, cmds, others): repo = repo.filtered("served") res = [] @@ -372,6 +385,17 @@ n, v = a.split('=') vals[n] = unescapearg(v) func, spec = commands[op] + + # If the protocol supports permissions checking, perform that + # checking on each batched command. + # TODO formalize permission checking as part of protocol interface. + if util.safehasattr(proto, 'checkperm'): + # Assume commands with no defined permissions are writes / for + # pushes. This is the safest from a security perspective because + # it doesn't allow commands with undefined semantics from + # bypassing permissions checks. + proto.checkperm(permissions.get(op, 'push')) + if spec: keys = spec.split() data = {} @@ -392,6 +416,7 @@ res.append(escapearg(result)) return ';'.join(res) +permissions['between'] = 'pull' def between(repo, proto, pairs): pairs = [decodelist(p, '-') for p in pairs.split(" ")] r = [] @@ -399,6 +424,7 @@ r.append(encodelist(b) + "\n") return "".join(r) +permissions['branchmap'] = 'pull' def branchmap(repo, proto): branchmap = repo.branchmap() heads = [] @@ -408,6 +434,7 @@ heads.append('%s %s' % (branchname, branchnodes)) return '\n'.join(heads) +permissions['branches'] = 'pull' def branches(repo, proto, nodes): nodes = decodelist(nodes) r = [] @@ -415,6 +442,7 @@ r.append(encodelist(b) + "\n") return "".join(r) +permissions['capabilities'] = 'pull' def capabilities(repo, proto): caps = ('lookup changegroupsubset branchmap pushkey known getbundle ' 'unbundlehash batch').split() @@ -432,22 +460,26 @@ caps.append('httpheader=1024') return ' '.join(caps) +permissions['changegroup'] = 'pull' def changegroup(repo, proto, roots): nodes = decodelist(roots) cg = repo.changegroup(nodes, 'serve') return streamres(proto.groupchunks(cg)) +permissions['changegroupsubset'] = 'pull' def changegroupsubset(repo, proto, bases, heads): bases = decodelist(bases) heads = decodelist(heads) cg = repo.changegroupsubset(bases, heads, 'serve') return streamres(proto.groupchunks(cg)) +permissions['debugwireargs'] = 'pull' def debugwireargs(repo, proto, one, two, others): # only accept optional args from the known set opts = options('debugwireargs', ['three', 'four'], others) return repo.debugwireargs(one, two, **opts) +permissions['getbundle'] = 'pull' def getbundle(repo, proto, others): opts = options('getbundle', ['heads', 'common'], others) for k, v in opts.iteritems(): @@ -455,10 +487,12 @@ cg = repo.getbundle('serve', **opts) return streamres(proto.groupchunks(cg)) +permissions['heads'] = 'pull' def heads(repo, proto): h = repo.heads() return encodelist(h) + "\n" +permissions['hello'] = 'pull' def hello(repo, proto): '''the hello command returns a set of lines describing various interesting things about the server, in an RFC822-like format. @@ -469,12 +503,14 @@ ''' return "capabilities: %s\n" % (capabilities(repo, proto)) +permissions['listkeys'] = 'pull' def listkeys(repo, proto, namespace): d = repo.listkeys(encoding.tolocal(namespace)).items() t = '\n'.join(['%s\t%s' % (encoding.fromlocal(k), encoding.fromlocal(v)) for k, v in d]) return t +permissions['lookup'] = 'pull' def lookup(repo, proto, key): try: k = encoding.tolocal(key) @@ -486,9 +522,11 @@ success = 0 return "%s %s\n" % (success, r) +permissions['known'] = 'pull' def known(repo, proto, nodes, others): return ''.join(b and "1" or "0" for b in repo.known(decodelist(nodes))) +permissions['pushkey'] = 'push' def pushkey(repo, proto, namespace, key, old, new): # compatibility with pre-1.8 clients which were accidentally # sending raw binary nodes rather than utf-8-encoded hex @@ -523,6 +561,7 @@ def _allowstream(ui): return ui.configbool('server', 'uncompressed', True, untrusted=True) +permissions['stream_out'] = 'pull' def stream(repo, proto): '''If the server supports streaming clone, it advertises the "stream" capability with a value representing the version and flags of the repo @@ -589,6 +628,7 @@ return streamres(streamer(repo, entries, total_bytes)) +permissions['unbundle'] = 'push' def unbundle(repo, proto, heads): their_heads = decodelist(heads) diff -r cceaf7af4c9e tests/get-with-headers.py --- a/tests/get-with-headers.py Sat Jun 01 17:09:41 2013 -0500 +++ b/tests/get-with-headers.py Tue Jul 03 11:25:06 2018 +0200 @@ -3,6 +3,7 @@ """This does HTTP GET requests given a host:port and path and returns a subset of the headers plus the body of the result.""" +import argparse import httplib, sys try: @@ -12,14 +13,22 @@ except ImportError: pass -twice = False -if '--twice' in sys.argv: - sys.argv.remove('--twice') - twice = True -headeronly = False -if '--headeronly' in sys.argv: - sys.argv.remove('--headeronly') - headeronly = True +parser = argparse.ArgumentParser() +parser.add_argument('--twice', action='store_true') +parser.add_argument('--headeronly', action='store_true') +parser.add_argument('--requestheader', nargs='*', default=[], + help='Send an additional HTTP request header. Argument ' + 'value is
=') +parser.add_argument('--bodyfile', + help='Write HTTP response body to a file') +parser.add_argument('host') +parser.add_argument('path') +parser.add_argument('show', nargs='*') +args = parser.parse_args() + +twice = args.twice +headeronly = args.headeronly +requestheaders = args.requestheader reasons = {'Not modified': 'Not Modified'} # python 2.4 @@ -31,6 +40,10 @@ if tag: headers['If-None-Match'] = tag + for header in requestheaders: + key, value = header.split('=', 1) + headers[key] = value + conn = httplib.HTTPConnection(host) conn.request("GET", '/' + path, None, headers) response = conn.getresponse() @@ -44,16 +57,22 @@ if not headeronly: print data = response.read() - sys.stdout.write(data) + if args.bodyfile: + bodyfh = open(args.bodyfile, 'wb') + else: + bodyfh = sys.stdout + bodyfh.write(data) if twice and response.getheader('ETag', None): tag = response.getheader('ETag') + if args.bodyfile: + bodyfh.close() return response.status -status = request(sys.argv[1], sys.argv[2], sys.argv[3:]) +status = request(args.host, args.path, args.show) if twice: - status = request(sys.argv[1], sys.argv[2], sys.argv[3:]) + status = request(args.host, args.path, args.show) if 200 <= status <= 305: sys.exit(0) diff -r cceaf7af4c9e tests/killdaemons.py --- a/tests/killdaemons.py Sat Jun 01 17:09:41 2013 -0500 +++ b/tests/killdaemons.py Tue Jul 03 11:25:06 2018 +0200 @@ -49,6 +49,10 @@ pass if __name__ == '__main__': - path, = sys.argv[1:] + if len(sys.argv) > 1: + path, = sys.argv[1:] + else: + path = os.environ["DAEMON_PIDS"] + killdaemons(path) diff -r cceaf7af4c9e tests/run-tests.py --- a/tests/run-tests.py Sat Jun 01 17:09:41 2013 -0500 +++ b/tests/run-tests.py Tue Jul 03 11:25:06 2018 +0200 @@ -1321,6 +1321,7 @@ os.environ["HGPORT"] = str(options.port) os.environ["HGPORT1"] = str(options.port + 1) os.environ["HGPORT2"] = str(options.port + 2) + os.environ["LOCALIP"] = '127.0.0.1' if options.with_hg: INST = None diff -r cceaf7af4c9e tests/test-http-permissions.t --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test-http-permissions.t Tue Jul 03 11:25:06 2018 +0200 @@ -0,0 +1,1491 @@ +#require killdaemons + + $ cat > fakeremoteuser.py << EOF + > import os + > from mercurial.hgweb import hgweb_mod + > from mercurial import wireproto + > class testenvhgweb(hgweb_mod.hgweb): + > def __call__(self, env, respond): + > # Allow REMOTE_USER to define authenticated user. + > if r'REMOTE_USER' in os.environ: + > env[r'REMOTE_USER'] = os.environ[r'REMOTE_USER'] + > # Allow REQUEST_METHOD to override HTTP method + > if r'REQUEST_METHOD' in os.environ: + > env[r'REQUEST_METHOD'] = os.environ[r'REQUEST_METHOD'] + > return super(testenvhgweb, self).__call__(env, respond) + > hgweb_mod.hgweb = testenvhgweb + > + > @wireproto.wireprotocommand('customreadnoperm') + > def customread(repo, proto): + > return b'read-only command no defined permissions\n' + > @wireproto.wireprotocommand('customwritenoperm') + > def customwritenoperm(repo, proto): + > return b'write command no defined permissions\n' + > wireproto.permissions['customreadwithperm'] = 'pull' + > @wireproto.wireprotocommand('customreadwithperm') + > def customreadwithperm(repo, proto): + > return b'read-only command w/ defined permissions\n' + > wireproto.permissions['customwritewithperm'] = 'push' + > @wireproto.wireprotocommand('customwritewithperm') + > def customwritewithperm(repo, proto): + > return b'write command w/ defined permissions\n' + > EOF + + $ cat >> $HGRCPATH << EOF + > [extensions] + > fakeremoteuser = $TESTTMP/fakeremoteuser.py + > EOF + + $ hg init test + $ cd test + $ echo a > a + $ hg ci -Ama + adding a + $ cd .. + $ hg clone test test2 + updating to branch default + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ cd test2 + $ echo a >> a + $ hg ci -mb + $ hg book bm -r 0 + $ cd ../test + +web.deny_read=* prevents access to wire protocol for all users + + $ cat > .hg/hgrc < [web] + > deny_read = * + > EOF + + $ hg serve -p $HGPORT -d --pid-file hg.pid + $ cat hg.pid > $DAEMON_PIDS + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=capabilities' + 401 read not authorized + + 0 + read not authorized + [1] + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=stream_out' + 401 read not authorized + + 0 + read not authorized + [1] + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=listkeys' --requestheader 'x-hgarg-1=namespace=phases' + 401 read not authorized + + 0 + read not authorized + [1] + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=batch' --requestheader 'x-hgarg-1=cmds=listkeys+namespace%3Dphases' + 401 read not authorized + + 0 + read not authorized + [1] + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=customreadnoperm' + 401 read not authorized + + 0 + read not authorized + [1] + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=customreadwithperm' + 401 read not authorized + + 0 + read not authorized + [1] + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=customwritenoperm' + 401 read not authorized + + 0 + read not authorized + [1] + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=customwritewithperm' + 401 read not authorized + + 0 + read not authorized + [1] + + $ hg --cwd ../test2 pull http://localhost:$HGPORT/ + abort: authorization failed + [255] + + $ "$TESTDIR/killdaemons.py" + +web.deny_read=* with REMOTE_USER set still locks out clients + + $ REMOTE_USER=authed_user hg serve -p $HGPORT -d --pid-file hg.pid + $ cat hg.pid > $DAEMON_PIDS + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=capabilities' + 401 read not authorized + + 0 + read not authorized + [1] + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=stream_out' + 401 read not authorized + + 0 + read not authorized + [1] + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=batch' --requestheader 'x-hgarg-1=cmds=listkeys+namespace%3Dphases' + 401 read not authorized + + 0 + read not authorized + [1] + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=customreadnoperm' + 401 read not authorized + + 0 + read not authorized + [1] + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=customreadwithperm' + 401 read not authorized + + 0 + read not authorized + [1] + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=customwritenoperm' + 401 read not authorized + + 0 + read not authorized + [1] + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=customwritewithperm' + 401 read not authorized + + 0 + read not authorized + [1] + + $ hg --cwd ../test2 pull http://localhost:$HGPORT/ + abort: authorization failed + [255] + + $ "$TESTDIR/killdaemons.py" + +web.deny_read= denies access to unauthenticated user + + $ cat > .hg/hgrc < [web] + > deny_read = baduser1,baduser2 + > EOF + + $ hg serve -p $HGPORT -d --pid-file hg.pid + $ cat hg.pid > $DAEMON_PIDS + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=listkeys' --requestheader 'x-hgarg-1=namespace=phases' + 401 read not authorized + + 0 + read not authorized + [1] + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=batch' --requestheader 'x-hgarg-1=cmds=listkeys+namespace%3Dphases' + 401 read not authorized + + 0 + read not authorized + [1] + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=customreadnoperm' + 401 read not authorized + + 0 + read not authorized + [1] + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=customreadwithperm' + 401 read not authorized + + 0 + read not authorized + [1] + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=customwritenoperm' + 401 read not authorized + + 0 + read not authorized + [1] + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=customwritewithperm' + 401 read not authorized + + 0 + read not authorized + [1] + + $ hg --cwd ../test2 pull http://localhost:$HGPORT/ + abort: authorization failed + [255] + + $ "$TESTDIR/killdaemons.py" + +web.deny_read= denies access to users in deny list + + $ REMOTE_USER=baduser2 hg serve -p $HGPORT -d --pid-file hg.pid + $ cat hg.pid > $DAEMON_PIDS + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=listkeys' --requestheader 'x-hgarg-1=namespace=phases' + 401 read not authorized + + 0 + read not authorized + [1] + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=batch' --requestheader 'x-hgarg-1=cmds=listkeys+namespace%3Dphases' + 401 read not authorized + + 0 + read not authorized + [1] + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=customreadnoperm' + 401 read not authorized + + 0 + read not authorized + [1] + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=customreadwithperm' + 401 read not authorized + + 0 + read not authorized + [1] + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=customwritenoperm' + 401 read not authorized + + 0 + read not authorized + [1] + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=customwritewithperm' + 401 read not authorized + + 0 + read not authorized + [1] + + $ hg --cwd ../test2 pull http://localhost:$HGPORT/ + abort: authorization failed + [255] + + $ "$TESTDIR/killdaemons.py" + +web.deny_read= allows access to authenticated users not in list + + $ REMOTE_USER=gooduser hg serve -p $HGPORT -d --pid-file hg.pid + $ cat hg.pid > $DAEMON_PIDS + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=listkeys' --requestheader 'x-hgarg-1=namespace=phases' + 200 Script output follows + + cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b 1 + publishing True (no-eol) + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=batch' --requestheader 'x-hgarg-1=cmds=listkeys+namespace%3Dphases' + 200 Script output follows + + cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b 1 + publishing True (no-eol) + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=customreadnoperm' + 405 push requires POST request + + 0 + push requires POST request + [1] + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=customreadwithperm' + 200 Script output follows + + read-only command w/ defined permissions + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=customwritenoperm' + 405 push requires POST request + + 0 + push requires POST request + [1] + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=customwritewithperm' + 405 push requires POST request + + 0 + push requires POST request + [1] + + $ hg --cwd ../test2 pull http://localhost:$HGPORT/ + pulling from http://localhost:$HGPORT/ + searching for changes + no changes found + + $ "$TESTDIR/killdaemons.py" + +web.allow_read=* allows reads for unauthenticated users + + $ cat > .hg/hgrc < [web] + > allow_read = * + > EOF + + $ hg serve -p $HGPORT -d --pid-file hg.pid + $ cat hg.pid > $DAEMON_PIDS + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=listkeys' --requestheader 'x-hgarg-1=namespace=phases' + 200 Script output follows + + cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b 1 + publishing True (no-eol) + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=batch' --requestheader 'x-hgarg-1=cmds=listkeys+namespace%3Dphases' + 200 Script output follows + + cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b 1 + publishing True (no-eol) + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=customreadnoperm' + 405 push requires POST request + + 0 + push requires POST request + [1] + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=customreadwithperm' + 200 Script output follows + + read-only command w/ defined permissions + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=customwritenoperm' + 405 push requires POST request + + 0 + push requires POST request + [1] + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=customwritewithperm' + 405 push requires POST request + + 0 + push requires POST request + [1] + + $ hg --cwd ../test2 pull http://localhost:$HGPORT/ + pulling from http://localhost:$HGPORT/ + searching for changes + no changes found + + $ "$TESTDIR/killdaemons.py" + +web.allow_read=* allows read for authenticated user + + $ REMOTE_USER=authed_user hg serve -p $HGPORT -d --pid-file hg.pid + $ cat hg.pid > $DAEMON_PIDS + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=listkeys' --requestheader 'x-hgarg-1=namespace=phases' + 200 Script output follows + + cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b 1 + publishing True (no-eol) + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=batch' --requestheader 'x-hgarg-1=cmds=listkeys+namespace%3Dphases' + 200 Script output follows + + cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b 1 + publishing True (no-eol) + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=customreadnoperm' + 405 push requires POST request + + 0 + push requires POST request + [1] + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=customreadwithperm' + 200 Script output follows + + read-only command w/ defined permissions + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=customwritenoperm' + 405 push requires POST request + + 0 + push requires POST request + [1] + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=customwritewithperm' + 405 push requires POST request + + 0 + push requires POST request + [1] + + $ hg --cwd ../test2 pull http://localhost:$HGPORT/ + pulling from http://localhost:$HGPORT/ + searching for changes + no changes found + + $ "$TESTDIR/killdaemons.py" + +web.allow_read= does not allow unauthenticated users to read + + $ cat > .hg/hgrc < [web] + > allow_read = gooduser + > EOF + + $ hg serve -p $HGPORT -d --pid-file hg.pid + $ cat hg.pid > $DAEMON_PIDS + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=listkeys' --requestheader 'x-hgarg-1=namespace=phases' + 401 read not authorized + + 0 + read not authorized + [1] + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=batch' --requestheader 'x-hgarg-1=cmds=listkeys+namespace%3Dphases' + 401 read not authorized + + 0 + read not authorized + [1] + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=customreadnoperm' + 401 read not authorized + + 0 + read not authorized + [1] + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=customreadwithperm' + 401 read not authorized + + 0 + read not authorized + [1] + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=customwritenoperm' + 401 read not authorized + + 0 + read not authorized + [1] + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=customwritewithperm' + 401 read not authorized + + 0 + read not authorized + [1] + + $ hg --cwd ../test2 pull http://localhost:$HGPORT/ + abort: authorization failed + [255] + + $ "$TESTDIR/killdaemons.py" + +web.allow_read= does not allow user not in list to read + + $ REMOTE_USER=baduser hg serve -p $HGPORT -d --pid-file hg.pid + $ cat hg.pid > $DAEMON_PIDS + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=listkeys' --requestheader 'x-hgarg-1=namespace=phases' + 401 read not authorized + + 0 + read not authorized + [1] + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=batch' --requestheader 'x-hgarg-1=cmds=listkeys+namespace%3Dphases' + 401 read not authorized + + 0 + read not authorized + [1] + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=customreadnoperm' + 401 read not authorized + + 0 + read not authorized + [1] + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=customreadwithperm' + 401 read not authorized + + 0 + read not authorized + [1] + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=customwritenoperm' + 401 read not authorized + + 0 + read not authorized + [1] + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=customwritewithperm' + 401 read not authorized + + 0 + read not authorized + [1] + + $ hg --cwd ../test2 pull http://localhost:$HGPORT/ + abort: authorization failed + [255] + + $ "$TESTDIR/killdaemons.py" + +web.allow_read= allows read from user in list + + $ REMOTE_USER=gooduser hg serve -p $HGPORT -d --pid-file hg.pid + $ cat hg.pid > $DAEMON_PIDS + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=listkeys' --requestheader 'x-hgarg-1=namespace=phases' + 200 Script output follows + + cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b 1 + publishing True (no-eol) + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=batch' --requestheader 'x-hgarg-1=cmds=listkeys+namespace%3Dphases' + 200 Script output follows + + cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b 1 + publishing True (no-eol) + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=customreadnoperm' + 405 push requires POST request + + 0 + push requires POST request + [1] + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=customreadwithperm' + 200 Script output follows + + read-only command w/ defined permissions + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=customwritenoperm' + 405 push requires POST request + + 0 + push requires POST request + [1] + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=customwritewithperm' + 405 push requires POST request + + 0 + push requires POST request + [1] + + $ hg --cwd ../test2 pull http://localhost:$HGPORT/ + pulling from http://localhost:$HGPORT/ + searching for changes + no changes found + + $ "$TESTDIR/killdaemons.py" + +web.deny_read takes precedence over web.allow_read + + $ cat > .hg/hgrc < [web] + > allow_read = baduser + > deny_read = baduser + > EOF + + $ REMOTE_USER=baduser hg serve -p $HGPORT -d --pid-file hg.pid + $ cat hg.pid > $DAEMON_PIDS + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=listkeys' --requestheader 'x-hgarg-1=namespace=phases' + 401 read not authorized + + 0 + read not authorized + [1] + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=batch' --requestheader 'x-hgarg-1=cmds=listkeys+namespace%3Dphases' + 401 read not authorized + + 0 + read not authorized + [1] + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=customreadnoperm' + 401 read not authorized + + 0 + read not authorized + [1] + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=customreadwithperm' + 401 read not authorized + + 0 + read not authorized + [1] + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=customwritenoperm' + 401 read not authorized + + 0 + read not authorized + [1] + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=customwritewithperm' + 401 read not authorized + + 0 + read not authorized + [1] + + $ hg --cwd ../test2 pull http://localhost:$HGPORT/ + abort: authorization failed + [255] + + $ "$TESTDIR/killdaemons.py" + +web.allowpull=false denies read access to repo + + $ cat > .hg/hgrc < [web] + > allowpull = false + > EOF + + $ hg serve -p $HGPORT -d --pid-file hg.pid + $ cat hg.pid > $DAEMON_PIDS + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=capabilities' + 401 pull not authorized + + 0 + pull not authorized + [1] + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=listkeys' --requestheader 'x-hgarg-1=namespace=phases' + 401 pull not authorized + + 0 + pull not authorized + [1] + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=batch' --requestheader 'x-hgarg-1=cmds=listkeys+namespace%3Dphases' + 401 pull not authorized + + 0 + pull not authorized + [1] + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=customreadnoperm' + 405 push requires POST request + + 0 + push requires POST request + [1] + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=customreadwithperm' + 401 pull not authorized + + 0 + pull not authorized + [1] + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=customwritenoperm' + 405 push requires POST request + + 0 + push requires POST request + [1] + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=customwritewithperm' + 405 push requires POST request + + 0 + push requires POST request + [1] + + $ hg --cwd ../test2 pull http://localhost:$HGPORT/ + abort: authorization failed + [255] + + $ "$TESTDIR/killdaemons.py" + +Attempting a write command with HTTP GET fails + + $ cat > .hg/hgrc < EOF + + $ REQUEST_METHOD=GET hg serve -p $HGPORT -d --pid-file hg.pid + $ cat hg.pid > $DAEMON_PIDS + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=pushkey' --requestheader 'x-hgarg-1=namespace=bookmarks&key=bm&old=&new=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b' + 405 push requires POST request + + 0 + push requires POST request + [1] + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=batch' --requestheader 'x-hgarg-1=cmds=pushkey+namespace%3Dbookmarks%2Ckey%3Dbm%2Cold%3D%2Cnew%3Dcb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b' + 405 push requires POST request + + 0 + push requires POST request + [1] + + $ hg bookmarks + no bookmarks set + $ hg bookmark -d bm + abort: bookmark 'bm' does not exist + [255] + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=customwritenoperm' + 405 push requires POST request + + 0 + push requires POST request + [1] + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=customwritewithperm' + 405 push requires POST request + + 0 + push requires POST request + [1] + + $ "$TESTDIR/killdaemons.py" + +Attempting a write command with an unknown HTTP verb fails + + $ REQUEST_METHOD=someverb hg serve -p $HGPORT -d --pid-file hg.pid + $ cat hg.pid > $DAEMON_PIDS + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=pushkey' --requestheader 'x-hgarg-1=namespace=bookmarks&key=bm&old=&new=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b' + 405 push requires POST request + + 0 + push requires POST request + [1] + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=batch' --requestheader 'x-hgarg-1=cmds=pushkey+namespace%3Dbookmarks%2Ckey%3Dbm%2Cold%3D%2Cnew%3Dcb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b' + 405 push requires POST request + + 0 + push requires POST request + [1] + + $ hg bookmarks + no bookmarks set + $ hg bookmark -d bm + abort: bookmark 'bm' does not exist + [255] + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=customwritenoperm' + 405 push requires POST request + + 0 + push requires POST request + [1] + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=customwritewithperm' + 405 push requires POST request + + 0 + push requires POST request + [1] + + $ "$TESTDIR/killdaemons.py" + +Pushing on a plaintext channel is disabled by default + + $ cat > .hg/hgrc < EOF + + $ REQUEST_METHOD=POST hg serve -p $HGPORT -d --pid-file hg.pid + $ cat hg.pid > $DAEMON_PIDS + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=pushkey' --requestheader 'x-hgarg-1=namespace=bookmarks&key=bm&old=&new=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b' + 200 ssl required + + 0 + ssl required + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=batch' --requestheader 'x-hgarg-1=cmds=pushkey+namespace%3Dbookmarks%2Ckey%3Dbm%2Cold%3D%2Cnew%3Dcb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b' + 200 ssl required + + 0 + ssl required + + $ hg bookmarks + no bookmarks set + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=customwritenoperm' + 200 ssl required + + 0 + ssl required + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=customwritewithperm' + 200 ssl required + + 0 + ssl required + +Reset server to remove REQUEST_METHOD hack to test hg client + + $ "$TESTDIR/killdaemons.py" + $ hg serve -p $HGPORT -d --pid-file hg.pid + $ cat hg.pid > $DAEMON_PIDS + + $ hg --cwd ../test2 push -B bm http://localhost:$HGPORT/ + pushing to http://localhost:$HGPORT/ + searching for changes + no changes found + exporting bookmark bm + remote: ssl required + updating bookmark bm failed! + [1] + + $ hg --cwd ../test2 push http://localhost:$HGPORT/ + pushing to http://localhost:$HGPORT/ + searching for changes + remote: ssl required + remote: ssl required + updating cb9a9f314b8b to public failed! + [1] + + $ "$TESTDIR/killdaemons.py" + +web.deny_push=* denies pushing to unauthenticated users + + $ cat > .hg/hgrc < [web] + > push_ssl = false + > deny_push = * + > EOF + + $ REQUEST_METHOD=POST hg serve -p $HGPORT -d --pid-file hg.pid + $ cat hg.pid > $DAEMON_PIDS + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=pushkey' --requestheader 'x-hgarg-1=namespace=bookmarks&key=bm&old=&new=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b' + 401 push not authorized + + 0 + push not authorized + [1] + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=batch' --requestheader 'x-hgarg-1=cmds=pushkey+namespace%3Dbookmarks%2Ckey%3Dbm%2Cold%3D%2Cnew%3Dcb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b' + 401 push not authorized + + 0 + push not authorized + [1] + + $ hg bookmarks + no bookmarks set + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=customwritenoperm' + 401 push not authorized + + 0 + push not authorized + [1] + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=customwritewithperm' + 401 push not authorized + + 0 + push not authorized + [1] + +Reset server to remove REQUEST_METHOD hack to test hg client + + $ "$TESTDIR/killdaemons.py" + $ hg serve -p $HGPORT -d --pid-file hg.pid + $ cat hg.pid > $DAEMON_PIDS + + $ hg --cwd ../test2 push -B bm http://localhost:$HGPORT/ + pushing to http://localhost:$HGPORT/ + searching for changes + no changes found + exporting bookmark bm + abort: authorization failed + [255] + + $ hg --cwd ../test2 push http://localhost:$HGPORT/ + pushing to http://localhost:$HGPORT/ + searching for changes + abort: authorization failed + [255] + + $ "$TESTDIR/killdaemons.py" + +web.deny_push=* denies pushing to authenticated users + + $ REMOTE_USER=someuser REQUEST_METHOD=POST hg serve -p $HGPORT -d --pid-file hg.pid + $ cat hg.pid > $DAEMON_PIDS + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=pushkey' --requestheader 'x-hgarg-1=namespace=bookmarks&key=bm&old=&new=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b' + 401 push not authorized + + 0 + push not authorized + [1] + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=batch' --requestheader 'x-hgarg-1=cmds=pushkey+namespace%3Dbookmarks%2Ckey%3Dbm%2Cold%3D%2Cnew%3Dcb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b' + 401 push not authorized + + 0 + push not authorized + [1] + + $ hg bookmarks + no bookmarks set + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=customwritenoperm' + 401 push not authorized + + 0 + push not authorized + [1] + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=customwritewithperm' + 401 push not authorized + + 0 + push not authorized + [1] + +Reset server to remove REQUEST_METHOD hack to test hg client + + $ "$TESTDIR/killdaemons.py" + $ REMOTE_USER=someuser hg serve -p $HGPORT -d --pid-file hg.pid + $ cat hg.pid > $DAEMON_PIDS + + $ hg --cwd ../test2 push -B bm http://localhost:$HGPORT/ + pushing to http://localhost:$HGPORT/ + searching for changes + no changes found + exporting bookmark bm + abort: authorization failed + [255] + + $ hg --cwd ../test2 push http://localhost:$HGPORT/ + pushing to http://localhost:$HGPORT/ + searching for changes + abort: authorization failed + [255] + + $ "$TESTDIR/killdaemons.py" + +web.deny_push= denies pushing to user in list + + $ cat > .hg/hgrc < [web] + > push_ssl = false + > deny_push = baduser + > EOF + + $ REMOTE_USER=baduser REQUEST_METHOD=POST hg serve -p $HGPORT -d --pid-file hg.pid + $ cat hg.pid > $DAEMON_PIDS + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=pushkey' --requestheader 'x-hgarg-1=namespace=bookmarks&key=bm&old=&new=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b' + 401 push not authorized + + 0 + push not authorized + [1] + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=batch' --requestheader 'x-hgarg-1=cmds=pushkey+namespace%3Dbookmarks%2Ckey%3Dbm%2Cold%3D%2Cnew%3Dcb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b' + 401 push not authorized + + 0 + push not authorized + [1] + + $ hg bookmarks + no bookmarks set + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=customwritenoperm' + 401 push not authorized + + 0 + push not authorized + [1] + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=customwritewithperm' + 401 push not authorized + + 0 + push not authorized + [1] + +Reset server to remove REQUEST_METHOD hack to test hg client + + $ "$TESTDIR/killdaemons.py" + $ REMOTE_USER=baduser hg serve -p $HGPORT -d --pid-file hg.pid + $ cat hg.pid > $DAEMON_PIDS + + $ hg --cwd ../test2 push -B bm http://localhost:$HGPORT/ + pushing to http://localhost:$HGPORT/ + searching for changes + no changes found + exporting bookmark bm + abort: authorization failed + [255] + + $ hg --cwd ../test2 push http://localhost:$HGPORT/ + pushing to http://localhost:$HGPORT/ + searching for changes + abort: authorization failed + [255] + + $ "$TESTDIR/killdaemons.py" + +web.deny_push= denies pushing to user not in list because allow_push isn't set + + $ REMOTE_USER=gooduser REQUEST_METHOD=POST hg serve -p $HGPORT -d --pid-file hg.pid + $ cat hg.pid > $DAEMON_PIDS + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=pushkey' --requestheader 'x-hgarg-1=namespace=bookmarks&key=bm&old=&new=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b' + 401 push not authorized + + 0 + push not authorized + [1] + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=batch' --requestheader 'x-hgarg-1=cmds=pushkey+namespace%3Dbookmarks%2Ckey%3Dbm%2Cold%3D%2Cnew%3Dcb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b' + 401 push not authorized + + 0 + push not authorized + [1] + + $ hg bookmarks + no bookmarks set + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=customwritenoperm' + 401 push not authorized + + 0 + push not authorized + [1] + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=customwritewithperm' + 401 push not authorized + + 0 + push not authorized + [1] + +Reset server to remove REQUEST_METHOD hack to test hg client + + $ "$TESTDIR/killdaemons.py" + $ REMOTE_USER=gooduser hg serve -p $HGPORT -d --pid-file hg.pid + $ cat hg.pid > $DAEMON_PIDS + + $ hg --cwd ../test2 push -B bm http://localhost:$HGPORT/ + pushing to http://localhost:$HGPORT/ + searching for changes + no changes found + exporting bookmark bm + abort: authorization failed + [255] + + $ hg --cwd ../test2 push http://localhost:$HGPORT/ + pushing to http://localhost:$HGPORT/ + searching for changes + abort: authorization failed + [255] + + $ "$TESTDIR/killdaemons.py" + +web.allow_push=* allows pushes from unauthenticated users + + $ cat > .hg/hgrc < [web] + > push_ssl = false + > allow_push = * + > EOF + + $ REQUEST_METHOD=POST hg serve -p $HGPORT -d --pid-file hg.pid + $ cat hg.pid > $DAEMON_PIDS + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=pushkey' --requestheader 'x-hgarg-1=namespace=bookmarks&key=bm&old=&new=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b' + 200 Script output follows + + 1 + + $ hg bookmarks + bm 0:cb9a9f314b8b + $ hg book -d bm + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=customwritenoperm' + 200 Script output follows + + write command no defined permissions + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=customwritewithperm' + 200 Script output follows + + write command w/ defined permissions + +Reset server to remove REQUEST_METHOD hack to test hg client + + $ "$TESTDIR/killdaemons.py" + $ hg serve -p $HGPORT -d --pid-file hg.pid + $ cat hg.pid > $DAEMON_PIDS + + $ hg --cwd ../test2 push -B bm http://localhost:$HGPORT/ + pushing to http://localhost:$HGPORT/ + searching for changes + no changes found + exporting bookmark bm + [1] + + $ hg book -d bm + + $ hg --cwd ../test2 push http://localhost:$HGPORT/ + pushing to http://localhost:$HGPORT/ + searching for changes + remote: adding changesets + remote: adding manifests + remote: adding file changes + remote: added 1 changesets with 1 changes to 1 files + + $ "$TESTDIR/killdaemons.py" + +web.allow_push=* allows pushes from authenticated users + + $ REMOTE_USER=someuser REQUEST_METHOD=POST hg serve -p $HGPORT -d --pid-file hg.pid + $ cat hg.pid > $DAEMON_PIDS + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=pushkey' --requestheader 'x-hgarg-1=namespace=bookmarks&key=bm&old=&new=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b' + 200 Script output follows + + 1 + + $ hg bookmarks + bm 0:cb9a9f314b8b + $ hg book -d bm + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=customwritenoperm' + 200 Script output follows + + write command no defined permissions + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=customwritewithperm' + 200 Script output follows + + write command w/ defined permissions + +Reset server to remove REQUEST_METHOD hack to test hg client + + $ "$TESTDIR/killdaemons.py" + $ cd .. + $ rm -rf test2 + $ hg clone test test2 + updating to branch default + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ cd test2 + $ echo a >> a + $ hg ci -mb + $ hg book bm -r 0 + $ cd ../test + $ REMOTE_USER=someuser hg serve -p $HGPORT -d --pid-file hg.pid + $ cat hg.pid > $DAEMON_PIDS + + $ hg --cwd ../test2 push -B bm http://localhost:$HGPORT/ + pushing to http://localhost:$HGPORT/ + searching for changes + no changes found + exporting bookmark bm + [1] + + $ hg book -d bm + + $ hg --cwd ../test2 push http://localhost:$HGPORT/ + pushing to http://localhost:$HGPORT/ + searching for changes + remote: adding changesets + remote: adding manifests + remote: adding file changes + remote: added 1 changesets with 1 changes to 1 files + + $ "$TESTDIR/killdaemons.py" + +web.allow_push= denies push to user not in list + + $ cat > .hg/hgrc < [web] + > push_ssl = false + > allow_push = gooduser + > EOF + + $ REMOTE_USER=baduser REQUEST_METHOD=POST hg serve -p $HGPORT -d --pid-file hg.pid + $ cat hg.pid > $DAEMON_PIDS + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=pushkey' --requestheader 'x-hgarg-1=namespace=bookmarks&key=bm&old=&new=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b' + 401 push not authorized + + 0 + push not authorized + [1] + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=batch' --requestheader 'x-hgarg-1=cmds=pushkey+namespace%3Dbookmarks%2Ckey%3Dbm%2Cold%3D%2Cnew%3Dcb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b' + 401 push not authorized + + 0 + push not authorized + [1] + + $ hg bookmarks + no bookmarks set + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=customwritenoperm' + 401 push not authorized + + 0 + push not authorized + [1] + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=customwritewithperm' + 401 push not authorized + + 0 + push not authorized + [1] + +Reset server to remove REQUEST_METHOD hack to test hg client + + $ "$TESTDIR/killdaemons.py" + $ cd .. + $ rm -rf test2 + $ hg clone test test2 + updating to branch default + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ cd test2 + $ echo a >> a + $ hg ci -mb + $ hg book bm -r 0 + $ cd ../test + $ REMOTE_USER=baduser hg serve -p $HGPORT -d --pid-file hg.pid + $ cat hg.pid > $DAEMON_PIDS + + $ hg --cwd ../test2 push -B bm http://localhost:$HGPORT/ + pushing to http://localhost:$HGPORT/ + searching for changes + no changes found + exporting bookmark bm + abort: authorization failed + [255] + + $ hg --cwd ../test2 push http://localhost:$HGPORT/ + pushing to http://localhost:$HGPORT/ + searching for changes + abort: authorization failed + [255] + + $ "$TESTDIR/killdaemons.py" + +web.allow_push= allows push from user in list + + $ REMOTE_USER=gooduser REQUEST_METHOD=POST hg serve -p $HGPORT -d --pid-file hg.pid + $ cat hg.pid > $DAEMON_PIDS + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=pushkey' --requestheader 'x-hgarg-1=namespace=bookmarks&key=bm&old=&new=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b' + 200 Script output follows + + 1 + + $ hg bookmarks + bm 0:cb9a9f314b8b + $ hg book -d bm + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=batch' --requestheader 'x-hgarg-1=cmds=pushkey+namespace%3Dbookmarks%2Ckey%3Dbm%2Cold%3D%2Cnew%3Dcb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b' + 200 Script output follows + + 1 + + $ hg bookmarks + bm 0:cb9a9f314b8b + $ hg book -d bm + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=customwritenoperm' + 200 Script output follows + + write command no defined permissions + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=customwritewithperm' + 200 Script output follows + + write command w/ defined permissions + +Reset server to remove REQUEST_METHOD hack to test hg client + + $ "$TESTDIR/killdaemons.py" + $ cd .. + $ rm -rf test2 + $ hg clone test test2 + updating to branch default + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ cd test2 + $ echo a >> a + $ hg ci -mb + $ hg book bm -r 0 + $ cd ../test + $ REMOTE_USER=gooduser hg serve -p $HGPORT -d --pid-file hg.pid + $ cat hg.pid > $DAEMON_PIDS + + $ hg --cwd ../test2 push -B bm http://localhost:$HGPORT/ + pushing to http://localhost:$HGPORT/ + searching for changes + no changes found + exporting bookmark bm + [1] + + $ hg book -d bm + + $ hg --cwd ../test2 push http://localhost:$HGPORT/ + pushing to http://localhost:$HGPORT/ + searching for changes + remote: adding changesets + remote: adding manifests + remote: adding file changes + remote: added 1 changesets with 1 changes to 1 files + + $ "$TESTDIR/killdaemons.py" + +web.deny_push takes precedence over web.allow_push + + $ cat > .hg/hgrc < [web] + > push_ssl = false + > allow_push = someuser + > deny_push = someuser + > EOF + + $ REMOTE_USER=someuser REQUEST_METHOD=POST hg serve -p $HGPORT -d --pid-file hg.pid + $ cat hg.pid > $DAEMON_PIDS + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=pushkey' --requestheader 'x-hgarg-1=namespace=bookmarks&key=bm&old=&new=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b' + 401 push not authorized + + 0 + push not authorized + [1] + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=batch' --requestheader 'x-hgarg-1=cmds=pushkey+namespace%3Dbookmarks%2Ckey%3Dbm%2Cold%3D%2Cnew%3Dcb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b' + 401 push not authorized + + 0 + push not authorized + [1] + + $ hg bookmarks + no bookmarks set + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=customwritenoperm' + 401 push not authorized + + 0 + push not authorized + [1] + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=customwritewithperm' + 401 push not authorized + + 0 + push not authorized + [1] + +Reset server to remove REQUEST_METHOD hack to test hg client + + $ "$TESTDIR/killdaemons.py" + $ cd .. + $ rm -rf test2 + $ hg clone test test2 + updating to branch default + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ cd test2 + $ echo a >> a + $ hg ci -mb + $ hg book bm -r 0 + $ cd ../test + $ REMOTE_USER=someuser hg serve -p $HGPORT -d --pid-file hg.pid + $ cat hg.pid > $DAEMON_PIDS + + $ hg --cwd ../test2 push -B bm http://localhost:$HGPORT/ + pushing to http://localhost:$HGPORT/ + searching for changes + no changes found + exporting bookmark bm + abort: authorization failed + [255] + + $ hg --cwd ../test2 push http://localhost:$HGPORT/ + pushing to http://localhost:$HGPORT/ + searching for changes + abort: authorization failed + [255] + + $ "$TESTDIR/killdaemons.py" + +web.allow_push has no effect if web.deny_read is set + + $ cat > .hg/hgrc < [web] + > push_ssl = false + > allow_push = * + > deny_read = * + > EOF + + $ REQUEST_METHOD=POST REMOTE_USER=someuser hg serve -p $HGPORT -d --pid-file hg.pid + $ cat hg.pid > $DAEMON_PIDS + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=pushkey' --requestheader 'x-hgarg-1=namespace=bookmarks&key=bm&old=&new=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b' + 401 read not authorized + + 0 + read not authorized + [1] + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=batch' --requestheader 'x-hgarg-1=cmds=pushkey+namespace%3Dbookmarks%2Ckey%3Dbm%2Cold%3D%2Cnew%3Dcb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b' + 401 read not authorized + + 0 + read not authorized + [1] + + $ hg bookmarks + no bookmarks set + + $ "$TESTDIR/get-with-headers.py" $LOCALIP:$HGPORT '?cmd=customreadnoperm' + 401 read not authorized + + 0 + read not authorized + [1] diff -r cceaf7af4c9e tests/test-pull-http.t --- a/tests/test-pull-http.t Sat Jun 01 17:09:41 2013 -0500 +++ b/tests/test-pull-http.t Tue Jul 03 11:25:06 2018 +0200 @@ -37,7 +37,6 @@ $ hg serve -p $HGPORT -d --pid-file=hg.pid -E errors.log $ cat hg.pid >> $DAEMON_PIDS $ hg clone http://localhost:$HGPORT/ test4 - requesting all changes abort: authorization failed [255] $ "$TESTDIR/killdaemons.py" $DAEMON_PIDS @@ -57,7 +56,6 @@ expect error, pulling not allowed $ req - pulling from http://localhost:$HGPORT/ abort: authorization failed % serve errors