diff options
-rw-r--r-- | bounce.c | 16 | ||||
-rw-r--r-- | bounce.h | 5 | ||||
-rw-r--r-- | pounce.1 | 40 | ||||
-rw-r--r-- | server.c | 20 |
4 files changed, 77 insertions, 4 deletions
diff --git a/bounce.c b/bounce.c index 9854145..31ca4a6 100644 --- a/bounce.c +++ b/bounce.c @@ -206,6 +206,8 @@ int main(int argc, char *argv[]) { const char *genPath = NULL; bool insecure = false; + bool printCert = false; + const char *trust = NULL; const char *clientCert = NULL; const char *clientPriv = NULL; const char *serverBindHost = NULL; @@ -246,10 +248,12 @@ int main(int argc, char *argv[]) { { .val = 'j', .name = "join", required_argument }, { .val = 'k', .name = "client-priv", required_argument }, { .val = 'n', .name = "nick", required_argument }, + { .val = 'o', .name = "print-cert", no_argument }, { .val = 'p', .name = "port", required_argument }, { .val = 'q', .name = "quit", required_argument }, { .val = 'r', .name = "real", required_argument }, { .val = 's', .name = "size", required_argument }, + { .val = 't', .name = "trust", required_argument }, { .val = 'u', .name = "user", required_argument }, { .val = 'v', .name = "verbose", no_argument }, { .val = 'w', .name = "pass", required_argument }, @@ -288,10 +292,12 @@ int main(int argc, char *argv[]) { break; case 'j': join = optarg; break; case 'k': clientPriv = optarg; break; case 'n': nick = optarg; + break; case 'o': insecure = true; printCert = true; break; case 'p': port = optarg; break; case 'q': quit = optarg; break; case 'r': real = optarg; break; case 's': ringSize = parseSize(optarg); + break; case 't': trust = optarg; break; case 'u': user = optarg; break; case 'v': verbose = true; break; case 'w': pass = optarg; @@ -341,6 +347,7 @@ int main(int argc, char *argv[]) { unveilConfig(certPath); unveilConfig(privPath); if (caPath) unveilConfig(caPath); + if (trust) unveilConfig(trust); if (clientCert) unveilConfig(clientCert); if (clientPriv) unveilConfig(clientPriv); if (savePath) unveilData(savePath); @@ -353,6 +360,13 @@ int main(int argc, char *argv[]) { if (error) err(EX_OSERR, "pledge"); #endif + if (printCert) { + serverConfig(insecure, trust, clientCert, clientPriv); + serverConnect(serverBindHost, host, port); + serverPrintCert(); + return EX_OK; + } + // Either exit with cleanup or ignore signals until entering the main loop. signal(SIGINT, justExit); signal(SIGTERM, justExit); @@ -406,7 +420,7 @@ int main(int argc, char *argv[]) { ? localUnix(bind, ARRAY_LEN(bind), bindPath) : localBind(bind, ARRAY_LEN(bind), bindHost, bindPort); - serverConfig(insecure, clientCert, clientPriv); + serverConfig(insecure, trust, clientCert, clientPriv); int server = serverConnect(serverBindHost, host, port); #ifdef __FreeBSD__ diff --git a/bounce.h b/bounce.h index d08f21f..2bcd77c 100644 --- a/bounce.h +++ b/bounce.h @@ -174,8 +174,11 @@ size_t localUnix(int fds[], size_t cap, const char *path); int localAccept(struct tls **tls, int bind); extern struct timeval serverQueueInterval; -void serverConfig(bool insecure, const char *cert, const char *priv); +void serverConfig( + bool insecure, const char *trust, const char *cert, const char *priv +); int serverConnect(const char *bindHost, const char *host, const char *port); +void serverPrintCert(void); void serverRecv(void); void serverSend(const char *ptr, size_t len); void serverFormat(const char *format, ...) diff --git a/pounce.1 b/pounce.1 index 8c4107d..caeb243 100644 --- a/pounce.1 +++ b/pounce.1 @@ -1,4 +1,4 @@ -.Dd August 28, 2020 +.Dd January 11, 2021 .Dt POUNCE 1 .Os . @@ -29,6 +29,7 @@ .Op Fl p Ar port .Op Fl q Ar quit .Op Fl r Ar real +.Op Fl t Ar trust .Op Fl s Ar size .Op Fl u Ar user .Op Fl w Ar pass @@ -36,6 +37,13 @@ .Op Ar config ... . .Nm +.Fl o +.Op Fl S Ar bind +.Op Fl h Ar host +.Op Fl p Ar port +.Op Ar config ... +. +.Nm .Op Fl A Ar ca .Fl g Ar cert . @@ -300,6 +308,11 @@ Set nickname to .Ar nick . The default nickname is the user's name. . +.It Fl o +Print the server certificate chain +to standard output in PEM format +and exit. +. .It Fl p Ar port , Cm port = Ar port Connect to .Ar port . @@ -321,6 +334,13 @@ Set the number of messages contained in the buffer to The size must be a power of two. The default size is 4096. . +.It Fl t Ar path , Cm trust = Ar path +Trust the certificate loaded from +.Ar path . +Server name verification is disabled. +See +.Sx Connecting to Servers with Self-signed Certificates . +. .It Fl u Ar user , Cm user = Ar user Set username to .Ar user . @@ -537,6 +557,24 @@ sasl-external .Ed .El . +.Ss Connecting to Servers with Self-signed Certificates +.Bl -enum +.It +Connect to the server +and write its certificate to a file: +.Bd -literal -offset indent +pounce -o -h irc.example.org > ~/.config/pounce/example.pem +.Ed +.It +Configure +.Nm +to trust the certificate: +.Bd -literal -offset indent +trust = example.pem +# or: pounce -t example.pem +.Ed +.El +. .Sh ENVIRONMENT .Bl -tag -width Ds .It Ev USER diff --git a/server.c b/server.c index 89e3e36..636d911 100644 --- a/server.c +++ b/server.c @@ -42,7 +42,9 @@ static struct tls *client; -void serverConfig(bool insecure, const char *cert, const char *priv) { +void serverConfig( + bool insecure, const char *trust, const char *cert, const char *priv +) { struct tls_config *config = tls_config_new(); if (!config) errx(EX_SOFTWARE, "tls_config_new"); @@ -55,6 +57,15 @@ void serverConfig(bool insecure, const char *cert, const char *priv) { tls_config_insecure_noverifycert(config); tls_config_insecure_noverifyname(config); } + if (trust) { + tls_config_insecure_noverifyname(config); + const char *dirs = NULL; + for (const char *path; NULL != (path = configPath(&dirs, trust));) { + error = tls_config_set_ca_file(config, path); + if (!error) break; + } + if (error) errx(EX_NOINPUT, "%s: %s", trust, tls_config_error(config)); + } if (cert) { const char *dirs = NULL; @@ -145,6 +156,13 @@ int serverConnect(const char *bindHost, const char *host, const char *port) { return sock; } +void serverPrintCert(void) { + size_t len; + const byte *pem = tls_peer_cert_chain_pem(client, &len); + printf("subject= %s\n", tls_peer_cert_subject(client)); + fwrite(pem, len, 1, stdout); +} + void serverSend(const char *ptr, size_t len) { if (verbose) fprintf(stderr, "\x1B[31m%.*s\x1B[m", (int)len, ptr); while (len) { |