Added m.getvars() and finalised Lua support.

This commit is contained in:
ivanr
2007-12-21 12:50:03 +00:00
parent 8924f605d4
commit 2068357af8
9 changed files with 322 additions and 135 deletions

View File

@@ -39,8 +39,6 @@ APACHECTL = apachectl
INCLUDES = -I /usr/include/libxml2 -I /usr/include/lua5.1
# INCLUDES = -I /usr/include/libxml2 -I /path/to/httpd-x.y/srclib/pcre
DEFS = -DWITH_LUA
# DEFS = -DWITH_ICONV
# DEFS = -DPERFORMANCE_MEASUREMENT
# DEFS = -DNO_MODSEC_API
# DEFS = -DDEBUG_CONF

View File

@@ -1283,14 +1283,12 @@ static const char *cmd_rule_inheritance(cmd_parms *cmd, void *_dcfg, int flag) {
return NULL;
}
#ifdef WITH_LUA
static const char *cmd_rule_script(cmd_parms *cmd, void *_dcfg, const char *p1,
const char *p2)
{
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
static const char *cmd_rule_remove_by_id(cmd_parms *cmd, void *_dcfg, const char *p1) {
directory_config *dcfg = (directory_config *)_dcfg;
@@ -1887,7 +1885,6 @@ const command_rec module_directives[] = {
"On or Off"
),
#ifdef WITH_LUA
AP_INIT_TAKE12 (
"SecRuleScript",
cmd_rule_script,
@@ -1895,7 +1892,6 @@ const command_rec module_directives[] = {
CMD_SCOPE_ANY,
"" // TODO
),
#endif
AP_INIT_ITERATE (
"SecRuleRemoveById",

View File

@@ -1,9 +1,6 @@
#include "msc_lua.h"
#ifdef WITH_LUA
#include "apr_strings.h"
typedef struct {
@@ -123,18 +120,60 @@ static int l_log(lua_State *L) {
return 0;
}
/**
*
*/
static apr_array_header_t *resolve_tfns(lua_State *L, int idx, modsec_rec *msr, apr_pool_t *mp) {
apr_array_header_t *tfn_arr = NULL;
msre_tfn_metadata *tfn = NULL;
char *name = NULL;
tfn_arr = apr_array_make(mp, 25, sizeof(msre_tfn_metadata *));
if (tfn_arr == NULL) return NULL;
if (lua_istable(L, idx)) { /* Is the second parameter an array? */
int i, n = lua_objlen(L, idx);
for(i = 1; i <= n; i++) {
lua_rawgeti(L, idx, i);
name = (char *)luaL_checkstring(L, -1);
tfn = msre_engine_tfn_resolve(msr->modsecurity->msre, name);
if (tfn == NULL) {
msr_log(msr, 1, "SecRuleScript: Invalid transformation function: %s", name);
} else {
*(msre_tfn_metadata **)apr_array_push(tfn_arr) = tfn;
}
}
} else if (lua_isstring(L, idx)) { /* The second parameter may be a simple string? */
name = (char *)luaL_checkstring(L, idx);
tfn = msre_engine_tfn_resolve(msr->modsecurity->msre, name);
if (tfn == NULL) {
msr_log(msr, 1, "SecRuleScript: Invalid transformation function: %s", name);
} else {
*(msre_tfn_metadata **)apr_array_push(tfn_arr) = tfn;
}
} else {
// TODO Error
return NULL;
}
return tfn_arr;
}
/**
*
*/
static int l_getvar(lua_State *L) {
char *varname = NULL;
char *param = NULL;
char *varname = NULL, *param = NULL;
modsec_rec *msr = NULL;
msre_rule *rule = NULL;
char *my_error_msg = NULL;
char *p1 = NULL;
apr_array_header_t *tfn_arr = NULL;
msre_var *vx = NULL;
/* Retrieve parameters. */
varname = (char *)luaL_checkstring(L, 1);
p1 = (char *)luaL_checkstring(L, 1);
/* Retrieve msr. */
lua_getglobal(L, "__msr");
@@ -144,100 +183,123 @@ static int l_getvar(lua_State *L) {
lua_getglobal(L, "__rule");
rule = (msre_rule *)lua_topointer(L, -1);
/* Resolve variable $varname. */
/* Extract the variable name and its parameter from the script. */
varname = apr_pstrdup(msr->msc_rule_mptmp, p1);
param = strchr(varname, '.');
if (param != NULL) {
*param = '\0';
param++;
}
/* Resolve variable. */
msre_var *var = msre_create_var_ex(msr->msc_rule_mptmp, msr->modsecurity->msre,
varname, param, msr, &my_error_msg);
if (var == NULL) {
msr_log(msr, 1, "SecRuleScript: Failed to resolve variable: %s", varname);
msr_log(msr, 1, "%s", my_error_msg);
lua_pushnil(L);
return 0;
} else {
msre_var *vx = NULL;
vx = generate_single_var(msr, var, rule, msr->msc_rule_mptmp);
if (vx != NULL) {
char *rval = NULL;
long int rval_len = -1;
/* Transform the variable if a list of transformation
* functions has been supplied.
*/
if (lua_istable(L, 2)) { /* Is the second parameter an array? */
int i, n = lua_objlen(L, 2);
/* Make a copy so that we don't ruin the original value. */
vx->value = apr_pstrmemdup(msr->msc_rule_mptmp, vx->value, vx->value_len);
for(i = 1; i <= n; i++) {
msre_tfn_metadata *tfn = NULL;
char *name = NULL;
int rc = 0;
lua_rawgeti(L, 2, i);
name = (char *)luaL_checkstring(L, -1);
tfn = msre_engine_tfn_resolve(msr->modsecurity->msre, name);
if (tfn == NULL) {
msr_log(msr, 1, "SecRuleScript: Invalid transformation function in getvar() call: %s", name);
return 0;
}
rc = tfn->execute(msr->msc_rule_mptmp, (unsigned char*)vx->value,
vx->value_len, &rval, &rval_len);
vx->value = rval;
vx->value_len = rval_len;
if (msr->txcfg->debuglog_level >= 9) {
msr_log(msr, 9, "T (%d) %s: \"%s\"", rc, tfn->name,
log_escape_nq_ex(msr->msc_rule_mptmp, vx->value, vx->value_len));
}
}
}
else if (lua_isstring(L, 2)) { /* The second parameter may be a simple string? */
msre_tfn_metadata *tfn = NULL;
char *name = NULL;
int rc = 0;
/* Make a copy so that we don't ruin the original value. */
vx->value = apr_pstrmemdup(msr->msc_rule_mptmp, vx->value, vx->value_len);
name = (char *)luaL_checkstring(L, 2);
tfn = msre_engine_tfn_resolve(msr->modsecurity->msre, name);
if (tfn == NULL) {
msr_log(msr, 1, "SecRuleScript: Invalid transformation function in getvar() call: %s", name);
return 0;
}
rc = tfn->execute(msr->msc_rule_mptmp, (unsigned char *)vx->value,
vx->value_len, &rval, &rval_len);
vx->value = rval;
vx->value_len = rval_len;
if (msr->txcfg->debuglog_level >= 9) {
msr_log(msr, 9, "T (%d) %s: \"%s\"", rc, tfn->name,
log_escape_nq_ex(msr->msc_rule_mptmp, vx->value, vx->value_len));
}
}
lua_pushlstring(L, vx->value, vx->value_len);
return 1;
}
}
return 0;
/* Resolve transformation functions. */
tfn_arr = resolve_tfns(L, 2, msr, msr->msc_rule_mptmp);
/* Generate variable. */
vx = generate_single_var(msr, var, tfn_arr, rule, msr->msc_rule_mptmp);
if (vx == NULL) {
lua_pushnil(L);
return 0;
}
/* Return variable value. */
lua_pushlstring(L, vx->value, vx->value_len);
return 1;
}
/**
*
*/
static int l_getvars(lua_State *L) {
const apr_array_header_t *tarr;
const apr_table_entry_t *telts;
apr_table_t *vartable = NULL;
apr_array_header_t *tfn_arr = NULL;
char *varname = NULL, *param = NULL;
modsec_rec *msr = NULL;
msre_rule *rule = NULL;
msre_var *vartemplate = NULL;
char *my_error_msg = NULL;
char *p1 = NULL;
int i;
/* Retrieve parameters. */
p1 = (char *)luaL_checkstring(L, 1);
/* Retrieve msr. */
lua_getglobal(L, "__msr");
msr = (modsec_rec *)lua_topointer(L, -1);
/* Retrieve rule. */
lua_getglobal(L, "__rule");
rule = (msre_rule *)lua_topointer(L, -1);
/* Extract the variable name and its parameter from the script. */
varname = apr_pstrdup(msr->msc_rule_mptmp, p1);
param = strchr(varname, '.');
if (param != NULL) {
*param = '\0';
param++;
}
/* Resolve transformation functions. */
tfn_arr = resolve_tfns(L, 2, msr, msr->msc_rule_mptmp);
lua_newtable(L);
/* Resolve variable. */
vartemplate = msre_create_var_ex(msr->msc_rule_mptmp, msr->modsecurity->msre,
varname, param, msr, &my_error_msg);
if (vartemplate == NULL) {
msr_log(msr, 1, "%s", my_error_msg);
/* Returning empty table. */
return 1;
}
vartable = generate_multi_var(msr, vartemplate, tfn_arr, rule, msr->msc_rule_mptmp);
tarr = apr_table_elts(vartable);
telts = (const apr_table_entry_t*)tarr->elts;
for (i = 0; i < tarr->nelts; i++) {
msre_var *var = (msre_var *)telts[i].val;
lua_pushnumber(L, i + 1); /* Index is not zero-based. */
lua_newtable(L); /* Per-parameter table. */
lua_pushstring(L, "name");
lua_pushlstring(L, var->name, strlen(var->name));
lua_settable(L, -3);
lua_pushstring(L, "value");
lua_pushlstring(L, var->value, var->value_len);
lua_settable(L, -3);
lua_settable(L, -3); /* Push one parameter into the results table. */
}
return 1;
}
static const struct luaL_Reg mylib[] = {
{ "log", l_log },
{ "getvar", l_getvar },
{ "getvars", l_getvars },
{ NULL, NULL }
};
@@ -317,4 +379,3 @@ int lua_execute(msc_script *script, char *param, modsec_rec *msr, msre_rule *rul
return ((*error_msg != NULL) ? RULE_MATCH : RULE_NO_MATCH);
}
#endif

View File

@@ -11,8 +11,6 @@
#ifndef _MSC_LUA_H_
#define _MSC_LUA_H_
#if defined(WITH_LUA)
typedef struct msc_script msc_script;
typedef struct msc_script_part msc_script_part;
@@ -39,4 +37,3 @@ char DSOLOCAL *lua_compile(msc_script **script, const char *filename, apr_pool_t
int DSOLOCAL lua_execute(msc_script *script, char *param, modsec_rec *msr, msre_rule *rule, char **error_msg);
#endif
#endif

View File

@@ -1314,7 +1314,6 @@ msre_rule *msre_rule_create(msre_ruleset *ruleset,
return rule;
}
#ifdef WITH_LUA
/**
*
*/
@@ -1362,7 +1361,6 @@ msre_rule *msre_rule_lua_create(msre_ruleset *ruleset,
return rule;
}
#endif
/**
* Perform non-disruptive actions associated with the provided actionset.
@@ -2001,11 +1999,9 @@ apr_status_t msre_rule_process(msre_rule *rule, modsec_rec *msr) {
apr_pool_clear(msr->msc_rule_mptmp);
}
#if defined(WITH_LUA)
if (rule->type == RULE_TYPE_LUA) {
return msre_rule_process_lua(rule, msr);
}
#endif
return msre_rule_process_normal(rule, msr);
}

View File

@@ -65,9 +65,11 @@ int DSOLOCAL msre_parse_generic(apr_pool_t *pool, const char *text, apr_table_t
int DSOLOCAL rule_id_in_range(int ruleid, const char *range);
msre_var DSOLOCAL *generate_single_var(modsec_rec *msr, msre_var *var, msre_rule *rule,
apr_pool_t *mptmp);
msre_var DSOLOCAL *generate_single_var(modsec_rec *msr, msre_var *var, apr_array_header_t *tfn_arr,
msre_rule *rule, apr_pool_t *mptmp);
apr_table_t DSOLOCAL *generate_multi_var(modsec_rec *msr, msre_var *var, apr_array_header_t *tfn_arr,
msre_rule *rule, apr_pool_t *mptmp);
/* Structures with the corresponding functions */
@@ -143,9 +145,8 @@ struct msre_rule {
unsigned int execution_time;
#endif
#if defined(WITH_LUA)
/* Compiled Lua script. */
msc_script *script;
#endif
};
msre_rule DSOLOCAL *msre_rule_create(msre_ruleset *ruleset,

View File

@@ -39,21 +39,118 @@ static void msre_engine_action_register(msre_engine *engine, const char *name, u
/**
* Generates a single variable (from the supplied metadata).
*/
msre_var *generate_single_var(modsec_rec *msr, msre_var *var, msre_rule *rule,
apr_pool_t *mptmp)
msre_var *generate_single_var(modsec_rec *msr, msre_var *var, apr_array_header_t *tfn_arr,
msre_rule *rule, apr_pool_t *mptmp)
{
apr_table_t *vartab = NULL;
const apr_table_entry_t *te = NULL;
const apr_array_header_t *arr = NULL;
msre_var *rvar = NULL;
int i;
/* Sanity check. */
if ((var == NULL)||(var->metadata == NULL)||(var->metadata->generate == NULL)) return NULL;
if (var->metadata->generate == NULL) return NULL;
vartab = apr_table_make(mptmp, 16);
var->metadata->generate(msr, var, rule, vartab, mptmp);
arr = apr_table_elts(vartab);
if (arr->nelts == 0) return NULL;
te = (apr_table_entry_t *)arr->elts;
te = (apr_table_entry_t *)arr->elts;
return (msre_var *)te[0].val;
rvar = (msre_var *)te[0].val;
/* Return straight away if there were no
* transformation functions supplied.
*/
if ((tfn_arr == NULL)||(tfn_arr->nelts == 0)) {
return rvar;
}
/* Copy the value so that we can transform it in piece. */
rvar->value = apr_pstrndup(mptmp, rvar->value, rvar->value_len);
/* Transform rvar in a loop. */
for (i = 0; i < tfn_arr->nelts; i++) {
msre_tfn_metadata *tfn = ((msre_tfn_metadata **)tfn_arr->elts)[i];
char *rval;
int rc;
long int rval_len;
rc = tfn->execute(mptmp, (unsigned char *)rvar->value,
rvar->value_len, &rval, &rval_len);
rvar->value = rval;
rvar->value_len = rval_len;
if (msr->txcfg->debuglog_level >= 9) {
msr_log(msr, 9, "T (%d) %s: \"%s\"", rc, tfn->name,
log_escape_nq_ex(mptmp, rvar->value, rvar->value_len));
}
}
return rvar;
}
/**
*
*/
apr_table_t *generate_multi_var(modsec_rec *msr, msre_var *var, apr_array_header_t *tfn_arr,
msre_rule *rule, apr_pool_t *mptmp)
{
const apr_array_header_t *tarr;
const apr_table_entry_t *telts;
apr_table_t *vartab = NULL, *tvartab = NULL;
msre_var *rvar = NULL;
int i, j;
/* Sanity check. */
if ((var == NULL)||(var->metadata == NULL)||(var->metadata->generate == NULL)) return NULL;
/* Generate variables. */
vartab = apr_table_make(mptmp, 16);
var->metadata->generate(msr, var, rule, vartab, mptmp);
/* Return straight away if there were no
* transformation functions supplied.
*/
if ((tfn_arr == NULL)||(tfn_arr->nelts == 0)) {
return vartab;
}
tvartab = apr_table_make(mptmp, 16);
tarr = apr_table_elts(vartab);
telts = (const apr_table_entry_t*)tarr->elts;
for (j = 0; j < tarr->nelts; j++) {
rvar = (msre_var *)telts[j].val;
/* Copy the value so that we can transform it in piece. */
rvar->value = apr_pstrndup(mptmp, rvar->value, rvar->value_len);
/* Transform rvar in a loop. */
for (i = 0; i < tfn_arr->nelts; i++) {
msre_tfn_metadata *tfn = ((msre_tfn_metadata **)tfn_arr->elts)[i];
char *rval;
int rc;
long int rval_len;
rc = tfn->execute(mptmp, (unsigned char *)rvar->value,
rvar->value_len, &rval, &rval_len);
rvar->value = rval;
rvar->value_len = rval_len;
if (msr->txcfg->debuglog_level >= 9) {
msr_log(msr, 9, "T (%d) %s: \"%s\"", rc, tfn->name,
log_escape_nq_ex(mptmp, rvar->value, rvar->value_len));
}
}
apr_table_addn(tvartab, rvar->name, (void *)rvar);
}
return tvartab;
}
/**
@@ -137,7 +234,7 @@ int expand_macros(modsec_rec *msr, msc_string *var, msre_rule *rule, apr_pool_t
var_resolved = msre_create_var_ex(mptmp, msr->modsecurity->msre, var_name, var_value,
msr, &my_error_msg);
if (var_resolved != NULL) {
var_generated = generate_single_var(msr, var_resolved, rule, mptmp);
var_generated = generate_single_var(msr, var_resolved, NULL, rule, mptmp);
if (var_generated != NULL) {
part = (msc_string *)apr_pcalloc(mptmp, sizeof(msc_string));
if (part == NULL) return -1;
@@ -1457,7 +1554,6 @@ static char *msre_action_exec_validate(msre_engine *engine, msre_action *action)
/* TODO Support relative filenames. */
#ifdef WITH_LUA
/* Process Lua scripts internally. */
if (strlen(filename) > 4) {
char *p = filename + strlen(filename) - 4;
@@ -1472,7 +1568,6 @@ static char *msre_action_exec_validate(msre_engine *engine, msre_action *action)
action->param_data = script;
}
}
#endif
return NULL;
}