annotate tests/httpserverauth.py @ 44588:2a98b0cd4995

setup: build C extensions with -Werror=declaration-after-statement MSVC 2008 still needs declarations at the top of the scope. I added it to the 3rd party code too in case somebody vendors a new version with a problem- they'll get an early warning. Clang seems to ignore this (at least on 10.14 with Xcode 10), and gcc 7.4 will error out as desired on Ubuntu 18.04. Thanks to Yuya for remembering the name of the option. Differential Revision: https://phab.mercurial-scm.org/D8318
author Matt Harbison <matt_harbison@yahoo.com>
date Fri, 20 Mar 2020 23:30:23 -0400
parents 2372284d9457
children 6000f5b25c9b
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
41585
549af2fa089f tests: extract the http server authentication extension to a single module
Matt Harbison <matt_harbison@yahoo.com>
parents:
diff changeset
1 from __future__ import absolute_import
549af2fa089f tests: extract the http server authentication extension to a single module
Matt Harbison <matt_harbison@yahoo.com>
parents:
diff changeset
2
549af2fa089f tests: extract the http server authentication extension to a single module
Matt Harbison <matt_harbison@yahoo.com>
parents:
diff changeset
3 import base64
41587
ccaa52865fac tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents: 41585
diff changeset
4 import hashlib
41585
549af2fa089f tests: extract the http server authentication extension to a single module
Matt Harbison <matt_harbison@yahoo.com>
parents:
diff changeset
5
549af2fa089f tests: extract the http server authentication extension to a single module
Matt Harbison <matt_harbison@yahoo.com>
parents:
diff changeset
6 from mercurial.hgweb import common
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41589
diff changeset
7 from mercurial import node
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41589
diff changeset
8
41587
ccaa52865fac tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents: 41585
diff changeset
9
ccaa52865fac tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents: 41585
diff changeset
10 def parse_keqv_list(req, l):
ccaa52865fac tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents: 41585
diff changeset
11 """Parse list of key=value strings where keys are not duplicated."""
ccaa52865fac tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents: 41585
diff changeset
12 parsed = {}
ccaa52865fac tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents: 41585
diff changeset
13 for elt in l:
ccaa52865fac tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents: 41585
diff changeset
14 k, v = elt.split(b'=', 1)
ccaa52865fac tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents: 41585
diff changeset
15 if v[0:1] == b'"' and v[-1:] == b'"':
ccaa52865fac tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents: 41585
diff changeset
16 v = v[1:-1]
ccaa52865fac tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents: 41585
diff changeset
17 parsed[k] = v
ccaa52865fac tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents: 41585
diff changeset
18 return parsed
ccaa52865fac tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents: 41585
diff changeset
19
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41589
diff changeset
20
41587
ccaa52865fac tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents: 41585
diff changeset
21 class digestauthserver(object):
ccaa52865fac tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents: 41585
diff changeset
22 def __init__(self):
ccaa52865fac tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents: 41585
diff changeset
23 self._user_hashes = {}
ccaa52865fac tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents: 41585
diff changeset
24
ccaa52865fac tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents: 41585
diff changeset
25 def gethashers(self):
ccaa52865fac tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents: 41585
diff changeset
26 def _md5sum(x):
ccaa52865fac tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents: 41585
diff changeset
27 m = hashlib.md5()
ccaa52865fac tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents: 41585
diff changeset
28 m.update(x)
ccaa52865fac tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents: 41585
diff changeset
29 return node.hex(m.digest())
ccaa52865fac tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents: 41585
diff changeset
30
ccaa52865fac tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents: 41585
diff changeset
31 h = _md5sum
ccaa52865fac tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents: 41585
diff changeset
32
ccaa52865fac tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents: 41585
diff changeset
33 kd = lambda s, d, h=h: h(b"%s:%s" % (s, d))
ccaa52865fac tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents: 41585
diff changeset
34 return h, kd
ccaa52865fac tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents: 41585
diff changeset
35
ccaa52865fac tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents: 41585
diff changeset
36 def adduser(self, user, password, realm):
ccaa52865fac tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents: 41585
diff changeset
37 h, kd = self.gethashers()
ccaa52865fac tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents: 41585
diff changeset
38 a1 = h(b'%s:%s:%s' % (user, realm, password))
ccaa52865fac tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents: 41585
diff changeset
39 self._user_hashes[(user, realm)] = a1
ccaa52865fac tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents: 41585
diff changeset
40
ccaa52865fac tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents: 41585
diff changeset
41 def makechallenge(self, realm):
ccaa52865fac tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents: 41585
diff changeset
42 # We aren't testing the protocol here, just that the bytes make the
ccaa52865fac tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents: 41585
diff changeset
43 # proper round trip. So hardcoded seems fine.
ccaa52865fac tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents: 41585
diff changeset
44 nonce = b'064af982c5b571cea6450d8eda91c20d'
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41589
diff changeset
45 return b'realm="%s", nonce="%s", algorithm=MD5, qop="auth"' % (
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41589
diff changeset
46 realm,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41589
diff changeset
47 nonce,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41589
diff changeset
48 )
41587
ccaa52865fac tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents: 41585
diff changeset
49
ccaa52865fac tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents: 41585
diff changeset
50 def checkauth(self, req, header):
ccaa52865fac tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents: 41585
diff changeset
51 log = req.rawenv[b'wsgi.errors']
ccaa52865fac tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents: 41585
diff changeset
52
ccaa52865fac tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents: 41585
diff changeset
53 h, kd = self.gethashers()
ccaa52865fac tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents: 41585
diff changeset
54 resp = parse_keqv_list(req, header.split(b', '))
ccaa52865fac tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents: 41585
diff changeset
55
ccaa52865fac tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents: 41585
diff changeset
56 if resp.get(b'algorithm', b'MD5').upper() != b'MD5':
ccaa52865fac tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents: 41585
diff changeset
57 log.write(b'Unsupported algorithm: %s' % resp.get(b'algorithm'))
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41589
diff changeset
58 raise common.ErrorResponse(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41589
diff changeset
59 common.HTTP_FORBIDDEN, b"unknown algorithm"
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41589
diff changeset
60 )
41587
ccaa52865fac tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents: 41585
diff changeset
61 user = resp[b'username']
ccaa52865fac tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents: 41585
diff changeset
62 realm = resp[b'realm']
ccaa52865fac tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents: 41585
diff changeset
63 nonce = resp[b'nonce']
ccaa52865fac tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents: 41585
diff changeset
64
ccaa52865fac tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents: 41585
diff changeset
65 ha1 = self._user_hashes.get((user, realm))
ccaa52865fac tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents: 41585
diff changeset
66 if not ha1:
ccaa52865fac tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents: 41585
diff changeset
67 log.write(b'No hash found for user/realm "%s/%s"' % (user, realm))
ccaa52865fac tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents: 41585
diff changeset
68 raise common.ErrorResponse(common.HTTP_FORBIDDEN, b"bad user")
ccaa52865fac tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents: 41585
diff changeset
69
ccaa52865fac tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents: 41585
diff changeset
70 qop = resp.get(b'qop', b'auth')
ccaa52865fac tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents: 41585
diff changeset
71 if qop != b'auth':
ccaa52865fac tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents: 41585
diff changeset
72 log.write(b"Unsupported qop: %s" % qop)
ccaa52865fac tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents: 41585
diff changeset
73 raise common.ErrorResponse(common.HTTP_FORBIDDEN, b"bad qop")
ccaa52865fac tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents: 41585
diff changeset
74
ccaa52865fac tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents: 41585
diff changeset
75 cnonce, ncvalue = resp.get(b'cnonce'), resp.get(b'nc')
ccaa52865fac tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents: 41585
diff changeset
76 if not cnonce or not ncvalue:
ccaa52865fac tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents: 41585
diff changeset
77 log.write(b'No cnonce (%s) or ncvalue (%s)' % (cnonce, ncvalue))
ccaa52865fac tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents: 41585
diff changeset
78 raise common.ErrorResponse(common.HTTP_FORBIDDEN, b"no cnonce")
ccaa52865fac tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents: 41585
diff changeset
79
ccaa52865fac tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents: 41585
diff changeset
80 a2 = b'%s:%s' % (req.method, resp[b'uri'])
ccaa52865fac tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents: 41585
diff changeset
81 noncebit = b"%s:%s:%s:%s:%s" % (nonce, ncvalue, cnonce, qop, h(a2))
ccaa52865fac tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents: 41585
diff changeset
82
ccaa52865fac tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents: 41585
diff changeset
83 respdig = kd(ha1, noncebit)
ccaa52865fac tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents: 41585
diff changeset
84 if respdig != resp[b'response']:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41589
diff changeset
85 log.write(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41589
diff changeset
86 b'User/realm "%s/%s" gave %s, but expected %s'
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41589
diff changeset
87 % (user, realm, resp[b'response'], respdig)
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41589
diff changeset
88 )
41587
ccaa52865fac tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents: 41585
diff changeset
89 return False
ccaa52865fac tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents: 41585
diff changeset
90
ccaa52865fac tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents: 41585
diff changeset
91 return True
41585
549af2fa089f tests: extract the http server authentication extension to a single module
Matt Harbison <matt_harbison@yahoo.com>
parents:
diff changeset
92
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41589
diff changeset
93
41589
46432c04f010 tests: enable HTTP digest testing
Matt Harbison <matt_harbison@yahoo.com>
parents: 41587
diff changeset
94 digest = digestauthserver()
46432c04f010 tests: enable HTTP digest testing
Matt Harbison <matt_harbison@yahoo.com>
parents: 41587
diff changeset
95
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41589
diff changeset
96
41585
549af2fa089f tests: extract the http server authentication extension to a single module
Matt Harbison <matt_harbison@yahoo.com>
parents:
diff changeset
97 def perform_authentication(hgweb, req, op):
549af2fa089f tests: extract the http server authentication extension to a single module
Matt Harbison <matt_harbison@yahoo.com>
parents:
diff changeset
98 auth = req.headers.get(b'Authorization')
41589
46432c04f010 tests: enable HTTP digest testing
Matt Harbison <matt_harbison@yahoo.com>
parents: 41587
diff changeset
99
46432c04f010 tests: enable HTTP digest testing
Matt Harbison <matt_harbison@yahoo.com>
parents: 41587
diff changeset
100 if req.headers.get(b'X-HgTest-AuthType') == b'Digest':
46432c04f010 tests: enable HTTP digest testing
Matt Harbison <matt_harbison@yahoo.com>
parents: 41587
diff changeset
101 if not auth:
46432c04f010 tests: enable HTTP digest testing
Matt Harbison <matt_harbison@yahoo.com>
parents: 41587
diff changeset
102 challenge = digest.makechallenge(b'mercurial')
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41589
diff changeset
103 raise common.ErrorResponse(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41589
diff changeset
104 common.HTTP_UNAUTHORIZED,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41589
diff changeset
105 b'who',
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41589
diff changeset
106 [(b'WWW-Authenticate', b'Digest %s' % challenge)],
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41589
diff changeset
107 )
41589
46432c04f010 tests: enable HTTP digest testing
Matt Harbison <matt_harbison@yahoo.com>
parents: 41587
diff changeset
108
46432c04f010 tests: enable HTTP digest testing
Matt Harbison <matt_harbison@yahoo.com>
parents: 41587
diff changeset
109 if not digest.checkauth(req, auth[7:]):
46432c04f010 tests: enable HTTP digest testing
Matt Harbison <matt_harbison@yahoo.com>
parents: 41587
diff changeset
110 raise common.ErrorResponse(common.HTTP_FORBIDDEN, b'no')
46432c04f010 tests: enable HTTP digest testing
Matt Harbison <matt_harbison@yahoo.com>
parents: 41587
diff changeset
111
46432c04f010 tests: enable HTTP digest testing
Matt Harbison <matt_harbison@yahoo.com>
parents: 41587
diff changeset
112 return
46432c04f010 tests: enable HTTP digest testing
Matt Harbison <matt_harbison@yahoo.com>
parents: 41587
diff changeset
113
41585
549af2fa089f tests: extract the http server authentication extension to a single module
Matt Harbison <matt_harbison@yahoo.com>
parents:
diff changeset
114 if not auth:
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41589
diff changeset
115 raise common.ErrorResponse(
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41589
diff changeset
116 common.HTTP_UNAUTHORIZED,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41589
diff changeset
117 b'who',
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41589
diff changeset
118 [(b'WWW-Authenticate', b'Basic Realm="mercurial"')],
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41589
diff changeset
119 )
41585
549af2fa089f tests: extract the http server authentication extension to a single module
Matt Harbison <matt_harbison@yahoo.com>
parents:
diff changeset
120
549af2fa089f tests: extract the http server authentication extension to a single module
Matt Harbison <matt_harbison@yahoo.com>
parents:
diff changeset
121 if base64.b64decode(auth.split()[1]).split(b':', 1) != [b'user', b'pass']:
549af2fa089f tests: extract the http server authentication extension to a single module
Matt Harbison <matt_harbison@yahoo.com>
parents:
diff changeset
122 raise common.ErrorResponse(common.HTTP_FORBIDDEN, b'no')
549af2fa089f tests: extract the http server authentication extension to a single module
Matt Harbison <matt_harbison@yahoo.com>
parents:
diff changeset
123
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 41589
diff changeset
124
41585
549af2fa089f tests: extract the http server authentication extension to a single module
Matt Harbison <matt_harbison@yahoo.com>
parents:
diff changeset
125 def extsetup(ui):
549af2fa089f tests: extract the http server authentication extension to a single module
Matt Harbison <matt_harbison@yahoo.com>
parents:
diff changeset
126 common.permhooks.insert(0, perform_authentication)
41589
46432c04f010 tests: enable HTTP digest testing
Matt Harbison <matt_harbison@yahoo.com>
parents: 41587
diff changeset
127 digest.adduser(b'user', b'pass', b'mercurial')