1 //
2 // Copyright 2020 Staysail Systems, Inc. <info@staysail.tech>
3 // Copyright 2018 Capitar IT Group BV <info@capitar.com>
4 // Copyright 2019 Devolutions <info@devolutions.net>
5 //
6 // This software is supplied under the terms of the MIT License, a
7 // copy of which should be located in the distribution where this
8 // file was obtained (LICENSE.txt). A copy of the license may also be
9 // found online at https://opensource.org/licenses/MIT.
10 //
11
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15
16 #include "core/nng_impl.h"
17
18 #include <nng/supplemental/tls/engine.h>
19 #include <nng/supplemental/tls/tls.h>
20
21 // NNG_TLS_MAX_SEND_SIZE limits the amount of data we will buffer for sending,
22 // exerting back-pressure if this size is exceeded. The 16K is aligned to the
23 // maximum TLS record size.
24 #ifndef NNG_TLS_MAX_SEND_SIZE
25 #define NNG_TLS_MAX_SEND_SIZE 16384
26 #endif
27
28 // NNG_TLS_MAX_RECV_SIZE limits the amount of data we will receive in a single
29 // operation. As we have to buffer data, this drives the size of our
30 // intermediary buffer. The 16K is aligned to the maximum TLS record size.
31 #ifndef NNG_TLX_MAX_RECV_SIZE
32 #define NNG_TLS_MAX_RECV_SIZE 16384
33 #endif
34
35 // This file contains common code for TLS, and is only compiled if we
36 // have TLS configured in the system. In particular, this provides the
37 // parts of TLS support that are invariant relative to different TLS
38 // libraries, such as dialer and listener support.
39
40 #ifdef NNG_SUPP_TLS
41
42 static const nng_tls_engine *tls_engine;
43 static nni_mtx tls_engine_lock;
44
45 struct nng_tls_config {
46 nng_tls_engine_config_ops ops;
47 const nng_tls_engine * engine; // store this so we can verify
48 nni_mtx lock;
49 int ref;
50 int busy;
51 size_t size;
52
53 // ... engine config data follows
54 };
55
56 typedef struct {
57 nng_stream stream;
58 nng_tls_engine_conn_ops ops;
59 nng_tls_config * cfg;
60 const nng_tls_engine * engine;
61 size_t size;
62 nni_aio * user_aio; // user's aio for connect/accept
63 nni_aio conn_aio; // system aio for connect/accept
64 nni_mtx lock;
65 bool closed;
66 bool hs_done;
67 nni_list send_queue;
68 nni_list recv_queue;
69 nng_stream * tcp; // lower level stream
70 nni_aio tcp_send; // lower level send pending
71 nni_aio tcp_recv; // lower level recv pending
72 uint8_t * tcp_send_buf;
73 uint8_t * tcp_recv_buf;
74 size_t tcp_recv_len;
75 size_t tcp_recv_off;
76 bool tcp_recv_pend;
77 bool tcp_send_active;
78 size_t tcp_send_len;
79 size_t tcp_send_head;
80 size_t tcp_send_tail;
81 nni_reap_node reap;
82
83 // ... engine connection data follows
84 } tls_conn;
85
86 static void tls_tcp_send_cb(void *arg);
87 static void tls_tcp_recv_cb(void *arg);
88 static void tls_do_send(tls_conn *);
89 static void tls_do_recv(tls_conn *);
90 static void tls_tcp_send_start(tls_conn *);
91 static void tls_free(void *);
92 static void tls_reap(void *);
93 static int tls_alloc(tls_conn **, nng_tls_config *, nng_aio *);
94 static int tls_start(tls_conn *, nng_stream *);
95 static void tls_tcp_error(tls_conn *, int);
96
97 static nni_reap_list tls_conn_reap_list = {
98 .rl_offset = offsetof(tls_conn, reap),
99 .rl_func = tls_reap,
100 };
101
102 typedef struct {
103 nng_stream_dialer ops;
104 nng_stream_dialer *d; // underlying TCP dialer
105 nng_tls_config * cfg;
106 nni_mtx lk; // protects the config
107 } tls_dialer;
108
109 static void
tls_dialer_close(void * arg)110 tls_dialer_close(void *arg)
111 {
112 tls_dialer *d = arg;
113 nng_stream_dialer_close(d->d);
114 }
115
116 static void
tls_dialer_free(void * arg)117 tls_dialer_free(void *arg)
118 {
119 tls_dialer *d;
120 if ((d = arg) != NULL) {
121 nng_stream_dialer_free(d->d);
122 nng_tls_config_free(d->cfg);
123 nni_mtx_fini(&d->lk);
124 NNI_FREE_STRUCT(d);
125 }
126 }
127
128 // For dialing, we need to have our own completion callback, instead of
129 // the user's completion callback.
130
131 static void
tls_conn_cb(void * arg)132 tls_conn_cb(void *arg)
133 {
134 tls_conn * conn = arg;
135 nng_stream *tcp;
136 int rv;
137
138 if ((rv = nni_aio_result(&conn->conn_aio)) != 0) {
139 nni_aio_finish_error(conn->user_aio, rv);
140 nng_stream_free(&conn->stream);
141 return;
142 }
143
144 tcp = nni_aio_get_output(&conn->conn_aio, 0);
145
146 if ((rv = tls_start(conn, tcp)) != 0) {
147 nni_aio_finish_error(conn->user_aio, rv);
148 nng_stream_free(&conn->stream);
149 return;
150 }
151
152 nni_aio_set_output(conn->user_aio, 0, &conn->stream);
153 nni_aio_finish(conn->user_aio, 0, 0);
154 }
155
156 // Dialer cancel is called when the user has indicated that they no longer
157 // want to wait for the connection to establish.
158 static void
tls_conn_cancel(nni_aio * aio,void * arg,int rv)159 tls_conn_cancel(nni_aio *aio, void *arg, int rv)
160 {
161 tls_conn *conn = arg;
162
163 NNI_ARG_UNUSED(aio);
164
165 // Just pass this down. If the connection is already done, this
166 // will have no effect.
167 nni_aio_abort(&conn->conn_aio, rv);
168 }
169
170 static void
tls_dialer_dial(void * arg,nng_aio * aio)171 tls_dialer_dial(void *arg, nng_aio *aio)
172 {
173 tls_dialer *d = arg;
174 int rv;
175 tls_conn * conn;
176
177 if (nni_aio_begin(aio) != 0) {
178 return;
179 }
180 if ((rv = tls_alloc(&conn, d->cfg, aio)) != 0) {
181 nni_aio_finish_error(aio, rv);
182 return;
183 }
184
185 if ((rv = nni_aio_schedule(aio, tls_conn_cancel, conn)) != 0) {
186 nni_aio_finish_error(aio, rv);
187 tls_free(conn);
188 return;
189 }
190
191 nng_stream_dialer_dial(d->d, &conn->conn_aio);
192 }
193
194 static int
tls_check_string(const void * v,size_t sz,nni_opt_type t)195 tls_check_string(const void *v, size_t sz, nni_opt_type t)
196 {
197 switch (t) {
198 case NNI_TYPE_OPAQUE:
199 if (nni_strnlen(v, sz) >= sz) {
200 return (NNG_EINVAL);
201 }
202 return (0);
203 case NNI_TYPE_STRING:
204 // Caller is assumed to pass a good string.
205 return (0);
206 default:
207 return (NNG_EBADTYPE);
208 }
209 }
210
211 static int
tls_dialer_set_config(void * arg,const void * buf,size_t sz,nni_type t)212 tls_dialer_set_config(void *arg, const void *buf, size_t sz, nni_type t)
213 {
214 int rv;
215 nng_tls_config *cfg;
216 tls_dialer * d = arg;
217 nng_tls_config *old;
218
219 if ((rv = nni_copyin_ptr((void **) &cfg, buf, sz, t)) != 0) {
220 return (rv);
221 }
222 if (cfg == NULL) {
223 return (NNG_EINVAL);
224 }
225 nng_tls_config_hold(cfg);
226
227 nni_mtx_lock(&d->lk);
228 old = d->cfg;
229 d->cfg = cfg;
230 nni_mtx_unlock(&d->lk);
231
232 nng_tls_config_free(old);
233 return (0);
234 }
235
236 static int
tls_dialer_get_config(void * arg,void * buf,size_t * szp,nni_type t)237 tls_dialer_get_config(void *arg, void *buf, size_t *szp, nni_type t)
238 {
239 tls_dialer * d = arg;
240 nng_tls_config *cfg;
241 int rv;
242 nni_mtx_lock(&d->lk);
243 if ((cfg = d->cfg) != NULL) {
244 nng_tls_config_hold(cfg);
245 }
246 if ((rv = nni_copyout_ptr(cfg, buf, szp, t)) != 0) {
247 nng_tls_config_free(cfg);
248 }
249 nni_mtx_unlock(&d->lk);
250 return (rv);
251 }
252
253 static int
tls_dialer_set_server_name(void * arg,const void * buf,size_t sz,nni_type t)254 tls_dialer_set_server_name(void *arg, const void *buf, size_t sz, nni_type t)
255 {
256 tls_dialer *d = arg;
257 int rv;
258 if ((rv = tls_check_string(buf, sz, t)) == 0) {
259 nni_mtx_lock(&d->lk);
260 rv = nng_tls_config_server_name(d->cfg, buf);
261 nni_mtx_unlock(&d->lk);
262 }
263 return (rv);
264 }
265
266 static int
tls_dialer_set_auth_mode(void * arg,const void * buf,size_t sz,nni_type t)267 tls_dialer_set_auth_mode(void *arg, const void *buf, size_t sz, nni_type t)
268 {
269 int mode;
270 int rv;
271 tls_dialer *d = arg;
272
273 rv = nni_copyin_int(&mode, buf, sz, NNG_TLS_AUTH_MODE_NONE,
274 NNG_TLS_AUTH_MODE_REQUIRED, t);
275 if (rv == 0) {
276 nni_mtx_lock(&d->lk);
277 rv = nng_tls_config_auth_mode(d->cfg, mode);
278 nni_mtx_unlock(&d->lk);
279 }
280 return (rv);
281 }
282
283 static int
tls_dialer_set_ca_file(void * arg,const void * buf,size_t sz,nni_opt_type t)284 tls_dialer_set_ca_file(void *arg, const void *buf, size_t sz, nni_opt_type t)
285 {
286 tls_dialer *d = arg;
287 int rv;
288
289 if ((rv = tls_check_string(buf, sz, t)) == 0) {
290 nni_mtx_lock(&d->lk);
291 rv = nng_tls_config_ca_file(d->cfg, buf);
292 nni_mtx_unlock(&d->lk);
293 }
294 return (rv);
295 }
296
297 static int
tls_dialer_set_cert_key_file(void * arg,const void * buf,size_t sz,nni_opt_type t)298 tls_dialer_set_cert_key_file(
299 void *arg, const void *buf, size_t sz, nni_opt_type t)
300 {
301 tls_dialer *d = arg;
302 int rv;
303
304 if ((rv = tls_check_string(buf, sz, t)) == 0) {
305 nni_mtx_lock(&d->lk);
306 rv = nng_tls_config_cert_key_file(d->cfg, buf, NULL);
307 nni_mtx_unlock(&d->lk);
308 }
309 return (rv);
310 }
311
312 static const nni_option tls_dialer_opts[] = {
313 {
314 .o_name = NNG_OPT_TLS_CONFIG,
315 .o_get = tls_dialer_get_config,
316 .o_set = tls_dialer_set_config,
317 },
318 {
319 .o_name = NNG_OPT_TLS_SERVER_NAME,
320 .o_set = tls_dialer_set_server_name,
321 },
322 {
323 .o_name = NNG_OPT_TLS_CA_FILE,
324 .o_set = tls_dialer_set_ca_file,
325 },
326 {
327 .o_name = NNG_OPT_TLS_CERT_KEY_FILE,
328 .o_set = tls_dialer_set_cert_key_file,
329 },
330 {
331 .o_name = NNG_OPT_TLS_AUTH_MODE,
332 .o_set = tls_dialer_set_auth_mode,
333 },
334 {
335 .o_name = NULL,
336 },
337 };
338
339 static int
tls_dialer_get(void * arg,const char * name,void * buf,size_t * szp,nni_type t)340 tls_dialer_get(void *arg, const char *name, void *buf, size_t *szp, nni_type t)
341 {
342 tls_dialer *d = arg;
343 int rv;
344
345 rv = nni_stream_dialer_get(d->d, name, buf, szp, t);
346 if (rv == NNG_ENOTSUP) {
347 rv = nni_getopt(tls_dialer_opts, name, d, buf, szp, t);
348 }
349 return (rv);
350 }
351
352 static int
tls_dialer_set(void * arg,const char * name,const void * buf,size_t sz,nni_type t)353 tls_dialer_set(
354 void *arg, const char *name, const void *buf, size_t sz, nni_type t)
355 {
356 tls_dialer *d = arg;
357 int rv;
358
359 rv = nni_stream_dialer_set(d->d, name, buf, sz, t);
360 if (rv == NNG_ENOTSUP) {
361 rv = nni_setopt(tls_dialer_opts, name, d, buf, sz, t);
362 }
363 return (rv);
364 }
365
366 int
nni_tls_dialer_alloc(nng_stream_dialer ** dp,const nng_url * url)367 nni_tls_dialer_alloc(nng_stream_dialer **dp, const nng_url *url)
368 {
369 tls_dialer *d;
370 int rv;
371 nng_url my_url;
372
373 memcpy(&my_url, url, sizeof(my_url));
374 if (strncmp(my_url.u_scheme, "tls+", 4) == 0) {
375 my_url.u_scheme += 4;
376 }
377
378 if ((rv = nni_init()) != 0) {
379 return (rv);
380 }
381 if ((d = NNI_ALLOC_STRUCT(d)) == NULL) {
382 return (NNG_ENOMEM);
383 }
384 nni_mtx_init(&d->lk);
385
386 if ((rv = nng_stream_dialer_alloc_url(&d->d, &my_url)) != 0) {
387 nni_mtx_fini(&d->lk);
388 NNI_FREE_STRUCT(d);
389 return (rv);
390 }
391 if ((rv = nng_tls_config_alloc(&d->cfg, NNG_TLS_MODE_CLIENT)) != 0) {
392 nng_stream_dialer_free(d->d);
393 nni_mtx_fini(&d->lk);
394 NNI_FREE_STRUCT(d);
395 return (rv);
396 }
397
398 // Set the expected outbound hostname
399 nng_tls_config_server_name(d->cfg, url->u_hostname);
400
401 d->ops.sd_close = tls_dialer_close;
402 d->ops.sd_free = tls_dialer_free;
403 d->ops.sd_dial = tls_dialer_dial;
404 d->ops.sd_get = tls_dialer_get;
405 d->ops.sd_set = tls_dialer_set;
406 *dp = (void *) d;
407 return (rv);
408 }
409
410 typedef struct {
411 nng_stream_listener ops;
412 nng_stream_listener *l;
413 nng_tls_config * cfg;
414 nni_mtx lk;
415 } tls_listener;
416
417 static void
tls_listener_close(void * arg)418 tls_listener_close(void *arg)
419 {
420 tls_listener *l = arg;
421 nng_stream_listener_close(l->l);
422 }
423
424 static void
tls_listener_free(void * arg)425 tls_listener_free(void *arg)
426 {
427 tls_listener *l;
428 if ((l = arg) != NULL) {
429 tls_listener_close(l);
430 nng_tls_config_free(l->cfg);
431 nng_stream_listener_free(l->l);
432 nni_mtx_fini(&l->lk);
433 NNI_FREE_STRUCT(l);
434 }
435 }
436
437 static int
tls_listener_listen(void * arg)438 tls_listener_listen(void *arg)
439 {
440 tls_listener *l = arg;
441 return (nng_stream_listener_listen(l->l));
442 }
443
444 static void
tls_listener_accept(void * arg,nng_aio * aio)445 tls_listener_accept(void *arg, nng_aio *aio)
446 {
447 tls_listener *l = arg;
448 int rv;
449 tls_conn * conn;
450
451 if (nni_aio_begin(aio) != 0) {
452 return;
453 }
454 if ((rv = tls_alloc(&conn, l->cfg, aio)) != 0) {
455 nni_aio_finish_error(aio, rv);
456 return;
457 }
458
459 if ((rv = nni_aio_schedule(aio, tls_conn_cancel, conn)) != 0) {
460 nni_aio_finish_error(aio, rv);
461 tls_free(conn);
462 return;
463 }
464
465 nng_stream_listener_accept(l->l, &conn->conn_aio);
466 }
467
468 static int
tls_listener_set_config(void * arg,const void * buf,size_t sz,nni_type t)469 tls_listener_set_config(void *arg, const void *buf, size_t sz, nni_type t)
470 {
471 int rv;
472 nng_tls_config *cfg;
473 tls_listener * l = arg;
474 nng_tls_config *old;
475
476 if ((rv = nni_copyin_ptr((void **) &cfg, buf, sz, t)) != 0) {
477 return (rv);
478 }
479 if (cfg == NULL) {
480 return (NNG_EINVAL);
481 }
482
483 nng_tls_config_hold(cfg);
484
485 nni_mtx_lock(&l->lk);
486 old = l->cfg;
487 l->cfg = cfg;
488 nni_mtx_unlock(&l->lk);
489
490 nng_tls_config_free(old);
491
492 return (0);
493 }
494
495 static int
tls_listener_get_config(void * arg,void * buf,size_t * szp,nni_type t)496 tls_listener_get_config(void *arg, void *buf, size_t *szp, nni_type t)
497 {
498 tls_listener * l = arg;
499 nng_tls_config *cfg;
500 int rv;
501 nni_mtx_lock(&l->lk);
502 if ((cfg = l->cfg) != NULL) {
503 nng_tls_config_hold(cfg);
504 }
505 if ((rv = nni_copyout_ptr(cfg, buf, szp, t)) != 0) {
506 nng_tls_config_free(cfg);
507 }
508 nni_mtx_unlock(&l->lk);
509 return (rv);
510 }
511
512 static int
tls_listener_set_server_name(void * arg,const void * buf,size_t sz,nni_type t)513 tls_listener_set_server_name(void *arg, const void *buf, size_t sz, nni_type t)
514 {
515 tls_listener *l = arg;
516 int rv;
517 if ((rv = tls_check_string(buf, sz, t)) == 0) {
518 nni_mtx_lock(&l->lk);
519 rv = nng_tls_config_server_name(l->cfg, buf);
520 nni_mtx_unlock(&l->lk);
521 }
522 return (rv);
523 }
524
525 static int
tls_listener_set_auth_mode(void * arg,const void * buf,size_t sz,nni_type t)526 tls_listener_set_auth_mode(void *arg, const void *buf, size_t sz, nni_type t)
527 {
528 int mode;
529 int rv;
530 tls_listener *l = arg;
531
532 rv = nni_copyin_int(&mode, buf, sz, NNG_TLS_AUTH_MODE_NONE,
533 NNG_TLS_AUTH_MODE_REQUIRED, t);
534 if (rv == 0) {
535 nni_mtx_lock(&l->lk);
536 rv = nng_tls_config_auth_mode(l->cfg, mode);
537 nni_mtx_unlock(&l->lk);
538 }
539 return (rv);
540 }
541
542 static int
tls_listener_set_ca_file(void * arg,const void * buf,size_t sz,nni_opt_type t)543 tls_listener_set_ca_file(void *arg, const void *buf, size_t sz, nni_opt_type t)
544 {
545 tls_listener *l = arg;
546 int rv;
547
548 if ((rv = tls_check_string(buf, sz, t)) == 0) {
549 nni_mtx_lock(&l->lk);
550 rv = nng_tls_config_ca_file(l->cfg, buf);
551 nni_mtx_unlock(&l->lk);
552 }
553 return (rv);
554 }
555
556 static int
tls_listener_set_cert_key_file(void * arg,const void * buf,size_t sz,nni_opt_type t)557 tls_listener_set_cert_key_file(
558 void *arg, const void *buf, size_t sz, nni_opt_type t)
559 {
560 tls_listener *l = arg;
561 int rv;
562
563 if ((rv = tls_check_string(buf, sz, t)) == 0) {
564 nni_mtx_lock(&l->lk);
565 rv = nng_tls_config_cert_key_file(l->cfg, buf, NULL);
566 nni_mtx_unlock(&l->lk);
567 }
568 return (rv);
569 }
570
571 static const nni_option tls_listener_opts[] = {
572 {
573 .o_name = NNG_OPT_TLS_CONFIG,
574 .o_get = tls_listener_get_config,
575 .o_set = tls_listener_set_config,
576 },
577 {
578 .o_name = NNG_OPT_TLS_SERVER_NAME,
579 .o_set = tls_listener_set_server_name,
580 },
581 {
582 .o_name = NNG_OPT_TLS_CA_FILE,
583 .o_set = tls_listener_set_ca_file,
584 },
585 {
586 .o_name = NNG_OPT_TLS_CERT_KEY_FILE,
587 .o_set = tls_listener_set_cert_key_file,
588 },
589 {
590 .o_name = NNG_OPT_TLS_AUTH_MODE,
591 .o_set = tls_listener_set_auth_mode,
592 },
593 {
594 .o_name = NULL,
595 },
596 };
597
598 static int
tls_listener_get(void * arg,const char * name,void * buf,size_t * szp,nni_type t)599 tls_listener_get(
600 void *arg, const char *name, void *buf, size_t *szp, nni_type t)
601 {
602 int rv;
603 tls_listener *l = arg;
604
605 rv = nni_stream_listener_get(l->l, name, buf, szp, t);
606 if (rv == NNG_ENOTSUP) {
607 rv = nni_getopt(tls_listener_opts, name, l, buf, szp, t);
608 }
609 return (rv);
610 }
611
612 static int
tls_listener_set(void * arg,const char * name,const void * buf,size_t sz,nni_type t)613 tls_listener_set(
614 void *arg, const char *name, const void *buf, size_t sz, nni_type t)
615 {
616 int rv;
617 tls_listener *l = arg;
618
619 rv = nni_stream_listener_set(l->l, name, buf, sz, t);
620 if (rv == NNG_ENOTSUP) {
621 rv = nni_setopt(tls_listener_opts, name, l, buf, sz, t);
622 }
623 return (rv);
624 }
625
626 int
nni_tls_listener_alloc(nng_stream_listener ** lp,const nng_url * url)627 nni_tls_listener_alloc(nng_stream_listener **lp, const nng_url *url)
628 {
629 tls_listener *l;
630 int rv;
631 nng_url my_url;
632
633 memcpy(&my_url, url, sizeof(my_url));
634
635 if (strncmp(my_url.u_scheme, "tls+", 4) == 0) {
636 my_url.u_scheme += 4;
637 }
638
639 if ((rv = nni_init()) != 0) {
640 return (rv);
641 }
642 if ((l = NNI_ALLOC_STRUCT(l)) == NULL) {
643 return (NNG_ENOMEM);
644 }
645 nni_mtx_init(&l->lk);
646
647 if ((rv = nng_stream_listener_alloc_url(&l->l, &my_url)) != 0) {
648 nni_mtx_fini(&l->lk);
649 NNI_FREE_STRUCT(l);
650 return (rv);
651 }
652 if ((rv = nng_tls_config_alloc(&l->cfg, NNG_TLS_MODE_SERVER)) != 0) {
653 nng_stream_listener_free(l->l);
654 nni_mtx_fini(&l->lk);
655 NNI_FREE_STRUCT(l);
656 return (rv);
657 }
658 l->ops.sl_free = tls_listener_free;
659 l->ops.sl_close = tls_listener_close;
660 l->ops.sl_accept = tls_listener_accept;
661 l->ops.sl_listen = tls_listener_listen;
662 l->ops.sl_get = tls_listener_get;
663 l->ops.sl_set = tls_listener_set;
664 *lp = (void *) l;
665 return (0);
666 }
667
668 static void
tls_cancel(nni_aio * aio,void * arg,int rv)669 tls_cancel(nni_aio *aio, void *arg, int rv)
670 {
671 tls_conn *conn = arg;
672 nni_mtx_lock(&conn->lock);
673 if (aio == nni_list_first(&conn->recv_queue)) {
674 nni_aio_abort(&conn->tcp_recv, rv);
675 } else if (aio == nni_list_first(&conn->send_queue)) {
676 nni_aio_abort(&conn->tcp_send, rv);
677 } else if (nni_aio_list_active(aio)) {
678 nni_aio_list_remove(aio);
679 nni_aio_finish_error(aio, rv);
680 }
681 nni_mtx_unlock(&conn->lock);
682 }
683
684 // tls_send implements the upper layer stream send operation.
685 static void
tls_send(void * arg,nni_aio * aio)686 tls_send(void *arg, nni_aio *aio)
687 {
688 int rv;
689 tls_conn *conn = arg;
690
691 if (nni_aio_begin(aio) != 0) {
692 return;
693 }
694 nni_mtx_lock(&conn->lock);
695 if (conn->closed) {
696 nni_mtx_unlock(&conn->lock);
697 nni_aio_finish_error(aio, NNG_ECLOSED);
698 return;
699 }
700 if ((rv = nni_aio_schedule(aio, tls_cancel, conn)) != 0) {
701 nni_mtx_unlock(&conn->lock);
702 nni_aio_finish_error(aio, rv);
703 return;
704 }
705 nni_list_append(&conn->send_queue, aio);
706 tls_do_send(conn);
707 nni_mtx_unlock(&conn->lock);
708 }
709
710 static void
tls_recv(void * arg,nni_aio * aio)711 tls_recv(void *arg, nni_aio *aio)
712 {
713 int rv;
714 tls_conn *conn = arg;
715
716 if (nni_aio_begin(aio) != 0) {
717 return;
718 }
719 nni_mtx_lock(&conn->lock);
720 if (conn->closed) {
721 nni_mtx_unlock(&conn->lock);
722 nni_aio_finish_error(aio, NNG_ECLOSED);
723 return;
724 }
725 if ((rv = nni_aio_schedule(aio, tls_cancel, conn)) != 0) {
726 nni_mtx_unlock(&conn->lock);
727 nni_aio_finish_error(aio, rv);
728 return;
729 }
730
731 nni_list_append(&conn->recv_queue, aio);
732 tls_do_recv(conn);
733 nni_mtx_unlock(&conn->lock);
734 }
735
736 static void
tls_close(void * arg)737 tls_close(void *arg)
738 {
739 tls_conn *conn = arg;
740
741 nni_mtx_lock(&conn->lock);
742 conn->ops.close((void *) (conn + 1));
743 tls_tcp_error(conn, NNG_ECLOSED);
744 nni_mtx_unlock(&conn->lock);
745 nng_stream_close(conn->tcp);
746 }
747
748 static int
tls_get_verified(void * arg,void * buf,size_t * szp,nni_type t)749 tls_get_verified(void *arg, void *buf, size_t *szp, nni_type t)
750 {
751 tls_conn *conn = arg;
752 bool v;
753
754 nni_mtx_lock(&conn->lock);
755 v = conn->ops.verified((void *) (conn + 1));
756 nni_mtx_unlock(&conn->lock);
757 return (nni_copyout_bool(v, buf, szp, t));
758 }
759
760 static const nni_option tls_options[] = {
761 {
762 .o_name = NNG_OPT_TLS_VERIFIED,
763 .o_get = tls_get_verified,
764 },
765 {
766 .o_name = NULL,
767 },
768 };
769
770 static int
tls_set(void * arg,const char * name,const void * buf,size_t sz,nni_type t)771 tls_set(void *arg, const char *name, const void *buf, size_t sz, nni_type t)
772 {
773 tls_conn * conn = arg;
774 int rv;
775 nng_stream *tcp;
776
777 tcp = (conn != NULL) ? conn->tcp : NULL;
778
779 if ((rv = nni_stream_set(tcp, name, buf, sz, t)) != NNG_ENOTSUP) {
780 return (rv);
781 }
782 return (nni_setopt(tls_options, name, conn, buf, sz, t));
783 }
784
785 static int
tls_get(void * arg,const char * name,void * buf,size_t * szp,nni_type t)786 tls_get(void *arg, const char *name, void *buf, size_t *szp, nni_type t)
787 {
788 tls_conn *conn = arg;
789 int rv;
790
791 if ((rv = nni_stream_get(conn->tcp, name, buf, szp, t)) !=
792 NNG_ENOTSUP) {
793 return (rv);
794 }
795 return (nni_getopt(tls_options, name, conn, buf, szp, t));
796 }
797
798 static int
tls_alloc(tls_conn ** conn_p,nng_tls_config * cfg,nng_aio * user_aio)799 tls_alloc(tls_conn **conn_p, nng_tls_config *cfg, nng_aio *user_aio)
800 {
801 tls_conn * conn;
802 const nng_tls_engine *eng;
803 size_t size;
804
805 eng = cfg->engine;
806
807 size = NNI_ALIGN_UP(sizeof(*conn)) + eng->conn_ops->size;
808
809 if ((conn = nni_zalloc(size)) == NULL) {
810 return (NNG_ENOMEM);
811 }
812 if (((conn->tcp_send_buf = nni_alloc(NNG_TLS_MAX_SEND_SIZE)) ==
813 NULL) ||
814 ((conn->tcp_recv_buf = nni_alloc(NNG_TLS_MAX_RECV_SIZE)) ==
815 NULL)) {
816 tls_free(conn);
817 return (NNG_ENOMEM);
818 }
819 conn->size = size;
820 conn->ops = *eng->conn_ops;
821 conn->engine = eng;
822 conn->user_aio = user_aio;
823 conn->cfg = cfg;
824
825 nni_aio_init(&conn->conn_aio, tls_conn_cb, conn);
826 nni_aio_init(&conn->tcp_recv, tls_tcp_recv_cb, conn);
827 nni_aio_init(&conn->tcp_send, tls_tcp_send_cb, conn);
828 nni_aio_list_init(&conn->send_queue);
829 nni_aio_list_init(&conn->recv_queue);
830 nni_mtx_init(&conn->lock);
831 nni_aio_set_timeout(&conn->tcp_send, NNG_DURATION_INFINITE);
832 nni_aio_set_timeout(&conn->tcp_recv, NNG_DURATION_INFINITE);
833
834 conn->stream.s_close = tls_close;
835 conn->stream.s_free = tls_free;
836 conn->stream.s_send = tls_send;
837 conn->stream.s_recv = tls_recv;
838 conn->stream.s_get = tls_get;
839 conn->stream.s_set = tls_set;
840
841 nng_tls_config_hold(cfg);
842 *conn_p = conn;
843 return (0);
844 }
845
846 static void
tls_reap(void * arg)847 tls_reap(void *arg)
848 {
849 tls_conn *conn = arg;
850
851 // Shut it all down first. We should be freed.
852 if (conn->tcp != NULL) {
853 nng_stream_close(conn->tcp);
854 }
855 nni_aio_stop(&conn->conn_aio);
856 nni_aio_stop(&conn->tcp_send);
857 nni_aio_stop(&conn->tcp_recv);
858
859 conn->ops.fini((void *) (conn + 1));
860 nni_aio_fini(&conn->conn_aio);
861 nni_aio_fini(&conn->tcp_send);
862 nni_aio_fini(&conn->tcp_recv);
863 nng_stream_free(conn->tcp);
864 if (conn->cfg != NULL) {
865 nng_tls_config_free(conn->cfg); // this drops our hold on it
866 }
867 if (conn->tcp_send_buf != NULL) {
868 nni_free(conn->tcp_send_buf, NNG_TLS_MAX_SEND_SIZE);
869 }
870 if (conn->tcp_recv_buf != NULL) {
871 nni_free(conn->tcp_recv_buf, NNG_TLS_MAX_RECV_SIZE);
872 }
873 NNI_FREE_STRUCT(conn);
874 }
875
876 static void
tls_free(void * arg)877 tls_free(void *arg)
878 {
879 tls_conn *conn = arg;
880
881 nni_reap(&tls_conn_reap_list, conn);
882 }
883
884 static int
tls_start(tls_conn * conn,nng_stream * tcp)885 tls_start(tls_conn *conn, nng_stream *tcp)
886 {
887 int rv;
888
889 conn->tcp = tcp;
890 rv = conn->ops.init(
891 (void *) (conn + 1), conn, (void *) (conn->cfg + 1));
892 return (rv);
893 }
894
895 static void
tls_tcp_error(tls_conn * conn,int rv)896 tls_tcp_error(tls_conn *conn, int rv)
897 {
898 // An error here is fatal. Shut it all down.
899 nni_aio *aio;
900 nng_stream_close(conn->tcp);
901 nni_aio_close(&conn->tcp_send);
902 nni_aio_close(&conn->tcp_recv);
903 while (((aio = nni_list_first(&conn->send_queue)) != NULL) ||
904 ((aio = nni_list_first(&conn->recv_queue)) != NULL)) {
905 nni_aio_list_remove(aio);
906 nni_aio_finish_error(aio, rv);
907 }
908 }
909
910 static bool
tls_do_handshake(tls_conn * conn)911 tls_do_handshake(tls_conn *conn)
912 {
913 int rv;
914 if (conn->hs_done) {
915 return (true);
916 }
917 rv = conn->ops.handshake((void *) (conn + 1));
918 if (rv == NNG_EAGAIN) {
919 // We need more data.
920 return (false);
921 }
922 if (rv == 0) {
923 conn->hs_done = true;
924 return (true);
925 }
926 tls_tcp_error(conn, rv);
927 return (true);
928 }
929
930 static void
tls_do_recv(tls_conn * conn)931 tls_do_recv(tls_conn *conn)
932 {
933 nni_aio *aio;
934
935 while ((aio = nni_list_first(&conn->recv_queue)) != NULL) {
936 uint8_t *buf = NULL;
937 size_t len = 0;
938 nni_iov *iov;
939 unsigned nio;
940 int rv;
941
942 nni_aio_get_iov(aio, &nio, &iov);
943
944 for (unsigned i = 0; i < nio; i++) {
945 if (iov[i].iov_len != 0) {
946 buf = iov[i].iov_buf;
947 len = iov[i].iov_len;
948 break;
949 }
950 }
951 if (len == 0 || buf == NULL) {
952 // Caller has asked to receive "nothing".
953 nni_aio_list_remove(aio);
954 nni_aio_finish_error(aio, NNG_EINVAL);
955 continue;
956 }
957
958 rv = conn->ops.recv((void *) (conn + 1), buf, &len);
959 if (rv == NNG_EAGAIN) {
960 // Nothing more we can do, the engine doesn't
961 // have anything else for us (yet).
962 return;
963 }
964
965 // Unlike the send side, we want to return back to the
966 // caller as *soon* as we have some data.
967 nni_aio_list_remove(aio);
968
969 if (rv != 0) {
970 nni_aio_finish_error(aio, rv);
971 } else {
972 nni_aio_finish(aio, 0, len);
973 }
974 }
975 }
976
977 // tls_do_send attempts to send user data.
978 static void
tls_do_send(tls_conn * conn)979 tls_do_send(tls_conn *conn)
980 {
981 nni_aio *aio;
982
983 while ((aio = nni_list_first(&conn->send_queue)) != NULL) {
984 uint8_t *buf = NULL;
985 size_t len = 0;
986 nni_iov *iov;
987 unsigned nio;
988 int rv;
989
990 nni_aio_get_iov(aio, &nio, &iov);
991
992 for (unsigned i = 0; i < nio; i++) {
993 if (iov[i].iov_len != 0) {
994 buf = iov[i].iov_buf;
995 len = iov[i].iov_len;
996 break;
997 }
998 }
999 if (len == 0 || buf == NULL) {
1000 nni_aio_list_remove(aio);
1001 // Presumably this means we've completed this
1002 // one, lets preserve the count, and move to the
1003 // next.
1004 nni_aio_finish(aio, 0, nni_aio_count(aio));
1005 continue;
1006 }
1007
1008 // Ask the engine to send.
1009 rv = conn->ops.send((void *) (conn + 1), buf, &len);
1010 if (rv == NNG_EAGAIN) {
1011 // Can't send any more, wait for callback.
1012 return;
1013 }
1014
1015 if (rv != 0) {
1016 nni_aio_list_remove(aio);
1017 nni_aio_finish_error(aio, rv);
1018 } else {
1019 nni_aio_list_remove(aio);
1020 nni_aio_finish(aio, 0, len);
1021 }
1022 }
1023 }
1024
1025 static void
tls_tcp_send_cb(void * arg)1026 tls_tcp_send_cb(void *arg)
1027 {
1028 tls_conn *conn = arg;
1029 nng_aio * aio = &conn->tcp_send;
1030 int rv;
1031 size_t count;
1032
1033 nni_mtx_lock(&conn->lock);
1034 conn->tcp_send_active = false;
1035
1036 if ((rv = nni_aio_result(aio)) != 0) {
1037 tls_tcp_error(conn, rv);
1038 nni_mtx_unlock(&conn->lock);
1039 return;
1040 }
1041
1042 count = nni_aio_count(aio);
1043 NNI_ASSERT(count <= conn->tcp_send_len);
1044 conn->tcp_send_len -= count;
1045 conn->tcp_send_tail += count;
1046 conn->tcp_send_tail %= NNG_TLS_MAX_SEND_SIZE;
1047 tls_tcp_send_start(conn);
1048
1049 if (tls_do_handshake(conn)) {
1050 tls_do_send(conn);
1051 tls_do_recv(conn);
1052 }
1053
1054 nni_mtx_unlock(&conn->lock);
1055 }
1056
1057 static void
tls_tcp_recv_cb(void * arg)1058 tls_tcp_recv_cb(void *arg)
1059 {
1060 tls_conn *conn = arg;
1061 nni_aio * aio = &conn->tcp_recv;
1062 int rv;
1063
1064 nni_mtx_lock(&conn->lock);
1065
1066 conn->tcp_recv_pend = false;
1067 if ((rv = nni_aio_result(aio)) != 0) {
1068 tls_tcp_error(conn, rv);
1069 nni_mtx_unlock(&conn->lock);
1070 return;
1071 }
1072
1073 NNI_ASSERT(conn->tcp_recv_len == 0);
1074 NNI_ASSERT(conn->tcp_recv_off == 0);
1075 conn->tcp_recv_len = nni_aio_count(aio);
1076
1077 if (tls_do_handshake(conn)) {
1078 tls_do_recv(conn);
1079 tls_do_send(conn);
1080 }
1081
1082 nni_mtx_unlock(&conn->lock);
1083 }
1084
1085 static void
tls_tcp_recv_start(tls_conn * conn)1086 tls_tcp_recv_start(tls_conn *conn)
1087 {
1088 nng_iov iov;
1089
1090 if (conn->tcp_recv_len != 0) {
1091 // We already have data in the buffer.
1092 return;
1093 }
1094 if (conn->tcp_recv_pend) {
1095 // Already have a receive in flight.
1096 return;
1097 }
1098 conn->tcp_recv_off = 0;
1099 iov.iov_len = NNG_TLS_MAX_RECV_SIZE;
1100 iov.iov_buf = conn->tcp_recv_buf;
1101
1102 conn->tcp_recv_pend = true;
1103 nng_aio_set_iov(&conn->tcp_recv, 1, &iov);
1104
1105 nng_stream_recv(conn->tcp, &conn->tcp_recv);
1106 }
1107
1108 static void
tls_tcp_send_start(tls_conn * conn)1109 tls_tcp_send_start(tls_conn *conn)
1110 {
1111 nni_iov iov[2];
1112 unsigned nio = 0;
1113 size_t len;
1114 size_t tail;
1115 size_t head;
1116
1117 if (conn->tcp_send_active) {
1118 return;
1119 }
1120 if (conn->tcp_send_len == 0) {
1121 return;
1122 }
1123 len = conn->tcp_send_len;
1124 head = conn->tcp_send_head;
1125 tail = conn->tcp_send_tail;
1126
1127 while (len > 0) {
1128 size_t cnt;
1129 NNI_ASSERT(nio < 2);
1130 if (tail < head) {
1131 cnt = head - tail;
1132 } else {
1133 cnt = NNG_TLS_MAX_SEND_SIZE - tail;
1134 }
1135 if (cnt > len) {
1136 cnt = len;
1137 }
1138 iov[nio].iov_buf = conn->tcp_send_buf + tail;
1139 iov[nio].iov_len = cnt;
1140 len -= cnt;
1141 tail += cnt;
1142 tail %= NNG_TLS_MAX_SEND_SIZE;
1143 nio++;
1144 }
1145 conn->tcp_send_active = true;
1146 nni_aio_set_iov(&conn->tcp_send, nio, iov);
1147 nng_stream_send(conn->tcp, &conn->tcp_send);
1148 }
1149
1150 int
nng_tls_engine_send(void * arg,const uint8_t * buf,size_t * szp)1151 nng_tls_engine_send(void *arg, const uint8_t *buf, size_t *szp)
1152 {
1153 tls_conn *conn = arg;
1154 size_t len = *szp;
1155 size_t head = conn->tcp_send_head;
1156 size_t tail = conn->tcp_send_tail;
1157 size_t space;
1158 size_t cnt;
1159
1160 space = NNG_TLS_MAX_SEND_SIZE - conn->tcp_send_len;
1161
1162 if (space == 0) {
1163 return (NNG_EAGAIN);
1164 }
1165
1166 if (conn->closed) {
1167 return (NNG_ECLOSED);
1168 }
1169
1170 if (len > space) {
1171 len = space;
1172 }
1173
1174 // We are committed at this point to sending out len bytes.
1175 // Update this now, so that we can use len to update.
1176 *szp = len;
1177 conn->tcp_send_len += len;
1178 NNI_ASSERT(conn->tcp_send_len <= NNG_TLS_MAX_SEND_SIZE);
1179
1180 while (len > 0) {
1181 if (head >= tail) {
1182 cnt = NNG_TLS_MAX_SEND_SIZE - head;
1183 } else {
1184 cnt = tail - head;
1185 }
1186 if (cnt > len) {
1187 cnt = len;
1188 }
1189
1190 memcpy(conn->tcp_send_buf + head, buf, cnt);
1191 buf += cnt;
1192 head += cnt;
1193 head %= NNG_TLS_MAX_SEND_SIZE;
1194 len -= cnt;
1195 }
1196
1197 conn->tcp_send_head = head;
1198
1199 tls_tcp_send_start(conn);
1200 return (0);
1201 }
1202
1203 int
nng_tls_engine_recv(void * arg,uint8_t * buf,size_t * szp)1204 nng_tls_engine_recv(void *arg, uint8_t *buf, size_t *szp)
1205 {
1206 tls_conn *conn = arg;
1207 size_t len = *szp;
1208
1209 if (conn->closed) {
1210 return (NNG_ECLOSED);
1211 }
1212 if (conn->tcp_recv_len == 0) {
1213 tls_tcp_recv_start(conn);
1214 return (NNG_EAGAIN);
1215 }
1216 if (len > conn->tcp_recv_len) {
1217 len = conn->tcp_recv_len;
1218 }
1219 memcpy(buf, conn->tcp_recv_buf + conn->tcp_recv_off, len);
1220 conn->tcp_recv_off += len;
1221 conn->tcp_recv_len -= len;
1222
1223 // If we still have data left in the buffer, then the following
1224 // call is a no-op.
1225 tls_tcp_recv_start(conn);
1226
1227 *szp = len;
1228 return (0);
1229 }
1230
1231 int
nng_tls_config_cert_key_file(nng_tls_config * cfg,const char * path,const char * pass)1232 nng_tls_config_cert_key_file(
1233 nng_tls_config *cfg, const char *path, const char *pass)
1234 {
1235 int rv;
1236 void * data;
1237 size_t size;
1238 char * pem;
1239
1240 if ((rv = nni_file_get(path, &data, &size)) != 0) {
1241 return (rv);
1242 }
1243 if ((pem = nni_zalloc(size + 1)) == NULL) {
1244 nni_free(data, size);
1245 return (NNG_ENOMEM);
1246 }
1247 memcpy(pem, data, size);
1248 nni_free(data, size);
1249 rv = nng_tls_config_own_cert(cfg, pem, pem, pass);
1250 nni_free(pem, size + 1);
1251 return (rv);
1252 }
1253
1254 int
nng_tls_config_ca_file(nng_tls_config * cfg,const char * path)1255 nng_tls_config_ca_file(nng_tls_config *cfg, const char *path)
1256 {
1257 int rv;
1258 void * data;
1259 size_t size;
1260 char * pem;
1261
1262 if ((rv = nni_file_get(path, &data, &size)) != 0) {
1263 return (rv);
1264 }
1265 if ((pem = nni_zalloc(size + 1)) == NULL) {
1266 nni_free(data, size);
1267 return (NNG_ENOMEM);
1268 }
1269 memcpy(pem, data, size);
1270 nni_free(data, size);
1271 if (strstr(pem, "-----BEGIN X509 CRL-----") != NULL) {
1272 rv = nng_tls_config_ca_chain(cfg, pem, pem);
1273 } else {
1274 rv = nng_tls_config_ca_chain(cfg, pem, NULL);
1275 }
1276 nni_free(pem, size + 1);
1277 return (rv);
1278 }
1279
1280 int
nng_tls_config_version(nng_tls_config * cfg,nng_tls_version min_ver,nng_tls_version max_ver)1281 nng_tls_config_version(
1282 nng_tls_config *cfg, nng_tls_version min_ver, nng_tls_version max_ver)
1283 {
1284 int rv;
1285
1286 nni_mtx_lock(&cfg->lock);
1287 if (cfg->busy != 0) {
1288 rv = NNG_EBUSY;
1289 } else {
1290 rv = cfg->ops.version((void *) (cfg + 1), min_ver, max_ver);
1291 }
1292 nni_mtx_unlock(&cfg->lock);
1293 return (rv);
1294 }
1295
1296 int
nng_tls_config_server_name(nng_tls_config * cfg,const char * name)1297 nng_tls_config_server_name(nng_tls_config *cfg, const char *name)
1298 {
1299 int rv;
1300
1301 nni_mtx_lock(&cfg->lock);
1302 if (cfg->busy != 0) {
1303 rv = NNG_EBUSY;
1304 } else {
1305 rv = cfg->ops.server((void *) (cfg + 1), name);
1306 }
1307 nni_mtx_unlock(&cfg->lock);
1308 return (rv);
1309 }
1310
1311 int
nng_tls_config_ca_chain(nng_tls_config * cfg,const char * certs,const char * crl)1312 nng_tls_config_ca_chain(
1313 nng_tls_config *cfg, const char *certs, const char *crl)
1314 {
1315 int rv;
1316
1317 nni_mtx_lock(&cfg->lock);
1318 if (cfg->busy != 0) {
1319 rv = NNG_EBUSY;
1320 } else {
1321 rv = cfg->ops.ca_chain((void *) (cfg + 1), certs, crl);
1322 }
1323 nni_mtx_unlock(&cfg->lock);
1324 return (rv);
1325 }
1326
1327 int
nng_tls_config_own_cert(nng_tls_config * cfg,const char * cert,const char * key,const char * pass)1328 nng_tls_config_own_cert(
1329 nng_tls_config *cfg, const char *cert, const char *key, const char *pass)
1330 {
1331 int rv;
1332 nni_mtx_lock(&cfg->lock);
1333 if (cfg->busy != 0) {
1334 rv = NNG_EBUSY;
1335 } else {
1336 rv = cfg->ops.own_cert((void *) (cfg + 1), cert, key, pass);
1337 }
1338 nni_mtx_unlock(&cfg->lock);
1339 return (rv);
1340 }
1341
1342 int
nng_tls_config_auth_mode(nng_tls_config * cfg,nng_tls_auth_mode mode)1343 nng_tls_config_auth_mode(nng_tls_config *cfg, nng_tls_auth_mode mode)
1344 {
1345 int rv;
1346
1347 nni_mtx_lock(&cfg->lock);
1348 if (cfg->busy != 0) {
1349 rv = NNG_EBUSY;
1350 } else {
1351 rv = cfg->ops.auth((void *) (cfg + 1), mode);
1352 }
1353 nni_mtx_unlock(&cfg->lock);
1354 return (rv);
1355 }
1356
1357 int
nng_tls_config_alloc(nng_tls_config ** cfg_p,nng_tls_mode mode)1358 nng_tls_config_alloc(nng_tls_config **cfg_p, nng_tls_mode mode)
1359 {
1360 nng_tls_config * cfg;
1361 const nng_tls_engine *eng;
1362 size_t size;
1363 int rv;
1364
1365 if ((rv = nni_init()) != 0) {
1366 return (rv);
1367 }
1368
1369 nni_mtx_lock(&tls_engine_lock);
1370 eng = tls_engine;
1371 nni_mtx_unlock(&tls_engine_lock);
1372
1373 if (eng == NULL) {
1374 return (NNG_ENOTSUP);
1375 }
1376
1377 size = NNI_ALIGN_UP(sizeof(*cfg)) + eng->config_ops->size;
1378
1379 if ((cfg = nni_zalloc(size)) == NULL) {
1380 return (NNG_ENOMEM);
1381 }
1382
1383 cfg->ops = *eng->config_ops;
1384 cfg->size = size;
1385 cfg->engine = eng;
1386 cfg->ref = 1;
1387 cfg->busy = 0;
1388 nni_mtx_init(&cfg->lock);
1389
1390 if ((rv = cfg->ops.init((void *) (cfg + 1), mode)) != 0) {
1391 nni_free(cfg, cfg->size);
1392 return (rv);
1393 }
1394 *cfg_p = cfg;
1395 return (0);
1396 }
1397
1398 void
nng_tls_config_free(nng_tls_config * cfg)1399 nng_tls_config_free(nng_tls_config *cfg)
1400 {
1401 nni_mtx_lock(&cfg->lock);
1402 cfg->ref--;
1403 if (cfg->ref != 0) {
1404 nni_mtx_unlock(&cfg->lock);
1405 return;
1406 }
1407 nni_mtx_unlock(&cfg->lock);
1408 nni_mtx_fini(&cfg->lock);
1409 cfg->ops.fini((void *) (cfg + 1));
1410 nni_free(cfg, cfg->size);
1411 }
1412
1413 void
nng_tls_config_hold(nng_tls_config * cfg)1414 nng_tls_config_hold(nng_tls_config *cfg)
1415 {
1416 nni_mtx_lock(&cfg->lock);
1417 cfg->ref++;
1418 nni_mtx_unlock(&cfg->lock);
1419 }
1420
1421 const char *
nng_tls_engine_name(void)1422 nng_tls_engine_name(void)
1423 {
1424 const nng_tls_engine *eng;
1425
1426 nni_init();
1427 nni_mtx_lock(&tls_engine_lock);
1428 eng = tls_engine;
1429 nni_mtx_unlock(&tls_engine_lock);
1430
1431 return (eng == NULL ? "none" : eng->name);
1432 }
1433
1434 const char *
nng_tls_engine_description(void)1435 nng_tls_engine_description(void)
1436 {
1437 const nng_tls_engine *eng;
1438
1439 nni_init();
1440 nni_mtx_lock(&tls_engine_lock);
1441 eng = tls_engine;
1442 nni_mtx_unlock(&tls_engine_lock);
1443
1444 return (eng == NULL ? "" : eng->description);
1445 }
1446
1447 bool
nng_tls_engine_fips_mode(void)1448 nng_tls_engine_fips_mode(void)
1449 {
1450 const nng_tls_engine *eng;
1451
1452 nni_init();
1453 nni_mtx_lock(&tls_engine_lock);
1454 eng = tls_engine;
1455 nni_mtx_unlock(&tls_engine_lock);
1456
1457 return (eng == NULL ? false : eng->fips_mode);
1458 }
1459
1460 int
nng_tls_engine_register(const nng_tls_engine * engine)1461 nng_tls_engine_register(const nng_tls_engine *engine)
1462 {
1463 if (engine->version != NNG_TLS_ENGINE_VERSION) {
1464 return (NNG_ENOTSUP);
1465 }
1466 nni_mtx_lock(&tls_engine_lock);
1467 tls_engine = engine;
1468 nni_mtx_unlock(&tls_engine_lock);
1469 return (0);
1470 }
1471
1472 #ifdef NNG_TLS_ENGINE_INIT
1473 extern int NNG_TLS_ENGINE_INIT(void);
1474 #else
1475 static int
NNG_TLS_ENGINE_INIT(void)1476 NNG_TLS_ENGINE_INIT(void)
1477 {
1478 return (0);
1479 }
1480 #endif
1481
1482 #ifdef NNG_TLS_ENGINE_FINI
1483 extern void NNG_TLS_ENGINE_FINI(void);
1484 #else
1485 static void
NNG_TLS_ENGINE_FINI(void)1486 NNG_TLS_ENGINE_FINI(void)
1487 {
1488 }
1489 #endif
1490
1491 int
nni_tls_sys_init(void)1492 nni_tls_sys_init(void)
1493 {
1494 int rv;
1495 nni_mtx_init(&tls_engine_lock);
1496 tls_engine = NULL;
1497
1498 rv = NNG_TLS_ENGINE_INIT();
1499 if (rv != 0) {
1500 nni_mtx_fini(&tls_engine_lock);
1501 return (rv);
1502 }
1503 return (0);
1504 }
1505
1506 void
nni_tls_sys_fini(void)1507 nni_tls_sys_fini(void)
1508 {
1509 nni_reap_drain();
1510 NNG_TLS_ENGINE_FINI();
1511 }
1512
1513 #else // NNG_SUPP_TLS
1514
1515 // Provide stubs for the case where TLS is not enabled.
1516 void
nni_tls_config_fini(nng_tls_config * cfg)1517 nni_tls_config_fini(nng_tls_config *cfg)
1518 {
1519 NNI_ARG_UNUSED(cfg);
1520 }
1521
1522 int
nni_tls_config_init(nng_tls_config ** cpp,enum nng_tls_mode mode)1523 nni_tls_config_init(nng_tls_config **cpp, enum nng_tls_mode mode)
1524 {
1525 NNI_ARG_UNUSED(cpp);
1526 NNI_ARG_UNUSED(mode);
1527 return (NNG_ENOTSUP);
1528 }
1529
1530 void
nni_tls_config_hold(nng_tls_config * cfg)1531 nni_tls_config_hold(nng_tls_config *cfg)
1532 {
1533 NNI_ARG_UNUSED(cfg);
1534 }
1535
1536 int
nng_tls_config_server_name(nng_tls_config * cfg,const char * name)1537 nng_tls_config_server_name(nng_tls_config *cfg, const char *name)
1538 {
1539 NNI_ARG_UNUSED(cfg);
1540 NNI_ARG_UNUSED(name);
1541 return (NNG_ENOTSUP);
1542 }
1543
1544 int
nng_tls_config_auth_mode(nng_tls_config * cfg,nng_tls_auth_mode mode)1545 nng_tls_config_auth_mode(nng_tls_config *cfg, nng_tls_auth_mode mode)
1546 {
1547 NNI_ARG_UNUSED(cfg);
1548 NNI_ARG_UNUSED(mode);
1549 return (NNG_ENOTSUP);
1550 }
1551
1552 int
nng_tls_config_ca_chain(nng_tls_config * cfg,const char * certs,const char * crl)1553 nng_tls_config_ca_chain(
1554 nng_tls_config *cfg, const char *certs, const char *crl)
1555 {
1556 NNI_ARG_UNUSED(cfg);
1557 NNI_ARG_UNUSED(certs);
1558 NNI_ARG_UNUSED(crl);
1559 return (NNG_ENOTSUP);
1560 }
1561
1562 int
nng_tls_config_own_cert(nng_tls_config * cfg,const char * cert,const char * key,const char * pass)1563 nng_tls_config_own_cert(
1564 nng_tls_config *cfg, const char *cert, const char *key, const char *pass)
1565 {
1566 NNI_ARG_UNUSED(cfg);
1567 NNI_ARG_UNUSED(cert);
1568 NNI_ARG_UNUSED(key);
1569 NNI_ARG_UNUSED(pass);
1570 return (NNG_ENOTSUP);
1571 }
1572
1573 int
nng_tls_config_ca_file(nng_tls_config * cfg,const char * path)1574 nng_tls_config_ca_file(nng_tls_config *cfg, const char *path)
1575 {
1576 NNI_ARG_UNUSED(cfg);
1577 NNI_ARG_UNUSED(path);
1578 return (NNG_ENOTSUP);
1579 }
1580
1581 int
nng_tls_config_cert_key_file(nng_tls_config * cfg,const char * path,const char * pass)1582 nng_tls_config_cert_key_file(
1583 nng_tls_config *cfg, const char *path, const char *pass)
1584 {
1585 NNI_ARG_UNUSED(cfg);
1586 NNI_ARG_UNUSED(path);
1587 NNI_ARG_UNUSED(pass);
1588 return (NNG_ENOTSUP);
1589 }
1590
1591 int
nng_tls_config_key(nng_tls_config * cfg,const uint8_t * key,size_t size)1592 nng_tls_config_key(nng_tls_config *cfg, const uint8_t *key, size_t size)
1593 {
1594 NNI_ARG_UNUSED(cfg);
1595 NNI_ARG_UNUSED(key);
1596 NNI_ARG_UNUSED(size);
1597 return (NNG_ENOTSUP);
1598 }
1599
1600 int
nng_tls_config_pass(nng_tls_config * cfg,const char * pass)1601 nng_tls_config_pass(nng_tls_config *cfg, const char *pass)
1602 {
1603 NNI_ARG_UNUSED(cfg);
1604 NNI_ARG_UNUSED(pass);
1605 return (NNG_ENOTSUP);
1606 }
1607
1608 int
nng_tls_config_alloc(nng_tls_config ** cfgp,nng_tls_mode mode)1609 nng_tls_config_alloc(nng_tls_config **cfgp, nng_tls_mode mode)
1610 {
1611
1612 NNI_ARG_UNUSED(cfgp);
1613 NNI_ARG_UNUSED(mode);
1614 return (NNG_ENOTSUP);
1615 }
1616
1617 void
nng_tls_config_free(nng_tls_config * cfg)1618 nng_tls_config_free(nng_tls_config *cfg)
1619 {
1620 NNI_ARG_UNUSED(cfg);
1621 }
1622
1623 int
nng_tls_config_version(nng_tls_config * cfg,nng_tls_version min_ver,nng_tls_version max_ver)1624 nng_tls_config_version(
1625 nng_tls_config *cfg, nng_tls_version min_ver, nng_tls_version max_ver)
1626 {
1627 NNI_ARG_UNUSED(cfg);
1628 NNI_ARG_UNUSED(min_ver);
1629 NNI_ARG_UNUSED(max_ver);
1630 return (NNG_ENOTSUP);
1631 }
1632
1633 int
nni_tls_dialer_alloc(nng_stream_dialer ** dp,const nng_url * url)1634 nni_tls_dialer_alloc(nng_stream_dialer **dp, const nng_url *url)
1635 {
1636 NNI_ARG_UNUSED(dp);
1637 NNI_ARG_UNUSED(url);
1638 return (NNG_ENOTSUP);
1639 }
1640
1641 int
nni_tls_listener_alloc(nng_stream_listener ** lp,const nng_url * url)1642 nni_tls_listener_alloc(nng_stream_listener **lp, const nng_url *url)
1643 {
1644 NNI_ARG_UNUSED(lp);
1645 NNI_ARG_UNUSED(url);
1646 return (NNG_ENOTSUP);
1647 }
1648
1649 int
nni_tls_checkopt(const char * nm,const void * buf,size_t sz,nni_type t)1650 nni_tls_checkopt(const char *nm, const void *buf, size_t sz, nni_type t)
1651 {
1652 NNI_ARG_UNUSED(nm);
1653 NNI_ARG_UNUSED(buf);
1654 NNI_ARG_UNUSED(sz);
1655 NNI_ARG_UNUSED(t);
1656 return (NNG_ENOTSUP);
1657 }
1658
1659 const char *
nng_tls_engine_name(void)1660 nng_tls_engine_name(void)
1661 {
1662 return ("none");
1663 }
1664
1665 const char *
nng_tls_engine_description(void)1666 nng_tls_engine_description(void)
1667 {
1668 return ("");
1669 }
1670
1671 bool
nng_tls_engine_fips_mode(void)1672 nng_tls_engine_fips_mode(void)
1673 {
1674 return (false);
1675 }
1676
1677 int
nng_tls_engine_register(const nng_tls_engine * engine)1678 nng_tls_engine_register(const nng_tls_engine *engine)
1679 {
1680 NNI_ARG_UNUSED(engine);
1681 return (NNG_ENOTSUP);
1682 }
1683
1684 int
nni_tls_sys_init(void)1685 nni_tls_sys_init(void)
1686 {
1687 return (0);
1688 }
1689
1690 void
nni_tls_sys_fini(void)1691 nni_tls_sys_fini(void)
1692 {
1693 }
1694
1695 #endif // !NNG_SUPP_TLS