19a747e4fSDavid du Colombier #include <u.h>
29a747e4fSDavid du Colombier #include <libc.h>
39a747e4fSDavid du Colombier #include <auth.h>
49a747e4fSDavid du Colombier #include "httpd.h"
59a747e4fSDavid du Colombier #include "httpsrv.h"
69a747e4fSDavid du Colombier
79a747e4fSDavid du Colombier static char* readfile(char*);
89a747e4fSDavid du Colombier
99a747e4fSDavid du Colombier /*
10*236eb0b0SDavid du Colombier * these should be done better; see the response codes in /lib/rfc/rfc2616 for
119a747e4fSDavid du Colombier * more info on what should be included.
129a747e4fSDavid du Colombier */
139a747e4fSDavid du Colombier #define UNAUTHED "You are not authorized to see this area.\n"
149a747e4fSDavid du Colombier
159a747e4fSDavid du Colombier /*
16*236eb0b0SDavid du Colombier * check for authorization for some parts of the server tree.
179a747e4fSDavid du Colombier * the user name supplied with the authorization request is ignored;
189a747e4fSDavid du Colombier * instead, we authenticate as the realm's user.
199a747e4fSDavid du Colombier *
209a747e4fSDavid du Colombier * authorization should be done before opening any files so that
219a747e4fSDavid du Colombier * unauthorized users don't get to validate file names.
229a747e4fSDavid du Colombier *
239a747e4fSDavid du Colombier * returns 1 if authorized, 0 if unauthorized, -1 for io failure.
249a747e4fSDavid du Colombier */
259a747e4fSDavid du Colombier int
authorize(HConnect * c,char * file)269a747e4fSDavid du Colombier authorize(HConnect *c, char *file)
279a747e4fSDavid du Colombier {
289a747e4fSDavid du Colombier char *p, *p0;
299a747e4fSDavid du Colombier Hio *hout;
309a747e4fSDavid du Colombier char *buf;
319a747e4fSDavid du Colombier int i, n;
329a747e4fSDavid du Colombier char *t[257];
339a747e4fSDavid du Colombier
349a747e4fSDavid du Colombier p0 = halloc(c, strlen(file)+STRLEN("/.httplogin")+1);
359a747e4fSDavid du Colombier strcpy(p0, file);
369a747e4fSDavid du Colombier for(;;){
379a747e4fSDavid du Colombier p = strrchr(p0, '/');
389a747e4fSDavid du Colombier if(p == nil)
399a747e4fSDavid du Colombier return hfail(c, HInternal);
409a747e4fSDavid du Colombier if(*(p+1) != 0)
419a747e4fSDavid du Colombier break;
429a747e4fSDavid du Colombier
439a747e4fSDavid du Colombier /* ignore trailing '/'s */
449a747e4fSDavid du Colombier *p = 0;
459a747e4fSDavid du Colombier }
469a747e4fSDavid du Colombier strcpy(p, "/.httplogin");
479a747e4fSDavid du Colombier
489a747e4fSDavid du Colombier buf = readfile(p0);
499a747e4fSDavid du Colombier if(buf == nil){
509a747e4fSDavid du Colombier return 1;
519a747e4fSDavid du Colombier }
529a747e4fSDavid du Colombier n = tokenize(buf, t, nelem(t));
539a747e4fSDavid du Colombier
549a747e4fSDavid du Colombier if(c->head.authuser != nil && c->head.authpass != 0){
559a747e4fSDavid du Colombier for(i = 1; i+1 < n; i += 2){
569a747e4fSDavid du Colombier if(strcmp(t[i], c->head.authuser) == 0
579a747e4fSDavid du Colombier && strcmp(t[i+1], c->head.authpass) == 0){
589a747e4fSDavid du Colombier free(buf);
599a747e4fSDavid du Colombier return 1;
609a747e4fSDavid du Colombier }
619a747e4fSDavid du Colombier }
629a747e4fSDavid du Colombier }
639a747e4fSDavid du Colombier
649a747e4fSDavid du Colombier hout = &c->hout;
659a747e4fSDavid du Colombier hprint(hout, "%s 401 Unauthorized\r\n", hversion);
669a747e4fSDavid du Colombier hprint(hout, "Server: Plan9\r\n");
679a747e4fSDavid du Colombier hprint(hout, "Date: %D\r\n", time(nil));
689a747e4fSDavid du Colombier hprint(hout, "WWW-Authenticate: Basic realm=\"%s\"\r\n", t[0]);
699a747e4fSDavid du Colombier hprint(hout, "Content-Type: text/html\r\n");
709a747e4fSDavid du Colombier hprint(hout, "Content-Length: %d\r\n", STRLEN(UNAUTHED));
719a747e4fSDavid du Colombier if(c->head.closeit)
729a747e4fSDavid du Colombier hprint(hout, "Connection: close\r\n");
739a747e4fSDavid du Colombier else if(!http11(c))
749a747e4fSDavid du Colombier hprint(hout, "Connection: Keep-Alive\r\n");
759a747e4fSDavid du Colombier hprint(hout, "\r\n");
769a747e4fSDavid du Colombier if(strcmp(c->req.meth, "HEAD") != 0)
779a747e4fSDavid du Colombier hprint(hout, "%s", UNAUTHED);
789a747e4fSDavid du Colombier writelog(c, "Reply: 401 Unauthorized\n");
799a747e4fSDavid du Colombier free(buf);
809a747e4fSDavid du Colombier return hflush(hout);
819a747e4fSDavid du Colombier }
829a747e4fSDavid du Colombier
839a747e4fSDavid du Colombier static char*
readfile(char * file)849a747e4fSDavid du Colombier readfile(char *file)
859a747e4fSDavid du Colombier {
869a747e4fSDavid du Colombier Dir *d;
879a747e4fSDavid du Colombier int fd;
889a747e4fSDavid du Colombier char *buf;
899a747e4fSDavid du Colombier int n, len;
909a747e4fSDavid du Colombier
919a747e4fSDavid du Colombier fd = open(file, OREAD);
929a747e4fSDavid du Colombier if(fd < 0)
939a747e4fSDavid du Colombier return nil;
949a747e4fSDavid du Colombier d = dirfstat(fd);
959a747e4fSDavid du Colombier if(d == nil){ /* shouldn't happen */
969a747e4fSDavid du Colombier close(fd);
979a747e4fSDavid du Colombier return nil;
989a747e4fSDavid du Colombier }
999a747e4fSDavid du Colombier len = d->length;
1009a747e4fSDavid du Colombier free(d);
1019a747e4fSDavid du Colombier
1029a747e4fSDavid du Colombier buf = malloc(len+1);
1039a747e4fSDavid du Colombier if(buf == 0){
1049a747e4fSDavid du Colombier close(fd);
1059a747e4fSDavid du Colombier return nil;
1069a747e4fSDavid du Colombier }
1079a747e4fSDavid du Colombier
1089a747e4fSDavid du Colombier n = readn(fd, buf, len);
1099a747e4fSDavid du Colombier close(fd);
1109a747e4fSDavid du Colombier if(n <= 0){
1119a747e4fSDavid du Colombier free(buf);
1129a747e4fSDavid du Colombier return nil;
1139a747e4fSDavid du Colombier }
11423adc3a5SDavid du Colombier buf[n] = '\0';
1159a747e4fSDavid du Colombier return buf;
1169a747e4fSDavid du Colombier }
117