Пример #1
0
/* Validate URL
 */
bool validate_url(t_session *session) {
	if (valid_uri(session->uri, session->host->allow_dot_files)) {
		if (session->host->secure_url == false) {
			return true;
		} else if (strstr(session->request_uri, "%00") == NULL) {
			return true;
		} else {
			session->return_code = 403;
		}
	} else {
		session->return_code = (session->request_method == PUT) ? 403 : 404;
	}

	log_exploit_attempt(session, "invalid URL", NULL);
#ifdef ENABLE_TOMAHAWK
	increment_counter(COUNTER_EXPLOIT);
#endif
#ifdef ENABLE_MONITOR
	if (session->config->monitor_enabled) {
		monitor_count_exploit(session);
		monitor_event("Invalid URL %s for %s", session->uri, session->host->hostname.item[0]);
	}
#endif

	session->error_cause = ec_INVALID_URL;

	return false;
}
Пример #2
0
int use_toolkit(char *url, char *toolkit_id, t_toolkit_options *options) {
	t_url_toolkit *toolkit;
	t_toolkit_rule *rule;
	bool condition_met, url_replaced = false;
	int result, skip = 0;
	char *file, *qmark, *header;
	regmatch_t pmatch[REGEXEC_NMATCH];
	struct stat fileinfo;
	t_http_header *headers;

	if (options == NULL) {
		return UT_ERROR;
	}

	options->new_url = NULL;

	if ((toolkit = select_toolkit(toolkit_id, options->url_toolkit)) == NULL) {
		return UT_ERROR;
	}

	rule = toolkit->toolkit_rule;
	while (rule != NULL) {
		condition_met = false;

		/* Skip lines
		 */
		if (skip > 0) {
			skip--;
			rule = rule->next;
			continue;
		}

		/* Condition
		 */
		switch (rule->condition) {
			case tc_none:
				/* None
				 */
				condition_met = true;
				break;
			case tc_match:
				/* Match
				 */
				if (regexec(&(rule->pattern), url, REGEXEC_NMATCH, pmatch, 0) == 0) {
					condition_met = true;
				}
				if (rule->neg_match) {
					condition_met = (condition_met == false);
				}
				break;
			case tc_header:
				/* Header
				 */
				if (rule->header == NULL) {
					headers = options->http_headers;
					while (headers != NULL) {
						if (regexec(&(rule->pattern), headers->data + headers->value_offset, REGEXEC_NMATCH, pmatch, 0) == 0) {
							condition_met = true;
						}
						if (rule->neg_match) {
							condition_met = (condition_met == false);
						}

						if (condition_met) {
							break;
						}

						headers = headers->next;
					}
				} else {
					if ((header = get_http_header(rule->header, options->http_headers)) == NULL) {
						break;
					}
					if (regexec(&(rule->pattern), header, REGEXEC_NMATCH, pmatch, 0) == 0) {
						condition_met = true;
					}
					if (rule->neg_match) {
						condition_met = (condition_met == false);
					}
				}
				break;
			case tc_method:
				/* Request method
				 */
				if (strcmp(options->method, rule->parameter) == 0) {
					condition_met = true;
				}
				if (rule->neg_match) {
					condition_met = (condition_met == false);
				}
				break;
			case tc_request_uri:
				/* Request URI
				 */
				if (valid_uri(url, false) == false) {
					break;
				}
				if ((file = make_path(options->website_root, url)) == NULL) {
					return UT_ERROR;
				}

				if ((qmark = strchr(file, '?')) != NULL) {
					*qmark = '\0';
				}
				url_decode(file);

				if (stat(file, &fileinfo) != -1) {
					switch (rule->value) {
						case IU_EXISTS:
							if (S_ISDIR(fileinfo.st_mode) || S_ISREG(fileinfo.st_mode)) {
								condition_met = true;
							}
							break;
						case IU_ISFILE:
							if (S_ISREG(fileinfo.st_mode)) {
								condition_met = true;
							}
							break;
						case IU_ISDIR:
							if (S_ISDIR(fileinfo.st_mode)) {
								condition_met = true;
							}
							break;
					}
				}

				free(file);
				break;
			case tc_total_connections:
				/* Total connections reached?
				 */
				condition_met = options->total_connections >= rule->value;
				break;
#ifdef ENABLE_TLS
			case tc_use_tls:
				/* Client connections uses TLS?
				 */
				condition_met = options->use_tls;
				break;
#endif
		}

		/* Condition not met
		 */
		if (condition_met == false) {
			rule = rule->next;
			continue;
		}

		/* Operation
		 */
		switch (rule->operation) {
			case to_none:
				/* None
				 */
				break;
			case to_ban:
				/* Ban client
				 */
				options->ban = rule->value;
				break;
			case to_deny_access:
				/* Deny access
				 */
				return UT_DENY_ACCESS;
			case to_omit_request_log:
				/* Omit requeest log
				 */
				options->log_request = false;
				break;
			case to_expire:
				/* Send Expire HTTP header
				 */
				options->expire = rule->value;
				options->caco_private = rule->caco_private;
				break;
			case to_fastcgi:
				/* Use FastCGI server
				 */
				options->fastcgi_server = rule->parameter;
				break;
			case to_redirect:
				/* Redirect client
				 */
				if (rule->neg_match) {
					if ((options->new_url = strdup(rule->parameter)) == NULL) {
						return UT_ERROR;
					}
				} else if (do_rewrite(url, &(rule->pattern), pmatch, rule->parameter, &(options->new_url), rule->match_loop) == -1) {
					if (options->new_url != NULL) {
						free(options->new_url);
						options->new_url = NULL;
					}
					return UT_ERROR;
				}
				if (options->new_url != NULL) {
					if (url_replaced) {
						free(url);
					}
					return UT_REDIRECT;
				} else if (url_replaced) {
					options->new_url = url;
				}
				break;
			case to_rewrite:
				/* Rewrite
				 */
				if (rule->neg_match) {
					if ((options->new_url = strdup(rule->parameter)) == NULL) {
						return UT_ERROR;
					}
				} else if (do_rewrite(url, &(rule->pattern), pmatch, rule->parameter, &(options->new_url), rule->match_loop) == -1) {
					if (options->new_url != NULL) {
						free(options->new_url);
						options->new_url = NULL;
					}
					return UT_ERROR;
				}
				if (options->new_url != NULL) {
					if (url_replaced) {
						free(url);
					}
					url = options->new_url;
					url_replaced = true;
				} else if (url_replaced) {
					options->new_url = url;
				}
				break;
			case to_skip:
				/* Skip
				 */
				skip = rule->value;
				break;
			case to_sub:
				/* Subroutine
				 */
				if (++(options->sub_depth) > MAX_SUB_DEPTH) {
					return UT_ERROR;
				}

				if ((result = use_toolkit(url, rule->parameter, options)) == UT_ERROR) {
					if (options->new_url != NULL) {
						free(options->new_url);
						options->new_url = NULL;
					}
					return UT_ERROR;
				}
				options->sub_depth--;

				if (options->new_url != NULL) {
					if (url_replaced) {
						free(url);
					}
					url = options->new_url;
					url_replaced = true;
				} else if (url_replaced) {
					options->new_url = url;
				}

				if (result != UT_RETURN) {
					return result;
				}
				break;
			case to_use:
				/* Replace URL
				 */
				if (url_replaced) {
					free(url);
				}
				if ((options->new_url = strdup(rule->parameter)) == NULL) {
					return UT_ERROR;
				}
				break;
		}

		/* Flow
		 */
		switch (rule->flow) {
			case tf_continue:
				/* Continue
				 */
				break;
			case tf_exit:
				/* Exit
				 */
				return UT_EXIT;
			case tf_return:
				/* Return
				 */
				return UT_RETURN;
		}

		rule = rule->next;
	}

	return UT_RETURN;
}
Пример #3
0
static bool parse_parameters(t_toolkit_rule *new_rule, char *value, char **operation) {
	char *rest;
	bool allowed = false;
	int loop, time;

	split_string(value, &value, &rest, ' ');

	while (*operation != NULL) {
		if (strcasecmp(*operation, value) == 0) {
			allowed = true;
			break;
		}
		operation++;
	}

	if (allowed == false) {
		return false;
	}

	if (strcasecmp(value, "ban") == 0) {
		/* Ban
		 */
		new_rule->operation = to_ban;

		if ((new_rule->value = str_to_int(rest)) == false) {
			return false;
		}
	} else if (strcasecmp(value, "call") == 0) {
		/* Call
		 */
		new_rule->operation = to_sub;

		if (rest == NULL) {
			return false;
		} else if ((new_rule->parameter = strdup(rest)) == NULL) {
			return false;
		}
	} else if (strcasecmp(value, "denyaccess") == 0) {
		/* Deny access
		 */
		new_rule->operation = to_deny_access;
		new_rule->flow = tf_exit;
	} else if (strcasecmp(value, "omitrequestlog") == 0) {
		/* Omit request log
		 */
		new_rule->operation = to_omit_request_log;
	} else if (strcasecmp(value, "exit") == 0) {
		/* Exit
		 */
		new_rule->flow = tf_exit;
	} else if (strcasecmp(value, "expire") == 0) {
		/* Expire
		 */
		new_rule->operation = to_expire;

		if (split_string(rest, &value, &rest, ' ') == -1) {
			return false;
		}
		if ((new_rule->value = str_to_int(value)) == -1) {
			return false;
		}

		time = new_rule->value;

		split_string(rest, &value, &rest, ' ');
		if (strcasecmp(value, "minutes") == 0) {
			new_rule->value *= MINUTE;
		} else if (strcasecmp(value, "hours") == 0) {
			new_rule->value *= HOUR;
		} else if (strcasecmp(value, "days") == 0) {
			new_rule->value *= DAY;
		} else if (strcasecmp(value, "weeks") == 0) {
			new_rule->value *= 7 * DAY;
		} else if (strcasecmp(value, "months") == 0) {
			new_rule->value *= 30.5 * DAY;
		} else if (strcasecmp(value, "seconds") != 0) {
			return false;
		}

		if (new_rule->value < time) {
			return false;
		}

		/* public / private
		 */
		if (rest == NULL) {
			return true;
		}
		split_string(rest, &value, &rest, ' ');
		if (strcasecmp(value, "private") == 0) {
			new_rule->caco_private = true;
		} else if (strcasecmp(value, "public") == 0) {
			new_rule->caco_private = false;
		} else if (rest == NULL) {
			rest = value;
		} else {
			return false;
		}

		/* exit / return
		 */
		if (rest == NULL) {
			return true;
		}
		if (strcasecmp(rest, "exit") == 0) {
			new_rule->flow = tf_exit;
		} else if (strcasecmp(rest, "return") == 0) {
			new_rule->flow = tf_return;
		} else {
			return false;
		}
	} else if (strcasecmp(value, "goto") == 0) {
		/* Goto
		 */
		new_rule->operation = to_sub;
		new_rule->flow = tf_exit;

		if (rest == NULL) {
			return false;
		} else if ((new_rule->parameter = strdup(rest)) == NULL) {
			return false;
		}
	} else if (strcasecmp(value, "redirect") == 0) {
		/* Redirect
		 */
		new_rule->operation = to_redirect;
		new_rule->flow = tf_exit;

		if (rest == NULL) {
			return false;
		} else if ((new_rule->parameter = strdup(rest)) == NULL) {
			return false;
		}
	} else if (strcasecmp(value, "return") == 0) {
		/* Return
		 */
		new_rule->flow = tf_return;
	} else if (strcasecmp(value, "rewrite") == 0) {
		/* Rewrite
		 */
		new_rule->operation = to_rewrite;
		new_rule->flow = tf_exit;

		split_string(rest, &value, &rest, ' ');
		if (value == NULL) {
			return false;
		} else if ((new_rule->parameter = strdup(value)) == NULL) {
			return false;
		}

		if (rest != NULL) {
			split_string(rest, &value, &rest, ' ');
			if ((loop = str_to_int(value)) > 0) {
				if (loop > MAX_MATCH_LOOP) {
					return false;
				}
				new_rule->match_loop = loop;
				if ((value = rest) == NULL) {
					return true;
				}
			} else if (rest != NULL) {
				return false;
			}

			if (strcasecmp(value, "continue") == 0) {
				new_rule->flow = tf_continue;
			} else if (strcasecmp(value, "return") == 0) {
				new_rule->flow = tf_return;
			} else {
				return false;
			}
		}
	} else if (strcasecmp(value, "skip") == 0) {
		/* Skip
		 */
		new_rule->operation = to_skip;

		if ((new_rule->value = str_to_int(rest)) < 1) {
			return false;
		}
	} else if (strcasecmp(value, "use") == 0) {
		/* Use
		 */
		new_rule->operation = to_use;
		new_rule->flow = tf_exit;

		if (valid_uri(rest, false) == false) {
			return false;
		} else if ((new_rule->parameter = strdup(rest)) == NULL) {
			return false;
		}
	} else if (strcasecmp(value, "usefastcgi") == 0) {
		/* Match UseFastCGI
		 */
		new_rule->operation = to_fastcgi;
		new_rule->flow = tf_exit;

		if (rest == NULL) {
			return false;
		} else if ((new_rule->parameter = strdup(rest)) == NULL) {
			return false;
		} 
	} else {
		/* Error
		 */
		return false;
	}

	return true;
}
Пример #4
0
bool toolkit_setting(char *key, char *value, t_url_toolkit *toolkit) {
	t_toolkit_rule *new_rule, *rule;
	char *rest;
	int loop, time, cflags;
	size_t len;

	if ((key == NULL) || (value == NULL) || (toolkit == NULL)) {
		return false;
	}

	if (strcmp(key, "toolkitid") == 0) {
		return (toolkit->toolkit_id = strdup(value)) != NULL;
	}

	if ((new_rule = (t_toolkit_rule*)malloc(sizeof(t_toolkit_rule))) == NULL) {
		return false;
	} else if (toolkit->toolkit_rule == NULL) {
		toolkit->toolkit_rule = new_rule;
	} else {
		rule = toolkit->toolkit_rule;
		while (rule->next != NULL) {
			rule = rule->next;
		}
		rule->next = new_rule;
	}

	new_rule->condition = tc_none;
	new_rule->operation = to_none;
	new_rule->flow = tf_continue;
	new_rule->match_loop = 1;
	new_rule->neg_match = false;
	new_rule->parameter = NULL;
	new_rule->header = NULL;
	new_rule->value = 0;
	new_rule->case_insensitive = false;
	new_rule->next = NULL;

	if (strcmp(key, "matchci") == 0) {
		new_rule->case_insensitive = true;
		key = "match";
	}

	if (strcasecmp(key, "call") == 0) {
		/* Call
		 */
		new_rule->operation = to_sub;

		if ((new_rule->parameter = strdup(value)) == NULL) {
			return false;
		}
	} else if (strcasecmp(key, "header") == 0) {
		/* Header
		 */
		new_rule->condition = tc_header;

		if (split_string(value, &value, &rest, ' ') == -1) {
			return false;
		}

		len = strlen(value);
		if ((new_rule->header = (char*)malloc(len + 2)) == NULL) {
			return false;
		}
		sprintf(new_rule->header, "%s:", value);

		if ((*rest == '\'') || (*rest == '"')) {
			value = rest + 1;
			if ((rest = strchr(rest + 1, *rest)) == NULL) {
				return false;
			}
			*rest = '\0';
			rest = remove_spaces(rest + 1);
		} else if (split_string(rest, &value, &rest, ' ') == -1) {
			return false;
		}

		if (*value == '!') {
			new_rule->neg_match = true;
			value++;
		}
		if (regcomp(&(new_rule->pattern), value, REG_EXTENDED | REG_ICASE | REG_NOSUB) != 0) {
			return false;
		}

		split_string(rest, &value, &rest, ' ');

		if (strcasecmp(value, "call") == 0) {
			/* Header Call
			 */
			new_rule->operation = to_sub;

			if (rest == NULL) {
				return false;
			} else if ((new_rule->parameter = strdup(rest)) == NULL) {
				return false;
			}
		} else if (strcasecmp(value, "denyaccess") == 0) {
			/* Header Deny access
			 */
			new_rule->operation = to_deny_access;
			new_rule->flow = tf_exit;
		} else if (strcasecmp(value, "exit") == 0) {
			/* Header Exit
			 */
			new_rule->flow = tf_exit;
		} else if (strcasecmp(value, "goto") == 0) {
			/* Header Goto
			 */
			new_rule->operation = to_sub;
			new_rule->flow = tf_exit;

			if (rest == NULL) {
				return false;
			} else if ((new_rule->parameter = strdup(rest)) == NULL) {
				return false;
			}
		} else if (strcasecmp(value, "redirect") == 0) {
			/* Header Redirect
			 */
			new_rule->operation = to_redirect;
			new_rule->flow = tf_exit;

			if (rest == NULL) {
				return false;
			} else if ((new_rule->parameter = strdup(rest)) == NULL) {
				return false;
			}
		} else if (strcasecmp(value, "return") == 0) {
			/* Header Return
			 */
			new_rule->flow = tf_return;
		} else if (strcasecmp(value, "skip") == 0) {
			/* Header Skip
			 */
			if ((new_rule->value = str2int(rest)) < 1) {
				return false;
			}
		} else if (strcasecmp(value, "use") == 0) {
			/* Header Use
			 */
			new_rule->operation = to_replace;
			new_rule->flow = tf_exit;

			if (valid_uri(rest, false) == false) {
				return false;
			} else if ((new_rule->parameter = strdup(rest)) == NULL) {
				return false;
			}
		} else {
			return false;
		}
	} else if (strcmp(key, "match") == 0) {
		/* Match
		 */
		cflags = REG_EXTENDED;
		if (new_rule->case_insensitive) {
			cflags |= REG_ICASE;
		}

		new_rule->condition = tc_match;
		if (split_string(value, &value, &rest, ' ') == -1) {
			return false;
		}
		if (*value == '!') {
			new_rule->neg_match = true;
			value++;
		}
		if (regcomp(&(new_rule->pattern), value, cflags) != 0) {
			return false;
		}
		split_string(rest, &value, &rest, ' ');

		if (strcasecmp(value, "ban") == 0) {
			/* Match Ban
			 */
			new_rule->operation = to_ban;

			if ((new_rule->value = str2int(rest)) == false) {
				return false;
			}
		} else if (strcasecmp(value, "call") == 0) {
			/* Match Call
			 */
			new_rule->operation = to_sub;

			if (rest == NULL) {
				return false;
			} else if ((new_rule->parameter = strdup(rest)) == NULL) {
				return false;
			}
		} else if (strcasecmp(value, "denyaccess") == 0) {
			/* Match DenyAccess
			 */
			new_rule->operation = to_deny_access;
			new_rule->flow = tf_exit;
		} else if (strcasecmp(value, "exit") == 0) {
			/* Match Exit
			 */
			new_rule->flow = tf_exit;
		} else if (strcasecmp(value, "expire") == 0) {
			/* Match Expire
			 */
			new_rule->operation = to_expire;

			if (split_string(rest, &value, &rest, ' ') == -1) {
				return false;
			}
			if ((new_rule->value = str2int(value)) == -1) {
				return false;
			}

			time = new_rule->value;

			split_string(rest, &value, &rest, ' ');
			if (strcasecmp(value, "minutes") == 0) {
				new_rule->value *= MINUTE;
			} else if (strcasecmp(value, "hours") == 0) {
				new_rule->value *= HOUR;
			} else if (strcasecmp(value, "days") == 0) {
				new_rule->value *= DAY;
			} else if (strcasecmp(value, "weeks") == 0) {
				new_rule->value *= 7 * DAY;
			} else if (strcasecmp(value, "months") == 0) {
				new_rule->value *= 30.5 * DAY;
			} else if (strcasecmp(value, "seconds") != 0) {
				return false;
			}

			if (new_rule->value < time) {
				return false;
			}

			if (rest != NULL) {
				if (strcasecmp(rest, "exit") == 0) {
					new_rule->flow = tf_exit;
				} else if (strcasecmp(rest, "return") == 0) {
					new_rule->flow = tf_return;
				} else {
					return false;
				}
			}
		} else if (strcasecmp(value, "goto") == 0) {
			/* Match Goto
			 */
			new_rule->operation = to_sub;
			new_rule->flow = tf_exit;

			if (rest == NULL) {
				return false;
			} else if ((new_rule->parameter = strdup(rest)) == NULL) {
				return false;
			}
		} else if (strcasecmp(value, "redirect") == 0) {
			/* Match Redirect
			 */
			new_rule->operation = to_redirect;
			new_rule->flow = tf_exit;

			if (rest == NULL) {
				return false;
			} else if ((new_rule->parameter = strdup(rest)) == NULL) {
				return false;
			}
		} else if (strcasecmp(value, "return") == 0) {
			/* Match Return
			 */
			new_rule->flow = tf_return;
		} else if (strcasecmp(value, "rewrite") == 0) {
			/* Match Rewrite
			 */
			new_rule->operation = to_rewrite;
			new_rule->flow = tf_exit;

			split_string(rest, &value, &rest, ' ');
			if (value == NULL) {
				return false;
			} else if ((new_rule->parameter = strdup(value)) == NULL) {
				return false;
			}

			if (rest != NULL) {
				split_string(rest, &value, &rest, ' ');
				if ((loop = str2int(value)) > 0) {
					if (loop > MAX_MATCH_LOOP) {
						return false;
					}
					new_rule->match_loop = loop;
					if ((value = rest) == NULL) {
						return true;
					}
				} else if (rest != NULL) {
					return false;
				}

				if (strcasecmp(value, "continue") == 0) {
					new_rule->flow = tf_continue;
				} else if (strcasecmp(value, "return") == 0) {
					new_rule->flow = tf_return;
				} else {
					return false;
				}
			}
		} else if (strcasecmp(value, "skip") == 0) {
			/* Match Skip
			 */
			new_rule->operation = to_skip;

			if ((new_rule->value = str2int(rest)) < 1) {
				return false;
			}
		} else if (strcasecmp(value, "usefastcgi") == 0) {
			/* Match UseFastCGI
			 */
			new_rule->operation = to_fastcgi;
			new_rule->flow = tf_exit;

			if (rest == NULL) {
				return false;
			} else if ((new_rule->parameter = strdup(rest)) == NULL) {
				return false;
			}
		} else {
			return false;
		}
	} else if (strcasecmp(key, "requesturi") == 0) {
		/* RequestURI
		 */
		new_rule->condition = tc_request_uri;

		if (split_string(value, &value, &rest, ' ') == -1) {
			return false;
		}

		if (strcasecmp(value, "exists") == 0) {
			new_rule->value = IU_EXISTS;
		} else if (strcasecmp(value, "isfile") == 0) {
			new_rule->value = IU_ISFILE;
		} else if (strcasecmp(value, "isdir") == 0) {
			new_rule->value = IU_ISDIR;
		} else {
			return false;
		}

		if (strcasecmp(rest, "return") == 0) {
			new_rule->flow = tf_return;
		} else if (strcasecmp(rest, "exit") == 0) {
			new_rule->flow = tf_exit;
		} else {
			return false;
		}
	} else if (strcasecmp(key, "skip") == 0) {
		/* Skip
		 */
		new_rule->operation = to_skip;

		if ((new_rule->value = str2int(value)) < 1) {
			return false;
		}
#ifdef ENABLE_SSL
	} else if (strcmp(key, "usessl") == 0) {
		/* UseSSL
		 */
		new_rule->condition = tc_use_ssl;
		split_string(value, &value, &rest, ' ');

		if (strcasecmp(value, "call") == 0) {
			/* UseSSL Call
			 */
			new_rule->operation = to_sub;
			if (rest == NULL) {
				return false;
			} else if ((new_rule->parameter = strdup(rest)) == NULL) {
				return false;
			}
		} else if (strcasecmp(value, "exit") == 0) {
			/* UseSSL Exit
			 */
			new_rule->flow = tf_exit;
		} else if (strcasecmp(value, "goto") == 0) {
			/* UseSSL Goto
			 */
			new_rule->operation = to_sub;
			new_rule->flow = tf_exit;
			if (rest == NULL) {
				return false;
			} else if ((new_rule->parameter = strdup(rest)) == NULL) {
				return false;
			}
		} else if (strcasecmp(value, "return") == 0) {
			/* UseSSL Return
			 */
			new_rule->flow = tf_return;
		} else if (strcasecmp(value, "skip") == 0) {
			/* UseSSL Skip
			 */
			new_rule->operation = to_skip;
			if ((new_rule->value = str2int(rest)) < 1) {
				return false;
			}
		} else {
			return false;
		}
#endif
	} else {
		/* Unknown condition
		 */
		return false;
	}

	return true;
}