/src/libsoup/libsoup/auth/soup-auth-digest.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */ |
2 | | /* |
3 | | * soup-auth-digest.c: HTTP Digest Authentication |
4 | | * |
5 | | * Copyright (C) 2001-2003, Ximian, Inc. |
6 | | */ |
7 | | |
8 | | #ifdef HAVE_CONFIG_H |
9 | | #include <config.h> |
10 | | #endif |
11 | | |
12 | | #include <string.h> |
13 | | |
14 | | #include "auth/soup-auth-digest-private.h" |
15 | | #include "soup.h" |
16 | | #include "soup-message-private.h" |
17 | | #include "soup-message-headers-private.h" |
18 | | #include "soup-uri-utils-private.h" |
19 | | |
20 | | #ifdef G_OS_WIN32 |
21 | | #include <process.h> |
22 | | #endif |
23 | | |
24 | | struct _SoupAuthDigest { |
25 | | SoupAuth parent; |
26 | | }; |
27 | | |
28 | | typedef struct { |
29 | | char *user; |
30 | | char hex_urp[33]; |
31 | | char hex_a1[33]; |
32 | | |
33 | | /* These are provided by the server */ |
34 | | char *nonce; |
35 | | char *opaque; |
36 | | SoupAuthDigestQop qop_options; |
37 | | SoupAuthDigestAlgorithm algorithm; |
38 | | char *domain; |
39 | | |
40 | | /* These are generated by the client */ |
41 | | char *cnonce; |
42 | | int nc; |
43 | | SoupAuthDigestQop qop; |
44 | | } SoupAuthDigestPrivate; |
45 | | |
46 | | static void recompute_hex_a1 (SoupAuthDigestPrivate *priv); |
47 | | |
48 | | /** |
49 | | * SoupAuthDigest: |
50 | | * |
51 | | * HTTP "Digest" authentication. |
52 | | * |
53 | | * [class@Session]s support this by default; if you want to disable |
54 | | * support for it, call [method@Session.remove_feature_by_type] |
55 | | * passing %SOUP_TYPE_AUTH_DIGEST. |
56 | | * |
57 | | */ |
58 | | |
59 | | G_DEFINE_FINAL_TYPE_WITH_PRIVATE (SoupAuthDigest, soup_auth_digest, SOUP_TYPE_AUTH) |
60 | | |
61 | | static void |
62 | | soup_auth_digest_init (SoupAuthDigest *digest) |
63 | 0 | { |
64 | 0 | } |
65 | | |
66 | | static void |
67 | | soup_auth_digest_finalize (GObject *object) |
68 | 0 | { |
69 | 0 | SoupAuthDigestPrivate *priv = soup_auth_digest_get_instance_private (SOUP_AUTH_DIGEST (object)); |
70 | |
|
71 | 0 | g_free (priv->user); |
72 | 0 | g_free (priv->nonce); |
73 | 0 | g_free (priv->domain); |
74 | 0 | g_free (priv->cnonce); |
75 | 0 | g_free (priv->opaque); |
76 | |
|
77 | 0 | memset (priv->hex_urp, 0, sizeof (priv->hex_urp)); |
78 | 0 | memset (priv->hex_a1, 0, sizeof (priv->hex_a1)); |
79 | |
|
80 | 0 | G_OBJECT_CLASS (soup_auth_digest_parent_class)->finalize (object); |
81 | 0 | } |
82 | | |
83 | | SoupAuthDigestAlgorithm |
84 | | soup_auth_digest_parse_algorithm (const char *algorithm) |
85 | 0 | { |
86 | 0 | if (!algorithm || !g_ascii_strcasecmp (algorithm, "MD5")) |
87 | 0 | return SOUP_AUTH_DIGEST_ALGORITHM_MD5; |
88 | 0 | else if (!g_ascii_strcasecmp (algorithm, "MD5-sess")) |
89 | 0 | return SOUP_AUTH_DIGEST_ALGORITHM_MD5_SESS; |
90 | 0 | else |
91 | 0 | return -1; |
92 | 0 | } |
93 | | |
94 | | char * |
95 | | soup_auth_digest_get_algorithm (SoupAuthDigestAlgorithm algorithm) |
96 | 0 | { |
97 | 0 | if (algorithm == SOUP_AUTH_DIGEST_ALGORITHM_MD5) |
98 | 0 | return g_strdup ("MD5"); |
99 | 0 | else if (algorithm == SOUP_AUTH_DIGEST_ALGORITHM_MD5_SESS) |
100 | 0 | return g_strdup ("MD5-sess"); |
101 | 0 | else |
102 | 0 | return NULL; |
103 | 0 | } |
104 | | |
105 | | SoupAuthDigestQop |
106 | | soup_auth_digest_parse_qop (const char *qop) |
107 | 0 | { |
108 | 0 | GSList *qop_values, *iter; |
109 | 0 | SoupAuthDigestQop out = 0; |
110 | |
|
111 | 0 | g_return_val_if_fail (qop != NULL, 0); |
112 | | |
113 | 0 | qop_values = soup_header_parse_list (qop); |
114 | 0 | for (iter = qop_values; iter; iter = iter->next) { |
115 | 0 | if (!g_ascii_strcasecmp (iter->data, "auth")) |
116 | 0 | out |= SOUP_AUTH_DIGEST_QOP_AUTH; |
117 | 0 | else if (!g_ascii_strcasecmp (iter->data, "auth-int")) |
118 | 0 | out |= SOUP_AUTH_DIGEST_QOP_AUTH_INT; |
119 | 0 | } |
120 | 0 | soup_header_free_list (qop_values); |
121 | |
|
122 | 0 | return out; |
123 | 0 | } |
124 | | |
125 | | char * |
126 | | soup_auth_digest_get_qop (SoupAuthDigestQop qop) |
127 | 0 | { |
128 | 0 | GString *out; |
129 | |
|
130 | 0 | out = g_string_new (NULL); |
131 | 0 | if (qop & SOUP_AUTH_DIGEST_QOP_AUTH) |
132 | 0 | g_string_append (out, "auth"); |
133 | 0 | if (qop & SOUP_AUTH_DIGEST_QOP_AUTH_INT) { |
134 | 0 | if (qop & SOUP_AUTH_DIGEST_QOP_AUTH) |
135 | 0 | g_string_append (out, ","); |
136 | 0 | g_string_append (out, "auth-int"); |
137 | 0 | } |
138 | |
|
139 | 0 | return g_string_free (out, FALSE); |
140 | 0 | } |
141 | | |
142 | | static gboolean |
143 | | soup_auth_digest_update (SoupAuth *auth, SoupMessage *msg, |
144 | | GHashTable *auth_params) |
145 | 0 | { |
146 | 0 | SoupAuthDigest *auth_digest = SOUP_AUTH_DIGEST (auth); |
147 | 0 | SoupAuthDigestPrivate *priv = soup_auth_digest_get_instance_private (auth_digest); |
148 | 0 | const char *stale, *qop; |
149 | 0 | guint qop_options; |
150 | 0 | gboolean ok = TRUE; |
151 | |
|
152 | 0 | if (!soup_auth_get_realm (auth) || !g_hash_table_lookup (auth_params, "nonce")) |
153 | 0 | return FALSE; |
154 | | |
155 | 0 | g_free (priv->domain); |
156 | 0 | g_free (priv->nonce); |
157 | 0 | g_free (priv->opaque); |
158 | |
|
159 | 0 | priv->nc = 1; |
160 | |
|
161 | 0 | priv->domain = g_strdup (g_hash_table_lookup (auth_params, "domain")); |
162 | 0 | priv->nonce = g_strdup (g_hash_table_lookup (auth_params, "nonce")); |
163 | 0 | priv->opaque = g_strdup (g_hash_table_lookup (auth_params, "opaque")); |
164 | |
|
165 | 0 | qop = g_hash_table_lookup (auth_params, "qop"); |
166 | 0 | if (qop) { |
167 | 0 | qop_options = soup_auth_digest_parse_qop (qop); |
168 | | /* We only support auth */ |
169 | 0 | if (!(qop_options & SOUP_AUTH_DIGEST_QOP_AUTH)) |
170 | 0 | ok = FALSE; |
171 | 0 | priv->qop = SOUP_AUTH_DIGEST_QOP_AUTH; |
172 | 0 | } else |
173 | 0 | priv->qop = 0; |
174 | |
|
175 | 0 | priv->algorithm = soup_auth_digest_parse_algorithm (g_hash_table_lookup (auth_params, "algorithm")); |
176 | 0 | if (priv->algorithm == -1) |
177 | 0 | ok = FALSE; |
178 | |
|
179 | 0 | if (ok) { |
180 | 0 | stale = g_hash_table_lookup (auth_params, "stale"); |
181 | 0 | if (stale && !g_ascii_strcasecmp (stale, "TRUE") && *priv->hex_urp) |
182 | 0 | recompute_hex_a1 (priv); |
183 | 0 | else { |
184 | 0 | g_free (priv->user); |
185 | 0 | priv->user = NULL; |
186 | 0 | g_free (priv->cnonce); |
187 | 0 | priv->cnonce = NULL; |
188 | 0 | memset (priv->hex_urp, 0, sizeof (priv->hex_urp)); |
189 | 0 | memset (priv->hex_a1, 0, sizeof (priv->hex_a1)); |
190 | 0 | } |
191 | 0 | } |
192 | |
|
193 | 0 | return ok; |
194 | 0 | } |
195 | | |
196 | | static GSList * |
197 | | soup_auth_digest_get_protection_space (SoupAuth *auth, GUri *source_uri) |
198 | 0 | { |
199 | 0 | SoupAuthDigest *auth_digest = SOUP_AUTH_DIGEST (auth); |
200 | 0 | SoupAuthDigestPrivate *priv = soup_auth_digest_get_instance_private (auth_digest); |
201 | 0 | GSList *space = NULL; |
202 | 0 | GUri *uri; |
203 | 0 | char **dvec, *d, *dir, *slash; |
204 | 0 | int dix; |
205 | |
|
206 | 0 | if (!priv->domain || !*priv->domain) { |
207 | | /* If no domain directive, the protection space is the |
208 | | * whole server. |
209 | | */ |
210 | 0 | return g_slist_prepend (NULL, g_strdup ("")); |
211 | 0 | } |
212 | | |
213 | 0 | dvec = g_strsplit (priv->domain, " ", 0); |
214 | 0 | for (dix = 0; dvec[dix] != NULL; dix++) { |
215 | 0 | d = dvec[dix]; |
216 | 0 | if (*d == '/') |
217 | 0 | dir = g_strdup (d); |
218 | 0 | else { |
219 | 0 | uri = g_uri_parse (d, SOUP_HTTP_URI_FLAGS, NULL); |
220 | 0 | if (uri && |
221 | 0 | g_strcmp0 (g_uri_get_scheme (uri), g_uri_get_scheme (source_uri)) == 0 && |
222 | 0 | g_uri_get_port (uri) == g_uri_get_port (source_uri) && |
223 | 0 | !g_strcmp0 (g_uri_get_host (uri), g_uri_get_host (source_uri))) |
224 | 0 | dir = g_strdup (g_uri_get_path (uri)); |
225 | 0 | else |
226 | 0 | dir = NULL; |
227 | 0 | if (uri) |
228 | 0 | g_uri_unref (uri); |
229 | 0 | } |
230 | |
|
231 | 0 | if (dir) { |
232 | 0 | slash = strrchr (dir, '/'); |
233 | 0 | if (slash && !slash[1]) |
234 | 0 | *slash = '\0'; |
235 | |
|
236 | 0 | space = g_slist_prepend (space, dir); |
237 | 0 | } |
238 | 0 | } |
239 | 0 | g_strfreev (dvec); |
240 | |
|
241 | 0 | return space; |
242 | 0 | } |
243 | | |
244 | | void |
245 | | soup_auth_digest_compute_hex_urp (const char *username, |
246 | | const char *realm, |
247 | | const char *password, |
248 | | char hex_urp[33]) |
249 | 0 | { |
250 | 0 | GChecksum *checksum; |
251 | |
|
252 | 0 | checksum = g_checksum_new (G_CHECKSUM_MD5); |
253 | 0 | g_checksum_update (checksum, (guchar *)username, strlen (username)); |
254 | 0 | g_checksum_update (checksum, (guchar *)":", 1); |
255 | 0 | g_checksum_update (checksum, (guchar *)realm, strlen (realm)); |
256 | 0 | g_checksum_update (checksum, (guchar *)":", 1); |
257 | 0 | g_checksum_update (checksum, (guchar *)password, strlen (password)); |
258 | 0 | g_strlcpy (hex_urp, g_checksum_get_string (checksum), 33); |
259 | 0 | g_checksum_free (checksum); |
260 | 0 | } |
261 | | |
262 | | void |
263 | | soup_auth_digest_compute_hex_a1 (const char *hex_urp, |
264 | | SoupAuthDigestAlgorithm algorithm, |
265 | | const char *nonce, |
266 | | const char *cnonce, |
267 | | char hex_a1[33]) |
268 | 0 | { |
269 | 0 | if (algorithm == SOUP_AUTH_DIGEST_ALGORITHM_MD5) { |
270 | | /* In MD5, A1 is just user:realm:password, so hex_A1 |
271 | | * is just hex_urp. |
272 | | */ |
273 | | /* You'd think you could say "sizeof (hex_a1)" here, |
274 | | * but you'd be wrong. |
275 | | */ |
276 | 0 | memcpy (hex_a1, hex_urp, 33); |
277 | 0 | } else { |
278 | 0 | GChecksum *checksum; |
279 | | |
280 | | /* In MD5-sess, A1 is hex_urp:nonce:cnonce */ |
281 | |
|
282 | 0 | g_assert (nonce && cnonce); |
283 | | |
284 | 0 | checksum = g_checksum_new (G_CHECKSUM_MD5); |
285 | 0 | g_checksum_update (checksum, (guchar *)hex_urp, strlen (hex_urp)); |
286 | 0 | g_checksum_update (checksum, (guchar *)":", 1); |
287 | 0 | g_checksum_update (checksum, (guchar *)nonce, strlen (nonce)); |
288 | 0 | g_checksum_update (checksum, (guchar *)":", 1); |
289 | 0 | g_checksum_update (checksum, (guchar *)cnonce, strlen (cnonce)); |
290 | 0 | g_strlcpy (hex_a1, g_checksum_get_string (checksum), 33); |
291 | 0 | g_checksum_free (checksum); |
292 | 0 | } |
293 | 0 | } |
294 | | |
295 | | static void |
296 | | recompute_hex_a1 (SoupAuthDigestPrivate *priv) |
297 | 0 | { |
298 | 0 | soup_auth_digest_compute_hex_a1 (priv->hex_urp, |
299 | 0 | priv->algorithm, |
300 | 0 | priv->nonce, |
301 | 0 | priv->cnonce, |
302 | 0 | priv->hex_a1); |
303 | 0 | } |
304 | | |
305 | | static void |
306 | | soup_auth_digest_authenticate (SoupAuth *auth, const char *username, |
307 | | const char *password) |
308 | 0 | { |
309 | 0 | SoupAuthDigest *auth_digest = SOUP_AUTH_DIGEST (auth); |
310 | 0 | SoupAuthDigestPrivate *priv = soup_auth_digest_get_instance_private (auth_digest); |
311 | 0 | char *bgen; |
312 | |
|
313 | 0 | g_clear_pointer (&priv->cnonce, g_free); |
314 | 0 | g_clear_pointer (&priv->user, g_free); |
315 | | |
316 | | /* Create client nonce */ |
317 | 0 | bgen = g_strdup_printf ("%p:%lu:%lu", |
318 | 0 | auth, |
319 | 0 | (unsigned long) getpid (), |
320 | 0 | (unsigned long) time (0)); |
321 | 0 | priv->cnonce = g_base64_encode ((guchar *)bgen, strlen (bgen)); |
322 | 0 | g_free (bgen); |
323 | |
|
324 | 0 | priv->user = g_strdup (username); |
325 | | |
326 | | /* compute "URP" (user:realm:password) */ |
327 | 0 | soup_auth_digest_compute_hex_urp (username, soup_auth_get_realm (auth), |
328 | 0 | password ? password : "", |
329 | 0 | priv->hex_urp); |
330 | | |
331 | | /* And compute A1 from that */ |
332 | 0 | recompute_hex_a1 (priv); |
333 | 0 | } |
334 | | |
335 | | static gboolean |
336 | | soup_auth_digest_is_authenticated (SoupAuth *auth) |
337 | 0 | { |
338 | 0 | SoupAuthDigestPrivate *priv = soup_auth_digest_get_instance_private (SOUP_AUTH_DIGEST (auth)); |
339 | |
|
340 | 0 | return priv->cnonce != NULL; |
341 | 0 | } |
342 | | |
343 | | void |
344 | | soup_auth_digest_compute_response (const char *method, |
345 | | const char *uri, |
346 | | const char *hex_a1, |
347 | | SoupAuthDigestQop qop, |
348 | | const char *nonce, |
349 | | const char *cnonce, |
350 | | int nc, |
351 | | char response[33]) |
352 | 0 | { |
353 | 0 | char hex_a2[33]; |
354 | 0 | GChecksum *checksum; |
355 | | |
356 | | /* compute A2 */ |
357 | 0 | checksum = g_checksum_new (G_CHECKSUM_MD5); |
358 | 0 | g_checksum_update (checksum, (guchar *)method, strlen (method)); |
359 | 0 | g_checksum_update (checksum, (guchar *)":", 1); |
360 | 0 | g_checksum_update (checksum, (guchar *)uri, strlen (uri)); |
361 | 0 | memcpy (hex_a2, g_checksum_get_string (checksum), sizeof (char) * 33); |
362 | 0 | g_checksum_free (checksum); |
363 | | |
364 | | /* compute KD */ |
365 | 0 | checksum = g_checksum_new (G_CHECKSUM_MD5); |
366 | 0 | g_checksum_update (checksum, (guchar *)hex_a1, strlen (hex_a1)); |
367 | 0 | g_checksum_update (checksum, (guchar *)":", 1); |
368 | 0 | g_checksum_update (checksum, (guchar *)nonce, strlen (nonce)); |
369 | 0 | g_checksum_update (checksum, (guchar *)":", 1); |
370 | |
|
371 | 0 | if (qop) { |
372 | 0 | char tmp[9]; |
373 | |
|
374 | 0 | g_assert (cnonce); |
375 | | |
376 | 0 | g_snprintf (tmp, 9, "%.8x", nc); |
377 | 0 | g_checksum_update (checksum, (guchar *)tmp, strlen (tmp)); |
378 | 0 | g_checksum_update (checksum, (guchar *)":", 1); |
379 | 0 | g_checksum_update (checksum, (guchar *)cnonce, strlen (cnonce)); |
380 | 0 | g_checksum_update (checksum, (guchar *)":", 1); |
381 | |
|
382 | 0 | if (!(qop & SOUP_AUTH_DIGEST_QOP_AUTH)) |
383 | 0 | g_warn_if_reached (); |
384 | 0 | g_checksum_update (checksum, (guchar *)"auth", strlen ("auth")); |
385 | 0 | g_checksum_update (checksum, (guchar *)":", 1); |
386 | 0 | } |
387 | | |
388 | 0 | g_checksum_update (checksum, (guchar *)hex_a2, 32); |
389 | 0 | memcpy (response, g_checksum_get_string (checksum), sizeof (char) * 33); |
390 | 0 | g_checksum_free (checksum); |
391 | 0 | } |
392 | | |
393 | | static void |
394 | | authentication_info_cb (SoupMessage *msg, gpointer data) |
395 | 0 | { |
396 | 0 | SoupAuth *auth = data; |
397 | 0 | SoupAuthDigest *auth_digest = SOUP_AUTH_DIGEST (auth); |
398 | 0 | SoupAuthDigestPrivate *priv = soup_auth_digest_get_instance_private (auth_digest); |
399 | 0 | const char *header; |
400 | 0 | GHashTable *auth_params; |
401 | 0 | char *nextnonce; |
402 | |
|
403 | 0 | if (auth != soup_message_get_auth (msg)) |
404 | 0 | return; |
405 | | |
406 | 0 | header = soup_message_headers_get_one_common (soup_message_get_response_headers (msg), |
407 | 0 | soup_auth_is_for_proxy (auth) ? |
408 | 0 | SOUP_HEADER_PROXY_AUTHENTICATION_INFO : |
409 | 0 | SOUP_HEADER_AUTHENTICATION_INFO); |
410 | 0 | g_return_if_fail (header != NULL); |
411 | | |
412 | 0 | auth_params = soup_header_parse_param_list (header); |
413 | 0 | if (!auth_params) |
414 | 0 | return; |
415 | | |
416 | 0 | nextnonce = g_strdup (g_hash_table_lookup (auth_params, "nextnonce")); |
417 | 0 | if (nextnonce) { |
418 | 0 | g_free (priv->nonce); |
419 | 0 | priv->nonce = nextnonce; |
420 | 0 | } |
421 | |
|
422 | 0 | soup_header_free_param_list (auth_params); |
423 | 0 | } |
424 | | |
425 | | static char * |
426 | | soup_auth_digest_get_authorization (SoupAuth *auth, SoupMessage *msg) |
427 | 0 | { |
428 | 0 | SoupAuthDigest *auth_digest = SOUP_AUTH_DIGEST (auth); |
429 | 0 | SoupAuthDigestPrivate *priv = soup_auth_digest_get_instance_private (auth_digest); |
430 | 0 | char response[33], *token; |
431 | 0 | char *url, *algorithm; |
432 | 0 | GString *out; |
433 | 0 | GUri *uri; |
434 | |
|
435 | 0 | uri = soup_message_get_uri (msg); |
436 | 0 | g_return_val_if_fail (uri != NULL, NULL); |
437 | 0 | url = soup_uri_get_path_and_query (uri); |
438 | |
|
439 | 0 | g_assert (priv->nonce); |
440 | 0 | g_assert (!priv->qop || priv->cnonce); |
441 | | |
442 | 0 | soup_auth_digest_compute_response (soup_message_get_method (msg), url, priv->hex_a1, |
443 | 0 | priv->qop, priv->nonce, |
444 | 0 | priv->cnonce, priv->nc, |
445 | 0 | response); |
446 | |
|
447 | 0 | out = g_string_new ("Digest "); |
448 | |
|
449 | 0 | soup_header_g_string_append_param_quoted (out, "username", priv->user); |
450 | 0 | g_string_append (out, ", "); |
451 | 0 | soup_header_g_string_append_param_quoted (out, "realm", soup_auth_get_realm (auth)); |
452 | 0 | g_string_append (out, ", "); |
453 | 0 | soup_header_g_string_append_param_quoted (out, "nonce", priv->nonce); |
454 | 0 | g_string_append (out, ", "); |
455 | 0 | soup_header_g_string_append_param_quoted (out, "uri", url); |
456 | 0 | g_string_append (out, ", "); |
457 | 0 | algorithm = soup_auth_digest_get_algorithm (priv->algorithm); |
458 | 0 | g_string_append_printf (out, "algorithm=%s", algorithm); |
459 | 0 | g_free (algorithm); |
460 | 0 | g_string_append (out, ", "); |
461 | 0 | soup_header_g_string_append_param_quoted (out, "response", response); |
462 | |
|
463 | 0 | if (priv->opaque) { |
464 | 0 | g_string_append (out, ", "); |
465 | 0 | soup_header_g_string_append_param_quoted (out, "opaque", priv->opaque); |
466 | 0 | } |
467 | |
|
468 | 0 | if (priv->qop) { |
469 | 0 | char *qop = soup_auth_digest_get_qop (priv->qop); |
470 | |
|
471 | 0 | g_string_append (out, ", "); |
472 | 0 | soup_header_g_string_append_param_quoted (out, "cnonce", priv->cnonce); |
473 | 0 | g_string_append_printf (out, ", nc=%.8x, qop=%s", |
474 | 0 | priv->nc, qop); |
475 | 0 | g_free (qop); |
476 | 0 | } |
477 | |
|
478 | 0 | g_free (url); |
479 | |
|
480 | 0 | priv->nc++; |
481 | |
|
482 | 0 | token = g_string_free (out, FALSE); |
483 | |
|
484 | 0 | soup_message_add_header_handler (msg, |
485 | 0 | "got_headers", |
486 | 0 | soup_auth_is_for_proxy (auth) ? |
487 | 0 | "Proxy-Authentication-Info" : |
488 | 0 | "Authentication-Info", |
489 | 0 | G_CALLBACK (authentication_info_cb), |
490 | 0 | auth); |
491 | 0 | return token; |
492 | 0 | } |
493 | | |
494 | | static void |
495 | | soup_auth_digest_class_init (SoupAuthDigestClass *auth_digest_class) |
496 | 0 | { |
497 | 0 | SoupAuthClass *auth_class = SOUP_AUTH_CLASS (auth_digest_class); |
498 | 0 | GObjectClass *object_class = G_OBJECT_CLASS (auth_digest_class); |
499 | |
|
500 | 0 | auth_class->scheme_name = "Digest"; |
501 | 0 | auth_class->strength = 5; |
502 | |
|
503 | 0 | auth_class->get_protection_space = soup_auth_digest_get_protection_space; |
504 | 0 | auth_class->update = soup_auth_digest_update; |
505 | 0 | auth_class->authenticate = soup_auth_digest_authenticate; |
506 | 0 | auth_class->is_authenticated = soup_auth_digest_is_authenticated; |
507 | 0 | auth_class->get_authorization = soup_auth_digest_get_authorization; |
508 | |
|
509 | 0 | object_class->finalize = soup_auth_digest_finalize; |
510 | 0 | } |