ii-2.0-tls.diff (4917B)
1 commit 6e349ab328266ab6a6beee31db2c7f97921d480f 2 Author: Jan Klemkow <j.klemkow@wemelug.de> 3 Date: Sun Oct 30 22:25:31 2022 +0100 4 5 add tls support 6 7 diff --git a/Makefile b/Makefile 8 index 28c7781..8c19387 100644 9 --- a/Makefile 10 +++ b/Makefile 11 @@ -12,7 +12,7 @@ OBJ = $(SRC:.c=.o) 12 13 # use system flags. 14 II_CFLAGS = $(CFLAGS) 15 -II_LDFLAGS = $(LDFLAGS) 16 +II_LDFLAGS = $(LDFLAGS) -ltls 17 18 # on systems which provide strlcpy(3), 19 # remove NEED_STRLCPY from CPPFLAGS and 20 diff --git a/ii.1 b/ii.1 21 index 59fd798..a51944e 100644 22 --- a/ii.1 23 +++ b/ii.1 24 @@ -3,6 +3,7 @@ 25 ii - irc it or irc improved 26 .SH SYNOPSIS 27 .B ii 28 +.RB [ -t ] 29 .B -s 30 .I host 31 .RB [ -p 32 @@ -18,6 +19,8 @@ ii - irc it or irc improved 33 .IR realname ] 34 .RB [ -k 35 .IR env_pass ] 36 +.RB [ -F 37 +.IR fingerprint ] 38 .SH DESCRIPTION 39 .B ii 40 is a minimalistic FIFO and filesystem based IRC client. 41 @@ -34,6 +37,9 @@ For example if you will join a channel just do echo "/j #channel" > in 42 and ii creates a new channel directory with in and out file. 43 .SH OPTIONS 44 .TP 45 +.BI -t 46 +TLS encrypted connection 47 +.TP 48 .BI -s " host" 49 server/host to connect to, for example: irc.freenode.net 50 .TP 51 @@ -60,6 +66,11 @@ lets you specify an environment variable that contains your IRC password, 52 e.g. IIPASS="foobar" ii -k IIPASS. 53 This is done in order to prevent other users from eavesdropping the server 54 password via the process list. 55 +.TP 56 +.BI -F " fingerprint" 57 +disables certificate and hostname verification. 58 +Just check the server's certificate fingerprint. 59 +This is recommended to connection to servers with self signed certificates. 60 .SH DIRECTORIES 61 .TP 62 .B ~/irc 63 diff --git a/ii.c b/ii.c 64 index c402a87..95819c5 100644 65 --- a/ii.c 66 +++ b/ii.c 67 @@ -20,6 +20,9 @@ 68 #include <time.h> 69 #include <unistd.h> 70 71 +#include <tls.h> 72 +struct tls *tls = NULL; 73 +int ircfd; 74 char *argv0; 75 76 #include "arg.h" 77 @@ -101,8 +104,9 @@ die(const char *fmt, ...) 78 static void 79 usage(void) 80 { 81 - die("usage: %s -s host [-p port | -u sockname] [-i ircdir]\n" 82 - " [-n nickname] [-f fullname] [-k env_pass]\n", argv0); 83 + die("usage: %s [-t] -s host [-p port | -u sockname] [-i ircdir]\n" 84 + " [-n nickname] [-f fullname] [-k env_pass] [-F fingerprint]\n", 85 + argv0); 86 } 87 88 static void 89 @@ -113,11 +117,17 @@ ewritestr(int fd, const char *s) 90 91 len = strlen(s); 92 for (off = 0; off < len; off += w) { 93 - if ((w = write(fd, s + off, len - off)) == -1) 94 + if (tls && (w = tls_write(tls, s + off, len - off)) == -1) 95 break; 96 + if (!tls && (w = write(fd, s + off, len - off)) == -1) 97 + break; 98 + } 99 + if (w == -1) { 100 + if (tls) 101 + die("%s: tls_write: %s\n", argv0, tls_error(tls)); 102 + else 103 + die("%s: write: %s\n", argv0, strerror(errno)); 104 } 105 - if (w == -1) 106 - die("%s: write: %s\n", argv0, strerror(errno)); 107 } 108 109 /* creates directories bottom-up, if necessary */ 110 @@ -686,8 +696,15 @@ read_line(int fd, char *buf, size_t bufsiz) 111 char c = '\0'; 112 113 do { 114 - if (read(fd, &c, sizeof(char)) != sizeof(char)) 115 - return -1; 116 + if (tls && fd == ircfd) { 117 + if (tls_read(tls, &c, sizeof(c)) == -1) { 118 + die(""); 119 + return -1; 120 + } 121 + } else { 122 + if (read(fd, &c, sizeof(char)) != sizeof(char)) 123 + return -1; 124 + } 125 buf[i++] = c; 126 } while (c != '\n' && i < bufsiz); 127 buf[i - 1] = '\0'; /* eliminates '\n' */ 128 @@ -798,8 +815,9 @@ main(int argc, char *argv[]) 129 struct passwd *spw; 130 const char *key = NULL, *fullname = NULL, *host = ""; 131 const char *uds = NULL, *service = "6667"; 132 - char prefix[PATH_MAX]; 133 - int ircfd, r; 134 + char prefix[PATH_MAX], *fingerprint = NULL; 135 + int r; 136 + struct tls_config *tls_config = NULL; 137 138 /* use nickname and home dir of user by default */ 139 if (!(spw = getpwuid(getuid()))) 140 @@ -827,6 +845,16 @@ main(int argc, char *argv[]) 141 case 's': 142 host = EARGF(usage()); 143 break; 144 + case 't': 145 + if (tls != NULL) 146 + break; 147 + 148 + if ((tls = tls_client()) == NULL) 149 + die("%s: tls_client\n", argv0); 150 + break; 151 + case 'F': 152 + fingerprint = EARGF(usage()); 153 + break; 154 case 'u': 155 uds = EARGF(usage()); 156 break; 157 @@ -843,6 +871,22 @@ main(int argc, char *argv[]) 158 else 159 ircfd = tcpopen(host, service); 160 161 + if (tls && (tls_config = tls_config_new()) == NULL) 162 + die("%s: tls_config_new\n", argv0); 163 + if (tls && fingerprint) { 164 + /* Just check cert fingerprint and no CA chain or cert name. */ 165 + tls_config_insecure_noverifycert(tls_config); 166 + tls_config_insecure_noverifyname(tls_config); 167 + } 168 + if (tls && tls_configure(tls, tls_config) == -1) 169 + die("%s: tls_configure\n", argv0); 170 + if (tls && tls_connect_socket(tls, ircfd, host) == -1) 171 + die("%s: tls_connect_socket: %s\n", argv0, tls_error(tls)); 172 + if (tls && tls_handshake(tls) == -1) 173 + die("%s: tls_handshake: %s\n", argv0, tls_error(tls)); 174 + if (tls && fingerprint && strcmp(fingerprint, tls_peer_cert_hash(tls)) != 0) 175 + die("%s: wrong fingerprint: %s\n", argv0, tls_peer_cert_hash(tls)); 176 + 177 #ifdef __OpenBSD__ 178 /* OpenBSD pledge(2) support */ 179 if (pledge("stdio rpath wpath cpath dpath", NULL) == -1)