1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 #include <cx/string.h>
30
31 #include "pathcheck.h"
32
33 #include "../util/pblock.h"
34 #include "../daemon/config.h"
35 #include "../daemon/acl.h"
36 #include "../daemon/acldata.h"
37 #include "../daemon/session.h"
38 #include "../daemon/vserver.h"
39
40 #include "../daemon/vfs.h"
41
42 #include "../config/acl.h"
43
44 #define PATHCHECK_MAX_TOKENS 2048
45
46 int require_auth(pblock *pb, Session *sn, Request *rq) {
47 char *user = pblock_findkeyval(pb_key_auth_user, rq->vars);
48
49 if(user ==
NULL) {
50 pblock_nvinsert(
51 "www-authenticate",
52 "Basic realm=\"Webserver\"",
53 rq->srvhdrs);
54
55 protocol_status(sn, rq,
PROTOCOL_UNAUTHORIZED,
NULL);
56 return REQ_ABORTED;
57 }
58
59 return REQ_PROCEED;
60 }
61
62 int require_access(pblock *pb, Session *sn, Request *rq) {
63 char *mask_str = pblock_findval(
"mask", pb);
64 if(!mask_str) {
65 log_ereport(
LOG_MISCONFIG,
"require-access: missing mask parameter");
66 protocol_status(sn, rq,
500,
NULL);
67 return REQ_ABORTED;
68 }
69
70 char *method = pblock_findval(
"method", pb);
71 if(method) {
72 char *m = pblock_findkeyval(pb_key_method, rq->reqpb);
73 if(strcmp(method, m)) {
74 return REQ_NOACTION;
75 }
76 }
77
78 uint32_t access_mask =
0;
79 cxstring *rights =
NULL;
80 ssize_t n = cx_strsplit_a(pool_allocator(sn->pool), cx_str(mask_str), (cxstring){
",",
1},
PATHCHECK_MAX_TOKENS, &rights);
81 for(
int i=
0;i<n;i++) {
82 cxstring right = rights[i];
83 access_mask = access_mask | accstr2int(right);
84 }
85 pool_free(sn->pool, rights);
86
87 rq->aclreqaccess = access_mask;
88
89 return REQ_PROCEED;
90 }
91
92 int append_acl(pblock *pb, Session *sn, Request *rq) {
93 const VirtualServer *vs = request_get_vs(rq);
94
95 WS_ASSERT(vs);
96
97 char *aclname = pblock_findval(
"acl", pb);
98 if(aclname) {
99 ACLList *acl = acl_get(vs->acls, aclname);
100 if(!acl) {
101 log_ereport(
102 LOG_MISCONFIG,
103 "append-acl: acl %s not found", aclname);
104 protocol_status(sn, rq,
500,
NULL);
105 return REQ_ABORTED;
106 }
107
108 acllist_append(sn, rq, acl);
109 }
110
111 return REQ_PROCEED;
112 }
113
114
115 int check_acl(pblock *pb, Session *sn, Request *rq) {
116 int access_mask =
ACL_READ_DATA | rq->aclreqaccess;
117
118 int ret = acl_evaluate(sn, rq, access_mask);
119 if(ret ==
REQ_ABORTED) {
120
121 return REQ_ABORTED;
122 }
123
124 return REQ_PROCEED;
125 }
126
127 int find_index(pblock *pb, Session *sn, Request *rq) {
128 char *inames = pblock_findval(
"index-names", pb);
129 if(!inames) {
130 log_ereport(
131 LOG_MISCONFIG,
132 "find-index: index-names parameter missing");
133 return REQ_ABORTED;
134 }
135
136 cxstring *names =
NULL;
137 ssize_t ni = cx_strsplit_a(pool_allocator(sn->pool), cx_str(inames), (cxstring)
CX_STR(
","),
PATHCHECK_MAX_TOKENS, &names);
138 if(ni <=
0) {
139 log_ereport(
140 LOG_MISCONFIG,
141 "find-index: no files specified in index-names parameter");
142 return REQ_ABORTED;
143 }
144
145
146
147
148 char *method = pblock_findkeyval(pb_key_method, rq->reqpb);
149 if(strcmp(method,
"GET")) {
150 return REQ_NOACTION;
151 }
152
153 VFSContext *vfs = vfs_request_context(sn, rq);
154 int ret =
REQ_NOACTION;
155
156 char *path = pblock_findkeyval(pb_key_path, rq->vars);
157 size_t pathlen = strlen(path);
158 cxstring p = cx_strn(path, pathlen);
159 if(path[pathlen-
1] ==
'/') {
160 for(
int i=
0;i<ni;i++) {
161 cxmutstr newpath = cx_strcat(
2, p, cx_strtrim(names[i]));
162 struct stat s;
163 if(!vfs_stat(vfs, newpath.ptr, &s)) {
164 pblock_kvinsert(
165 pb_key_path,
166 newpath.ptr,
167 newpath.length,
168 rq->vars);
169 free(newpath.ptr);
170 ret =
REQ_PROCEED;
171 }
else {
172 free(newpath.ptr);
173 }
174 }
175 }
176
177 pool_free(sn->pool, names);
178
179 return ret;
180 }
181
182 int dir_redirect(pblock *pb, Session *sn, Request *rq) {
183 char *path = pblock_findkeyval(pb_key_path, rq->vars);
184
185 VFSContext *vfs = vfs_request_context(sn, rq);
186
187 struct stat s;
188 if(vfs_stat(vfs, path, &s) !=
0) {
189 return REQ_NOACTION;
190 }
191
192
193
194 if(
S_ISDIR(s.st_mode) && path[strlen(path)-
1] !=
'/') {
195 pblock_nvinsert(
"content-length",
"0", rq->srvhdrs);
196 pblock_removekey(pb_key_content_type, rq->srvhdrs);
197 char *uri = pblock_findkeyval(pb_key_uri, rq->reqpb);
198 size_t urilen = strlen(uri);
199 char *location = pool_malloc(sn->pool, urilen +
2);
200 memcpy(location, uri, urilen);
201 location[urilen] =
'/';
202 location[urilen+
1] =
'\0';
203 pblock_kvinsert(pb_key_location, location, urilen +
1, rq->srvhdrs);
204 protocol_status(sn, rq,
302,
NULL);
205 http_start_response(sn, rq);
206 return REQ_ABORTED;
207 }
208
209 return REQ_PROCEED;
210 }
211