Mercurial > hg
annotate tests/httpserverauth.py @ 42920:a50661567f83
uncommit: drop the hyphen from --current-user and --current-date
I didn't pay enough attention to these long forms- graft, amend and MQ already
use the old style naming. It's probably more important to be consistent than
modern. The hypenated style came from evolve.
Yuya mentioned this naming discrepancy in 4145fd3569c3, but it didn't attract
any discussion[1]. There's also a bit of inconsistency in that the default
parameter for `currentdate` is `False` for graft, and `None` for the rest.
[1] https://www.mercurial-scm.org/pipermail/mercurial-devel/2019-January/126767.html
Differential Revision: https://phab.mercurial-scm.org/D6841
author | Matt Harbison <matt_harbison@yahoo.com> |
---|---|
date | Tue, 10 Sep 2019 22:04:22 -0400 |
parents | 46432c04f010 |
children | 2372284d9457 |
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 |
41587
ccaa52865fac
tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents:
41585
diff
changeset
|
7 from mercurial import ( |
ccaa52865fac
tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents:
41585
diff
changeset
|
8 node, |
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 |
ccaa52865fac
tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents:
41585
diff
changeset
|
11 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
|
12 """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
|
13 parsed = {} |
ccaa52865fac
tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents:
41585
diff
changeset
|
14 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
|
15 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
|
16 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
|
17 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
|
18 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
|
19 return parsed |
ccaa52865fac
tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents:
41585
diff
changeset
|
20 |
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' |
ccaa52865fac
tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents:
41585
diff
changeset
|
45 return b'realm="%s", nonce="%s", algorithm=MD5, qop="auth"' % (realm, |
ccaa52865fac
tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents:
41585
diff
changeset
|
46 nonce) |
ccaa52865fac
tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents:
41585
diff
changeset
|
47 |
ccaa52865fac
tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents:
41585
diff
changeset
|
48 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
|
49 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
|
50 |
ccaa52865fac
tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents:
41585
diff
changeset
|
51 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
|
52 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
|
53 |
ccaa52865fac
tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents:
41585
diff
changeset
|
54 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
|
55 log.write(b'Unsupported algorithm: %s' % resp.get(b'algorithm')) |
ccaa52865fac
tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents:
41585
diff
changeset
|
56 raise common.ErrorResponse(common.HTTP_FORBIDDEN, |
ccaa52865fac
tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents:
41585
diff
changeset
|
57 b"unknown algorithm") |
ccaa52865fac
tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents:
41585
diff
changeset
|
58 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
|
59 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
|
60 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
|
61 |
ccaa52865fac
tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents:
41585
diff
changeset
|
62 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
|
63 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
|
64 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
|
65 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
|
66 |
ccaa52865fac
tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents:
41585
diff
changeset
|
67 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
|
68 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
|
69 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
|
70 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
|
71 |
ccaa52865fac
tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents:
41585
diff
changeset
|
72 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
|
73 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
|
74 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
|
75 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
|
76 |
ccaa52865fac
tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents:
41585
diff
changeset
|
77 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
|
78 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
|
79 |
ccaa52865fac
tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents:
41585
diff
changeset
|
80 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
|
81 if respdig != resp[b'response']: |
ccaa52865fac
tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents:
41585
diff
changeset
|
82 log.write(b'User/realm "%s/%s" gave %s, but expected %s' |
ccaa52865fac
tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents:
41585
diff
changeset
|
83 % (user, realm, resp[b'response'], respdig)) |
ccaa52865fac
tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents:
41585
diff
changeset
|
84 return False |
ccaa52865fac
tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents:
41585
diff
changeset
|
85 |
ccaa52865fac
tests: add code to handle HTTP digests on the server side
Matt Harbison <matt_harbison@yahoo.com>
parents:
41585
diff
changeset
|
86 return True |
41585
549af2fa089f
tests: extract the http server authentication extension to a single module
Matt Harbison <matt_harbison@yahoo.com>
parents:
diff
changeset
|
87 |
41589
46432c04f010
tests: enable HTTP digest testing
Matt Harbison <matt_harbison@yahoo.com>
parents:
41587
diff
changeset
|
88 digest = digestauthserver() |
46432c04f010
tests: enable HTTP digest testing
Matt Harbison <matt_harbison@yahoo.com>
parents:
41587
diff
changeset
|
89 |
41585
549af2fa089f
tests: extract the http server authentication extension to a single module
Matt Harbison <matt_harbison@yahoo.com>
parents:
diff
changeset
|
90 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
|
91 auth = req.headers.get(b'Authorization') |
41589
46432c04f010
tests: enable HTTP digest testing
Matt Harbison <matt_harbison@yahoo.com>
parents:
41587
diff
changeset
|
92 |
46432c04f010
tests: enable HTTP digest testing
Matt Harbison <matt_harbison@yahoo.com>
parents:
41587
diff
changeset
|
93 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
|
94 if not auth: |
46432c04f010
tests: enable HTTP digest testing
Matt Harbison <matt_harbison@yahoo.com>
parents:
41587
diff
changeset
|
95 challenge = digest.makechallenge(b'mercurial') |
46432c04f010
tests: enable HTTP digest testing
Matt Harbison <matt_harbison@yahoo.com>
parents:
41587
diff
changeset
|
96 raise common.ErrorResponse(common.HTTP_UNAUTHORIZED, b'who', |
46432c04f010
tests: enable HTTP digest testing
Matt Harbison <matt_harbison@yahoo.com>
parents:
41587
diff
changeset
|
97 [(b'WWW-Authenticate', b'Digest %s' % challenge)]) |
46432c04f010
tests: enable HTTP digest testing
Matt Harbison <matt_harbison@yahoo.com>
parents:
41587
diff
changeset
|
98 |
46432c04f010
tests: enable HTTP digest testing
Matt Harbison <matt_harbison@yahoo.com>
parents:
41587
diff
changeset
|
99 if not digest.checkauth(req, auth[7:]): |
46432c04f010
tests: enable HTTP digest testing
Matt Harbison <matt_harbison@yahoo.com>
parents:
41587
diff
changeset
|
100 raise common.ErrorResponse(common.HTTP_FORBIDDEN, b'no') |
46432c04f010
tests: enable HTTP digest testing
Matt Harbison <matt_harbison@yahoo.com>
parents:
41587
diff
changeset
|
101 |
46432c04f010
tests: enable HTTP digest testing
Matt Harbison <matt_harbison@yahoo.com>
parents:
41587
diff
changeset
|
102 return |
46432c04f010
tests: enable HTTP digest testing
Matt Harbison <matt_harbison@yahoo.com>
parents:
41587
diff
changeset
|
103 |
41585
549af2fa089f
tests: extract the http server authentication extension to a single module
Matt Harbison <matt_harbison@yahoo.com>
parents:
diff
changeset
|
104 if not auth: |
549af2fa089f
tests: extract the http server authentication extension to a single module
Matt Harbison <matt_harbison@yahoo.com>
parents:
diff
changeset
|
105 raise common.ErrorResponse(common.HTTP_UNAUTHORIZED, b'who', |
549af2fa089f
tests: extract the http server authentication extension to a single module
Matt Harbison <matt_harbison@yahoo.com>
parents:
diff
changeset
|
106 [(b'WWW-Authenticate', b'Basic Realm="mercurial"')]) |
549af2fa089f
tests: extract the http server authentication extension to a single module
Matt Harbison <matt_harbison@yahoo.com>
parents:
diff
changeset
|
107 |
549af2fa089f
tests: extract the http server authentication extension to a single module
Matt Harbison <matt_harbison@yahoo.com>
parents:
diff
changeset
|
108 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
|
109 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
|
110 |
549af2fa089f
tests: extract the http server authentication extension to a single module
Matt Harbison <matt_harbison@yahoo.com>
parents:
diff
changeset
|
111 def extsetup(ui): |
549af2fa089f
tests: extract the http server authentication extension to a single module
Matt Harbison <matt_harbison@yahoo.com>
parents:
diff
changeset
|
112 common.permhooks.insert(0, perform_authentication) |
41589
46432c04f010
tests: enable HTTP digest testing
Matt Harbison <matt_harbison@yahoo.com>
parents:
41587
diff
changeset
|
113 digest.adduser(b'user', b'pass', b'mercurial') |