zygo

ncurses gopher client
git clone https://hhvn.uk/zygo
git clone git://hhvn.uk/zygo
Log | Files | Refs

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 }