diff options
| author | Fumitoshi UKAI <ukai@debian.or.jp> | 2002-01-30 17:48:49 +0000 | 
|---|---|---|
| committer | Fumitoshi UKAI <ukai@debian.or.jp> | 2002-01-30 17:48:49 +0000 | 
| commit | e074983ced7c3f2fab8a2677bf8cdf40d3e5edcb (patch) | |
| tree | 475ff4310942d7c820f62dfb678827e3ce84f89c | |
| parent | [w3m-dev 02934] add auth cookie with unquoted realm (diff) | |
| download | w3m-e074983ced7c3f2fab8a2677bf8cdf40d3e5edcb.tar.gz w3m-e074983ced7c3f2fab8a2677bf8cdf40d3e5edcb.zip | |
[w3m-dev 02942] Digest qop=auth support
* file.c (http_auth): add request to cred() arg
* file.c (AuthBasicCred): ditto
* file.c (AuthDigestCred): ditto
* file.c (AuthDigestCred): support algorithm=MD5, MD5-sess
			qop=auth, auth-int
* file.c (qstr_unquote): return NULL if input is NULL
* file.c (none_auth_param): added
* file.c (findAuthentication): skip weak or unknown auth
* file.c (getAuthCookie): add request to arg
* file.c (loadGeneralFile): add request to getAuthCookie()
From: Fumitoshi UKAI  <ukai@debian.or.jp>
| -rw-r--r-- | ChangeLog | 16 | ||||
| -rw-r--r-- | file.c | 172 | 
2 files changed, 154 insertions, 34 deletions
| @@ -1,3 +1,17 @@ +2002-01-31  Fumitoshi UKAI  <ukai@debian.or.jp> + +	* [w3m-dev 02942] Digest qop=auth support +	* file.c (http_auth): add request to cred() arg +	* file.c (AuthBasicCred): ditto +	* file.c (AuthDigestCred): ditto +	* file.c (AuthDigestCred): support algorithm=MD5, MD5-sess +			qop=auth, auth-int +	* file.c (qstr_unquote): return NULL if input is NULL +	* file.c (none_auth_param): added +	* file.c (findAuthentication): skip weak or unknown auth +	* file.c (getAuthCookie): add request to arg +	* file.c (loadGeneralFile): add request to getAuthCookie() +  2002-01-31  Hironori Sakamoto <hsaka@mth.biglobe.ne.jp>  	* [w3m-dev 02934] add auth cookie with unquoted realm @@ -2426,4 +2440,4 @@  	* release-0-2-1  	* import w3m-0.2.1 -$Id: ChangeLog,v 1.278 2002/01/30 15:16:52 ukai Exp $ +$Id: ChangeLog,v 1.279 2002/01/30 17:48:49 ukai Exp $ @@ -1,4 +1,4 @@ -/* $Id: file.c,v 1.52 2002/01/30 15:16:52 ukai Exp $ */ +/* $Id: file.c,v 1.53 2002/01/30 17:48:49 ukai Exp $ */  #include "fm.h"  #include <sys/types.h>  #include "myctype.h" @@ -849,7 +849,7 @@ struct http_auth {      char *scheme;      struct auth_param *param;      Str (*cred) (struct http_auth * ha, Str uname, Str pw, ParsedURL *pu, -		 HRequest *hr); +		 HRequest *hr, FormList *request);  };  #define TOKEN_PAT	"[^][()<>@,;:\\\"/?={} \t\001-\037\177]*" @@ -914,7 +914,11 @@ extract_auth_val(char **q)  static Str  qstr_unquote(Str s)  { -    char *p = s->ptr; +    char *p; + +    if (s == NULL) +	return NULL; +    p = s->ptr;      if (*p == '"') {  	Str tmp = Strnew();  	for (p++; *p != '\0'; p++) { @@ -984,7 +988,7 @@ get_auth_param(struct auth_param *auth, char *name)  static Str  AuthBasicCred(struct http_auth *ha, Str uname, Str pw, ParsedURL *pu, -	      HRequest *hr) +	      HRequest *hr, FormList *request)  {      Str s = Strdup(uname);      Strcat_char(s, ':'); @@ -1035,40 +1039,106 @@ digest_hex(char *p)  static Str  AuthDigestCred(struct http_auth *ha, Str uname, Str pw, ParsedURL *pu, -	       HRequest *hr) +	       HRequest *hr, FormList *request)  {      Str tmp, a1buf, a2buf, rd, s;      char md5[MD5_DIGEST_LENGTH + 1];      Str uri = HTTPrequestURI(pu, hr); -    /* -     * A1BUF = H(user ":" realm ":" password) -     * A2BUF = H(method ":" path) -     * RESPONSE_DIGEST = H(A1BUF ":" nonce ":" A2BUF) -     */ +    char nc[] = "00000001"; +    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 qop = qstr_unquote(get_auth_param(ha->param, "qop")); + +    if (cnonce == NULL) +	cnonce = Strnew_charp("cnonce");	/* XXX */ + +    /* A1 = unq(username-value) ":" unq(realm-value) ":" passwd */      tmp = Strnew_m_charp(uname->ptr, ":",  			 qstr_unquote(get_auth_param(ha->param, "realm"))->ptr,  			 ":", pw->ptr, NULL);      MD5(tmp->ptr, strlen(tmp->ptr), md5);      a1buf = digest_hex(md5); +    if (algorithm) { +	if (strcasecmp(algorithm->ptr, "MD5-sess") == 0) { +	    /* A1 = H(unq(username-value) ":" unq(realm-value) ":" passwd) +	     *      ":" unq(nonce-value) ":" unq(cnonce-value) +	     */ +	    if (nonce == NULL) +		return NULL; +	    tmp = Strnew_m_charp(a1buf->ptr, ":", +				 qstr_unquote(nonce)->ptr, +				 ":", qstr_unquote(cnonce)->ptr, NULL); +	    MD5(tmp->ptr, strlen(tmp->ptr), md5); +	    a1buf = digest_hex(md5); +	} +	else if (strcasecmp(algorithm->ptr, "MD5") == 0) +	    /* ok default */ +	    ; +	else +	    /* unknown algorithm */ +	    return NULL; +    } + +    /* A2 = Method ":" digest-uri-value */      tmp = Strnew_m_charp(HTTPrequestMethod(hr)->ptr, ":", uri->ptr, NULL); +    if (qop && (strcasecmp(qop->ptr, "auth-int") == 0)) { +	/*  A2 = Method ":" digest-uri-value ":" H(entity-body) */ +	Str ebody = Strnew(); +	if (request && request->body) { +	    FILE *fp = fopen(request->body, "r"); +	    if (fp != NULL) { +		int c; +		while ((c = fgetc(fp)) != EOF) +		    Strcat_char(ebody, c); +		fclose(fp); +	    } +	} +	MD5(ebody->ptr, strlen(ebody->ptr), md5); +	ebody = digest_hex(md5); +	Strcat_m_charp(tmp, ":", ebody->ptr, NULL); +    }      MD5(tmp->ptr, strlen(tmp->ptr), md5);      a2buf = digest_hex(md5); -    tmp = Strnew_m_charp(a1buf->ptr, ":", -			 qstr_unquote(get_auth_param(ha->param, "nonce"))->ptr, -			 ":", a2buf->ptr, NULL); -    MD5(tmp->ptr, strlen(tmp->ptr), md5); -    rd = digest_hex(md5); +    if (qop && +	(strcasecmp(qop->ptr, "auth") == 0 +	 || strcasecmp(qop->ptr, "auth-int") == 0)) { +	/* request-digest  = <"> < KD ( H(A1),     unq(nonce-value) +	 *                      ":" nc-value +	 *                      ":" unq(cnonce-value) +	 *                      ":" unq(qop-value) +	 *                      ":" H(A2) +	 *                      ) <"> +	 */ +	if (nonce == NULL) +	    return NULL; +	tmp = Strnew_m_charp(a1buf->ptr, ":", qstr_unquote(nonce)->ptr, +			     ":", nc, +			     ":", qstr_unquote(cnonce)->ptr, +			     ":", qstr_unquote(qop)->ptr, +			     ":", a2buf->ptr, NULL); +	MD5(tmp->ptr, strlen(tmp->ptr), md5); +	rd = digest_hex(md5); +    } +    else { +	/* compatibility with RFC 2069 +	 * request_digest = KD(H(A1),  unq(nonce), H(A2)) +	 */ +	tmp = Strnew_m_charp(a1buf->ptr, ":", +			     qstr_unquote(get_auth_param(ha->param, "nonce"))-> +			     ptr, ":", a2buf->ptr, NULL); +	MD5(tmp->ptr, strlen(tmp->ptr), md5); +	rd = digest_hex(md5); +    }      /* -     * username=<uname>, -     * realm=<realm>, -     * nonce=<nonce>, -     * uri=<uri>, -     * response=<RESPONSE_DIGEST>, -     * [opaque=<opaque>] +     * digest-response  = 1#( username | realm | nonce | digest-uri +     *                          | response | [ algorithm ] | [cnonce] | +     *                          [opaque] | [message-qop] | +     *                          [nonce-count]  | [auth-param] )       */      tmp = Strnew_m_charp("username=\"", uname->ptr, "\"", NULL); @@ -1079,14 +1149,32 @@ AuthDigestCred(struct http_auth *ha, Str uname, Str pw, ParsedURL *pu,      Strcat_m_charp(tmp, ", uri=\"", uri->ptr, "\"", NULL);      Strcat_m_charp(tmp, ", response=\"", rd->ptr, "\"", NULL); +    if (algorithm) +	Strcat_m_charp(tmp, ", algorithm=", +		       get_auth_param(ha->param, "algorithm")->ptr, NULL); + +    if (cnonce) +	Strcat_m_charp(tmp, ", cnonce=\"", cnonce->ptr, "\"", NULL); +      if ((s = get_auth_param(ha->param, "opaque")) != NULL)  	Strcat_m_charp(tmp, ", opaque=", s->ptr, NULL); +    if (qop) { +	Strcat_m_charp(tmp, ", qop=", +		       get_auth_param(ha->param, "qop")->ptr, NULL); +	/* XXX how to count? */ +	Strcat_m_charp(tmp, ", nc=", nc, NULL); +    } +      return tmp;  }  #endif  /* *INDENT-OFF* */ +struct auth_param none_auth_param[] = { +    {NULL, NULL} +}; +  struct auth_param basic_auth_param[] = {      {"realm", NULL},      {NULL, NULL} @@ -1138,7 +1226,7 @@ findAuthentication(struct http_auth *hauth, Buffer *buf, char *auth_field)      struct http_auth *ha;      int len = strlen(auth_field);      TextListItem *i; -    char *p; +    char *p0, *p;      Regex re_token;      newRegex(TOKEN_PAT, FALSE, &re_token, NULL); @@ -1148,6 +1236,7 @@ findAuthentication(struct http_auth *hauth, Buffer *buf, char *auth_field)  	if (strncasecmp(i->ptr, auth_field, len) == 0) {  	    for (p = i->ptr + len; p != NULL && *p != '\0';) {  		SKIP_BLANKS(p); +		p0 = p;  		for (ha = &www_auth[0]; ha->scheme != NULL; ha++) {  		    if (strncmp(p, ha->scheme, strlen(ha->scheme)) == 0) {  			if (hauth->pri < ha->pri) { @@ -1157,10 +1246,22 @@ findAuthentication(struct http_auth *hauth, Buffer *buf, char *auth_field)  			    p = extract_auth_param(p, hauth->param);  			    break;  			} -			else +			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); +		}  	    }  	}      } @@ -1169,7 +1270,8 @@ findAuthentication(struct http_auth *hauth, Buffer *buf, char *auth_field)  static Str  getAuthCookie(struct http_auth *hauth, char *auth_header, -	      TextList *extra_header, ParsedURL *pu, HRequest *hr) +	      TextList *extra_header, ParsedURL *pu, HRequest *hr, +	      FormList *request)  {      Str ss;      Str uname, pwd; @@ -1251,13 +1353,15 @@ getAuthCookie(struct http_auth *hauth, char *auth_header,  				       "Password: "));  #endif  	} -	ss = hauth->cred(hauth, uname, pwd, pu, hr); +	ss = hauth->cred(hauth, uname, pwd, pu, hr, request); +    } +    if (ss) { +	tmp = Strnew_charp(auth_header); +	Strcat_m_charp(tmp, " ", hauth->scheme, NULL); +	Strcat(tmp, ss); +	Strcat_charp(tmp, "\r\n"); +	pushText(extra_header, tmp->ptr);      } -    tmp = Strnew_charp(auth_header); -    Strcat_m_charp(tmp, " ", hauth->scheme, NULL); -    Strcat(tmp, ss); -    Strcat_charp(tmp, "\r\n"); -    pushText(extra_header, tmp->ptr);      return ss;  } @@ -1496,8 +1600,8 @@ loadGeneralFile(char *path, ParsedURL *volatile current, char *referer,  	    struct http_auth hauth;  	    if (findAuthentication(&hauth, t_buf, "WWW-Authenticate:") != NULL  		&& (realm = get_auth_param(hauth.param, "realm")) != NULL) { -		ss = getAuthCookie(&hauth, "Authorization:", extra_header, -				   &pu, &hr); +		ss = getAuthCookie(&hauth, "Authorization:", extra_header, &pu, +				   &hr, request);  		if (ss == NULL) {  		    /* abort */  		    UFclose(&f); @@ -1518,7 +1622,8 @@ loadGeneralFile(char *path, ParsedURL *volatile current, char *referer,  		!= NULL  		&& (realm = get_auth_param(hauth.param, "realm")) != NULL) {  		ss = getAuthCookie(&hauth, "Proxy-Authorization:", -				   extra_header, &HTTP_proxy_parsed, &hr); +				   extra_header, &HTTP_proxy_parsed, &hr, +				   request);  		proxy_auth_cookie = ss;  		if (ss == NULL) {  		    /* abort */ @@ -1531,6 +1636,7 @@ loadGeneralFile(char *path, ParsedURL *volatile current, char *referer,  		goto load_doc;  	    }  	} +	/* XXX: RFC2617 3.2.3 Authentication-Info: ? */  	if (add_auth_cookie_flag)  	    /* If authorization is required and passed */  	    add_auth_cookie(pu.host, pu.port, qstr_unquote(realm)->ptr, ss); | 
