source: trunk/minix/commands/httpd/police.c@ 21

Last change on this file since 21 was 9, checked in by Mattia Monga, 13 years ago

Minix 3.1.2a

File size: 9.7 KB
RevLine 
[9]1/* police.c
2 *
3 * This file is part of httpd.
4 *
5 * 02/17/1996 Michael Temari <Michael@TemWare.Com>
6 * 07/07/1996 Initial Release Michael Temari <Michael@TemWare.Com>
7 * 12/29/2002 Michael Temari <Michael@TemWare.Com>
8 *
9 */
10#include <sys/types.h>
11#include <sys/stat.h>
12#include <ctype.h>
13#include <stdio.h>
14#include <string.h>
15#include <stdlib.h>
16#include <time.h>
17#include <fcntl.h>
18#include <unistd.h>
19#include <errno.h>
20
21#include "http.h"
22#include "utility.h"
23#include "config.h"
24#include "pass.h"
25
26#define MATCH_NONE 0
27#define MATCH_WILD 1
28#define MATCH_FULL 2
29
30_PROTOTYPE(static int authaccess, (struct http_request *rq, struct http_reply *rp));
31_PROTOTYPE(static void purl, (struct http_request *rq, struct http_reply *rp));
32_PROTOTYPE(static char *virt, (char *to, char *host));
33
34static int authaccess(rq, rp)
35struct http_request *rq;
36struct http_reply *rp;
37{
38struct auth *auth;
39struct authuser *pu;
40
41 /* set authorization to be checked against */
42 if(rq->type == HTTP_REQUEST_TYPE_PROXY)
43 auth = proxyauth;
44 else
45 auth = rp->auth;
46
47 /* no authorization so no access to anyone */
48 if(auth == NULL) {
49 rp->status = HTTP_STATUS_FORBIDDEN;
50 strcpy(rp->statusmsg, "No Authoriation");
51 return(-1);
52 }
53
54 /* access must be R for PROXY */
55 if(rq->type == HTTP_REQUEST_TYPE_PROXY)
56 if(!(auth->urlaccess & URLA_READ)) {
57 rp->status = HTTP_STATUS_FORBIDDEN;
58 strcpy(rp->statusmsg, "Proxy not authorized");
59 return(-1);
60 }
61
62 /* no password file so it is a free for all */
63 if(auth->passwdfile == NULL)
64 return(0);
65
66 /* they did not give us an authorized user */
67 if(rq->authuser[0] == '\0') {
68 if(rq->type == HTTP_REQUEST_TYPE_PROXY)
69 rp->status = HTTP_STATUS_PROXY_AUTH_REQRD;
70 else
71 rp->status = HTTP_STATUS_UNAUTHORIZED;
72 strcpy(rp->statusmsg, "No Authorized User Given");
73 return(-1);
74 }
75
76 /* check if user okay */
77 pu = auth->users;
78 if(pu == NULL)
79 ; /* no user list we allow anyone in file */
80 else {
81 while(pu != NULL) {
82 if(!strcmp(pu->user, rq->authuser))
83 break;
84 pu = pu->next;
85 }
86 /* user is not in list so no access */
87 if(pu == NULL) {
88 if(rq->type == HTTP_REQUEST_TYPE_PROXY)
89 rp->status = HTTP_STATUS_PROXY_AUTH_REQRD;
90 else
91 rp->status = HTTP_STATUS_UNAUTHORIZED;
92 strcpy(rp->statusmsg, "Forbidden User not authorized");
93 return(-1);
94 }
95 }
96
97 /* check if password file exists, if not no access */
98 if(passfile(auth->passwdfile)) {
99 rp->status = HTTP_STATUS_FORBIDDEN;
100 strcpy(rp->statusmsg, "Invalid passwd file");
101 return(-1);
102 }
103
104 /* check if user in password file, if not no access */
105 if(passuser(auth->passwdfile, rq->authuser)) {
106 if(rq->type == HTTP_REQUEST_TYPE_PROXY)
107 rp->status = HTTP_STATUS_PROXY_AUTH_REQRD;
108 else
109 rp->status = HTTP_STATUS_UNAUTHORIZED;
110 strcpy(rp->statusmsg, "Forbidden Bad User");
111 return(-1);
112 }
113
114 /* check if a password exists, if not no access */
115 if(passnone(auth->passwdfile, rq->authuser)) {
116 if(rq->type == HTTP_REQUEST_TYPE_PROXY)
117 rp->status = HTTP_STATUS_PROXY_AUTH_REQRD;
118 else
119 rp->status = HTTP_STATUS_UNAUTHORIZED;
120 strcpy(rp->statusmsg, "Forbidden no password");
121 return(-1);
122 }
123
124 /* check if password matches, if not no access */
125 if(passpass(auth->passwdfile, rq->authuser, rq->authpass)) {
126 if(rq->type == HTTP_REQUEST_TYPE_PROXY)
127 rp->status = HTTP_STATUS_PROXY_AUTH_REQRD;
128 else
129 rp->status = HTTP_STATUS_UNAUTHORIZED;
130 strcpy(rp->statusmsg, "Forbidden bad password");
131 return(-1);
132 }
133
134 /* whew, all the checks passed so I guess we let them have it */
135 return(0);
136}
137
138int police(rq, rp)
139struct http_request *rq;
140struct http_reply *rp;
141{
142int size;
143struct stat st;
144struct dirsend *ds;
145
146 purl(rq, rp);
147
148 rp->mtype = "text/html";
149
150#ifdef DEBUG
151 fprintf(stderr, "httpd: Trying %s\n", rp->realurl);
152#endif
153
154 /* now check authorizations */
155 if(authaccess(rq, rp)) {
156 /* Don't give them any details why authorization failed */
157 strcpy(rp->statusmsg, "No Access Granted");
158 return(0);
159 }
160
161 /* a proxy request only needs an authorization check */
162 if(rq->type == HTTP_REQUEST_TYPE_PROXY)
163 return(0);
164
165 /* check access to real url */
166 if(stat(rp->realurl, &st)) {
167 if(errno == EACCES)
168 rp->status = HTTP_STATUS_FORBIDDEN;
169 else
170 rp->status = HTTP_STATUS_NOT_FOUND;
171 strcpy(rp->statusmsg, strerror(errno));
172 /* a PUT and NOT FOUND is okay since we are creating */
173 if(rq->method != HTTP_METHOD_PUT || rp->status != HTTP_STATUS_NOT_FOUND)
174 return(0);
175 }
176
177 /* If it is a directory do the appropriate thang! */
178 if(rq->method == HTTP_METHOD_GET || rq->method == HTTP_METHOD_HEAD)
179 if((st.st_mode & S_IFMT) == S_IFDIR) {
180 if(rq->url[strlen(rq->url) - 1] != '/') {
181 strncat(rq->url, "/", sizeof(rq->url) - strlen(rq->url));
182 rp->status = HTTP_STATUS_MOVED_TEMP;
183 sprintf(rp->statusmsg, "Moved to %s", rq->url);
184 return(0);
185 }
186 size = strlen(rq->url);
187 ds = dirsend;
188 while(ds != NULL) {
189 strncpy(rq->url+size, ds->file, sizeof(rq->url)-size);
190 purl(rq, rp);
191 if(stat(rp->realurl, &st)) {
192 if(errno == EACCES)
193 rp->status = HTTP_STATUS_FORBIDDEN;
194 else
195 if(errno != ENOENT)
196 rp->status = HTTP_STATUS_NOT_FOUND;
197 } else
198 break;
199 if(rp->status != HTTP_STATUS_OK) {
200 strcpy(rp->statusmsg, strerror(errno));
201 return(0);
202 }
203 ds = ds->next;
204 }
205 if(ds == NULL) {
206 rq->url[size] = '\0';
207 purl(rq, rp);
208 if(stat(rp->realurl, &st)) {
209 if(errno == EACCES)
210 rp->status = HTTP_STATUS_FORBIDDEN;
211 else
212 rp->status = HTTP_STATUS_NOT_FOUND;
213 strcpy(rp->statusmsg, strerror(errno));
214 return(0);
215 }
216 }
217 }
218
219 if(rq->method == HTTP_METHOD_PUT && !(rp->urlaccess & URLA_WRITE)) {
220 rp->status = HTTP_STATUS_METHOD_NOT_ALLOWED;
221 strcpy(rp->statusmsg, "Method not allowed");
222 return(0);
223 }
224
225 if(rp->status == HTTP_STATUS_OK) {
226 /* Here is where we check if it is a program or script to run */
227 if(cgiexec(rq, rp))
228 return(0);
229
230 if((st.st_mode & S_IFMT) == S_IFDIR) {
231 rp->status = HTTP_STATUS_NOT_FOUND;
232 strcpy(rp->statusmsg, "Directory listing not available");
233 return(0);
234 }
235
236 if((st.st_mode & S_IFMT) != S_IFREG) {
237 rp->status = HTTP_STATUS_NOT_FOUND;
238 strcpy(rp->statusmsg, "Not a regular file");
239 return(0);
240 }
241 }
242
243 /* open the URL for updating */
244 if(rq->method == HTTP_METHOD_PUT) {
245 rp->status = HTTP_STATUS_OK;
246 strcpy(rp->statusmsg, "OK");
247 rp->ofd = open(rp->realurl, O_WRONLY | O_CREAT | O_TRUNC);
248 if(rp->ofd < 0) {
249 if(errno == EACCES)
250 rp->status = HTTP_STATUS_FORBIDDEN;
251 else
252 rp->status = HTTP_STATUS_NOT_FOUND;
253 strcpy(rp->statusmsg, strerror(errno));
254 return(0);
255 }
256 return(0);
257 }
258
259 if(!(rp->urlaccess & URLA_READ)) {
260 rp->status = HTTP_STATUS_FORBIDDEN;
261 strcpy(rp->statusmsg, "No way...");
262 return(0);
263 }
264
265 rp->mtype = mimetype(rp->realurl);
266
267 rp->size = st.st_size;
268 rp->modtime = st.st_mtime;
269
270 /* open the url if it is a file */
271 rp->fd = open(rp->realurl, O_RDONLY);
272 if(rp->fd < 0) {
273 if(errno == EACCES)
274 rp->status = HTTP_STATUS_FORBIDDEN;
275 else
276 rp->status = HTTP_STATUS_NOT_FOUND;
277 strcpy(rp->statusmsg, strerror(errno));
278 return(0);
279 }
280
281 return(0);
282}
283
284static void purl(rq, rp)
285struct http_request *rq;
286struct http_reply *rp;
287{
288struct vpath *pv;
289int gotreal, gotperm;
290char *p;
291int match;
292int len;
293
294 gotreal = 0; gotperm = 0;
295
296#ifdef DEBUG
297 fprintf(stderr, "httpd: Processing url = \"%s\"\n", rq->url);
298#endif
299
300 /* remove any .. references */
301 p = rq->url;
302 while(*p) {
303 while(*p && *p != '/') p++;
304 if(*p != '/') continue;
305 p++;
306 if(*p != '.') continue;
307 p++;
308 if(*p != '.') continue;
309 p++;
310 strcpy(p - 3, p);
311 p = p - 3;
312 }
313
314 for(pv = vpath; pv != NULL; pv = pv->next) {
315 len = strlen(pv->from) - 1;
316 if(pv->from[len] == '*' || pv->from[len] == '$')
317 if(len == 0)
318 match = MATCH_WILD;
319 else
320 match = strncmp(rq->url, pv->from, len) ? MATCH_NONE : MATCH_WILD;
321 else
322 if(!strcmp(rq->url, pv->from))
323 match = MATCH_FULL;
324 else
325 match = MATCH_NONE;
326#ifdef DEBUG
327 fprintf(stderr, "httpd: Trying \"%s\" %d %d %d %s\n",
328 pv->from, match, gotreal, gotperm, pv->auth->name);
329#endif
330 if(match != MATCH_NONE) {
331 gotperm = 1;
332 rp->auth = pv->auth;
333 if(pv->urlaccess == -1 && rp->auth != NULL)
334 rp->urlaccess = rp->auth->urlaccess;
335 else
336 rp->urlaccess = pv->urlaccess;
337 if(strcmp(pv->to, ".")) {
338 gotreal = 1;
339 strncpy(rp->realurl, virt(pv->to, rq->host), sizeof(rp->realurl));
340 rp->realurl[sizeof(rp->realurl)-1] = '\0';
341 if(match == MATCH_WILD && pv->from[len] != '$') {
342 strncat(rp->realurl, rq->url+len, sizeof(rp->realurl) - strlen(rp->realurl));
343 rp->realurl[sizeof(rp->realurl)-1] = '\0';
344 }
345 }
346 }
347 if(match == MATCH_FULL) break;
348 }
349
350 if(rp->urlaccess == -1) rp->urlaccess = mkurlaccess("");
351
352 if(!gotreal) {
353 strncpy(rp->realurl, rq->url, sizeof(rp->realurl));
354 rp->realurl[sizeof(rp->realurl)-1] = '\0';
355 }
356
357 if(!gotperm)
358 rp->auth = NULL;
359
360#ifdef DEBUG
361 fprintf(stderr, "DEBUG: url = \"%s\" realurl = \"%s\" auth = \"%s\"\n",
362 rq->url, rp->realurl, ((rp->auth == NULL) ? "No Access" : rp->auth->name));
363 fprintf(stderr, "DEBUG: query = %s\n", rq->query);
364#endif
365
366 return;
367}
368
369static char *virt(to, host)
370char *to;
371char *host;
372{
373static char vroot[256];
374struct vhost *ph;
375
376#ifdef DEBUG
377fprintf(stderr, "virt: %s %s\n", to, host);
378#endif
379
380 if(vhost == NULL) return(to);
381
382 if(to[0] != '/') return(to);
383 if(to[1] != '/') return(to);
384 if(to[2] != '/') return(to);
385
386 vroot[0] = '\0';
387
388 for(ph = vhost; ph != NULL; ph = ph->next) {
389#ifdef DEBUG
390 fprintf(stderr, "ph: %s %s %s\n", ph->hname, ph->root, vroot);
391#endif
392 if(!strcmp(ph->hname, "*") && vroot[0] == '\0')
393 strncpy(vroot, ph->root, sizeof(vroot));
394 if(!strcasecmp(ph->hname, host)) {
395 strncpy(vroot, ph->root, sizeof(vroot));
396 break;
397 }
398 }
399
400 strncat(vroot, to+3, sizeof(vroot));
401
402#ifdef DEBUG
403 fprintf(stderr, "vroot: %s\n", vroot);
404#endif
405
406 return(vroot);
407}
Note: See TracBrowser for help on using the repository browser.