source: mod_gnutls/src/gnutls_lua.c @ bca274d

debian/masterdebian/stretch-backportsjessie-backportsmsvaupstream
Last change on this file since bca274d was 84cb5b2, checked in by Paul Querna <chip@…>, 15 years ago
  • add lua to do client verification
  • only use gcrypt locking when required to
  • Property mode set to 100644
File size: 7.5 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    }
58    else {
59        return 0;
60    }
61}
62
63static int mgs_lua_getenv(lua_State *lvm)
64{
65    return get_request_table(lvm, APR_OFFSETOF(request_rec, subprocess_env));
66}
67
68static int mgs_lua_getheader(lua_State *lvm)
69{   
70    return get_request_table(lvm, APR_OFFSETOF(request_rec, headers_in));
71} 
72
73static const luaL_reg mgs_lua_reg[] = {
74    {"getenv", mgs_lua_getenv},
75    {"header", mgs_lua_getheader},
76    {NULL, NULL}
77};
78
79lua_State* get_luastate() 
80{
81    lua_State* lvm = lua_open();
82    luaopen_base(lvm);
83    luaopen_io(lvm);
84    luaopen_table(lvm);
85    luaopen_string(lvm);
86    luaopen_math(lvm);
87    luaopen_loadlib(lvm);
88    luaL_openlib(lvm, "ap", mgs_lua_reg, 0);
89   
90    return lvm;
91}
92
93int mgs_authz_lua(request_rec* r)
94{
95    int rv;
96    lua_State* lvm;
97    mgs_dirconf_rec *dc = ap_get_module_config(r->per_dir_config,
98                                               &gnutls_module);
99   
100    if (dc->lua_bytecode_len <= 0) {
101        return 0;
102    }
103   
104    lvm = get_luastate();
105    lua_pushlightuserdata(lvm, MGS_LUA_RRKEY);
106    lua_pushlightuserdata(lvm, r);
107    lua_settable(lvm, LUA_REGISTRYINDEX);
108   
109    /* Push Bytecode onto the stack */
110    rv = luaL_loadbuffer(lvm, dc->lua_bytecode, dc->lua_bytecode_len, "gnutls-lua");
111
112    if (rv != 0) {
113        /* Get the Error message */
114        const char* error = lua_tostring(lvm, -1);
115        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, 
116                      "GnuTLS: Error Loading Lua Bytecode: %s", error);
117        lua_pop(lvm, 1);
118        return -1;
119    }
120   
121    rv = lua_pcall(lvm, 0, 1, 0);
122    if (rv != 0) {
123        /* Get the Error message */
124        const char* error = lua_tostring(lvm, -1);
125        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, 
126                      "GnuTLS: Error Running Lua: %s", error);
127        lua_pop(lvm, 1);
128        return -1;
129    }
130   
131    rv = (int)lua_tonumber(lvm, -1);
132    ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, 
133                  "GnuTLS: (%d) Lua Return: %d",
134                  dc->lua_bytecode_len, rv);
135    lua_pop(lvm, 1);
136    lua_close(lvm);
137    return rv;
138}
139
140static apr_size_t config_getstr(ap_configfile_t *cfg, char *buf, size_t bufsiz)
141{
142    apr_size_t i = 0;
143   
144    if (cfg->getstr) {
145        const char *res = (cfg->getstr)(buf, bufsiz, cfg->param);
146        if (res) {
147            i = strlen(buf);
148            if (i && buf[i - 1] == '\n') ++cfg->line_number;
149        }
150        else {
151            buf[0] = '\0';
152            i = 0;
153        }
154    }
155    else {
156        while (i < bufsiz) {
157            int ch = (cfg->getch)(cfg->param);
158            if (ch == EOF) break;
159            buf[i++] = ch;
160            if (ch == '\n') {
161                ++cfg->line_number;
162                break;
163            }
164        }
165    }
166    return i;
167}
168
169struct cr_ctx {
170    ap_configfile_t *cfp;
171    size_t startline;
172    char buf[HUGE_STRING_LEN];
173};
174
175static const char *LUACMD = "gnutlsrequire";
176static const char *lf = "\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";
177#define N_LF 32
178
179static const char *direct_chunkreader(lua_State *lvm, void *udata, size_t *plen)
180{
181    const char *p;
182    struct cr_ctx *ctx = udata;
183   
184    if (ctx->startline) {
185        *plen = ctx->startline > N_LF ? N_LF : ctx->startline;
186        ctx->startline -= *plen;
187        return lf;
188    }
189    *plen = config_getstr(ctx->cfp, ctx->buf, HUGE_STRING_LEN);
190   
191    for (p = ctx->buf; isspace(*p); ++p);
192    if (p[0] == '<' && p[1] == '/') {
193        int i = 0;
194        while (i < strlen(LUACMD)) {
195            if (tolower(p[i + 2]) != LUACMD[i]) return ctx->buf;
196            ++i;
197        }
198        *plen = 0;
199        return NULL;
200    }
201    return ctx->buf;
202}
203
204static int ldump_writer (lua_State *L, const void* b, size_t size, void* B) {
205    (void)L;
206    luaL_addlstring((luaL_Buffer*) B, (const char *)b, size);
207    return 1;
208}
209
210/* a bytecode buffer*/
211typedef struct bcbuf_ctx {
212    apr_size_t buflen;
213    char* buf;
214} bcbuf_ctx;
215
216const char *mgs_set_require_section(cmd_parms *cmd, void *mconfig, const char *arg)
217{
218    apr_size_t bytecode_len;
219    const char* bytecode;
220    bcbuf_ctx* bcbuf;
221    luaL_Buffer b;
222    ap_directive_t **current = mconfig;
223    struct cr_ctx ctx[1];
224    int result;
225    const char *filename = apr_psprintf(cmd->pool, "@%s", cmd->config_file->name);
226    // get a word argument
227    const char *word;
228    apr_size_t wordlen;
229    lua_State *lvm = get_luastate();
230
231    word = ap_getword_conf(cmd->pool, &arg);
232    wordlen = strlen(word);
233    do {
234        if (wordlen) {
235            if (word[wordlen - 1] == '>') {
236                --wordlen;
237                break;
238            }
239            if (*arg == '>') break;
240        }
241        return apr_pstrcat(cmd->pool, "<", LUACMD, "> takes exactly one argument", NULL);
242    } while (0);
243
244    ctx->cfp = cmd->config_file;
245    ctx->startline = cmd->config_file->line_number;
246    lua_settop(lvm, 0);
247    result = lua_load(lvm, direct_chunkreader, ctx, filename);
248
249    if (result != 0) {
250        word = apr_pstrcat(cmd->pool, "Lua Error:", lua_tostring(lvm, -1), NULL);
251        lua_close(lvm);
252        return word;
253    }
254    else {
255        luaL_buffinit(lvm, &b);
256        lua_dump(lvm, ldump_writer, &b);
257        luaL_pushresult(&b);
258        bytecode = lua_tostring(lvm, -1);
259        bytecode_len = lua_strlen(lvm, -1);
260    }
261   
262    /* Here, we have to replace our current config node for the next pass */
263    if (!*current) {
264        *current = apr_pcalloc(cmd->pool, sizeof(**current));
265    }
266   
267    (*current)->filename = cmd->config_file->name;
268    (*current)->line_num = ctx->startline;
269    (*current)->directive = apr_pstrdup(cmd->pool, "GnuTLSRequireByteCode");
270    (*current)->args = NULL;
271
272    bcbuf = apr_pcalloc(cmd->pool, sizeof(bcbuf));
273    bcbuf->buflen = bytecode_len;
274    bcbuf->buf = apr_pstrmemdup(cmd->pool, bytecode, bytecode_len);
275
276    (*current)->data = bcbuf;
277    lua_close(lvm);
278    return NULL;
279}
280
281const char *mgs_set_require_bytecode(cmd_parms *cmd, void *mconfig, const char *arg)
282{
283    bcbuf_ctx* bcbuf;
284    ap_directive_t *directive = cmd->directive;
285    mgs_dirconf_rec *dc = mconfig;
286
287    bcbuf = directive->data;
288    dc->lua_bytecode_len = bcbuf->buflen;
289    dc->lua_bytecode = apr_pstrmemdup(cmd->pool, bcbuf->buf, bcbuf->buflen);
290   
291    return NULL;
292}
Note: See TracBrowser for help on using the repository browser.