Add TLS support - sacc - sacc(omys), simple console gopher client | |
git clone git://bitreich.org/sacc/ git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65… | |
Log | |
Files | |
Refs | |
Tags | |
LICENSE | |
--- | |
commit 92394502830c460c78633f56a69da4ce5f01d5fa | |
parent a58414c67ddf05ff48b8a86fb2d3cf5e58cea4b9 | |
Author: Quentin Rameau <[email protected]> | |
Date: Fri, 9 Apr 2021 23:58:34 +0200 | |
Add TLS support | |
TLS will be used when a gophers:// URL is requested. | |
Diffstat: | |
M Makefile | 4 ++-- | |
M config.mk | 4 ++++ | |
M sacc.c | 124 ++++++++++++++++++++++++++---… | |
3 files changed, 110 insertions(+), 22 deletions(-) | |
--- | |
diff --git a/Makefile b/Makefile | |
@@ -14,7 +14,7 @@ config.h: | |
cp config.def.h config.h | |
$(BIN): $(OBJ) | |
- $(CC) $(OBJ) $(LDFLAGS) $(LIBS) -o $@ | |
+ $(CC) $(OBJ) $(LDFLAGS) $(LIBS) $(TLSLIBS) -o $@ | |
$(OBJ): config.h config.mk common.h | |
@@ -33,7 +33,7 @@ uninstall: | |
# Stock FLAGS | |
SACCCFLAGS = -D_DEFAULT_SOURCE -D_XOPEN_SOURCE=700 -D_BSD_SOURCE -D_GNU_SOURCE… | |
- $(CFLAGS) | |
+ $(TLSCFLAGS) $(CFLAGS) | |
.c.o: | |
$(CC) $(SACCCFLAGS) -c $< | |
diff --git a/config.mk b/config.mk | |
@@ -12,3 +12,7 @@ LIBS=-lcurses | |
# Define NEED_ASPRINTF and/or NEED_STRCASESTR in your cflags if your system do… | |
# not provide asprintf() or strcasestr(), respectively. | |
#CFLAGS = -DNEED_ASPRINTF -DNEED_STRCASESTR | |
+ | |
+# gophers (gopher over TLS) support | |
+TLSCFLAGS = -DUSE_TLS | |
+TLSLIBS = -ltls | |
diff --git a/sacc.c b/sacc.c | |
@@ -18,14 +18,26 @@ | |
#include <sys/types.h> | |
#include <sys/wait.h> | |
+#ifdef USE_TLS | |
+#include <tls.h> | |
+#endif | |
+ | |
#include "common.h" | |
#include "config.h" | |
+struct cnx { | |
+#ifdef USE_TLS | |
+ struct tls *tls; | |
+#endif | |
+ int sock; | |
+}; | |
+ | |
static char *mainurl; | |
static Item *mainentry; | |
static int devnullfd; | |
static int parent = 1; | |
static int interactive; | |
+static int tls; | |
static void (*diag)(char *fmt, ...); | |
@@ -417,7 +429,7 @@ molddiritem(char *raw) | |
} | |
static char * | |
-getrawitem(int sock) | |
+getrawitem(struct cnx *cnx) | |
{ | |
char *raw, *buf; | |
size_t bn, bs; | |
@@ -445,7 +457,18 @@ getrawitem(int sock) | |
buf = raw + (bn-1) * BUFSIZ; | |
bs = BUFSIZ; | |
} | |
- } while ((n = read(sock, buf, bs)) > 0); | |
+ | |
+#ifdef USE_TLS | |
+ if (tls) { | |
+ do { | |
+ n = tls_read(cnx->tls, buf, bs); | |
+ } while (n == TLS_WANT_POLLIN || n == TLS_WANT_POLLOUT… | |
+ } else | |
+#endif | |
+ { | |
+ n = read(cnx->sock, buf, bs); | |
+ } | |
+ } while (n > 0); | |
*buf = '\0'; | |
@@ -458,7 +481,7 @@ getrawitem(int sock) | |
} | |
static int | |
-sendselector(int sock, const char *selector) | |
+sendselector(struct cnx *cnx, const char *selector) | |
{ | |
char *msg, *p; | |
size_t ln; | |
@@ -468,10 +491,21 @@ sendselector(int sock, const char *selector) | |
msg = p = xmalloc(ln); | |
snprintf(msg, ln--, "%s\r\n", selector); | |
- while ((n = write(sock, p, ln)) > 0) { | |
+ do { | |
+#ifdef USE_TLS | |
+ if (tls) { | |
+ do { | |
+ n = tls_write(cnx->tls, p, ln); | |
+ } while (n == TLS_WANT_POLLIN || n == TLS_WANT_POLLOUT… | |
+ } else | |
+#endif | |
+ { | |
+ n = write(cnx->sock, p, ln); | |
+ } | |
+ | |
ln -= n; | |
p += n; | |
- } | |
+ } while (n > 0); | |
free(msg); | |
if (n == -1) | |
@@ -480,8 +514,20 @@ sendselector(int sock, const char *selector) | |
return n; | |
} | |
+static void | |
+closecnx(struct cnx *cnx) | |
+{ | |
+#ifdef USE_TLS | |
+ if (tls) { | |
+ tls_close(cnx->tls); | |
+ tls_free(cnx->tls); | |
+ } | |
+#endif | |
+ close(cnx->sock); | |
+} | |
+ | |
static int | |
-connectto(const char *host, const char *port) | |
+connectto(const char *host, const char *port, struct cnx *cnx) | |
{ | |
sigset_t set, oset; | |
static const struct addrinfo hints = { | |
@@ -506,10 +552,23 @@ connectto(const char *host, const char *port) | |
if ((sock = socket(addr->ai_family, addr->ai_socktype, | |
addr->ai_protocol)) < 0) | |
continue; | |
- if ((r = connect(sock, addr->ai_addr, addr->ai_addrlen)) < 0) { | |
+ | |
+ r = connect(sock, addr->ai_addr, addr->ai_addrlen); | |
+ if (r == -1) { | |
close(sock); | |
continue; | |
} | |
+#ifdef USE_TLS | |
+ if (tls) { | |
+ if ((cnx->tls = tls_client()) == NULL) { | |
+ diag("Can't establish TLS with \"%s\": %s", | |
+ host, tls_error(cnx->tls)); | |
+ close(sock); | |
+ continue; | |
+ } | |
+ r = tls_connect_socket(cnx->tls, sock, host); | |
+ } | |
+#endif | |
break; | |
} | |
@@ -526,8 +585,10 @@ connectto(const char *host, const char *port) | |
} | |
sigprocmask(SIG_SETMASK, &oset, NULL); | |
- return sock; | |
+ cnx->sock = sock; | |
+ | |
+ return 0; | |
err: | |
sigprocmask(SIG_SETMASK, &oset, NULL); | |
return -1; | |
@@ -537,13 +598,15 @@ static int | |
download(Item *item, int dest) | |
{ | |
char buf[BUFSIZ]; | |
+ struct cnx cnx; | |
ssize_t r, w; | |
int src; | |
if (!item->tag) { | |
- if ((src = connectto(item->host, item->port)) < 0 || | |
- sendselector(src, item->selector) < 0) | |
+ if (connectto(item->host, item->port, &cnx) < 0 || | |
+ sendselector(&cnx, item->selector) < 0) | |
return 0; | |
+ src = cnx.sock; | |
} else if ((src = open(item->tag, O_RDONLY)) < 0) { | |
printf("Can't open source file %s: %s", | |
item->tag, strerror(errno)); | |
@@ -551,8 +614,20 @@ download(Item *item, int dest) | |
return 0; | |
} | |
- w = 0; | |
- while ((r = read(src, buf, BUFSIZ)) > 0) { | |
+ for (w = 0; w != -1;) { | |
+#ifdef USE_TLS | |
+ if (tls) { | |
+ do { | |
+ r = tls_read(cnx.tls, buf, sizeof(buf)); | |
+ } while (r == TLS_WANT_POLLIN || r == TLS_WANT_POLLOUT… | |
+ } else | |
+#endif | |
+ { | |
+ r = read(src, buf, sizeof(buf)); | |
+ } | |
+ if (r <= 0) | |
+ break; | |
+ | |
while ((w = write(dest, buf, r)) > 0) | |
r -= w; | |
} | |
@@ -563,7 +638,7 @@ download(Item *item, int dest) | |
errno = 0; | |
} | |
- close(src); | |
+ closecnx(&cnx); | |
return (r == 0 && w == 0); | |
} | |
@@ -618,14 +693,15 @@ cleanup: | |
static int | |
fetchitem(Item *item) | |
{ | |
- char *raw, *r; | |
- int sock; | |
+ struct cnx cnx; | |
+ char *raw; | |
- if ((sock = connectto(item->host, item->port)) < 0 || | |
- sendselector(sock, item->selector) < 0) | |
+ if (connectto(item->host, item->port, &cnx) < 0 || | |
+ sendselector(&cnx, item->selector) < 0) | |
return 0; | |
- raw = getrawitem(sock); | |
- close(sock); | |
+ | |
+ raw = getrawitem(&cnx); | |
+ closecnx(&cnx); | |
if (raw == NULL || !*raw) { | |
diag("Empty response from server"); | |
@@ -910,8 +986,16 @@ moldentry(char *url) | |
int parsed, ipv6; | |
if (p = strstr(url, "://")) { | |
- if (strncmp(url, "gopher", p - url)) | |
+ if (strncmp(url, "gopher", p - url) == 0) { | |
+ if (tls) { | |
+ diag("Switching from gophers to gopher"); | |
+ tls = 0; | |
+ } | |
+ } else if (strncmp(url, "gophers", p - url) == 0) { | |
+ tls = 1; | |
+ } else { | |
die("Protocol not supported: %.*s", p - url, url); | |
+ } | |
host = p + 3; | |
} | |