diff --git a/http.c b/http.c index 49b30dc..6bf4264 100644 --- a/http.c +++ b/http.c @@ -600,11 +600,6 @@ http_send_response(int fd, const struct request *req) return http_send_status(fd, S_BAD_REQUEST); } - /* reject hidden target */ - if (realtarget[0] == '.' || strstr(realtarget, "/.")) { - return http_send_status(fd, S_FORBIDDEN); - } - /* stat the target */ if (stat(RELPATH(realtarget), &st) < 0) { return http_send_status(fd, (errno == EACCES) ? @@ -623,6 +618,15 @@ http_send_response(int fd, const struct request *req) } } + /* + * reject hidden target, except if it is a well-known URI + * according to RFC 8615 + */ + if (strstr(realtarget, "/.") && strncmp(realtarget, + "/.well-known/", sizeof("/.well-known/") - 1)) { + return http_send_status(fd, S_FORBIDDEN); + } + /* redirect if targets differ, host is non-canonical or we prefixed */ if (strcmp(req->target, realtarget) || (s.vhost && vhostmatch && strcmp(req->field[REQ_HOST], vhostmatch))) {