diff options
author | Omar Polo <op@omarpolo.com> | 2021-04-30 17:16:34 +0000 |
---|---|---|
committer | Omar Polo <op@omarpolo.com> | 2021-04-30 17:16:34 +0000 |
commit | fdea6aa0bca24f6f947e2126ce101fd59caa7a31 (patch) | |
tree | c167f225e73250eb8cc82347a23ce7a86cfbf027 /server.c | |
parent | adbe6a6493c0e91fcfc918db8f4b5839a2867b1c (diff) |
allow ``root'' rule to be specified per-location block
Diffstat (limited to 'server.c')
-rw-r--r-- | server.c | 47 |
1 files changed, 37 insertions, 10 deletions
@@ -203,6 +203,25 @@ vhost_block_return(struct vhost *v, const char *path, int *code, const char **fm } int +vhost_dirfd(struct vhost *v, const char *path) +{ + struct location *loc; + + if (v == NULL || path == NULL) + return -1; + + loc = TAILQ_FIRST(&v->locations); + while ((loc = TAILQ_NEXT(loc, locations)) != NULL) { + if (loc->dirfd != -1) + if (matches(loc->match, path)) + return loc->dirfd; + } + + loc = TAILQ_FIRST(&v->locations); + return loc->dirfd; +} + +int vhost_strip(struct vhost *v, const char *path) { struct location *loc; @@ -265,22 +284,30 @@ check_path(struct client *c, const char *path, int *fd) { struct stat sb; const char *p; - int flags; + int flags, dirfd, strip; assert(path != NULL); - if (*path == '\0') + /* + * in send_dir we add an initial / (to be redirect-friendly), + * but here we want to skip it + */ + if (*path == '/') + path++; + + strip = vhost_strip(c->host, path); + p = strip_path(path, strip); + + if (*p == '/') + p = p+1; + if (*p == '\0') p = "."; - else if (*path == '/') - /* in send_dir we add an initial / (to be - * redirect-friendly), but here we want to skip it */ - p = path+1; - else - p = path; + dirfd = vhost_dirfd(c->host, path); + log_debug(c, "check_path: strip=%d path=%s original=%s", + strip, p, path); flags = O_RDONLY | O_NOFOLLOW; - - if (*fd == -1 && (*fd = openat(c->host->dirfd, p, flags)) == -1) + if (*fd == -1 && (*fd = openat(dirfd, p, flags)) == -1) return FILE_MISSING; if (fstat(*fd, &sb) == -1) { |