diff options
| -rw-r--r-- | fcgiwrap.c | 29 | 
1 files changed, 27 insertions, 2 deletions
@@ -58,6 +58,8 @@  extern char **environ;  static char * const * inherited_environ; +static const char **allowed_programs; +static size_t allowed_programs_count;  static const char * blacklisted_env_vars[] = {  	"AUTH_TYPE", @@ -485,6 +487,19 @@ static void inherit_environment(void)  	}  } +static bool is_allowed_program(const char *program) { +	size_t i; +	if (!allowed_programs_count) +		return true; + +	for (i = 0; i < allowed_programs_count; i++) { +		if (!strcmp(allowed_programs[i], program)) +			return true; +	} + +	return false; +} +  static void cgi_error(const char *message, const char *reason, const char *filename)  {  	printf("Status: %s\r\nContent-Type: text/plain\r\n\r\n%s\r\n", @@ -541,6 +556,9 @@ static void handle_fcgi_request(void)  			if (!filename)  				cgi_error("403 Forbidden", "Cannot get script name, are DOCUMENT_ROOT and SCRIPT_NAME (or SCRIPT_FILENAME) set and is the script executable?", NULL); +			if (!is_allowed_program(filename)) +				cgi_error("403 Forbidden", "The given script is not allowed to execute", filename); +  			last_slash = strrchr(filename, '/');  			if (!last_slash)  				cgi_error("403 Forbidden", "Script name must be a fully qualified path", filename); @@ -760,7 +778,7 @@ int main(int argc, char **argv)  	char *socket_url = NULL;  	int c; -	while ((c = getopt(argc, argv, "c:hfs:")) != -1) { +	while ((c = getopt(argc, argv, "c:hfs:p:")) != -1) {  		switch (c) {  			case 'f':  				stderr_to_fastcgi++; @@ -773,6 +791,7 @@ int main(int argc, char **argv)  					"  -c <number>\t\tNumber of processes to prefork\n"  					"  -s <socket_url>\tSocket to bind to (say -s help for help)\n"  					"  -h\t\t\tShow this help message and exit\n" +					"  -p <path>\t\tRestrict execution to this script. (repeated options will be merged)\n"  					"\nReport bugs to Grzegorz Nosek <"PACKAGE_BUGREPORT">.\n"  					PACKAGE_NAME" home page: <http://nginx.localdomain.pl/wiki/FcgiWrap>\n",  					argv[0] @@ -784,8 +803,14 @@ int main(int argc, char **argv)  			case 's':  				socket_url = strdup(optarg);  				break; +			case 'p': +				allowed_programs = realloc(allowed_programs, (allowed_programs_count + 1) * sizeof (char *)); +				if (!allowed_programs) +					abort(); +				allowed_programs[allowed_programs_count++] = strdup(optarg); +				break;  			case '?': -				if (optopt == 'c' || optopt == 's') +				if (optopt == 'c' || optopt == 's' || optopt == 'p')  					fprintf(stderr, "Option -%c requires an argument.\n", optopt);  				else if (isprint(optopt))  					fprintf(stderr, "Unknown option `-%c'.\n", optopt);  | 
