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:
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"},