#include <cx/string.h>
#include "pathcheck.h"
#include "../util/pblock.h"
#include "../daemon/config.h"
#include "../daemon/acl.h"
#include "../daemon/acldata.h"
#include "../daemon/session.h"
#include "../daemon/vserver.h"
#include "../daemon/vfs.h"
#include "../config/acl.h"
#define PATHCHECK_MAX_TOKENS 2048
int require_auth(pblock *pb, Session *sn, Request *rq) {
char *user = pblock_findkeyval(pb_key_auth_user, rq->vars);
if(user ==
NULL) {
pblock_nvinsert(
"www-authenticate",
"Basic realm=\"Webserver\"",
rq->srvhdrs);
protocol_status(sn, rq,
PROTOCOL_UNAUTHORIZED,
NULL);
return REQ_ABORTED;
}
return REQ_PROCEED;
}
int require_access(pblock *pb, Session *sn, Request *rq) {
char *mask_str = pblock_findval(
"mask", pb);
if(!mask_str) {
log_ereport(
LOG_MISCONFIG,
"require-access: missing mask parameter");
protocol_status(sn, rq,
500,
NULL);
return REQ_ABORTED;
}
char *method = pblock_findval(
"method", pb);
if(method) {
char *m = pblock_findkeyval(pb_key_method, rq->reqpb);
if(strcmp(method, m)) {
return REQ_NOACTION;
}
}
uint32_t access_mask =
0;
cxstring *rights =
NULL;
ssize_t n = cx_strsplit_a(pool_allocator(sn->pool), cx_str(mask_str), (cxstring){
",",
1},
PATHCHECK_MAX_TOKENS, &rights);
for(
int i=
0;i<n;i++) {
cxstring right = rights[i];
access_mask = access_mask | accstr2int(right);
}
pool_free(sn->pool, rights);
rq->aclreqaccess = access_mask;
return REQ_PROCEED;
}
int append_acl(pblock *pb, Session *sn, Request *rq) {
const VirtualServer *vs = request_get_vs(rq);
WS_ASSERT(vs);
char *aclname = pblock_findval(
"acl", pb);
if(aclname) {
ACLList *acl = acl_get(vs->acls, aclname);
if(!acl) {
log_ereport(
LOG_MISCONFIG,
"append-acl: acl %s not found", aclname);
protocol_status(sn, rq,
500,
NULL);
return REQ_ABORTED;
}
acllist_append(sn, rq, acl);
}
return REQ_PROCEED;
}
int check_acl(pblock *pb, Session *sn, Request *rq) {
int access_mask =
ACL_READ_DATA | rq->aclreqaccess;
int ret = acl_evaluate(sn, rq, access_mask);
if(ret ==
REQ_ABORTED) {
return REQ_ABORTED;
}
return REQ_PROCEED;
}
int find_index(pblock *pb, Session *sn, Request *rq) {
char *inames = pblock_findval(
"index-names", pb);
if(!inames) {
log_ereport(
LOG_MISCONFIG,
"find-index: index-names parameter missing");
return REQ_ABORTED;
}
cxstring *names =
NULL;
ssize_t ni = cx_strsplit_a(pool_allocator(sn->pool), cx_str(inames), (cxstring)
CX_STR(
","),
PATHCHECK_MAX_TOKENS, &names);
if(ni <=
0) {
log_ereport(
LOG_MISCONFIG,
"find-index: no files specified in index-names parameter");
return REQ_ABORTED;
}
char *method = pblock_findkeyval(pb_key_method, rq->reqpb);
if(strcmp(method,
"GET")) {
return REQ_NOACTION;
}
VFSContext *vfs = vfs_request_context(sn, rq);
int ret =
REQ_NOACTION;
char *path = pblock_findkeyval(pb_key_path, rq->vars);
size_t pathlen = strlen(path);
cxstring p = cx_strn(path, pathlen);
if(path[pathlen-
1] ==
'/') {
for(
int i=
0;i<ni;i++) {
cxmutstr newpath = cx_strcat(
2, p, cx_strtrim(names[i]));
struct stat s;
if(!vfs_stat(vfs, newpath.ptr, &s)) {
pblock_kvinsert(
pb_key_path,
newpath.ptr,
newpath.length,
rq->vars);
free(newpath.ptr);
ret =
REQ_PROCEED;
}
else {
free(newpath.ptr);
}
}
}
pool_free(sn->pool, names);
return ret;
}
int dir_redirect(pblock *pb, Session *sn, Request *rq) {
char *path = pblock_findkeyval(pb_key_path, rq->vars);
VFSContext *vfs = vfs_request_context(sn, rq);
struct stat s;
if(vfs_stat(vfs, path, &s) !=
0) {
return REQ_NOACTION;
}
if(
S_ISDIR(s.st_mode) && path[strlen(path)-
1] !=
'/') {
pblock_nvinsert(
"content-length",
"0", rq->srvhdrs);
pblock_removekey(pb_key_content_type, rq->srvhdrs);
char *uri = pblock_findkeyval(pb_key_uri, rq->reqpb);
size_t urilen = strlen(uri);
char *location = pool_malloc(sn->pool, urilen +
2);
memcpy(location, uri, urilen);
location[urilen] =
'/';
location[urilen+
1] =
'\0';
pblock_kvinsert(pb_key_location, location, urilen +
1, rq->srvhdrs);
protocol_status(sn, rq,
302,
NULL);
http_start_response(sn, rq);
return REQ_ABORTED;
}
return REQ_PROCEED;
}