r6987: - make sure esp pages cannot read data outside of the swat directory
authorAndrew Tridgell <tridge@samba.org>
Thu, 26 May 2005 03:05:37 +0000 (03:05 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:17:02 +0000 (13:17 -0500)
- don't expose the real system path to esp scripts

- fixed absolute paths in include() calls
(This used to be commit 6535611aa22f51b7376be3c15715e8040a059736)

source4/web_server/esp/esp.h
source4/web_server/esp/espProcs.c
source4/web_server/http.c

index 33ab9d7ac947689f4519d5faba7170005c2dea69..4503cacbb728d74c93f9fab019a349fb9cd861cb 100644 (file)
@@ -99,7 +99,7 @@ typedef struct Esp {
        char    *(*getSessionId)(EspHandle handle);
        int             (*mapToStorage)(EspHandle handle, char *path, int len, char *uri,
                                int flags);
-       int             (*readFile)(EspHandle handle, char **buf, int *len, char *path);
+       int             (*readFile)(EspHandle handle, char **buf, int *len, const char *path);
        void    (*redirect)(EspHandle handle, int code, char *url);
        void    (*setCookie)(EspHandle handle, char *name, char *value, 
                                int lifetime, char *path, bool secure);
index a8da800213b5f536ed6635709a11ad34498f49c1..5c99e092c94cb832fcff0f02af6bc65f17a5cd18 100644 (file)
@@ -77,8 +77,12 @@ static int includeProc(EspRequest *ep, int argc, char **argv)
        esp = ep->esp;
        mprAssert(argv);
        for (i = 0; i < argc; i++) {
-               mprGetDirName(dir, sizeof(dir), ep->docPath);
-               mprSprintf(path, sizeof(path), "%s/%s", dir, argv[i]);
+               if (argv[i][0] != '/') {
+                       mprGetDirName(dir, sizeof(dir), ep->docPath);
+                       mprSprintf(path, sizeof(path), "%s/%s", dir, argv[i]);
+               } else {
+                       mprSprintf(path, sizeof(path), "%s", argv[i]);
+               }
                
                if (esp->readFile(ep->requestHandle, &buf, &size, path) < 0) {
                        espError(ep, "Can't read include file: %s", path);
index 5f89e47163e30a261b24d7d2bed1390717dfbb0c..fa038302959c15657e5775ef725a62530f972b3b 100644 (file)
@@ -96,15 +96,46 @@ static void http_output_headers(struct websrv_context *web)
        data_blob_free(&b);
 }
 
+/*
+  return the local path for a URL
+*/
+static const char *http_local_path(struct websrv_context *web, const char *url)
+{
+       int i;
+       char *path;
+
+       /* check that the url is OK */
+       if (url[0] != '/') return NULL;
+
+       for (i=0;url[i];i++) {
+               if ((!isalnum(url[i]) && !strchr("./", url[i])) ||
+                   (url[i] == '.' && strchr("/.", url[i+1]))) {
+                       return NULL;
+               }
+       }
+
+       path = talloc_asprintf(web, "%s/%s", lp_swat_directory(), url+1);
+       if (path == NULL) return NULL;
+
+       if (directory_exist(path)) {
+               path = talloc_asprintf_append(path, "/index.html");
+       }
+       return path;
+}
+
 /*
   called when esp wants to read a file to support include() calls
 */
-static int http_readFile(EspHandle handle, char **buf, int *len, char *path)
+static int http_readFile(EspHandle handle, char **buf, int *len, const char *path)
 {
+       struct websrv_context *web = talloc_get_type(handle, struct websrv_context);
        int fd = -1;
        struct stat st;
        *buf = NULL;
 
+       path = http_local_path(web, path);
+       if (path == NULL) goto failed;
+
        fd = open(path, O_RDONLY);
        if (fd == -1 || fstat(fd, &st) != 0 || !S_ISREG(st.st_mode)) goto failed;
 
@@ -263,33 +294,6 @@ void http_error_unix(struct websrv_context *web, const char *info)
        http_error(web, code, info);
 }
 
-/*
-  return the local path for a URL
-*/
-static const char *http_local_path(struct websrv_context *web, const char *url)
-{
-       int i;
-       char *path;
-
-       /* check that the url is OK */
-       if (url[0] != '/') return NULL;
-
-       for (i=0;url[i];i++) {
-               if ((!isalnum(url[i]) && !strchr("./", url[i])) ||
-                   (url[i] == '.' && strchr("/.", url[i+1]))) {
-                       return NULL;
-               }
-       }
-
-       path = talloc_asprintf(web, "%s/%s", lp_swat_directory(), url+1);
-       if (path == NULL) return NULL;
-
-       if (directory_exist(path)) {
-               path = talloc_asprintf_append(path, "/index.html");
-       }
-       return path;
-}
-
 
 /*
   a simple file request
@@ -356,6 +360,7 @@ static void http_setup_arrays(struct esp_state *esp)
        espSetStringVar(req, ESP_SERVER_OBJ, "SERVER_PORT", 
                        talloc_asprintf(esp, "%u", socket_get_my_port(web->conn->socket)));
        espSetStringVar(req, ESP_SERVER_OBJ, "SERVER_PROTOCOL", "http");
+       espSetStringVar(esp->req, ESP_REQUEST_OBJ, "SCRIPT_FILENAME", web->input.url);
 }
 
 
@@ -369,34 +374,24 @@ static void esp_request(struct esp_state *esp)
 {
        struct websrv_context *web = esp->web;
        const char *url = web->input.url;
-       const char *path;
        size_t size;
        int res;
        char *emsg = NULL, *buf;
 
        http_setup_arrays(esp);
 
-       path = http_local_path(web, url);
-       if (path == NULL) goto invalid;
-
-       espSetStringVar(esp->req, ESP_REQUEST_OBJ, "SCRIPT_FILENAME", path);
-
-       if (http_readFile(web, &buf, &size, path) != 0) {
-               http_error_unix(web, path);
+       if (http_readFile(web, &buf, &size, url) != 0) {
+               http_error_unix(web, url);
                return;
        }
 
-       res = espProcessRequest(esp->req, path, buf, &emsg);
+       res = espProcessRequest(esp->req, url, buf, &emsg);
        if (res != 0 && emsg) {
-               http_writeBlock(esp, emsg, strlen(emsg));
+               http_writeBlock(web, emsg, strlen(emsg));
        }
        talloc_free(buf);
        http_output_headers(web);
        EVENT_FD_WRITEABLE(web->conn->event.fde);
-       return;
-
-invalid:
-       http_error(web, 400, "Malformed URL");
 }