Dillo v3.2.0-151-g90488cbf
Loading...
Searching...
No Matches
auth.c
Go to the documentation of this file.
1/*
2 * File: auth.c
3 *
4 * Copyright 2008 Jeremy Henty <onepoint@starurchin.org>
5 * Copyright 2009 Justus Winter <4winter@informatik.uni-hamburg.de>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
11 */
12
20#include "auth.h"
21#include "msg.h"
22#include "misc.h"
23#include "dialog.hh"
24#include "digest.h"
25#include "dlib/dlib.h" /* dIsascii */
26
27typedef struct {
28 int ok;
30 const char *realm;
31 const char *nonce;
32 const char *opaque;
33 int stale;
34 enum AuthParseDigestAlgorithm_t algorithm;
35 const char *domain;
36 enum AuthParseDigestQOP_t qop;
37} AuthParse_t;
38
39typedef struct {
40 char *scheme;
41 char *authority;
42 Dlist *realms;
43} AuthHost_t;
44
45typedef struct {
46 const AuthParse_t *auth_parse;
47 const DilloUrl *url;
48} AuthDialogData_t;
49
54
58void a_Auth_init(void)
59{
61}
62
63static AuthParse_t *Auth_parse_new(void)
64{
65 AuthParse_t *auth_parse = dNew(AuthParse_t, 1);
66 auth_parse->ok = 0;
67 auth_parse->type = TYPENOTSET;
68 auth_parse->realm = NULL;
69 auth_parse->nonce = NULL;
70 auth_parse->opaque = NULL;
71 auth_parse->stale = 0;
72 auth_parse->algorithm = ALGORITHMNOTSET;
73 auth_parse->domain = NULL;
74 auth_parse->qop = QOPNOTSET;
75 return auth_parse;
76}
77
78static void Auth_parse_free(AuthParse_t *auth_parse)
79{
80 if (auth_parse) {
81 dFree((void *)auth_parse->realm);
82 dFree((void *)auth_parse->nonce);
83 dFree((void *)auth_parse->opaque);
84 dFree((void *)auth_parse->domain);
85 dFree(auth_parse);
86 }
87}
88
89static int Auth_path_is_inside(const char *path1, const char *path2, int len)
90{
91 /*
92 * path2 is effectively truncated to length len. Typically len will be
93 * strlen(path2), or 1 less when we want to ignore a trailing '/'.
94 */
95 return
96 strncmp(path1, path2, len) == 0 &&
97 (path1[len] == '\0' || path1[len] == '/');
98}
99
104static int Auth_is_token_char(char c)
105{
106 const char *invalid = "\"()<>@,;:\\[]?=/{} \t";
107 return (!dIsascii(c) || strchr(invalid, c) || dIscntrl(c)) ? 0 : 1;
108}
109
124static Dstr *Auth_unquote_value(char **valuep)
125{
126 char c, quoted;
127 char *value = *valuep;
128 Dstr *result;
129
130 while (*value == ' ' || *value == '\t')
131 value++;
132
133 if ((quoted = *value == '"'))
134 value++;
135
136 result = dStr_new(NULL);
137 while ((c = *value) &&
138 (( quoted && c != '"') ||
139 (!quoted && Auth_is_token_char(c)))) {
140 dStr_append_c(result, (c == '\\' && value[1]) ? *++value : c);
141 value++;
142 }
143
144 if (quoted && *value == '\"')
145 value++;
146 *valuep = value;
147 return result;
148}
149
150typedef int (Auth_parse_token_value_callback_t)(AuthParse_t *auth_parse,
151 char *token,
152 const char *value);
153
154
163static int Auth_parse_token_value(AuthParse_t *auth_parse, char **auth,
165{
166 char keep_going, expect_quoted;
167 char *token, *beyond_token;
168 Dstr *value;
169 size_t *token_size;
170
171 while (**auth) {
172 _MSG("Auth_parse_token_value: remaining: %s\n", *auth);
173
174 /* parse a token */
175 token = *auth;
176
177 token_size = 0;
178 while (Auth_is_token_char(**auth)) {
179 (*auth)++;
180 token_size++;
181 }
182 if (token_size == 0) {
183 MSG("Auth_parse_token_value: missing auth token\n");
184 return 0;
185 }
186 beyond_token = *auth;
187 /* skip linear whitespace characters */
188 while (**auth == ' ' || **auth == '\t')
189 (*auth)++;
190
191 /* parse the '=' */
192 switch (*(*auth)++) {
193 case '=':
194 *beyond_token = '\0';
195 break;
196 case '\0':
197 case ',':
198 MSG("Auth_parse_token_value: missing auth token value\n");
199 return 0;
200 break;
201 default:
202 MSG("Auth_parse_token_value: garbage after auth token\n");
203 return 0;
204 break;
205 }
206
207 value = Auth_unquote_value(auth);
208 expect_quoted = !(strcmp(token, "stale") == 0 ||
209 strcmp(token, "algorithm") == 0);
210
211 if (((*auth)[-1] == '"') != expect_quoted)
212 MSG_WARN("Auth_parse_token_value: "
213 "Values for key %s should%s be quoted.\n",
214 token, expect_quoted ? "" : " not");
215
216 keep_going = callback(auth_parse, token, value->str);
217 dStr_free(value, 1);
218 if (!keep_going)
219 break;
220
221 /* skip ' ' and ',' */
222 while ((**auth == ' ') || (**auth == ','))
223 (*auth)++;
224 }
225 return 1;
226}
227
228static int Auth_parse_basic_challenge_cb(AuthParse_t *auth_parse, char *token,
229 const char *value)
230{
231 if (dStrAsciiCasecmp("realm", token) == 0) {
232 if (!auth_parse->realm)
233 auth_parse->realm = dStrdup(value);
234 return 0; /* end parsing */
235 } else
236 MSG("Auth_parse_basic_challenge_cb: Ignoring unknown parameter: %s = "
237 "'%s'\n", token, value);
238 return 1;
239}
240
241static int Auth_parse_digest_challenge_cb(AuthParse_t *auth_parse, char *token,
242 const char *value)
243{
244 const char *const fn = "Auth_parse_digest_challenge_cb";
245
246 if (!dStrAsciiCasecmp("realm", token) && !auth_parse->realm)
247 auth_parse->realm = dStrdup(value);
248 else if (!strcmp("domain", token) && !auth_parse->domain)
249 auth_parse->domain = dStrdup(value);
250 else if (!strcmp("nonce", token) && !auth_parse->nonce)
251 auth_parse->nonce = dStrdup(value);
252 else if (!strcmp("opaque", token) && !auth_parse->opaque)
253 auth_parse->opaque = dStrdup(value);
254 else if (strcmp("stale", token) == 0) {
255 if (dStrAsciiCasecmp("true", value) == 0)
256 auth_parse->stale = 1;
257 else if (dStrAsciiCasecmp("false", value) == 0)
258 auth_parse->stale = 0;
259 else {
260 MSG("%s: Invalid stale value: %s\n", fn, value);
261 return 0;
262 }
263 } else if (strcmp("algorithm", token) == 0) {
264 if (strcmp("MD5", value) == 0)
265 auth_parse->algorithm = MD5;
266 else if (strcmp("MD5-sess", value) == 0) {
267 /* auth_parse->algorithm = MD5SESS; */
268 MSG("%s: MD5-sess algorithm disabled (not tested because 'not "
269 "correctly implemented yet' in Apache 2.2)\n", fn);
270 return 0;
271 } else {
272 MSG("%s: Unknown algorithm: %s\n", fn, value);
273 return 0;
274 }
275 } else if (strcmp("qop", token) == 0) {
276 while (*value) {
277 int len = strcspn(value, ", \t");
278 if (len == 4 && strncmp("auth", value, 4) == 0) {
279 auth_parse->qop = AUTH;
280 break;
281 }
282 if (len == 8 && strncmp("auth-int", value, 8) == 0) {
283 /* auth_parse->qop = AUTHINT; */
284 /* Keep searching; maybe we'll find an "auth" yet. */
285 MSG("%s: auth-int qop disabled (not tested because 'not "
286 "implemented yet' in Apache 2.2)\n", fn);
287 } else {
288 MSG("%s: Unknown qop value in %s\n", fn, value);
289 }
290 value += len;
291 while (*value == ' ' || *value == '\t')
292 value++;
293 if (*value == ',')
294 value++;
295 while (*value == ' ' || *value == '\t')
296 value++;
297 }
298 } else {
299 MSG("%s: Ignoring unknown parameter: %s = '%s'\n", fn, token, value);
300 }
301 return 1;
302}
303
304static void Auth_parse_challenge_args(AuthParse_t *auth_parse,
305 char **challenge,
307{
308 /* parse comma-separated token-value pairs */
309 while (1) {
310 /* skip space and comma characters */
311 while (**challenge == ' ' || **challenge == ',')
312 (*challenge)++;
313 /* end of string? */
314 if (!**challenge)
315 break;
316 /* parse token-value pair */
317 if (!Auth_parse_token_value(auth_parse, challenge, cb))
318 break;
319 }
320
321 if (auth_parse->type == BASIC) {
322 if (auth_parse->realm) {
323 auth_parse->ok = 1;
324 } else {
325 MSG("Auth_parse_challenge_args: missing Basic auth realm\n");
326 return;
327 }
328 } else if (auth_parse->type == DIGEST) {
329 if (auth_parse->realm && auth_parse->nonce) {
330 auth_parse->ok = 1;
331 } else {
332 MSG("Auth_parse_challenge_args: Digest challenge incomplete\n");
333 return;
334 }
335 }
336}
337
338static void Auth_parse_challenge(AuthParse_t *auth_parse, char *challenge)
339{
341
342 MSG("auth.c: Auth_parse_challenge: challenge = '%s'\n", challenge);
343 if (auth_parse->type == DIGEST) {
344 challenge += 7;
346 } else {
347 challenge += 6;
349 }
350 Auth_parse_challenge_args(auth_parse, &challenge, cb);
351}
352
356static AuthHost_t *Auth_host_by_url(const DilloUrl *url)
357{
358 AuthHost_t *host;
359 int i;
360
361 for (i = 0; (host = dList_nth_data(auth_hosts, i)); i++)
362 if (((dStrAsciiCasecmp(URL_SCHEME(url), host->scheme) == 0) &&
363 (dStrAsciiCasecmp(URL_AUTHORITY(url), host->authority) == 0)))
364 return host;
365
366 return NULL;
367}
368
372static AuthRealm_t *Auth_realm_by_name(const AuthHost_t *host,
373 const char *name)
374{
375 AuthRealm_t *realm;
376 int i;
377
378 for (i = 0; (realm = dList_nth_data(host->realms, i)); i++)
379 if (strcmp(realm->name, name) == 0)
380 return realm;
381
382 return NULL;
383}
384
388static AuthRealm_t *Auth_realm_by_path(const AuthHost_t *host,
389 const char *path)
390{
391 AuthRealm_t *realm_best, *realm;
392 int i, j;
393 int match_length = 0;
394
395 realm_best = NULL;
396 for (i = 0; (realm = dList_nth_data(host->realms, i)); i++) {
397 char *realm_path;
398
399 for (j = 0; (realm_path = dList_nth_data(realm->paths, j)); j++) {
400 int realm_path_length = strlen(realm_path);
401 if (Auth_path_is_inside(path, realm_path, realm_path_length) &&
402 !(realm_best && match_length >= realm_path_length)) {
403 realm_best = realm;
404 match_length = realm_path_length;
405 }
406 }
407 }
408
409 return realm_best;
410}
411
413{
414 int i;
415
416 MSG("Auth_realm_delete: \"%s\"\n", realm->name);
417 for (i = dList_length(realm->paths) - 1; i >= 0; i--)
418 dFree(dList_nth_data(realm->paths, i));
419 dList_free(realm->paths);
420 dFree(realm->name);
421 dFree(realm->username);
422 dFree(realm->authorization);
423 dFree(realm->cnonce);
424 dFree(realm->nonce);
425 dFree(realm->opaque);
426 dFree(realm->domain);
427 dFree(realm);
428}
429
430static int Auth_realm_includes_path(const AuthRealm_t *realm, const char *path)
431{
432 int i;
433 char *realm_path;
434
435 for (i = 0; (realm_path = dList_nth_data(realm->paths, i)); i++)
436 if (Auth_path_is_inside(path, realm_path, strlen(realm_path)))
437 return 1;
438
439 return 0;
440}
441
442static void Auth_realm_add_path(AuthRealm_t *realm, const char *path)
443{
444 int len, i;
445 char *realm_path, *n_path;
446
447 n_path = dStrdup(path);
448 len = strlen(n_path);
449
450 /* remove trailing '/' */
451 if (len && n_path[len - 1] == '/')
452 n_path[--len] = 0;
453
454 /* delete existing paths that are inside the new one */
455 for (i = 0; (realm_path = dList_nth_data(realm->paths, i)); i++) {
456 if (Auth_path_is_inside(realm_path, path, len)) {
457 dList_remove_fast(realm->paths, realm_path);
458 dFree(realm_path);
459 i--; /* reconsider this slot */
460 }
461 }
462
463 dList_append(realm->paths, n_path);
464}
465
471char *a_Auth_get_auth_str(const DilloUrl *url, const char *request_uri)
472{
473 char *ret = NULL;
474 AuthHost_t *host;
475 AuthRealm_t *realm;
476
477 if ((host = Auth_host_by_url(url)) &&
478 (realm = Auth_realm_by_path(host, URL_PATH(url)))) {
479 if (realm->type == BASIC)
480 ret = dStrdup(realm->authorization);
481 else if (realm->type == DIGEST)
482 ret = a_Digest_authorization_hdr(realm, url, request_uri);
483 else
484 MSG("a_Auth_get_auth_str() got an unknown realm type: %i.\n",
485 realm->type);
486 }
487 return ret;
488}
489
493static int Auth_do_auth_required(const AuthParse_t *auth_parse,
494 const DilloUrl *url)
495{
496 /*
497 * TO DO: I dislike the way that this code must decide whether we
498 * sent authentication during the request and trust us to resend it
499 * after the reload. Could it be more robust if every DilloUrl
500 * recorded its authentication, and whether it was accepted? (JCH)
501 */
502
503 AuthHost_t *host;
504 AuthRealm_t *realm;
505
506 /*
507 * The size of the following comments reflects the concerns in the
508 * TO DO at the top of this function. It should not be so hard to
509 * explain why code is correct! (JCH)
510 */
511
512 /*
513 * If we have authentication but did not send it (because we did
514 * not know this path was in the realm) then we update the realm.
515 * We do not re-authenticate because our authentication is probably
516 * OK. Thanks to the updated realm the forthcoming reload will
517 * make us send the authentication. If our authentication is not
518 * OK the server will challenge us again after the reload and then
519 * we will re-authenticate.
520 */
521 if ((host = Auth_host_by_url(url)) &&
522 (realm = Auth_realm_by_name(host, auth_parse->realm))) {
523 if (!Auth_realm_includes_path(realm, URL_PATH(url))) {
524 _MSG("Auth_do_auth_required: updating realm '%s' with URL '%s'\n",
525 auth_parse->realm, URL_STR(url));
526 Auth_realm_add_path(realm, URL_PATH(url));
527 return 0;
528 }
529
530 if (auth_parse->type == DIGEST && auth_parse->stale) {
531 /* we do have valid credentials but our nonce is old */
532 dFree((void *)realm->nonce);
533 realm->nonce = dStrdup(auth_parse->nonce);
534 return 0;
535 }
536 }
537
538 /*
539 * Either we had no authentication or we sent it and the server
540 * rejected it, so we must re-authenticate.
541 */
542 return 1;
543}
544
545static void Auth_do_auth_dialog_cb(const char *user, const char *password,
546 void *vData)
547{
548 AuthDialogData_t *data;
549 AuthHost_t *host;
550 AuthRealm_t *realm;
551
552 data = (AuthDialogData_t *)vData;
553
554 /* find or create the host */
555 if (!(host = Auth_host_by_url(data->url))) {
556 /* create a new host */
557 host = dNew(AuthHost_t, 1);
558 host->scheme = dStrdup(URL_SCHEME(data->url));
559 host->authority = dStrdup(URL_AUTHORITY(data->url));
560 host->realms = dList_new(1);
562 }
563
564 /* find or create the realm */
565 if (!(realm = Auth_realm_by_name(host, data->auth_parse->realm))) {
566 realm = dNew0(AuthRealm_t, 1);
567 realm->name = dStrdup(data->auth_parse->realm);
568 realm->paths = dList_new(1);
569 dList_append(host->realms, realm);
570 }
571 realm->type = data->auth_parse->type;
572 dFree(realm->authorization);
573 realm->authorization = NULL;
574
575 Auth_realm_add_path(realm, URL_PATH(data->url));
576
577 if (realm->type == BASIC) {
578 char *user_password = dStrconcat(user, ":", password, NULL);
579 char *response = a_Misc_encode_base64(user_password);
580 char *authorization =
581 dStrconcat("Authorization: Basic ", response, "\r\n", NULL);
582 dFree(realm->authorization);
583 realm->authorization = authorization;
584 dFree(response);
585 dStrshred(user_password);
586 dFree(user_password);
587 } else if (realm->type == DIGEST) {
588 dFree(realm->username);
589 realm->username = dStrdup(user);
590 realm->nonce_count = 0;
591 dFree(realm->nonce);
592 realm->nonce = dStrdup(data->auth_parse->nonce);
593 dFree(realm->opaque);
594 realm->opaque = dStrdup(data->auth_parse->opaque);
595 realm->algorithm = data->auth_parse->algorithm;
596 dFree(realm->domain);
597 realm->domain = dStrdup(data->auth_parse->domain);
598 realm->qop = data->auth_parse->qop;
599 dFree(realm->cnonce);
600 if (realm->qop != QOPNOTSET)
602 if (!a_Digest_compute_digest(realm, user, password)) {
603 MSG("Auth_do_auth_dialog_cb: a_Digest_compute_digest failed.\n");
604 dList_remove_fast(host->realms, realm);
605 Auth_realm_delete(realm);
606 }
607 } else {
608 MSG("Auth_do_auth_dialog_cb: Unknown auth type: %i\n",
609 realm->type);
610 }
611 dStrshred((char *)password);
612}
613
614/*
615 * Return: Nonzero if we got new credentials from the user and everything
616 * seems fine.
617 */
618static int Auth_do_auth_dialog(const AuthParse_t *auth_parse,
619 const DilloUrl *url)
620{
621 int ret;
622 char *title, *msg;
623 AuthDialogData_t *data;
624 const char *typestr = auth_parse->type == DIGEST ? "Digest" : "Basic";
625
626 _MSG("auth.c: Auth_do_auth_dialog: realm = '%s'\n", auth_parse->realm);
627
628 title = dStrconcat("Dillo: Password for ", auth_parse->realm, NULL);
629 msg = dStrconcat("The server at ", URL_HOST(url), " requires a username"
630 " and password for \"", auth_parse->realm, "\".\n\n"
631 "Authentication scheme: ", typestr, NULL);
632 data = dNew(AuthDialogData_t, 1);
633 data->auth_parse = auth_parse;
634 data->url = a_Url_dup(url);
635 ret = a_Dialog_user_password(title, msg, Auth_do_auth_dialog_cb, data);
636 dFree(title); dFree(msg);
637 a_Url_free((void *)data->url);
638 dFree(data);
639 return ret;
640}
641
645static int Auth_do_auth(char *challenge, enum AuthParseHTTPAuthType_t type,
646 const DilloUrl *url)
647{
648 AuthParse_t *auth_parse;
649 int reload = 0;
650
651 _MSG("auth.c: Auth_do_auth: challenge={%s}\n", challenge);
652 auth_parse = Auth_parse_new();
653 auth_parse->type = type;
654 Auth_parse_challenge(auth_parse, challenge);
655 if (auth_parse->ok)
656 reload =
657 Auth_do_auth_required(auth_parse, url) ?
658 Auth_do_auth_dialog(auth_parse, url)
659 : 1;
660 Auth_parse_free(auth_parse);
661
662 return reload;
663}
664
670int a_Auth_do_auth(Dlist *challenges, const DilloUrl *url)
671{
672 int i;
673 char *chal;
674
675 for (i = 0; (chal = dList_nth_data(challenges, i)); ++i)
676 if (!dStrnAsciiCasecmp(chal, "Digest ", 7))
677 if (Auth_do_auth(chal, DIGEST, url))
678 return 1;
679 for (i = 0; (chal = dList_nth_data(challenges, i)); ++i)
680 if (!dStrnAsciiCasecmp(chal, "Basic ", 6))
681 if (Auth_do_auth(chal, BASIC, url))
682 return 1;
683
684 return 0;
685}
686
static AuthParse_t * Auth_parse_new(void)
Definition auth.c:63
static AuthRealm_t * Auth_realm_by_name(const AuthHost_t *host, const char *name)
Search all realms for the one with the given name.
Definition auth.c:372
static AuthHost_t * Auth_host_by_url(const DilloUrl *url)
Return the host that contains a URL, or NULL if there is no such host.
Definition auth.c:356
int a_Auth_do_auth(Dlist *challenges, const DilloUrl *url)
Given authentication challenge(s), prepare authorization.
Definition auth.c:670
static int Auth_do_auth_required(const AuthParse_t *auth_parse, const DilloUrl *url)
Determine whether the user needs to authenticate.
Definition auth.c:493
static int Auth_is_token_char(char c)
Check valid chars.
Definition auth.c:104
void a_Auth_init(void)
Initialize the auth module.
Definition auth.c:58
int() Auth_parse_token_value_callback_t(AuthParse_t *auth_parse, char *token, const char *value)
Definition auth.c:150
static void Auth_parse_challenge_args(AuthParse_t *auth_parse, char **challenge, Auth_parse_token_value_callback_t *cb)
Definition auth.c:304
static void Auth_do_auth_dialog_cb(const char *user, const char *password, void *vData)
Definition auth.c:545
static int Auth_do_auth_dialog(const AuthParse_t *auth_parse, const DilloUrl *url)
Definition auth.c:618
static int Auth_parse_basic_challenge_cb(AuthParse_t *auth_parse, char *token, const char *value)
Definition auth.c:228
char * a_Auth_get_auth_str(const DilloUrl *url, const char *request_uri)
Return the authorization header for an HTTP query.
Definition auth.c:471
static void Auth_realm_add_path(AuthRealm_t *realm, const char *path)
Definition auth.c:442
static int Auth_parse_digest_challenge_cb(AuthParse_t *auth_parse, char *token, const char *value)
Definition auth.c:241
static int Auth_parse_token_value(AuthParse_t *auth_parse, char **auth, Auth_parse_token_value_callback_t *callback)
Parse authentication challenge into token-value pairs and feed them into the callback function.
Definition auth.c:163
static int Auth_realm_includes_path(const AuthRealm_t *realm, const char *path)
Definition auth.c:430
static int Auth_do_auth(char *challenge, enum AuthParseHTTPAuthType_t type, const DilloUrl *url)
Do authorization for an auth string.
Definition auth.c:645
static void Auth_parse_challenge(AuthParse_t *auth_parse, char *challenge)
Definition auth.c:338
static Dstr * Auth_unquote_value(char **valuep)
Unquote the content of a (potentially) quoted string.
Definition auth.c:124
static int Auth_path_is_inside(const char *path1, const char *path2, int len)
Definition auth.c:89
static AuthRealm_t * Auth_realm_by_path(const AuthHost_t *host, const char *path)
Search all realms for the one with the best-matching path.
Definition auth.c:388
static void Auth_realm_delete(AuthRealm_t *realm)
Definition auth.c:412
static Dlist * auth_hosts
Local data.
Definition auth.c:53
static void Auth_parse_free(AuthParse_t *auth_parse)
Definition auth.c:78
AuthParseDigestQOP_t
Definition auth.h:12
@ AUTH
Definition auth.h:12
@ QOPNOTSET
Definition auth.h:12
AuthParseHTTPAuthType_t
Definition auth.h:10
@ TYPENOTSET
Definition auth.h:10
@ BASIC
Definition auth.h:10
@ DIGEST
Definition auth.h:10
AuthParseDigestAlgorithm_t
Definition auth.h:11
@ MD5
Definition auth.h:11
@ ALGORITHMNOTSET
Definition auth.h:11
#define _MSG(...)
Definition bookmarks.c:44
#define MSG(...)
Definition bookmarks.c:45
int a_Dialog_user_password(const char *title, const char *msg, UserPasswordCB cb, void *vp)
Make a user/password dialog.
Definition dialog.cc:419
int a_Digest_compute_digest(AuthRealm_t *realm, const char *username, const char *passwd)
This portion only has to be calculated once.
Definition digest.c:54
char * a_Digest_create_cnonce(void)
Returns a pointer to a newly allocated string containing a cnonce.
Definition digest.c:41
char * a_Digest_authorization_hdr(AuthRealm_t *realm, const DilloUrl *url, const char *digest_uri)
Construct Digest Authorization header.
Definition digest.c:169
char * dStrconcat(const char *s1,...)
Concatenate a NULL-terminated list of strings.
Definition dlib.c:101
void dFree(void *mem)
Definition dlib.c:67
int dStrAsciiCasecmp(const char *s1, const char *s2)
Definition dlib.c:202
char * dStrdup(const char *s)
Definition dlib.c:76
Dlist * dList_new(int size)
Create a new empty list.
Definition dlib.c:575
int dStrnAsciiCasecmp(const char *s1, const char *s2, size_t n)
Definition dlib.c:214
int dList_length(Dlist *lp)
For completing the ADT.
Definition dlib.c:640
void * dList_nth_data(Dlist *lp, int n0)
Return the nth data item, NULL when not found or 'n0' is out of range.
Definition dlib.c:689
void dList_remove_fast(Dlist *lp, const void *data)
Remove a data item without preserving order.
Definition dlib.c:650
void dStr_free(Dstr *ds, int all)
Free a dillo string.
Definition dlib.c:336
void dStrshred(char *s)
Clear the contents of the string.
Definition dlib.c:139
void dStr_append_c(Dstr *ds, int c)
Append one character.
Definition dlib.c:348
Dstr * dStr_new(const char *s)
Create a new string.
Definition dlib.c:324
void dList_append(Dlist *lp, void *data)
Append a data item to the list.
Definition dlib.c:624
void dList_free(Dlist *lp)
Free a list (not its elements)
Definition dlib.c:591
#define dNew0(type, count)
Definition dlib.h:80
static int dIsascii(unsigned char c)
Definition dlib.h:57
static int dIscntrl(unsigned char c)
Definition dlib.h:49
#define dNew(type, count)
Definition dlib.h:78
#define MSG_WARN(...)
Definition msg.h:26
char * a_Misc_encode_base64(const char *in)
Encodes string using base64 encoding.
Definition misc.c:426
unsigned int nonce_count
Definition auth.h:23
enum AuthParseHTTPAuthType_t type
Definition auth.h:15
char * domain
Definition auth.h:27
char * username
Definition auth.h:21
char * cnonce
Definition auth.h:22
enum AuthParseDigestQOP_t qop
Definition auth.h:28
char * opaque
Definition auth.h:25
Dlist * paths
Definition auth.h:17
char * nonce
Definition auth.h:24
char * name
Definition auth.h:16
char * authorization
Definition auth.h:18
enum AuthParseDigestAlgorithm_t algorithm
Definition auth.h:26
Definition url.h:88
Definition dlib.h:161
Definition dlib.h:131
Dstr_char_t * str
Definition dlib.h:134
static void path()
Definition cookies.c:858
void a_Url_free(DilloUrl *url)
Free a DilloUrl.
Definition url.c:207
DilloUrl * a_Url_dup(const DilloUrl *ori)
Duplicate a Url structure.
Definition url.c:476
#define URL_PATH(u)
Definition url.h:72
#define URL_STR(u)
Definition url.h:76
#define URL_SCHEME(u)
Definition url.h:70
#define URL_AUTHORITY(u)
Definition url.h:71
#define URL_HOST(u)
Definition url.h:75