From f2755afbac8ee4439e0fef1ac6939e37652b8fc1 Mon Sep 17 00:00:00 2001 From: Grzegorz Nosek Date: Sat, 10 Mar 2007 16:18:53 +0100 Subject: Improved CGI permission logic Symlinks are now allowed if owner matches --- fcgiwrap.c | 46 +++++++++++++++++++++++++++++++++++++--------- 1 file changed, 37 insertions(+), 9 deletions(-) diff --git a/fcgiwrap.c b/fcgiwrap.c index 577b13c..5e9b4fe 100644 --- a/fcgiwrap.c +++ b/fcgiwrap.c @@ -71,12 +71,41 @@ static void fcgi_pass(int fd_stdin, int fd_stdout, int fd_stderr) } } +int check_file_perms(const char *path) +{ + struct stat ls; + struct stat fs; + + if (lstat(path, &ls) < 0) { + return -ENOENT; + } else if (S_ISREG(ls.st_mode)) { + if (ls.st_mode & S_IXUSR) { + return 0; + } else { + return -EACCES; + } + } else if (!S_ISLNK(ls.st_mode)) { + return -EACCES; + } + + if (stat(path, &fs) < 0) { + return -ENOENT; + } else if (S_ISREG(fs.st_mode)) { + if (fs.st_mode & S_IXUSR) { + return 0; + } else { + return -EACCES; + } + } else { + return -EACCES; + } +} + char *get_cgi_filename() { int buflen = 1, docrootlen; char *buf; char *docroot, *scriptname, *p; - struct stat s; if ((p = getenv("DOCUMENT_ROOT"))) { docroot = p; @@ -99,15 +128,14 @@ char *get_cgi_filename() strcpy(buf + docrootlen, scriptname); while(1) { - if (lstat(buf, &s) == 0) { - if (!S_ISREG(s.st_mode) || ((s.st_mode & S_IXOTH) == 0)) - return NULL; /* 403 */ - - return buf; + switch(check_file_perms(buf)) { + case -EACCES: return NULL; + case 0: return buf; + default: + p = strrchr(buf, '/'); + if (!p) return NULL; + *p = 0; } - p = strrchr(buf, '/'); - if (!p) break; - *p = 0; } return NULL; -- cgit v1.2.3