1 # This file is part of CherryPy <http://www.cherrypy.org/>
2 # -*- coding: utf-8 -*-
3 # vim:ts=4:sw=4:expandtab:fileencoding=utf-8
7 from cherrypy
.lib
import auth_digest
9 from cherrypy
.test
import helper
11 class DigestAuthTest(helper
.CPWebCase
):
16 return "This is public."
19 class DigestProtected
:
21 return "Hello %s, you've been authorized." % cherrypy
.request
.login
25 return {'test': 'test'}
28 get_ha1
= cherrypy
.lib
.auth_digest
.get_ha1_dict_plain(fetch_users())
29 conf
= {'/digest': {'tools.auth_digest.on': True,
30 'tools.auth_digest.realm': 'localhost',
31 'tools.auth_digest.get_ha1': get_ha1
,
32 'tools.auth_digest.key': 'a565c27146791cfb',
33 'tools.auth_digest.debug': 'True'}}
36 root
.digest
= DigestProtected()
37 cherrypy
.tree
.mount(root
, config
=conf
)
38 setup_server
= staticmethod(setup_server
)
42 self
.assertStatus('200 OK')
43 self
.assertHeader('Content-Type', 'text/html;charset=utf-8')
44 self
.assertBody('This is public.')
47 self
.getPage("/digest/")
48 self
.assertStatus(401)
51 for k
, v
in self
.headers
:
52 if k
.lower() == "www-authenticate":
53 if v
.startswith("Digest"):
58 self
._handlewebError
("Digest authentification scheme was not found")
61 items
= value
.split(', ')
64 key
, value
= item
.split('=')
65 tokens
[key
.lower()] = value
67 missing_msg
= "%s is missing"
68 bad_value_msg
= "'%s' was expecting '%s' but found '%s'"
70 if 'realm' not in tokens
:
71 self
._handlewebError
(missing_msg
% 'realm')
72 elif tokens
['realm'] != '"localhost"':
73 self
._handlewebError
(bad_value_msg
% ('realm', '"localhost"', tokens
['realm']))
74 if 'nonce' not in tokens
:
75 self
._handlewebError
(missing_msg
% 'nonce')
77 nonce
= tokens
['nonce'].strip('"')
78 if 'algorithm' not in tokens
:
79 self
._handlewebError
(missing_msg
% 'algorithm')
80 elif tokens
['algorithm'] != '"MD5"':
81 self
._handlewebError
(bad_value_msg
% ('algorithm', '"MD5"', tokens
['algorithm']))
82 if 'qop' not in tokens
:
83 self
._handlewebError
(missing_msg
% 'qop')
84 elif tokens
['qop'] != '"auth"':
85 self
._handlewebError
(bad_value_msg
% ('qop', '"auth"', tokens
['qop']))
87 get_ha1
= auth_digest
.get_ha1_dict_plain({'test' : 'test'})
89 # Test user agent response with a wrong value for 'realm'
90 base_auth
= 'Digest username="test", realm="wrong realm", nonce="%s", uri="/digest/", algorithm=MD5, response="%s", qop=auth, nc=%s, cnonce="1522e61005789929"'
92 auth_header
= base_auth
% (nonce
, '11111111111111111111111111111111', '00000001')
93 auth
= auth_digest
.HttpDigestAuthorization(auth_header
, 'GET')
94 # calculate the response digest
95 ha1
= get_ha1(auth
.realm
, 'test')
96 response
= auth
.request_digest(ha1
)
97 # send response with correct response digest, but wrong realm
98 auth_header
= base_auth
% (nonce
, response
, '00000001')
99 self
.getPage('/digest/', [('Authorization', auth_header
)])
100 self
.assertStatus(401)
102 # Test that must pass
103 base_auth
= 'Digest username="test", realm="localhost", nonce="%s", uri="/digest/", algorithm=MD5, response="%s", qop=auth, nc=%s, cnonce="1522e61005789929"'
105 auth_header
= base_auth
% (nonce
, '11111111111111111111111111111111', '00000001')
106 auth
= auth_digest
.HttpDigestAuthorization(auth_header
, 'GET')
107 # calculate the response digest
108 ha1
= get_ha1('localhost', 'test')
109 response
= auth
.request_digest(ha1
)
110 # send response with correct response digest
111 auth_header
= base_auth
% (nonce
, response
, '00000001')
112 self
.getPage('/digest/', [('Authorization', auth_header
)])
113 self
.assertStatus('200 OK')
114 self
.assertBody("Hello test, you've been authorized.")