[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>
This commit is contained in:
@@ -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,
|
||||
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,11 +1246,23 @@ 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return hauth->scheme ? hauth : NULL;
|
||||
@@ -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);
|
||||
}
|
||||
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);
|
||||
|
||||
Reference in New Issue
Block a user