mirror of
https://github.com/cesanta/mongoose.git
synced 2024-12-18 03:18:10 +08:00
Stricter realpath checks
This commit is contained in:
parent
ae5f6c0920
commit
d5a1d5a5e8
15
mongoose.c
15
mongoose.c
@ -1090,11 +1090,11 @@ void mg_http_serve_dir(struct mg_connection *c, struct mg_http_message *hm,
|
|||||||
char t1[MG_PATH_MAX], t2[sizeof(t1)];
|
char t1[MG_PATH_MAX], t2[sizeof(t1)];
|
||||||
t1[0] = t2[0] = '\0';
|
t1[0] = t2[0] = '\0';
|
||||||
|
|
||||||
if (realpath(opts->root_dir, t1) == NULL)
|
if (realpath(opts->root_dir, t1) == NULL) {
|
||||||
LOG(LL_ERROR, ("realpath(%s): %d", opts->root_dir, errno));
|
LOG(LL_ERROR, ("realpath(%s): %d", opts->root_dir, errno));
|
||||||
|
mg_http_reply(c, 400, "", "Bad web root [%s]\n", opts->root_dir);
|
||||||
if (!mg_is_dir(t1)) {
|
} else if (!mg_is_dir(t1)) {
|
||||||
mg_http_reply(c, 400, "", "Bad web root [%s]\n", t1);
|
mg_http_reply(c, 400, "", "Invalid web root [%s]\n", t1);
|
||||||
} else {
|
} else {
|
||||||
// NOTE(lsm): Xilinx snprintf does not 0-terminate the detination for
|
// NOTE(lsm): Xilinx snprintf does not 0-terminate the detination for
|
||||||
// the %.*s specifier, if the length is zero. Make sure hm->uri.len > 0
|
// the %.*s specifier, if the length is zero. Make sure hm->uri.len > 0
|
||||||
@ -1106,8 +1106,11 @@ void mg_http_serve_dir(struct mg_connection *c, struct mg_http_message *hm,
|
|||||||
n2 = strlen(t1);
|
n2 = strlen(t1);
|
||||||
while (n2 > 0 && t1[n2 - 1] == '/') t1[--n2] = 0;
|
while (n2 > 0 && t1[n2 - 1] == '/') t1[--n2] = 0;
|
||||||
|
|
||||||
if (realpath(t1, t2) == NULL)
|
if (realpath(t1, t2) == NULL) {
|
||||||
LOG(LL_ERROR, ("realpath(%s): %d", t1, errno));
|
LOG(LL_ERROR, ("realpath(%s): %d", t1, errno));
|
||||||
|
mg_http_reply(c, 400, "", "Error serving [%s]\n", t1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (mg_is_dir(t2)) {
|
if (mg_is_dir(t2)) {
|
||||||
strncat(t2, "/index.html", sizeof(t2) - strlen(t2) - 1);
|
strncat(t2, "/index.html", sizeof(t2) - strlen(t2) - 1);
|
||||||
@ -1117,7 +1120,7 @@ void mg_http_serve_dir(struct mg_connection *c, struct mg_http_message *hm,
|
|||||||
|
|
||||||
if (strlen(t2) < n1 || memcmp(t1, t2, n1) != 0) {
|
if (strlen(t2) < n1 || memcmp(t1, t2, n1) != 0) {
|
||||||
// Requested file is located outside root directory, fail
|
// Requested file is located outside root directory, fail
|
||||||
mg_http_reply(c, 404, "", "Not found %.*s\n", (int) hm->uri.len,
|
mg_http_reply(c, 404, "", "Invalid URI [%.*s]\n", (int) hm->uri.len,
|
||||||
hm->uri.ptr);
|
hm->uri.ptr);
|
||||||
} else {
|
} else {
|
||||||
FILE *fp = mg_fopen(t2, "r");
|
FILE *fp = mg_fopen(t2, "r");
|
||||||
|
@ -270,7 +270,7 @@ typedef int socklen_t;
|
|||||||
#ifndef EWOULDBLOCK
|
#ifndef EWOULDBLOCK
|
||||||
#define EWOULDBLOCK WSAEWOULDBLOCK
|
#define EWOULDBLOCK WSAEWOULDBLOCK
|
||||||
#endif
|
#endif
|
||||||
#define realpath(a, b) _fullpath((b), (a), 512)
|
#define realpath(a, b) _fullpath((b), (a), MG_PATH_MAX)
|
||||||
#ifndef va_copy
|
#ifndef va_copy
|
||||||
#ifdef __va_copy
|
#ifdef __va_copy
|
||||||
#define va_copy __va_copy
|
#define va_copy __va_copy
|
||||||
|
@ -40,7 +40,7 @@ typedef int socklen_t;
|
|||||||
#ifndef EWOULDBLOCK
|
#ifndef EWOULDBLOCK
|
||||||
#define EWOULDBLOCK WSAEWOULDBLOCK
|
#define EWOULDBLOCK WSAEWOULDBLOCK
|
||||||
#endif
|
#endif
|
||||||
#define realpath(a, b) _fullpath((b), (a), 512)
|
#define realpath(a, b) _fullpath((b), (a), MG_PATH_MAX)
|
||||||
#ifndef va_copy
|
#ifndef va_copy
|
||||||
#ifdef __va_copy
|
#ifdef __va_copy
|
||||||
#define va_copy __va_copy
|
#define va_copy __va_copy
|
||||||
|
15
src/http.c
15
src/http.c
@ -670,11 +670,11 @@ void mg_http_serve_dir(struct mg_connection *c, struct mg_http_message *hm,
|
|||||||
char t1[MG_PATH_MAX], t2[sizeof(t1)];
|
char t1[MG_PATH_MAX], t2[sizeof(t1)];
|
||||||
t1[0] = t2[0] = '\0';
|
t1[0] = t2[0] = '\0';
|
||||||
|
|
||||||
if (realpath(opts->root_dir, t1) == NULL)
|
if (realpath(opts->root_dir, t1) == NULL) {
|
||||||
LOG(LL_ERROR, ("realpath(%s): %d", opts->root_dir, errno));
|
LOG(LL_ERROR, ("realpath(%s): %d", opts->root_dir, errno));
|
||||||
|
mg_http_reply(c, 400, "", "Bad web root [%s]\n", opts->root_dir);
|
||||||
if (!mg_is_dir(t1)) {
|
} else if (!mg_is_dir(t1)) {
|
||||||
mg_http_reply(c, 400, "", "Bad web root [%s]\n", t1);
|
mg_http_reply(c, 400, "", "Invalid web root [%s]\n", t1);
|
||||||
} else {
|
} else {
|
||||||
// NOTE(lsm): Xilinx snprintf does not 0-terminate the detination for
|
// NOTE(lsm): Xilinx snprintf does not 0-terminate the detination for
|
||||||
// the %.*s specifier, if the length is zero. Make sure hm->uri.len > 0
|
// the %.*s specifier, if the length is zero. Make sure hm->uri.len > 0
|
||||||
@ -686,8 +686,11 @@ void mg_http_serve_dir(struct mg_connection *c, struct mg_http_message *hm,
|
|||||||
n2 = strlen(t1);
|
n2 = strlen(t1);
|
||||||
while (n2 > 0 && t1[n2 - 1] == '/') t1[--n2] = 0;
|
while (n2 > 0 && t1[n2 - 1] == '/') t1[--n2] = 0;
|
||||||
|
|
||||||
if (realpath(t1, t2) == NULL)
|
if (realpath(t1, t2) == NULL) {
|
||||||
LOG(LL_ERROR, ("realpath(%s): %d", t1, errno));
|
LOG(LL_ERROR, ("realpath(%s): %d", t1, errno));
|
||||||
|
mg_http_reply(c, 400, "", "Error serving [%s]\n", t1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (mg_is_dir(t2)) {
|
if (mg_is_dir(t2)) {
|
||||||
strncat(t2, "/index.html", sizeof(t2) - strlen(t2) - 1);
|
strncat(t2, "/index.html", sizeof(t2) - strlen(t2) - 1);
|
||||||
@ -697,7 +700,7 @@ void mg_http_serve_dir(struct mg_connection *c, struct mg_http_message *hm,
|
|||||||
|
|
||||||
if (strlen(t2) < n1 || memcmp(t1, t2, n1) != 0) {
|
if (strlen(t2) < n1 || memcmp(t1, t2, n1) != 0) {
|
||||||
// Requested file is located outside root directory, fail
|
// Requested file is located outside root directory, fail
|
||||||
mg_http_reply(c, 404, "", "Not found %.*s\n", (int) hm->uri.len,
|
mg_http_reply(c, 404, "", "Invalid URI [%.*s]\n", (int) hm->uri.len,
|
||||||
hm->uri.ptr);
|
hm->uri.ptr);
|
||||||
} else {
|
} else {
|
||||||
FILE *fp = mg_fopen(t2, "r");
|
FILE *fp = mg_fopen(t2, "r");
|
||||||
|
@ -496,7 +496,7 @@ static void test_http_server(void) {
|
|||||||
|
|
||||||
ASSERT(fetch(&mgr, buf, url, "GET /badroot HTTP/1.0\r\n\n") == 400);
|
ASSERT(fetch(&mgr, buf, url, "GET /badroot HTTP/1.0\r\n\n") == 400);
|
||||||
#if MG_ARCH == MG_ARCH_WIN32
|
#if MG_ARCH == MG_ARCH_WIN32
|
||||||
ASSERT(cmpbody(buf, "Bad web root [Z:\\BAAADDD!]\n") == 0);
|
ASSERT(cmpbody(buf, "Invalid web root [Z:\\BAAADDD!]\n") == 0);
|
||||||
#else
|
#else
|
||||||
// LOG(LL_INFO, ("--> [%s]", buf));
|
// LOG(LL_INFO, ("--> [%s]", buf));
|
||||||
ASSERT(cmpbody(buf, "Bad web root [/BAAADDD!]\n") == 0);
|
ASSERT(cmpbody(buf, "Bad web root [/BAAADDD!]\n") == 0);
|
||||||
|
Loading…
Reference in New Issue
Block a user