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
30 #include <config/config.h>
32 #include <sys/param.h> /* MAXHOSTNAMELEN */
33 #include <sys/socket.h>
35 #include <arpa/inet.h>
37 #include <netinet/in.h>
38 #include <netinet/tcp.h>
50 #include <openssl/err.h>
51 #include <openssl/ssl.h>
53 #include <compat/compat.h>
54 #ifndef HAVE_CLOSEFROM
55 #include <compat/closefrom.h>
58 #include <compat/strlcpy.h>
62 #include "proto_impl.h"
66 #define TLS_CTX_MAGIC 0x715c7
69 struct proto_conn *tls_sock;
70 struct proto_conn *tls_tcp;
74 #define TLS_SIDE_CLIENT 0
75 #define TLS_SIDE_SERVER_LISTEN 1
76 #define TLS_SIDE_SERVER_WORK 2
80 #define TLS_DEFAULT_TIMEOUT 30
82 static int tls_connect_wait(void *ctx, int timeout);
83 static void tls_close(void *ctx);
90 flags = fcntl(fd, F_GETFL);
92 pjdlog_exit(EX_TEMPFAIL, "fcntl(F_GETFL) failed");
94 if (fcntl(fd, F_SETFL, flags) == -1)
95 pjdlog_exit(EX_TEMPFAIL, "fcntl(F_SETFL) failed");
103 flags = fcntl(fd, F_GETFL);
105 pjdlog_exit(EX_TEMPFAIL, "fcntl(F_GETFL) failed");
107 if (fcntl(fd, F_SETFL, flags) == -1)
108 pjdlog_exit(EX_TEMPFAIL, "fcntl(F_SETFL) failed");
112 wait_for_fd(int fd, int timeout)
127 ret = select(fd + 1, NULL, &fdset, NULL,
128 timeout == -1 ? NULL : &tv);
132 } else if (ret == -1) {
138 PJDLOG_ASSERT(ret > 0);
139 PJDLOG_ASSERT(FD_ISSET(fd, &fdset));
151 while ((error = ERR_get_error()) != 0)
152 pjdlog_error("SSL error: %s", ERR_error_string(error, NULL));
156 ssl_check_error(SSL *ssl, int ret)
160 error = SSL_get_error(ssl, ret);
165 case SSL_ERROR_WANT_READ:
166 pjdlog_debug(2, "SSL_ERROR_WANT_READ");
168 case SSL_ERROR_WANT_WRITE:
169 pjdlog_debug(2, "SSL_ERROR_WANT_WRITE");
171 case SSL_ERROR_ZERO_RETURN:
172 pjdlog_exitx(EX_OK, "Connection closed.");
173 case SSL_ERROR_SYSCALL:
175 pjdlog_exitx(EX_TEMPFAIL, "SSL I/O error.");
178 pjdlog_exitx(EX_TEMPFAIL, "SSL protocol error.");
181 pjdlog_exitx(EX_TEMPFAIL, "Unknown SSL error (%d).", error);
186 tcp_recv_ssl_send(int recvfd, SSL *sendssl)
188 static unsigned char buf[65536];
192 sendfd = SSL_get_fd(sendssl);
193 PJDLOG_ASSERT(sendfd >= 0);
194 pjdlog_debug(2, "%s: start %d -> %d", __func__, recvfd, sendfd);
196 tcpdone = recv(recvfd, buf, sizeof(buf), 0);
197 pjdlog_debug(2, "%s: recv() returned %zd", __func__, tcpdone);
199 pjdlog_debug(1, "Connection terminated.");
201 } else if (tcpdone == -1) {
204 else if (errno == EAGAIN)
206 pjdlog_exit(EX_TEMPFAIL, "recv() failed");
209 ssldone = SSL_write(sendssl, buf, (int)tcpdone);
210 pjdlog_debug(2, "%s: send() returned %d", __func__,
212 if (ssl_check_error(sendssl, ssldone) == -1) {
213 (void)wait_for_fd(sendfd, -1);
216 PJDLOG_ASSERT(ssldone == tcpdone);
220 pjdlog_debug(2, "%s: done %d -> %d", __func__, recvfd, sendfd);
224 ssl_recv_tcp_send(SSL *recvssl, int sendfd)
226 static unsigned char buf[65536];
232 recvfd = SSL_get_fd(recvssl);
233 PJDLOG_ASSERT(recvfd >= 0);
234 pjdlog_debug(2, "%s: start %d -> %d", __func__, recvfd, sendfd);
236 ssldone = SSL_read(recvssl, buf, sizeof(buf));
237 pjdlog_debug(2, "%s: SSL_read() returned %d", __func__,
239 if (ssl_check_error(recvssl, ssldone) == -1)
241 todo = (size_t)ssldone;
244 tcpdone = send(sendfd, ptr, todo, MSG_NOSIGNAL);
245 pjdlog_debug(2, "%s: send() returned %zd", __func__,
248 pjdlog_debug(1, "Connection terminated.");
250 } else if (tcpdone == -1) {
251 if (errno == EINTR || errno == ENOBUFS)
253 if (errno == EAGAIN) {
254 (void)wait_for_fd(sendfd, -1);
257 pjdlog_exit(EX_TEMPFAIL, "send() failed");
263 pjdlog_debug(2, "%s: done %d -> %d", __func__, recvfd, sendfd);
267 tls_loop(int sockfd, SSL *tcpssl)
272 tcpfd = SSL_get_fd(tcpssl);
273 PJDLOG_ASSERT(tcpfd >= 0);
277 FD_SET(sockfd, &fds);
279 maxfd = MAX(sockfd, tcpfd);
281 PJDLOG_ASSERT(maxfd + 1 <= (int)FD_SETSIZE);
282 if (select(maxfd + 1, &fds, NULL, NULL, NULL) == -1) {
285 pjdlog_exit(EX_TEMPFAIL, "select() failed");
287 if (FD_ISSET(sockfd, &fds))
288 tcp_recv_ssl_send(sockfd, tcpssl);
289 if (FD_ISSET(tcpfd, &fds))
290 ssl_recv_tcp_send(tcpssl, sockfd);
295 tls_certificate_verify(SSL *ssl, const char *fingerprint)
297 unsigned char md[EVP_MAX_MD_SIZE];
298 char mdstr[sizeof("SHA256=") - 1 + EVP_MAX_MD_SIZE * 3];
300 unsigned int i, mdsize;
303 if (fingerprint[0] == '\0') {
304 pjdlog_debug(1, "No fingerprint verification requested.");
308 cert = SSL_get_peer_certificate(ssl);
310 pjdlog_exitx(EX_TEMPFAIL, "No peer certificate received.");
312 if (X509_digest(cert, EVP_sha256(), md, &mdsize) != 1)
313 pjdlog_exitx(EX_TEMPFAIL, "X509_digest() failed.");
314 PJDLOG_ASSERT(mdsize <= EVP_MAX_MD_SIZE);
318 (void)strlcpy(mdstr, "SHA256=", sizeof(mdstr));
319 mdstrp = mdstr + strlen(mdstr);
320 for (i = 0; i < mdsize; i++) {
321 PJDLOG_VERIFY(mdstrp + 3 <= mdstr + sizeof(mdstr));
322 (void)sprintf(mdstrp, "%02hhX:", md[i]);
325 /* Clear last colon. */
327 if (strcasecmp(mdstr, fingerprint) != 0) {
328 pjdlog_exitx(EX_NOPERM,
329 "Finger print doesn't match. Received \"%s\", expected \"%s\"",
335 tls_exec_client(const char *user, int startfd, const char *srcaddr,
336 const char *dstaddr, const char *fingerprint, const char *defport,
337 int timeout, int debuglevel)
339 struct proto_conn *tcp;
347 pjdlog_debug_set(debuglevel);
348 pjdlog_prefix_set("[TLS sandbox] (client) ");
349 #ifdef HAVE_SETPROCTITLE
350 setproctitle("[TLS sandbox] (client) ");
352 proto_set("tcp:port", defport);
356 /* Change tls:// to tcp://. */
357 if (srcaddr == NULL) {
360 saddr = strdup(srcaddr);
362 pjdlog_exitx(EX_TEMPFAIL, "Unable to allocate memory.");
363 bcopy("tcp://", saddr, 6);
365 daddr = strdup(dstaddr);
367 pjdlog_exitx(EX_TEMPFAIL, "Unable to allocate memory.");
368 bcopy("tcp://", daddr, 6);
370 /* Establish TCP connection. */
371 if (proto_connect(saddr, daddr, timeout, &tcp) == -1)
374 SSL_load_error_strings();
378 * TODO: On FreeBSD we could move this below sandbox() once libc and
379 * libcrypto use sysctl kern.arandom to obtain random data
380 * instead of /dev/urandom and friends.
382 sslctx = SSL_CTX_new(TLSv1_client_method());
384 pjdlog_exitx(EX_TEMPFAIL, "SSL_CTX_new() failed.");
386 if (sandbox(user, true, "proto_tls client: %s", dstaddr) != 0)
387 pjdlog_exitx(EX_CONFIG, "Unable to sandbox TLS client.");
388 pjdlog_debug(1, "Privileges successfully dropped.");
390 SSL_CTX_set_options(sslctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
394 //SSL_CTX_load_verify_locations(sslctx, cacerts_file, NULL);
396 ssl = SSL_new(sslctx);
398 pjdlog_exitx(EX_TEMPFAIL, "SSL_new() failed.");
400 tcpfd = proto_descriptor(tcp);
404 if (SSL_set_fd(ssl, tcpfd) != 1)
405 pjdlog_exitx(EX_TEMPFAIL, "SSL_set_fd() failed.");
407 ret = SSL_connect(ssl);
408 ssl_check_error(ssl, (int)ret);
413 tls_certificate_verify(ssl, fingerprint);
416 * The following byte is send to make proto_connect_wait() to work.
420 switch (send(sockfd, &connected, sizeof(connected), 0)) {
422 if (errno == EINTR || errno == ENOBUFS)
424 if (errno == EAGAIN) {
425 (void)wait_for_fd(sockfd, -1);
428 pjdlog_exit(EX_TEMPFAIL, "send() failed");
430 pjdlog_debug(1, "Connection terminated.");
438 tls_loop(sockfd, ssl);
442 tls_call_exec_client(struct proto_conn *sock, const char *srcaddr,
443 const char *dstaddr, int timeout)
445 char *timeoutstr, *startfdstr, *debugstr;
448 /* Declare that we are receiver. */
449 proto_recv(sock, NULL, 0);
451 if (pjdlog_mode_get() == PJDLOG_MODE_STD)
453 else /* if (pjdlog_mode_get() == PJDLOG_MODE_SYSLOG) */
456 if (proto_descriptor(sock) != startfd) {
457 /* Move socketpair descriptor to descriptor number startfd. */
458 if (dup2(proto_descriptor(sock), startfd) == -1)
459 pjdlog_exit(EX_OSERR, "dup2() failed");
463 * The FD_CLOEXEC is cleared by dup2(2), so when we not
464 * call it, we have to clear it by hand in case it is set.
466 if (fcntl(startfd, F_SETFD, 0) == -1)
467 pjdlog_exit(EX_OSERR, "fcntl() failed");
470 closefrom(startfd + 1);
472 if (asprintf(&startfdstr, "%d", startfd) == -1)
473 pjdlog_exit(EX_TEMPFAIL, "asprintf() failed");
475 timeout = TLS_DEFAULT_TIMEOUT;
476 if (asprintf(&timeoutstr, "%d", timeout) == -1)
477 pjdlog_exit(EX_TEMPFAIL, "asprintf() failed");
478 if (asprintf(&debugstr, "%d", pjdlog_debug_get()) == -1)
479 pjdlog_exit(EX_TEMPFAIL, "asprintf() failed");
481 execl(proto_get("execpath"), proto_get("execpath"), "proto", "tls",
482 proto_get("user"), "client", startfdstr,
483 srcaddr == NULL ? "" : srcaddr, dstaddr,
484 proto_get("tls:fingerprint"), proto_get("tcp:port"), timeoutstr,
486 pjdlog_exit(EX_SOFTWARE, "execl() failed");
490 tls_connect(const char *srcaddr, const char *dstaddr, int timeout, void **ctxp)
492 struct tls_ctx *tlsctx;
493 struct proto_conn *sock;
497 PJDLOG_ASSERT(srcaddr == NULL || srcaddr[0] != '\0');
498 PJDLOG_ASSERT(dstaddr != NULL);
499 PJDLOG_ASSERT(timeout >= -1);
500 PJDLOG_ASSERT(ctxp != NULL);
502 if (strncmp(dstaddr, "tls://", 6) != 0)
504 if (srcaddr != NULL && strncmp(srcaddr, "tls://", 6) != 0)
507 if (proto_connect(NULL, "socketpair://", -1, &sock) == -1)
512 * We use rfork() with the following flags to disable SIGCHLD
513 * delivery upon the sandbox process exit.
515 pid = rfork(RFFDG | RFPROC | RFTSIGZMB | RFTSIGFLAGS(0));
518 * We don't use rfork() to be able to log information about sandbox
531 pjdlog_prefix_set("[TLS sandbox] (client) ");
532 #ifdef HAVE_SETPROCTITLE
533 setproctitle("[TLS sandbox] (client) ");
535 tls_call_exec_client(sock, srcaddr, dstaddr, timeout);
539 tlsctx = calloc(1, sizeof(*tlsctx));
540 if (tlsctx == NULL) {
543 (void)kill(pid, SIGKILL);
546 proto_send(sock, NULL, 0);
547 tlsctx->tls_sock = sock;
548 tlsctx->tls_tcp = NULL;
549 tlsctx->tls_side = TLS_SIDE_CLIENT;
550 tlsctx->tls_wait_called = false;
551 tlsctx->tls_magic = TLS_CTX_MAGIC;
553 error = tls_connect_wait(tlsctx, timeout);
555 (void)kill(pid, SIGKILL);
566 tls_connect_wait(void *ctx, int timeout)
568 struct tls_ctx *tlsctx = ctx;
572 PJDLOG_ASSERT(tlsctx != NULL);
573 PJDLOG_ASSERT(tlsctx->tls_magic == TLS_CTX_MAGIC);
574 PJDLOG_ASSERT(tlsctx->tls_side == TLS_SIDE_CLIENT);
575 PJDLOG_ASSERT(tlsctx->tls_sock != NULL);
576 PJDLOG_ASSERT(!tlsctx->tls_wait_called);
577 PJDLOG_ASSERT(timeout >= 0);
579 sockfd = proto_descriptor(tlsctx->tls_sock);
580 error = wait_for_fd(sockfd, timeout);
585 switch (recv(sockfd, &connected, sizeof(connected),
588 if (errno == EINTR || errno == ENOBUFS)
593 pjdlog_debug(1, "Connection terminated.");
597 tlsctx->tls_wait_called = true;
607 tls_server(const char *lstaddr, void **ctxp)
609 struct proto_conn *tcp;
610 struct tls_ctx *tlsctx;
614 if (strncmp(lstaddr, "tls://", 6) != 0)
617 tlsctx = malloc(sizeof(*tlsctx));
618 if (tlsctx == NULL) {
619 pjdlog_warning("Unable to allocate memory.");
623 laddr = strdup(lstaddr);
626 pjdlog_warning("Unable to allocate memory.");
629 bcopy("tcp://", laddr, 6);
631 if (proto_server(laddr, &tcp) == -1) {
639 tlsctx->tls_sock = NULL;
640 tlsctx->tls_tcp = tcp;
641 tlsctx->tls_side = TLS_SIDE_SERVER_LISTEN;
642 tlsctx->tls_wait_called = true;
643 tlsctx->tls_magic = TLS_CTX_MAGIC;
650 tls_exec_server(const char *user, int startfd, const char *privkey,
651 const char *cert, int debuglevel)
655 int sockfd, tcpfd, ret;
657 pjdlog_debug_set(debuglevel);
658 pjdlog_prefix_set("[TLS sandbox] (server) ");
659 #ifdef HAVE_SETPROCTITLE
660 setproctitle("[TLS sandbox] (server) ");
666 SSL_load_error_strings();
669 sslctx = SSL_CTX_new(TLSv1_server_method());
671 pjdlog_exitx(EX_TEMPFAIL, "SSL_CTX_new() failed.");
673 SSL_CTX_set_options(sslctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
675 ssl = SSL_new(sslctx);
677 pjdlog_exitx(EX_TEMPFAIL, "SSL_new() failed.");
679 if (SSL_use_RSAPrivateKey_file(ssl, privkey, SSL_FILETYPE_PEM) != 1) {
681 pjdlog_exitx(EX_CONFIG,
682 "SSL_use_RSAPrivateKey_file(%s) failed.", privkey);
685 if (SSL_use_certificate_file(ssl, cert, SSL_FILETYPE_PEM) != 1) {
687 pjdlog_exitx(EX_CONFIG, "SSL_use_certificate_file(%s) failed.",
691 if (sandbox(user, true, "proto_tls server") != 0)
692 pjdlog_exitx(EX_CONFIG, "Unable to sandbox TLS server.");
693 pjdlog_debug(1, "Privileges successfully dropped.");
698 if (SSL_set_fd(ssl, tcpfd) != 1)
699 pjdlog_exitx(EX_TEMPFAIL, "SSL_set_fd() failed.");
701 ret = SSL_accept(ssl);
702 ssl_check_error(ssl, ret);
704 tls_loop(sockfd, ssl);
708 tls_call_exec_server(struct proto_conn *sock, struct proto_conn *tcp)
710 int startfd, sockfd, tcpfd, safefd;
711 char *startfdstr, *debugstr;
713 if (pjdlog_mode_get() == PJDLOG_MODE_STD)
715 else /* if (pjdlog_mode_get() == PJDLOG_MODE_SYSLOG) */
718 /* Declare that we are receiver. */
719 proto_send(sock, NULL, 0);
721 sockfd = proto_descriptor(sock);
722 tcpfd = proto_descriptor(tcp);
724 safefd = MAX(sockfd, tcpfd);
725 safefd = MAX(safefd, startfd);
728 /* Move sockfd and tcpfd to safe numbers first. */
729 if (dup2(sockfd, safefd) == -1)
730 pjdlog_exit(EX_OSERR, "dup2() failed");
733 if (dup2(tcpfd, safefd + 1) == -1)
734 pjdlog_exit(EX_OSERR, "dup2() failed");
738 /* Move socketpair descriptor to descriptor number startfd. */
739 if (dup2(sockfd, startfd) == -1)
740 pjdlog_exit(EX_OSERR, "dup2() failed");
742 /* Move tcp descriptor to descriptor number startfd + 1. */
743 if (dup2(tcpfd, startfd + 1) == -1)
744 pjdlog_exit(EX_OSERR, "dup2() failed");
747 closefrom(startfd + 2);
750 * Even if FD_CLOEXEC was set on descriptors before dup2(), it should
751 * have been cleared on dup2(), but better be safe than sorry.
753 if (fcntl(startfd, F_SETFD, 0) == -1)
754 pjdlog_exit(EX_OSERR, "fcntl() failed");
755 if (fcntl(startfd + 1, F_SETFD, 0) == -1)
756 pjdlog_exit(EX_OSERR, "fcntl() failed");
758 if (asprintf(&startfdstr, "%d", startfd) == -1)
759 pjdlog_exit(EX_TEMPFAIL, "asprintf() failed");
760 if (asprintf(&debugstr, "%d", pjdlog_debug_get()) == -1)
761 pjdlog_exit(EX_TEMPFAIL, "asprintf() failed");
763 execl(proto_get("execpath"), proto_get("execpath"), "proto", "tls",
764 proto_get("user"), "server", startfdstr, proto_get("tls:keyfile"),
765 proto_get("tls:certfile"), debugstr, NULL);
766 pjdlog_exit(EX_SOFTWARE, "execl() failed");
770 tls_accept(void *ctx, void **newctxp)
772 struct tls_ctx *tlsctx = ctx;
773 struct tls_ctx *newtlsctx;
774 struct proto_conn *sock, *tcp;
778 PJDLOG_ASSERT(tlsctx != NULL);
779 PJDLOG_ASSERT(tlsctx->tls_magic == TLS_CTX_MAGIC);
780 PJDLOG_ASSERT(tlsctx->tls_side == TLS_SIDE_SERVER_LISTEN);
782 if (proto_connect(NULL, "socketpair://", -1, &sock) == -1)
785 /* Accept TCP connection. */
786 if (proto_accept(tlsctx->tls_tcp, &tcp) == -1) {
801 pjdlog_prefix_set("[TLS sandbox] (server) ");
802 #ifdef HAVE_SETPROCTITLE
803 setproctitle("[TLS sandbox] (server) ");
805 /* Close listen socket. */
806 proto_close(tlsctx->tls_tcp);
807 tls_call_exec_server(sock, tcp);
809 PJDLOG_ABORT("Unreachable.");
812 newtlsctx = calloc(1, sizeof(*tlsctx));
813 if (newtlsctx == NULL) {
817 (void)kill(pid, SIGKILL);
820 proto_local_address(tcp, newtlsctx->tls_laddr,
821 sizeof(newtlsctx->tls_laddr));
822 PJDLOG_ASSERT(strncmp(newtlsctx->tls_laddr, "tcp://", 6) == 0);
823 bcopy("tls://", newtlsctx->tls_laddr, 6);
824 *strrchr(newtlsctx->tls_laddr, ':') = '\0';
825 proto_remote_address(tcp, newtlsctx->tls_raddr,
826 sizeof(newtlsctx->tls_raddr));
827 PJDLOG_ASSERT(strncmp(newtlsctx->tls_raddr, "tcp://", 6) == 0);
828 bcopy("tls://", newtlsctx->tls_raddr, 6);
829 *strrchr(newtlsctx->tls_raddr, ':') = '\0';
831 proto_recv(sock, NULL, 0);
832 newtlsctx->tls_sock = sock;
833 newtlsctx->tls_tcp = NULL;
834 newtlsctx->tls_wait_called = true;
835 newtlsctx->tls_side = TLS_SIDE_SERVER_WORK;
836 newtlsctx->tls_magic = TLS_CTX_MAGIC;
837 *newctxp = newtlsctx;
843 tls_wrap(int fd, bool client, void **ctxp)
845 struct tls_ctx *tlsctx;
846 struct proto_conn *sock;
849 tlsctx = calloc(1, sizeof(*tlsctx));
853 if (proto_wrap("socketpair", client, fd, &sock) == -1) {
859 tlsctx->tls_sock = sock;
860 tlsctx->tls_tcp = NULL;
861 tlsctx->tls_wait_called = (client ? false : true);
862 tlsctx->tls_side = (client ? TLS_SIDE_CLIENT : TLS_SIDE_SERVER_WORK);
863 tlsctx->tls_magic = TLS_CTX_MAGIC;
870 tls_send(void *ctx, const unsigned char *data, size_t size, int fd)
872 struct tls_ctx *tlsctx = ctx;
874 PJDLOG_ASSERT(tlsctx != NULL);
875 PJDLOG_ASSERT(tlsctx->tls_magic == TLS_CTX_MAGIC);
876 PJDLOG_ASSERT(tlsctx->tls_side == TLS_SIDE_CLIENT ||
877 tlsctx->tls_side == TLS_SIDE_SERVER_WORK);
878 PJDLOG_ASSERT(tlsctx->tls_sock != NULL);
879 PJDLOG_ASSERT(tlsctx->tls_wait_called);
880 PJDLOG_ASSERT(fd == -1);
882 if (proto_send(tlsctx->tls_sock, data, size) == -1)
889 tls_recv(void *ctx, unsigned char *data, size_t size, int *fdp)
891 struct tls_ctx *tlsctx = ctx;
893 PJDLOG_ASSERT(tlsctx != NULL);
894 PJDLOG_ASSERT(tlsctx->tls_magic == TLS_CTX_MAGIC);
895 PJDLOG_ASSERT(tlsctx->tls_side == TLS_SIDE_CLIENT ||
896 tlsctx->tls_side == TLS_SIDE_SERVER_WORK);
897 PJDLOG_ASSERT(tlsctx->tls_sock != NULL);
898 PJDLOG_ASSERT(tlsctx->tls_wait_called);
899 PJDLOG_ASSERT(fdp == NULL);
901 if (proto_recv(tlsctx->tls_sock, data, size) == -1)
908 tls_descriptor(const void *ctx)
910 const struct tls_ctx *tlsctx = ctx;
912 PJDLOG_ASSERT(tlsctx != NULL);
913 PJDLOG_ASSERT(tlsctx->tls_magic == TLS_CTX_MAGIC);
915 switch (tlsctx->tls_side) {
916 case TLS_SIDE_CLIENT:
917 case TLS_SIDE_SERVER_WORK:
918 PJDLOG_ASSERT(tlsctx->tls_sock != NULL);
920 return (proto_descriptor(tlsctx->tls_sock));
921 case TLS_SIDE_SERVER_LISTEN:
922 PJDLOG_ASSERT(tlsctx->tls_tcp != NULL);
924 return (proto_descriptor(tlsctx->tls_tcp));
926 PJDLOG_ABORT("Invalid side (%d).", tlsctx->tls_side);
931 tcp_address_match(const void *ctx, const char *addr)
933 const struct tls_ctx *tlsctx = ctx;
935 PJDLOG_ASSERT(tlsctx != NULL);
936 PJDLOG_ASSERT(tlsctx->tls_magic == TLS_CTX_MAGIC);
938 return (strcmp(tlsctx->tls_raddr, addr) == 0);
942 tls_local_address(const void *ctx, char *addr, size_t size)
944 const struct tls_ctx *tlsctx = ctx;
946 PJDLOG_ASSERT(tlsctx != NULL);
947 PJDLOG_ASSERT(tlsctx->tls_magic == TLS_CTX_MAGIC);
948 PJDLOG_ASSERT(tlsctx->tls_wait_called);
950 switch (tlsctx->tls_side) {
951 case TLS_SIDE_CLIENT:
952 PJDLOG_ASSERT(tlsctx->tls_sock != NULL);
954 PJDLOG_VERIFY(strlcpy(addr, "tls://N/A", size) < size);
956 case TLS_SIDE_SERVER_WORK:
957 PJDLOG_ASSERT(tlsctx->tls_sock != NULL);
959 PJDLOG_VERIFY(strlcpy(addr, tlsctx->tls_laddr, size) < size);
961 case TLS_SIDE_SERVER_LISTEN:
962 PJDLOG_ASSERT(tlsctx->tls_tcp != NULL);
964 proto_local_address(tlsctx->tls_tcp, addr, size);
965 PJDLOG_ASSERT(strncmp(addr, "tcp://", 6) == 0);
966 /* Replace tcp:// prefix with tls:// */
967 bcopy("tls://", addr, 6);
970 PJDLOG_ABORT("Invalid side (%d).", tlsctx->tls_side);
975 tls_remote_address(const void *ctx, char *addr, size_t size)
977 const struct tls_ctx *tlsctx = ctx;
979 PJDLOG_ASSERT(tlsctx != NULL);
980 PJDLOG_ASSERT(tlsctx->tls_magic == TLS_CTX_MAGIC);
981 PJDLOG_ASSERT(tlsctx->tls_wait_called);
983 switch (tlsctx->tls_side) {
984 case TLS_SIDE_CLIENT:
985 PJDLOG_ASSERT(tlsctx->tls_sock != NULL);
987 PJDLOG_VERIFY(strlcpy(addr, "tls://N/A", size) < size);
989 case TLS_SIDE_SERVER_WORK:
990 PJDLOG_ASSERT(tlsctx->tls_sock != NULL);
992 PJDLOG_VERIFY(strlcpy(addr, tlsctx->tls_raddr, size) < size);
994 case TLS_SIDE_SERVER_LISTEN:
995 PJDLOG_ASSERT(tlsctx->tls_tcp != NULL);
997 proto_remote_address(tlsctx->tls_tcp, addr, size);
998 PJDLOG_ASSERT(strncmp(addr, "tcp://", 6) == 0);
999 /* Replace tcp:// prefix with tls:// */
1000 bcopy("tls://", addr, 6);
1003 PJDLOG_ABORT("Invalid side (%d).", tlsctx->tls_side);
1008 tls_close(void *ctx)
1010 struct tls_ctx *tlsctx = ctx;
1012 PJDLOG_ASSERT(tlsctx != NULL);
1013 PJDLOG_ASSERT(tlsctx->tls_magic == TLS_CTX_MAGIC);
1015 if (tlsctx->tls_sock != NULL) {
1016 proto_close(tlsctx->tls_sock);
1017 tlsctx->tls_sock = NULL;
1019 if (tlsctx->tls_tcp != NULL) {
1020 proto_close(tlsctx->tls_tcp);
1021 tlsctx->tls_tcp = NULL;
1023 tlsctx->tls_side = 0;
1024 tlsctx->tls_magic = 0;
1029 tls_exec(int argc, char *argv[])
1032 PJDLOG_ASSERT(argc > 3);
1033 PJDLOG_ASSERT(strcmp(argv[0], "tls") == 0);
1035 pjdlog_init(atoi(argv[3]) == 0 ? PJDLOG_MODE_SYSLOG : PJDLOG_MODE_STD);
1037 if (strcmp(argv[2], "client") == 0) {
1040 tls_exec_client(argv[1], atoi(argv[3]),
1041 argv[4][0] == '\0' ? NULL : argv[4], argv[5], argv[6],
1042 argv[7], atoi(argv[8]), atoi(argv[9]));
1043 } else if (strcmp(argv[2], "server") == 0) {
1046 tls_exec_server(argv[1], atoi(argv[3]), argv[4], argv[5],
1052 static struct proto tls_proto = {
1054 .prt_connect = tls_connect,
1055 .prt_connect_wait = tls_connect_wait,
1056 .prt_server = tls_server,
1057 .prt_accept = tls_accept,
1058 .prt_wrap = tls_wrap,
1059 .prt_send = tls_send,
1060 .prt_recv = tls_recv,
1061 .prt_descriptor = tls_descriptor,
1062 .prt_address_match = tcp_address_match,
1063 .prt_local_address = tls_local_address,
1064 .prt_remote_address = tls_remote_address,
1065 .prt_close = tls_close,
1066 .prt_exec = tls_exec
1069 static __constructor void
1073 proto_register(&tls_proto, false);