tls.c (3439B)
1 /* 2 * zygo/tls.c 3 * 4 * Copyright (c) 2022 hhvn <dev@hhvn.uk> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 * 18 */ 19 20 #include <unistd.h> 21 #include <netdb.h> 22 #include <tls.h> 23 #include <sys/socket.h> 24 #include "zygo.h" 25 26 struct tls *ctx = NULL; 27 struct tls_config *conf = NULL; 28 int fd; 29 int tls; 30 31 int 32 net_connect(Elem *e, int silent) { 33 struct addrinfo *ai = NULL; 34 int ret; 35 36 tls = e->tls; 37 38 if (tls) { 39 if (conf) 40 tls_config_free(conf); 41 if (ctx) 42 tls_free(ctx); 43 44 if ((conf = tls_config_new()) == NULL) { 45 if (!silent) 46 error("tls_config_new(): %s", tls_config_error(conf)); 47 goto fail; 48 } 49 50 if (insecure) { 51 tls_config_insecure_noverifycert(conf); 52 tls_config_insecure_noverifyname(conf); 53 } 54 55 if ((ctx = tls_client()) == NULL) { 56 if (!silent) 57 error("tls_client(): %s", tls_error(ctx)); 58 goto fail; 59 } 60 61 if (tls_configure(ctx, conf) == -1) { 62 if (!silent) 63 error("tls_configure(): %s", tls_error(ctx)); 64 goto fail; 65 } 66 } 67 68 if ((ret = getaddrinfo(e->server, e->port, NULL, &ai)) != 0 || ai == NULL) { 69 if (!silent) 70 error("could not lookup %s:%s", e->server, e->port); 71 goto fail; 72 } 73 74 if ((fd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol)) == -1 || 75 connect(fd, ai->ai_addr, ai->ai_addrlen) == -1) { 76 if (!silent) 77 error("could not connect to %s:%s", e->server, e->port); 78 goto fail; 79 } 80 81 if (tls) { 82 if (tls_connect_socket(ctx, fd, e->server) == -1) { 83 if (!silent) 84 error("could not tls-ify connection to %s:%s", e->server, e->port); 85 goto fail; 86 } 87 88 if (tls_handshake(ctx) == -1) { 89 if (!silent) 90 error("could not perform tls handshake with %s:%s", e->server, e->port); 91 goto fail; 92 } 93 } 94 95 freeaddrinfo(ai); 96 return 0; 97 98 fail: 99 if (ai) 100 freeaddrinfo(ai); 101 if (ctx) { 102 tls_free(ctx); 103 ctx = NULL; 104 } 105 if (conf) { 106 tls_config_free(conf); 107 conf = NULL; 108 } 109 return -1; 110 } 111 112 int 113 net_read(void *buf, size_t count) { 114 int ret; 115 116 if (tls) { 117 do { 118 ret = tls_read(ctx, buf, count); 119 } while (ret == TLS_WANT_POLLIN || ret == TLS_WANT_POLLOUT); 120 if (ret == -1) 121 error("tls_read(): %s", tls_error(ctx)); 122 } else { 123 ret = read(fd, buf, count); 124 } 125 126 return ret; 127 } 128 129 int 130 net_write(void *buf, size_t count) { 131 int ret; 132 133 if (tls) { 134 while (count > 0) { 135 switch (ret = tls_write(ctx, buf, count)) { 136 case TLS_WANT_POLLIN: 137 case TLS_WANT_POLLOUT: 138 break; 139 case -1: 140 error("tls_write(): %s", tls_error(ctx)); 141 break; 142 default: 143 buf += ret; 144 count -= ret; 145 } 146 } 147 } else { 148 ret = write(fd, buf, count); 149 } 150 151 return ret; 152 } 153 154 int 155 net_close(void) { 156 int ret; 157 158 if (tls) { 159 do { 160 ret = tls_close(ctx); 161 } while (ret == TLS_WANT_POLLIN || ret == TLS_WANT_POLLOUT); 162 tls_free(ctx); 163 ctx = NULL; 164 tls_config_free(conf); 165 conf = NULL; 166 } 167 168 return close(fd); 169 }