1 #include <u.h>
2 #include <libc.h>
3 #include <auth.h>
4 #include "httpd.h"
5 #include "httpsrv.h"
6
7 static char* readfile(char*);
8
9 /*
10 * these should be done better; see the response codes in /lib/rfc/rfc2616 for
11 * more info on what should be included.
12 */
13 #define UNAUTHED "You are not authorized to see this area.\n"
14
15 /*
16 * check for authorization for some parts of the server tree.
17 * the user name supplied with the authorization request is ignored;
18 * instead, we authenticate as the realm's user.
19 *
20 * authorization should be done before opening any files so that
21 * unauthorized users don't get to validate file names.
22 *
23 * returns 1 if authorized, 0 if unauthorized, -1 for io failure.
24 */
25 int
authorize(HConnect * c,char * file)26 authorize(HConnect *c, char *file)
27 {
28 char *p, *p0;
29 Hio *hout;
30 char *buf;
31 int i, n;
32 char *t[257];
33
34 p0 = halloc(c, strlen(file)+STRLEN("/.httplogin")+1);
35 strcpy(p0, file);
36 for(;;){
37 p = strrchr(p0, '/');
38 if(p == nil)
39 return hfail(c, HInternal);
40 if(*(p+1) != 0)
41 break;
42
43 /* ignore trailing '/'s */
44 *p = 0;
45 }
46 strcpy(p, "/.httplogin");
47
48 buf = readfile(p0);
49 if(buf == nil){
50 return 1;
51 }
52 n = tokenize(buf, t, nelem(t));
53
54 if(c->head.authuser != nil && c->head.authpass != 0){
55 for(i = 1; i+1 < n; i += 2){
56 if(strcmp(t[i], c->head.authuser) == 0
57 && strcmp(t[i+1], c->head.authpass) == 0){
58 free(buf);
59 return 1;
60 }
61 }
62 }
63
64 hout = &c->hout;
65 hprint(hout, "%s 401 Unauthorized\r\n", hversion);
66 hprint(hout, "Server: Plan9\r\n");
67 hprint(hout, "Date: %D\r\n", time(nil));
68 hprint(hout, "WWW-Authenticate: Basic realm=\"%s\"\r\n", t[0]);
69 hprint(hout, "Content-Type: text/html\r\n");
70 hprint(hout, "Content-Length: %d\r\n", STRLEN(UNAUTHED));
71 if(c->head.closeit)
72 hprint(hout, "Connection: close\r\n");
73 else if(!http11(c))
74 hprint(hout, "Connection: Keep-Alive\r\n");
75 hprint(hout, "\r\n");
76 if(strcmp(c->req.meth, "HEAD") != 0)
77 hprint(hout, "%s", UNAUTHED);
78 writelog(c, "Reply: 401 Unauthorized\n");
79 free(buf);
80 return hflush(hout);
81 }
82
83 static char*
readfile(char * file)84 readfile(char *file)
85 {
86 Dir *d;
87 int fd;
88 char *buf;
89 int n, len;
90
91 fd = open(file, OREAD);
92 if(fd < 0)
93 return nil;
94 d = dirfstat(fd);
95 if(d == nil){ /* shouldn't happen */
96 close(fd);
97 return nil;
98 }
99 len = d->length;
100 free(d);
101
102 buf = malloc(len+1);
103 if(buf == 0){
104 close(fd);
105 return nil;
106 }
107
108 n = readn(fd, buf, len);
109 close(fd);
110 if(n <= 0){
111 free(buf);
112 return nil;
113 }
114 buf[n] = '\0';
115 return buf;
116 }
117