Handler for performing digest authentication.
| 82 | # Authentication infrastructure |
| 83 | |
| 84 | class DigestAuthHandler: |
| 85 | """Handler for performing digest authentication.""" |
| 86 | |
| 87 | def __init__(self): |
| 88 | self._request_num = 0 |
| 89 | self._nonces = [] |
| 90 | self._users = {} |
| 91 | self._realm_name = "Test Realm" |
| 92 | self._qop = "auth" |
| 93 | |
| 94 | def set_qop(self, qop): |
| 95 | self._qop = qop |
| 96 | |
| 97 | def set_users(self, users): |
| 98 | assert isinstance(users, dict) |
| 99 | self._users = users |
| 100 | |
| 101 | def set_realm(self, realm): |
| 102 | self._realm_name = realm |
| 103 | |
| 104 | def _generate_nonce(self): |
| 105 | self._request_num += 1 |
| 106 | nonce = hashlib.md5(str(self._request_num).encode("ascii")).hexdigest() |
| 107 | self._nonces.append(nonce) |
| 108 | return nonce |
| 109 | |
| 110 | def _create_auth_dict(self, auth_str): |
| 111 | first_space_index = auth_str.find(" ") |
| 112 | auth_str = auth_str[first_space_index+1:] |
| 113 | |
| 114 | parts = auth_str.split(",") |
| 115 | |
| 116 | auth_dict = {} |
| 117 | for part in parts: |
| 118 | name, value = part.split("=") |
| 119 | name = name.strip() |
| 120 | if value[0] == '"' and value[-1] == '"': |
| 121 | value = value[1:-1] |
| 122 | else: |
| 123 | value = value.strip() |
| 124 | auth_dict[name] = value |
| 125 | return auth_dict |
| 126 | |
| 127 | def _validate_auth(self, auth_dict, password, method, uri): |
| 128 | final_dict = {} |
| 129 | final_dict.update(auth_dict) |
| 130 | final_dict["password"] = password |
| 131 | final_dict["method"] = method |
| 132 | final_dict["uri"] = uri |
| 133 | HA1_str = "%(username)s:%(realm)s:%(password)s" % final_dict |
| 134 | HA1 = hashlib.md5(HA1_str.encode("ascii")).hexdigest() |
| 135 | HA2_str = "%(method)s:%(uri)s" % final_dict |
| 136 | HA2 = hashlib.md5(HA2_str.encode("ascii")).hexdigest() |
| 137 | final_dict["HA1"] = HA1 |
| 138 | final_dict["HA2"] = HA2 |
| 139 | response_str = "%(HA1)s:%(nonce)s:%(nc)s:" \ |
| 140 | "%(cnonce)s:%(qop)s:%(HA2)s" % final_dict |
| 141 | response = hashlib.md5(response_str.encode("ascii")).hexdigest() |