Sat, 20 Nov 2010 20:04:11 -0800
context: support for diffie-hellman key exchange
0 | 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 | ||
28
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
22 | /* The export DH key */ |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
23 | static DH *dh_512 = NULL; |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
24 | /* The larger key (builtin is 2048, caller may specify larger) */ |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
25 | static DH *dh_larger = NULL; |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
26 | |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
27 | /* Generated via "openssl dhparam -2 -noout -C 512 2>/dev/null" */ |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
28 | static unsigned char dh512_p[] = { |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
29 | 0xE4,0x3F,0x75,0x82,0xAD,0x0B,0x28,0xC7,0xEF,0xCE,0xBC,0x3B, |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
30 | 0x14,0xBB,0xA6,0xF4,0xA2,0xE9,0xA6,0x59,0xCF,0x97,0x1C,0x86, |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
31 | 0x43,0x3B,0x92,0x4A,0x6B,0x15,0x4B,0x0C,0xAC,0x8F,0xFA,0x43, |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
32 | 0xE2,0xA8,0xC3,0x3B,0x7B,0x51,0x1B,0x46,0x21,0xBF,0x8C,0x06, |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
33 | 0x6C,0xB1,0x49,0x75,0xC7,0xAC,0x47,0x1D,0x9D,0x64,0xD5,0x99, |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
34 | 0x33,0x86,0xAD,0xEB, |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
35 | }; |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
36 | |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
37 | /* Generated via "openssl dhparam -2 -noout -C 2048 2>/dev/null" */ |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
38 | static unsigned char dh2048_p[] = { |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
39 | 0x9B,0xF4,0xC5,0x57,0x81,0x8F,0xCF,0x31,0x78,0x95,0x04,0xCD, |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
40 | 0xEA,0xCC,0x30,0xEA,0xF7,0xCA,0x76,0xC8,0x8F,0x91,0xEA,0x0E, |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
41 | 0x44,0x8D,0xE2,0x63,0x19,0x3B,0x4D,0x04,0xC8,0x7D,0x0D,0xFF, |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
42 | 0x3D,0x52,0x76,0x02,0xF3,0xCA,0x1C,0x44,0xAF,0x0E,0xA9,0x59, |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
43 | 0x02,0x40,0x75,0xD6,0xED,0x35,0x4D,0x11,0x5B,0x2B,0x73,0x23, |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
44 | 0xE5,0x53,0x0B,0x1F,0xB0,0x47,0xC4,0x7F,0x95,0x5D,0xB0,0xD5, |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
45 | 0xF3,0xD3,0xAB,0x5F,0x28,0x2B,0xEC,0x2C,0x15,0x0B,0x1B,0x0C, |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
46 | 0xD4,0xBE,0x24,0x2F,0xC5,0x07,0x3C,0xE4,0xC5,0xE6,0x16,0x42, |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
47 | 0x4C,0x31,0x04,0xBB,0x80,0x96,0xFF,0x64,0x50,0xA4,0xA5,0xB5, |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
48 | 0xF5,0x3A,0xBA,0x57,0xE4,0xE6,0xC2,0x23,0x0A,0xB6,0x27,0xC4, |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
49 | 0x06,0x01,0x1E,0x98,0x20,0x09,0xC8,0xB7,0x90,0x09,0x86,0x06, |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
50 | 0xAA,0x85,0xE7,0x02,0xC8,0xC6,0xD9,0x1D,0xAB,0x17,0xEE,0x78, |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
51 | 0x73,0x78,0x88,0x7F,0xA7,0xF2,0x34,0xA7,0xDD,0x02,0x16,0x36, |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
52 | 0x0D,0x77,0x16,0x3E,0x95,0xAE,0x02,0xEE,0x36,0x37,0xD5,0x61, |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
53 | 0x5D,0xFE,0xC6,0x0B,0xDF,0xCE,0xB9,0x26,0x31,0x6F,0x34,0x92, |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
54 | 0xBB,0xBB,0x91,0x29,0x77,0x62,0x1D,0x75,0xA0,0x51,0x8D,0x31, |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
55 | 0x4C,0x64,0x4E,0xBF,0xDC,0xE8,0x67,0x17,0x90,0x6A,0x80,0xE9, |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
56 | 0xD7,0xD8,0x56,0x4E,0x85,0x21,0x9C,0xFB,0xE6,0x1B,0xD8,0x05, |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
57 | 0xFD,0x13,0x77,0x00,0x96,0x2D,0x0C,0x2A,0x95,0x1A,0x08,0x82, |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
58 | 0x2E,0xB3,0xE2,0xFC,0xE8,0xA6,0xF1,0x16,0x37,0x57,0x82,0xD6, |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
59 | 0xF5,0xAB,0xA9,0x43,0x8F,0x33,0xB0,0x57,0x38,0x6E,0x61,0xD4, |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
60 | 0xDD,0xE0,0x1C,0xCB, |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
61 | }; |
0 | 62 | |
63 | static ssl_option_t ssl_options[] = { | |
64 | /* OpenSSL 0.9.7 and 0.9.8 */ | |
65 | {"all", SSL_OP_ALL}, | |
66 | {"cipher_server_preference", SSL_OP_CIPHER_SERVER_PREFERENCE}, | |
67 | {"dont_insert_empty_fragments", SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS}, | |
68 | {"ephemeral_rsa", SSL_OP_EPHEMERAL_RSA}, | |
69 | {"netscape_ca_dn_bug", SSL_OP_NETSCAPE_CA_DN_BUG}, | |
70 | {"netscape_challenge_bug", SSL_OP_NETSCAPE_CHALLENGE_BUG}, | |
71 | {"microsoft_big_sslv3_buffer", SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER}, | |
72 | {"microsoft_sess_id_bug", SSL_OP_MICROSOFT_SESS_ID_BUG}, | |
73 | {"msie_sslv2_rsa_padding", SSL_OP_MSIE_SSLV2_RSA_PADDING}, | |
74 | {"netscape_demo_cipher_change_bug", SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG}, | |
75 | {"netscape_reuse_cipher_change_bug", SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG}, | |
76 | {"no_session_resumption_on_renegotiation", | |
77 | SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION}, | |
78 | {"no_sslv2", SSL_OP_NO_SSLv2}, | |
79 | {"no_sslv3", SSL_OP_NO_SSLv3}, | |
80 | {"no_tlsv1", SSL_OP_NO_TLSv1}, | |
81 | {"pkcs1_check_1", SSL_OP_PKCS1_CHECK_1}, | |
82 | {"pkcs1_check_2", SSL_OP_PKCS1_CHECK_2}, | |
83 | {"single_dh_use", SSL_OP_SINGLE_DH_USE}, | |
84 | {"ssleay_080_client_dh_bug", SSL_OP_SSLEAY_080_CLIENT_DH_BUG}, | |
85 | {"sslref2_reuse_cert_type_bug", SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG}, | |
86 | {"tls_block_padding_bug", SSL_OP_TLS_BLOCK_PADDING_BUG}, | |
87 | {"tls_d5_bug", SSL_OP_TLS_D5_BUG}, | |
88 | {"tls_rollback_bug", SSL_OP_TLS_ROLLBACK_BUG}, | |
89 | /* OpenSSL 0.9.8 only */ | |
90 | #if OPENSSL_VERSION_NUMBER > 0x00908000L | |
91 | {"cookie_exchange", SSL_OP_COOKIE_EXCHANGE}, | |
92 | {"no_query_mtu", SSL_OP_NO_QUERY_MTU}, | |
93 | {"single_ecdh_use", SSL_OP_SINGLE_ECDH_USE}, | |
94 | #endif | |
95 | /* OpenSSL 0.9.8f and above */ | |
96 | #if defined(SSL_OP_NO_TICKET) | |
97 | {"no_ticket", SSL_OP_NO_TICKET}, | |
98 | #endif | |
1
5f89e535765a
context.c: Add no_compression option for when supported
Matthew Wild <mwild1@gmail.com>
parents:
0
diff
changeset
|
99 | #if defined(SSL_OP_NO_COMPRESSION) |
5f89e535765a
context.c: Add no_compression option for when supported
Matthew Wild <mwild1@gmail.com>
parents:
0
diff
changeset
|
100 | {"no_compression", SSL_OP_NO_COMPRESSION}, |
5f89e535765a
context.c: Add no_compression option for when supported
Matthew Wild <mwild1@gmail.com>
parents:
0
diff
changeset
|
101 | #endif |
0 | 102 | {NULL, 0L} |
103 | }; | |
104 | ||
105 | /*--------------------------- Auxiliary Functions ----------------------------*/ | |
106 | ||
107 | /** | |
108 | * Return the context. | |
109 | */ | |
110 | static p_context checkctx(lua_State *L, int idx) | |
111 | { | |
112 | return (p_context)luaL_checkudata(L, idx, "SSL:Context"); | |
113 | } | |
114 | ||
115 | /** | |
116 | * Prepare the SSL options flag. | |
117 | */ | |
118 | static int set_option_flag(const char *opt, unsigned long *flag) | |
119 | { | |
120 | ssl_option_t *p; | |
121 | for (p = ssl_options; p->name; p++) { | |
122 | if (!strcmp(opt, p->name)) { | |
123 | *flag |= p->code; | |
124 | return 1; | |
125 | } | |
126 | } | |
127 | return 0; | |
128 | } | |
129 | ||
130 | /** | |
131 | * Find the protocol. | |
132 | */ | |
133 | static SSL_METHOD* str2method(const char *method) | |
134 | { | |
135 | if (!strcmp(method, "sslv3")) return SSLv3_method(); | |
136 | if (!strcmp(method, "tlsv1")) return TLSv1_method(); | |
137 | if (!strcmp(method, "sslv23")) return SSLv23_method(); | |
138 | return NULL; | |
139 | } | |
140 | ||
141 | /** | |
142 | * Prepare the SSL handshake verify flag. | |
143 | */ | |
144 | static int set_verify_flag(const char *str, int *flag) | |
145 | { | |
146 | if (!strcmp(str, "none")) { | |
147 | *flag |= SSL_VERIFY_NONE; | |
148 | return 1; | |
149 | } | |
150 | if (!strcmp(str, "peer")) { | |
151 | *flag |= SSL_VERIFY_PEER; | |
152 | return 1; | |
153 | } | |
154 | if (!strcmp(str, "client_once")) { | |
155 | *flag |= SSL_VERIFY_CLIENT_ONCE; | |
156 | return 1; | |
157 | } | |
158 | if (!strcmp(str, "fail_if_no_peer_cert")) { | |
159 | *flag |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT; | |
160 | return 1; | |
161 | } | |
162 | return 0; | |
163 | } | |
164 | ||
165 | /** | |
166 | * Password callback for reading the private key. | |
167 | */ | |
168 | static int passwd_cb(char *buf, int size, int flag, void *udata) | |
169 | { | |
170 | lua_State *L = (lua_State*)udata; | |
171 | switch (lua_type(L, 3)) { | |
172 | case LUA_TFUNCTION: | |
173 | lua_pushvalue(L, 3); | |
174 | lua_call(L, 0, 1); | |
175 | if (lua_type(L, -1) != LUA_TSTRING) | |
176 | return 0; | |
177 | /* fallback */ | |
178 | case LUA_TSTRING: | |
179 | strncpy(buf, lua_tostring(L, -1), size); | |
180 | buf[size-1] = '\0'; | |
181 | return (int)strlen(buf); | |
182 | } | |
183 | return 0; | |
184 | } | |
185 | ||
28
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
186 | static DH *get_dh(const unsigned char *p, int len) |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
187 | { |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
188 | DH *dh = NULL; |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
189 | static unsigned char g[] = { 0x02 }; |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
190 | |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
191 | if ((dh = DH_new()) == NULL) return NULL; |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
192 | dh->p = BN_bin2bn(p, len, NULL); |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
193 | dh->g = BN_bin2bn(g, sizeof(g), NULL); |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
194 | if (dh->p == NULL || dh->g == NULL) { |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
195 | DH_free(dh); |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
196 | return NULL; |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
197 | } |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
198 | |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
199 | return dh; |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
200 | } |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
201 | |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
202 | /** |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
203 | * DH parameter callback |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
204 | */ |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
205 | static DH *dh_param_cb(SSL *ssl, int is_export, int keylength) |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
206 | { |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
207 | /* Logic in postfix and dovecot, but we're using a 2048-bit group... */ |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
208 | if (is_export && keylength == 512) { |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
209 | if (dh_512 == NULL) { dh_512 = get_dh(dh512_p, sizeof(dh512_p)); } |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
210 | return dh_512; |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
211 | } else { |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
212 | if (dh_larger == NULL) { dh_larger = get_dh(dh2048_p, sizeof(dh2048_p)); } |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
213 | return dh_larger; |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
214 | } |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
215 | } |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
216 | |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
217 | |
0 | 218 | /*------------------------------ Lua Functions -------------------------------*/ |
219 | ||
220 | /** | |
221 | * Create a SSL context. | |
222 | */ | |
223 | static int create(lua_State *L) | |
224 | { | |
225 | p_context ctx; | |
226 | SSL_METHOD *method; | |
227 | ||
228 | method = str2method(luaL_checkstring(L, 1)); | |
229 | if (!method) { | |
230 | lua_pushnil(L); | |
231 | lua_pushstring(L, "invalid protocol"); | |
232 | return 2; | |
233 | } | |
234 | ctx = (p_context) lua_newuserdata(L, sizeof(t_context)); | |
235 | if (!ctx) { | |
236 | lua_pushnil(L); | |
237 | lua_pushstring(L, "error creating context"); | |
238 | return 2; | |
239 | } | |
240 | ctx->context = SSL_CTX_new(method); | |
241 | if (!ctx->context) { | |
242 | lua_pushnil(L); | |
243 | lua_pushstring(L, "error creating context"); | |
244 | return 2; | |
245 | } | |
246 | ctx->mode = MD_CTX_INVALID; | |
247 | /* No session support */ | |
248 | SSL_CTX_set_session_cache_mode(ctx->context, SSL_SESS_CACHE_OFF); | |
28
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
249 | /* |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
250 | * Support ephemeral diffie-hellman key exchange. This is only needed |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
251 | * for server mode, but clearer to put it here rather than set_mode. |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
252 | */ |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
253 | SSL_CTX_set_tmp_dh_callback(ctx->context, dh_param_cb); |
0 | 254 | luaL_getmetatable(L, "SSL:Context"); |
255 | lua_setmetatable(L, -2); | |
256 | return 1; | |
257 | } | |
258 | ||
259 | /** | |
260 | * Load the trusting certificates. | |
261 | */ | |
262 | static int load_locations(lua_State *L) | |
263 | { | |
264 | SSL_CTX *ctx = ctx_getcontext(L, 1); | |
265 | const char *cafile = luaL_optstring(L, 2, NULL); | |
266 | const char *capath = luaL_optstring(L, 3, NULL); | |
267 | if (SSL_CTX_load_verify_locations(ctx, cafile, capath) != 1) { | |
268 | lua_pushboolean(L, 0); | |
269 | lua_pushfstring(L, "error loading CA locations (%s)", | |
270 | ERR_reason_error_string(ERR_get_error())); | |
271 | return 2; | |
272 | } | |
273 | lua_pushboolean(L, 1); | |
274 | return 1; | |
275 | } | |
276 | ||
277 | /** | |
278 | * Load the certificate file. | |
279 | */ | |
280 | static int load_cert(lua_State *L) | |
281 | { | |
282 | SSL_CTX *ctx = ctx_getcontext(L, 1); | |
283 | const char *filename = luaL_checkstring(L, 2); | |
284 | if (SSL_CTX_use_certificate_chain_file(ctx, filename) != 1) { | |
285 | lua_pushboolean(L, 0); | |
286 | lua_pushfstring(L, "error loading certificate (%s)", | |
287 | ERR_reason_error_string(ERR_get_error())); | |
288 | return 2; | |
289 | } | |
290 | lua_pushboolean(L, 1); | |
291 | return 1; | |
292 | } | |
293 | ||
294 | /** | |
295 | * Load the key file -- only in PEM format. | |
296 | */ | |
297 | static int load_key(lua_State *L) | |
298 | { | |
299 | int ret = 1; | |
300 | SSL_CTX *ctx = ctx_getcontext(L, 1); | |
301 | const char *filename = luaL_checkstring(L, 2); | |
302 | switch (lua_type(L, 3)) { | |
303 | case LUA_TSTRING: | |
304 | case LUA_TFUNCTION: | |
305 | SSL_CTX_set_default_passwd_cb(ctx, passwd_cb); | |
306 | SSL_CTX_set_default_passwd_cb_userdata(ctx, L); | |
307 | /* fallback */ | |
308 | case LUA_TNIL: | |
309 | if (SSL_CTX_use_PrivateKey_file(ctx, filename, SSL_FILETYPE_PEM) == 1) | |
310 | lua_pushboolean(L, 1); | |
311 | else { | |
312 | ret = 2; | |
313 | lua_pushboolean(L, 0); | |
314 | lua_pushfstring(L, "error loading private key (%s)", | |
315 | ERR_reason_error_string(ERR_get_error())); | |
316 | } | |
317 | SSL_CTX_set_default_passwd_cb(ctx, NULL); | |
318 | SSL_CTX_set_default_passwd_cb_userdata(ctx, NULL); | |
319 | break; | |
320 | default: | |
321 | lua_pushstring(L, "invalid callback value"); | |
322 | lua_error(L); | |
323 | } | |
324 | return ret; | |
325 | } | |
326 | ||
327 | /** | |
28
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
328 | * Load a DH params files. This is a global LuaSec thing. |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
329 | */ |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
330 | static int load_dhparams(lua_State *L) |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
331 | { |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
332 | const char *filename = luaL_checkstring(L, 1); |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
333 | FILE *paramfile; |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
334 | DH *dh; |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
335 | |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
336 | paramfile = fopen(filename, "r"); |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
337 | if (!paramfile) { |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
338 | lua_pushboolean(L, 0); |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
339 | lua_pushfstring(L, "error reading dh param file %s: %s", filename, |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
340 | strerror(errno)); |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
341 | return 2; |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
342 | } |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
343 | |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
344 | dh = PEM_read_DHparams(paramfile, NULL, NULL, NULL); |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
345 | fclose(paramfile); |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
346 | if (!dh) { |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
347 | lua_pushboolean(L, 0); |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
348 | lua_pushfstring(L, "error loading dh param file %s: %s", filename, |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
349 | ERR_reason_error_string(ERR_get_error())); |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
350 | return 2; |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
351 | } |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
352 | |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
353 | if (dh_larger) |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
354 | DH_free(dh_larger); |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
355 | |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
356 | dh_larger = dh; |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
357 | |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
358 | lua_pushboolean(L, 1); |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
359 | return 1; |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
360 | } |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
361 | |
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
362 | /** |
0 | 363 | * Set the cipher list. |
364 | */ | |
365 | static int set_cipher(lua_State *L) | |
366 | { | |
367 | SSL_CTX *ctx = ctx_getcontext(L, 1); | |
368 | const char *list = luaL_checkstring(L, 2); | |
369 | if (SSL_CTX_set_cipher_list(ctx, list) != 1) { | |
370 | lua_pushboolean(L, 0); | |
371 | lua_pushfstring(L, "error setting cipher list (%s)", | |
372 | ERR_reason_error_string(ERR_get_error())); | |
373 | return 2; | |
374 | } | |
375 | lua_pushboolean(L, 1); | |
376 | return 1; | |
377 | } | |
378 | ||
379 | /** | |
380 | * Set the depth for certificate checking. | |
381 | */ | |
382 | static int set_depth(lua_State *L) | |
383 | { | |
384 | SSL_CTX *ctx = ctx_getcontext(L, 1); | |
385 | SSL_CTX_set_verify_depth(ctx, luaL_checkint(L, 2)); | |
386 | lua_pushboolean(L, 1); | |
387 | return 1; | |
388 | } | |
389 | ||
390 | /** | |
391 | * Set the handshake verify options. | |
392 | */ | |
393 | static int set_verify(lua_State *L) | |
394 | { | |
395 | int i; | |
396 | int flag = 0; | |
397 | SSL_CTX *ctx = ctx_getcontext(L, 1); | |
398 | int max = lua_gettop(L); | |
399 | /* any flag? */ | |
400 | if (max > 1) { | |
401 | for (i = 2; i <= max; i++) { | |
402 | if (!set_verify_flag(luaL_checkstring(L, i), &flag)) { | |
403 | lua_pushboolean(L, 0); | |
404 | lua_pushstring(L, "invalid verify option"); | |
405 | return 2; | |
406 | } | |
407 | } | |
408 | SSL_CTX_set_verify(ctx, flag, NULL); | |
409 | } | |
410 | lua_pushboolean(L, 1); | |
411 | return 1; | |
412 | } | |
413 | ||
414 | /** | |
415 | * Set the protocol options. | |
416 | */ | |
417 | static int set_options(lua_State *L) | |
418 | { | |
419 | int i; | |
420 | unsigned long flag = 0L; | |
421 | SSL_CTX *ctx = ctx_getcontext(L, 1); | |
422 | int max = lua_gettop(L); | |
423 | /* any option? */ | |
424 | if (max > 1) { | |
425 | for (i = 2; i <= max; i++) { | |
426 | if (!set_option_flag(luaL_checkstring(L, i), &flag)) { | |
427 | lua_pushboolean(L, 0); | |
428 | lua_pushstring(L, "invalid option"); | |
429 | return 2; | |
430 | } | |
431 | } | |
432 | SSL_CTX_set_options(ctx, flag); | |
433 | } | |
434 | lua_pushboolean(L, 1); | |
435 | return 1; | |
436 | } | |
437 | ||
438 | /** | |
439 | * Set the context mode. | |
440 | */ | |
441 | static int set_mode(lua_State *L) | |
442 | { | |
443 | p_context ctx = checkctx(L, 1); | |
444 | const char *str = luaL_checkstring(L, 2); | |
445 | if (!strcmp("server", str)) { | |
446 | ctx->mode = MD_CTX_SERVER; | |
447 | lua_pushboolean(L, 1); | |
448 | return 1; | |
449 | } | |
450 | if(!strcmp("client", str)) { | |
451 | ctx->mode = MD_CTX_CLIENT; | |
452 | lua_pushboolean(L, 1); | |
453 | return 1; | |
454 | } | |
455 | lua_pushboolean(L, 0); | |
456 | lua_pushstring(L, "invalid mode"); | |
457 | return 1; | |
458 | } | |
459 | ||
460 | /** | |
461 | * Return a pointer to SSL_CTX structure. | |
462 | */ | |
463 | static int raw_ctx(lua_State *L) | |
464 | { | |
465 | p_context ctx = checkctx(L, 1); | |
466 | lua_pushlightuserdata(L, (void*)ctx->context); | |
467 | return 1; | |
468 | } | |
469 | ||
470 | /** | |
471 | * Package functions | |
472 | */ | |
473 | static luaL_Reg funcs[] = { | |
474 | {"create", create}, | |
475 | {"locations", load_locations}, | |
476 | {"loadcert", load_cert}, | |
477 | {"loadkey", load_key}, | |
478 | {"setcipher", set_cipher}, | |
479 | {"setdepth", set_depth}, | |
480 | {"setverify", set_verify}, | |
481 | {"setoptions", set_options}, | |
482 | {"setmode", set_mode}, | |
483 | {"rawcontext", raw_ctx}, | |
28
8c61b29d87ec
context: support for diffie-hellman key exchange
Paul Aurich <paul@darkrain42.org>
parents:
1
diff
changeset
|
484 | {"loaddhparams", load_dhparams}, |
0 | 485 | {NULL, NULL} |
486 | }; | |
487 | ||
488 | /*-------------------------------- Metamethods -------------------------------*/ | |
489 | ||
490 | /** | |
491 | * Collect SSL context -- GC metamethod. | |
492 | */ | |
493 | static int meth_destroy(lua_State *L) | |
494 | { | |
495 | p_context ctx = checkctx(L, 1); | |
496 | if (ctx->context) { | |
497 | SSL_CTX_free(ctx->context); | |
498 | ctx->context = NULL; | |
499 | } | |
500 | return 0; | |
501 | } | |
502 | ||
503 | /** | |
504 | * Object information -- tostring metamethod. | |
505 | */ | |
506 | static int meth_tostring(lua_State *L) | |
507 | { | |
508 | p_context ctx = checkctx(L, 1); | |
509 | lua_pushfstring(L, "SSL context: %p", ctx); | |
510 | return 1; | |
511 | } | |
512 | ||
513 | /** | |
514 | * Context metamethods. | |
515 | */ | |
516 | static luaL_Reg meta[] = { | |
517 | {"__gc", meth_destroy}, | |
518 | {"__tostring", meth_tostring}, | |
519 | {NULL, NULL} | |
520 | }; | |
521 | ||
522 | ||
523 | /*----------------------------- Public Functions ---------------------------*/ | |
524 | ||
525 | /** | |
526 | * Retrieve the SSL context from the Lua stack. | |
527 | */ | |
528 | SSL_CTX* ctx_getcontext(lua_State *L, int idx) | |
529 | { | |
530 | p_context ctx = checkctx(L, idx); | |
531 | return ctx->context; | |
532 | } | |
533 | ||
534 | /** | |
535 | * Retrieve the mode from the context in the Lua stack. | |
536 | */ | |
537 | char ctx_getmode(lua_State *L, int idx) | |
538 | { | |
539 | p_context ctx = checkctx(L, idx); | |
540 | return ctx->mode; | |
541 | } | |
542 | ||
543 | /*------------------------------ Initialization ------------------------------*/ | |
544 | ||
545 | /** | |
546 | * Registre the module. | |
547 | */ | |
548 | int luaopen_ssl_context(lua_State *L) | |
549 | { | |
550 | luaL_newmetatable(L, "SSL:Context"); | |
551 | luaL_register(L, NULL, meta); | |
552 | luaL_register(L, "ssl.context", funcs); | |
553 | return 1; | |
554 | } |