Recently Written · git

sacc

Mirror of git://bitreich.org/sacc, the sacc gopher client from bitreich.org.

git clone https://github.com/equwal/sacc

Log | Files | Refs


commit 7e0793d8395184b5b21ecdd0b13bccb524d1e414
Quentin Rameau <quinq@fifth.space>
2021-04-11 17:12:00 +0200

Retry cleartext connection in case TLS failed

 io_tls.c | 33 ++++++++++++++++++++++++++++-----
 sacc.c   | 32 +++++++++++++++++---------------
 2 files changed, 45 insertions(+), 20 deletions(-)
diff --git a/io_tls.c b/io_tls.c
index a50aebd..1b072d4 100644
--- a/io_tls.c
+++ b/io_tls.c
@@ -1,3 +1,4 @@
+#include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 #include <netdb.h>
@@ -32,6 +33,7 @@ static int
 connect_tls(struct cnx *c, struct addrinfo *ai, const char *host)
 {
 	struct tls *t;
+	char *r;
 	int s;
 
 	c->tls = NULL;
@@ -43,13 +45,34 @@ connect_tls(struct cnx *c, struct addrinfo *ai, const char *host)
 	if (tls) {
 		if ((t = tls_client()) == NULL)
 			return -1;
-		if (tls_connect_socket(t, s, host) == -1)
-			return -1;
-
-		c->tls = t;
+		if (tls_connect_socket(t, s, host) == 0) {
+			do {
+				s = tls_handshake(t);
+			} while (s == TLS_WANT_POLLIN || s == TLS_WANT_POLLOUT);
+			if (s == 0) {
+				c->tls = t;
+			} else {
+				diag("Can't establish TLS with \"%s\": %s",
+				     host, tls_error(t));
+				r = uiprompt("Retry on cleartext? [Yn]: ");
+				switch (*r) {
+				case 'Y':
+				case 'y':
+				case '\0':
+					tls = 0;
+					s = -2;
+					break;
+				default:
+					s = -3;
+				}
+				free(r);
+			}
+		} else {
+			s = -1;
+		}
 	}
 
-	return 0;
+	return s;
 }
 
 static void
diff --git a/sacc.c b/sacc.c
index cf9c8e7..fd74b54 100644
--- a/sacc.c
+++ b/sacc.c
@@ -491,8 +491,8 @@ connectto(const char *host, const char *port, struct cnx *c)
 	    .ai_socktype = SOCK_STREAM,
 	    .ai_protocol = IPPROTO_TCP,
 	};
-	struct addrinfo *addrs, *addr;
-	int r, err;
+	struct addrinfo *addrs, *ai;
+	int r, err, conn;
 
 	sigemptyset(&set);
 	sigaddset(&set, SIGWINCH);
@@ -505,18 +505,20 @@ connectto(const char *host, const char *port, struct cnx *c)
 	}
 
 	r = -1;
-	for (addr = addrs; addr; addr = addr->ai_next) {
-		if ((c->sock = socket(addr->ai_family, addr->ai_socktype,
-		                      addr->ai_protocol)) == -1) {
-			err = errno;
-			continue;
-		}
-
-		if ((r = ioconnect(c, addr, host)) == 0)
-			break;
+	for (ai = addrs; ai && r == -1; ai = ai->ai_next) {
+		do {
+			if ((c->sock = socket(ai->ai_family, ai->ai_socktype,
+			                      ai->ai_protocol)) == -1) {
+				err = errno;
+				break;
+			}
 
-		err = errno;
-		close(c->sock);
+			if ((r = ioconnect(c, ai, host)) < 0) {
+				err = errno;
+				ioclose(c);
+			}
+		/* retry on cleartext */
+		} while (r == -2);
 	}
 
 	freeaddrinfo(addrs);
@@ -537,7 +539,7 @@ download(Item *item, int dest)
 	ssize_t r, w;
 
 	if (item->tag == NULL) {
-		if (connectto(item->host, item->port, &c) == -1 ||
+		if (connectto(item->host, item->port, &c) < 0 ||
 		    sendselector(&c, item->selector) == -1)
 			return 0;
 	} else {
@@ -621,7 +623,7 @@ fetchitem(Item *item)
 	struct cnx c;
 	char *raw;
 
-	if (connectto(item->host, item->port, &c) == -1 ||
+	if (connectto(item->host, item->port, &c) < 0 ||
 	    sendselector(&c, item->selector) == -1)
 		return 0;