ii-2.0-ssl.diff (10577B)
1 From 20b47a9dbf4c8299f01d0d73f112ece58da8cabb Mon Sep 17 00:00:00 2001 2 From: Jon Eskin <eskinjp@gmail.com> 3 Date: Wed, 4 Jan 2023 06:20:19 -0500 4 Subject: [PATCH] porting ssl patch to 2.0 5 6 --- 7 Makefile | 2 +- 8 ii.1 | 5 ++ 9 ii.c | 156 ++++++++++++++++++++++++++++++++++++++++++------------- 10 3 files changed, 125 insertions(+), 38 deletions(-) 11 12 diff --git a/Makefile b/Makefile 13 index 28c7781..23db7c1 100644 14 --- a/Makefile 15 +++ b/Makefile 16 @@ -12,7 +12,7 @@ OBJ = $(SRC:.c=.o) 17 18 # use system flags. 19 II_CFLAGS = $(CFLAGS) 20 -II_LDFLAGS = $(LDFLAGS) 21 +II_LDFLAGS = $(LDFLAGS) -lssl -lcrypto 22 23 # on systems which provide strlcpy(3), 24 # remove NEED_STRLCPY from CPPFLAGS and 25 diff --git a/ii.1 b/ii.1 26 index 59fd798..3ddc376 100644 27 --- a/ii.1 28 +++ b/ii.1 29 @@ -7,6 +7,8 @@ ii - irc it or irc improved 30 .I host 31 .RB [ -p 32 .I port 33 +.RB [ \-e 34 +.IR ssl ] 35 | 36 .B -u 37 .IR sockname ] 38 @@ -40,6 +42,9 @@ server/host to connect to, for example: irc.freenode.net 39 .BI -p " port" 40 lets you override the default port (6667) 41 .TP 42 +.BI \-e " ssl" 43 +lets you connect using ssl encryption. The default ssl port is 6697. 44 +.TP 45 .BI -u " sockname" 46 connect to a UNIX domain socket instead of directly to a server. 47 If set, the 48 diff --git a/ii.c b/ii.c 49 index c402a87..6de4157 100644 50 --- a/ii.c 51 +++ b/ii.c 52 @@ -20,6 +20,10 @@ 53 #include <time.h> 54 #include <unistd.h> 55 56 +#include <openssl/rand.h> 57 +#include <openssl/ssl.h> 58 +#include <openssl/err.h> 59 + 60 char *argv0; 61 62 #include "arg.h" 63 @@ -43,6 +47,14 @@ struct Channel { 64 Channel *next; 65 }; 66 67 +typedef struct { 68 + int use_ssl; 69 + int irc; 70 + SSL *sslHandle; 71 + SSL_CTX *sslContext; 72 +} conn; 73 + 74 + 75 static Channel * channel_add(const char *); 76 static Channel * channel_find(const char *); 77 static Channel * channel_join(const char *); 78 @@ -57,21 +69,24 @@ static void channel_rm(Channel *); 79 static void cleanup(void); 80 static void create_dirtree(const char *); 81 static void create_filepath(char *, size_t, const char *, const char *, const char *); 82 +static int swrite(conn *, const char *, size_t); 83 +static void ewritestr(conn *, const char *); 84 +static void handle_channels_input(conn *, Channel *); 85 +static void handle_server_output(conn *); 86 static void die(const char *, ...); 87 -static void ewritestr(int, const char *); 88 -static void handle_channels_input(int, Channel *); 89 -static void handle_server_output(int); 90 static int isnumeric(const char *); 91 -static void loginkey(int, const char *); 92 -static void loginuser(int, const char *, const char *); 93 -static void proc_channels_input(int, Channel *, char *); 94 -static void proc_channels_privmsg(int, Channel *, char *); 95 -static void proc_server_cmd(int, char *); 96 -static int read_line(int, char *, size_t); 97 -static void run(int, const char *); 98 +static void loginkey(conn *, const char *); 99 +static void loginuser(conn *, const char *, const char *); 100 +static void proc_channels_input(conn *, Channel *, char *); 101 +static void proc_channels_privmsg(conn *, Channel *, char *); 102 +static void proc_server_cmd(conn *, char *); 103 +static int sread(conn *, char *, size_t); 104 +static int read_line(conn *, char *, size_t); 105 +static int read_line_from_channel(int, char *, size_t); 106 +static void run(conn *, const char *); 107 static void setup(void); 108 static void sighandler(int); 109 -static int tcpopen(const char *, const char *); 110 +static void tcpopen(conn *ircfd, const char *, const char *); 111 static size_t tokenize(char **, size_t, char *, int); 112 static int udsopen(const char *); 113 static void usage(void); 114 @@ -102,18 +117,27 @@ static void 115 usage(void) 116 { 117 die("usage: %s -s host [-p port | -u sockname] [-i ircdir]\n" 118 - " [-n nickname] [-f fullname] [-k env_pass]\n", argv0); 119 + " [-e <ssl>] [-n nickname] [-f fullname] [-k env_pass]\n", argv0); 120 +} 121 + 122 +static int 123 +swrite(conn *ircfd, const char *msg, size_t len) 124 +{ 125 + if (ircfd->use_ssl) 126 + return SSL_write(ircfd->sslHandle, msg, len); 127 + 128 + return write(ircfd->irc, msg, len); 129 } 130 131 static void 132 -ewritestr(int fd, const char *s) 133 +ewritestr(conn *fd, const char *s) 134 { 135 size_t len, off = 0; 136 int w = -1; 137 138 len = strlen(s); 139 for (off = 0; off < len; off += w) { 140 - if ((w = write(fd, s + off, len - off)) == -1) 141 + if ((w = swrite(fd, s + off, len - off)) == -1) 142 break; 143 } 144 if (w == -1) 145 @@ -185,6 +209,7 @@ cleanup(void) 146 tmp = c->next; 147 channel_leave(c); 148 } 149 + 150 } 151 152 static void 153 @@ -341,14 +366,14 @@ channel_leave(Channel *c) 154 } 155 156 static void 157 -loginkey(int ircfd, const char *key) 158 +loginkey(conn *ircfd, const char *key) 159 { 160 snprintf(msg, sizeof(msg), "PASS %s\r\n", key); 161 ewritestr(ircfd, msg); 162 } 163 164 static void 165 -loginuser(int ircfd, const char *host, const char *fullname) 166 +loginuser(conn *ircfd, const char *host, const char *fullname) 167 { 168 snprintf(msg, sizeof(msg), "NICK %s\r\nUSER %s localhost %s :%s\r\n", 169 nick, nick, host, fullname); 170 @@ -377,12 +402,15 @@ udsopen(const char *uds) 171 return fd; 172 } 173 174 -static int 175 -tcpopen(const char *host, const char *service) 176 +static void 177 +tcpopen(conn *ircfd, const char *host, const char *service) 178 { 179 struct addrinfo hints, *res = NULL, *rp; 180 int fd = -1, e; 181 182 + ircfd->sslHandle = NULL; 183 + ircfd->sslContext = NULL; 184 + 185 memset(&hints, 0, sizeof(hints)); 186 hints.ai_family = AF_UNSPEC; /* allow IPv4 or IPv6 */ 187 hints.ai_flags = AI_NUMERICSERV; /* avoid name lookup for port */ 188 @@ -407,7 +435,19 @@ tcpopen(const char *host, const char *service) 189 argv0, host, service, strerror(errno)); 190 191 freeaddrinfo(res); 192 - return fd; 193 + ircfd->irc = fd; 194 + if (!ircfd->use_ssl) 195 + return; 196 + 197 + //SSL_load_error_strings(); 198 + //SSL_library_init(); 199 + ircfd->sslContext = SSL_CTX_new(SSLv23_client_method()); 200 + if (ircfd->sslContext == NULL) 201 + ERR_print_errors_fp(stderr); 202 + ircfd->sslHandle = SSL_new(ircfd->sslContext); 203 + if (!SSL_set_fd(ircfd->sslHandle, ircfd->irc) || 204 + (SSL_connect(ircfd->sslHandle) != 1)) 205 + ERR_print_errors_fp(stderr); 206 } 207 208 static int 209 @@ -459,7 +499,7 @@ channel_print(Channel *c, const char *buf) 210 } 211 212 static void 213 -proc_channels_privmsg(int ircfd, Channel *c, char *buf) 214 +proc_channels_privmsg(conn *ircfd, Channel *c, char *buf) 215 { 216 snprintf(msg, sizeof(msg), "<%s> %s", nick, buf); 217 channel_print(c, msg); 218 @@ -468,7 +508,7 @@ proc_channels_privmsg(int ircfd, Channel *c, char *buf) 219 } 220 221 static void 222 -proc_channels_input(int ircfd, Channel *c, char *buf) 223 +proc_channels_input(conn *ircfd, Channel *c, char *buf) 224 { 225 char *p = NULL; 226 size_t buflen; 227 @@ -560,7 +600,7 @@ proc_channels_input(int ircfd, Channel *c, char *buf) 228 } 229 230 static void 231 -proc_server_cmd(int fd, char *buf) 232 +proc_server_cmd(conn *fd, char *buf) 233 { 234 Channel *c; 235 const char *channel; 236 @@ -679,8 +719,33 @@ proc_server_cmd(int fd, char *buf) 237 channel_print(c, msg); 238 } 239 240 + 241 +static int 242 +sread(conn *fd, char *buf, size_t bufsize) 243 +{ 244 + if (fd->use_ssl) 245 + return SSL_read(fd->sslHandle, buf, bufsize); 246 + 247 + return read(fd->irc, buf, bufsize); 248 +} 249 + 250 static int 251 -read_line(int fd, char *buf, size_t bufsiz) 252 +read_line(conn *fd, char *buf, size_t bufsiz) 253 +{ 254 + size_t i = 0; 255 + char c = '\0'; 256 + 257 + do { 258 + if (sread(fd, &c, sizeof(char)) != sizeof(char)) 259 + return -1; 260 + buf[i++] = c; 261 + } while (c != '\n' && i < bufsiz); 262 + buf[i - 1] = '\0'; /* eliminates '\n' */ 263 + return 0; 264 +} 265 + 266 +static int 267 +read_line_from_channel(int fd, char *buf, size_t bufsiz) 268 { 269 size_t i = 0; 270 char c = '\0'; 271 @@ -695,7 +760,7 @@ read_line(int fd, char *buf, size_t bufsiz) 272 } 273 274 static void 275 -handle_channels_input(int ircfd, Channel *c) 276 +handle_channels_input(conn *ircfd, Channel *c) 277 { 278 /* 279 * Do not allow to read this fully, since commands will be 280 @@ -706,7 +771,7 @@ handle_channels_input(int ircfd, Channel *c) 281 */ 282 char buf[IRC_MSG_MAX-64]; 283 284 - if (read_line(c->fdin, buf, sizeof(buf)) == -1) { 285 + if (read_line_from_channel(c->fdin, buf, sizeof(buf)) == -1) { 286 if (channel_reopen(c) == -1) 287 channel_rm(c); 288 return; 289 @@ -715,7 +780,7 @@ handle_channels_input(int ircfd, Channel *c) 290 } 291 292 static void 293 -handle_server_output(int ircfd) 294 +handle_server_output(conn *ircfd) 295 { 296 char buf[IRC_MSG_MAX]; 297 298 @@ -746,7 +811,7 @@ setup(void) 299 } 300 301 static void 302 -run(int ircfd, const char *host) 303 +run(conn *ircfd, const char *host) 304 { 305 Channel *c, *tmp; 306 fd_set rdset; 307 @@ -756,9 +821,9 @@ run(int ircfd, const char *host) 308 309 snprintf(ping_msg, sizeof(ping_msg), "PING %s\r\n", host); 310 while (isrunning) { 311 - maxfd = ircfd; 312 + maxfd = ircfd->irc; 313 FD_ZERO(&rdset); 314 - FD_SET(ircfd, &rdset); 315 + FD_SET(ircfd->irc, &rdset); 316 for (c = channels; c; c = c->next) { 317 if (c->fdin > maxfd) 318 maxfd = c->fdin; 319 @@ -780,7 +845,7 @@ run(int ircfd, const char *host) 320 ewritestr(ircfd, ping_msg); 321 continue; 322 } 323 - if (FD_ISSET(ircfd, &rdset)) { 324 + if (FD_ISSET(ircfd->irc, &rdset)) { 325 handle_server_output(ircfd); 326 last_response = time(NULL); 327 } 328 @@ -797,9 +862,12 @@ main(int argc, char *argv[]) 329 { 330 struct passwd *spw; 331 const char *key = NULL, *fullname = NULL, *host = ""; 332 - const char *uds = NULL, *service = "6667"; 333 + const char *uds = NULL; 334 + const char *service = "6667"; 335 + const char *sservice = "6697"; 336 char prefix[PATH_MAX]; 337 - int ircfd, r; 338 + int r, defaultPort = 1; 339 + conn ircfd; 340 341 /* use nickname and home dir of user by default */ 342 if (!(spw = getpwuid(getuid()))) 343 @@ -823,6 +891,7 @@ main(int argc, char *argv[]) 344 break; 345 case 'p': 346 service = EARGF(usage()); 347 + defaultPort = 0; 348 break; 349 case 's': 350 host = EARGF(usage()); 351 @@ -830,6 +899,11 @@ main(int argc, char *argv[]) 352 case 'u': 353 uds = EARGF(usage()); 354 break; 355 + case 'e': 356 + if (defaultPort) 357 + service = sservice; 358 + ircfd.use_ssl = 1; 359 + break; 360 default: 361 usage(); 362 break; 363 @@ -839,9 +913,9 @@ main(int argc, char *argv[]) 364 usage(); 365 366 if (uds) 367 - ircfd = udsopen(uds); 368 + ircfd.irc = udsopen(uds); 369 else 370 - ircfd = tcpopen(host, service); 371 + tcpopen(&ircfd, host, service); 372 373 #ifdef __OpenBSD__ 374 /* OpenBSD pledge(2) support */ 375 @@ -856,11 +930,19 @@ main(int argc, char *argv[]) 376 377 channelmaster = channel_add(""); /* master channel */ 378 if (key) 379 - loginkey(ircfd, key); 380 - loginuser(ircfd, host, fullname && *fullname ? fullname : nick); 381 + loginkey(&ircfd, key); 382 + loginuser(&ircfd, host, fullname && *fullname ? fullname : nick); 383 setup(); 384 - run(ircfd, host); 385 + run(&ircfd, host); 386 cleanup(); 387 388 + if (ircfd.use_ssl) { 389 + SSL_shutdown(ircfd.sslHandle); 390 + SSL_free(ircfd.sslHandle); 391 + SSL_CTX_free(ircfd.sslContext); 392 + } 393 + 394 + close(ircfd.irc); 395 + 396 return 0; 397 } 398 -- 399 2.39.0 400