aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorGravatar Paul Querna 2005-05-17 21:00:53 +0000
committerGravatar Paul Querna 2005-05-17 21:00:53 +0000
commit84cb5b2ad2abada1069659895d16dcb64f669008 (patch)
tree447923776aaf6d7bb7c399e888845465ce0b4891 /src
parent836417fceaf154bde03418a1525ff149f5a07cca (diff)
- add lua to do client verification
- only use gcrypt locking when required to
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am6
-rw-r--r--src/gnutls_config.c17
-rw-r--r--src/gnutls_hooks.c28
-rw-r--r--src/gnutls_lua.c292
-rw-r--r--src/mod_gnutls.c15
5 files changed, 338 insertions, 20 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index c6d42c9..59c8909 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,8 +1,8 @@
1CLEANFILES = .libs/libmod_gnutls *~ 1CLEANFILES = .libs/libmod_gnutls *~
2 2
3libmod_gnutls_la_SOURCES = mod_gnutls.c gnutls_io.c gnutls_cache.c gnutls_config.c gnutls_hooks.c 3libmod_gnutls_la_SOURCES = mod_gnutls.c gnutls_io.c gnutls_cache.c gnutls_config.c gnutls_hooks.c gnutls_lua.c
4libmod_gnutls_la_CFLAGS = -Wall ${MODULE_CFLAGS} 4libmod_gnutls_la_CFLAGS = -Wall ${MODULE_CFLAGS} ${LUA_CFLAGS}
5libmod_gnutls_la_LDFLAGS = -rpath ${AP_LIBEXECDIR} -module -avoid-version ${MODULE_LIBS} 5libmod_gnutls_la_LDFLAGS = -rpath ${AP_LIBEXECDIR} -module -avoid-version ${MODULE_LIBS} ${LUA_LIBS}
6 6
7lib_LTLIBRARIES = libmod_gnutls.la 7lib_LTLIBRARIES = libmod_gnutls.la
8 8
diff --git a/src/gnutls_config.c b/src/gnutls_config.c
index f9a315c..1194448 100644
--- a/src/gnutls_config.c
+++ b/src/gnutls_config.c
@@ -317,12 +317,27 @@ void *mgs_config_server_create(apr_pool_t * p, server_rec * s)
317 return sc; 317 return sc;
318} 318}
319 319
320void *mgs_config_dir_merge(apr_pool_t *p, void *basev, void *addv)
321{
322 mgs_dirconf_rec *new;
323 mgs_dirconf_rec *base = (mgs_dirconf_rec *) basev;
324 mgs_dirconf_rec *add = (mgs_dirconf_rec *) addv;
325
326 new = (mgs_dirconf_rec *) apr_pcalloc(p, sizeof(mgs_dirconf_rec));
327 new->lua_bytecode = apr_pstrmemdup(p, add->lua_bytecode,
328 add->lua_bytecode_len);
329 new->lua_bytecode_len = add->lua_bytecode_len;
330 new->client_verify_mode = add->client_verify_mode;
331 return new;
332}
333
320void *mgs_config_dir_create(apr_pool_t *p, char *dir) 334void *mgs_config_dir_create(apr_pool_t *p, char *dir)
321{ 335{
322 mgs_dirconf_rec *dc = apr_palloc(p, sizeof(*dc)); 336 mgs_dirconf_rec *dc = apr_palloc(p, sizeof(*dc));
323 337
324 dc->client_verify_mode = -1; 338 dc->client_verify_mode = -1;
325 339 dc->lua_bytecode = NULL;
340 dc->lua_bytecode_len = 0;
326 return dc; 341 return dc;
327} 342}
328 343
diff --git a/src/gnutls_hooks.c b/src/gnutls_hooks.c
index 2d12b51..3862c9d 100644
--- a/src/gnutls_hooks.c
+++ b/src/gnutls_hooks.c
@@ -17,6 +17,7 @@
17 17
18#include "mod_gnutls.h" 18#include "mod_gnutls.h"
19#include "http_vhost.h" 19#include "http_vhost.h"
20#include "ap_mpm.h"
20 21
21#if !USING_2_1_RECENT 22#if !USING_2_1_RECENT
22extern server_rec *ap_server_conf; 23extern server_rec *ap_server_conf;
@@ -30,6 +31,8 @@ GCRY_THREAD_OPTION_PTHREAD_IMPL;
30static apr_file_t* debug_log_fp; 31static apr_file_t* debug_log_fp;
31#endif 32#endif
32 33
34static int mpm_is_threaded;
35
33static apr_status_t mgs_cleanup_pre_config(void *data) 36static apr_status_t mgs_cleanup_pre_config(void *data)
34{ 37{
35 gnutls_global_deinit(); 38 gnutls_global_deinit();
@@ -48,8 +51,12 @@ int mgs_hook_pre_config(apr_pool_t * pconf,
48{ 51{
49 52
50#if APR_HAS_THREADS 53#if APR_HAS_THREADS
51 /* TODO: Check MPM Type here */ 54 ap_mpm_query(AP_MPMQ_IS_THREADED, &mpm_is_threaded);
52 gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread); 55 if (mpm_is_threaded) {
56 gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
57 }
58#else
59 mpm_is_threaded = 0;
53#endif 60#endif
54 61
55 gnutls_global_init(); 62 gnutls_global_init();
@@ -234,11 +241,6 @@ int mgs_hook_post_config(apr_pool_t * p, apr_pool_t * plog,
234 rv = gnutls_x509_crt_get_dn_by_oid(sc->cert_x509, 241 rv = gnutls_x509_crt_get_dn_by_oid(sc->cert_x509,
235 GNUTLS_OID_X520_COMMON_NAME, 0, 0, 242 GNUTLS_OID_X520_COMMON_NAME, 0, 0,
236 sc->cert_cn, &data_len); 243 sc->cert_cn, &data_len);
237 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0,
238 s,
239 "GnuTLS: sni-x509 cn: %s/%d pk: %s s: 0x%08X sc: 0x%08X", sc->cert_cn, rv,
240 gnutls_pk_algorithm_get_name(gnutls_x509_privkey_get_pk_algorithm(sc->privkey_x509)),
241 (unsigned int)s, (unsigned int)sc);
242 } 244 }
243 } 245 }
244 246
@@ -568,7 +570,6 @@ int mgs_hook_fixups(request_rec *r)
568 gnutls_x509_crt_get_issuer_dn(ctxt->sc->cert_x509, buf, &len); 570 gnutls_x509_crt_get_issuer_dn(ctxt->sc->cert_x509, buf, &len);
569 apr_table_setn(env, "SSL_SERVER_I_DN", apr_pstrmemdup(r->pool, buf, len)); 571 apr_table_setn(env, "SSL_SERVER_I_DN", apr_pstrmemdup(r->pool, buf, len));
570 } 572 }
571
572 return rv; 573 return rv;
573} 574}
574 575
@@ -585,11 +586,14 @@ int mgs_hook_authz(request_rec *r)
585 if (!ctxt) { 586 if (!ctxt) {
586 return DECLINED; 587 return DECLINED;
587 } 588 }
588 589 ap_add_common_vars(r);
589 if (!dc) { 590 mgs_hook_fixups(r);
590 dc = mgs_config_dir_create(r->pool, NULL); 591 status = mgs_authz_lua(r);
592 if (status != 0) {
593 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
594 "GnuTLS: FAILED Lua Authorization Test");
595 return HTTP_FORBIDDEN;
591 } 596 }
592
593 if (dc->client_verify_mode == GNUTLS_CERT_IGNORE) { 597 if (dc->client_verify_mode == GNUTLS_CERT_IGNORE) {
594 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, 598 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
595 "GnuTLS: Directory set to Ignore Client Certificate!"); 599 "GnuTLS: Directory set to Ignore Client Certificate!");
diff --git a/src/gnutls_lua.c b/src/gnutls_lua.c
new file mode 100644
index 0000000..6d80574
--- /dev/null
+++ b/src/gnutls_lua.c
@@ -0,0 +1,292 @@
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}
diff --git a/src/mod_gnutls.c b/src/mod_gnutls.c
index a2c36ee..84440d0 100644
--- a/src/mod_gnutls.c
+++ b/src/mod_gnutls.c
@@ -54,7 +54,6 @@ static void gnutls_hooks(apr_pool_t * p)
54 AP_FTYPE_CONNECTION + 5); 54 AP_FTYPE_CONNECTION + 5);
55} 55}
56 56
57
58static const command_rec mgs_config_cmds[] = { 57static const command_rec mgs_config_cmds[] = {
59 AP_INIT_TAKE1("GnuTLSClientVerify", mgs_set_client_verify, 58 AP_INIT_TAKE1("GnuTLSClientVerify", mgs_set_client_verify,
60 NULL, 59 NULL,
@@ -81,16 +80,24 @@ static const command_rec mgs_config_cmds[] = {
81 RSRC_CONF, 80 RSRC_CONF,
82 "Cache Configuration"), 81 "Cache Configuration"),
83 AP_INIT_TAKE1("GnuTLSEnable", mgs_set_enabled, 82 AP_INIT_TAKE1("GnuTLSEnable", mgs_set_enabled,
84 NULL, RSRC_CONF, 83 NULL,
84 RSRC_CONF,
85 "Whether this server has GnuTLS Enabled. Default: Off"), 85 "Whether this server has GnuTLS Enabled. Default: Off"),
86 86 AP_INIT_RAW_ARGS("<GnuTLSRequire", mgs_set_require_section,
87 NULL,
88 EXEC_ON_READ|OR_ALL,
89 "Whether this server has GnuTLS Enabled. Default: Off"),
90 AP_INIT_RAW_ARGS("GnuTLSRequireByteCode", mgs_set_require_bytecode,
91 NULL,
92 OR_ALL,
93 "Internal Command for reading Lua Bytecode."),
87 {NULL} 94 {NULL}
88}; 95};
89 96
90module AP_MODULE_DECLARE_DATA gnutls_module = { 97module AP_MODULE_DECLARE_DATA gnutls_module = {
91 STANDARD20_MODULE_STUFF, 98 STANDARD20_MODULE_STUFF,
92 mgs_config_dir_create, 99 mgs_config_dir_create,
93 NULL, 100 mgs_config_dir_merge,
94 mgs_config_server_create, 101 mgs_config_server_create,
95 NULL, 102 NULL,
96 mgs_config_cmds, 103 mgs_config_cmds,