26#include "../dlib/dlib.h"
47 const AuthParse_t *auth_parse;
66 AuthParse_t *auth_parse =
dNew(AuthParse_t, 1);
69 auth_parse->realm = NULL;
70 auth_parse->nonce = NULL;
71 auth_parse->opaque = NULL;
72 auth_parse->stale = 0;
74 auth_parse->domain = NULL;
82 dFree((
void *)auth_parse->realm);
83 dFree((
void *)auth_parse->nonce);
84 dFree((
void *)auth_parse->opaque);
85 dFree((
void *)auth_parse->domain);
97 strncmp(path1, path2, len) == 0 &&
98 (path1[len] ==
'\0' || path1[len] ==
'/');
107 const char *invalid =
"\"()<>@,;:\\[]?=/{} \t";
108 return (!
d_isascii(c) || strchr(invalid, c) || iscntrl((
uchar_t)c)) ? 0 : 1;
128 char *value = *valuep;
131 while (*value ==
' ' || *value ==
'\t')
134 if ((quoted = *value ==
'"'))
138 while ((c = *value) &&
139 (( quoted && c !=
'"') ||
141 dStr_append_c(result, (c ==
'\\' && value[1]) ? *++value : c);
145 if (quoted && *value ==
'\"')
167 char keep_going, expect_quoted;
168 char *token, *beyond_token;
173 _MSG(
"Auth_parse_token_value: remaining: %s\n", *auth);
183 if (token_size == 0) {
184 MSG(
"Auth_parse_token_value: missing auth token\n");
187 beyond_token = *auth;
189 while (**auth ==
' ' || **auth ==
'\t')
193 switch (*(*auth)++) {
195 *beyond_token =
'\0';
199 MSG(
"Auth_parse_token_value: missing auth token value\n");
203 MSG(
"Auth_parse_token_value: garbage after auth token\n");
209 expect_quoted = !(strcmp(token,
"stale") == 0 ||
210 strcmp(token,
"algorithm") == 0);
212 if (((*auth)[-1] ==
'"') != expect_quoted)
214 "Values for key %s should%s be quoted.\n",
215 token, expect_quoted ?
"" :
" not");
217 keep_going = callback(auth_parse, token, value->
str);
223 while ((**auth ==
' ') || (**auth ==
','))
233 if (!auth_parse->realm)
234 auth_parse->realm =
dStrdup(value);
237 MSG(
"Auth_parse_basic_challenge_cb: Ignoring unknown parameter: %s = "
238 "'%s'\n", token, value);
245 const char *
const fn =
"Auth_parse_digest_challenge_cb";
248 auth_parse->realm =
dStrdup(value);
249 else if (!strcmp(
"domain", token) && !auth_parse->domain)
250 auth_parse->domain =
dStrdup(value);
251 else if (!strcmp(
"nonce", token) && !auth_parse->nonce)
252 auth_parse->nonce =
dStrdup(value);
253 else if (!strcmp(
"opaque", token) && !auth_parse->opaque)
254 auth_parse->opaque =
dStrdup(value);
255 else if (strcmp(
"stale", token) == 0) {
257 auth_parse->stale = 1;
259 auth_parse->stale = 0;
261 MSG(
"%s: Invalid stale value: %s\n", fn, value);
264 }
else if (strcmp(
"algorithm", token) == 0) {
265 if (strcmp(
"MD5", value) == 0)
266 auth_parse->algorithm =
MD5;
267 else if (strcmp(
"MD5-sess", value) == 0) {
269 MSG(
"%s: MD5-sess algorithm disabled (not tested because 'not "
270 "correctly implemented yet' in Apache 2.2)\n", fn);
273 MSG(
"%s: Unknown algorithm: %s\n", fn, value);
276 }
else if (strcmp(
"qop", token) == 0) {
278 int len = strcspn(value,
", \t");
279 if (len == 4 && strncmp(
"auth", value, 4) == 0) {
280 auth_parse->qop =
AUTH;
283 if (len == 8 && strncmp(
"auth-int", value, 8) == 0) {
286 MSG(
"%s: auth-int qop disabled (not tested because 'not "
287 "implemented yet' in Apache 2.2)\n", fn);
289 MSG(
"%s: Unknown qop value in %s\n", fn, value);
292 while (*value ==
' ' || *value ==
'\t')
296 while (*value ==
' ' || *value ==
'\t')
300 MSG(
"%s: Ignoring unknown parameter: %s = '%s'\n", fn, token, value);
312 while (**challenge ==
' ' || **challenge ==
',')
322 if (auth_parse->type ==
BASIC) {
323 if (auth_parse->realm) {
326 MSG(
"Auth_parse_challenge_args: missing Basic auth realm\n");
329 }
else if (auth_parse->type ==
DIGEST) {
330 if (auth_parse->realm && auth_parse->nonce) {
333 MSG(
"Auth_parse_challenge_args: Digest challenge incomplete\n");
343 MSG(
"auth.c: Auth_parse_challenge: challenge = '%s'\n", challenge);
344 if (auth_parse->type ==
DIGEST) {
380 if (strcmp(realm->
name, name) == 0)
394 int match_length = 0;
401 int realm_path_length = strlen(realm_path);
403 !(realm_best && match_length >= realm_path_length)) {
405 match_length = realm_path_length;
417 MSG(
"Auth_realm_delete: \"%s\"\n", realm->
name);
446 char *realm_path, *n_path;
449 len = strlen(n_path);
452 if (len && n_path[len - 1] ==
'/')
485 MSG(
"a_Auth_get_auth_str() got an unknown realm type: %i.\n",
525 _MSG(
"Auth_do_auth_required: updating realm '%s' with URL '%s'\n",
526 auth_parse->realm,
URL_STR(url));
531 if (auth_parse->type ==
DIGEST && auth_parse->stale) {
549 AuthDialogData_t *data;
553 data = (AuthDialogData_t *)vData;
558 host =
dNew(AuthHost_t, 1);
572 realm->
type = data->auth_parse->type;
579 char *user_password =
dStrconcat(user,
":", password, NULL);
581 char *authorization =
582 dStrconcat(
"Authorization: Basic ", response,
"\r\n", NULL);
587 dFree(user_password);
596 realm->
algorithm = data->auth_parse->algorithm;
599 realm->
qop = data->auth_parse->qop;
604 MSG(
"Auth_do_auth_dialog_cb: a_Digest_compute_digest failed.\n");
609 MSG(
"Auth_do_auth_dialog_cb: Unknown auth type: %i\n",
624 AuthDialogData_t *data;
625 const char *typestr = auth_parse->type ==
DIGEST ?
"Digest" :
"Basic";
627 _MSG(
"auth.c: Auth_do_auth_dialog: realm = '%s'\n", auth_parse->realm);
629 title =
dStrconcat(
"Dillo: Password for ", auth_parse->realm, NULL);
631 " and password for \"", auth_parse->realm,
"\".\n\n"
632 "Authentication scheme: ", typestr, NULL);
633 data =
dNew(AuthDialogData_t, 1);
634 data->auth_parse = auth_parse;
649 AuthParse_t *auth_parse;
652 _MSG(
"auth.c: Auth_do_auth: challenge={%s}\n", challenge);
654 auth_parse->type = type;
static AuthParse_t * Auth_parse_new(void)
static AuthRealm_t * Auth_realm_by_name(const AuthHost_t *host, const char *name)
Search all realms for the one with the given name.
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.
int a_Auth_do_auth(Dlist *challenges, const DilloUrl *url)
Given authentication challenge(s), prepare authorization.
static int Auth_do_auth_required(const AuthParse_t *auth_parse, const DilloUrl *url)
Determine whether the user needs to authenticate.
static int Auth_is_token_char(char c)
Check valid chars.
void a_Auth_init(void)
Initialize the auth module.
int() Auth_parse_token_value_callback_t(AuthParse_t *auth_parse, char *token, const char *value)
static void Auth_parse_challenge_args(AuthParse_t *auth_parse, char **challenge, Auth_parse_token_value_callback_t *cb)
static void Auth_do_auth_dialog_cb(const char *user, const char *password, void *vData)
static int Auth_do_auth_dialog(const AuthParse_t *auth_parse, const DilloUrl *url)
static int Auth_parse_basic_challenge_cb(AuthParse_t *auth_parse, char *token, const char *value)
char * a_Auth_get_auth_str(const DilloUrl *url, const char *request_uri)
Return the authorization header for an HTTP query.
static void Auth_realm_add_path(AuthRealm_t *realm, const char *path)
static int Auth_parse_digest_challenge_cb(AuthParse_t *auth_parse, char *token, const char *value)
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.
static int Auth_realm_includes_path(const AuthRealm_t *realm, const char *path)
static int Auth_do_auth(char *challenge, enum AuthParseHTTPAuthType_t type, const DilloUrl *url)
Do authorization for an auth string.
static void Auth_parse_challenge(AuthParse_t *auth_parse, char *challenge)
static Dstr * Auth_unquote_value(char **valuep)
Unquote the content of a (potentially) quoted string.
static int Auth_path_is_inside(const char *path1, const char *path2, int len)
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.
static void Auth_realm_delete(AuthRealm_t *realm)
static Dlist * auth_hosts
Local data.
static void Auth_parse_free(AuthParse_t *auth_parse)
AuthParseDigestAlgorithm_t
int a_Dialog_user_password(const char *title, const char *msg, UserPasswordCB cb, void *vp)
Make a user/password dialog.
int a_Digest_compute_digest(AuthRealm_t *realm, const char *username, const char *passwd)
This portion only has to be calculated once.
char * a_Digest_create_cnonce(void)
Returns a pointer to a newly allocated string containing a cnonce.
char * a_Digest_authorization_hdr(AuthRealm_t *realm, const DilloUrl *url, const char *digest_uri)
Construct Digest Authorization header.
char * dStrconcat(const char *s1,...)
Concatenate a NULL-terminated list of strings.
int dStrAsciiCasecmp(const char *s1, const char *s2)
char * dStrdup(const char *s)
Dlist * dList_new(int size)
Create a new empty list.
int dStrnAsciiCasecmp(const char *s1, const char *s2, size_t n)
int dList_length(Dlist *lp)
For completing the ADT.
void * dList_nth_data(Dlist *lp, int n0)
Return the nth data item, NULL when not found or 'n0' is out of range.
void dList_remove_fast(Dlist *lp, const void *data)
Remove a data item without preserving order.
void dStr_free(Dstr *ds, int all)
Free a dillo string.
void dStrshred(char *s)
Clear the contents of the string.
void dStr_append_c(Dstr *ds, int c)
Append one character.
Dstr * dStr_new(const char *s)
Create a new string.
void dList_append(Dlist *lp, void *data)
Append a data item to the list.
void dList_free(Dlist *lp)
Free a list (not its elements)
#define dNew0(type, count)
#define dNew(type, count)
char * a_Misc_encode_base64(const char *in)
Encodes string using base64 encoding.
enum AuthParseHTTPAuthType_t type
enum AuthParseDigestQOP_t qop
enum AuthParseDigestAlgorithm_t algorithm
void a_Url_free(DilloUrl *url)
Free a DilloUrl.
DilloUrl * a_Url_dup(const DilloUrl *ori)
Duplicate a Url structure.