root/luci/trunk/libs/nixio/src/tls-context.c @ 4275

Revision 4275, 5.5 KB (checked in by Cyrus, 4 years ago)

nixio: Finetuning of TLS-support
httpclient: HTTPS support
axTLS: enable diagnostic mode

Line 
1/*
2 * nixio - Linux I/O library for lua
3 *
4 *   Copyright (C) 2009 Steven Barth <steven@midlink.org>
5 *
6 *  Licensed under the Apache License, Version 2.0 (the "License");
7 *  you may not use this file except in compliance with the License.
8 *  You may obtain a copy of the License at
9 *
10 *      http://www.apache.org/licenses/LICENSE-2.0
11 *
12 *  Unless required by applicable law or agreed to in writing, software
13 *  distributed under the License is distributed on an "AS IS" BASIS,
14 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 *  See the License for the specific language governing permissions and
16 *  limitations under the License.
17 */
18
19#include "nixio-tls.h"
20#include <string.h>
21
22static SSL_CTX* nixio__checktlsctx(lua_State *L) {
23    SSL_CTX **ctx = (SSL_CTX **)luaL_checkudata(L, 1, NIXIO_TLS_CTX_META);
24    luaL_argcheck(L, *ctx, 1, "invalid context");
25    return *ctx;
26}
27
28static int nixio__tls_perror(lua_State *L, int code) {
29    lua_pushnil(L);
30    lua_pushinteger(L, code);
31    return 2;
32}
33
34static int nixio__tls_pstatus(lua_State *L, int code) {
35    if (code == 1) {
36        lua_pushboolean(L, 1);
37        return 1;
38    } else {
39        return nixio__tls_perror(L, code);
40    }
41}
42
43static int nixio_tls_ctx(lua_State * L) {
44    const char *method = luaL_optlstring(L, 1, "tlsv1", NULL);
45
46    SSL_CTX **ctx = lua_newuserdata(L, sizeof(SSL_CTX *));
47    if (!ctx) {
48        return luaL_error(L, "out of memory");
49    }
50
51    /* create userdata */
52    luaL_getmetatable(L, NIXIO_TLS_CTX_META);
53    lua_setmetatable(L, -2);
54
55    if (!strcmp(method, "tlsv1")) {
56        *ctx = SSL_CTX_new(TLSv1_method());
57    } else if (!strcmp(method, "sslv23")) {
58        *ctx = SSL_CTX_new(SSLv23_method());
59    } else {
60        return luaL_argerror(L, 1, "supported values: tlsv1, sslv23");
61    }
62
63
64    SSL_CTX_set_options(*ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
65
66    if (!(*ctx)) {
67        return luaL_error(L, "unable to create TLS context");
68    }
69
70    return 1;
71}
72
73static int nixio_tls_ctx_create(lua_State *L) {
74    SSL_CTX *ctx = nixio__checktlsctx(L);
75    int fd = nixio__checkfd(L, 2);
76
77    lua_createtable(L, 0, 3);
78    nixio_tls_sock *sock = lua_newuserdata(L, sizeof(nixio_tls_sock));
79    if (!sock) {
80        return luaL_error(L, "out of memory");
81    }
82    memset(sock, 0, sizeof(nixio_tls_sock));
83
84    /* create userdata */
85    luaL_getmetatable(L, NIXIO_TLS_SOCK_META);
86    lua_pushvalue(L, -1);
87    lua_setmetatable(L, -3);
88
89    sock->socket = SSL_new(ctx);
90    if (!sock->socket) {
91        return nixio__tls_perror(L, 0);
92    }
93
94    if (SSL_set_fd(sock->socket, fd) != 1) {
95        return nixio__tls_perror(L, 0);
96    }
97
98    /* save context and socket to prevent GC from collecting them */
99    lua_setmetatable(L, -3);
100    lua_setfield(L, -2, "connection");
101
102    lua_pushvalue(L, 1);
103    lua_setfield(L, -2, "context");
104
105    lua_pushvalue(L, 2);
106    lua_setfield(L, -2, "socket");
107
108    return 1;
109}
110
111static int nixio_tls_ctx_set_cert(lua_State *L) {
112    SSL_CTX *ctx = nixio__checktlsctx(L);
113    const char *cert = luaL_checkstring(L, 2);
114    return nixio__tls_pstatus(L, SSL_CTX_use_certificate_chain_file(ctx, cert));
115}
116
117static int nixio_tls_ctx_set_key(lua_State *L) {
118    SSL_CTX *ctx = nixio__checktlsctx(L);
119    const char *cert = luaL_checkstring(L, 2);
120    const int ktype = SSL_FILETYPE_PEM;
121    return nixio__tls_pstatus(L, SSL_CTX_use_PrivateKey_file(ctx, cert, ktype));
122}
123
124static int nixio_tls_ctx_set_ciphers(lua_State *L) {
125    SSL_CTX *ctx = nixio__checktlsctx(L);
126    size_t len;
127    const char *ciphers = luaL_checklstring(L, 2, &len);
128    luaL_argcheck(L, len < 255, 2, "cipher string too long");
129    return nixio__tls_pstatus(L, SSL_CTX_set_cipher_list(ctx, ciphers));
130}
131
132static int nixio_tls_ctx_set_verify_depth(lua_State *L) {
133    SSL_CTX *ctx = nixio__checktlsctx(L);
134    const int depth = luaL_checkinteger(L, 2);
135    SSL_CTX_set_verify_depth(ctx, depth);
136    return 0;
137}
138
139static int nixio_tls_ctx_set_verify(lua_State *L) {
140    SSL_CTX *ctx = nixio__checktlsctx(L);
141    const int j = lua_gettop(L);
142    int flags = 0;
143    for (int i=2; i<=j; i++) {
144        const char *flag = luaL_checkstring(L, i);
145        if (!strcmp(flag, "none")) {
146            flags |= SSL_VERIFY_NONE;
147        } else if (!strcmp(flag, "peer")) {
148            flags |= SSL_VERIFY_PEER;
149        } else if (!strcmp(flag, "verify_fail_if_no_peer_cert")) {
150            flags |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
151        } else if (!strcmp(flag, "client_once")) {
152            flags |= SSL_VERIFY_CLIENT_ONCE;
153        } else {
154            return luaL_argerror(L, i, "supported values: none, peer, "
155             "verify_fail_if_no_peer_cert, client_once");
156        }
157    }
158    SSL_CTX_set_verify(ctx, flags, NULL);
159    return 0;
160}
161
162static int nixio_tls_ctx__gc(lua_State *L) {
163    SSL_CTX **ctx = (SSL_CTX **)luaL_checkudata(L, 1, NIXIO_TLS_CTX_META);
164    if (*ctx) {
165        SSL_CTX_free(*ctx);
166        *ctx = NULL;
167    }
168    return 0;
169}
170
171static int nixio_tls_ctx__tostring(lua_State *L) {
172    SSL_CTX *ctx = nixio__checktlsctx(L);
173    lua_pushfstring(L, "nixio TLS context: %p", ctx);
174    return 1;
175}
176
177/* module table */
178static const luaL_reg R[] = {
179    {"tls",     nixio_tls_ctx},
180    {NULL,          NULL}
181};
182
183/* ctx function table */
184static const luaL_reg CTX_M[] = {
185    {"set_cert",            nixio_tls_ctx_set_cert},
186    {"set_key",             nixio_tls_ctx_set_key},
187    {"set_ciphers",         nixio_tls_ctx_set_ciphers},
188    {"set_verify_depth",    nixio_tls_ctx_set_verify_depth},
189    {"set_verify",          nixio_tls_ctx_set_verify},
190    {"create",              nixio_tls_ctx_create},
191    {"__gc",                nixio_tls_ctx__gc},
192    {"__tostring",          nixio_tls_ctx__tostring},
193    {NULL,                  NULL}
194};
195
196
197void nixio_open_tls_context(lua_State *L) {
198    /* initialize tls library */
199    SSL_load_error_strings();
200    SSL_library_init();
201
202    /* register module functions */
203    luaL_register(L, NULL, R);
204
205    /* create context metatable */
206    luaL_newmetatable(L, NIXIO_TLS_CTX_META);
207    lua_pushvalue(L, -1);
208    lua_setfield(L, -2, "__index");
209    luaL_register(L, NULL, CTX_M);
210    lua_pop(L, 1);
211}
Note: See TracBrowser for help on using the browser.