hirc

IRC client
Log | Files | Refs

commit 78d573dbda47504c262f6c77c2693fdc4dc2a570
parent 99b4048422599541e84aed0098a96104c76f6095
Author: hhvn <dev@hhvn.uk>
Date:   Fri, 17 Dec 2021 18:13:25 +0000

s/serv.c s/main.c s/handle.c s/ui.c s/commands.c s/config.c s/hirc.h s/struct.h: basic TLS

Diffstat:
Msrc/commands.c | 5++++-
Msrc/config.c | 13++++++++++++-
Msrc/handle.c | 5+++--
Msrc/hirc.h | 3++-
Msrc/main.c | 33+++++++++++++++++++++++++++++++--
Msrc/serv.c | 53++++++++++++++++++++++++++++++++++++++++-------------
Msrc/struct.h | 1+
Msrc/ui.c | 5++++-
8 files changed, 97 insertions(+), 21 deletions(-)

diff --git a/src/commands.c b/src/commands.c @@ -419,7 +419,10 @@ command_connect(struct Server *server, char *str) { nick = user ? user->pw_name : "null"; } - port = port ? port : "6667"; + if (!port) { + port = tls ? "6697" : "6667"; + } + username = username ? username : nick; realname = realname ? realname : nick; network = network ? network : host; diff --git a/src/config.c b/src/config.c @@ -243,11 +243,22 @@ struct Config config[] = { .description = { "Format of SELF_CONNECTFAIL messages", NULL}}, #ifndef TLS - {"format.ui.tlsnotcompiled", 1, Val_string, + {"format.ui.tls.notcompiled", 1, Val_string, .str = "TLS not compiled into hirc", .strhandle = config_redraws, .description = { "Format of SELF_TLSNOTCOMPILED messages", NULL}}, +#else + {"format.ui.tls.version", 1, Val_string, + .str = "Protocol: %{b}${2}%{b} (%{b}${3}%{b} bits, %{b}${4}%{b})", + .strhandle = config_redraws, + .description = { + "TLS version information", NULL}}, + {"format.ui.tls.names", 1, Val_string, + .str = "SNI name: %{b}${2}%{b}\nCert subject: %{b}${3}%{b}\nCert issuer: %{b}${3}%{b}", + .strhandle = config_redraws, + .description = { + "TLS identification", NULL}}, #endif /* TLS */ {"format.ui.keybind", 1, Val_string, .str = " ${1}: ${2}", diff --git a/src/handle.c b/src/handle.c @@ -581,7 +581,7 @@ handle_logonly(char *msg, char **params, struct Server *server, time_t timestamp } void -handle(int rfd, struct Server *server) { +handle(struct Server *server) { time_t timestamp; char **params; char *cmd; @@ -594,7 +594,8 @@ handle(int rfd, struct Server *server) { * - a \0 is needed at the end, so 510 + 1 = 511 */ int i; - if (!read_line(rfd, buf, sizeof(buf))) { + memset(buf, '\0', sizeof(buf)); + if (!ircgets(server, buf, sizeof(buf))) { if (buf[0] == EOF || buf[0] == 3 || buf[0] == 4) { serv_disconnect(server, 1, "EOF"); hist_format(server->history, Activity_error, HIST_SHOW, diff --git a/src/hirc.h b/src/hirc.h @@ -42,6 +42,7 @@ void param_free(char **params); int param_len(char **params); char ** param_create(char *msg); int read_line(int fd, char *buf, size_t buf_len); +int ircgets(struct Server *server, char *buf, size_t buf_len); int ircprintf(struct Server *server, char *format, ...); char * homepath(char *path); char chrcmp(char c, char *s); @@ -109,7 +110,7 @@ void schedule_push(struct Server *server, char *tmsg, char *msg); char * schedule_pull(struct Server *server, char *tmsg); /* handle.c */ -void handle(int rfd, struct Server *server); +void handle(struct Server *server); void handle_expect(struct Server *server, enum Expect cmd, char *about); char * handle_expect_get(struct Server *server, enum Expect cmd); diff --git a/src/main.c b/src/main.c @@ -124,6 +124,30 @@ param_create(char *msg) { } int +ircgets(struct Server *server, char *buf, size_t buf_len) { + size_t i = 0; + char c = 0; + + do { +#ifdef TLS + if (server->tls) { + if (tls_read(server->tls_ctx, &c, sizeof(char)) != sizeof(char)) + return 0; + } else { +#endif /* TLS */ + if (read(server->rfd, &c, sizeof(char)) != sizeof(char)) + return 0; +#ifdef TLS + } +#endif /* TLS */ + if (c != '\r') + buf[i++] = c; + } while (c != '\n' && i < buf_len); + buf[i - 1] = '\0'; + return 1; +} + +int read_line(int fd, char *buf, size_t buf_len) { size_t i = 0; char c = 0; @@ -155,7 +179,12 @@ ircprintf(struct Server *server, char *format, ...) { return -1; } - ret = write(server->wfd, msg, strlen(msg)); +#ifdef TLS + if (server->tls) + ret = tls_write(server->tls_ctx, msg, strlen(msg)); + else + ret = write(server->wfd, msg, strlen(msg)); +#endif /* TLS */ if (ret == -1 && server->status == ConnStatus_connected) { serv_disconnect(server, 1, NULL); @@ -294,7 +323,7 @@ main(int argc, char *argv[]) { sp->pingsent = 0; sp->lastrecv = time(NULL); sp->rpollfd->revents = 0; - handle(sp->rfd, sp); + handle(sp); } else if (!sp->pingsent && sp->lastrecv && (time(NULL) - sp->lastrecv) >= pinginact) { /* haven't heard from server in pinginact seconds, sending a ping */ ircprintf(sp, "PING :ground control to Major Tom\r\n"); diff --git a/src/serv.c b/src/serv.c @@ -53,8 +53,12 @@ serv_free(struct Server *server) { free(p->value); } #ifdef TLS - if (server->tls) - tls_free(server->tls_ctx); + if (server->tls) { + if (server->tls_ctx) + tls_free(server->tls_ctx); + if (server->tls_conf) + tls_config_free(server->tls_conf); + } #endif /* TLS */ free(p); } @@ -63,7 +67,6 @@ struct Server * serv_create(char *name, char *host, char *port, char *nick, char *username, char *realname, int tls, int tls_verify) { struct Server *server; - struct tls_config *conf; int i; if (!name || !host || !port || !nick) @@ -103,14 +106,15 @@ serv_create(char *name, char *host, char *port, char *nick, #ifdef TLS server->tls = tls; server->tls_ctx = NULL; - if (server->tls && (conf = tls_config_new()) == NULL) { - ui_tls_config_error(conf, "tls_config_new()"); + server->tls_conf = NULL; + if (server->tls && (server->tls_conf = tls_config_new()) == NULL) { + ui_tls_config_error(server->tls_conf, "tls_config_new()"); server->tls = 0; } if (server->tls && !tls_verify) { - tls_config_insecure_noverifycert(conf); - tls_config_insecure_noverifyname(conf); + tls_config_insecure_noverifycert(server->tls_conf); + tls_config_insecure_noverifyname(server->tls_conf); } if (server->tls && (server->tls_ctx = tls_client()) == NULL) { @@ -118,13 +122,10 @@ serv_create(char *name, char *host, char *port, char *nick, server->tls = 0; } - if (server->tls && tls_configure(server->tls_ctx, conf) == -1) { + if (server->tls && tls_configure(server->tls_ctx, server->tls_conf) == -1) { ui_tls_error(server->tls_ctx, "tls_configure()"); server->tls = 0; } - - if (tls) - tls_config_free(conf); #else if (tls) hist_format(server->history, Activity_error, HIST_SHOW, @@ -256,11 +257,35 @@ serv_connect(struct Server *server) { goto fail; } - server->connectfail = 0; + freeaddrinfo(ai); server->rfd = server->wfd = fd; + server->connectfail = 0; hist_format(server->history, Activity_status, HIST_SHOW|HIST_MAIN, "SELF_CONNECTED %s %s %s", server->name, server->host, server->port); - freeaddrinfo(ai); + +#ifdef TLS + if (server->tls) { + if (tls_connect_socket(server->tls_ctx, fd, server->host) == -1) { + hist_format(server->history, Activity_error, HIST_SHOW, + "SELF_CONNECTLOST %s %s %s :%s", + server->name, server->host, server->port, tls_error(server->tls_ctx)); + goto fail; + } + + if (tls_peer_cert_provided(server->tls_ctx)) { + hist_format(server->history, Activity_status, HIST_SHOW, + "SELF_TLS_VERSION %s %s %s %s", + server->name, tls_conn_version(server->tls_ctx), + tls_conn_cipher_strength(server->tls_ctx), + tls_conn_cipher(server->tls_ctx)); + hist_format(server->history, Activity_status, HIST_SHOW, + "SELF_TLS_NAMES %s %s %s %s", + server->name, tls_conn_servername(server->tls_ctx), + tls_peer_cert_issuer(server->tls_ctx), + tls_peer_cert_subject(server->tls_ctx)); + } + } +#endif /* TLS */ ircprintf(server, "NICK %s\r\n", server->self->nick); ircprintf(server, "USER %s * * :%s\r\n", @@ -318,6 +343,8 @@ serv_disconnect(struct Server *server, int reconnect, char *msg) { if (msg) ircprintf(server, "QUIT %s\r\n", msg); + if (server->tls) + tls_close(server->tls_ctx); shutdown(server->rfd, SHUT_RDWR); shutdown(server->wfd, SHUT_RDWR); close(server->rfd); diff --git a/src/struct.h b/src/struct.h @@ -152,6 +152,7 @@ struct Server { #ifdef TLS int tls; struct tls *tls_ctx; + struct tls_config *tls_conf; #endif /* TLS */ struct Server *next; }; diff --git a/src/ui.c b/src/ui.c @@ -73,7 +73,10 @@ struct { {"SELF_LOOKUPFAIL", "format.ui.lookupfail"}, {"SELF_CONNECTFAIL", "format.ui.connectfail"}, #ifndef TLS - {"SELF_TLSNOTCOMPILED", "format.ui.tlsnotcompiled"}, + {"SELF_TLSNOTCOMPILED", "format.ui.tls.notcompiled"}, +#else + {"SELF_TLS_VERSION", "format.ui.tls.version"}, + {"SELF_TLS_NAMES", "format.ui.tls.names"}, #endif /* TLS */ {"SELF_KEYBIND_START", "format.ui.keybind.start"}, {"SELF_KEYBIND_LIST", "format.ui.keybind"},