2 * Copyright (c) 2011 The FreeBSD Foundation
5 * This software was developed by Pawel Jakub Dawidek under sponsorship from
6 * the FreeBSD Foundation.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * $P4: //depot/projects/trustedbsd/openbsm/bin/auditdistd/proto_tls.c#2 $
32 #include <config/config.h>
34 #include <sys/param.h> /* MAXHOSTNAMELEN */
35 #include <sys/socket.h>
37 #include <arpa/inet.h>
39 #include <netinet/in.h>
40 #include <netinet/tcp.h>
52 #include <openssl/err.h>
53 #include <openssl/ssl.h>
55 #include <compat/compat.h>
56 #ifndef HAVE_CLOSEFROM
57 #include <compat/closefrom.h>
60 #include <compat/strlcpy.h>
64 #include "proto_impl.h"
68 #define TLS_CTX_MAGIC 0x715c7
71 struct proto_conn *tls_sock;
72 struct proto_conn *tls_tcp;
76 #define TLS_SIDE_CLIENT 0
77 #define TLS_SIDE_SERVER_LISTEN 1
78 #define TLS_SIDE_SERVER_WORK 2
82 #define TLS_DEFAULT_TIMEOUT 30
84 static int tls_connect_wait(void *ctx, int timeout);
85 static void tls_close(void *ctx);
92 flags = fcntl(fd, F_GETFL);
94 pjdlog_exit(EX_TEMPFAIL, "fcntl(F_GETFL) failed");
96 if (fcntl(fd, F_SETFL, flags) == -1)
97 pjdlog_exit(EX_TEMPFAIL, "fcntl(F_SETFL) failed");
105 flags = fcntl(fd, F_GETFL);
107 pjdlog_exit(EX_TEMPFAIL, "fcntl(F_GETFL) failed");
109 if (fcntl(fd, F_SETFL, flags) == -1)
110 pjdlog_exit(EX_TEMPFAIL, "fcntl(F_SETFL) failed");
114 wait_for_fd(int fd, int timeout)
129 ret = select(fd + 1, NULL, &fdset, NULL,
130 timeout == -1 ? NULL : &tv);
134 } else if (ret == -1) {
140 PJDLOG_ASSERT(ret > 0);
141 PJDLOG_ASSERT(FD_ISSET(fd, &fdset));
153 while ((error = ERR_get_error()) != 0)
154 pjdlog_error("SSL error: %s", ERR_error_string(error, NULL));
158 ssl_check_error(SSL *ssl, int ret)
162 error = SSL_get_error(ssl, ret);
167 case SSL_ERROR_WANT_READ:
168 pjdlog_debug(2, "SSL_ERROR_WANT_READ");
170 case SSL_ERROR_WANT_WRITE:
171 pjdlog_debug(2, "SSL_ERROR_WANT_WRITE");
173 case SSL_ERROR_ZERO_RETURN:
174 pjdlog_exitx(EX_OK, "Connection closed.");
175 case SSL_ERROR_SYSCALL:
177 pjdlog_exitx(EX_TEMPFAIL, "SSL I/O error.");
180 pjdlog_exitx(EX_TEMPFAIL, "SSL protocol error.");
183 pjdlog_exitx(EX_TEMPFAIL, "Unknown SSL error (%d).", error);
188 tcp_recv_ssl_send(int recvfd, SSL *sendssl)
190 static unsigned char buf[65536];
194 sendfd = SSL_get_fd(sendssl);
195 PJDLOG_ASSERT(sendfd >= 0);
196 pjdlog_debug(2, "%s: start %d -> %d", __func__, recvfd, sendfd);
198 tcpdone = recv(recvfd, buf, sizeof(buf), 0);
199 pjdlog_debug(2, "%s: recv() returned %zd", __func__, tcpdone);
201 pjdlog_debug(1, "Connection terminated.");
203 } else if (tcpdone == -1) {
206 else if (errno == EAGAIN)
208 pjdlog_exit(EX_TEMPFAIL, "recv() failed");
211 ssldone = SSL_write(sendssl, buf, (int)tcpdone);
212 pjdlog_debug(2, "%s: send() returned %d", __func__,
214 if (ssl_check_error(sendssl, ssldone) == -1) {
215 (void)wait_for_fd(sendfd, -1);
218 PJDLOG_ASSERT(ssldone == tcpdone);
222 pjdlog_debug(2, "%s: done %d -> %d", __func__, recvfd, sendfd);
226 ssl_recv_tcp_send(SSL *recvssl, int sendfd)
228 static unsigned char buf[65536];
234 recvfd = SSL_get_fd(recvssl);
235 PJDLOG_ASSERT(recvfd >= 0);
236 pjdlog_debug(2, "%s: start %d -> %d", __func__, recvfd, sendfd);
238 ssldone = SSL_read(recvssl, buf, sizeof(buf));
239 pjdlog_debug(2, "%s: SSL_read() returned %d", __func__,
241 if (ssl_check_error(recvssl, ssldone) == -1)
243 todo = (size_t)ssldone;
246 tcpdone = send(sendfd, ptr, todo, MSG_NOSIGNAL);
247 pjdlog_debug(2, "%s: send() returned %zd", __func__,
250 pjdlog_debug(1, "Connection terminated.");
252 } else if (tcpdone == -1) {
253 if (errno == EINTR || errno == ENOBUFS)
255 if (errno == EAGAIN) {
256 (void)wait_for_fd(sendfd, -1);
259 pjdlog_exit(EX_TEMPFAIL, "send() failed");
265 pjdlog_debug(2, "%s: done %d -> %d", __func__, recvfd, sendfd);
269 tls_loop(int sockfd, SSL *tcpssl)
274 tcpfd = SSL_get_fd(tcpssl);
275 PJDLOG_ASSERT(tcpfd >= 0);
279 FD_SET(sockfd, &fds);
281 maxfd = MAX(sockfd, tcpfd);
283 PJDLOG_ASSERT(maxfd + 1 <= (int)FD_SETSIZE);
284 if (select(maxfd + 1, &fds, NULL, NULL, NULL) == -1) {
287 pjdlog_exit(EX_TEMPFAIL, "select() failed");
289 if (FD_ISSET(sockfd, &fds))
290 tcp_recv_ssl_send(sockfd, tcpssl);
291 if (FD_ISSET(tcpfd, &fds))
292 ssl_recv_tcp_send(tcpssl, sockfd);
297 tls_certificate_verify(SSL *ssl, const char *fingerprint)
299 unsigned char md[EVP_MAX_MD_SIZE];
300 char mdstr[sizeof("SHA256=") - 1 + EVP_MAX_MD_SIZE * 3];
302 unsigned int i, mdsize;
305 if (fingerprint[0] == '\0') {
306 pjdlog_debug(1, "No fingerprint verification requested.");
310 cert = SSL_get_peer_certificate(ssl);
312 pjdlog_exitx(EX_TEMPFAIL, "No peer certificate received.");
314 if (X509_digest(cert, EVP_sha256(), md, &mdsize) != 1)
315 pjdlog_exitx(EX_TEMPFAIL, "X509_digest() failed.");
316 PJDLOG_ASSERT(mdsize <= EVP_MAX_MD_SIZE);
320 (void)strlcpy(mdstr, "SHA256=", sizeof(mdstr));
321 mdstrp = mdstr + strlen(mdstr);
322 for (i = 0; i < mdsize; i++) {
323 PJDLOG_VERIFY(mdstrp + 3 <= mdstr + sizeof(mdstr));
324 (void)sprintf(mdstrp, "%02hhX:", md[i]);
327 /* Clear last colon. */
329 if (strcasecmp(mdstr, fingerprint) != 0) {
330 pjdlog_exitx(EX_NOPERM,
331 "Finger print doesn't match. Received \"%s\", expected \"%s\"",
337 tls_exec_client(const char *user, int startfd, const char *srcaddr,
338 const char *dstaddr, const char *fingerprint, const char *defport,
339 int timeout, int debuglevel)
341 struct proto_conn *tcp;
349 pjdlog_debug_set(debuglevel);
350 pjdlog_prefix_set("[TLS sandbox] (client) ");
351 #ifdef HAVE_SETPROCTITLE
352 setproctitle("[TLS sandbox] (client) ");
354 proto_set("tcp:port", defport);
358 /* Change tls:// to tcp://. */
359 if (srcaddr == NULL) {
362 saddr = strdup(srcaddr);
364 pjdlog_exitx(EX_TEMPFAIL, "Unable to allocate memory.");
365 bcopy("tcp://", saddr, 6);
367 daddr = strdup(dstaddr);
369 pjdlog_exitx(EX_TEMPFAIL, "Unable to allocate memory.");
370 bcopy("tcp://", daddr, 6);
372 /* Establish TCP connection. */
373 if (proto_connect(saddr, daddr, timeout, &tcp) == -1)
376 SSL_load_error_strings();
380 * TODO: On FreeBSD we could move this below sandbox() once libc and
381 * libcrypto use sysctl kern.arandom to obtain random data
382 * instead of /dev/urandom and friends.
384 sslctx = SSL_CTX_new(TLSv1_client_method());
386 pjdlog_exitx(EX_TEMPFAIL, "SSL_CTX_new() failed.");
388 if (sandbox(user, true, "proto_tls client: %s", dstaddr) != 0)
389 pjdlog_exitx(EX_CONFIG, "Unable to sandbox TLS client.");
390 pjdlog_debug(1, "Privileges successfully dropped.");
392 SSL_CTX_set_options(sslctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
396 //SSL_CTX_load_verify_locations(sslctx, cacerts_file, NULL);
398 ssl = SSL_new(sslctx);
400 pjdlog_exitx(EX_TEMPFAIL, "SSL_new() failed.");
402 tcpfd = proto_descriptor(tcp);
406 if (SSL_set_fd(ssl, tcpfd) != 1)
407 pjdlog_exitx(EX_TEMPFAIL, "SSL_set_fd() failed.");
409 ret = SSL_connect(ssl);
410 ssl_check_error(ssl, (int)ret);
415 tls_certificate_verify(ssl, fingerprint);
418 * The following byte is send to make proto_connect_wait() to work.
422 switch (send(sockfd, &connected, sizeof(connected), 0)) {
424 if (errno == EINTR || errno == ENOBUFS)
426 if (errno == EAGAIN) {
427 (void)wait_for_fd(sockfd, -1);
430 pjdlog_exit(EX_TEMPFAIL, "send() failed");
432 pjdlog_debug(1, "Connection terminated.");
440 tls_loop(sockfd, ssl);
444 tls_call_exec_client(struct proto_conn *sock, const char *srcaddr,
445 const char *dstaddr, int timeout)
447 char *timeoutstr, *startfdstr, *debugstr;
450 /* Declare that we are receiver. */
451 proto_recv(sock, NULL, 0);
453 if (pjdlog_mode_get() == PJDLOG_MODE_STD)
455 else /* if (pjdlog_mode_get() == PJDLOG_MODE_SYSLOG) */
458 if (proto_descriptor(sock) != startfd) {
459 /* Move socketpair descriptor to descriptor number startfd. */
460 if (dup2(proto_descriptor(sock), startfd) == -1)
461 pjdlog_exit(EX_OSERR, "dup2() failed");
465 * The FD_CLOEXEC is cleared by dup2(2), so when we not
466 * call it, we have to clear it by hand in case it is set.
468 if (fcntl(startfd, F_SETFD, 0) == -1)
469 pjdlog_exit(EX_OSERR, "fcntl() failed");
472 closefrom(startfd + 1);
474 if (asprintf(&startfdstr, "%d", startfd) == -1)
475 pjdlog_exit(EX_TEMPFAIL, "asprintf() failed");
477 timeout = TLS_DEFAULT_TIMEOUT;
478 if (asprintf(&timeoutstr, "%d", timeout) == -1)
479 pjdlog_exit(EX_TEMPFAIL, "asprintf() failed");
480 if (asprintf(&debugstr, "%d", pjdlog_debug_get()) == -1)
481 pjdlog_exit(EX_TEMPFAIL, "asprintf() failed");
483 execl(proto_get("execpath"), proto_get("execpath"), "proto", "tls",
484 proto_get("user"), "client", startfdstr,
485 srcaddr == NULL ? "" : srcaddr, dstaddr,
486 proto_get("tls:fingerprint"), proto_get("tcp:port"), timeoutstr,
488 pjdlog_exit(EX_SOFTWARE, "execl() failed");
492 tls_connect(const char *srcaddr, const char *dstaddr, int timeout, void **ctxp)
494 struct tls_ctx *tlsctx;
495 struct proto_conn *sock;
499 PJDLOG_ASSERT(srcaddr == NULL || srcaddr[0] != '\0');
500 PJDLOG_ASSERT(dstaddr != NULL);
501 PJDLOG_ASSERT(timeout >= -1);
502 PJDLOG_ASSERT(ctxp != NULL);
504 if (strncmp(dstaddr, "tls://", 6) != 0)
506 if (srcaddr != NULL && strncmp(srcaddr, "tls://", 6) != 0)
509 if (proto_connect(NULL, "socketpair://", -1, &sock) == -1)
514 * We use rfork() with the following flags to disable SIGCHLD
515 * delivery upon the sandbox process exit.
517 pid = rfork(RFFDG | RFPROC | RFTSIGZMB | RFTSIGFLAGS(0));
520 * We don't use rfork() to be able to log information about sandbox
533 pjdlog_prefix_set("[TLS sandbox] (client) ");
534 #ifdef HAVE_SETPROCTITLE
535 setproctitle("[TLS sandbox] (client) ");
537 tls_call_exec_client(sock, srcaddr, dstaddr, timeout);
541 tlsctx = calloc(1, sizeof(*tlsctx));
542 if (tlsctx == NULL) {
545 (void)kill(pid, SIGKILL);
548 proto_send(sock, NULL, 0);
549 tlsctx->tls_sock = sock;
550 tlsctx->tls_tcp = NULL;
551 tlsctx->tls_side = TLS_SIDE_CLIENT;
552 tlsctx->tls_wait_called = false;
553 tlsctx->tls_magic = TLS_CTX_MAGIC;
555 error = tls_connect_wait(tlsctx, timeout);
557 (void)kill(pid, SIGKILL);
568 tls_connect_wait(void *ctx, int timeout)
570 struct tls_ctx *tlsctx = ctx;
574 PJDLOG_ASSERT(tlsctx != NULL);
575 PJDLOG_ASSERT(tlsctx->tls_magic == TLS_CTX_MAGIC);
576 PJDLOG_ASSERT(tlsctx->tls_side == TLS_SIDE_CLIENT);
577 PJDLOG_ASSERT(tlsctx->tls_sock != NULL);
578 PJDLOG_ASSERT(!tlsctx->tls_wait_called);
579 PJDLOG_ASSERT(timeout >= 0);
581 sockfd = proto_descriptor(tlsctx->tls_sock);
582 error = wait_for_fd(sockfd, timeout);
587 switch (recv(sockfd, &connected, sizeof(connected),
590 if (errno == EINTR || errno == ENOBUFS)
595 pjdlog_debug(1, "Connection terminated.");
599 tlsctx->tls_wait_called = true;
609 tls_server(const char *lstaddr, void **ctxp)
611 struct proto_conn *tcp;
612 struct tls_ctx *tlsctx;
616 if (strncmp(lstaddr, "tls://", 6) != 0)
619 tlsctx = malloc(sizeof(*tlsctx));
620 if (tlsctx == NULL) {
621 pjdlog_warning("Unable to allocate memory.");
625 laddr = strdup(lstaddr);
628 pjdlog_warning("Unable to allocate memory.");
631 bcopy("tcp://", laddr, 6);
633 if (proto_server(laddr, &tcp) == -1) {
641 tlsctx->tls_sock = NULL;
642 tlsctx->tls_tcp = tcp;
643 tlsctx->tls_side = TLS_SIDE_SERVER_LISTEN;
644 tlsctx->tls_wait_called = true;
645 tlsctx->tls_magic = TLS_CTX_MAGIC;
652 tls_exec_server(const char *user, int startfd, const char *privkey,
653 const char *cert, int debuglevel)
657 int sockfd, tcpfd, ret;
659 pjdlog_debug_set(debuglevel);
660 pjdlog_prefix_set("[TLS sandbox] (server) ");
661 #ifdef HAVE_SETPROCTITLE
662 setproctitle("[TLS sandbox] (server) ");
668 SSL_load_error_strings();
671 sslctx = SSL_CTX_new(TLSv1_server_method());
673 pjdlog_exitx(EX_TEMPFAIL, "SSL_CTX_new() failed.");
675 SSL_CTX_set_options(sslctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
677 ssl = SSL_new(sslctx);
679 pjdlog_exitx(EX_TEMPFAIL, "SSL_new() failed.");
681 if (SSL_use_RSAPrivateKey_file(ssl, privkey, SSL_FILETYPE_PEM) != 1) {
683 pjdlog_exitx(EX_CONFIG,
684 "SSL_use_RSAPrivateKey_file(%s) failed.", privkey);
687 if (SSL_use_certificate_file(ssl, cert, SSL_FILETYPE_PEM) != 1) {
689 pjdlog_exitx(EX_CONFIG, "SSL_use_certificate_file(%s) failed.",
693 if (sandbox(user, true, "proto_tls server") != 0)
694 pjdlog_exitx(EX_CONFIG, "Unable to sandbox TLS server.");
695 pjdlog_debug(1, "Privileges successfully dropped.");
700 if (SSL_set_fd(ssl, tcpfd) != 1)
701 pjdlog_exitx(EX_TEMPFAIL, "SSL_set_fd() failed.");
703 ret = SSL_accept(ssl);
704 ssl_check_error(ssl, ret);
706 tls_loop(sockfd, ssl);
710 tls_call_exec_server(struct proto_conn *sock, struct proto_conn *tcp)
712 int startfd, sockfd, tcpfd, safefd;
713 char *startfdstr, *debugstr;
715 if (pjdlog_mode_get() == PJDLOG_MODE_STD)
717 else /* if (pjdlog_mode_get() == PJDLOG_MODE_SYSLOG) */
720 /* Declare that we are receiver. */
721 proto_send(sock, NULL, 0);
723 sockfd = proto_descriptor(sock);
724 tcpfd = proto_descriptor(tcp);
726 safefd = MAX(sockfd, tcpfd);
727 safefd = MAX(safefd, startfd);
730 /* Move sockfd and tcpfd to safe numbers first. */
731 if (dup2(sockfd, safefd) == -1)
732 pjdlog_exit(EX_OSERR, "dup2() failed");
735 if (dup2(tcpfd, safefd + 1) == -1)
736 pjdlog_exit(EX_OSERR, "dup2() failed");
740 /* Move socketpair descriptor to descriptor number startfd. */
741 if (dup2(sockfd, startfd) == -1)
742 pjdlog_exit(EX_OSERR, "dup2() failed");
744 /* Move tcp descriptor to descriptor number startfd + 1. */
745 if (dup2(tcpfd, startfd + 1) == -1)
746 pjdlog_exit(EX_OSERR, "dup2() failed");
749 closefrom(startfd + 2);
752 * Even if FD_CLOEXEC was set on descriptors before dup2(), it should
753 * have been cleared on dup2(), but better be safe than sorry.
755 if (fcntl(startfd, F_SETFD, 0) == -1)
756 pjdlog_exit(EX_OSERR, "fcntl() failed");
757 if (fcntl(startfd + 1, F_SETFD, 0) == -1)
758 pjdlog_exit(EX_OSERR, "fcntl() failed");
760 if (asprintf(&startfdstr, "%d", startfd) == -1)
761 pjdlog_exit(EX_TEMPFAIL, "asprintf() failed");
762 if (asprintf(&debugstr, "%d", pjdlog_debug_get()) == -1)
763 pjdlog_exit(EX_TEMPFAIL, "asprintf() failed");
765 execl(proto_get("execpath"), proto_get("execpath"), "proto", "tls",
766 proto_get("user"), "server", startfdstr, proto_get("tls:keyfile"),
767 proto_get("tls:certfile"), debugstr, NULL);
768 pjdlog_exit(EX_SOFTWARE, "execl() failed");
772 tls_accept(void *ctx, void **newctxp)
774 struct tls_ctx *tlsctx = ctx;
775 struct tls_ctx *newtlsctx;
776 struct proto_conn *sock, *tcp;
780 PJDLOG_ASSERT(tlsctx != NULL);
781 PJDLOG_ASSERT(tlsctx->tls_magic == TLS_CTX_MAGIC);
782 PJDLOG_ASSERT(tlsctx->tls_side == TLS_SIDE_SERVER_LISTEN);
784 if (proto_connect(NULL, "socketpair://", -1, &sock) == -1)
787 /* Accept TCP connection. */
788 if (proto_accept(tlsctx->tls_tcp, &tcp) == -1) {
803 pjdlog_prefix_set("[TLS sandbox] (server) ");
804 #ifdef HAVE_SETPROCTITLE
805 setproctitle("[TLS sandbox] (server) ");
807 /* Close listen socket. */
808 proto_close(tlsctx->tls_tcp);
809 tls_call_exec_server(sock, tcp);
811 PJDLOG_ABORT("Unreachable.");
814 newtlsctx = calloc(1, sizeof(*tlsctx));
815 if (newtlsctx == NULL) {
819 (void)kill(pid, SIGKILL);
822 proto_local_address(tcp, newtlsctx->tls_laddr,
823 sizeof(newtlsctx->tls_laddr));
824 PJDLOG_ASSERT(strncmp(newtlsctx->tls_laddr, "tcp://", 6) == 0);
825 bcopy("tls://", newtlsctx->tls_laddr, 6);
826 *strrchr(newtlsctx->tls_laddr, ':') = '\0';
827 proto_remote_address(tcp, newtlsctx->tls_raddr,
828 sizeof(newtlsctx->tls_raddr));
829 PJDLOG_ASSERT(strncmp(newtlsctx->tls_raddr, "tcp://", 6) == 0);
830 bcopy("tls://", newtlsctx->tls_raddr, 6);
831 *strrchr(newtlsctx->tls_raddr, ':') = '\0';
833 proto_recv(sock, NULL, 0);
834 newtlsctx->tls_sock = sock;
835 newtlsctx->tls_tcp = NULL;
836 newtlsctx->tls_wait_called = true;
837 newtlsctx->tls_side = TLS_SIDE_SERVER_WORK;
838 newtlsctx->tls_magic = TLS_CTX_MAGIC;
839 *newctxp = newtlsctx;
845 tls_wrap(int fd, bool client, void **ctxp)
847 struct tls_ctx *tlsctx;
848 struct proto_conn *sock;
851 tlsctx = calloc(1, sizeof(*tlsctx));
855 if (proto_wrap("socketpair", client, fd, &sock) == -1) {
861 tlsctx->tls_sock = sock;
862 tlsctx->tls_tcp = NULL;
863 tlsctx->tls_wait_called = (client ? false : true);
864 tlsctx->tls_side = (client ? TLS_SIDE_CLIENT : TLS_SIDE_SERVER_WORK);
865 tlsctx->tls_magic = TLS_CTX_MAGIC;
872 tls_send(void *ctx, const unsigned char *data, size_t size, int fd)
874 struct tls_ctx *tlsctx = ctx;
876 PJDLOG_ASSERT(tlsctx != NULL);
877 PJDLOG_ASSERT(tlsctx->tls_magic == TLS_CTX_MAGIC);
878 PJDLOG_ASSERT(tlsctx->tls_side == TLS_SIDE_CLIENT ||
879 tlsctx->tls_side == TLS_SIDE_SERVER_WORK);
880 PJDLOG_ASSERT(tlsctx->tls_sock != NULL);
881 PJDLOG_ASSERT(tlsctx->tls_wait_called);
882 PJDLOG_ASSERT(fd == -1);
884 if (proto_send(tlsctx->tls_sock, data, size) == -1)
891 tls_recv(void *ctx, unsigned char *data, size_t size, int *fdp)
893 struct tls_ctx *tlsctx = ctx;
895 PJDLOG_ASSERT(tlsctx != NULL);
896 PJDLOG_ASSERT(tlsctx->tls_magic == TLS_CTX_MAGIC);
897 PJDLOG_ASSERT(tlsctx->tls_side == TLS_SIDE_CLIENT ||
898 tlsctx->tls_side == TLS_SIDE_SERVER_WORK);
899 PJDLOG_ASSERT(tlsctx->tls_sock != NULL);
900 PJDLOG_ASSERT(tlsctx->tls_wait_called);
901 PJDLOG_ASSERT(fdp == NULL);
903 if (proto_recv(tlsctx->tls_sock, data, size) == -1)
910 tls_descriptor(const void *ctx)
912 const struct tls_ctx *tlsctx = ctx;
914 PJDLOG_ASSERT(tlsctx != NULL);
915 PJDLOG_ASSERT(tlsctx->tls_magic == TLS_CTX_MAGIC);
917 switch (tlsctx->tls_side) {
918 case TLS_SIDE_CLIENT:
919 case TLS_SIDE_SERVER_WORK:
920 PJDLOG_ASSERT(tlsctx->tls_sock != NULL);
922 return (proto_descriptor(tlsctx->tls_sock));
923 case TLS_SIDE_SERVER_LISTEN:
924 PJDLOG_ASSERT(tlsctx->tls_tcp != NULL);
926 return (proto_descriptor(tlsctx->tls_tcp));
928 PJDLOG_ABORT("Invalid side (%d).", tlsctx->tls_side);
933 tcp_address_match(const void *ctx, const char *addr)
935 const struct tls_ctx *tlsctx = ctx;
937 PJDLOG_ASSERT(tlsctx != NULL);
938 PJDLOG_ASSERT(tlsctx->tls_magic == TLS_CTX_MAGIC);
940 return (strcmp(tlsctx->tls_raddr, addr) == 0);
944 tls_local_address(const void *ctx, char *addr, size_t size)
946 const struct tls_ctx *tlsctx = ctx;
948 PJDLOG_ASSERT(tlsctx != NULL);
949 PJDLOG_ASSERT(tlsctx->tls_magic == TLS_CTX_MAGIC);
950 PJDLOG_ASSERT(tlsctx->tls_wait_called);
952 switch (tlsctx->tls_side) {
953 case TLS_SIDE_CLIENT:
954 PJDLOG_ASSERT(tlsctx->tls_sock != NULL);
956 PJDLOG_VERIFY(strlcpy(addr, "tls://N/A", size) < size);
958 case TLS_SIDE_SERVER_WORK:
959 PJDLOG_ASSERT(tlsctx->tls_sock != NULL);
961 PJDLOG_VERIFY(strlcpy(addr, tlsctx->tls_laddr, size) < size);
963 case TLS_SIDE_SERVER_LISTEN:
964 PJDLOG_ASSERT(tlsctx->tls_tcp != NULL);
966 proto_local_address(tlsctx->tls_tcp, addr, size);
967 PJDLOG_ASSERT(strncmp(addr, "tcp://", 6) == 0);
968 /* Replace tcp:// prefix with tls:// */
969 bcopy("tls://", addr, 6);
972 PJDLOG_ABORT("Invalid side (%d).", tlsctx->tls_side);
977 tls_remote_address(const void *ctx, char *addr, size_t size)
979 const struct tls_ctx *tlsctx = ctx;
981 PJDLOG_ASSERT(tlsctx != NULL);
982 PJDLOG_ASSERT(tlsctx->tls_magic == TLS_CTX_MAGIC);
983 PJDLOG_ASSERT(tlsctx->tls_wait_called);
985 switch (tlsctx->tls_side) {
986 case TLS_SIDE_CLIENT:
987 PJDLOG_ASSERT(tlsctx->tls_sock != NULL);
989 PJDLOG_VERIFY(strlcpy(addr, "tls://N/A", size) < size);
991 case TLS_SIDE_SERVER_WORK:
992 PJDLOG_ASSERT(tlsctx->tls_sock != NULL);
994 PJDLOG_VERIFY(strlcpy(addr, tlsctx->tls_raddr, size) < size);
996 case TLS_SIDE_SERVER_LISTEN:
997 PJDLOG_ASSERT(tlsctx->tls_tcp != NULL);
999 proto_remote_address(tlsctx->tls_tcp, addr, size);
1000 PJDLOG_ASSERT(strncmp(addr, "tcp://", 6) == 0);
1001 /* Replace tcp:// prefix with tls:// */
1002 bcopy("tls://", addr, 6);
1005 PJDLOG_ABORT("Invalid side (%d).", tlsctx->tls_side);
1010 tls_close(void *ctx)
1012 struct tls_ctx *tlsctx = ctx;
1014 PJDLOG_ASSERT(tlsctx != NULL);
1015 PJDLOG_ASSERT(tlsctx->tls_magic == TLS_CTX_MAGIC);
1017 if (tlsctx->tls_sock != NULL) {
1018 proto_close(tlsctx->tls_sock);
1019 tlsctx->tls_sock = NULL;
1021 if (tlsctx->tls_tcp != NULL) {
1022 proto_close(tlsctx->tls_tcp);
1023 tlsctx->tls_tcp = NULL;
1025 tlsctx->tls_side = 0;
1026 tlsctx->tls_magic = 0;
1031 tls_exec(int argc, char *argv[])
1034 PJDLOG_ASSERT(argc > 3);
1035 PJDLOG_ASSERT(strcmp(argv[0], "tls") == 0);
1037 pjdlog_init(atoi(argv[3]) == 0 ? PJDLOG_MODE_SYSLOG : PJDLOG_MODE_STD);
1039 if (strcmp(argv[2], "client") == 0) {
1042 tls_exec_client(argv[1], atoi(argv[3]),
1043 argv[4][0] == '\0' ? NULL : argv[4], argv[5], argv[6],
1044 argv[7], atoi(argv[8]), atoi(argv[9]));
1045 } else if (strcmp(argv[2], "server") == 0) {
1048 tls_exec_server(argv[1], atoi(argv[3]), argv[4], argv[5],
1054 static struct proto tls_proto = {
1056 .prt_connect = tls_connect,
1057 .prt_connect_wait = tls_connect_wait,
1058 .prt_server = tls_server,
1059 .prt_accept = tls_accept,
1060 .prt_wrap = tls_wrap,
1061 .prt_send = tls_send,
1062 .prt_recv = tls_recv,
1063 .prt_descriptor = tls_descriptor,
1064 .prt_address_match = tcp_address_match,
1065 .prt_local_address = tls_local_address,
1066 .prt_remote_address = tls_remote_address,
1067 .prt_close = tls_close,
1068 .prt_exec = tls_exec
1071 static __constructor void
1075 proto_register(&tls_proto, false);