summaryrefslogtreecommitdiff
path: root/cherrypy/test
diff options
context:
space:
mode:
authorvisteya <none@none>2009-05-11 17:20:22 +0000
committervisteya <none@none>2009-05-11 17:20:22 +0000
commit0704e6ca8c3e5a6014ecc88e3265854faf9fe764 (patch)
tree62c60bb4f84ef3b8835b1ba4b8a3c140199bd0fe /cherrypy/test
parent78d5ecf00480a63b31e00445052eb35bafb27f24 (diff)
downloadcherrypy-git-0704e6ca8c3e5a6014ecc88e3265854faf9fe764.tar.gz
Added improved Tools (and tests) for basic and digest authentication, as mentioned in tickets #913 and #914
Diffstat (limited to 'cherrypy/test')
-rw-r--r--cherrypy/test/test_auth_basic.py89
-rw-r--r--cherrypy/test/test_auth_digest.py120
2 files changed, 209 insertions, 0 deletions
diff --git a/cherrypy/test/test_auth_basic.py b/cherrypy/test/test_auth_basic.py
new file mode 100644
index 00000000..982bb9a1
--- /dev/null
+++ b/cherrypy/test/test_auth_basic.py
@@ -0,0 +1,89 @@
+# This file is part of CherryPy <http://www.cherrypy.org/>
+# -*- coding: utf-8 -*-
+# vim:ts=4:sw=4:expandtab:fileencoding=utf-8
+
+from cherrypy.test import test
+test.prefer_parent_path()
+
+try:
+ from hashlib import md5
+except ImportError:
+ # Python 2.4 and earlier
+ from md5 import new as md5
+
+import cherrypy
+from cherrypy.lib import auth_basic
+
+def setup_server():
+ class Root:
+ def index(self):
+ return "This is public."
+ index.exposed = True
+
+ class BasicProtected:
+ def index(self):
+ return "Hello %s, you've been authorized." % cherrypy.request.login
+ index.exposed = True
+
+ class BasicProtected2:
+ def index(self):
+ return "Hello %s, you've been authorized." % cherrypy.request.login
+ index.exposed = True
+
+ userpassdict = {'xuser' : 'xpassword'}
+ userhashdict = {'xuser' : md5('xpassword').hexdigest()}
+
+ def checkpasshash(realm, user, password):
+ p = userhashdict.get(user)
+ return p and p == md5(password).hexdigest() or False
+
+ conf = {'/basic': {'tools.auth_basic.on': True,
+ 'tools.auth_basic.realm': 'wonderland',
+ 'tools.auth_basic.checkpassword_func': auth_basic.checkpassword_dict(userpassdict)},
+ '/basic2': {'tools.auth_basic.on': True,
+ 'tools.auth_basic.realm': 'wonderland',
+ 'tools.auth_basic.checkpassword_func': checkpasshash},
+ }
+
+ root = Root()
+ root.basic = BasicProtected()
+ root.basic2 = BasicProtected2()
+ cherrypy.tree.mount(root, config=conf)
+
+from cherrypy.test import helper
+
+class BasicAuthTest(helper.CPWebCase):
+
+ def testPublic(self):
+ self.getPage("/")
+ self.assertStatus('200 OK')
+ self.assertHeader('Content-Type', 'text/html')
+ self.assertBody('This is public.')
+
+ def testBasic(self):
+ self.getPage("/basic/")
+ self.assertStatus(401)
+ self.assertHeader('WWW-Authenticate', 'Basic realm="wonderland"')
+
+ self.getPage('/basic/', [('Authorization', 'Basic eHVzZXI6eHBhc3N3b3JX')])
+ self.assertStatus(401)
+
+ self.getPage('/basic/', [('Authorization', 'Basic eHVzZXI6eHBhc3N3b3Jk')])
+ self.assertStatus('200 OK')
+ self.assertBody("Hello xuser, you've been authorized.")
+
+ def testBasic2(self):
+ self.getPage("/basic2/")
+ self.assertStatus(401)
+ self.assertHeader('WWW-Authenticate', 'Basic realm="wonderland"')
+
+ self.getPage('/basic2/', [('Authorization', 'Basic eHVzZXI6eHBhc3N3b3JX')])
+ self.assertStatus(401)
+
+ self.getPage('/basic2/', [('Authorization', 'Basic eHVzZXI6eHBhc3N3b3Jk')])
+ self.assertStatus('200 OK')
+ self.assertBody("Hello xuser, you've been authorized.")
+
+
+if __name__ == "__main__":
+ helper.testmain()
diff --git a/cherrypy/test/test_auth_digest.py b/cherrypy/test/test_auth_digest.py
new file mode 100644
index 00000000..15000bdf
--- /dev/null
+++ b/cherrypy/test/test_auth_digest.py
@@ -0,0 +1,120 @@
+# This file is part of CherryPy <http://www.cherrypy.org/>
+# -*- coding: utf-8 -*-
+# vim:ts=4:sw=4:expandtab:fileencoding=utf-8
+
+from cherrypy.test import test
+test.prefer_parent_path()
+
+
+import cherrypy
+from cherrypy.lib import auth_digest
+
+def setup_server():
+ class Root:
+ def index(self):
+ return "This is public."
+ index.exposed = True
+
+ class DigestProtected:
+ def index(self):
+ return "Hello %s, you've been authorized." % cherrypy.request.login
+ index.exposed = True
+
+ def fetch_users():
+ return {'test': 'test'}
+
+
+ get_ha1 = cherrypy.lib.auth_digest.get_ha1_dict_plain(fetch_users())
+ conf = {'/digest': {'tools.auth_digest.on': True,
+ 'tools.auth_digest.realm': 'localhost',
+ 'tools.auth_digest.get_ha1_func': get_ha1,
+ 'tools.auth_digest.key': 'a565c27146791cfb',
+ 'tools.auth_digest.debug': 'True'}}
+
+ root = Root()
+ root.digest = DigestProtected()
+ cherrypy.tree.mount(root, config=conf)
+
+from cherrypy.test import helper
+
+class DigestAuthTest(helper.CPWebCase):
+
+ def testPublic(self):
+ self.getPage("/")
+ self.assertStatus('200 OK')
+ self.assertHeader('Content-Type', 'text/html')
+ self.assertBody('This is public.')
+
+ def testDigest(self):
+ self.getPage("/digest/")
+ self.assertStatus(401)
+
+ value = None
+ for k, v in self.headers:
+ if k.lower() == "www-authenticate":
+ if v.startswith("Digest"):
+ value = v
+ break
+
+ if value is None:
+ self._handlewebError("Digest authentification scheme was not found")
+
+ value = value[7:]
+ items = value.split(', ')
+ tokens = {}
+ for item in items:
+ key, value = item.split('=')
+ tokens[key.lower()] = value
+
+ missing_msg = "%s is missing"
+ bad_value_msg = "'%s' was expecting '%s' but found '%s'"
+ nonce = None
+ if 'realm' not in tokens:
+ self._handlewebError(missing_msg % 'realm')
+ elif tokens['realm'] != '"localhost"':
+ self._handlewebError(bad_value_msg % ('realm', '"localhost"', tokens['realm']))
+ if 'nonce' not in tokens:
+ self._handlewebError(missing_msg % 'nonce')
+ else:
+ nonce = tokens['nonce'].strip('"')
+ if 'algorithm' not in tokens:
+ self._handlewebError(missing_msg % 'algorithm')
+ elif tokens['algorithm'] != '"MD5"':
+ self._handlewebError(bad_value_msg % ('algorithm', '"MD5"', tokens['algorithm']))
+ if 'qop' not in tokens:
+ self._handlewebError(missing_msg % 'qop')
+ elif tokens['qop'] != '"auth"':
+ self._handlewebError(bad_value_msg % ('qop', '"auth"', tokens['qop']))
+
+ get_ha1_func = auth_digest.get_ha1_dict_plain({'test' : 'test'})
+
+ # Test user agent response with a wrong value for 'realm'
+ base_auth = 'Digest username="test", realm="wrong realm", nonce="%s", uri="/digest/", algorithm=MD5, response="%s", qop=auth, nc=%s, cnonce="1522e61005789929"'
+
+ auth_header = base_auth % (nonce, '11111111111111111111111111111111', '00000001')
+ auth = auth_digest.HttpDigestAuthorization(auth_header, 'GET')
+ # calculate the response digest
+ ha1 = get_ha1_func(auth.realm, 'test')
+ response = auth.request_digest(ha1)
+ # send response with correct response digest, but wrong realm
+ auth_header = base_auth % (nonce, response, '00000001')
+ self.getPage('/digest/', [('Authorization', auth_header)])
+ self.assertStatus(401)
+
+ # Test that must pass
+ base_auth = 'Digest username="test", realm="localhost", nonce="%s", uri="/digest/", algorithm=MD5, response="%s", qop=auth, nc=%s, cnonce="1522e61005789929"'
+
+ auth_header = base_auth % (nonce, '11111111111111111111111111111111', '00000001')
+ auth = auth_digest.HttpDigestAuthorization(auth_header, 'GET')
+ # calculate the response digest
+ ha1 = get_ha1_func('localhost', 'test')
+ response = auth.request_digest(ha1)
+ # send response with correct response digest
+ auth_header = base_auth % (nonce, response, '00000001')
+ self.getPage('/digest/', [('Authorization', auth_header)])
+ self.assertStatus('200 OK')
+ self.assertBody("Hello test, you've been authorized.")
+
+if __name__ == "__main__":
+ helper.testmain()
+