xref: /plan9/sys/src/cmd/ip/httpd/authorize.c (revision 236eb0b0b4ce4e4900554977fe3d9f7486a540de)
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