src/context.c

changeset 0
f7d2d78eb424
child 1
5f89e535765a
equal deleted inserted replaced
-1:000000000000 0:f7d2d78eb424
1 /*--------------------------------------------------------------------------
2 * LuaSec 0.4
3 * Copyright (C) 2006-2009 Bruno Silvestre
4 *
5 *--------------------------------------------------------------------------*/
6
7 #include <string.h>
8 #include <openssl/ssl.h>
9 #include <openssl/err.h>
10
11 #include <lua.h>
12 #include <lauxlib.h>
13
14 #include "context.h"
15
16 struct ssl_option_s {
17 const char *name;
18 unsigned long code;
19 };
20 typedef struct ssl_option_s ssl_option_t;
21
22
23 static ssl_option_t ssl_options[] = {
24 /* OpenSSL 0.9.7 and 0.9.8 */
25 {"all", SSL_OP_ALL},
26 {"cipher_server_preference", SSL_OP_CIPHER_SERVER_PREFERENCE},
27 {"dont_insert_empty_fragments", SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS},
28 {"ephemeral_rsa", SSL_OP_EPHEMERAL_RSA},
29 {"netscape_ca_dn_bug", SSL_OP_NETSCAPE_CA_DN_BUG},
30 {"netscape_challenge_bug", SSL_OP_NETSCAPE_CHALLENGE_BUG},
31 {"microsoft_big_sslv3_buffer", SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER},
32 {"microsoft_sess_id_bug", SSL_OP_MICROSOFT_SESS_ID_BUG},
33 {"msie_sslv2_rsa_padding", SSL_OP_MSIE_SSLV2_RSA_PADDING},
34 {"netscape_demo_cipher_change_bug", SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG},
35 {"netscape_reuse_cipher_change_bug", SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG},
36 {"no_session_resumption_on_renegotiation",
37 SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION},
38 {"no_sslv2", SSL_OP_NO_SSLv2},
39 {"no_sslv3", SSL_OP_NO_SSLv3},
40 {"no_tlsv1", SSL_OP_NO_TLSv1},
41 {"pkcs1_check_1", SSL_OP_PKCS1_CHECK_1},
42 {"pkcs1_check_2", SSL_OP_PKCS1_CHECK_2},
43 {"single_dh_use", SSL_OP_SINGLE_DH_USE},
44 {"ssleay_080_client_dh_bug", SSL_OP_SSLEAY_080_CLIENT_DH_BUG},
45 {"sslref2_reuse_cert_type_bug", SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG},
46 {"tls_block_padding_bug", SSL_OP_TLS_BLOCK_PADDING_BUG},
47 {"tls_d5_bug", SSL_OP_TLS_D5_BUG},
48 {"tls_rollback_bug", SSL_OP_TLS_ROLLBACK_BUG},
49 /* OpenSSL 0.9.8 only */
50 #if OPENSSL_VERSION_NUMBER > 0x00908000L
51 {"cookie_exchange", SSL_OP_COOKIE_EXCHANGE},
52 {"no_query_mtu", SSL_OP_NO_QUERY_MTU},
53 {"single_ecdh_use", SSL_OP_SINGLE_ECDH_USE},
54 #endif
55 /* OpenSSL 0.9.8f and above */
56 #if defined(SSL_OP_NO_TICKET)
57 {"no_ticket", SSL_OP_NO_TICKET},
58 #endif
59 {NULL, 0L}
60 };
61
62 /*--------------------------- Auxiliary Functions ----------------------------*/
63
64 /**
65 * Return the context.
66 */
67 static p_context checkctx(lua_State *L, int idx)
68 {
69 return (p_context)luaL_checkudata(L, idx, "SSL:Context");
70 }
71
72 /**
73 * Prepare the SSL options flag.
74 */
75 static int set_option_flag(const char *opt, unsigned long *flag)
76 {
77 ssl_option_t *p;
78 for (p = ssl_options; p->name; p++) {
79 if (!strcmp(opt, p->name)) {
80 *flag |= p->code;
81 return 1;
82 }
83 }
84 return 0;
85 }
86
87 /**
88 * Find the protocol.
89 */
90 static SSL_METHOD* str2method(const char *method)
91 {
92 if (!strcmp(method, "sslv3")) return SSLv3_method();
93 if (!strcmp(method, "tlsv1")) return TLSv1_method();
94 if (!strcmp(method, "sslv23")) return SSLv23_method();
95 return NULL;
96 }
97
98 /**
99 * Prepare the SSL handshake verify flag.
100 */
101 static int set_verify_flag(const char *str, int *flag)
102 {
103 if (!strcmp(str, "none")) {
104 *flag |= SSL_VERIFY_NONE;
105 return 1;
106 }
107 if (!strcmp(str, "peer")) {
108 *flag |= SSL_VERIFY_PEER;
109 return 1;
110 }
111 if (!strcmp(str, "client_once")) {
112 *flag |= SSL_VERIFY_CLIENT_ONCE;
113 return 1;
114 }
115 if (!strcmp(str, "fail_if_no_peer_cert")) {
116 *flag |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
117 return 1;
118 }
119 return 0;
120 }
121
122 /**
123 * Password callback for reading the private key.
124 */
125 static int passwd_cb(char *buf, int size, int flag, void *udata)
126 {
127 lua_State *L = (lua_State*)udata;
128 switch (lua_type(L, 3)) {
129 case LUA_TFUNCTION:
130 lua_pushvalue(L, 3);
131 lua_call(L, 0, 1);
132 if (lua_type(L, -1) != LUA_TSTRING)
133 return 0;
134 /* fallback */
135 case LUA_TSTRING:
136 strncpy(buf, lua_tostring(L, -1), size);
137 buf[size-1] = '\0';
138 return (int)strlen(buf);
139 }
140 return 0;
141 }
142
143 /*------------------------------ Lua Functions -------------------------------*/
144
145 /**
146 * Create a SSL context.
147 */
148 static int create(lua_State *L)
149 {
150 p_context ctx;
151 SSL_METHOD *method;
152
153 method = str2method(luaL_checkstring(L, 1));
154 if (!method) {
155 lua_pushnil(L);
156 lua_pushstring(L, "invalid protocol");
157 return 2;
158 }
159 ctx = (p_context) lua_newuserdata(L, sizeof(t_context));
160 if (!ctx) {
161 lua_pushnil(L);
162 lua_pushstring(L, "error creating context");
163 return 2;
164 }
165 ctx->context = SSL_CTX_new(method);
166 if (!ctx->context) {
167 lua_pushnil(L);
168 lua_pushstring(L, "error creating context");
169 return 2;
170 }
171 ctx->mode = MD_CTX_INVALID;
172 /* No session support */
173 SSL_CTX_set_session_cache_mode(ctx->context, SSL_SESS_CACHE_OFF);
174 luaL_getmetatable(L, "SSL:Context");
175 lua_setmetatable(L, -2);
176 return 1;
177 }
178
179 /**
180 * Load the trusting certificates.
181 */
182 static int load_locations(lua_State *L)
183 {
184 SSL_CTX *ctx = ctx_getcontext(L, 1);
185 const char *cafile = luaL_optstring(L, 2, NULL);
186 const char *capath = luaL_optstring(L, 3, NULL);
187 if (SSL_CTX_load_verify_locations(ctx, cafile, capath) != 1) {
188 lua_pushboolean(L, 0);
189 lua_pushfstring(L, "error loading CA locations (%s)",
190 ERR_reason_error_string(ERR_get_error()));
191 return 2;
192 }
193 lua_pushboolean(L, 1);
194 return 1;
195 }
196
197 /**
198 * Load the certificate file.
199 */
200 static int load_cert(lua_State *L)
201 {
202 SSL_CTX *ctx = ctx_getcontext(L, 1);
203 const char *filename = luaL_checkstring(L, 2);
204 if (SSL_CTX_use_certificate_chain_file(ctx, filename) != 1) {
205 lua_pushboolean(L, 0);
206 lua_pushfstring(L, "error loading certificate (%s)",
207 ERR_reason_error_string(ERR_get_error()));
208 return 2;
209 }
210 lua_pushboolean(L, 1);
211 return 1;
212 }
213
214 /**
215 * Load the key file -- only in PEM format.
216 */
217 static int load_key(lua_State *L)
218 {
219 int ret = 1;
220 SSL_CTX *ctx = ctx_getcontext(L, 1);
221 const char *filename = luaL_checkstring(L, 2);
222 switch (lua_type(L, 3)) {
223 case LUA_TSTRING:
224 case LUA_TFUNCTION:
225 SSL_CTX_set_default_passwd_cb(ctx, passwd_cb);
226 SSL_CTX_set_default_passwd_cb_userdata(ctx, L);
227 /* fallback */
228 case LUA_TNIL:
229 if (SSL_CTX_use_PrivateKey_file(ctx, filename, SSL_FILETYPE_PEM) == 1)
230 lua_pushboolean(L, 1);
231 else {
232 ret = 2;
233 lua_pushboolean(L, 0);
234 lua_pushfstring(L, "error loading private key (%s)",
235 ERR_reason_error_string(ERR_get_error()));
236 }
237 SSL_CTX_set_default_passwd_cb(ctx, NULL);
238 SSL_CTX_set_default_passwd_cb_userdata(ctx, NULL);
239 break;
240 default:
241 lua_pushstring(L, "invalid callback value");
242 lua_error(L);
243 }
244 return ret;
245 }
246
247 /**
248 * Set the cipher list.
249 */
250 static int set_cipher(lua_State *L)
251 {
252 SSL_CTX *ctx = ctx_getcontext(L, 1);
253 const char *list = luaL_checkstring(L, 2);
254 if (SSL_CTX_set_cipher_list(ctx, list) != 1) {
255 lua_pushboolean(L, 0);
256 lua_pushfstring(L, "error setting cipher list (%s)",
257 ERR_reason_error_string(ERR_get_error()));
258 return 2;
259 }
260 lua_pushboolean(L, 1);
261 return 1;
262 }
263
264 /**
265 * Set the depth for certificate checking.
266 */
267 static int set_depth(lua_State *L)
268 {
269 SSL_CTX *ctx = ctx_getcontext(L, 1);
270 SSL_CTX_set_verify_depth(ctx, luaL_checkint(L, 2));
271 lua_pushboolean(L, 1);
272 return 1;
273 }
274
275 /**
276 * Set the handshake verify options.
277 */
278 static int set_verify(lua_State *L)
279 {
280 int i;
281 int flag = 0;
282 SSL_CTX *ctx = ctx_getcontext(L, 1);
283 int max = lua_gettop(L);
284 /* any flag? */
285 if (max > 1) {
286 for (i = 2; i <= max; i++) {
287 if (!set_verify_flag(luaL_checkstring(L, i), &flag)) {
288 lua_pushboolean(L, 0);
289 lua_pushstring(L, "invalid verify option");
290 return 2;
291 }
292 }
293 SSL_CTX_set_verify(ctx, flag, NULL);
294 }
295 lua_pushboolean(L, 1);
296 return 1;
297 }
298
299 /**
300 * Set the protocol options.
301 */
302 static int set_options(lua_State *L)
303 {
304 int i;
305 unsigned long flag = 0L;
306 SSL_CTX *ctx = ctx_getcontext(L, 1);
307 int max = lua_gettop(L);
308 /* any option? */
309 if (max > 1) {
310 for (i = 2; i <= max; i++) {
311 if (!set_option_flag(luaL_checkstring(L, i), &flag)) {
312 lua_pushboolean(L, 0);
313 lua_pushstring(L, "invalid option");
314 return 2;
315 }
316 }
317 SSL_CTX_set_options(ctx, flag);
318 }
319 lua_pushboolean(L, 1);
320 return 1;
321 }
322
323 /**
324 * Set the context mode.
325 */
326 static int set_mode(lua_State *L)
327 {
328 p_context ctx = checkctx(L, 1);
329 const char *str = luaL_checkstring(L, 2);
330 if (!strcmp("server", str)) {
331 ctx->mode = MD_CTX_SERVER;
332 lua_pushboolean(L, 1);
333 return 1;
334 }
335 if(!strcmp("client", str)) {
336 ctx->mode = MD_CTX_CLIENT;
337 lua_pushboolean(L, 1);
338 return 1;
339 }
340 lua_pushboolean(L, 0);
341 lua_pushstring(L, "invalid mode");
342 return 1;
343 }
344
345 /**
346 * Return a pointer to SSL_CTX structure.
347 */
348 static int raw_ctx(lua_State *L)
349 {
350 p_context ctx = checkctx(L, 1);
351 lua_pushlightuserdata(L, (void*)ctx->context);
352 return 1;
353 }
354
355 /**
356 * Package functions
357 */
358 static luaL_Reg funcs[] = {
359 {"create", create},
360 {"locations", load_locations},
361 {"loadcert", load_cert},
362 {"loadkey", load_key},
363 {"setcipher", set_cipher},
364 {"setdepth", set_depth},
365 {"setverify", set_verify},
366 {"setoptions", set_options},
367 {"setmode", set_mode},
368 {"rawcontext", raw_ctx},
369 {NULL, NULL}
370 };
371
372 /*-------------------------------- Metamethods -------------------------------*/
373
374 /**
375 * Collect SSL context -- GC metamethod.
376 */
377 static int meth_destroy(lua_State *L)
378 {
379 p_context ctx = checkctx(L, 1);
380 if (ctx->context) {
381 SSL_CTX_free(ctx->context);
382 ctx->context = NULL;
383 }
384 return 0;
385 }
386
387 /**
388 * Object information -- tostring metamethod.
389 */
390 static int meth_tostring(lua_State *L)
391 {
392 p_context ctx = checkctx(L, 1);
393 lua_pushfstring(L, "SSL context: %p", ctx);
394 return 1;
395 }
396
397 /**
398 * Context metamethods.
399 */
400 static luaL_Reg meta[] = {
401 {"__gc", meth_destroy},
402 {"__tostring", meth_tostring},
403 {NULL, NULL}
404 };
405
406
407 /*----------------------------- Public Functions ---------------------------*/
408
409 /**
410 * Retrieve the SSL context from the Lua stack.
411 */
412 SSL_CTX* ctx_getcontext(lua_State *L, int idx)
413 {
414 p_context ctx = checkctx(L, idx);
415 return ctx->context;
416 }
417
418 /**
419 * Retrieve the mode from the context in the Lua stack.
420 */
421 char ctx_getmode(lua_State *L, int idx)
422 {
423 p_context ctx = checkctx(L, idx);
424 return ctx->mode;
425 }
426
427 /*------------------------------ Initialization ------------------------------*/
428
429 /**
430 * Registre the module.
431 */
432 int luaopen_ssl_context(lua_State *L)
433 {
434 luaL_newmetatable(L, "SSL:Context");
435 luaL_register(L, NULL, meta);
436 luaL_register(L, "ssl.context", funcs);
437 return 1;
438 }

mercurial