[w3m-dev 04130] Multiple challeges in *-Authenticate header

Kiyokazu SUTO <[email protected]> 18 Dec 2004 19:27:45 +0900
Newsgroups gmane.comp.web.w3m.devel
Message-ID <[email protected]>
*-Authenticate
2

(,)



-- 
  <[email protected]>
http://pub.ks-and-ks.ne.jp/pgp-public-key.html

-----  -----  -----  -----  -----
Index: file.c
===================================================================
RCS file: /cvsroot/w3m/w3m/file.c,v
retrieving revision 1.236
diff -u -r1.236 file.c
--- file.c	4 Nov 2004 17:25:45 -0000	1.236
+++ file.c	18 Dec 2004 09:57:32 -0000
@@ -972,7 +972,59 @@
 		 HRequest *hr, FormList *request);
 };
 
-#define TOKEN_PAT	"[^][()<>@,;:\\\"/?={} \t\001-\037\177]*"
+enum {
+    AUTHCHR_NUL,
+    AUTHCHR_SEP,
+    AUTHCHR_TOKEN,
+};
+
+static int
+skip_auth_token(char **pp)
+{
+    char *p;
+    int first = AUTHCHR_NUL, typ;
+
+    for (p = *pp ;; ++p) {
+	switch (*p) {
+	case '\0':
+	    goto endoftoken;
+	default:
+	    if ((unsigned char)*p > 037) {
+		typ = AUTHCHR_TOKEN;
+		break;
+	    }
+	    /* thru */
+	case '\177':
+	case '[':
+	case ']':
+	case '(':
+	case ')':
+	case '<':
+	case '>':
+	case '@':
+	case ';':
+	case ':':
+	case '\\':
+	case '"':
+	case '/':
+	case '?':
+	case '=':
+	case ' ':
+	case '\t':
+	case ',':
+	    typ = AUTHCHR_SEP;
+	    break;
+	}
+
+	if (!first)
+	    first = typ;
+	else if (first != typ)
+	    break;
+    }
+endoftoken:
+    *pp = p;
+    return first;
+}
 
 static Str
 extract_auth_val(char **q)
@@ -993,12 +1045,13 @@
 	}
 	if (!quoted) {
 	    switch (*qq) {
+	    case '[':
+	    case ']':
 	    case '(':
 	    case ')':
 	    case '<':
 	    case '>':
 	    case '@':
-	    case ',':
 	    case ';':
 	    case ':':
 	    case '\\':
@@ -1009,6 +1062,7 @@
 	    case ' ':
 	    case '\t':
 		qq++;
+	    case ',':
 		goto end_token;
 	    default:
 		if (*qq <= 037 || *qq == 0177) {
@@ -1022,11 +1076,6 @@
 	Strcat_char(val, *qq++);
     }
   end_token:
-    if (*qq != '\0') {
-	SKIP_BLANKS(qq);
-	if (*qq == ',')
-	    qq++;
-    }
     *q = (char *)qq;
     return val;
 }
@@ -1058,10 +1107,7 @@
 extract_auth_param(char *q, struct auth_param *auth)
 {
     struct auth_param *ap;
-    char *q0;
-    Regex re_token;
-
-    newRegex(TOKEN_PAT, FALSE, &re_token, NULL);
+    char *p;
 
     for (ap = auth; ap->name != NULL; ap++) {
 	ap->val = NULL;
@@ -1070,26 +1116,41 @@
     while (*q != '\0') {
 	SKIP_BLANKS(q);
 	for (ap = auth; ap->name != NULL; ap++) {
-	    if (strncasecmp(q, ap->name, strlen(ap->name)) == 0) {
-		q += strlen(ap->name);
-		SKIP_BLANKS(q);
-		if (*q != '=')
+	    size_t len;
+
+	    len = strlen(ap->name);
+	    if (strncasecmp(q, ap->name, len) == 0 &&
+		(IS_SPACE(q[len]) || q[len] == '=')) {
+		p = q + len;
+		SKIP_BLANKS(p);
+		if (*p != '=')
 		    return q;
-		q++;
+		q = p + 1;
 		ap->val = extract_auth_val(&q);
 		break;
 	    }
 	}
 	if (ap->name == NULL) {
 	    /* skip unknown param */
-	    if (RegexMatch(&re_token, q, -1, TRUE) == 0)
-		return q;
-	    MatchedPosition(&re_token, &q0, &q);
+	    int token_type;
+	    p = q;
+	    if ((token_type = skip_auth_token(&q)) == AUTHCHR_TOKEN &&
+		(IS_SPACE(*q) || *q == '=')) {
+		SKIP_BLANKS(q);
+		if (*q != '=')
+		    return p;
+		q++;
+		extract_auth_val(&q);
+	    }
+	    else
+		return p;
+	}
+	if (*q != '\0') {
 	    SKIP_BLANKS(q);
-	    if (*q != '=')
-		return q;
-	    q++;
-	    extract_auth_val(&q);
+	    if (*q == ',')
+		q++;
+	    else
+		break;
 	}
     }
     return q;
@@ -1344,12 +1405,9 @@
 findAuthentication(struct http_auth *hauth, Buffer *buf, char *auth_field)
 {
     struct http_auth *ha;
-    int len = strlen(auth_field);
+    int len = strlen(auth_field), slen;
     TextListItem *i;
     char *p0, *p;
-    Regex re_token;
-
-    newRegex(TOKEN_PAT, FALSE, &re_token, NULL);
 
     bzero(hauth, sizeof(struct http_auth));
     for (i = buf->document_header->first; i != NULL; i = i->next) {
@@ -1358,29 +1416,30 @@
 		SKIP_BLANKS(p);
 		p0 = p;
 		for (ha = &www_auth[0]; ha->scheme != NULL; ha++) {
-		    if (strncasecmp(p, ha->scheme, strlen(ha->scheme)) == 0) {
+		    slen = strlen(ha->scheme);
+		    if (strncasecmp(p, ha->scheme, slen) == 0) {
+			p += slen;
+			SKIP_BLANKS(p);
 			if (hauth->pri < ha->pri) {
 			    *hauth = *ha;
-			    p += strlen(ha->scheme);
-			    SKIP_BLANKS(p);
 			    p = extract_auth_param(p, hauth->param);
 			    break;
 			}
 			else {
 			    /* weak auth */
-			    p += strlen(ha->scheme);
-			    SKIP_BLANKS(p);
 			    p = extract_auth_param(p, none_auth_param);
 			}
 		    }
 		}
 		if (p0 == p) {
 		    /* all unknown auth failed */
-		    if (RegexMatch(&re_token, p0, -1, TRUE) == 0)
-			return NULL;
-		    MatchedPosition(&re_token, &p0, &p);
-		    SKIP_BLANKS(p);
-		    p = extract_auth_param(p, none_auth_param);
+		    int token_type;
+		    if ((token_type = skip_auth_token(&p)) == AUTHCHR_TOKEN && IS_SPACE(*p)) {
+			SKIP_BLANKS(p);
+			p = extract_auth_param(p, none_auth_param);
+		    }
+		    else
+			break;
 		}
 	    }
 	}
@@ -1893,6 +1952,27 @@
 	    status = HTST_NORMAL;
 	    goto load_doc;
 	}
+#ifdef AUTH_DEBUG
+	if ((p = checkHeader(t_buf, "WWW-Authenticate:")) != NULL) {
+	    /* Authentication needed */
+	    struct http_auth hauth;
+	    if (findAuthentication(&hauth, t_buf, "WWW-Authenticate:") != NULL
+		&& (realm = get_auth_param(hauth.param, "realm")) != NULL) {
+		auth_pu = &pu;
+		getAuthCookie(&hauth, "Authorization:", extra_header,
+			      auth_pu, &hr, request, &uname, &pwd);
+		if (uname == NULL) {
+		    /* abort */
+		    TRAP_OFF;
+		    goto page_loaded;
+		}
+		UFclose(&f);
+		add_auth_cookie_flag = 1;
+		status = HTST_NORMAL;
+		goto load_doc;
+	    }
+	}
+#endif /* defined(AUTH_DEBUG) */
 	t = checkContentType(t_buf);
 	if (t == NULL)
 	    t = "text/plain";