# HG changeset patch # User Kevin Bullock # Date 1520363827 21600 # Node ID 8bba684efde7f45add05f737952093bb2aa07155 # Parent 2c49b2e7da86580e12d01d7b986f6d39230c0de0# Parent 2ecb0fc535b1ca08e0170a5df6085c44005beeeb merge with security patches diff -r 2c49b2e7da86 -r 8bba684efde7 hgext/largefiles/uisetup.py --- a/hgext/largefiles/uisetup.py Tue Mar 06 13:08:00 2018 -0600 +++ b/hgext/largefiles/uisetup.py Tue Mar 06 13:17:07 2018 -0600 @@ -12,7 +12,6 @@ from mercurial.i18n import _ from mercurial.hgweb import ( - hgweb_mod, webcommands, ) @@ -175,9 +174,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 2c49b2e7da86 -r 8bba684efde7 mercurial/hgweb/hgweb_mod.py --- a/mercurial/hgweb/hgweb_mod.py Tue Mar 06 13:08:00 2018 -0600 +++ b/mercurial/hgweb/hgweb_mod.py Tue Mar 06 13:17:07 2018 -0600 @@ -36,6 +36,7 @@ templater, ui as uimod, util, + wireproto, ) from . import ( @@ -45,15 +46,8 @@ wsgicgi, ) -perms = { - 'changegroup': 'pull', - 'changegroupsubset': 'pull', - 'getbundle': 'pull', - 'stream_out': 'pull', - 'listkeys': 'pull', - 'unbundle': 'push', - 'pushkey': 'push', -} +# Aliased for API compatibility. +perms = wireproto.permissions archivespecs = util.sortdict(( ('zip', ('application/zip', 'zip', '.zip', None)), @@ -366,8 +360,13 @@ try: if query: raise ErrorResponse(HTTP_NOT_FOUND) - if cmd in perms: - self.check_perm(rctx, req, perms[cmd]) + + req.checkperm = lambda op: self.check_perm(rctx, 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(rctx.repo, req, cmd) except ErrorResponse as inst: # A client that sends unbundle without 100-continue will diff -r 2c49b2e7da86 -r 8bba684efde7 mercurial/hgweb/protocol.py --- a/mercurial/hgweb/protocol.py Tue Mar 06 13:08:00 2018 -0600 +++ b/mercurial/hgweb/protocol.py Tue Mar 06 13:17:07 2018 -0600 @@ -52,6 +52,7 @@ self.response = '' self.ui = ui self.name = 'http' + self.checkperm = req.checkperm def getargs(self, args): knownargs = self._args() diff -r 2c49b2e7da86 -r 8bba684efde7 mercurial/wireproto.py --- a/mercurial/wireproto.py Tue Mar 06 13:08:00 2018 -0600 +++ b/mercurial/wireproto.py Tue Mar 06 13:17:07 2018 -0600 @@ -677,6 +677,11 @@ # list of commands commands = {} +# Maps wire protocol name to operation type. This is used for permissions +# checking. All defined @wireiprotocommand should have an entry in this +# dict. +permissions = {} + def wireprotocommand(name, args=''): """decorator for wire protocol command""" def register(func): @@ -684,6 +689,8 @@ return func return register +# TODO define a more appropriate permissions type to use for this. +permissions['batch'] = 'pull' @wireprotocommand('batch', 'cmds *') def batch(repo, proto, cmds, others): repo = repo.filtered("served") @@ -696,6 +703,17 @@ n, v = a.split('=') vals[unescapearg(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 = {} @@ -716,6 +734,7 @@ res.append(escapearg(result)) return ';'.join(res) +permissions['between'] = 'pull' @wireprotocommand('between', 'pairs') def between(repo, proto, pairs): pairs = [decodelist(p, '-') for p in pairs.split(" ")] @@ -724,6 +743,7 @@ r.append(encodelist(b) + "\n") return "".join(r) +permissions['branchmap'] = 'pull' @wireprotocommand('branchmap') def branchmap(repo, proto): branchmap = repo.branchmap() @@ -734,6 +754,7 @@ heads.append('%s %s' % (branchname, branchnodes)) return '\n'.join(heads) +permissions['branches'] = 'pull' @wireprotocommand('branches', 'nodes') def branches(repo, proto, nodes): nodes = decodelist(nodes) @@ -742,6 +763,7 @@ r.append(encodelist(b) + "\n") return "".join(r) +permissions['clonebundles'] = 'pull' @wireprotocommand('clonebundles', '') def clonebundles(repo, proto): """Server command for returning info for available bundles to seed clones. @@ -804,10 +826,12 @@ # If you are writing an extension and consider wrapping this function. Wrap # `_capabilities` instead. +permissions['capabilities'] = 'pull' @wireprotocommand('capabilities') def capabilities(repo, proto): return ' '.join(_capabilities(repo, proto)) +permissions['changegroup'] = 'pull' @wireprotocommand('changegroup', 'roots') def changegroup(repo, proto, roots): nodes = decodelist(roots) @@ -817,6 +841,7 @@ gen = iter(lambda: cg.read(32768), '') return streamres(gen=gen) +permissions['changegroupsubset'] = 'pull' @wireprotocommand('changegroupsubset', 'bases heads') def changegroupsubset(repo, proto, bases, heads): bases = decodelist(bases) @@ -827,12 +852,14 @@ gen = iter(lambda: cg.read(32768), '') return streamres(gen=gen) +permissions['debugwireargs'] = 'pull' @wireprotocommand('debugwireargs', 'one two *') 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, **pycompat.strkwargs(opts)) +permissions['getbundle'] = 'pull' @wireprotocommand('getbundle', '*') def getbundle(repo, proto, others): opts = options('getbundle', gboptsmap.keys(), others) @@ -899,11 +926,13 @@ return streamres(gen=chunks, prefer_uncompressed=not prefercompressed) +permissions['heads'] = 'pull' @wireprotocommand('heads') def heads(repo, proto): h = repo.heads() return encodelist(h) + "\n" +permissions['hello'] = 'pull' @wireprotocommand('hello') def hello(repo, proto): '''the hello command returns a set of lines describing various @@ -915,11 +944,13 @@ ''' return "capabilities: %s\n" % (capabilities(repo, proto)) +permissions['listkeys'] = 'pull' @wireprotocommand('listkeys', 'namespace') def listkeys(repo, proto, namespace): d = repo.listkeys(encoding.tolocal(namespace)).items() return pushkeymod.encodekeys(d) +permissions['lookup'] = 'pull' @wireprotocommand('lookup', 'key') def lookup(repo, proto, key): try: @@ -932,10 +963,12 @@ success = 0 return "%d %s\n" % (success, r) +permissions['known'] = 'pull' @wireprotocommand('known', 'nodes *') def known(repo, proto, nodes, others): return ''.join(b and "1" or "0" for b in repo.known(decodelist(nodes))) +permissions['pushkey'] = 'push' @wireprotocommand('pushkey', 'namespace key old new') def pushkey(repo, proto, namespace, key, old, new): # compatibility with pre-1.8 clients which were accidentally @@ -968,6 +1001,7 @@ encoding.tolocal(old), new) return '%s\n' % int(r) +permissions['stream_out'] = 'pull' @wireprotocommand('stream_out') def stream(repo, proto): '''If the server supports streaming clone, it advertises the "stream" @@ -976,6 +1010,7 @@ ''' return streamres_legacy(streamclone.generatev1wireproto(repo)) +permissions['unbundle'] = 'push' @wireprotocommand('unbundle', 'heads') def unbundle(repo, proto, heads): their_heads = decodelist(heads) diff -r 2c49b2e7da86 -r 8bba684efde7 tests/test-http-bundle1.t --- a/tests/test-http-bundle1.t Tue Mar 06 13:08:00 2018 -0600 +++ b/tests/test-http-bundle1.t Tue Mar 06 13:17:07 2018 -0600 @@ -259,60 +259,52 @@ $ hg rollback -q $ sed 's/.*] "/"/' < ../access.log - "GET /?cmd=capabilities HTTP/1.1" 200 - - "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ - "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ + "GET /?cmd=capabilities HTTP/1.1" 401 - + "GET /?cmd=capabilities HTTP/1.1" 401 - + "GET /?cmd=capabilities HTTP/1.1" 401 - "GET /?cmd=capabilities HTTP/1.1" 200 - "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ - "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ + "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ + "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ + "GET /?cmd=capabilities HTTP/1.1" 401 - "GET /?cmd=capabilities HTTP/1.1" 200 - "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ - "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ - "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ - "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ - "GET /?cmd=capabilities HTTP/1.1" 200 - - "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ - "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ + "GET /?cmd=capabilities HTTP/1.1" 401 - "GET /?cmd=capabilities HTTP/1.1" 200 - "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ - "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ + "GET /?cmd=capabilities HTTP/1.1" 401 - "GET /?cmd=capabilities HTTP/1.1" 200 - "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ - "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ + "GET /?cmd=capabilities HTTP/1.1" 401 - "GET /?cmd=capabilities HTTP/1.1" 200 - "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ - "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ + "GET /?cmd=capabilities HTTP/1.1" 401 - "GET /?cmd=capabilities HTTP/1.1" 200 - "GET /?cmd=branchmap HTTP/1.1" 200 - x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ - "GET /?cmd=stream_out HTTP/1.1" 401 - x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ "GET /?cmd=stream_out HTTP/1.1" 200 - x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D5fed3813f7f5e1824344fdc9cf8f63bb662c292d x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ + "GET /?cmd=capabilities HTTP/1.1" 401 - "GET /?cmd=capabilities HTTP/1.1" 200 - - "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ "GET /?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:common=0000000000000000000000000000000000000000&heads=5fed3813f7f5e1824344fdc9cf8f63bb662c292d x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ - "GET /?cmd=capabilities HTTP/1.1" 200 - - "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ - "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ - "GET /?cmd=capabilities HTTP/1.1" 200 - - "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ - "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ - "GET /?cmd=listkeys HTTP/1.1" 403 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ + "GET /?cmd=capabilities HTTP/1.1" 401 - + "GET /?cmd=capabilities HTTP/1.1" 401 - + "GET /?cmd=capabilities HTTP/1.1" 403 - + "GET /?cmd=capabilities HTTP/1.1" 401 - "GET /?cmd=capabilities HTTP/1.1" 200 - "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D7f4e523d01f2cc3765ac8934da3d14db775ff872 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ - "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ "GET /?cmd=branchmap HTTP/1.1" 200 - x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ diff -r 2c49b2e7da86 -r 8bba684efde7 tests/test-http-permissions.t --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/test-http-permissions.t Tue Mar 06 13:17:07 2018 -0600 @@ -0,0 +1,1502 @@ +#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 + > strip = + > 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 + + $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=capabilities' + 401 read not authorized + + 0 + read not authorized + [1] + + $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=stream_out' + 401 read not authorized + + 0 + read not authorized + [1] + + $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=listkeys' --requestheader 'x-hgarg-1=namespace=phases' + 401 read not authorized + + 0 + read not authorized + [1] + + $ 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] + + $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customreadnoperm' + 401 read not authorized + + 0 + read not authorized + [1] + + $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customreadwithperm' + 401 read not authorized + + 0 + read not authorized + [1] + + $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritenoperm' + 401 read not authorized + + 0 + read not authorized + [1] + + $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritewithperm' + 401 read not authorized + + 0 + read not authorized + [1] + + $ hg --cwd ../test2 pull http://localhost:$HGPORT/ + pulling from http://localhost:$HGPORT/ + abort: authorization failed + [255] + + $ 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 + + $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=capabilities' + 401 read not authorized + + 0 + read not authorized + [1] + + $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=stream_out' + 401 read not authorized + + 0 + read not authorized + [1] + + $ 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] + + $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customreadnoperm' + 401 read not authorized + + 0 + read not authorized + [1] + + $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customreadwithperm' + 401 read not authorized + + 0 + read not authorized + [1] + + $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritenoperm' + 401 read not authorized + + 0 + read not authorized + [1] + + $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritewithperm' + 401 read not authorized + + 0 + read not authorized + [1] + + $ hg --cwd ../test2 pull http://localhost:$HGPORT/ + pulling from http://localhost:$HGPORT/ + abort: authorization failed + [255] + + $ 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 + + $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=listkeys' --requestheader 'x-hgarg-1=namespace=phases' + 401 read not authorized + + 0 + read not authorized + [1] + + $ 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] + + $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customreadnoperm' + 401 read not authorized + + 0 + read not authorized + [1] + + $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customreadwithperm' + 401 read not authorized + + 0 + read not authorized + [1] + + $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritenoperm' + 401 read not authorized + + 0 + read not authorized + [1] + + $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritewithperm' + 401 read not authorized + + 0 + read not authorized + [1] + + $ hg --cwd ../test2 pull http://localhost:$HGPORT/ + pulling from http://localhost:$HGPORT/ + abort: authorization failed + [255] + + $ 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 + + $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=listkeys' --requestheader 'x-hgarg-1=namespace=phases' + 401 read not authorized + + 0 + read not authorized + [1] + + $ 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] + + $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customreadnoperm' + 401 read not authorized + + 0 + read not authorized + [1] + + $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customreadwithperm' + 401 read not authorized + + 0 + read not authorized + [1] + + $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritenoperm' + 401 read not authorized + + 0 + read not authorized + [1] + + $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritewithperm' + 401 read not authorized + + 0 + read not authorized + [1] + + $ hg --cwd ../test2 pull http://localhost:$HGPORT/ + pulling from http://localhost:$HGPORT/ + abort: authorization failed + [255] + + $ 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 + + $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=listkeys' --requestheader 'x-hgarg-1=namespace=phases' + 200 Script output follows + + cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b 1 + publishing True (no-eol) + + $ 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) + + $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customreadnoperm' + 405 push requires POST request + + 0 + push requires POST request + [1] + + $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customreadwithperm' + 200 Script output follows + + read-only command w/ defined permissions + + $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritenoperm' + 405 push requires POST request + + 0 + push requires POST request + [1] + + $ 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 + + $ 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 + + $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=listkeys' --requestheader 'x-hgarg-1=namespace=phases' + 200 Script output follows + + cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b 1 + publishing True (no-eol) + + $ 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) + + $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customreadnoperm' + 405 push requires POST request + + 0 + push requires POST request + [1] + + $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customreadwithperm' + 200 Script output follows + + read-only command w/ defined permissions + + $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritenoperm' + 405 push requires POST request + + 0 + push requires POST request + [1] + + $ 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 + + $ 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 + + $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=listkeys' --requestheader 'x-hgarg-1=namespace=phases' + 200 Script output follows + + cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b 1 + publishing True (no-eol) + + $ 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) + + $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customreadnoperm' + 405 push requires POST request + + 0 + push requires POST request + [1] + + $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customreadwithperm' + 200 Script output follows + + read-only command w/ defined permissions + + $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritenoperm' + 405 push requires POST request + + 0 + push requires POST request + [1] + + $ 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 + + $ 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 + + $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=listkeys' --requestheader 'x-hgarg-1=namespace=phases' + 401 read not authorized + + 0 + read not authorized + [1] + + $ 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] + + $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customreadnoperm' + 401 read not authorized + + 0 + read not authorized + [1] + + $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customreadwithperm' + 401 read not authorized + + 0 + read not authorized + [1] + + $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritenoperm' + 401 read not authorized + + 0 + read not authorized + [1] + + $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritewithperm' + 401 read not authorized + + 0 + read not authorized + [1] + + $ hg --cwd ../test2 pull http://localhost:$HGPORT/ + pulling from http://localhost:$HGPORT/ + abort: authorization failed + [255] + + $ 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 + + $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=listkeys' --requestheader 'x-hgarg-1=namespace=phases' + 401 read not authorized + + 0 + read not authorized + [1] + + $ 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] + + $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customreadnoperm' + 401 read not authorized + + 0 + read not authorized + [1] + + $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customreadwithperm' + 401 read not authorized + + 0 + read not authorized + [1] + + $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritenoperm' + 401 read not authorized + + 0 + read not authorized + [1] + + $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritewithperm' + 401 read not authorized + + 0 + read not authorized + [1] + + $ hg --cwd ../test2 pull http://localhost:$HGPORT/ + pulling from http://localhost:$HGPORT/ + abort: authorization failed + [255] + + $ 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 + + $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=listkeys' --requestheader 'x-hgarg-1=namespace=phases' + 200 Script output follows + + cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b 1 + publishing True (no-eol) + + $ 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) + + $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customreadnoperm' + 405 push requires POST request + + 0 + push requires POST request + [1] + + $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customreadwithperm' + 200 Script output follows + + read-only command w/ defined permissions + + $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritenoperm' + 405 push requires POST request + + 0 + push requires POST request + [1] + + $ 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 + + $ 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 + + $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=listkeys' --requestheader 'x-hgarg-1=namespace=phases' + 401 read not authorized + + 0 + read not authorized + [1] + + $ 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] + + $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customreadnoperm' + 401 read not authorized + + 0 + read not authorized + [1] + + $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customreadwithperm' + 401 read not authorized + + 0 + read not authorized + [1] + + $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritenoperm' + 401 read not authorized + + 0 + read not authorized + [1] + + $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritewithperm' + 401 read not authorized + + 0 + read not authorized + [1] + + $ hg --cwd ../test2 pull http://localhost:$HGPORT/ + pulling from http://localhost:$HGPORT/ + abort: authorization failed + [255] + + $ killdaemons.py + +web.allow-pull=false denies read access to repo + + $ cat > .hg/hgrc < [web] + > allow-pull = false + > EOF + + $ hg serve -p $HGPORT -d --pid-file hg.pid + $ cat hg.pid > $DAEMON_PIDS + + $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=capabilities' + 401 pull not authorized + + 0 + pull not authorized + [1] + + $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=listkeys' --requestheader 'x-hgarg-1=namespace=phases' + 401 pull not authorized + + 0 + pull not authorized + [1] + + $ 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] + + $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customreadnoperm' + 405 push requires POST request + + 0 + push requires POST request + [1] + + $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customreadwithperm' + 401 pull not authorized + + 0 + pull not authorized + [1] + + $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritenoperm' + 405 push requires POST request + + 0 + push requires POST request + [1] + + $ 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/ + abort: authorization failed + [255] + + $ 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 + + $ 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] + + $ 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] + + $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritenoperm' + 405 push requires POST request + + 0 + push requires POST request + [1] + + $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritewithperm' + 405 push requires POST request + + 0 + push requires POST request + [1] + + $ 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 + + $ 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] + + $ 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] + + $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritenoperm' + 405 push requires POST request + + 0 + push requires POST request + [1] + + $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritewithperm' + 405 push requires POST request + + 0 + push requires POST request + [1] + + $ 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 + + $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=pushkey' --requestheader 'x-hgarg-1=namespace=bookmarks&key=bm&old=&new=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b' + 403 ssl required + + 0 + ssl required + [1] + + $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=batch' --requestheader 'x-hgarg-1=cmds=pushkey+namespace%3Dbookmarks%2Ckey%3Dbm%2Cold%3D%2Cnew%3Dcb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b' + 403 ssl required + + 0 + ssl required + [1] + + $ hg bookmarks + no bookmarks set + + $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritenoperm' + 403 ssl required + + 0 + ssl required + [1] + + $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritewithperm' + 403 ssl required + + 0 + ssl required + [1] + +Reset server to remove REQUEST_METHOD hack to test hg client + + $ 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 + abort: HTTP Error 403: ssl required + [255] + + $ hg --cwd ../test2 push http://localhost:$HGPORT/ + pushing to http://localhost:$HGPORT/ + searching for changes + abort: HTTP Error 403: ssl required + [255] + + $ 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 + + $ 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] + + $ 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 + + $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritenoperm' + 401 push not authorized + + 0 + push not authorized + [1] + + $ 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 + + $ 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 + abort: authorization failed + [255] + + $ hg --cwd ../test2 push http://localhost:$HGPORT/ + pushing to http://localhost:$HGPORT/ + searching for changes + abort: authorization failed + [255] + + $ 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 + + $ 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] + + $ 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 + + $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritenoperm' + 401 push not authorized + + 0 + push not authorized + [1] + + $ 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 + + $ 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 + abort: authorization failed + [255] + + $ hg --cwd ../test2 push http://localhost:$HGPORT/ + pushing to http://localhost:$HGPORT/ + searching for changes + abort: authorization failed + [255] + + $ 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 + + $ 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] + + $ 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 + + $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritenoperm' + 401 push not authorized + + 0 + push not authorized + [1] + + $ 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 + + $ 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 + abort: authorization failed + [255] + + $ hg --cwd ../test2 push http://localhost:$HGPORT/ + pushing to http://localhost:$HGPORT/ + searching for changes + abort: authorization failed + [255] + + $ 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 + + $ 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] + + $ 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 + + $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritenoperm' + 401 push not authorized + + 0 + push not authorized + [1] + + $ 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 + + $ 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 + abort: authorization failed + [255] + + $ hg --cwd ../test2 push http://localhost:$HGPORT/ + pushing to http://localhost:$HGPORT/ + searching for changes + abort: authorization failed + [255] + + $ 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 + + $ 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 + + $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritenoperm' + 200 Script output follows + + write command no defined permissions + + $ 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 + + $ 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 + + $ hg strip -r 1: + saved backup bundle to $TESTTMP/test/.hg/strip-backup/ba677d0156c1-eea704d7-backup.hg + + $ 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 + + $ 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 + + $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritenoperm' + 200 Script output follows + + write command no defined permissions + + $ 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 + + $ 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 + [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 + + $ hg strip -r 1: + saved backup bundle to $TESTTMP/test/.hg/strip-backup/ba677d0156c1-eea704d7-backup.hg + + $ 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 + + $ 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] + + $ 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 + + $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritenoperm' + 401 push not authorized + + 0 + push not authorized + [1] + + $ 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 + + $ 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 + abort: authorization failed + [255] + + $ hg --cwd ../test2 push http://localhost:$HGPORT/ + pushing to http://localhost:$HGPORT/ + searching for changes + abort: authorization failed + [255] + + $ 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 + + $ 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 + + $ 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 + + $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritenoperm' + 200 Script output follows + + write command no defined permissions + + $ 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 + + $ 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 + [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 + + $ hg strip -r 1: + saved backup bundle to $TESTTMP/test/.hg/strip-backup/ba677d0156c1-eea704d7-backup.hg + + $ 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 + + $ 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] + + $ 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 + + $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritenoperm' + 401 push not authorized + + 0 + push not authorized + [1] + + $ 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 + + $ 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 + abort: authorization failed + [255] + + $ hg --cwd ../test2 push http://localhost:$HGPORT/ + pushing to http://localhost:$HGPORT/ + searching for changes + abort: authorization failed + [255] + + $ 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 + + $ 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] + + $ 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 + + $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customreadnoperm' + 401 read not authorized + + 0 + read not authorized + [1] + + $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customreadwithperm' + 401 read not authorized + + 0 + read not authorized + [1] + + $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritenoperm' + 401 read not authorized + + 0 + read not authorized + [1] + + $ get-with-headers.py $LOCALIP:$HGPORT '?cmd=customwritewithperm' + 401 read not authorized + + 0 + read not authorized + [1] + +Reset server to remove REQUEST_METHOD hack to test hg client + + $ 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/ + abort: authorization failed + [255] + + $ hg --cwd ../test2 push http://localhost:$HGPORT/ + pushing to http://localhost:$HGPORT/ + abort: authorization failed + [255] + + $ killdaemons.py diff -r 2c49b2e7da86 -r 8bba684efde7 tests/test-http.t --- a/tests/test-http.t Tue Mar 06 13:08:00 2018 -0600 +++ b/tests/test-http.t Tue Mar 06 13:17:07 2018 -0600 @@ -254,6 +254,7 @@ http auth: user user, password **** sending capabilities command devel-peer-request: GET http://localhost:$HGPORT2/?cmd=capabilities + http auth: user user, password **** devel-peer-request: finished in *.???? seconds (200) (glob) query 1; heads sending batch command @@ -270,7 +271,6 @@ devel-peer-request: Vary X-HgArg-1,X-HgProto-1 devel-peer-request: X-hgproto-1 0.1 0.2 comp=$USUAL_COMPRESSIONS$ devel-peer-request: 16 bytes of commands arguments in headers - http auth: user user, password **** devel-peer-request: finished in *.???? seconds (200) (glob) received listkey for "phases": 58 bytes checking for updated bookmarks @@ -340,57 +340,49 @@ $ hg rollback -q $ sed 's/.*] "/"/' < ../access.log - "GET /?cmd=capabilities HTTP/1.1" 200 - - "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ - "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ + "GET /?cmd=capabilities HTTP/1.1" 401 - + "GET /?cmd=capabilities HTTP/1.1" 401 - + "GET /?cmd=capabilities HTTP/1.1" 401 - "GET /?cmd=capabilities HTTP/1.1" 200 - "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ - "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ + "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ + "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ + "GET /?cmd=capabilities HTTP/1.1" 401 - "GET /?cmd=capabilities HTTP/1.1" 200 - "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ - "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ - "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ - "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ - "GET /?cmd=capabilities HTTP/1.1" 200 - - "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ - "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ + "GET /?cmd=capabilities HTTP/1.1" 401 - "GET /?cmd=capabilities HTTP/1.1" 200 - "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ - "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ + "GET /?cmd=capabilities HTTP/1.1" 401 - "GET /?cmd=capabilities HTTP/1.1" 200 - "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ - "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ + "GET /?cmd=capabilities HTTP/1.1" 401 - "GET /?cmd=capabilities HTTP/1.1" 200 - "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ - "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ + "GET /?cmd=capabilities HTTP/1.1" 401 - "GET /?cmd=capabilities HTTP/1.1" 200 - "GET /?cmd=branchmap HTTP/1.1" 200 - x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ - "GET /?cmd=stream_out HTTP/1.1" 401 - x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ "GET /?cmd=stream_out HTTP/1.1" 200 - x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D5fed3813f7f5e1824344fdc9cf8f63bb662c292d x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ "GET /?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:bookmarks=1&$USUAL_BUNDLE_CAPS$&cg=0&common=5fed3813f7f5e1824344fdc9cf8f63bb662c292d&heads=5fed3813f7f5e1824344fdc9cf8f63bb662c292d&listkeys=bookmarks&phases=1 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ + "GET /?cmd=capabilities HTTP/1.1" 401 - "GET /?cmd=capabilities HTTP/1.1" 200 - "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ - "GET /?cmd=getbundle HTTP/1.1" 401 - x-hgarg-1:bookmarks=1&$USUAL_BUNDLE_CAPS$&cg=1&common=0000000000000000000000000000000000000000&heads=5fed3813f7f5e1824344fdc9cf8f63bb662c292d&listkeys=bookmarks&phases=1 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ "GET /?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:bookmarks=1&$USUAL_BUNDLE_CAPS$&cg=1&common=0000000000000000000000000000000000000000&heads=5fed3813f7f5e1824344fdc9cf8f63bb662c292d&listkeys=bookmarks&phases=1 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ - "GET /?cmd=capabilities HTTP/1.1" 200 - - "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ - "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ - "GET /?cmd=capabilities HTTP/1.1" 200 - - "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ - "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ - "GET /?cmd=listkeys HTTP/1.1" 403 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ + "GET /?cmd=capabilities HTTP/1.1" 401 - + "GET /?cmd=capabilities HTTP/1.1" 401 - + "GET /?cmd=capabilities HTTP/1.1" 403 - + "GET /?cmd=capabilities HTTP/1.1" 401 - "GET /?cmd=capabilities HTTP/1.1" 200 - "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D7f4e523d01f2cc3765ac8934da3d14db775ff872 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ - "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ "GET /?cmd=branchmap HTTP/1.1" 200 - x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ @@ -398,9 +390,9 @@ "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ "POST /?cmd=unbundle HTTP/1.1" 200 - x-hgarg-1:heads=666f726365* (glob) "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ + "GET /?cmd=capabilities HTTP/1.1" 401 - "GET /?cmd=capabilities HTTP/1.1" 200 - "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D7f4e523d01f2cc3765ac8934da3d14db775ff872 x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ - "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ "GET /?cmd=branchmap HTTP/1.1" 200 - x-hgproto-1:0.1 0.2 comp=$USUAL_COMPRESSIONS$ diff -r 2c49b2e7da86 -r 8bba684efde7 tests/test-largefiles-wireproto.t --- a/tests/test-largefiles-wireproto.t Tue Mar 06 13:08:00 2018 -0600 +++ b/tests/test-largefiles-wireproto.t Tue Mar 06 13:17:07 2018 -0600 @@ -434,11 +434,11 @@ > EOF $ hg clone --config ui.interactive=true --config extensions.getpass=get_pass.py \ > http://user@localhost:$HGPORT credentialclone - requesting all changes http authorization required for http://localhost:$HGPORT/ realm: mercurial user: user - password: adding changesets + password: requesting all changes + adding changesets adding manifests adding file changes added 1 changesets with 1 changes to 1 files diff -r 2c49b2e7da86 -r 8bba684efde7 tests/test-pull-http.t --- a/tests/test-pull-http.t Tue Mar 06 13:08:00 2018 -0600 +++ b/tests/test-pull-http.t Tue Mar 06 13:17:07 2018 -0600 @@ -50,7 +50,6 @@ $ hg serve -p $HGPORT -d --pid-file=hg.pid -E errors.log $ cat hg.pid >> $DAEMON_PIDS $ hg clone http://localhost:$HGPORT/ test4 # bundle2+ - requesting all changes abort: authorization failed [255] $ hg clone http://localhost:$HGPORT/ test4 --config devel.legacy.exchange=bundle1 @@ -74,7 +73,6 @@ $ req pulling from http://localhost:$HGPORT/ - searching for changes abort: authorization failed % serve errors diff -r 2c49b2e7da86 -r 8bba684efde7 tests/test-push-http.t --- a/tests/test-push-http.t Tue Mar 06 13:08:00 2018 -0600 +++ b/tests/test-push-http.t Tue Mar 06 13:17:07 2018 -0600 @@ -307,28 +307,6 @@ $ hg --config extensions.strip= strip -r 1: saved backup bundle to $TESTTMP/test/.hg/strip-backup/ba677d0156c1-eea704d7-backup.hg -expect authorization error: all users denied - - $ echo '[web]' > .hg/hgrc - $ echo 'push_ssl = false' >> .hg/hgrc - $ echo 'deny_push = *' >> .hg/hgrc - $ req - pushing to http://localhost:$HGPORT/ - searching for changes - abort: authorization failed - % serve errors - [255] - -expect authorization error: some users denied, users must be authenticated - - $ echo 'deny_push = unperson' >> .hg/hgrc - $ req - pushing to http://localhost:$HGPORT/ - searching for changes - abort: authorization failed - % serve errors - [255] - #if bundle2 $ cat > .hg/hgrc <