]> git.lizzy.rs Git - plan9front.git/blobdiff - sys/src/cmd/webfs/http.c
merge
[plan9front.git] / sys / src / cmd / webfs / http.c
index 96a884c0c07c183980fdf2b9bce2bfbc56fadb84..ef53e4e8ae414ffc8e676e5fc1850300272a76d0 100644 (file)
@@ -73,24 +73,26 @@ tlstrace(char *fmt, ...)
 }
 
 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;
@@ -98,20 +100,22 @@ hdial(Url *u)
 
        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);
@@ -120,14 +124,15 @@ hdial(Url *u)
                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);
@@ -139,7 +144,7 @@ hdial(Url *u)
        h->time = 0;
        h->cancel = 0;
        h->tunnel = 0;
-       h->keep = 1;
+       h->keep = cached;
        h->len = 0;
        h->fd = fd;
        h->ctl = ctl;
@@ -237,7 +242,7 @@ hclose(Hconn *h)
                                        /* free the tail */
                                        hcloseall(x);
                                } while(i);
-                               exits(0);
+                               exits(nil);
                        }
                        return;
                }
@@ -345,14 +350,26 @@ hline(Hconn *h, char *data, int len, int cont)
        }
 }
 
+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;
@@ -372,7 +389,8 @@ authenticate(Url *u, Url *ru, char *method, char *s)
                                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;
@@ -415,7 +433,7 @@ authenticate(Url *u, Url *ru, char *method, char *s)
                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);
@@ -425,7 +443,7 @@ authenticate(Url *u, Url *ru, char *method, char *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);
@@ -442,6 +460,7 @@ authenticate(Url *u, Url *ru, char *method, char *s)
                free(s);
                return -1;
        }
+
        a = emalloc(sizeof(*a));
        a->url = u;
        a->auth = s;
@@ -450,6 +469,7 @@ authenticate(Url *u, Url *ru, char *method, char *s)
        hauth = a;
        qunlock(&authlk);
 
+       errstr(oerr, sizeof(oerr));
        return 0;
 }
 
@@ -489,7 +509,7 @@ Again:
 static void
 catch(void *, char *msg)
 {
-       if(strstr("alarm", msg) || strstr("die", msg))
+       if(strstr("alarm", msg) != nil)
                noted(NCONT);
        else
                noted(NDFLT);
@@ -500,7 +520,7 @@ catch(void *, char *msg)
 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;
@@ -542,6 +562,7 @@ http(char *m, Url *u, Key *shdr, Buq *qbody, Buq *qpost)
        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"))){
@@ -605,7 +626,7 @@ http(char *m, Url *u, Key *shdr, Buq *qbody, Buq *qpost)
 
                /* 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;
@@ -624,7 +645,7 @@ http(char *m, Url *u, Key *shdr, Buq *qbody, Buq *qpost)
                }
                if(h == nil){
                        alarm(timeout);
-                       if((h = hdial(u)) == nil)
+                       if((h = hdial(u, qpost!=nil)) == nil)
                                break;
                }
                if(h->tunnel){
@@ -707,7 +728,7 @@ http(char *m, Url *u, Key *shdr, Buq *qbody, Buq *qpost)
                                }else
                                        h->keep = 0;
                                if(pid == 0)
-                                       exits(0);
+                                       exits(nil);
                        }
                        /* no timeout when posting */
                        alarm(0);
@@ -844,22 +865,34 @@ http(char *m, Url *u, Key *shdr, Buq *qbody, Buq *qpost)
                                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)
@@ -905,7 +938,7 @@ http(char *m, Url *u, Key *shdr, Buq *qbody, Buq *qpost)
                 * 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 */
@@ -997,5 +1030,5 @@ http(char *m, Url *u, Key *shdr, Buq *qbody, Buq *qpost)
                shdr = k->next;
                free(k);
        }
-       exits(0);
+       exits(nil);
 }