}
static int
-tlswrap(int fd)
+tlswrap(int fd, char *servername)
{
TLSconn conn;
memset(&conn, 0, sizeof(conn));
if(debug)
conn.trace = tlstrace;
+ if(servername != nil)
+ conn.serverName = smprint("%N", servername);
if((fd = tlsClient(fd, &conn)) < 0){
if(debug) fprint(2, "tlsClient: %r\n");
- return -1;
}
free(conn.cert);
free(conn.sessionID);
+ free(conn.serverName);
return fd;
}
static Hconn*
-hdial(Url *u)
+hdial(Url *u, int cached)
{
char addr[128];
Hconn *h, *p;
snprint(addr, sizeof(addr), "tcp!%s!%s", u->host, u->port ? u->port : u->scheme);
- qlock(&hpool);
- for(p = nil, h = hpool.head; h; p = h, h = h->next){
- if(strcmp(h->addr, addr) == 0){
- if(p)
- p->next = h->next;
- else
- hpool.head = h->next;
- h->next = nil;
- qunlock(&hpool);
- return h;
+ if(cached){
+ qlock(&hpool);
+ for(p = nil, h = hpool.head; h; p = h, h = h->next){
+ if(strcmp(h->addr, addr) == 0){
+ if(p)
+ p->next = h->next;
+ else
+ hpool.head = h->next;
+ h->next = nil;
+ qunlock(&hpool);
+ return h;
+ }
}
+ hpool.active++;
+ qunlock(&hpool);
}
- hpool.active++;
- qunlock(&hpool);
if(debug)
fprint(2, "hdial [%d] %s\n", hpool.active, addr);
snprint(addr, sizeof(addr), "tcp!%s!%s",
proxy->host, proxy->port ? proxy->port : proxy->scheme);
- if((fd = dial(addr, 0, 0, &ctl)) >= 0){
- if(proxy){
- if(strcmp(proxy->scheme, "https") == 0)
- fd = tlswrap(fd);
- } else {
- if(strcmp(u->scheme, "https") == 0)
- fd = tlswrap(fd);
- }
+ if((fd = dial(addr, 0, 0, &ctl)) < 0)
+ return nil;
+
+ if(proxy){
+ if(strcmp(proxy->scheme, "https") == 0)
+ fd = tlswrap(fd, proxy->host);
+ } else {
+ if(strcmp(u->scheme, "https") == 0)
+ fd = tlswrap(fd, u->host);
}
if(fd < 0){
close(ctl);
h->time = 0;
h->cancel = 0;
h->tunnel = 0;
- h->keep = 1;
+ h->keep = cached;
h->len = 0;
h->fd = fd;
h->ctl = ctl;
/* free the tail */
hcloseall(x);
} while(i);
- exits(0);
+ exits(nil);
}
return;
}
}
}
+static int
+hauthgetkey(char *params)
+{
+ if(debug)
+ fprint(2, "hauthgetkey %s\n", params);
+ werrstr("needkey %s", params);
+ return -1;
+}
+
int
authenticate(Url *u, Url *ru, char *method, char *s)
{
- char *user, *pass, *realm, *nonce, *opaque, *x;
+ char oerr[ERRMAX], *user, *pass, *realm, *nonce, *opaque, *x;
Hauth *a;
Fmt fmt;
int n;
+ snprint(oerr, sizeof(oerr), "authentification failed");
+ errstr(oerr, sizeof(oerr));
+
user = u->user;
pass = u->pass;
realm = nonce = opaque = nil;
fmtprint(&fmt, " user=%q", user);
if((s = fmtstrflush(&fmt)) == nil)
return -1;
- up = auth_getuserpasswd(nil, "proto=pass service=http server=%q%s", u->host, s);
+ up = auth_getuserpasswd(hauthgetkey,
+ "proto=pass service=http server=%q%s", u->host, s);
free(s);
if(up == nil)
return -1;
if((s = fmtstrflush(&fmt)) == nil)
return -1;
nchal = snprint(chal, sizeof(chal), "%s %s %U", nonce, method, ru);
- n = auth_respond(chal, nchal, ouser, sizeof ouser, resp, sizeof resp, nil,
+ n = auth_respond(chal, nchal, ouser, sizeof ouser, resp, sizeof resp, hauthgetkey,
"proto=httpdigest role=client server=%q%s", u->host, s);
memset(chal, 0, sizeof(chal));
free(s);
fmtprint(&fmt, "Digest ");
fmtprint(&fmt, "username=\"%s\", ", ouser);
fmtprint(&fmt, "realm=\"%s\", ", realm);
- fmtprint(&fmt, "host=\"%H\", ", u->host);
+ fmtprint(&fmt, "host=\"%N\", ", u->host);
fmtprint(&fmt, "uri=\"%U\", ", ru);
fmtprint(&fmt, "nonce=\"%s\", ", nonce);
fmtprint(&fmt, "response=\"%s\"", resp);
free(s);
return -1;
}
+
a = emalloc(sizeof(*a));
a->url = u;
a->auth = s;
hauth = a;
qunlock(&authlk);
+ errstr(oerr, sizeof(oerr));
return 0;
}
static void
catch(void *, char *msg)
{
- if(strstr("alarm", msg) || strstr("die", msg))
+ if(strstr("alarm", msg) != nil)
noted(NCONT);
else
noted(NDFLT);
void
http(char *m, Url *u, Key *shdr, Buq *qbody, Buq *qpost)
{
- int i, l, n, try, pid, fd, cfd, needlength, chunked, retry, nobody;
+ int i, l, n, try, pid, fd, cfd, needlength, chunked, retry, nobody, badauth;
char *s, *x, buf[8192+2], status[256], method[16], *host;
vlong length, offset;
Url ru, tu, *nu;
pid = 0;
host = nil;
needlength = 0;
+ badauth = 0;
for(try = 0; try < 12; try++){
strcpy(status, "0 No status");
if(u == nil || (strcmp(u->scheme, "http") && strcmp(u->scheme, "https"))){
/* http requires ascii encoding of host */
free(host);
- host = smprint("%H", u->host);
+ host = smprint("%N", u->host);
if(proxy && strcmp(u->scheme, "https") != 0){
ru = *u;
}
if(h == nil){
alarm(timeout);
- if((h = hdial(u)) == nil)
+ if((h = hdial(u, qpost!=nil)) == nil)
break;
}
if(h->tunnel){
}else
h->keep = 0;
if(pid == 0)
- exits(0);
+ exits(nil);
}
/* no timeout when posting */
alarm(0);
goto Error;
freeurl(u);
u = nu;
- if(0){
+ if(0){
case 401: /* Unauthorized */
- if(x = lookkey(shdr, "Authorization"))
+ if(x = lookkey(shdr, "Authorization")){
flushauth(nil, x);
- if(hauthenticate(u, &ru, method, "WWW-Authenticate", rhdr) < 0)
- goto Error;
+ if(badauth++)
+ goto Error;
}
- if(0){
+ if(hauthenticate(u, &ru, method, "WWW-Authenticate", rhdr) < 0){
+ Autherror:
+ h->cancel = 1;
+ rerrstr(buf, sizeof(buf));
+ buclose(qbody, buf);
+ buclose(qpost, buf);
+ break;
+ }
+ }
+ if(0){
case 407: /* Proxy Auth */
if(proxy == nil)
goto Error;
- if(x = lookkey(shdr, "Proxy-Authorization"))
+ if(x = lookkey(shdr, "Proxy-Authorization")){
flushauth(proxy, x);
- if(hauthenticate(u, &ru, method, "Proxy-Authenticate", rhdr) < 0)
- goto Error;
+ if(badauth++)
+ goto Error;
}
+ if(hauthenticate(proxy, proxy, method, "Proxy-Authenticate", rhdr) < 0)
+ goto Autherror;
+ }
case 0: /* No status */
if(qpost && fd < 0){
if(i > 0)
* then the proxy server has established the connection.
*/
if(h->tunnel && !retry && (i/100) == 2){
- if((h->fd = tlswrap(h->fd)) < 0)
+ if((h->fd = tlswrap(h->fd, host)) < 0)
break;
/* proceed to the original request */
shdr = k->next;
free(k);
}
- exits(0);
+ exits(nil);
}