17dd7cddfSDavid du Colombier #include <u.h> 27dd7cddfSDavid du Colombier #include <libc.h> 37dd7cddfSDavid du Colombier #include <auth.h> 49a747e4fSDavid du Colombier #include <mp.h> 59a747e4fSDavid du Colombier #include <libsec.h> 67dd7cddfSDavid du Colombier #include "httpd.h" 780ee5cbfSDavid du Colombier #include "httpsrv.h" 87dd7cddfSDavid du Colombier 97dd7cddfSDavid du Colombier typedef struct Strings Strings; 107dd7cddfSDavid du Colombier 117dd7cddfSDavid du Colombier struct Strings 127dd7cddfSDavid du Colombier { 137dd7cddfSDavid du Colombier char *s1; 147dd7cddfSDavid du Colombier char *s2; 157dd7cddfSDavid du Colombier }; 167dd7cddfSDavid du Colombier 1780ee5cbfSDavid du Colombier char *netdir; 1880ee5cbfSDavid du Colombier char *webroot; 1980ee5cbfSDavid du Colombier char *HTTPLOG = "httpd/log"; 207dd7cddfSDavid du Colombier 2180ee5cbfSDavid du Colombier static char netdirb[256]; 2280ee5cbfSDavid du Colombier static char *namespace; 2380ee5cbfSDavid du Colombier 247dd7cddfSDavid du Colombier static void becomenone(char*); 257dd7cddfSDavid du Colombier static char *csquery(char*, char*, char*); 267dd7cddfSDavid du Colombier static void dolisten(char*); 2780ee5cbfSDavid du Colombier static int doreq(HConnect*); 2880ee5cbfSDavid du Colombier static int send(HConnect*); 2980ee5cbfSDavid du Colombier static Strings stripmagic(HConnect*, char*); 307dd7cddfSDavid du Colombier static char* stripprefix(char*, char*); 317dd7cddfSDavid du Colombier static char* sysdom(void); 329a747e4fSDavid du Colombier static int notfound(HConnect *c, char *url); 339a747e4fSDavid du Colombier 349a747e4fSDavid du Colombier uchar *certificate; 359a747e4fSDavid du Colombier int certlen; 367dd7cddfSDavid du Colombier 377dd7cddfSDavid du Colombier void 387dd7cddfSDavid du Colombier usage(void) 397dd7cddfSDavid du Colombier { 407dd7cddfSDavid du Colombier fprint(2, "usage: httpd [-a srvaddress] [-d domain] [-n namespace] [-w webroot]\n"); 417dd7cddfSDavid du Colombier exits("usage"); 427dd7cddfSDavid du Colombier } 437dd7cddfSDavid du Colombier 447dd7cddfSDavid du Colombier void 457dd7cddfSDavid du Colombier main(int argc, char **argv) 467dd7cddfSDavid du Colombier { 477dd7cddfSDavid du Colombier char *address; 487dd7cddfSDavid du Colombier 497dd7cddfSDavid du Colombier namespace = nil; 507dd7cddfSDavid du Colombier address = nil; 5180ee5cbfSDavid du Colombier hmydomain = nil; 5280ee5cbfSDavid du Colombier netdir = "/net"; 539a747e4fSDavid du Colombier fmtinstall('D', hdatefmt); 549a747e4fSDavid du Colombier fmtinstall('H', httpfmt); 559a747e4fSDavid du Colombier fmtinstall('U', hurlfmt); 567dd7cddfSDavid du Colombier ARGBEGIN{ 579a747e4fSDavid du Colombier case 'c': 589a747e4fSDavid du Colombier certificate = readcert(ARGF(), &certlen); 599a747e4fSDavid du Colombier if(certificate == nil) 60d9306527SDavid du Colombier sysfatal("reading certificate: %r"); 619a747e4fSDavid du Colombier break; 627dd7cddfSDavid du Colombier case 'n': 637dd7cddfSDavid du Colombier namespace = ARGF(); 647dd7cddfSDavid du Colombier break; 657dd7cddfSDavid du Colombier case 'a': 667dd7cddfSDavid du Colombier address = ARGF(); 677dd7cddfSDavid du Colombier break; 687dd7cddfSDavid du Colombier case 'd': 6980ee5cbfSDavid du Colombier hmydomain = ARGF(); 707dd7cddfSDavid du Colombier break; 717dd7cddfSDavid du Colombier case 'w': 727dd7cddfSDavid du Colombier webroot = ARGF(); 737dd7cddfSDavid du Colombier break; 747dd7cddfSDavid du Colombier default: 757dd7cddfSDavid du Colombier usage(); 767dd7cddfSDavid du Colombier break; 777dd7cddfSDavid du Colombier }ARGEND 787dd7cddfSDavid du Colombier 797dd7cddfSDavid du Colombier if(argc) 807dd7cddfSDavid du Colombier usage(); 817dd7cddfSDavid du Colombier 827dd7cddfSDavid du Colombier if(namespace == nil) 837dd7cddfSDavid du Colombier namespace = "/lib/namespace.httpd"; 847dd7cddfSDavid du Colombier if(address == nil) 859a747e4fSDavid du Colombier address = "*"; 867dd7cddfSDavid du Colombier if(webroot == nil) 877dd7cddfSDavid du Colombier webroot = "/usr/web"; 887dd7cddfSDavid du Colombier else{ 897dd7cddfSDavid du Colombier cleanname(webroot); 907dd7cddfSDavid du Colombier if(webroot[0] != '/') 917dd7cddfSDavid du Colombier webroot = "/usr/web"; 927dd7cddfSDavid du Colombier } 937dd7cddfSDavid du Colombier 947dd7cddfSDavid du Colombier switch(rfork(RFNOTEG|RFPROC|RFFDG|RFNAMEG)) { 957dd7cddfSDavid du Colombier case -1: 967dd7cddfSDavid du Colombier sysfatal("fork"); 977dd7cddfSDavid du Colombier case 0: 987dd7cddfSDavid du Colombier break; 997dd7cddfSDavid du Colombier default: 1007dd7cddfSDavid du Colombier exits(nil); 1017dd7cddfSDavid du Colombier } 1027dd7cddfSDavid du Colombier 1037dd7cddfSDavid du Colombier /* 1047dd7cddfSDavid du Colombier * open all files we might need before castrating namespace 1057dd7cddfSDavid du Colombier */ 1067dd7cddfSDavid du Colombier time(nil); 10780ee5cbfSDavid du Colombier if(hmydomain == nil) 10880ee5cbfSDavid du Colombier hmydomain = sysdom(); 1097dd7cddfSDavid du Colombier syslog(0, HTTPLOG, nil); 1107dd7cddfSDavid du Colombier logall[0] = open("/sys/log/httpd/0", OWRITE); 1117dd7cddfSDavid du Colombier logall[1] = open("/sys/log/httpd/1", OWRITE); 1127dd7cddfSDavid du Colombier redirectinit(); 1137dd7cddfSDavid du Colombier contentinit(); 1147dd7cddfSDavid du Colombier urlinit(); 1157dd7cddfSDavid du Colombier statsinit(); 1167dd7cddfSDavid du Colombier 1177dd7cddfSDavid du Colombier becomenone(namespace); 1189a747e4fSDavid du Colombier dolisten(netmkaddr(address, "tcp", certificate == nil ? "http" : "https")); 1197dd7cddfSDavid du Colombier exits(nil); 1207dd7cddfSDavid du Colombier } 1217dd7cddfSDavid du Colombier 1227dd7cddfSDavid du Colombier static void 1237dd7cddfSDavid du Colombier becomenone(char *namespace) 1247dd7cddfSDavid du Colombier { 1257dd7cddfSDavid du Colombier int fd; 1267dd7cddfSDavid du Colombier 1277dd7cddfSDavid du Colombier fd = open("#c/user", OWRITE); 1287dd7cddfSDavid du Colombier if(fd < 0 || write(fd, "none", strlen("none")) < 0) 1297dd7cddfSDavid du Colombier sysfatal("can't become none"); 1307dd7cddfSDavid du Colombier close(fd); 1317dd7cddfSDavid du Colombier if(newns("none", nil) < 0) 1327dd7cddfSDavid du Colombier sysfatal("can't build normal namespace"); 1337dd7cddfSDavid du Colombier if(addns("none", namespace) < 0) 1347dd7cddfSDavid du Colombier sysfatal("can't build httpd namespace"); 1357dd7cddfSDavid du Colombier } 1367dd7cddfSDavid du Colombier 13780ee5cbfSDavid du Colombier static HConnect* 1387dd7cddfSDavid du Colombier mkconnect(void) 1397dd7cddfSDavid du Colombier { 14080ee5cbfSDavid du Colombier HConnect *c; 1417dd7cddfSDavid du Colombier 14280ee5cbfSDavid du Colombier c = ezalloc(sizeof(HConnect)); 1437dd7cddfSDavid du Colombier c->hpos = c->header; 1447dd7cddfSDavid du Colombier c->hstop = c->header; 14580ee5cbfSDavid du Colombier c->replog = writelog; 1467dd7cddfSDavid du Colombier return c; 1477dd7cddfSDavid du Colombier } 1487dd7cddfSDavid du Colombier 14980ee5cbfSDavid du Colombier static HSPriv* 15080ee5cbfSDavid du Colombier mkhspriv(void) 15180ee5cbfSDavid du Colombier { 15280ee5cbfSDavid du Colombier HSPriv *p; 15380ee5cbfSDavid du Colombier 15480ee5cbfSDavid du Colombier p = ezalloc(sizeof(HSPriv)); 15580ee5cbfSDavid du Colombier return p; 15680ee5cbfSDavid du Colombier } 15780ee5cbfSDavid du Colombier 1587dd7cddfSDavid du Colombier static void 1597dd7cddfSDavid du Colombier dolisten(char *address) 1607dd7cddfSDavid du Colombier { 16180ee5cbfSDavid du Colombier HSPriv *hp; 16280ee5cbfSDavid du Colombier HConnect *c; 1639a747e4fSDavid du Colombier NetConnInfo *nci; 1647dd7cddfSDavid du Colombier char ndir[NETPATHLEN], dir[NETPATHLEN], *p; 16580ee5cbfSDavid du Colombier int ctl, nctl, data, t, ok, spotchk; 1669a747e4fSDavid du Colombier TLSconn conn; 1677dd7cddfSDavid du Colombier 16880ee5cbfSDavid du Colombier spotchk = 0; 1697dd7cddfSDavid du Colombier syslog(0, HTTPLOG, "httpd starting"); 1707dd7cddfSDavid du Colombier ctl = announce(address, dir); 1717dd7cddfSDavid du Colombier if(ctl < 0){ 1727dd7cddfSDavid du Colombier syslog(0, HTTPLOG, "can't announce on %s: %r", address); 1739a747e4fSDavid du Colombier fprint(2, "failed: %d\n", getpid()); 1749a747e4fSDavid du Colombier for(;;)sleep(1000); 1757dd7cddfSDavid du Colombier return; 1767dd7cddfSDavid du Colombier } 17780ee5cbfSDavid du Colombier strcpy(netdirb, dir); 1787dd7cddfSDavid du Colombier p = nil; 1797dd7cddfSDavid du Colombier if(netdir[0] == '/'){ 18080ee5cbfSDavid du Colombier p = strchr(netdirb+1, '/'); 1817dd7cddfSDavid du Colombier if(p != nil) 1827dd7cddfSDavid du Colombier *p = '\0'; 1837dd7cddfSDavid du Colombier } 1847dd7cddfSDavid du Colombier if(p == nil) 18580ee5cbfSDavid du Colombier strcpy(netdirb, "/net"); 18680ee5cbfSDavid du Colombier netdir = netdirb; 1877dd7cddfSDavid du Colombier 1887dd7cddfSDavid du Colombier for(;;){ 1897dd7cddfSDavid du Colombier 1907dd7cddfSDavid du Colombier /* 1917dd7cddfSDavid du Colombier * wait for a call (or an error) 1927dd7cddfSDavid du Colombier */ 1937dd7cddfSDavid du Colombier nctl = listen(dir, ndir); 1947dd7cddfSDavid du Colombier if(nctl < 0){ 1957dd7cddfSDavid du Colombier syslog(0, HTTPLOG, "can't listen on %s: %r", address); 1967dd7cddfSDavid du Colombier syslog(0, HTTPLOG, "ctls = %d", ctl); 1977dd7cddfSDavid du Colombier return; 1987dd7cddfSDavid du Colombier } 1997dd7cddfSDavid du Colombier 2007dd7cddfSDavid du Colombier /* 2017dd7cddfSDavid du Colombier * start a process for the service 2027dd7cddfSDavid du Colombier */ 2037dd7cddfSDavid du Colombier switch(rfork(RFFDG|RFPROC|RFNOWAIT|RFNAMEG)){ 2047dd7cddfSDavid du Colombier case -1: 2057dd7cddfSDavid du Colombier close(nctl); 2067dd7cddfSDavid du Colombier continue; 2077dd7cddfSDavid du Colombier case 0: 2087dd7cddfSDavid du Colombier /* 2097dd7cddfSDavid du Colombier * see if we know the service requested 2107dd7cddfSDavid du Colombier */ 2117dd7cddfSDavid du Colombier data = accept(ctl, ndir); 2129a747e4fSDavid du Colombier if(data >= 0 && certificate != nil){ 2139a747e4fSDavid du Colombier memset(&conn, 0, sizeof(conn)); 2149a747e4fSDavid du Colombier conn.cert = certificate; 2159a747e4fSDavid du Colombier conn.certlen = certlen; 2169a747e4fSDavid du Colombier data = tlsServer(data, &conn); 2179a747e4fSDavid du Colombier } 2187dd7cddfSDavid du Colombier if(data < 0){ 2197dd7cddfSDavid du Colombier syslog(0, HTTPLOG, "can't open %s/data: %r", ndir); 2207dd7cddfSDavid du Colombier exits(nil); 2217dd7cddfSDavid du Colombier } 2227dd7cddfSDavid du Colombier dup(data, 0); 2237dd7cddfSDavid du Colombier dup(data, 1); 2247dd7cddfSDavid du Colombier dup(data, 2); 2257dd7cddfSDavid du Colombier close(data); 2267dd7cddfSDavid du Colombier close(ctl); 2277dd7cddfSDavid du Colombier close(nctl); 2287dd7cddfSDavid du Colombier 2299a747e4fSDavid du Colombier nci = getnetconninfo(ndir, -1); 2307dd7cddfSDavid du Colombier c = mkconnect(); 23180ee5cbfSDavid du Colombier hp = mkhspriv(); 2329a747e4fSDavid du Colombier hp->remotesys = nci->rsys; 2339a747e4fSDavid du Colombier hp->remoteserv = nci->rserv; 23480ee5cbfSDavid du Colombier c->private = hp; 2357dd7cddfSDavid du Colombier 2367dd7cddfSDavid du Colombier hinit(&c->hin, 0, Hread); 2377dd7cddfSDavid du Colombier hinit(&c->hout, 1, Hwrite); 2387dd7cddfSDavid du Colombier 23980ee5cbfSDavid du Colombier /* 24080ee5cbfSDavid du Colombier * serve requests until a magic request. 24180ee5cbfSDavid du Colombier * later requests have to come quickly. 24280ee5cbfSDavid du Colombier * only works for http/1.1 or later. 24380ee5cbfSDavid du Colombier */ 24480ee5cbfSDavid du Colombier for(t = 15*60*1000; ; t = 15*1000){ 24580ee5cbfSDavid du Colombier if(hparsereq(c, t) <= 0) 24680ee5cbfSDavid du Colombier exits(nil); 24780ee5cbfSDavid du Colombier ok = doreq(c); 24880ee5cbfSDavid du Colombier 2499a747e4fSDavid du Colombier hflush(&c->hout); 2509a747e4fSDavid du Colombier 25180ee5cbfSDavid du Colombier if(c->head.closeit || ok < 0) 25280ee5cbfSDavid du Colombier exits(nil); 25380ee5cbfSDavid du Colombier 25480ee5cbfSDavid du Colombier hreqcleanup(c); 25580ee5cbfSDavid du Colombier } 2567dd7cddfSDavid du Colombier 2577dd7cddfSDavid du Colombier exits(nil); 2587dd7cddfSDavid du Colombier default: 2597dd7cddfSDavid du Colombier close(nctl); 2607dd7cddfSDavid du Colombier break; 2617dd7cddfSDavid du Colombier } 2627dd7cddfSDavid du Colombier 2637dd7cddfSDavid du Colombier if(++spotchk > 50){ 2647dd7cddfSDavid du Colombier spotchk = 0; 2657dd7cddfSDavid du Colombier redirectinit(); 2667dd7cddfSDavid du Colombier contentinit(); 2677dd7cddfSDavid du Colombier urlinit(); 2687dd7cddfSDavid du Colombier statsinit(); 2697dd7cddfSDavid du Colombier } 2707dd7cddfSDavid du Colombier } 2717dd7cddfSDavid du Colombier } 2727dd7cddfSDavid du Colombier 2737dd7cddfSDavid du Colombier static int 27480ee5cbfSDavid du Colombier doreq(HConnect *c) 2757dd7cddfSDavid du Colombier { 27680ee5cbfSDavid du Colombier HSPriv *hp; 2777dd7cddfSDavid du Colombier Strings ss; 27880ee5cbfSDavid du Colombier char *magic, *uri, *origuri, *newpath, *hb; 27980ee5cbfSDavid du Colombier char virtualhost[100], logfd0[10], logfd1[10], vers[16]; 28080ee5cbfSDavid du Colombier int n; 2817dd7cddfSDavid du Colombier 2827dd7cddfSDavid du Colombier /* 28380ee5cbfSDavid du Colombier * munge uri for magic 2847dd7cddfSDavid du Colombier */ 28580ee5cbfSDavid du Colombier uri = c->req.uri; 28680ee5cbfSDavid du Colombier ss = stripmagic(c, uri); 2877dd7cddfSDavid du Colombier uri = ss.s1; 2887dd7cddfSDavid du Colombier magic = ss.s2; 2897dd7cddfSDavid du Colombier 29080ee5cbfSDavid du Colombier /* 29180ee5cbfSDavid du Colombier * for magic we exec a new program and serve no more requests 29280ee5cbfSDavid du Colombier */ 29380ee5cbfSDavid du Colombier if(magic != nil && strcmp(magic, "httpd") != 0){ 29480ee5cbfSDavid du Colombier snprint(c->xferbuf, HBufSize, "/bin/ip/httpd/%s", magic); 29580ee5cbfSDavid du Colombier snprint(logfd0, sizeof(logfd0), "%d", logall[0]); 29680ee5cbfSDavid du Colombier snprint(logfd1, sizeof(logfd1), "%d", logall[1]); 29780ee5cbfSDavid du Colombier snprint(vers, sizeof(vers), "HTTP/%d.%d", c->req.vermaj, c->req.vermin); 29880ee5cbfSDavid du Colombier hb = hunload(&c->hin); 2999a747e4fSDavid du Colombier if(hb == nil){ 30080ee5cbfSDavid du Colombier hfail(c, HInternal); 3019a747e4fSDavid du Colombier return -1; 3029a747e4fSDavid du Colombier } 30380ee5cbfSDavid du Colombier hp = c->private; 30480ee5cbfSDavid du Colombier execl(c->xferbuf, magic, "-d", hmydomain, "-w", webroot, "-r", hp->remotesys, "-N", netdir, "-b", hb, 30580ee5cbfSDavid du Colombier "-L", logfd0, logfd1, "-R", c->header, 30680ee5cbfSDavid du Colombier c->req.meth, vers, uri, c->req.search, nil); 30780ee5cbfSDavid du Colombier logit(c, "no magic %s uri %s", magic, uri); 30880ee5cbfSDavid du Colombier hfail(c, HNotFound, uri); 30980ee5cbfSDavid du Colombier return -1; 31080ee5cbfSDavid du Colombier } 3117dd7cddfSDavid du Colombier 3127dd7cddfSDavid du Colombier /* 3137dd7cddfSDavid du Colombier * normal case is just file transfer 3147dd7cddfSDavid du Colombier */ 3157dd7cddfSDavid du Colombier origuri = uri; 31680ee5cbfSDavid du Colombier if(hparseheaders(c, 15*60*1000) < 0) 31780ee5cbfSDavid du Colombier exits("failed"); 3187dd7cddfSDavid du Colombier if(!http11(c) && !c->head.persist) 3197dd7cddfSDavid du Colombier c->head.closeit = 1; 3207dd7cddfSDavid du Colombier 3217dd7cddfSDavid du Colombier if(origuri[0]=='/' && origuri[1]=='~'){ 3227dd7cddfSDavid du Colombier n = strlen(origuri) + 4 + UTFmax; 32380ee5cbfSDavid du Colombier newpath = halloc(c, n); 3247dd7cddfSDavid du Colombier snprint(newpath, n, "/who/%s", origuri+2); 3257dd7cddfSDavid du Colombier c->req.uri = newpath; 3267dd7cddfSDavid du Colombier uri = newpath; 3277dd7cddfSDavid du Colombier }else if(origuri[0]=='/' && origuri[1]==0){ 3287dd7cddfSDavid du Colombier snprint(virtualhost, sizeof virtualhost, "http://%s/", c->head.host); 32980ee5cbfSDavid du Colombier uri = redirect(c, virtualhost); 3307dd7cddfSDavid du Colombier if(uri == nil) 33180ee5cbfSDavid du Colombier uri = redirect(c, origuri); 3327dd7cddfSDavid du Colombier }else 33380ee5cbfSDavid du Colombier uri = redirect(c, origuri); 3347dd7cddfSDavid du Colombier 33580ee5cbfSDavid du Colombier if(uri != nil) 33680ee5cbfSDavid du Colombier return hmoved(c, uri); 33780ee5cbfSDavid du Colombier return send(c); 3387dd7cddfSDavid du Colombier } 3397dd7cddfSDavid du Colombier 3407dd7cddfSDavid du Colombier static int 34180ee5cbfSDavid du Colombier send(HConnect *c) 3427dd7cddfSDavid du Colombier { 3439a747e4fSDavid du Colombier Dir *dir; 344*fe853e23SDavid du Colombier char *w, *w2, *p, *masque; 3457dd7cddfSDavid du Colombier int fd, fd1, n, force301, ok; 3467dd7cddfSDavid du Colombier 3477dd7cddfSDavid du Colombier if(c->req.search) 34880ee5cbfSDavid du Colombier return hfail(c, HNoSearch, c->req.uri); 3497dd7cddfSDavid du Colombier if(strcmp(c->req.meth, "GET") != 0 && strcmp(c->req.meth, "HEAD") != 0) 35080ee5cbfSDavid du Colombier return hunallowed(c, "GET, HEAD"); 3517dd7cddfSDavid du Colombier if(c->head.expectother || c->head.expectcont) 35280ee5cbfSDavid du Colombier return hfail(c, HExpectFail); 3537dd7cddfSDavid du Colombier 3549a747e4fSDavid du Colombier masque = masquerade(c->head.host); 3557dd7cddfSDavid du Colombier 3567dd7cddfSDavid du Colombier /* 3577dd7cddfSDavid du Colombier * check for directory/file mismatch with trailing /, 3587dd7cddfSDavid du Colombier * and send any redirections. 3597dd7cddfSDavid du Colombier */ 3609a747e4fSDavid du Colombier n = strlen(webroot) + strlen(masque) + strlen(c->req.uri) + 3619a747e4fSDavid du Colombier STRLEN("/index.html") + STRLEN("/.httplogin") + 1; 36280ee5cbfSDavid du Colombier w = halloc(c, n); 3637dd7cddfSDavid du Colombier strcpy(w, webroot); 3649a747e4fSDavid du Colombier strcat(w, masque); 3659a747e4fSDavid du Colombier strcat(w, c->req.uri); 3663ff48bf5SDavid du Colombier 3673ff48bf5SDavid du Colombier /* 368*fe853e23SDavid du Colombier * favicon can be overridden by hostname.ico 369*fe853e23SDavid du Colombier */ 370*fe853e23SDavid du Colombier if(strcmp(c->req.uri, "/favicon.ico") == 0){ 371*fe853e23SDavid du Colombier w2 = halloc(c, n+strlen(c->head.host)+2); 372*fe853e23SDavid du Colombier strcpy(w2, webroot); 373*fe853e23SDavid du Colombier strcat(w2, masque); 374*fe853e23SDavid du Colombier strcat(w2, "/"); 375*fe853e23SDavid du Colombier strcat(w2, c->head.host); 376*fe853e23SDavid du Colombier strcat(w2, ".ico"); 377*fe853e23SDavid du Colombier if(access(w2, AREAD)==0) 378*fe853e23SDavid du Colombier w = w2; 379*fe853e23SDavid du Colombier } 380*fe853e23SDavid du Colombier 381*fe853e23SDavid du Colombier /* 3823ff48bf5SDavid du Colombier * don't show the contents of .httplogin 3833ff48bf5SDavid du Colombier */ 3843ff48bf5SDavid du Colombier n = strlen(w); 3853ff48bf5SDavid du Colombier if(strcmp(w+n-STRLEN(".httplogin"), ".httplogin") == 0) 3863ff48bf5SDavid du Colombier return notfound(c, c->req.uri); 3873ff48bf5SDavid du Colombier 3889a747e4fSDavid du Colombier fd = open(w, OREAD); 3899a747e4fSDavid du Colombier if(fd < 0 && strlen(masque)>0 && strncmp(c->req.uri, masque, strlen(masque)) == 0){ 3909a747e4fSDavid du Colombier // may be a URI from before virtual hosts; try again without masque 3919a747e4fSDavid du Colombier strcpy(w, webroot); 3927dd7cddfSDavid du Colombier strcat(w, c->req.uri); 3937dd7cddfSDavid du Colombier fd = open(w, OREAD); 3949a747e4fSDavid du Colombier } 3957dd7cddfSDavid du Colombier if(fd < 0) 3967dd7cddfSDavid du Colombier return notfound(c, c->req.uri); 3979a747e4fSDavid du Colombier dir = dirfstat(fd); 3989a747e4fSDavid du Colombier if(dir == nil){ 3997dd7cddfSDavid du Colombier close(fd); 40080ee5cbfSDavid du Colombier return hfail(c, HInternal); 4017dd7cddfSDavid du Colombier } 4027dd7cddfSDavid du Colombier p = strchr(w, '\0'); 4039a747e4fSDavid du Colombier if(dir->mode & DMDIR){ 4049a747e4fSDavid du Colombier free(dir); 4057dd7cddfSDavid du Colombier if(p > w && p[-1] == '/'){ 4067dd7cddfSDavid du Colombier strcat(w, "index.html"); 4077dd7cddfSDavid du Colombier force301 = 0; 4087dd7cddfSDavid du Colombier }else{ 4097dd7cddfSDavid du Colombier strcat(w, "/index.html"); 4107dd7cddfSDavid du Colombier force301 = 1; 4117dd7cddfSDavid du Colombier } 4127dd7cddfSDavid du Colombier fd1 = open(w, OREAD); 4137dd7cddfSDavid du Colombier if(fd1 < 0){ 4147dd7cddfSDavid du Colombier close(fd); 4157dd7cddfSDavid du Colombier return notfound(c, c->req.uri); 4167dd7cddfSDavid du Colombier } 4179a747e4fSDavid du Colombier c->req.uri = w + strlen(webroot) + strlen(masque); 4187dd7cddfSDavid du Colombier if(force301 && c->req.vermaj){ 4197dd7cddfSDavid du Colombier close(fd); 4207dd7cddfSDavid du Colombier close(fd1); 42180ee5cbfSDavid du Colombier return hmoved(c, c->req.uri); 4227dd7cddfSDavid du Colombier } 4237dd7cddfSDavid du Colombier close(fd); 4247dd7cddfSDavid du Colombier fd = fd1; 4259a747e4fSDavid du Colombier dir = dirfstat(fd); 4269a747e4fSDavid du Colombier if(dir == nil){ 4277dd7cddfSDavid du Colombier close(fd); 42880ee5cbfSDavid du Colombier return hfail(c, HInternal); 4297dd7cddfSDavid du Colombier } 4307dd7cddfSDavid du Colombier }else if(p > w && p[-1] == '/'){ 4319a747e4fSDavid du Colombier free(dir); 4327dd7cddfSDavid du Colombier close(fd); 4337dd7cddfSDavid du Colombier *strrchr(c->req.uri, '/') = '\0'; 43480ee5cbfSDavid du Colombier return hmoved(c, c->req.uri); 4357dd7cddfSDavid du Colombier } 4367dd7cddfSDavid du Colombier 4379a747e4fSDavid du Colombier ok = authorize(c, w); 4389a747e4fSDavid du Colombier if(ok <= 0){ 4399a747e4fSDavid du Colombier free(dir); 4409a747e4fSDavid du Colombier close(fd); 4419a747e4fSDavid du Colombier return ok; 4429a747e4fSDavid du Colombier } 4439a747e4fSDavid du Colombier 4449a747e4fSDavid du Colombier return sendfd(c, fd, dir, nil, nil); 4457dd7cddfSDavid du Colombier } 4467dd7cddfSDavid du Colombier 4477dd7cddfSDavid du Colombier static Strings 44880ee5cbfSDavid du Colombier stripmagic(HConnect *hc, char *uri) 4497dd7cddfSDavid du Colombier { 4507dd7cddfSDavid du Colombier Strings ss; 4517dd7cddfSDavid du Colombier char *newuri, *prog, *s; 4527dd7cddfSDavid du Colombier 4537dd7cddfSDavid du Colombier prog = stripprefix("/magic/", uri); 4547dd7cddfSDavid du Colombier if(prog == nil){ 4557dd7cddfSDavid du Colombier ss.s1 = uri; 4567dd7cddfSDavid du Colombier ss.s2 = nil; 4577dd7cddfSDavid du Colombier return ss; 4587dd7cddfSDavid du Colombier } 4597dd7cddfSDavid du Colombier 4607dd7cddfSDavid du Colombier s = strchr(prog, '/'); 4617dd7cddfSDavid du Colombier if(s == nil) 4627dd7cddfSDavid du Colombier newuri = ""; 4637dd7cddfSDavid du Colombier else{ 46480ee5cbfSDavid du Colombier newuri = hstrdup(hc, s); 4657dd7cddfSDavid du Colombier *s = 0; 4667dd7cddfSDavid du Colombier s = strrchr(s, '/'); 4677dd7cddfSDavid du Colombier if(s != nil && s[1] == 0) 4687dd7cddfSDavid du Colombier *s = 0; 4697dd7cddfSDavid du Colombier } 4707dd7cddfSDavid du Colombier ss.s1 = newuri; 4717dd7cddfSDavid du Colombier ss.s2 = prog; 4727dd7cddfSDavid du Colombier return ss; 4737dd7cddfSDavid du Colombier } 4747dd7cddfSDavid du Colombier 4757dd7cddfSDavid du Colombier static char* 4767dd7cddfSDavid du Colombier stripprefix(char *pre, char *str) 4777dd7cddfSDavid du Colombier { 4787dd7cddfSDavid du Colombier while(*pre) 4797dd7cddfSDavid du Colombier if(*str++ != *pre++) 4807dd7cddfSDavid du Colombier return nil; 4817dd7cddfSDavid du Colombier return str; 4827dd7cddfSDavid du Colombier } 4837dd7cddfSDavid du Colombier 4849a747e4fSDavid du Colombier /* 4859a747e4fSDavid du Colombier * couldn't open a file 4869a747e4fSDavid du Colombier * figure out why and return and error message 4879a747e4fSDavid du Colombier */ 4889a747e4fSDavid du Colombier static int 4899a747e4fSDavid du Colombier notfound(HConnect *c, char *url) 4909a747e4fSDavid du Colombier { 4919a747e4fSDavid du Colombier c->xferbuf[0] = 0; 4929a747e4fSDavid du Colombier errstr(c->xferbuf, sizeof c->xferbuf); 4939a747e4fSDavid du Colombier if(strstr(c->xferbuf, "file does not exist") != nil) 4949a747e4fSDavid du Colombier return hfail(c, HNotFound, url); 4959a747e4fSDavid du Colombier if(strstr(c->xferbuf, "permission denied") != nil) 4969a747e4fSDavid du Colombier return hfail(c, HUnauth, url); 4979a747e4fSDavid du Colombier return hfail(c, HNotFound, url); 4989a747e4fSDavid du Colombier } 4999a747e4fSDavid du Colombier 5007dd7cddfSDavid du Colombier static char* 5017dd7cddfSDavid du Colombier sysdom(void) 5027dd7cddfSDavid du Colombier { 5037dd7cddfSDavid du Colombier char *dn; 5047dd7cddfSDavid du Colombier 5057dd7cddfSDavid du Colombier dn = csquery("sys" , sysname(), "dom"); 5067dd7cddfSDavid du Colombier if(dn == nil) 5077dd7cddfSDavid du Colombier dn = "who cares"; 5087dd7cddfSDavid du Colombier return dn; 5097dd7cddfSDavid du Colombier } 5107dd7cddfSDavid du Colombier 5117dd7cddfSDavid du Colombier /* 5127dd7cddfSDavid du Colombier * query the connection server 5137dd7cddfSDavid du Colombier */ 5147dd7cddfSDavid du Colombier static char* 5157dd7cddfSDavid du Colombier csquery(char *attr, char *val, char *rattr) 5167dd7cddfSDavid du Colombier { 5177dd7cddfSDavid du Colombier char token[64+4]; 5187dd7cddfSDavid du Colombier char buf[256], *p, *sp; 5197dd7cddfSDavid du Colombier int fd, n; 5207dd7cddfSDavid du Colombier 5217dd7cddfSDavid du Colombier if(val == nil || val[0] == 0) 5227dd7cddfSDavid du Colombier return nil; 5237dd7cddfSDavid du Colombier snprint(buf, sizeof(buf), "%s/cs", netdir); 5247dd7cddfSDavid du Colombier fd = open(buf, ORDWR); 5257dd7cddfSDavid du Colombier if(fd < 0) 5267dd7cddfSDavid du Colombier return nil; 5277dd7cddfSDavid du Colombier fprint(fd, "!%s=%s", attr, val); 5287dd7cddfSDavid du Colombier seek(fd, 0, 0); 5297dd7cddfSDavid du Colombier snprint(token, sizeof(token), "%s=", rattr); 5307dd7cddfSDavid du Colombier for(;;){ 5317dd7cddfSDavid du Colombier n = read(fd, buf, sizeof(buf)-1); 5327dd7cddfSDavid du Colombier if(n <= 0) 5337dd7cddfSDavid du Colombier break; 5347dd7cddfSDavid du Colombier buf[n] = 0; 5357dd7cddfSDavid du Colombier p = strstr(buf, token); 5367dd7cddfSDavid du Colombier if(p != nil && (p == buf || *(p-1) == 0)){ 5377dd7cddfSDavid du Colombier close(fd); 5387dd7cddfSDavid du Colombier sp = strchr(p, ' '); 5397dd7cddfSDavid du Colombier if(sp) 5407dd7cddfSDavid du Colombier *sp = 0; 5417dd7cddfSDavid du Colombier p = strchr(p, '='); 5427dd7cddfSDavid du Colombier if(p == nil) 5437dd7cddfSDavid du Colombier return nil; 5447dd7cddfSDavid du Colombier return estrdup(p+1); 5457dd7cddfSDavid du Colombier } 5467dd7cddfSDavid du Colombier } 5477dd7cddfSDavid du Colombier close(fd); 5487dd7cddfSDavid du Colombier return nil; 5497dd7cddfSDavid du Colombier } 550