fix
[libexssl.git] / src / libexssl / sslwnet.c
blob82a5e514c01add78f5dd221ad58f3d711e0f8c66
1 #include "sslnet.h"
3 static __thread str_t *errmsg = NULL;
4 __thread int ssl_errno = 0;
6 __attribute__ ((destructor))
7 static void sslw_free_err () {
8 if (errmsg)
9 free(errmsg);
12 static int adderr (const char *str, size_t len, void *userdata) {
13 if (errmsg)
14 strnadd(&errmsg, str, len);
15 else
16 errmsg = mkstr(str, len, 64);
17 return 0;
20 cstr_t *ssl_error () {
21 if (errmsg)
22 return mkcstr(errmsg->ptr, errmsg->len);
23 return NULL;
26 SSL_CTX *ssl_create (int kind) {
27 const SSL_METHOD *m;
28 switch (kind) {
29 case SSL_CLIENT:
30 m = SSLv23_client_method();
31 break;
32 case SSL_SERVER:
33 m = SSLv23_server_method();
34 break;
35 default:
36 m = SSLv23_method();
37 break;
39 SSL_CTX *ctx = SSL_CTX_new(m);
40 if (!ctx) {
41 if (errmsg) {
42 free(errmsg);
43 errmsg = NULL;
45 ERR_print_errors_cb(adderr, NULL);
47 return ctx;
50 int ssl_config (SSL_CTX *ctx, const char *cert_file, const char *key_file) {
51 int rc;
52 SSL_CTX_set_ecdh_auto(ctx, 1);
53 if ((rc = SSL_CTX_use_certificate_chain_file(ctx, cert_file)) > 0)
54 rc = SSL_CTX_use_PrivateKey_file(ctx, key_file, SSL_FILETYPE_PEM);
55 if (rc <= 0) {
56 if (errmsg) {
57 free(errmsg);
58 errmsg = NULL;
60 ERR_print_errors_cb(adderr, NULL);
62 return rc > 0 ? 0 : -1;
65 int ssl_accept (SSL_CTX *ctx, int fd, SSL **ssl) {
66 int rc;
67 if (!*ssl) {
68 *ssl = SSL_new(ctx);
69 SSL_set_fd(*ssl, fd);
70 } else
71 if (SSL_is_init_finished(*ssl))
72 return NET_WAIT;
73 rc = SSL_accept(*ssl);
74 if (1 == rc)
75 return 1;
76 switch (SSL_get_error(*ssl, rc)) {
77 case SSL_ERROR_NONE:
78 return 1;
79 case SSL_ERROR_WANT_WRITE:
80 case SSL_ERROR_WANT_READ:
81 return 0;
82 default:
83 if (errmsg) {
84 free(errmsg);
85 errmsg = NULL;
87 ERR_print_errors_cb(adderr, NULL);
88 SSL_shutdown(*ssl);
89 SSL_free(*ssl);
90 *ssl = NULL;
92 return -1;
95 int ssl_connect (SSL_CTX *ctx, int fd, SSL **ssl) {
96 int rc;
97 if (!*ssl) {
98 *ssl = SSL_new(ctx);
99 SSL_set_fd(*ssl, fd);
101 if (SSL_is_init_finished(*ssl))
102 return 0;
103 rc = SSL_connect(*ssl);
104 if (1 == rc)
105 return 1;
106 switch (SSL_get_error(*ssl, rc)) {
107 case SSL_ERROR_NONE:
108 return 1;
109 case SSL_ERROR_WANT_WRITE:
110 case SSL_ERROR_WANT_READ:
111 return 0;
112 default:
113 if (errmsg) {
114 free(errmsg);
115 errmsg = NULL;
117 ERR_print_errors_cb(adderr, NULL);
118 SSL_shutdown(*ssl);
119 SSL_free(*ssl);
120 *ssl = NULL;
122 return -1;
125 ssize_t ssl_recv (SSL *ssl, strbuf_t *buf) {
126 ssize_t readed = -1;
127 int rc;
128 ssl_errno = 0;
129 if (-1 == strbufsize(buf, buf->len + buf->chunk_size, STR_KEEPLEN | STR_REDUCE))
130 return -1;
131 rc = SSL_read_ex(ssl, buf->ptr + buf->len, buf->chunk_size, (size_t*)&readed);
132 if (rc > 0) {
133 buf->len += readed;
134 return readed;
136 switch ((ssl_errno = SSL_get_error(ssl, rc))) {
137 case SSL_ERROR_WANT_READ:
138 case SSL_ERROR_NONE:
139 if (0 == rc)
140 ssl_errno = 0;
141 return 0;
142 case SSL_ERROR_ZERO_RETURN:
143 case SSL_ERROR_SYSCALL:
144 SSL_shutdown(ssl);
145 return -1;
146 default:
147 if (errmsg) {
148 free(errmsg);
149 errmsg = NULL;
151 ERR_print_errors_cb(adderr, NULL);
152 break;
154 return -1;
157 ssize_t ssl_send (SSL *ssl, const void *buf, size_t size) {
158 ssize_t sent = 0, wrote = 0;
159 int rc;
160 ssl_errno = 0;
161 while (sent < size) {
162 rc = SSL_write_ex(ssl, buf, size - sent, (size_t*)&wrote);
163 if (rc > 0) {
164 sent += wrote;
165 buf += wrote;
166 continue;
168 if (0 == rc)
169 continue;
170 if (errmsg) {
171 free(errmsg);
172 errmsg = NULL;
174 ssl_errno = SSL_get_error(ssl, rc);
175 if (SSL_ERROR_WANT_WRITE == ssl_errno)
176 continue;
177 if (SSL_ERROR_ZERO_RETURN == ssl_errno)
178 SSL_shutdown(ssl);
179 ERR_print_errors_cb(adderr, NULL);
180 sent = -1;
182 return sent;
185 int sslws_handshake (SSL *ssl, strbuf_t *buf, strptr_t *url) {
186 int rc = WS_ERROR;
187 ssize_t readed;
188 while ((readed = ssl_recv(ssl, buf)) > 0);
189 if (0 == readed && SSL_ERROR_WANT_READ == ssl_errno)
190 return WS_WAIT;
191 if (-1 == readed)
192 return WS_ERROR;
193 http_request_t req;
194 ws_handshake_t wsh;
195 memset(&req, 0, sizeof req);
196 memset(&wsh, 0, sizeof wsh);
197 switch ((rc = ws_handshake(&req, buf->ptr, buf->len, &wsh))) {
198 case HTTP_LOADED:
199 if (url) {
200 url->ptr = strndup(req.url.ptr, req.url.len);
201 url->len = req.url.len;
203 ws_make_response(buf, &wsh);
204 if ((readed = ssl_send(ssl, buf->ptr, buf->len)) > 0) {
205 rc = WS_OK;
206 buf->len = 0;
207 return rc;
209 rc = WS_ERROR;
210 buf->len = 0;
211 if (url) {
212 if (url->ptr) {
213 free(url->ptr);
214 url->ptr = NULL;
216 url->len = 0;
218 break;
219 case HTTP_ERROR:
220 rc = WS_ERROR;
221 break;
222 default:
223 rc = WS_WAIT;
224 break;
226 return rc;
229 int sslws_recv (SSL *ssl, netbuf_t *nbuf, ws_t *result) {
230 int rc = 0;
231 ssize_t nbytes, ntotal = 0;
232 if ((nbytes = ws_buflen((const uint8_t*)nbuf->buf.ptr, nbuf->buf.len)) > 0) {
233 rc = ws_parse(nbuf->buf.ptr, nbytes, result);
234 wsnet_save_tail(nbuf, nbytes);
235 if (WS_OK == rc)
236 return WS_OK;
237 return WS_WAIT;
239 while ((nbytes = ssl_recv(ssl, &nbuf->buf)) > 0)
240 ntotal += nbytes;
241 if (0 == nbytes && SSL_ERROR_WANT_READ == ssl_errno)
242 return WS_WAIT;
243 if (-1 == nbytes)
244 return WS_ERROR;
245 if (-1 == (nbytes = ws_buflen((const uint8_t*)nbuf->buf.ptr, nbuf->buf.len)))
246 return WS_WAIT;
247 rc = ws_parse(nbuf->buf.ptr, nbytes, result);
248 wsnet_save_tail(nbuf, nbytes);
249 if (WS_OK == rc)
250 return WS_OK;
251 return WS_WAIT;
254 // WS SRV
256 static int sslws_ev_open (int fd, ssl_srv_t *srv, http_url_t *h_url) {
257 int rc = NET_ERROR;
258 ssize_t rd;
259 ssl_ev_t *ev = (ssl_ev_t*)&srv->fd_info[fd];
260 str_t *req;
261 strbuf_t buf;
262 switch (ssl_connect(srv->ctx_cli, fd, &ev->ssl)) {
263 case -1:
264 return NET_ERROR;
265 case 0:
266 return NET_ERROR;
267 case 1:
268 ev->nf_flags |= NF_SSLACCEPTED;
269 break;
271 req = create_ws_request(h_url);
272 strbufalloc(&buf, SRV_BUF_SIZE, SRV_BUF_SIZE);
273 if (req->len == ssl_send(ev->ssl, req->ptr, req->len)) {
274 while ((rd = ssl_recv(ev->ssl, &buf)) > 0) {
275 if (buf.len > 4 && 0 == cmpstr(buf.ptr+buf.len-4, 4, CONST_STR_LEN("\r\n\r\n"))) { // FIXME : parse response, save tail
276 rc = NET_WAIT;
277 srv->fd_info[fd].nf_flags |= NF_WSCONNECTED;
278 break;
282 free(buf.ptr);
283 free(req);
284 return rc;
287 static int sslws_ev_recv (int fd, ssl_srv_t *srv) {
288 ssl_ev_t *ev = (ssl_ev_t*)&srv->fd_info[fd];
289 if (!(ev->nf_flags & NF_SSLACCEPTED)) {
290 switch (ssl_accept(srv->ctx_srv, fd, &ev->ssl)) {
291 case -1:
292 return NET_ERROR;
293 case 0:
294 return NET_WAIT;
295 case 1:
296 ev->nf_flags |= NF_SSLACCEPTED;
297 return NET_WAIT;
300 if (!(ev->nf_flags & NF_WSCONNECTED)) {
301 strptr_t url = CONST_STR_INIT_NULL;
302 switch (sslws_handshake(ev->ssl, &ev->rd_buf.buf, &url)) {
303 case WS_WAIT:
304 return NET_WAIT;
305 case WS_ERROR:
306 return NET_ERROR;
308 ticket_lock(&ev->locker);
309 ev->nf_flags |= NF_WSCONNECTED;
310 if (ev->rd_buf.buf.ptr) {
311 free(ev->rd_buf.buf.ptr);
312 ev->rd_buf.buf.ptr = NULL;
314 if (url.ptr) {
315 if (srv->on_check_url && NET_ERROR == srv->on_check_url(fd, (net_srv_t*)srv, &url)) {
316 ticket_unlock(&ev->locker);
317 free(url.ptr);
318 return NET_ERROR;
320 free(url.ptr);
322 ticket_unlock(&ev->locker);
323 return NET_OK;
325 switch (sslws_recv(ev->ssl, &ev->rd_buf, &ev->ws)) {
326 case WS_WAIT:
327 return NET_WAIT;
328 case WS_ERROR:
329 return NET_ERROR;
331 return NET_OK;
334 static int ssl_ev_send (int fd, ssl_srv_t *srv) {
335 ssize_t rc;
336 cstr_t *buf;
337 ssl_ev_t *ev = (ssl_ev_t*)&srv->fd_info[fd];
338 if (!ev->ssl)
339 return NET_OK;
340 ticket_lock(&ev->locker);
341 buf = mkcstr(ev->wr_buf.ptr + ev->wrote, ev->wr_buf.len - ev->wrote);
342 ticket_unlock(&ev->locker);
343 if ((rc = ssl_send(ev->ssl, buf->ptr, buf->len)) > 0)
344 ev->wrote += rc;
345 free(buf);
346 return rc;
349 static int ssl_close_ev (int fd, ssl_srv_t *srv) {
350 ssl_ev_t *ev = (ssl_ev_t*)&srv->fd_info[fd];
351 if (ev->ssl) {
352 SSL_shutdown(ev->ssl);
353 SSL_free(ev->ssl);
354 ev->ssl = NULL;
356 return NET_OK;
359 net_srv_t *sslws_srv_init (const char *svc, const char *cert_file, const char *key_file) {
360 net_srv_t *srv = net_srv_init(svc, sizeof(ssl_srv_t), sizeof(ssl_ev_t));
361 SSL_CTX *ctx_cli = NULL, *ctx_srv = NULL;
362 if (!srv) return NULL;
363 if (!(ctx_cli = ssl_create(SSL_CLIENT)) ||
364 !(ctx_srv = ssl_create(SSL_SERVER)) ||
365 -1 == ssl_config(ctx_cli, cert_file, key_file) ||
366 -1 == ssl_config(ctx_srv, cert_file, key_file))
367 goto err;
368 ((ssl_srv_t*)srv)->ctx_cli = ctx_cli;
369 ((ssl_srv_t*)srv)->ctx_srv = ctx_srv;
370 srv->on_open = (net_ev_open_h)sslws_ev_open;
371 srv->on_recv = (net_ev_h)sslws_ev_recv;
372 srv->on_send = (net_ev_h)ssl_ev_send;
373 srv->on_recvd = ws_ev_recvd;
374 srv->ev_bufsize = sizeof(ev_buf_t);
375 srv->on_evbuf_set = ws_evbuf_set;
376 srv->on_close_ev = (net_ev_h)ssl_close_ev;
377 srv->msg_info = ws_create_msg_info();
378 return srv;
379 err:
380 if (ctx_srv) SSL_CTX_free(ctx_srv);
381 if (ctx_cli) SSL_CTX_free(ctx_cli);
382 net_srv_done(srv);
383 return NULL;
386 void sslws_srv_done (net_srv_t *srv) {
387 SSL_CTX *ctx;
388 if ((ctx = ((ssl_srv_t*)srv)->ctx_srv))
389 SSL_CTX_free(ctx);
390 if ((ctx = ((ssl_srv_t*)srv)->ctx_cli))
391 SSL_CTX_free(ctx);
392 rbtree_free(srv->msg_info);
393 ws_srv_done(srv);
396 // WS JSONRPC SRV
398 net_srv_t *sslws_jsonrpc_srv_init (const char *svc, const char *cert_file, const char *key_file) {
399 net_srv_t *srv = sslws_srv_init(svc, cert_file, key_file);
400 if (srv) {
401 srv->on_evbuf_free = ws_jsonrpc_evbuf_free;
402 srv->on_event = ws_jsonrpc_srv_event;
403 srv->on_check_url = check_api_ver;
405 return srv;