tls: Add support for TOFU (Trusted On First Use) - sacc - sacc(omys), simple co… | |
git clone git://bitreich.org/sacc/ git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65… | |
Log | |
Files | |
Refs | |
Tags | |
LICENSE | |
--- | |
commit e8930420e7c31a3cea0484314bd38aba5197fa39 | |
parent 7d3b71e31c73e122b62fec68a7196586f1b93082 | |
Author: Quentin Rameau <[email protected]> | |
Date: Tue, 20 Sep 2022 23:04:00 +0200 | |
tls: Add support for TOFU (Trusted On First Use) | |
Diffstat: | |
M io_tls.c | 77 +++++++++++++++++++++++++++++… | |
M sacc.c | 2 +- | |
2 files changed, 76 insertions(+), 3 deletions(-) | |
--- | |
diff --git a/io_tls.c b/io_tls.c | |
@@ -1,3 +1,5 @@ | |
+#include <limits.h> | |
+#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <unistd.h> | |
@@ -29,13 +31,36 @@ close_tls(struct cnx *c) | |
} | |
static int | |
+savepem(struct tls *t, char *path) | |
+{ | |
+ FILE *f; | |
+ const char *s; | |
+ size_t ln; | |
+ | |
+ if ((s = tls_peer_cert_chain_pem(t, &ln)) == NULL) | |
+ return -1; | |
+ if ((f = fopen(path, "w")) == NULL) | |
+ return -1; | |
+ fprintf(f, "%.*s\n", ln, s); | |
+ if (fclose(f) != 0) | |
+ return -1; | |
+ | |
+ return 0; | |
+} | |
+ | |
+static int | |
connect_tls(struct cnx *c, struct addrinfo *ai, const char *host) | |
{ | |
+ char pempath[PATH_MAX]; | |
struct tls *t; | |
+ struct tls_config *tc; | |
char *s; | |
int r; | |
c->tls = NULL; | |
+ tc = NULL; | |
+ s = NULL; | |
+ r = -1; | |
if (connect(c->sock, ai->ai_addr, ai->ai_addrlen) == -1) | |
return -1; | |
@@ -45,16 +70,60 @@ connect_tls(struct cnx *c, struct addrinfo *ai, const char … | |
if ((t = tls_client()) == NULL) | |
return -1; | |
+ | |
+ snprintf(pempath, sizeof(pempath), "/home/quinq/share/sacc/%s.pem", ho… | |
+ switch (tls) { | |
+ case 1: | |
+ /* check if there is a local certificate for target */ | |
+ if (access(pempath, R_OK) == 0) { | |
+ if ((tc = tls_config_new()) == NULL) | |
+ goto end; | |
+ if (tls_config_set_ca_file(tc, pempath) == -1) | |
+ goto end; | |
+ if (tls_configure(t, tc) == -1) | |
+ goto end; | |
+ } | |
+ break; | |
+ case 2: | |
+ /* save target certificate to file */ | |
+ if ((tc = tls_config_new()) == NULL) | |
+ goto end; | |
+ tls_config_insecure_noverifycert(tc); | |
+ if (tls_configure(t, tc) == -1) | |
+ goto end; | |
+ break; | |
+ } | |
+ | |
if (tls_connect_socket(t, c->sock, host) == -1) | |
return -1; | |
+ | |
do { | |
r = tls_handshake(t); | |
} while (r == TLS_WANT_POLLIN || r == TLS_WANT_POLLOUT); | |
+ | |
if (r == 0) { | |
- c->tls = t; | |
+ switch (tls) { | |
+ case 1: | |
+ c->tls = t; | |
+ break; | |
+ case 2: | |
+ r = savepem(t, pempath) == 0 ? -2 : -1; | |
+ tls = 1; | |
+ break; | |
+ } | |
} else { | |
diag("Can't establish TLS with \"%s\": %s", | |
host, tls_error(t)); | |
+ | |
+ s = uiprompt("Save certificate locally and retry? [yN]: "); | |
+ switch (*s) { | |
+ case 'Y': | |
+ case 'y': | |
+ tls = 2; | |
+ r = -2; | |
+ goto end; | |
+ } | |
+ | |
s = uiprompt("Retry on cleartext? [Yn]: "); | |
switch (*s) { | |
case 'Y': | |
@@ -66,8 +135,12 @@ connect_tls(struct cnx *c, struct addrinfo *ai, const char … | |
default: | |
r = -3; | |
} | |
- free(s); | |
} | |
+end: | |
+ free(s); | |
+ tls_config_free(tc); | |
+ if (r != 0) | |
+ tls_free(t); | |
return r; | |
} | |
diff --git a/sacc.c b/sacc.c | |
@@ -581,7 +581,7 @@ connectto(const char *host, const char *port, struct cnx *c) | |
err = errno; | |
ioclose(c); | |
} | |
- /* retry on cleartext */ | |
+ /* retry */ | |
} while (r == -2); | |
} | |