|
Lines 8-10
Link Here
|
| 8 |
#include <sys/socket.h> |
8 |
#include <sys/socket.h> |
| 9 |
#include <sys/un.h> |
9 |
#include <sys/un.h> |
| 10 |
|
10 |
|
|
|
11 |
--- ./fcgiwrap.c.orig 2013-02-03 22:25:17.000000000 +0900 |
| 12 |
+++ ./fcgiwrap.c 2014-01-09 20:10:43.000000000 +0900 |
| 13 |
@@ -58,6 +58,8 @@ |
| 14 |
|
| 15 |
extern char **environ; |
| 16 |
static char * const * inherited_environ; |
| 17 |
+static const char **allowed_programs; |
| 18 |
+static size_t allowed_programs_count; |
| 19 |
|
| 20 |
static const char * blacklisted_env_vars[] = { |
| 21 |
"AUTH_TYPE", |
| 22 |
@@ -485,6 +487,19 @@ |
| 23 |
} |
| 24 |
} |
| 25 |
|
| 26 |
+static bool is_allowed_program(const char *program) { |
| 27 |
+ size_t i; |
| 28 |
+ if (!allowed_programs_count) |
| 29 |
+ return true; |
| 30 |
+ |
| 31 |
+ for (i = 0; i < allowed_programs_count; i++) { |
| 32 |
+ if (!strcmp(allowed_programs[i], program)) |
| 33 |
+ return true; |
| 34 |
+ } |
| 35 |
+ |
| 36 |
+ return false; |
| 37 |
+} |
| 38 |
+ |
| 39 |
static void cgi_error(const char *message, const char *reason, const char *filename) |
| 40 |
{ |
| 41 |
printf("Status: %s\r\nContent-Type: text/plain\r\n\r\n%s\r\n", |
| 42 |
@@ -541,6 +556,9 @@ |
| 43 |
if (!filename) |
| 44 |
cgi_error("403 Forbidden", "Cannot get script name, are DOCUMENT_ROOT and SCRIPT_NAME (or SCRIPT_FILENAME) set and is the script executable?", NULL); |
| 45 |
|
| 46 |
+ if (!is_allowed_program(filename)) |
| 47 |
+ cgi_error("403 Forbidden", "The given script is not allowed to execute", filename); |
| 48 |
+ |
| 49 |
last_slash = strrchr(filename, '/'); |
| 50 |
if (!last_slash) |
| 51 |
cgi_error("403 Forbidden", "Script name must be a fully qualified path", filename); |
| 52 |
@@ -605,7 +623,7 @@ |
| 53 |
{ |
| 54 |
int status; |
| 55 |
|
| 56 |
- while ((dummy = waitpid(-1, &status, WNOHANG)) != -1) { |
| 57 |
+ while ((dummy = waitpid(-1, &status, WNOHANG)) > 0) { |
| 58 |
/* sanity check */ |
| 59 |
if (nrunning > 0) |
| 60 |
nrunning--; |
| 61 |
@@ -760,7 +778,7 @@ |
| 62 |
char *socket_url = NULL; |
| 63 |
int c; |
| 64 |
|
| 65 |
- while ((c = getopt(argc, argv, "c:hfs:")) != -1) { |
| 66 |
+ while ((c = getopt(argc, argv, "c:hfs:p:")) != -1) { |
| 67 |
switch (c) { |
| 68 |
case 'f': |
| 69 |
stderr_to_fastcgi++; |
| 70 |
@@ -773,6 +791,7 @@ |
| 71 |
" -c <number>\t\tNumber of processes to prefork\n" |
| 72 |
" -s <socket_url>\tSocket to bind to (say -s help for help)\n" |
| 73 |
" -h\t\t\tShow this help message and exit\n" |
| 74 |
+ " -p <path>\t\tRestrict execution to this script. (repeated options will be merged)\n" |
| 75 |
"\nReport bugs to Grzegorz Nosek <"PACKAGE_BUGREPORT">.\n" |
| 76 |
PACKAGE_NAME" home page: <http://nginx.localdomain.pl/wiki/FcgiWrap>\n", |
| 77 |
argv[0] |
| 78 |
@@ -784,8 +803,14 @@ |
| 79 |
case 's': |
| 80 |
socket_url = strdup(optarg); |
| 81 |
break; |
| 82 |
+ case 'p': |
| 83 |
+ allowed_programs = realloc(allowed_programs, (allowed_programs_count + 1) * sizeof (char *)); |
| 84 |
+ if (!allowed_programs) |
| 85 |
+ abort(); |
| 86 |
+ allowed_programs[allowed_programs_count++] = strdup(optarg); |
| 87 |
+ break; |
| 88 |
case '?': |
| 89 |
- if (optopt == 'c' || optopt == 's') |
| 90 |
+ if (optopt == 'c' || optopt == 's' || optopt == 'p') |
| 91 |
fprintf(stderr, "Option -%c requires an argument.\n", optopt); |
| 92 |
else if (isprint(optopt)) |
| 93 |
fprintf(stderr, "Unknown option `-%c'.\n", optopt); |