1 from cherrypy.test import test
2 test.prefer_parent_path()
3
4 import md5, sha
5
6 import cherrypy
7 from cherrypy.lib import httpauth
8
10 class Root:
11 def index(self):
12 return "This is public."
13 index.exposed = True
14
15 class DigestProtected:
16 def index(self):
17 return "Hello %s, you've been authorized." % cherrypy.request.login
18 index.exposed = True
19
20 class BasicProtected:
21 def index(self):
22 return "Hello %s, you've been authorized." % cherrypy.request.login
23 index.exposed = True
24
25 class BasicProtected2:
26 def index(self):
27 return "Hello %s, you've been authorized." % cherrypy.request.login
28 index.exposed = True
29
30 def fetch_users():
31 return {'test': 'test'}
32
33 def sha_password_encrypter(password):
34 return sha.new(password).hexdigest()
35
36 def fetch_password(username):
37 return sha.new('test').hexdigest()
38
39 conf = {'/digest': {'tools.digest_auth.on': True,
40 'tools.digest_auth.realm': 'localhost',
41 'tools.digest_auth.users': fetch_users},
42 '/basic': {'tools.basic_auth.on': True,
43 'tools.basic_auth.realm': 'localhost',
44 'tools.basic_auth.users': {'test': md5.new('test').hexdigest()}},
45 '/basic2': {'tools.basic_auth.on': True,
46 'tools.basic_auth.realm': 'localhost',
47 'tools.basic_auth.users': fetch_password,
48 'tools.basic_auth.encrypt': sha_password_encrypter}}
49
50 root = Root()
51 root.digest = DigestProtected()
52 root.basic = BasicProtected()
53 root.basic2 = BasicProtected2()
54 cherrypy.tree.mount(root, config=conf)
55 cherrypy.config.update({'environment': 'test_suite'})
56
57 from cherrypy.test import helper
58
60
66
78
90
92 self.getPage("/digest/")
93 self.assertStatus(401)
94
95 value = None
96 for k, v in self.headers:
97 if k.lower() == "www-authenticate":
98 if v.startswith("Digest"):
99 value = v
100 break
101
102 if value is None:
103 self._handlewebError("Digest authentification scheme was not found")
104
105 value = value[7:]
106 items = value.split(', ')
107 tokens = {}
108 for item in items:
109 key, value = item.split('=')
110 tokens[key.lower()] = value
111
112 missing_msg = "%s is missing"
113 bad_value_msg = "'%s' was expecting '%s' but found '%s'"
114 nonce = None
115 if 'realm' not in tokens:
116 self._handlewebError(missing_msg % 'realm')
117 elif tokens['realm'] != '"localhost"':
118 self._handlewebError(bad_value_msg % ('realm', '"localhost"', tokens['realm']))
119 if 'nonce' not in tokens:
120 self._handlewebError(missing_msg % 'nonce')
121 else:
122 nonce = tokens['nonce'].strip('"')
123 if 'algorithm' not in tokens:
124 self._handlewebError(missing_msg % 'algorithm')
125 elif tokens['algorithm'] != '"MD5"':
126 self._handlewebError(bad_value_msg % ('algorithm', '"MD5"', tokens['algorithm']))
127 if 'qop' not in tokens:
128 self._handlewebError(missing_msg % 'qop')
129 elif tokens['qop'] != '"auth"':
130 self._handlewebError(bad_value_msg % ('qop', '"auth"', tokens['qop']))
131
132
133 base_auth = 'Digest username="test", realm="wrong realm", nonce="%s", uri="/digest/", algorithm=MD5, response="%s", qop=auth, nc=%s, cnonce="1522e61005789929"'
134
135 auth = base_auth % (nonce, '', '00000001')
136 params = httpauth.parseAuthorization(auth)
137 response = httpauth._computeDigestResponse(params, 'test')
138
139 auth = base_auth % (nonce, response, '00000001')
140 self.getPage('/digest/', [('Authorization', auth)])
141 self.assertStatus(401)
142
143
144 base_auth = 'Digest username="test", realm="localhost", nonce="%s", uri="/digest/", algorithm=MD5, response="%s", qop=auth, nc=%s, cnonce="1522e61005789929"'
145
146 auth = base_auth % (nonce, '', '00000001')
147 params = httpauth.parseAuthorization(auth)
148 response = httpauth._computeDigestResponse(params, 'test')
149
150 auth = base_auth % (nonce, response, '00000001')
151 self.getPage('/digest/', [('Authorization', auth)])
152 self.assertStatus('200 OK')
153 self.assertBody("Hello test, you've been authorized.")
154
155 if __name__ == "__main__":
156 setup_server()
157 helper.testmain()
158