[w3m-dev 04132] Re: Multiple challeges in *-Authenticate header

Kiyokazu SUTO <[email protected]> 26 Dec 2004 12:58:43 +0900
Newsgroups gmane.comp.web.w3m.devel
Message-ID <[email protected]>
Citation (with leading "> " of each line) from article:
  <[email protected]>
    by Kiyokazu SUTO <[email protected]> :
> *-Authenticate
> 2

qopqop="auth,auth-int"auth
auth-intAuthorization:qop
qop=auth,auth-int(
Apache(1.3.33)mod_auth_digest)

Citation (with leading "| " of each line) from article:
  <[email protected]>
    by Kiyokazu SUTO <[email protected]> :
| [w3m-dev 04130]request->body
| 

()

[w3m-dev 4130][w3m-dev 4131]

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

-----  -----  -----  -----  -----
--- file.c~	Sat Dec 18 20:13:03 2004
+++ file.c	Sun Dec 26 12:51:14 2004
@@ -1218,6 +1218,12 @@
     return tmp;
 }
 
+enum {
+    QOP_NONE,
+    QOP_AUTH,
+    QOP_AUTH_INT,
+};
+
 static Str
 AuthDigestCred(struct http_auth *ha, Str uname, Str pw, ParsedURL *pu,
 	       HRequest *hr, FormList *request)
@@ -1229,11 +1235,50 @@
 
     Str algorithm = qstr_unquote(get_auth_param(ha->param, "algorithm"));
     Str nonce = qstr_unquote(get_auth_param(ha->param, "nonce"));
-    Str cnonce = qstr_unquote(get_auth_param(ha->param, "cnonce"));
+    Str cnonce /* = qstr_unquote(get_auth_param(ha->param, "cnonce")) */;
+    /* cnonce is what client should generate. */
     Str qop = qstr_unquote(get_auth_param(ha->param, "qop"));
 
-    if (cnonce == NULL)
-	cnonce = Strnew_charp("cnonce");	/* XXX */
+    static union {
+	int r[4];
+	char s[sizeof(int) * 4];
+    } cnonce_seed;
+    int qop_i = QOP_NONE;
+
+    cnonce_seed.r[0] = rand();
+    cnonce_seed.r[1] = rand();
+    cnonce_seed.r[2] = rand();
+    MD5(cnonce_seed.s, sizeof(cnonce_seed.s), md5);
+    cnonce = digest_hex(md5);
+    cnonce_seed.r[3]++;
+
+    if (qop) {
+	char *p;
+	size_t i;
+
+	p = qop->ptr;
+	SKIP_BLANKS(p);
+
+	for (;;) {
+	    if ((i = strcspn(p, " \t,")) > 0) {
+		if (i == sizeof("auth-int") - sizeof("") && !strncasecmp(p, "auth-int", i)) {
+		    if (qop_i < QOP_AUTH_INT)
+			qop_i = QOP_AUTH_INT;
+		}
+		else if (i == sizeof("auth") - sizeof("") && !strncasecmp(p, "auth", i)) {
+		    if (qop_i < QOP_AUTH)
+			qop_i = QOP_AUTH;
+		}
+	    }
+
+	    if (p[i]) {
+		p += i + 1;
+		SKIP_BLANKS(p);
+	    }
+	    else
+		break;
+	}
+    }
 
     /* A1 = unq(username-value) ":" unq(realm-value) ":" passwd */
     tmp = Strnew_m_charp(uname->ptr, ":",
@@ -1265,10 +1310,10 @@
 
     /* A2 = Method ":" digest-uri-value */
     tmp = Strnew_m_charp(HTTPrequestMethod(hr)->ptr, ":", uri->ptr, NULL);
-    if (qop && (strcasecmp(qop->ptr, "auth-int") == 0)) {
+    if (qop_i == QOP_AUTH_INT) {
 	/*  A2 = Method ":" digest-uri-value ":" H(entity-body) */
 	if (request && request->body) {
-	    if (request->enctype == FORM_ENCTYPE_MULTIPART) {
+	    if (request->method == FORM_METHOD_POST && request->enctype == FORM_ENCTYPE_MULTIPART) {
 		FILE *fp = fopen(request->body, "r");
 		if (fp != NULL) {
 		    Str ebody;
@@ -1292,9 +1337,7 @@
     MD5(tmp->ptr, strlen(tmp->ptr), md5);
     a2buf = digest_hex(md5);
 
-    if (qop &&
-	(strcasecmp(qop->ptr, "auth") == 0
-	 || strcasecmp(qop->ptr, "auth-int") == 0)) {
+    if (qop_i >= QOP_AUTH) {
 	/* request-digest  = <"> < KD ( H(A1),     unq(nonce-value)
 	 *                      ":" nc-value
 	 *                      ":" unq(cnonce-value)
@@ -1307,7 +1350,7 @@
 	tmp = Strnew_m_charp(a1buf->ptr, ":", qstr_unquote(nonce)->ptr,
 			     ":", nc,
 			     ":", qstr_unquote(cnonce)->ptr,
-			     ":", qstr_unquote(qop)->ptr,
+			     ":", qop_i == QOP_AUTH ? "auth" : "auth-int",
 			     ":", a2buf->ptr, NULL);
 	MD5(tmp->ptr, strlen(tmp->ptr), md5);
 	rd = digest_hex(md5);
@@ -1348,10 +1391,13 @@
     if ((s = get_auth_param(ha->param, "opaque")) != NULL)
 	Strcat_m_charp(tmp, ", opaque=", s->ptr, NULL);
 
-    if (qop) {
+    if (qop_i >= QOP_AUTH) {
 	Strcat_m_charp(tmp, ", qop=",
-		       get_auth_param(ha->param, "qop")->ptr, NULL);
+		       qop_i == QOP_AUTH ? "auth" : "auth-int",
+		       NULL);
 	/* XXX how to count? */
+	/* Since nonce is unique up to each *-Authenticate and w3m does not re-use *-Authenticate: headers,
+	   nonce-count should be always "00000001". */
 	Strcat_m_charp(tmp, ", nc=", nc, NULL);
     }