source: mod_gnutls/src/gnutls_lua.c @ b4a875b

debian/masterdebian/stretch-backportsjessie-backportsmsvaupstream
Last change on this file since b4a875b was e02dd8c, checked in by Nikos Mavrogiannopoulos <nmav@…>, 9 years ago

indented code

  • Property mode set to 100644
File size: 6.7 KB
Line 
1/**
2 *  Copyright 2004-2005 Paul Querna
3 *
4 *  Licensed under the Apache License, Version 2.0 (the "License");
5 *  you may not use this file except in compliance with the License.
6 *  You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 *  Unless required by applicable law or agreed to in writing, software
11 *  distributed under the License is distributed on an "AS IS" BASIS,
12 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 *  See the License for the specific language governing permissions and
14 *  limitations under the License.
15 *
16 */
17
18#include "mod_gnutls.h"
19
20#include "lua.h"
21#include "lualib.h"
22#include "lauxlib.h"
23
24#include <ctype.h>
25
26static char *MGS_LUA_RRKEY = "request_rec";
27
28static request_rec *mgs_lua_getrr(lua_State * lvm)
29{
30        request_rec *r;
31
32        /* Push the request_rec off the registry, onto the stack. */
33        lua_pushlightuserdata(lvm, MGS_LUA_RRKEY);
34        lua_gettable(lvm, LUA_REGISTRYINDEX);
35        r = lua_touserdata(lvm, -1);
36        lua_pop(lvm, 1);
37        return r;
38}
39
40static int get_request_table(lua_State * lvm, long offset)
41{
42        const char *key;
43        request_rec *r;
44        const char *value;
45        apr_table_t *t;
46        key = luaL_checkstring(lvm, 1);
47
48        r = mgs_lua_getrr(lvm);
49
50        t = *(apr_table_t **) ((char *) r + offset);
51
52        value = apr_table_get(t, key);
53
54        if (value) {
55                lua_pushstring(lvm, value);
56                return 1;
57        } else {
58                return 0;
59        }
60}
61
62static int mgs_lua_getenv(lua_State * lvm)
63{
64        return get_request_table(lvm,
65                                 APR_OFFSETOF(request_rec,
66                                              subprocess_env));
67}
68
69static int mgs_lua_getheader(lua_State * lvm)
70{
71        return get_request_table(lvm,
72                                 APR_OFFSETOF(request_rec, headers_in));
73}
74
75static const luaL_reg mgs_lua_reg[] = {
76        {"getenv", mgs_lua_getenv},
77        {"header", mgs_lua_getheader},
78        {NULL, NULL}
79};
80
81lua_State *get_luastate()
82{
83        lua_State *lvm = lua_open();
84        luaopen_base(lvm);
85        luaopen_io(lvm);
86        luaopen_table(lvm);
87        luaopen_string(lvm);
88        luaopen_math(lvm);
89        luaopen_loadlib(lvm);
90        luaL_openlib(lvm, "ap", mgs_lua_reg, 0);
91
92        return lvm;
93}
94
95int mgs_authz_lua(request_rec * r)
96{
97        int rv;
98        lua_State *lvm;
99        mgs_dirconf_rec *dc = ap_get_module_config(r->per_dir_config,
100                                                   &gnutls_module);
101
102        if (dc->lua_bytecode_len <= 0) {
103                return 0;
104        }
105
106        lvm = get_luastate();
107        lua_pushlightuserdata(lvm, MGS_LUA_RRKEY);
108        lua_pushlightuserdata(lvm, r);
109        lua_settable(lvm, LUA_REGISTRYINDEX);
110
111        /* Push Bytecode onto the stack */
112        rv = luaL_loadbuffer(lvm, dc->lua_bytecode, dc->lua_bytecode_len,
113                             "gnutls-lua");
114
115        if (rv != 0) {
116                /* Get the Error message */
117                const char *error = lua_tostring(lvm, -1);
118                ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
119                              "GnuTLS: Error Loading Lua Bytecode: %s",
120                              error);
121                lua_pop(lvm, 1);
122                return -1;
123        }
124
125        rv = lua_pcall(lvm, 0, 1, 0);
126        if (rv != 0) {
127                /* Get the Error message */
128                const char *error = lua_tostring(lvm, -1);
129                ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
130                              "GnuTLS: Error Running Lua: %s", error);
131                lua_pop(lvm, 1);
132                return -1;
133        }
134
135        rv = (int) lua_tonumber(lvm, -1);
136        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
137                      "GnuTLS: (%d) Lua Return: %d",
138                      dc->lua_bytecode_len, rv);
139        lua_pop(lvm, 1);
140        lua_close(lvm);
141        return rv;
142}
143
144static apr_size_t config_getstr(ap_configfile_t * cfg, char *buf,
145                                size_t bufsiz)
146{
147        apr_size_t i = 0;
148
149        if (cfg->getstr) {
150                const char *res = (cfg->getstr) (buf, bufsiz, cfg->param);
151                if (res) {
152                        i = strlen(buf);
153                        if (i && buf[i - 1] == '\n')
154                                ++cfg->line_number;
155                } else {
156                        buf[0] = '\0';
157                        i = 0;
158                }
159        } else {
160                while (i < bufsiz) {
161                        int ch = (cfg->getch) (cfg->param);
162                        if (ch == EOF)
163                                break;
164                        buf[i++] = ch;
165                        if (ch == '\n') {
166                                ++cfg->line_number;
167                                break;
168                        }
169                }
170        }
171        return i;
172}
173
174struct cr_ctx {
175        ap_configfile_t *cfp;
176        size_t startline;
177        char buf[HUGE_STRING_LEN];
178};
179
180static const char *LUACMD = "gnutlsrequire";
181static const char *lf =
182    "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n";
183#define N_LF 32
184
185static const char *direct_chunkreader(lua_State * lvm, void *udata,
186                                      size_t * plen)
187{
188        const char *p;
189        struct cr_ctx *ctx = udata;
190
191        if (ctx->startline) {
192                *plen = ctx->startline > N_LF ? N_LF : ctx->startline;
193                ctx->startline -= *plen;
194                return lf;
195        }
196        *plen = config_getstr(ctx->cfp, ctx->buf, HUGE_STRING_LEN);
197
198        for (p = ctx->buf; isspace(*p); ++p);
199        if (p[0] == '<' && p[1] == '/') {
200                int i = 0;
201                while (i < strlen(LUACMD)) {
202                        if (tolower(p[i + 2]) != LUACMD[i])
203                                return ctx->buf;
204                        ++i;
205                }
206                *plen = 0;
207                return NULL;
208        }
209        return ctx->buf;
210}
211
212static int ldump_writer(lua_State * L, const void *b, size_t size, void *B)
213{
214        (void) L;
215        luaL_addlstring((luaL_Buffer *) B, (const char *) b, size);
216        return 1;
217}
218
219/* a bytecode buffer*/
220typedef struct bcbuf_ctx {
221        apr_size_t buflen;
222        char *buf;
223} bcbuf_ctx;
224
225const char *mgs_set_require_section(cmd_parms * cmd, void *mconfig,
226                                    const char *arg)
227{
228        apr_size_t bytecode_len;
229        const char *bytecode;
230        bcbuf_ctx *bcbuf;
231        luaL_Buffer b;
232        ap_directive_t **current = mconfig;
233        struct cr_ctx ctx[1];
234        int result;
235        const char *filename =
236            apr_psprintf(cmd->pool, "@%s", cmd->config_file->name);
237        // get a word argument
238        const char *word;
239        apr_size_t wordlen;
240        lua_State *lvm = get_luastate();
241
242        word = ap_getword_conf(cmd->pool, &arg);
243        wordlen = strlen(word);
244        do {
245                if (wordlen) {
246                        if (word[wordlen - 1] == '>') {
247                                --wordlen;
248                                break;
249                        }
250                        if (*arg == '>')
251                                break;
252                }
253                return apr_pstrcat(cmd->pool, "<", LUACMD,
254                                   "> takes exactly one argument", NULL);
255        } while (0);
256
257        ctx->cfp = cmd->config_file;
258        ctx->startline = cmd->config_file->line_number;
259        lua_settop(lvm, 0);
260        result = lua_load(lvm, direct_chunkreader, ctx, filename);
261
262        if (result != 0) {
263                word =
264                    apr_pstrcat(cmd->pool, "Lua Error:",
265                                lua_tostring(lvm, -1), NULL);
266                lua_close(lvm);
267                return word;
268        } else {
269                luaL_buffinit(lvm, &b);
270                lua_dump(lvm, ldump_writer, &b);
271                luaL_pushresult(&b);
272                bytecode = lua_tostring(lvm, -1);
273                bytecode_len = lua_strlen(lvm, -1);
274        }
275
276        /* Here, we have to replace our current config node for the next pass */
277        if (!*current) {
278                *current = apr_pcalloc(cmd->pool, sizeof(**current));
279        }
280
281        (*current)->filename = cmd->config_file->name;
282        (*current)->line_num = ctx->startline;
283        (*current)->directive =
284            apr_pstrdup(cmd->pool, "GnuTLSRequireByteCode");
285        (*current)->args = NULL;
286
287        bcbuf = apr_pcalloc(cmd->pool, sizeof(bcbuf));
288        bcbuf->buflen = bytecode_len;
289        bcbuf->buf = apr_pstrmemdup(cmd->pool, bytecode, bytecode_len);
290
291        (*current)->data = bcbuf;
292        lua_close(lvm);
293        return NULL;
294}
295
296const char *mgs_set_require_bytecode(cmd_parms * cmd, void *mconfig,
297                                     const char *arg)
298{
299        bcbuf_ctx *bcbuf;
300        ap_directive_t *directive = cmd->directive;
301        mgs_dirconf_rec *dc = mconfig;
302
303        bcbuf = directive->data;
304        dc->lua_bytecode_len = bcbuf->buflen;
305        dc->lua_bytecode =
306            apr_pstrmemdup(cmd->pool, bcbuf->buf, bcbuf->buflen);
307
308        return NULL;
309}
Note: See TracBrowser for help on using the repository browser.