diff options
| author | Arno Töll <arno@debian.org> | 2012-10-20 02:58:14 +0200 |
|---|---|---|
| committer | Arno Töll <arno@debian.org> | 2012-10-20 02:58:14 +0200 |
| commit | 5c4fba3ffbe778bdffe10a93d04821579601a020 (patch) | |
| tree | 91be9a7f99d3988ba48b0a619479aa46a3234191 /modules/lua | |
| parent | 8f9c15530d0bc387af114619b3ff3f930eb23d3c (diff) | |
| download | apache2-5c4fba3ffbe778bdffe10a93d04821579601a020.tar.gz | |
Imported Upstream version 2.4.3upstream/2.4.3
Diffstat (limited to 'modules/lua')
| -rw-r--r-- | modules/lua/README | 7 | ||||
| -rw-r--r-- | modules/lua/lua_config.c | 58 | ||||
| -rw-r--r-- | modules/lua/lua_request.c | 87 | ||||
| -rw-r--r-- | modules/lua/lua_vmprep.c | 218 | ||||
| -rw-r--r-- | modules/lua/lua_vmprep.h | 6 | ||||
| -rw-r--r-- | modules/lua/mod_lua.c | 331 | ||||
| -rw-r--r-- | modules/lua/mod_lua.h | 9 |
7 files changed, 420 insertions, 296 deletions
diff --git a/modules/lua/README b/modules/lua/README index 4efa9cd6..c614b3e2 100644 --- a/modules/lua/README +++ b/modules/lua/README @@ -54,6 +54,13 @@ ** TODO apw_rgetvm needs to handle connection scoped vms ** TODO options in server scoped vms (ie, min and max vm counts) ** TODO provide means to implement authn and authz providers +** TODO: Flatten LuaHook* to LuaHook phase file fn ? +** TODO: Lua and ap_expr integration in one or both directions +** TODO: document or remove block sections +** TODO: test per-dir behavior of block sections +** TODO: Catch-up documentation on r: methods +** TODO: 500 errors instead of 404 with AddHandler lua-script +** TODO: Suppress internal details (fs path to scripts, etc) in error responses * License Apache License, Version 2.0, diff --git a/modules/lua/lua_config.c b/modules/lua/lua_config.c index 0e675652..07dd932b 100644 --- a/modules/lua/lua_config.c +++ b/modules/lua/lua_config.c @@ -154,14 +154,6 @@ static const struct luaL_Reg cfg_methods[] = { {NULL, NULL} }; - -static int cmd_foo(lua_State *L) -{ - cmd_parms *cmd = check_cmd_parms(L, 1); - ap_log_error(APLOG_MARK, APLOG_ERR, 0, cmd->server, APLOGNO(01479) "FOO!"); - return 0; -} - /* helper function for the logging functions below */ static int cmd_log_at(lua_State *L, int level) { @@ -181,88 +173,70 @@ static int cmd_log_at(lua_State *L, int level) /* r:debug(String) and friends which use apache logging */ static int cmd_emerg(lua_State *L) { - cmd_log_at(L, APLOG_EMERG); - return 0; + return cmd_log_at(L, APLOG_EMERG); } static int cmd_alert(lua_State *L) { - cmd_log_at(L, APLOG_ALERT); - return 0; + return cmd_log_at(L, APLOG_ALERT); } static int cmd_crit(lua_State *L) { - cmd_log_at(L, APLOG_CRIT); - return 0; + return cmd_log_at(L, APLOG_CRIT); } static int cmd_err(lua_State *L) { - cmd_log_at(L, APLOG_ERR); - return 0; + return cmd_log_at(L, APLOG_ERR); } static int cmd_warn(lua_State *L) { - cmd_log_at(L, APLOG_WARNING); - return 0; + return cmd_log_at(L, APLOG_WARNING); } static int cmd_notice(lua_State *L) { - cmd_log_at(L, APLOG_NOTICE); - return 0; + return cmd_log_at(L, APLOG_NOTICE); } static int cmd_info(lua_State *L) { - cmd_log_at(L, APLOG_INFO); - return 0; + return cmd_log_at(L, APLOG_INFO); } static int cmd_debug(lua_State *L) { - cmd_log_at(L, APLOG_DEBUG); - return 0; + return cmd_log_at(L, APLOG_DEBUG); } static int cmd_trace1(lua_State *L) { - cmd_log_at(L, APLOG_TRACE1); - return 0; + return cmd_log_at(L, APLOG_TRACE1); } static int cmd_trace2(lua_State *L) { - cmd_log_at(L, APLOG_TRACE2); - return 0; + return cmd_log_at(L, APLOG_TRACE2); } static int cmd_trace3(lua_State *L) { - cmd_log_at(L, APLOG_TRACE3); - return 0; + return cmd_log_at(L, APLOG_TRACE3); } static int cmd_trace4(lua_State *L) { - cmd_log_at(L, APLOG_TRACE4); - return 0; + return cmd_log_at(L, APLOG_TRACE4); } static int cmd_trace5(lua_State *L) { - cmd_log_at(L, APLOG_TRACE5); - return 0; + return cmd_log_at(L, APLOG_TRACE5); } static int cmd_trace6(lua_State *L) { - cmd_log_at(L, APLOG_TRACE6); - return 0; + return cmd_log_at(L, APLOG_TRACE6); } static int cmd_trace7(lua_State *L) { - cmd_log_at(L, APLOG_TRACE7); - return 0; + return cmd_log_at(L, APLOG_TRACE7); } static int cmd_trace8(lua_State *L) { - cmd_log_at(L, APLOG_TRACE8); - return 0; + return cmd_log_at(L, APLOG_TRACE8); } static const struct luaL_Reg cmd_methods[] = { - {"foo", cmd_foo}, - {"trace8", cmd_trace8}, {"trace7", cmd_trace7}, {"trace6", cmd_trace6}, diff --git a/modules/lua/lua_request.c b/modules/lua/lua_request.c index 91bd3b75..9a1cdf8c 100644 --- a/modules/lua/lua_request.c +++ b/modules/lua/lua_request.c @@ -164,6 +164,34 @@ static int req_parseargs(lua_State *L) return 2; /* [table<string, string>, table<string, array<string>>] */ } +/* r:parsebody() returning a lua table */ +static int req_parsebody(lua_State *L) +{ + apr_array_header_t *pairs; + apr_off_t len; + int res; + apr_size_t size; + apr_size_t max_post_size; + char *buffer; + request_rec *r = ap_lua_check_request_rec(L, 1); + max_post_size = (apr_size_t) luaL_optint(L, 2, MAX_STRING_LEN); + lua_newtable(L); + lua_newtable(L); /* [table, table] */ + res = ap_parse_form_data(r, NULL, &pairs, -1, max_post_size); + if (res == OK) { + while(pairs && !apr_is_empty_array(pairs)) { + ap_form_pair_t *pair = (ap_form_pair_t *) apr_array_pop(pairs); + apr_brigade_length(pair->value, 1, &len); + size = (apr_size_t) len; + buffer = apr_palloc(r->pool, size + 1); + apr_brigade_flatten(pair->value, buffer, &size); + buffer[len] = 0; + req_aprtable2luatable_cb(L, pair->name, buffer); + } + } + return 2; /* [table<string, string>, table<string, array<string>>] */ +} + /* wrap ap_rputs as r:puts(String) */ static int req_puts(lua_State *L) { @@ -235,6 +263,16 @@ static const char *req_document_root(request_rec *r) return ap_document_root(r); } +static const char *req_context_prefix(request_rec *r) +{ + return ap_context_prefix(r); +} + +static const char *req_context_document_root(request_rec *r) +{ + return ap_context_document_root(r); +} + static char *req_uri_field(request_rec *r) { return r->uri; @@ -323,6 +361,16 @@ static const char *req_the_request_field(request_rec *r) return r->the_request; } +static const char *req_log_id_field(request_rec *r) +{ + return r->log_id; +} + +static const char *req_useragent_ip_field(request_rec *r) +{ + return r->useragent_ip; +} + static int req_status_field(request_rec *r) { return r->status; @@ -452,49 +500,40 @@ static int req_log_at(lua_State *L, int level) /* r:debug(String) and friends which use apache logging */ static int req_emerg(lua_State *L) { - req_log_at(L, APLOG_EMERG); - return 0; + return req_log_at(L, APLOG_EMERG); } static int req_alert(lua_State *L) { - req_log_at(L, APLOG_ALERT); - return 0; + return req_log_at(L, APLOG_ALERT); } static int req_crit(lua_State *L) { - req_log_at(L, APLOG_CRIT); - return 0; + return req_log_at(L, APLOG_CRIT); } static int req_err(lua_State *L) { - req_log_at(L, APLOG_ERR); - return 0; + return req_log_at(L, APLOG_ERR); } static int req_warn(lua_State *L) { - req_log_at(L, APLOG_WARNING); - return 0; + return req_log_at(L, APLOG_WARNING); } static int req_notice(lua_State *L) { - req_log_at(L, APLOG_NOTICE); - return 0; + return req_log_at(L, APLOG_NOTICE); } static int req_info(lua_State *L) { - req_log_at(L, APLOG_INFO); - return 0; + return req_log_at(L, APLOG_INFO); } static int req_debug(lua_State *L) { - req_log_at(L, APLOG_DEBUG); - return 0; + return req_log_at(L, APLOG_DEBUG); } #define APLUA_REQ_TRACE(lev) static int req_trace##lev(lua_State *L) \ { \ - req_log_at(L, APLOG_TRACE##lev); \ - return 0; \ + return req_log_at(L, APLOG_TRACE##lev); \ } APLUA_REQ_TRACE(1) @@ -608,8 +647,14 @@ AP_LUA_DECLARE(void) ap_lua_load_request_lmodule(lua_State *L, apr_pool_t *p) makefun(&req_write, APL_REQ_FUNTYPE_LUACFUN, p)); apr_hash_set(dispatch, "document_root", APR_HASH_KEY_STRING, makefun(&req_document_root, APL_REQ_FUNTYPE_STRING, p)); + apr_hash_set(dispatch, "context_prefix", APR_HASH_KEY_STRING, + makefun(&req_context_prefix, APL_REQ_FUNTYPE_STRING, p)); + apr_hash_set(dispatch, "context_document_root", APR_HASH_KEY_STRING, + makefun(&req_context_document_root, APL_REQ_FUNTYPE_STRING, p)); apr_hash_set(dispatch, "parseargs", APR_HASH_KEY_STRING, makefun(&req_parseargs, APL_REQ_FUNTYPE_LUACFUN, p)); + apr_hash_set(dispatch, "parsebody", APR_HASH_KEY_STRING, + makefun(&req_parsebody, APL_REQ_FUNTYPE_LUACFUN, p)); apr_hash_set(dispatch, "debug", APR_HASH_KEY_STRING, makefun(&req_debug, APL_REQ_FUNTYPE_LUACFUN, p)); apr_hash_set(dispatch, "info", APR_HASH_KEY_STRING, @@ -688,6 +733,10 @@ AP_LUA_DECLARE(void) ap_lua_load_request_lmodule(lua_State *L, apr_pool_t *p) makefun(&req_uri_field, APL_REQ_FUNTYPE_STRING, p)); apr_hash_set(dispatch, "the_request", APR_HASH_KEY_STRING, makefun(&req_the_request_field, APL_REQ_FUNTYPE_STRING, p)); + apr_hash_set(dispatch, "log_id", APR_HASH_KEY_STRING, + makefun(&req_log_id_field, APL_REQ_FUNTYPE_STRING, p)); + apr_hash_set(dispatch, "useragent_ip", APR_HASH_KEY_STRING, + makefun(&req_useragent_ip_field, APL_REQ_FUNTYPE_STRING, p)); apr_hash_set(dispatch, "method", APR_HASH_KEY_STRING, makefun(&req_method_field, APL_REQ_FUNTYPE_STRING, p)); apr_hash_set(dispatch, "proxyreq", APR_HASH_KEY_STRING, @@ -744,7 +793,7 @@ AP_LUA_DECLARE(void) ap_lua_push_connection(lua_State *L, conn_rec *c) lua_setfield(L, -2, "notes"); lua_pushstring(L, c->client_ip); - lua_setfield(L, -2, "remote_ip"); + lua_setfield(L, -2, "client_ip"); lua_pop(L, 1); } diff --git a/modules/lua/lua_vmprep.c b/modules/lua/lua_vmprep.c index 7c383ca9..e821fee3 100644 --- a/modules/lua/lua_vmprep.c +++ b/modules/lua/lua_vmprep.c @@ -19,6 +19,7 @@ #include "apr_uuid.h" #include "lua_config.h" #include "apr_file_info.h" +#include "mod_auth.h" APLOG_USE_MODULE(lua); @@ -96,6 +97,8 @@ static void pstack_dump(lua_State *L, apr_pool_t *r, int level, /* BEGIN apache lmodule */ +#define makeintegerfield(L, n) lua_pushinteger(L, n); lua_setfield(L, -2, #n) + AP_LUA_DECLARE(void) ap_lua_load_apache2_lmodule(lua_State *L) { lua_getglobal(L, "package"); @@ -106,130 +109,83 @@ AP_LUA_DECLARE(void) ap_lua_load_apache2_lmodule(lua_State *L) lua_pop(L, 1); /* empty stack */ lua_getglobal(L, "apache2"); - lua_pushinteger(L, OK); - lua_setfield(L, -2, "OK"); - - lua_pushinteger(L, DECLINED); - lua_setfield(L, -2, "DECLINED"); - - lua_pushinteger(L, DONE); - lua_setfield(L, -2, "DONE"); lua_pushstring(L, ap_get_server_banner()); lua_setfield(L, -2, "version"); - lua_pushinteger(L, HTTP_MOVED_TEMPORARILY); - lua_setfield(L, -2, "HTTP_MOVED_TEMPORARILY"); - - lua_pushinteger(L, PROXYREQ_NONE); - lua_setfield(L, -2, "PROXYREQ_NONE"); - - lua_pushinteger(L, PROXYREQ_PROXY); - lua_setfield(L, -2, "PROXYREQ_PROXY"); - - lua_pushinteger(L, PROXYREQ_REVERSE); - lua_setfield(L, -2, "PROXYREQ_REVERSE"); - - lua_pushinteger(L, PROXYREQ_RESPONSE); - lua_setfield(L, -2, "PROXYREQ_RESPONSE"); + makeintegerfield(L, OK); + makeintegerfield(L, DECLINED); + makeintegerfield(L, DONE); + makeintegerfield(L, HTTP_MOVED_TEMPORARILY); + makeintegerfield(L, PROXYREQ_NONE); + makeintegerfield(L, PROXYREQ_PROXY); + makeintegerfield(L, PROXYREQ_REVERSE); + makeintegerfield(L, PROXYREQ_RESPONSE); + makeintegerfield(L, PROXYREQ_RESPONSE); + makeintegerfield(L, AUTHZ_DENIED); + makeintegerfield(L, AUTHZ_GRANTED); + makeintegerfield(L, AUTHZ_NEUTRAL); + makeintegerfield(L, AUTHZ_GENERAL_ERROR); + makeintegerfield(L, AUTHZ_DENIED_NO_USER); /* - lua_pushinteger(L, HTTP_CONTINUE); - lua_setfield(L, -2, "HTTP_CONTINUE"); - lua_pushinteger(L, HTTP_SWITCHING_PROTOCOLS); - lua_setfield(L, -2, "HTTP_SWITCHING_PROTOCOLS"); - lua_pushinteger(L, HTTP_PROCESSING); - lua_setfield(L, -2, "HTTP_PROCESSING"); - lua_pushinteger(L, HTTP_OK); - lua_setfield(L, -2, "HTTP_OK"); - lua_pushinteger(L, HTTP_CREATED); - lua_setfield(L, -2, "HTTP_CREATED"); - lua_pushinteger(L, HTTP_ACCEPTED); - lua_setfield(L, -2, "HTTP_ACCEPTED"); - lua_pushinteger(L, HTTP_NON_AUTHORITATIVE); - lua_setfield(L, -2, "HTTP_NON_AUTHORITATIVE"); - lua_pushinteger(L, HTTP_NO_CONTENT); - lua_setfield(L, -2, "HTTP_NO_CONTENT"); - lua_pushinteger(L, HTTP_RESET_CONTENT); - lua_setfield(L, -2, "HTTP_RESET_CONTENT"); - lua_pushinteger(L, HTTP_PARTIAL_CONTENT); - lua_setfield(L, -2, "HTTP_PARTIAL_CONTENT"); - lua_pushinteger(L, HTTP_MULTI_STATUS); - lua_setfield(L, -2, "HTTP_MULTI_STATUS"); - lua_pushinteger(L, HTTP_MULTIPLE_CHOICES); - lua_setfield(L, -2, "HTTP_MULTIPLE_CHOICES"); - lua_pushinteger(L, HTTP_MOVED_PERMANENTLY); - lua_setfield(L, -2, "HTTP_MOVED_PERMANENTLY"); - lua_pushinteger(L, HTTP_SEE_OTHER); - lua_setfield(L, -2, "HTTP_SEE_OTHER"); - lua_pushinteger(L, HTTP_NOT_MODIFIED); - lua_setfield(L, -2, "HTTP_NOT_MODIFIED"); - lua_pushinteger(L, HTTP_USE_PROXY); - lua_setfield(L, -2, "HTTP_USE_PROXY"); - lua_pushinteger(L, HTTP_TEMPORARY_REDIRECT); - lua_setfield(L, -2, "HTTP_TEMPORARY_REDIRECT"); - lua_pushinteger(L, HTTP_BAD_REQUEST); - lua_setfield(L, -2, "HTTP_BAD_REQUEST"); - lua_pushinteger(L, HTTP_UNAUTHORIZED); - lua_setfield(L, -2, "HTTP_UNAUTHORIZED"); - lua_pushinteger(L, HTTP_PAYMENT_REQUIRED); - lua_setfield(L, -2, "HTTP_PAYMENT_REQUIRED"); - lua_pushinteger(L, HTTP_FORBIDDEN); - lua_setfield(L, -2, "HTTP_FORBIDDEN"); - lua_pushinteger(L, HTTP_NOT_FOUND); - lua_setfield(L, -2, "HTTP_NOT_FOUND"); - lua_pushinteger(L, HTTP_METHOD_NOT_ALLOWED); - lua_setfield(L, -2, "HTTP_METHOD_NOT_ALLOWED"); - lua_pushinteger(L, HTTP_NOT_ACCEPTABLE); - lua_setfield(L, -2, "HTTP_NOT_ACCEPTABLE"); - lua_pushinteger(L, HTTP_PROXY_AUTHENTICATION_REQUIRED); - lua_setfield(L, -2, "HTTP_PROXY_AUTHENTICATION_REQUIRED"); - lua_pushinteger(L, HTTP_REQUEST_TIME_OUT); - lua_setfield(L, -2, "HTTP_REQUEST_TIME_OUT"); - lua_pushinteger(L, HTTP_CONFLICT); - lua_setfield(L, -2, "HTTP_CONFLICT"); - lua_pushinteger(L, HTTP_GONE); - lua_setfield(L, -2, "HTTP_GONE"); - lua_pushinteger(L, HTTP_LENGTH_REQUIRED); - lua_setfield(L, -2, "HTTP_LENGTH_REQUIRED"); - lua_pushinteger(L, HTTP_PRECONDITION_FAILED); - lua_setfield(L, -2, "HTTP_PRECONDITION_FAILED"); - lua_pushinteger(L, HTTP_REQUEST_ENTITY_TOO_LARGE); - lua_setfield(L, -2, "HTTP_REQUEST_ENTITY_TOO_LARGE"); - lua_pushinteger(L, HTTP_REQUEST_URI_TOO_LARGE); - lua_setfield(L, -2, "HTTP_REQUEST_URI_TOO_LARGE"); - lua_pushinteger(L, HTTP_UNSUPPORTED_MEDIA_TYPE); - lua_setfield(L, -2, "HTTP_UNSUPPORTED_MEDIA_TYPE"); - lua_pushinteger(L, HTTP_RANGE_NOT_SATISFIABLE); - lua_setfield(L, -2, "HTTP_RANGE_NOT_SATISFIABLE"); - lua_pushinteger(L, HTTP_EXPECTATION_FAILED); - lua_setfield(L, -2, "HTTP_EXPECTATION_FAILED"); - lua_pushinteger(L, HTTP_UNPROCESSABLE_ENTITY); - lua_setfield(L, -2, "HTTP_UNPROCESSABLE_ENTITY"); - lua_pushinteger(L, HTTP_LOCKED); - lua_setfield(L, -2, "HTTP_LOCKED"); - lua_pushinteger(L, HTTP_FAILED_DEPENDENCY); - lua_setfield(L, -2, "HTTP_FAILED_DEPENDENCY"); - lua_pushinteger(L, HTTP_UPGRADE_REQUIRED); - lua_setfield(L, -2, "HTTP_UPGRADE_REQUIRED"); - lua_pushinteger(L, HTTP_INTERNAL_SERVER_ERROR); - lua_setfield(L, -2, "HTTP_INTERNAL_SERVER_ERROR"); - lua_pushinteger(L, HTTP_NOT_IMPLEMENTED); - lua_setfield(L, -2, "HTTP_NOT_IMPLEMENTED"); - lua_pushinteger(L, HTTP_BAD_GATEWAY); - lua_setfield(L, -2, "HTTP_BAD_GATEWAY"); - lua_pushinteger(L, HTTP_SERVICE_UNAVAILABLE); - lua_setfield(L, -2, "HTTP_SERVICE_UNAVAILABLE"); - lua_pushinteger(L, HTTP_GATEWAY_TIME_OUT); - lua_setfield(L, -2, "HTTP_GATEWAY_TIME_OUT"); - lua_pushinteger(L, HTTP_VERSION_NOT_SUPPORTED); - lua_setfield(L, -2, "HTTP_VERSION_NOT_SUPPORTED"); - lua_pushinteger(L, HTTP_VARIANT_ALSO_VARIES); - lua_setfield(L, -2, "HTTP_VARIANT_ALSO_VARIES"); - lua_pushinteger(L, HTTP_INSUFFICIENT_STORAGE); - lua_setfield(L, -2, "HTTP_INSUFFICIENT_STORAGE"); - lua_pushinteger(L, HTTP_NOT_EXTENDED); - lua_setfield(L, -2, "HTTP_NOT_EXTENDED"); + makeintegerfield(L, HTTP_CONTINUE); + makeintegerfield(L, HTTP_SWITCHING_PROTOCOLS); + makeintegerfield(L, HTTP_PROCESSING); + makeintegerfield(L, HTTP_OK); + makeintegerfield(L, HTTP_CREATED); + makeintegerfield(L, HTTP_ACCEPTED); + makeintegerfield(L, HTTP_NON_AUTHORITATIVE); + makeintegerfield(L, HTTP_NO_CONTENT); + makeintegerfield(L, HTTP_RESET_CONTENT); + makeintegerfield(L, HTTP_PARTIAL_CONTENT); + makeintegerfield(L, HTTP_MULTI_STATUS); + makeintegerfield(L, HTTP_ALREADY_REPORTED); + makeintegerfield(L, HTTP_IM_USED); + makeintegerfield(L, HTTP_MULTIPLE_CHOICES); + makeintegerfield(L, HTTP_MOVED_PERMANENTLY); + makeintegerfield(L, HTTP_MOVED_TEMPORARILY); + makeintegerfield(L, HTTP_SEE_OTHER); + makeintegerfield(L, HTTP_NOT_MODIFIED); + makeintegerfield(L, HTTP_USE_PROXY); + makeintegerfield(L, HTTP_TEMPORARY_REDIRECT); + makeintegerfield(L, HTTP_PERMANENT_REDIRECT); + makeintegerfield(L, HTTP_BAD_REQUEST); + makeintegerfield(L, HTTP_UNAUTHORIZED); + makeintegerfield(L, HTTP_PAYMENT_REQUIRED); + makeintegerfield(L, HTTP_FORBIDDEN); + makeintegerfield(L, HTTP_NOT_FOUND); + makeintegerfield(L, HTTP_METHOD_NOT_ALLOWED); + makeintegerfield(L, HTTP_NOT_ACCEPTABLE); + makeintegerfield(L, HTTP_PROXY_AUTHENTICATION_REQUIRED); + makeintegerfield(L, HTTP_REQUEST_TIME_OUT); + makeintegerfield(L, HTTP_CONFLICT); + makeintegerfield(L, HTTP_GONE); + makeintegerfield(L, HTTP_LENGTH_REQUIRED); + makeintegerfield(L, HTTP_PRECONDITION_FAILED); + makeintegerfield(L, HTTP_REQUEST_ENTITY_TOO_LARGE); + makeintegerfield(L, HTTP_REQUEST_URI_TOO_LARGE); + makeintegerfield(L, HTTP_UNSUPPORTED_MEDIA_TYPE); + makeintegerfield(L, HTTP_RANGE_NOT_SATISFIABLE); + makeintegerfield(L, HTTP_EXPECTATION_FAILED); + makeintegerfield(L, HTTP_UNPROCESSABLE_ENTITY); + makeintegerfield(L, HTTP_LOCKED); + makeintegerfield(L, HTTP_FAILED_DEPENDENCY); + makeintegerfield(L, HTTP_UPGRADE_REQUIRED); + makeintegerfield(L, HTTP_PRECONDITION_REQUIRED); + makeintegerfield(L, HTTP_TOO_MANY_REQUESTS); + makeintegerfield(L, HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE); + makeintegerfield(L, HTTP_INTERNAL_SERVER_ERROR); + makeintegerfield(L, HTTP_NOT_IMPLEMENTED); + makeintegerfield(L, HTTP_BAD_GATEWAY); + makeintegerfield(L, HTTP_SERVICE_UNAVAILABLE); + makeintegerfield(L, HTTP_GATEWAY_TIME_OUT); + makeintegerfield(L, HTTP_VERSION_NOT_SUPPORTED); + makeintegerfield(L, HTTP_VARIANT_ALSO_VARIES); + makeintegerfield(L, HTTP_INSUFFICIENT_STORAGE); + makeintegerfield(L, HTTP_LOOP_DETECTED); + makeintegerfield(L, HTTP_NOT_EXTENDED); + makeintegerfield(L, HTTP_NETWORK_AUTHENTICATION_REQUIRED); */ } @@ -240,6 +196,7 @@ AP_LUA_DECLARE(void) ap_lua_load_apache2_lmodule(lua_State *L) /* callback for cleaning up a lua vm when pool is closed */ static apr_status_t cleanup_lua(void *l) { + AP_DEBUG_ASSERT(l != NULL); lua_close((lua_State *) l); return APR_SUCCESS; } @@ -319,7 +276,7 @@ static int loadjitmodule(lua_State *L, apr_pool_t *lifecycle_pool) { #endif -static apr_status_t vm_construct(void **vm, void *params, apr_pool_t *lifecycle_pool) +static apr_status_t vm_construct(lua_State **vm, void *params, apr_pool_t *lifecycle_pool) { lua_State* L; @@ -357,24 +314,10 @@ static apr_status_t vm_construct(void **vm, void *params, apr_pool_t *lifecycle_ "loading lua file %s", spec->file); rc = luaL_loadfile(L, spec->file); if (rc != 0) { - char *err; - switch (rc) { - case LUA_ERRSYNTAX: - err = "syntax error"; - break; - case LUA_ERRMEM: - err = "memory allocation error"; - break; - case LUA_ERRFILE: - err = "error opening or reading file"; - break; - default: - err = "unknown error"; - break; - } ap_log_perror(APLOG_MARK, APLOG_ERR, 0, lifecycle_pool, APLOGNO(01482) - "Loading lua file %s: %s", - spec->file, err); + "Error loading %s: %s", spec->file, + rc == LUA_ERRMEM ? "memory allocation error" + : lua_tostring(L, 0)); return APR_EBADF; } lua_pcall(L, 0, LUA_MULTRET, 0); @@ -407,7 +350,8 @@ AP_LUA_DECLARE(lua_State*)ap_lua_get_lua_state(apr_pool_t *lifecycle_pool, "creating lua_State with file %s", spec->file); /* not available, so create */ - if(!vm_construct((void **)&L, spec, lifecycle_pool)) { + if(!vm_construct(&L, spec, lifecycle_pool)) { + AP_DEBUG_ASSERT(L != NULL); apr_pool_userdata_set(L, spec->file, cleanup_lua, diff --git a/modules/lua/lua_vmprep.h b/modules/lua/lua_vmprep.h index be1750df..1d3758ca 100644 --- a/modules/lua/lua_vmprep.h +++ b/modules/lua/lua_vmprep.h @@ -54,7 +54,7 @@ typedef struct apr_array_header_t *package_cpaths; /* name of base file to load in the vm */ - char *file; + const char *file; /* APL_SCOPE_ONCE | APL_SCOPE_REQUEST | APL_SCOPE_CONN | APL_SCOPE_THREAD */ int scope; @@ -75,8 +75,8 @@ typedef struct typedef struct { - char *function_name; - char *file_name; + const char *function_name; + const char *file_name; int scope; ap_regex_t *uri_pattern; const char *bytecode; diff --git a/modules/lua/mod_lua.c b/modules/lua/mod_lua.c index 095e54fd..b5b626d1 100644 --- a/modules/lua/mod_lua.c +++ b/modules/lua/mod_lua.c @@ -24,6 +24,7 @@ #include "lua_config.h" #include "apr_optional.h" #include "mod_ssl.h" +#include "mod_auth.h" #ifdef APR_HAS_THREADS #include "apr_thread_proc.h" @@ -39,11 +40,22 @@ APR_IMPLEMENT_OPTIONAL_HOOK_RUN_ALL(ap_lua, AP_LUA, int, lua_request, static APR_OPTIONAL_FN_TYPE(ssl_var_lookup) *lua_ssl_val = NULL; static APR_OPTIONAL_FN_TYPE(ssl_is_https) *lua_ssl_is_https = NULL; - module AP_MODULE_DECLARE_DATA lua_module; +module AP_MODULE_DECLARE_DATA lua_module; #define AP_LUA_HOOK_FIRST (APR_HOOK_FIRST - 1) #define AP_LUA_HOOK_LAST (APR_HOOK_LAST + 1) +typedef struct { + const char *name; + const char *file_name; + const char *function_name; + ap_lua_vm_spec *spec; + apr_array_header_t *args; +} lua_authz_provider_spec; + +apr_hash_t *lua_authz_providers; + + /** * error reporting if lua has an error. * Extracts the error from lua stack and prints @@ -78,73 +90,114 @@ static int lua_open_hook(lua_State *L, apr_pool_t *p) return OK; } +static const char *scope_to_string(unsigned int scope) +{ + switch (scope) { + case AP_LUA_SCOPE_ONCE: + case AP_LUA_SCOPE_UNSET: + return "once"; + case AP_LUA_SCOPE_REQUEST: + return "request"; + case AP_LUA_SCOPE_CONN: + return "conn"; +#if APR_HAS_THREADS + case AP_LUA_SCOPE_THREAD: + return "thread"; +#endif + default: + ap_assert(0); + } +} + +static ap_lua_vm_spec *create_vm_spec(apr_pool_t **lifecycle_pool, + request_rec *r, + const ap_lua_dir_cfg *cfg, + const ap_lua_server_cfg *server_cfg, + const char *filename, + const char *bytecode, + apr_size_t bytecode_len, + const char *function, + const char *what) +{ + apr_pool_t *pool; + ap_lua_vm_spec *spec = apr_pcalloc(r->pool, sizeof(ap_lua_vm_spec)); + + spec->scope = cfg->vm_scope; + spec->pool = r->pool; + spec->package_paths = cfg->package_paths; + spec->package_cpaths = cfg->package_cpaths; + spec->cb = &lua_open_callback; + spec->cb_arg = NULL; + spec->bytecode = bytecode; + spec->bytecode_len = bytecode_len; + + if (filename) { + char *file; + apr_filepath_merge(&file, server_cfg->root_path, + filename, APR_FILEPATH_NOTRELATIVE, r->pool); + spec->file = file; + } + else { + spec->file = r->filename; + } + ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r, APLOGNO(02313) + "%s details: scope: %s, file: %s, func: %s", + what, scope_to_string(spec->scope), spec->file, + function ? function : "-"); + + switch (spec->scope) { + case AP_LUA_SCOPE_ONCE: + case AP_LUA_SCOPE_UNSET: + apr_pool_create(&pool, r->pool); + break; + case AP_LUA_SCOPE_REQUEST: + pool = r->pool; + break; + case AP_LUA_SCOPE_CONN: + pool = r->connection->pool; + break; +#if APR_HAS_THREADS + case AP_LUA_SCOPE_THREAD: + pool = apr_thread_pool_get(r->connection->current_thread); + break; +#endif + default: + ap_assert(0); + } + + *lifecycle_pool = pool; + return spec; +} + /** * "main" */ static int lua_handler(request_rec *r) { - ap_lua_dir_cfg *dcfg; - apr_pool_t *pool; if (strcmp(r->handler, "lua-script")) { return DECLINED; } - - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01472) "handling [%s] in mod_lua", - r->filename); - dcfg = ap_get_module_config(r->per_dir_config, &lua_module); + ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, APLOGNO(01472) + "handling [%s] in mod_lua", r->filename); + /* XXX: This seems wrong because it may generate wrong headers for HEAD requests */ if (!r->header_only) { lua_State *L; + apr_pool_t *pool; const ap_lua_dir_cfg *cfg = ap_get_module_config(r->per_dir_config, &lua_module); - ap_lua_vm_spec *spec = NULL; + ap_lua_vm_spec *spec = create_vm_spec(&pool, r, cfg, NULL, NULL, NULL, + 0, "handle", "request handler"); - spec = apr_pcalloc(r->pool, sizeof(ap_lua_vm_spec)); - spec->scope = dcfg->vm_scope; - spec->pool = r->pool; - spec->file = r->filename; - spec->package_paths = cfg->package_paths; - spec->package_cpaths = cfg->package_cpaths; - spec->cb = &lua_open_callback; - spec->cb_arg = NULL; - - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01473) - "request details scope:%u, filename:%s, function:%s", - spec->scope, - spec->file, - "handle"); - - switch (spec->scope) { - case AP_LUA_SCOPE_ONCE: - case AP_LUA_SCOPE_UNSET: - apr_pool_create(&pool, r->pool); - break; - case AP_LUA_SCOPE_REQUEST: - pool = r->pool; - break; - case AP_LUA_SCOPE_CONN: - pool = r->connection->pool; - break; - case AP_LUA_SCOPE_THREAD: - #if APR_HAS_THREADS - pool = apr_thread_pool_get(r->connection->current_thread); - break; - #endif - default: - ap_assert(0); - } - - L = ap_lua_get_lua_state(pool, - spec); - + L = ap_lua_get_lua_state(pool, spec); if (!L) { /* TODO annotate spec with failure reason */ r->status = HTTP_INTERNAL_SERVER_ERROR; ap_rputs("Unable to compile VM, see logs", r); return HTTP_INTERNAL_SERVER_ERROR; } - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01474) "got a vm!"); + ap_log_rerror(APLOG_MARK, APLOG_TRACE3, 0, r, APLOGNO(01474) "got a vm!"); lua_getglobal(L, "handle"); if (!lua_isfunction(L, -1)) { ap_log_rerror(APLOG_MARK, APLOG_CRIT, 0, r, APLOGNO(01475) @@ -163,7 +216,6 @@ static int lua_handler(request_rec *r) - /* ---------------- Configury stuff --------------- */ /** harnesses for magic hooks **/ @@ -190,46 +242,12 @@ static int lua_request_rec_hook_harness(request_rec *r, const char *name, int ap if (hook_spec == NULL) { continue; } - spec = apr_pcalloc(r->pool, sizeof(ap_lua_vm_spec)); - - spec->file = hook_spec->file_name; - spec->scope = cfg->vm_scope; - spec->bytecode = hook_spec->bytecode; - spec->bytecode_len = hook_spec->bytecode_len; - spec->pool = r->pool; - spec->package_paths = cfg->package_paths; - spec->package_cpaths = cfg->package_cpaths; - spec->cb = &lua_open_callback; - spec->cb_arg = NULL; - - apr_filepath_merge(&spec->file, server_cfg->root_path, - spec->file, APR_FILEPATH_NOTRELATIVE, r->pool); - - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01476) - "request details scope:%u, filename:%s, function:%s", - spec->scope, - spec->file, - hook_spec->function_name ? hook_spec->function_name : "-"); - - switch (spec->scope) { - case AP_LUA_SCOPE_ONCE: - case AP_LUA_SCOPE_UNSET: - apr_pool_create(&pool, r->pool); - break; - case AP_LUA_SCOPE_REQUEST: - pool = r->pool; - break; - case AP_LUA_SCOPE_CONN: - pool = r->connection->pool; - break; - case AP_LUA_SCOPE_THREAD: - #if APR_HAS_THREADS - pool = apr_thread_pool_get(r->connection->current_thread); - break; - #endif - default: - ap_assert(0); - } + spec = create_vm_spec(&pool, r, cfg, server_cfg, + hook_spec->file_name, + hook_spec->bytecode, + hook_spec->bytecode_len, + hook_spec->function_name, + "request hook"); L = ap_lua_get_lua_state(pool, spec); @@ -450,16 +468,15 @@ static const char *register_named_block_function_hook(const char *name, { cr_ctx ctx; - char buf[32]; lua_State *lvm; char *tmp; int rv; ap_directive_t **current; hack_section_baton *baton; - apr_snprintf(buf, sizeof(buf), "%u", cmd->config_file->line_number); - spec->file_name = apr_pstrcat(cmd->pool, cmd->config_file->name, ":", - buf, NULL); + spec->file_name = apr_psprintf(cmd->pool, "%s:%u", + cmd->config_file->name, + cmd->config_file->line_number); if (function) { spec->function_name = (char *) function; } @@ -959,6 +976,131 @@ AP_LUA_DECLARE(int) ap_lua_ssl_is_https(conn_rec *c) /*******************************/ +static const char *lua_authz_parse(cmd_parms *cmd, const char *require_line, + const void **parsed_require_line) +{ + const char *provider_name; + lua_authz_provider_spec *spec; + + apr_pool_userdata_get((void**)&provider_name, AUTHZ_PROVIDER_NAME_NOTE, + cmd->temp_pool); + ap_assert(provider_name != NULL); + + spec = apr_hash_get(lua_authz_providers, provider_name, APR_HASH_KEY_STRING); + ap_assert(spec != NULL); + + if (require_line && *require_line) { + const char *arg; + spec->args = apr_array_make(cmd->pool, 2, sizeof(const char *)); + while ((arg = ap_getword_conf(cmd->pool, &require_line)) && *arg) { + APR_ARRAY_PUSH(spec->args, const char *) = arg; + } + } + + *parsed_require_line = spec; + return NULL; +} + +static authz_status lua_authz_check(request_rec *r, const char *require_line, + const void *parsed_require_line) +{ + apr_pool_t *pool; + ap_lua_vm_spec *spec; + lua_State *L; + ap_lua_server_cfg *server_cfg = ap_get_module_config(r->server->module_config, + &lua_module); + const ap_lua_dir_cfg *cfg = ap_get_module_config(r->per_dir_config, + &lua_module); + const lua_authz_provider_spec *prov_spec = parsed_require_line; + int result; + int nargs = 0; + + spec = create_vm_spec(&pool, r, cfg, server_cfg, prov_spec->file_name, + NULL, 0, prov_spec->function_name, "authz provider"); + + L = ap_lua_get_lua_state(pool, spec); + if (L == NULL) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02314) + "Unable to compile VM for authz provider %s", prov_spec->name); + return AUTHZ_GENERAL_ERROR; + } + lua_getglobal(L, prov_spec->function_name); + if (!lua_isfunction(L, -1)) { + ap_log_rerror(APLOG_MARK, APLOG_CRIT, 0, r, APLOGNO(02319) + "Unable to find function %s in %s", + prov_spec->function_name, prov_spec->file_name); + return AUTHZ_GENERAL_ERROR; + } + ap_lua_run_lua_request(L, r); + if (prov_spec->args) { + int i; + if (!lua_checkstack(L, prov_spec->args->nelts)) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02315) + "Error: authz provider %s: too many arguments", prov_spec->name); + return AUTHZ_GENERAL_ERROR; + } + for (i = 0; i < prov_spec->args->nelts; i++) { + const char *arg = APR_ARRAY_IDX(prov_spec->args, i, const char *); + lua_pushstring(L, arg); + } + nargs = prov_spec->args->nelts; + } + if (lua_pcall(L, 1 + nargs, 1, 0)) { + const char *err = lua_tostring(L, -1); + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02316) + "Error executing authz provider %s: %s", prov_spec->name, err); + return AUTHZ_GENERAL_ERROR; + } + if (!lua_isnumber(L, -1)) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02317) + "Error: authz provider %s did not return integer", prov_spec->name); + return AUTHZ_GENERAL_ERROR; + } + result = lua_tointeger(L, -1); + switch (result) { + case AUTHZ_DENIED: + case AUTHZ_GRANTED: + case AUTHZ_NEUTRAL: + case AUTHZ_GENERAL_ERROR: + case AUTHZ_DENIED_NO_USER: + return result; + default: + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02318) + "Error: authz provider %s: invalid return value %d", + prov_spec->name, result); + } + return AUTHZ_GENERAL_ERROR; +} + +static const authz_provider lua_authz_provider = +{ + &lua_authz_check, + &lua_authz_parse, +}; + +static const char *register_authz_provider(cmd_parms *cmd, void *_cfg, + const char *name, const char *file, + const char *function) +{ + lua_authz_provider_spec *spec; + const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY); + if (err) + return err; + + spec = apr_pcalloc(cmd->pool, sizeof(*spec)); + spec->name = name; + spec->file_name = file; + spec->function_name = function; + + apr_hash_set(lua_authz_providers, name, APR_HASH_KEY_STRING, spec); + ap_register_auth_provider(cmd->pool, AUTHZ_PROVIDER_GROUP, name, + AUTHZ_PROVIDER_VERSION, + &lua_authz_provider, + AP_AUTH_INTERNAL_PER_CONF); + return NULL; +} + + command_rec lua_commands[] = { AP_INIT_TAKE1("LuaRoot", register_lua_root, NULL, OR_ALL, @@ -970,6 +1112,8 @@ command_rec lua_commands[] = { AP_INIT_TAKE1("LuaPackageCPath", register_package_cdir, NULL, OR_ALL, "Add a directory to lua's package.cpath"), + AP_INIT_TAKE3("LuaAuthzProvider", register_authz_provider, NULL, RSRC_CONF|EXEC_ON_READ, + "Provide an authorization provider"), AP_INIT_TAKE23("LuaHookTranslateName", register_translate_name_hook, NULL, OR_ALL, @@ -1202,6 +1346,9 @@ static void lua_register_hooks(apr_pool_t *p) APR_OPTIONAL_HOOK(ap_lua, lua_request, lua_request_hook, NULL, NULL, APR_HOOK_REALLY_FIRST); + + /* providers */ + lua_authz_providers = apr_hash_make(p); } AP_DECLARE_MODULE(lua) = { diff --git a/modules/lua/mod_lua.h b/modules/lua/mod_lua.h index 5394f7a4..52ff96ad 100644 --- a/modules/lua/mod_lua.h +++ b/modules/lua/mod_lua.h @@ -40,6 +40,9 @@ #include "apr_time.h" #include "apr_hooks.h" +/* Allow for Lua 5.2 backwards compatibility */ +#define LUA_COMPAT_ALL + #include "lua.h" #include "lauxlib.h" #include "lualib.h" @@ -113,7 +116,7 @@ typedef struct apr_hash_t *hooks; /* <wombat_hook_info> */ /* the actual directory being configured */ - char *dir; + const char *dir; /* Whether Lua scripts in a sub-dir are run before parents */ ap_lua_inherit_t inherit; @@ -131,7 +134,7 @@ typedef struct typedef struct { - char *function_name; + const char *function_name; ap_lua_vm_spec *spec; } mapped_request_details; @@ -144,7 +147,7 @@ typedef struct typedef struct { lua_State *L; - char *function; + const char *function; } ap_lua_filter_ctx; extern module AP_MODULE_DECLARE_DATA lua_module; |
