2 from cherrypy
._cpcompat
import md5
, sha
, ntob
3 from cherrypy
.lib
import httpauth
5 from cherrypy
.test
import helper
7 class HTTPAuthTest(helper
.CPWebCase
):
12 return "This is public."
15 class DigestProtected
:
17 return "Hello %s, you've been authorized." % cherrypy
.request
.login
22 return "Hello %s, you've been authorized." % cherrypy
.request
.login
25 class BasicProtected2
:
27 return "Hello %s, you've been authorized." % cherrypy
.request
.login
31 return {'test': 'test'}
33 def sha_password_encrypter(password
):
34 return sha(ntob(password
)).hexdigest()
36 def fetch_password(username
):
37 return sha(ntob('test')).hexdigest()
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(ntob('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
}}
51 root
.digest
= DigestProtected()
52 root
.basic
= BasicProtected()
53 root
.basic2
= BasicProtected2()
54 cherrypy
.tree
.mount(root
, config
=conf
)
55 setup_server
= staticmethod(setup_server
)
60 self
.assertStatus('200 OK')
61 self
.assertHeader('Content-Type', 'text/html;charset=utf-8')
62 self
.assertBody('This is public.')
65 self
.getPage("/basic/")
66 self
.assertStatus(401)
67 self
.assertHeader('WWW-Authenticate', 'Basic realm="localhost"')
69 self
.getPage('/basic/', [('Authorization', 'Basic dGVzdDp0ZX60')])
70 self
.assertStatus(401)
72 self
.getPage('/basic/', [('Authorization', 'Basic dGVzdDp0ZXN0')])
73 self
.assertStatus('200 OK')
74 self
.assertBody("Hello test, you've been authorized.")
77 self
.getPage("/basic2/")
78 self
.assertStatus(401)
79 self
.assertHeader('WWW-Authenticate', 'Basic realm="localhost"')
81 self
.getPage('/basic2/', [('Authorization', 'Basic dGVzdDp0ZX60')])
82 self
.assertStatus(401)
84 self
.getPage('/basic2/', [('Authorization', 'Basic dGVzdDp0ZXN0')])
85 self
.assertStatus('200 OK')
86 self
.assertBody("Hello test, you've been authorized.")
89 self
.getPage("/digest/")
90 self
.assertStatus(401)
93 for k
, v
in self
.headers
:
94 if k
.lower() == "www-authenticate":
95 if v
.startswith("Digest"):
100 self
._handlewebError
("Digest authentification scheme was not found")
103 items
= value
.split(', ')
106 key
, value
= item
.split('=')
107 tokens
[key
.lower()] = value
109 missing_msg
= "%s is missing"
110 bad_value_msg
= "'%s' was expecting '%s' but found '%s'"
112 if 'realm' not in tokens
:
113 self
._handlewebError
(missing_msg
% 'realm')
114 elif tokens
['realm'] != '"localhost"':
115 self
._handlewebError
(bad_value_msg
% ('realm', '"localhost"', tokens
['realm']))
116 if 'nonce' not in tokens
:
117 self
._handlewebError
(missing_msg
% 'nonce')
119 nonce
= tokens
['nonce'].strip('"')
120 if 'algorithm' not in tokens
:
121 self
._handlewebError
(missing_msg
% 'algorithm')
122 elif tokens
['algorithm'] != '"MD5"':
123 self
._handlewebError
(bad_value_msg
% ('algorithm', '"MD5"', tokens
['algorithm']))
124 if 'qop' not in tokens
:
125 self
._handlewebError
(missing_msg
% 'qop')
126 elif tokens
['qop'] != '"auth"':
127 self
._handlewebError
(bad_value_msg
% ('qop', '"auth"', tokens
['qop']))
129 # Test a wrong 'realm' value
130 base_auth
= 'Digest username="test", realm="wrong realm", nonce="%s", uri="/digest/", algorithm=MD5, response="%s", qop=auth, nc=%s, cnonce="1522e61005789929"'
132 auth
= base_auth
% (nonce
, '', '00000001')
133 params
= httpauth
.parseAuthorization(auth
)
134 response
= httpauth
._computeDigestResponse
(params
, 'test')
136 auth
= base_auth
% (nonce
, response
, '00000001')
137 self
.getPage('/digest/', [('Authorization', auth
)])
138 self
.assertStatus(401)
140 # Test that must pass
141 base_auth
= 'Digest username="test", realm="localhost", nonce="%s", uri="/digest/", algorithm=MD5, response="%s", qop=auth, nc=%s, cnonce="1522e61005789929"'
143 auth
= base_auth
% (nonce
, '', '00000001')
144 params
= httpauth
.parseAuthorization(auth
)
145 response
= httpauth
._computeDigestResponse
(params
, 'test')
147 auth
= base_auth
% (nonce
, response
, '00000001')
148 self
.getPage('/digest/', [('Authorization', auth
)])
149 self
.assertStatus('200 OK')
150 self
.assertBody("Hello test, you've been authorized.")