annotate tests/httpserverauth.py @ 48183:eb8092f9304f

dirstate-v2: Use "byte sequence" in docs The patch originally sent as https://phab.mercurial-scm.org/D11546 used "byte string" but that was changed during review to avoid suggesting Unicode or character encodings. However "byte range" sounds to be like a range of *indices* within a byte string/sequence elsewhere. This changes to "byte sequence". Python docs use "sequence" a lot when discussing the `bytes` type: https://docs.python.org/3/library/stdtypes.html Differential Revision: https://phab.mercurial-scm.org/D11623
author Simon Sapin <simon.sapin@octobus.net>
date Mon, 11 Oct 2021 17:31:27 +0200
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')