[w3m-dev 02928] RFC2617: HTTP Digest authentication
* NEWS: RFC2617: HTTP Digest authentication * config.h.dist (USE_DIGEST_AUTH): added * configure (use_digest_auth): added, enabled when openssl found (because it used openssl/md5.h) * file.c (auth_param): added * file.c (http_auth): added * file.c (extract_auth_val): added * file.c (qstr_unquote): added * file.c (extract_auth_param): added * file.c (get_auth_param): added * file.c (AuthBasicCred): added * file.c (digest_hex): added * file.c (AuthDigestCred): added * file.c (basic_auth_param): added * file.c (digest_auth_param): added * file.c (www_auth): added * file.c (findAuthentication): added * file.c (getAuthCookie): rewrite, use http_auth * file.c (loadGeneralFile): HRequest hr * file.c (loadGeneralFile): use findAuthentication, new getAuthCookie * proto.h (HTTPrequestMethod): added * proto.h (HTTPrequestURI): added * proto.h (openURL): add `hr' arg * url.c (HTTPrequestMethod): added * url.c (HTTPrequestURI): added * url.c (HTTPrequest): use HTTPrequestMethod and HTTPrequestURI * url.c (openURL): add `hr' arg From: Fumitoshi UKAI <ukai@debian.or.jp>
This commit is contained in:
@@ -1,3 +1,34 @@
|
|||||||
|
2002-01-30 Fumitoshi UKAI <ukai@debian.or.jp>
|
||||||
|
|
||||||
|
* [w3m-dev 02928] RFC2617: HTTP Digest authentication
|
||||||
|
* NEWS: RFC2617: HTTP Digest authentication
|
||||||
|
* config.h.dist (USE_DIGEST_AUTH): added
|
||||||
|
* configure (use_digest_auth): added, enabled when openssl found
|
||||||
|
(because it used openssl/md5.h)
|
||||||
|
* file.c (auth_param): added
|
||||||
|
* file.c (http_auth): added
|
||||||
|
* file.c (extract_auth_val): added
|
||||||
|
* file.c (qstr_unquote): added
|
||||||
|
* file.c (extract_auth_param): added
|
||||||
|
* file.c (get_auth_param): added
|
||||||
|
* file.c (AuthBasicCred): added
|
||||||
|
* file.c (digest_hex): added
|
||||||
|
* file.c (AuthDigestCred): added
|
||||||
|
* file.c (basic_auth_param): added
|
||||||
|
* file.c (digest_auth_param): added
|
||||||
|
* file.c (www_auth): added
|
||||||
|
* file.c (findAuthentication): added
|
||||||
|
* file.c (getAuthCookie): rewrite, use http_auth
|
||||||
|
* file.c (loadGeneralFile): HRequest hr
|
||||||
|
* file.c (loadGeneralFile): use findAuthentication, new getAuthCookie
|
||||||
|
* proto.h (HTTPrequestMethod): added
|
||||||
|
* proto.h (HTTPrequestURI): added
|
||||||
|
* proto.h (openURL): add `hr' arg
|
||||||
|
* url.c (HTTPrequestMethod): added
|
||||||
|
* url.c (HTTPrequestURI): added
|
||||||
|
* url.c (HTTPrequest): use HTTPrequestMethod and HTTPrequestURI
|
||||||
|
* url.c (openURL): add `hr' arg
|
||||||
|
|
||||||
2002-01-30 SASAKI Takeshi <sasaki@ct.sakura.ne.jp>
|
2002-01-30 SASAKI Takeshi <sasaki@ct.sakura.ne.jp>
|
||||||
|
|
||||||
* [w3m-dev 02927] mailto: POST method with w3mmail.cgi
|
* [w3m-dev 02927] mailto: POST method with w3mmail.cgi
|
||||||
@@ -2362,4 +2393,4 @@
|
|||||||
* release-0-2-1
|
* release-0-2-1
|
||||||
* import w3m-0.2.1
|
* import w3m-0.2.1
|
||||||
|
|
||||||
$Id: ChangeLog,v 1.272 2002/01/29 17:16:35 ukai Exp $
|
$Id: ChangeLog,v 1.273 2002/01/29 19:08:49 ukai Exp $
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
w3m 0.3?
|
w3m 0.3?
|
||||||
|
|
||||||
|
* RFC2617: HTTP Digest authentication
|
||||||
* rc: default_url=0(empty) 1(current URL) 2(link URL)
|
* rc: default_url=0(empty) 1(current URL) 2(link URL)
|
||||||
* GOTO_RELATIVE (M-u)
|
* GOTO_RELATIVE (M-u)
|
||||||
* highlight for incremental search
|
* highlight for incremental search
|
||||||
|
|||||||
@@ -113,6 +113,7 @@ MODEL=Linux.i686-monster-ja
|
|||||||
#undef USE_SYSMOUSE
|
#undef USE_SYSMOUSE
|
||||||
#define USE_MENU
|
#define USE_MENU
|
||||||
#define USE_COOKIE
|
#define USE_COOKIE
|
||||||
|
#define USE_DIGEST_AUTH
|
||||||
#define USE_SSL
|
#define USE_SSL
|
||||||
#undef USE_SSL_VERIFY
|
#undef USE_SSL_VERIFY
|
||||||
#undef FTPPASS_HOSTNAMEGEN
|
#undef FTPPASS_HOSTNAMEGEN
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
# $Id: configure,v 1.57 2002/01/29 16:23:37 ukai Exp $
|
# $Id: configure,v 1.58 2002/01/29 19:08:49 ukai Exp $
|
||||||
# Configuration.
|
# Configuration.
|
||||||
#
|
#
|
||||||
|
|
||||||
@@ -685,9 +685,12 @@ if [ "$use_ssl" = y ]; then
|
|||||||
fi
|
fi
|
||||||
if [ "$use_ssl" = y ]; then
|
if [ "$use_ssl" = y ]; then
|
||||||
ask_param "SSL verification support (SSL library >= version 0.8)" use_ssl_verify n
|
ask_param "SSL verification support (SSL library >= version 0.8)" use_ssl_verify n
|
||||||
|
ask_param "Digest Auth support" use_digest_auth y
|
||||||
else
|
else
|
||||||
use_ssl_verify=n
|
use_ssl_verify=n
|
||||||
def_param "use_ssl_verify" n
|
def_param "use_ssl_verify" n
|
||||||
|
use_digest_auth=n
|
||||||
|
def_param "use_digest_auth" n
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "$use_color" = y ]; then
|
if [ "$use_color" = y ]; then
|
||||||
@@ -2045,6 +2048,7 @@ $def_use_gpm
|
|||||||
$def_use_sysmouse
|
$def_use_sysmouse
|
||||||
$def_use_menu
|
$def_use_menu
|
||||||
$def_use_cookie
|
$def_use_cookie
|
||||||
|
$def_use_digest_auth
|
||||||
$def_use_ssl
|
$def_use_ssl
|
||||||
$def_use_ssl_verify
|
$def_use_ssl_verify
|
||||||
$def_ftppass_hostnamegen
|
$def_ftppass_hostnamegen
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: file.c,v 1.48 2002/01/29 17:16:35 ukai Exp $ */
|
/* $Id: file.c,v 1.49 2002/01/29 19:08:50 ukai Exp $ */
|
||||||
#include "fm.h"
|
#include "fm.h"
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include "myctype.h"
|
#include "myctype.h"
|
||||||
@@ -841,36 +841,337 @@ checkContentType(Buffer *buf)
|
|||||||
return r->ptr;
|
return r->ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Str
|
struct auth_param {
|
||||||
extractRealm(char *q)
|
char *name;
|
||||||
{
|
Str val;
|
||||||
Str p = Strnew();
|
};
|
||||||
char c;
|
|
||||||
|
|
||||||
SKIP_BLANKS(q);
|
struct http_auth {
|
||||||
if (strncasecmp(q, "Basic ", 6) != 0) {
|
int pri;
|
||||||
/* complicated authentication... not implemented */
|
char *scheme;
|
||||||
return NULL;
|
struct auth_param *param;
|
||||||
|
Str (*cred) (struct http_auth * ha, Str uname, Str pw, ParsedURL *pu,
|
||||||
|
HRequest *hr);
|
||||||
|
};
|
||||||
|
|
||||||
|
#define TOKEN_PAT "[^][()<>@,;:\\\"/?={} \t\001-\037\177]*"
|
||||||
|
|
||||||
|
static Str
|
||||||
|
extract_auth_val(char **q)
|
||||||
|
{
|
||||||
|
unsigned char *qq = *(unsigned char **)q;
|
||||||
|
int quoted = 0;
|
||||||
|
Str val = Strnew();
|
||||||
|
|
||||||
|
SKIP_BLANKS(qq);
|
||||||
|
if (*qq == '"') {
|
||||||
|
quoted = TRUE;
|
||||||
|
Strcat_char(val, *qq++);
|
||||||
}
|
}
|
||||||
q += 6;
|
while (*qq != '\0') {
|
||||||
SKIP_BLANKS(q);
|
if (quoted && *qq == '"') {
|
||||||
if (strncasecmp(q, "realm=", 6) != 0) {
|
Strcat_char(val, *qq++);
|
||||||
/* no realm attribute... get confused */
|
break;
|
||||||
return NULL;
|
}
|
||||||
|
if (!quoted) {
|
||||||
|
switch (*qq) {
|
||||||
|
case '(':
|
||||||
|
case ')':
|
||||||
|
case '<':
|
||||||
|
case '>':
|
||||||
|
case '@':
|
||||||
|
case ',':
|
||||||
|
case ';':
|
||||||
|
case ':':
|
||||||
|
case '\\':
|
||||||
|
case '"':
|
||||||
|
case '/':
|
||||||
|
case '?':
|
||||||
|
case '=':
|
||||||
|
case ' ':
|
||||||
|
case '\t':
|
||||||
|
qq++;
|
||||||
|
goto end_token;
|
||||||
|
default:
|
||||||
|
if (*qq <= 037 || *qq == 177) {
|
||||||
|
qq++;
|
||||||
|
goto end_token;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (quoted && *qq == '\\')
|
||||||
|
Strcat_char(val, *qq++);
|
||||||
|
Strcat_char(val, *qq++);
|
||||||
}
|
}
|
||||||
q += 6;
|
end_token:
|
||||||
SKIP_BLANKS(q);
|
if (*qq != '\0') {
|
||||||
c = '\0';
|
SKIP_BLANKS(qq);
|
||||||
if (*q == '"')
|
if (*qq == ',')
|
||||||
c = *q++;
|
qq++;
|
||||||
while (*q != '\0' && *q != c)
|
}
|
||||||
Strcat_char(p, *q++);
|
*q = qq;
|
||||||
return p;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Str
|
static Str
|
||||||
getAuthCookie(char *realm, char *auth_header, TextList *extra_header,
|
qstr_unquote(Str s)
|
||||||
ParsedURL *pu)
|
{
|
||||||
|
char *p = s->ptr;
|
||||||
|
if (*p == '"') {
|
||||||
|
Str tmp = Strnew();
|
||||||
|
for (p++; *p != '\0'; p++) {
|
||||||
|
if (*p == '\\')
|
||||||
|
p++;
|
||||||
|
Strcat_char(tmp, *p);
|
||||||
|
}
|
||||||
|
if (Strlastchar(tmp) == '"')
|
||||||
|
Strshrink(tmp, 1);
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
|
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);
|
||||||
|
|
||||||
|
for (ap = auth; ap->name != NULL; ap++) {
|
||||||
|
ap->val = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 != '=')
|
||||||
|
return q;
|
||||||
|
q++;
|
||||||
|
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);
|
||||||
|
SKIP_BLANKS(q);
|
||||||
|
if (*q != '=')
|
||||||
|
return q;
|
||||||
|
q++;
|
||||||
|
extract_auth_val(&q);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return q;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Str
|
||||||
|
get_auth_param(struct auth_param *auth, char *name)
|
||||||
|
{
|
||||||
|
struct auth_param *ap;
|
||||||
|
for (ap = auth; ap->name != NULL; ap++) {
|
||||||
|
if (strcasecmp(name, ap->name) == 0)
|
||||||
|
return ap->val;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Str
|
||||||
|
AuthBasicCred(struct http_auth *ha, Str uname, Str pw, ParsedURL *pu,
|
||||||
|
HRequest *hr)
|
||||||
|
{
|
||||||
|
Str s = Strdup(uname);
|
||||||
|
Strcat_char(s, ':');
|
||||||
|
Strcat(s, pw);
|
||||||
|
return encodeB(s->ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef USE_DIGEST_AUTH
|
||||||
|
#include <openssl/md5.h>
|
||||||
|
|
||||||
|
/* RFC2617: 3.2.2 The Authorization Request Header
|
||||||
|
*
|
||||||
|
* credentials = "Digest" digest-response
|
||||||
|
* digest-response = 1#( username | realm | nonce | digest-uri
|
||||||
|
* | response | [ algorithm ] | [cnonce] |
|
||||||
|
* [opaque] | [message-qop] |
|
||||||
|
* [nonce-count] | [auth-param] )
|
||||||
|
*
|
||||||
|
* username = "username" "=" username-value
|
||||||
|
* username-value = quoted-string
|
||||||
|
* digest-uri = "uri" "=" digest-uri-value
|
||||||
|
* digest-uri-value = request-uri ; As specified by HTTP/1.1
|
||||||
|
* message-qop = "qop" "=" qop-value
|
||||||
|
* cnonce = "cnonce" "=" cnonce-value
|
||||||
|
* cnonce-value = nonce-value
|
||||||
|
* nonce-count = "nc" "=" nc-value
|
||||||
|
* nc-value = 8LHEX
|
||||||
|
* response = "response" "=" request-digest
|
||||||
|
* request-digest = <"> 32LHEX <">
|
||||||
|
* LHEX = "0" | "1" | "2" | "3" |
|
||||||
|
* "4" | "5" | "6" | "7" |
|
||||||
|
* "8" | "9" | "a" | "b" |
|
||||||
|
* "c" | "d" | "e" | "f"
|
||||||
|
*/
|
||||||
|
|
||||||
|
static Str
|
||||||
|
digest_hex(char *p)
|
||||||
|
{
|
||||||
|
char *h = "0123456789abcdef";
|
||||||
|
Str tmp = Strnew_size(MD5_DIGEST_LENGTH * 2 + 1);
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < MD5_DIGEST_LENGTH; i++, p++) {
|
||||||
|
Strcat_char(tmp, h[(*p >> 4) & 0x0f]);
|
||||||
|
Strcat_char(tmp, h[*p & 0x0f]);
|
||||||
|
}
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Str
|
||||||
|
AuthDigestCred(struct http_auth *ha, Str uname, Str pw, ParsedURL *pu,
|
||||||
|
HRequest *hr)
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
*/
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
tmp = Strnew_m_charp(HTTPrequestMethod(hr)->ptr, ":", uri->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);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* username=<uname>,
|
||||||
|
* realm=<realm>,
|
||||||
|
* nonce=<nonce>,
|
||||||
|
* uri=<uri>,
|
||||||
|
* response=<RESPONSE_DIGEST>,
|
||||||
|
* [opaque=<opaque>]
|
||||||
|
*/
|
||||||
|
|
||||||
|
tmp = Strnew_m_charp("username=\"", uname->ptr, "\"", NULL);
|
||||||
|
Strcat_m_charp(tmp, ", realm=",
|
||||||
|
get_auth_param(ha->param, "realm")->ptr, NULL);
|
||||||
|
Strcat_m_charp(tmp, ", nonce=",
|
||||||
|
get_auth_param(ha->param, "nonce")->ptr, NULL);
|
||||||
|
Strcat_m_charp(tmp, ", uri=\"", uri->ptr, "\"", NULL);
|
||||||
|
Strcat_m_charp(tmp, ", response=\"", rd->ptr, "\"", NULL);
|
||||||
|
|
||||||
|
if ((s = get_auth_param(ha->param, "opaque")) != NULL)
|
||||||
|
Strcat_m_charp(tmp, ", opaque=", s->ptr, NULL);
|
||||||
|
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* *INDENT-OFF* */
|
||||||
|
struct auth_param basic_auth_param[] = {
|
||||||
|
{"realm", NULL},
|
||||||
|
{NULL, NULL}
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef USE_DIGEST_AUTH
|
||||||
|
/* RFC2617: 3.2.1 The WWW-Authenticate Response Header
|
||||||
|
* challenge = "Digest" digest-challenge
|
||||||
|
*
|
||||||
|
* digest-challenge = 1#( realm | [ domain ] | nonce |
|
||||||
|
* [ opaque ] |[ stale ] | [ algorithm ] |
|
||||||
|
* [ qop-options ] | [auth-param] )
|
||||||
|
*
|
||||||
|
* domain = "domain" "=" <"> URI ( 1*SP URI ) <">
|
||||||
|
* URI = absoluteURI | abs_path
|
||||||
|
* nonce = "nonce" "=" nonce-value
|
||||||
|
* nonce-value = quoted-string
|
||||||
|
* opaque = "opaque" "=" quoted-string
|
||||||
|
* stale = "stale" "=" ( "true" | "false" )
|
||||||
|
* algorithm = "algorithm" "=" ( "MD5" | "MD5-sess" |
|
||||||
|
* token )
|
||||||
|
* qop-options = "qop" "=" <"> 1#qop-value <">
|
||||||
|
* qop-value = "auth" | "auth-int" | token
|
||||||
|
*/
|
||||||
|
struct auth_param digest_auth_param[] = {
|
||||||
|
{"realm", NULL},
|
||||||
|
{"domain", NULL},
|
||||||
|
{"nonce", NULL},
|
||||||
|
{"opaque", NULL},
|
||||||
|
{"stale", NULL},
|
||||||
|
{"algorithm", NULL},
|
||||||
|
{"qop", NULL},
|
||||||
|
{NULL, NULL}
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
/* for RFC2617: HTTP Authentication */
|
||||||
|
struct http_auth www_auth[] = {
|
||||||
|
{ 1, "Basic ", basic_auth_param, AuthBasicCred },
|
||||||
|
#ifdef USE_DIGEST_AUTH
|
||||||
|
{ 10, "Digest ", digest_auth_param, AuthDigestCred },
|
||||||
|
#endif
|
||||||
|
{ 0, NULL, NULL, NULL,}
|
||||||
|
};
|
||||||
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
|
static struct http_auth *
|
||||||
|
findAuthentication(struct http_auth *hauth, Buffer *buf, char *auth_field)
|
||||||
|
{
|
||||||
|
struct http_auth *ha;
|
||||||
|
int len = strlen(auth_field);
|
||||||
|
TextListItem *i;
|
||||||
|
char *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) {
|
||||||
|
if (strncasecmp(i->ptr, auth_field, len) == 0) {
|
||||||
|
for (p = i->ptr + len; p != NULL && *p != '\0';) {
|
||||||
|
SKIP_BLANKS(p);
|
||||||
|
for (ha = &www_auth[0]; ha->scheme != NULL; ha++) {
|
||||||
|
if (strncmp(p, ha->scheme, strlen(ha->scheme)) == 0) {
|
||||||
|
if (hauth->pri < ha->pri) {
|
||||||
|
*hauth = *ha;
|
||||||
|
p += strlen(ha->scheme);
|
||||||
|
SKIP_BLANKS(p);
|
||||||
|
p = extract_auth_param(p, hauth->param);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
p += strlen(ha->scheme);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return hauth->scheme ? hauth : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Str
|
||||||
|
getAuthCookie(struct http_auth *hauth, char *auth_header,
|
||||||
|
TextList *extra_header, ParsedURL *pu, HRequest *hr)
|
||||||
{
|
{
|
||||||
Str ss;
|
Str ss;
|
||||||
Str uname, pwd;
|
Str uname, pwd;
|
||||||
@@ -878,6 +1179,7 @@ getAuthCookie(char *realm, char *auth_header, TextList *extra_header,
|
|||||||
TextListItem *i, **i0;
|
TextListItem *i, **i0;
|
||||||
int a_found;
|
int a_found;
|
||||||
int auth_header_len = strlen(auth_header);
|
int auth_header_len = strlen(auth_header);
|
||||||
|
char *realm = qstr_unquote(get_auth_param(hauth->param, "realm"))->ptr;
|
||||||
|
|
||||||
a_found = FALSE;
|
a_found = FALSE;
|
||||||
for (i0 = &(extra_header->first), i = *i0; i != NULL;
|
for (i0 = &(extra_header->first), i = *i0; i != NULL;
|
||||||
@@ -888,8 +1190,9 @@ getAuthCookie(char *realm, char *auth_header, TextList *extra_header,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (a_found) {
|
if (a_found) {
|
||||||
/* This means that *-Authenticate: header is received after *
|
/* This means that *-Authenticate: header is received after
|
||||||
* Authorization: header is sent to the server. */
|
* Authorization: header is sent to the server.
|
||||||
|
*/
|
||||||
if (fmInitialized) {
|
if (fmInitialized) {
|
||||||
message("Wrong username or password", 0, 0);
|
message("Wrong username or password", 0, 0);
|
||||||
refresh();
|
refresh();
|
||||||
@@ -951,18 +1254,17 @@ getAuthCookie(char *realm, char *auth_header, TextList *extra_header,
|
|||||||
"Password: "));
|
"Password: "));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
Strcat_char(uname, ':');
|
ss = hauth->cred(hauth, uname, pwd, pu, hr);
|
||||||
Strcat(uname, pwd);
|
|
||||||
ss = encodeB(uname->ptr);
|
|
||||||
}
|
}
|
||||||
tmp = Strnew_charp(auth_header);
|
tmp = Strnew_charp(auth_header);
|
||||||
Strcat_charp(tmp, " Basic ");
|
Strcat_m_charp(tmp, " ", hauth->scheme, NULL);
|
||||||
Strcat(tmp, ss);
|
Strcat(tmp, ss);
|
||||||
Strcat_charp(tmp, "\r\n");
|
Strcat_charp(tmp, "\r\n");
|
||||||
pushText(extra_header, tmp->ptr);
|
pushText(extra_header, tmp->ptr);
|
||||||
return ss;
|
return ss;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
same_url_p(ParsedURL *pu1, ParsedURL *pu2)
|
same_url_p(ParsedURL *pu1, ParsedURL *pu2)
|
||||||
{
|
{
|
||||||
@@ -997,6 +1299,7 @@ loadGeneralFile(char *path, ParsedURL *volatile current, char *referer,
|
|||||||
unsigned char status = HTST_NORMAL;
|
unsigned char status = HTST_NORMAL;
|
||||||
URLOption url_option;
|
URLOption url_option;
|
||||||
Str tmp;
|
Str tmp;
|
||||||
|
HRequest hr;
|
||||||
|
|
||||||
tpath = path;
|
tpath = path;
|
||||||
prevtrap = NULL;
|
prevtrap = NULL;
|
||||||
@@ -1010,7 +1313,7 @@ loadGeneralFile(char *path, ParsedURL *volatile current, char *referer,
|
|||||||
url_option.referer = referer;
|
url_option.referer = referer;
|
||||||
url_option.flag = flag;
|
url_option.flag = flag;
|
||||||
f = openURL(tpath, &pu, current, &url_option, request, extra_header, of,
|
f = openURL(tpath, &pu, current, &url_option, request, extra_header, of,
|
||||||
&status);
|
&hr, &status);
|
||||||
of = NULL;
|
of = NULL;
|
||||||
#ifdef JP_CHARSET
|
#ifdef JP_CHARSET
|
||||||
content_charset = '\0';
|
content_charset = '\0';
|
||||||
@@ -1193,10 +1496,11 @@ loadGeneralFile(char *path, ParsedURL *volatile current, char *referer,
|
|||||||
if ((p = checkHeader(t_buf, "WWW-Authenticate:")) != NULL &&
|
if ((p = checkHeader(t_buf, "WWW-Authenticate:")) != NULL &&
|
||||||
http_response_code == 401) {
|
http_response_code == 401) {
|
||||||
/* Authentication needed */
|
/* Authentication needed */
|
||||||
realm = extractRealm(p);
|
struct http_auth hauth;
|
||||||
if (realm != NULL) {
|
if (findAuthentication(&hauth, t_buf, "WWW-Authenticate:") != NULL
|
||||||
ss = getAuthCookie(realm->ptr, "Authorization:", extra_header,
|
&& (realm = get_auth_param(hauth.param, "realm")) != NULL) {
|
||||||
&pu);
|
ss = getAuthCookie(&hauth, "Authorization:", extra_header,
|
||||||
|
&pu, &hr);
|
||||||
if (ss == NULL) {
|
if (ss == NULL) {
|
||||||
/* abort */
|
/* abort */
|
||||||
UFclose(&f);
|
UFclose(&f);
|
||||||
@@ -1212,11 +1516,12 @@ loadGeneralFile(char *path, ParsedURL *volatile current, char *referer,
|
|||||||
if ((p = checkHeader(t_buf, "Proxy-Authenticate:")) != NULL &&
|
if ((p = checkHeader(t_buf, "Proxy-Authenticate:")) != NULL &&
|
||||||
http_response_code == 407) {
|
http_response_code == 407) {
|
||||||
/* Authentication needed */
|
/* Authentication needed */
|
||||||
realm = extractRealm(p);
|
struct http_auth hauth;
|
||||||
if (realm != NULL) {
|
if (findAuthentication(&hauth, t_buf, "Proxy-Authenticate:")
|
||||||
ss = getAuthCookie(realm->ptr,
|
!= NULL
|
||||||
"Proxy-Authorization:",
|
&& (realm = get_auth_param(hauth.param, "realm")) != NULL) {
|
||||||
extra_header, &HTTP_proxy_parsed);
|
ss = getAuthCookie(&hauth, "Proxy-Authorization:",
|
||||||
|
extra_header, &HTTP_proxy_parsed, &hr);
|
||||||
proxy_auth_cookie = ss;
|
proxy_auth_cookie = ss;
|
||||||
if (ss == NULL) {
|
if (ss == NULL) {
|
||||||
/* abort */
|
/* abort */
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: proto.h,v 1.29 2002/01/22 16:59:11 ukai Exp $ */
|
/* $Id: proto.h,v 1.30 2002/01/29 19:08:50 ukai Exp $ */
|
||||||
/*
|
/*
|
||||||
* This file was automatically generated by version 1.7 of cextract.
|
* This file was automatically generated by version 1.7 of cextract.
|
||||||
* Manual editing not recommended.
|
* Manual editing not recommended.
|
||||||
@@ -416,10 +416,12 @@ extern void parseURL2(char *url, ParsedURL *pu, ParsedURL *current);
|
|||||||
extern Str parsedURL2Str(ParsedURL *pu);
|
extern Str parsedURL2Str(ParsedURL *pu);
|
||||||
extern int getURLScheme(char **url);
|
extern int getURLScheme(char **url);
|
||||||
extern void init_stream(URLFile *uf, int scheme, InputStream stream);
|
extern void init_stream(URLFile *uf, int scheme, InputStream stream);
|
||||||
|
Str HTTPrequestMethod(HRequest *hr);
|
||||||
|
Str HTTPrequestURI(ParsedURL *pu, HRequest *hr);
|
||||||
extern URLFile openURL(char *url, ParsedURL *pu, ParsedURL *current,
|
extern URLFile openURL(char *url, ParsedURL *pu, ParsedURL *current,
|
||||||
URLOption *option, FormList *request,
|
URLOption *option, FormList *request,
|
||||||
TextList *extra_header, URLFile *ouf,
|
TextList *extra_header, URLFile *ouf,
|
||||||
unsigned char *status);
|
HRequest *hr, unsigned char *status);
|
||||||
extern int mailcapMatch(struct mailcap *mcap, char *type);
|
extern int mailcapMatch(struct mailcap *mcap, char *type);
|
||||||
extern struct mailcap *searchMailcap(struct mailcap *table, char *type);
|
extern struct mailcap *searchMailcap(struct mailcap *table, char *type);
|
||||||
extern void initMailcap();
|
extern void initMailcap();
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $Id: url.c,v 1.38 2002/01/21 18:34:00 ukai Exp $ */
|
/* $Id: url.c,v 1.39 2002/01/29 19:08:50 ukai Exp $ */
|
||||||
#include "fm.h"
|
#include "fm.h"
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
@@ -1236,28 +1236,29 @@ otherinfo(ParsedURL *target, ParsedURL *current, char *referer)
|
|||||||
return s->ptr;
|
return s->ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Str
|
Str
|
||||||
HTTPrequest(ParsedURL *pu, ParsedURL *current, HRequest *hr, TextList *extra)
|
HTTPrequestMethod(HRequest *hr)
|
||||||
{
|
{
|
||||||
Str tmp;
|
|
||||||
TextListItem *i;
|
|
||||||
#ifdef USE_COOKIE
|
|
||||||
Str cookie;
|
|
||||||
#endif /* USE_COOKIE */
|
|
||||||
switch (hr->command) {
|
switch (hr->command) {
|
||||||
case HR_COMMAND_CONNECT:
|
case HR_COMMAND_CONNECT:
|
||||||
tmp = Strnew_charp("CONNECT ");
|
return Strnew_charp("CONNECT");
|
||||||
break;
|
|
||||||
case HR_COMMAND_POST:
|
case HR_COMMAND_POST:
|
||||||
tmp = Strnew_charp("POST ");
|
return Strnew_charp("POST");
|
||||||
break;
|
break;
|
||||||
case HR_COMMAND_HEAD:
|
case HR_COMMAND_HEAD:
|
||||||
tmp = Strnew_charp("HEAD ");
|
return Strnew_charp("HEAD");
|
||||||
break;
|
break;
|
||||||
case HR_COMMAND_GET:
|
case HR_COMMAND_GET:
|
||||||
default:
|
default:
|
||||||
tmp = Strnew_charp("GET ");
|
return Strnew_charp("GET");
|
||||||
}
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Str
|
||||||
|
HTTPrequestURI(ParsedURL *pu, HRequest *hr)
|
||||||
|
{
|
||||||
|
Str tmp = Strnew();
|
||||||
if (hr->command == HR_COMMAND_CONNECT) {
|
if (hr->command == HR_COMMAND_CONNECT) {
|
||||||
Strcat_charp(tmp, pu->host);
|
Strcat_charp(tmp, pu->host);
|
||||||
Strcat(tmp, Sprintf(":%d", pu->port));
|
Strcat(tmp, Sprintf(":%d", pu->port));
|
||||||
@@ -1272,6 +1273,20 @@ HTTPrequest(ParsedURL *pu, ParsedURL *current, HRequest *hr, TextList *extra)
|
|||||||
else {
|
else {
|
||||||
Strcat(tmp, _parsedURL2Str(pu, TRUE));
|
Strcat(tmp, _parsedURL2Str(pu, TRUE));
|
||||||
}
|
}
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Str
|
||||||
|
HTTPrequest(ParsedURL *pu, ParsedURL *current, HRequest *hr, TextList *extra)
|
||||||
|
{
|
||||||
|
Str tmp;
|
||||||
|
TextListItem *i;
|
||||||
|
#ifdef USE_COOKIE
|
||||||
|
Str cookie;
|
||||||
|
#endif /* USE_COOKIE */
|
||||||
|
tmp = HTTPrequestMethod(hr);
|
||||||
|
Strcat_charp(tmp, " ");
|
||||||
|
Strcat_charp(tmp, HTTPrequestURI(pu, hr)->ptr);
|
||||||
Strcat_charp(tmp, " HTTP/1.0\r\n");
|
Strcat_charp(tmp, " HTTP/1.0\r\n");
|
||||||
if (hr->referer == NO_REFERER)
|
if (hr->referer == NO_REFERER)
|
||||||
Strcat_charp(tmp, otherinfo(pu, NULL, NULL));
|
Strcat_charp(tmp, otherinfo(pu, NULL, NULL));
|
||||||
@@ -1346,13 +1361,13 @@ openFTPStream(ParsedURL *pu)
|
|||||||
URLFile
|
URLFile
|
||||||
openURL(char *url, ParsedURL *pu, ParsedURL *current,
|
openURL(char *url, ParsedURL *pu, ParsedURL *current,
|
||||||
URLOption *option, FormList *request, TextList *extra_header,
|
URLOption *option, FormList *request, TextList *extra_header,
|
||||||
URLFile *ouf, unsigned char *status)
|
URLFile *ouf, HRequest *hr, unsigned char *status)
|
||||||
{
|
{
|
||||||
Str tmp;
|
Str tmp;
|
||||||
int i, sock, scheme;
|
int i, sock, scheme;
|
||||||
char *p, *q, *u;
|
char *p, *q, *u;
|
||||||
URLFile uf;
|
URLFile uf;
|
||||||
HRequest hr;
|
HRequest hr0;
|
||||||
#ifdef USE_SSL
|
#ifdef USE_SSL
|
||||||
SSL *sslh = NULL;
|
SSL *sslh = NULL;
|
||||||
#endif /* USE_SSL */
|
#endif /* USE_SSL */
|
||||||
@@ -1363,6 +1378,9 @@ openURL(char *url, ParsedURL *pu, ParsedURL *current,
|
|||||||
#endif /* USE_NNTP */
|
#endif /* USE_NNTP */
|
||||||
int extlen = strlen(CGI_EXTENSION);
|
int extlen = strlen(CGI_EXTENSION);
|
||||||
|
|
||||||
|
if (hr == NULL)
|
||||||
|
hr = &hr0;
|
||||||
|
|
||||||
if (ouf) {
|
if (ouf) {
|
||||||
uf = *ouf;
|
uf = *ouf;
|
||||||
}
|
}
|
||||||
@@ -1400,10 +1418,10 @@ openURL(char *url, ParsedURL *pu, ParsedURL *current,
|
|||||||
pu->is_nocache = (option->flag & RG_NOCACHE);
|
pu->is_nocache = (option->flag & RG_NOCACHE);
|
||||||
uf.ext = filename_extension(pu->file, 1);
|
uf.ext = filename_extension(pu->file, 1);
|
||||||
|
|
||||||
hr.command = HR_COMMAND_GET;
|
hr->command = HR_COMMAND_GET;
|
||||||
hr.flag = 0;
|
hr->flag = 0;
|
||||||
hr.referer = option->referer;
|
hr->referer = option->referer;
|
||||||
hr.request = request;
|
hr->request = request;
|
||||||
|
|
||||||
switch (pu->scheme) {
|
switch (pu->scheme) {
|
||||||
case SCM_LOCAL:
|
case SCM_LOCAL:
|
||||||
@@ -1501,7 +1519,7 @@ openURL(char *url, ParsedURL *pu, ParsedURL *current,
|
|||||||
if (sock < 0)
|
if (sock < 0)
|
||||||
return uf;
|
return uf;
|
||||||
uf.scheme = SCM_HTTP;
|
uf.scheme = SCM_HTTP;
|
||||||
tmp = HTTPrequest(pu, current, &hr, extra_header);
|
tmp = HTTPrequest(pu, current, hr, extra_header);
|
||||||
write(sock, tmp->ptr, tmp->length);
|
write(sock, tmp->ptr, tmp->length);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -1517,9 +1535,9 @@ openURL(char *url, ParsedURL *pu, ParsedURL *current,
|
|||||||
if (pu->file == NULL)
|
if (pu->file == NULL)
|
||||||
pu->file = allocStr("/", -1);
|
pu->file = allocStr("/", -1);
|
||||||
if (request && request->method == FORM_METHOD_POST && request->body)
|
if (request && request->method == FORM_METHOD_POST && request->body)
|
||||||
hr.command = HR_COMMAND_POST;
|
hr->command = HR_COMMAND_POST;
|
||||||
if (request && request->method == FORM_METHOD_HEAD)
|
if (request && request->method == FORM_METHOD_HEAD)
|
||||||
hr.command = HR_COMMAND_HEAD;
|
hr->command = HR_COMMAND_HEAD;
|
||||||
if (non_null(HTTP_proxy) &&
|
if (non_null(HTTP_proxy) &&
|
||||||
!Do_not_use_proxy &&
|
!Do_not_use_proxy &&
|
||||||
pu->host != NULL && !check_no_proxy(pu->host)) {
|
pu->host != NULL && !check_no_proxy(pu->host)) {
|
||||||
@@ -1554,20 +1572,20 @@ openURL(char *url, ParsedURL *pu, ParsedURL *current,
|
|||||||
#ifdef USE_SSL
|
#ifdef USE_SSL
|
||||||
if (pu->scheme == SCM_HTTPS) {
|
if (pu->scheme == SCM_HTTPS) {
|
||||||
if (*status == HTST_NORMAL) {
|
if (*status == HTST_NORMAL) {
|
||||||
hr.command = HR_COMMAND_CONNECT;
|
hr->command = HR_COMMAND_CONNECT;
|
||||||
tmp = HTTPrequest(pu, current, &hr, NULL);
|
tmp = HTTPrequest(pu, current, hr, NULL);
|
||||||
*status = HTST_CONNECT;
|
*status = HTST_CONNECT;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
hr.flag |= HR_FLAG_LOCAL;
|
hr->flag |= HR_FLAG_LOCAL;
|
||||||
tmp = HTTPrequest(pu, current, &hr, extra_header);
|
tmp = HTTPrequest(pu, current, hr, extra_header);
|
||||||
*status = HTST_NORMAL;
|
*status = HTST_NORMAL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif /* USE_SSL */
|
#endif /* USE_SSL */
|
||||||
{
|
{
|
||||||
tmp = HTTPrequest(pu, current, &hr, extra_header);
|
tmp = HTTPrequest(pu, current, hr, extra_header);
|
||||||
*status = HTST_NORMAL;
|
*status = HTST_NORMAL;
|
||||||
pu->label = save_label;
|
pu->label = save_label;
|
||||||
}
|
}
|
||||||
@@ -1587,8 +1605,8 @@ openURL(char *url, ParsedURL *pu, ParsedURL *current,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* USE_SSL */
|
#endif /* USE_SSL */
|
||||||
hr.flag |= HR_FLAG_LOCAL;
|
hr->flag |= HR_FLAG_LOCAL;
|
||||||
tmp = HTTPrequest(pu, current, &hr, extra_header);
|
tmp = HTTPrequest(pu, current, hr, extra_header);
|
||||||
*status = HTST_NORMAL;
|
*status = HTST_NORMAL;
|
||||||
}
|
}
|
||||||
#ifdef USE_SSL
|
#ifdef USE_SSL
|
||||||
@@ -1598,7 +1616,7 @@ openURL(char *url, ParsedURL *pu, ParsedURL *current,
|
|||||||
SSL_write(sslh, tmp->ptr, tmp->length);
|
SSL_write(sslh, tmp->ptr, tmp->length);
|
||||||
else
|
else
|
||||||
write(sock, tmp->ptr, tmp->length);
|
write(sock, tmp->ptr, tmp->length);
|
||||||
if (hr.command == HR_COMMAND_POST &&
|
if (hr->command == HR_COMMAND_POST &&
|
||||||
request->enctype == FORM_ENCTYPE_MULTIPART) {
|
request->enctype == FORM_ENCTYPE_MULTIPART) {
|
||||||
if (sslh)
|
if (sslh)
|
||||||
SSL_write_from_file(sslh, request->body);
|
SSL_write_from_file(sslh, request->body);
|
||||||
@@ -1618,7 +1636,7 @@ openURL(char *url, ParsedURL *pu, ParsedURL *current,
|
|||||||
fclose(ff);
|
fclose(ff);
|
||||||
}
|
}
|
||||||
#endif /* HTTP_DEBUG */
|
#endif /* HTTP_DEBUG */
|
||||||
if (hr.command == HR_COMMAND_POST &&
|
if (hr->command == HR_COMMAND_POST &&
|
||||||
request->enctype == FORM_ENCTYPE_MULTIPART)
|
request->enctype == FORM_ENCTYPE_MULTIPART)
|
||||||
write_from_file(sock, request->body);
|
write_from_file(sock, request->body);
|
||||||
}
|
}
|
||||||
@@ -1634,7 +1652,7 @@ openURL(char *url, ParsedURL *pu, ParsedURL *current,
|
|||||||
if (sock < 0)
|
if (sock < 0)
|
||||||
return uf;
|
return uf;
|
||||||
uf.scheme = SCM_HTTP;
|
uf.scheme = SCM_HTTP;
|
||||||
tmp = HTTPrequest(pu, current, &hr, extra_header);
|
tmp = HTTPrequest(pu, current, hr, extra_header);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
sock = openSocket(pu->host,
|
sock = openSocket(pu->host,
|
||||||
|
|||||||
Reference in New Issue
Block a user