Lua: Added support for scripting to @inspectFile.

This commit is contained in:
ivanr
2007-12-20 15:53:23 +00:00
parent 4cecdf4c5b
commit f64c7c39e8
9 changed files with 214 additions and 79 deletions

View File

@@ -9,7 +9,6 @@
*
*/
#include <limits.h>
#include <apr_lib.h>
#include "modsecurity.h"
#include "msc_logging.h"
@@ -18,15 +17,6 @@
#include "msc_lua.h"
static const char *configuration_relative_path(apr_pool_t *pool, const char *parent_filename, const char *filename) {
if (filename == NULL) return NULL;
// TODO Support paths on operating systems other than Unix.
if (filename[0] == '/') return filename;
return apr_pstrcat(pool, apr_pstrndup(pool, parent_filename,
strlen(parent_filename) - strlen(apr_filepath_name_get(parent_filename))),
filename, NULL);
}
/* -- Directory context creation and initialisation -- */
@@ -1297,7 +1287,7 @@ static const char *cmd_rule_inheritance(cmd_parms *cmd, void *_dcfg, int flag) {
static const char *cmd_rule_script(cmd_parms *cmd, void *_dcfg, const char *p1,
const char *p2)
{
const char *filename = configuration_relative_path(cmd->pool, cmd->directive->filename, p1);
const char *filename = resolve_relative_path(cmd->pool, cmd->directive->filename, p1);
return add_rule(cmd, (directory_config *)_dcfg, RULE_TYPE_LUA, filename, p2, NULL);
}
#endif

View File

@@ -244,7 +244,7 @@ static const struct luaL_Reg mylib[] = {
/**
*
*/
int lua_execute(msc_script *script, modsec_rec *msr, msre_rule *rule, char **error_msg) {
int lua_execute(msc_script *script, char *param, modsec_rec *msr, msre_rule *rule, char **error_msg) {
apr_time_t time_before;
lua_State *L = NULL;
int rc;
@@ -288,7 +288,12 @@ int lua_execute(msc_script *script, modsec_rec *msr, msre_rule *rule, char **err
/* Execute main() */
lua_getglobal(L, "main");
if (lua_pcall(L, 0, 1, 0)) {
/* Put the parameter on the stack. */
if (param != NULL) {
lua_pushlstring(L, param, strlen(param));
}
if (lua_pcall(L, ((param != NULL) ? 1 : 0), 1, 0)) {
*error_msg = apr_psprintf(msr->mp, "Lua: Script execution failed: %s", lua_tostring(L, -1));
return -1;
}

View File

@@ -36,7 +36,7 @@ struct msc_script_part {
char DSOLOCAL *lua_compile(msc_script **script, const char *filename, apr_pool_t *pool);
int DSOLOCAL lua_execute(msc_script *script, modsec_rec *msr, msre_rule *rule, char **error_msg);
int DSOLOCAL lua_execute(msc_script *script, char *param, modsec_rec *msr, msre_rule *rule, char **error_msg);
#endif
#endif

View File

@@ -16,6 +16,8 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <apr_lib.h>
/* NOTE: Be careful as these can ONLY be used on static values for X.
* (i.e. VALID_HEX(c++) will NOT work)
*/
@@ -1176,3 +1178,28 @@ char *modsec_build(apr_pool_t *mp) {
build_type,
atoi(MODSEC_VERSION_RELEASE));
}
int is_empty_string(const char *string) {
unsigned int i;
if (string == NULL) return 1;
if (strlen(string) == 0) return 1;
for(i = 0; i < strlen(string); i++) {
if (!isspace(string[i])) {
return 0;
}
}
return 1;
}
char *resolve_relative_path(apr_pool_t *pool, const char *parent_filename, const char *filename) {
if (filename == NULL) return NULL;
// TODO Support paths on operating systems other than Unix.
if (filename[0] == '/') return (char *)filename;
return apr_pstrcat(pool, apr_pstrndup(pool, parent_filename,
strlen(parent_filename) - strlen(apr_filepath_name_get(parent_filename))),
filename, NULL);
}

View File

@@ -78,4 +78,8 @@ int DSOLOCAL ansi_c_sequences_decode_inplace(unsigned char *input, int len);
char DSOLOCAL *modsec_build(apr_pool_t *mp);
int DSOLOCAL is_empty_string(const char *string);
char DSOLOCAL *resolve_relative_path(apr_pool_t *pool, const char *parent_filename, const char *filename);
#endif

View File

@@ -1966,7 +1966,7 @@ static apr_status_t msre_rule_process_lua(msre_rule *rule, modsec_rec *msr) {
acting_actionset = rule->chain_starter->actionset;
}
rc = lua_execute(rule->script, msr, rule, &my_error_msg);
rc = lua_execute(rule->script, NULL, msr, rule, &my_error_msg);
if (rc < 0) {
msr_log(msr, 1, "%s", my_error_msg);
return -1;

View File

@@ -1484,7 +1484,7 @@ static apr_status_t msre_action_exec_execute(modsec_rec *msr, apr_pool_t *mptmp,
msc_script *script = (msc_script *)action->param_data;
char *my_error_msg = NULL;
if (lua_execute(script, msr, rule, &my_error_msg) < 0) {
if (lua_execute(script, NULL, msr, rule, &my_error_msg) < 0) {
msr_log(msr, 1, "%s", my_error_msg);
return 0;
}

View File

@@ -1237,44 +1237,99 @@ static int msre_op_rbl_execute(modsec_rec *msr, msre_rule *rule, msre_var *var,
}
/* inspectFile */
static int msre_op_inspectFile_execute(modsec_rec *msr, msre_rule *rule, msre_var *var,
char **error_msg)
{
char *script_output = NULL;
char const *argv[5];
const char *approver_script = rule->op_param;
const char *target_file = apr_pstrmemdup(msr->mp, var->value, var->value_len);
static int msre_op_inspectFile_init(msre_rule *rule, char **error_msg) {
char *filename = (char *)rule->op_param;
if (error_msg == NULL) return -1;
*error_msg = NULL;
msr_log(msr, 4, "Executing %s to inspect %s.", approver_script, target_file);
argv[0] = approver_script;
argv[1] = target_file;
argv[2] = NULL;
if (apache2_exec(msr, approver_script, (const char **)argv, &script_output) <= 0) {
*error_msg = apr_psprintf(msr->mp, "Execution of the approver script \"%s\" failed (invocation failed).",
log_escape(msr->mp, approver_script));
if ((filename == NULL)||(is_empty_string(filename))) {
*error_msg = apr_psprintf(rule->ruleset->mp, "Operator @inspectFile requires parameter.");
return -1;
}
if (script_output == NULL) {
*error_msg = apr_psprintf(msr->mp, "Execution of the approver script \"%s\" failed (no output).",
log_escape(msr->mp, approver_script));
return -1;
filename = resolve_relative_path(rule->ruleset->mp, rule->filename, filename);
#ifdef WITH_LUA
// TODO Write & use string_ends(s, e).
if (strlen(rule->op_param) > 4) {
char *p = filename + strlen(filename) - 4;
if ((p[0] == '.')&&(p[1] == 'l')&&(p[2] == 'u')&&(p[3] == 'a'))
{
msc_script *script = NULL;
/* Compile script. */
*error_msg = lua_compile(&script, filename, rule->ruleset->mp);
if (*error_msg != NULL) return -1;
rule->op_param_data = script;
}
}
#endif
if (rule->op_param_data == NULL) {
// TODO Verify the script exists and that we have
// the rights to execute it.
}
if (script_output[0] != '1') {
*error_msg = apr_psprintf(msr->mp, "File \"%s\" rejected by the approver script \"%s\": %s",
log_escape(msr->mp, target_file), log_escape(msr->mp, approver_script),
log_escape_nq(msr->mp, script_output));
return 1; /* Match. */
}
return 1;
}
/* No match. */
return 0;
static int msre_op_inspectFile_execute(modsec_rec *msr, msre_rule *rule, msre_var *var,
char **error_msg)
{
if (error_msg == NULL) return -1;
*error_msg = NULL;
if (rule->op_param_data == NULL) {
/* Execute externally, as native binary/shell script. */
char *script_output = NULL;
char const *argv[5];
const char *approver_script = rule->op_param;
const char *target_file = apr_pstrmemdup(msr->mp, var->value, var->value_len);
msr_log(msr, 4, "Executing %s to inspect %s.", approver_script, target_file);
argv[0] = approver_script;
argv[1] = target_file;
argv[2] = NULL;
if (apache2_exec(msr, approver_script, (const char **)argv, &script_output) <= 0) {
*error_msg = apr_psprintf(msr->mp, "Execution of the approver script \"%s\" failed (invocation failed).",
log_escape(msr->mp, approver_script));
return -1;
}
if (script_output == NULL) {
*error_msg = apr_psprintf(msr->mp, "Execution of the approver script \"%s\" failed (no output).",
log_escape(msr->mp, approver_script));
return -1;
}
if (script_output[0] != '1') {
*error_msg = apr_psprintf(msr->mp, "File \"%s\" rejected by the approver script \"%s\": %s",
log_escape(msr->mp, target_file), log_escape(msr->mp, approver_script),
log_escape_nq(msr->mp, script_output));
return 1; /* Match. */
}
/* No match. */
return 0;
} else {
/* Execute internally, as Lua script. */
char *target = apr_pstrmemdup(msr->mp, var->value, var->value_len);
msc_script *script = (msc_script *)rule->op_param_data;
int rc;
rc = lua_execute(script, target, msr, rule, error_msg);
if (rc < 0) {
/* Error. */
return -1;
}
return rc;
}
}
/* validateByteRange */
@@ -1867,7 +1922,7 @@ void msre_engine_register_default_operators(msre_engine *engine) {
/* inspectFile */
msre_engine_op_register(engine,
"inspectFile",
NULL,
msre_op_inspectFile_init,
msre_op_inspectFile_execute
);