sites

public wiki contents of suckless.org
git clone git://git.suckless.org/sites
Log | Files | Refs

ii-ssl-20200811-ecf3902.diff (21310B)


      1 From 68d3498bb0ce639875c5927a618567231b500d61 Mon Sep 17 00:00:00 2001
      2 From: Alexandre Hannedouche <hannedouche.alex@gmail.com>
      3 Date: Tue, 11 Aug 2020 22:51:08 +0200
      4 Subject: [PATCH] porting ssh patch to 1.8
      5 
      6 ---
      7  config.mk |   2 +-
      8  ii.1      |   5 ++
      9  ii.c      | 154 +++++++++++++++++++++++++++++++++++++++++-------------
     10  3 files changed, 123 insertions(+), 38 deletions(-)
     11 
     12 diff --git a/config.mk b/config.mk
     13 index 957bae0..9becc42 100644
     14 --- a/config.mk
     15 +++ b/config.mk
     16 @@ -10,5 +10,5 @@ DOCPREFIX = ${PREFIX}/share/doc
     17  # remove NEED_STRLCPY from CFLAGS and
     18  # remove strlcpy.o from LIBS
     19  CFLAGS   = -DNEED_STRLCPY -Os
     20 -LDFLAGS  = -s
     21 +LDFLAGS  = -s -lssl -lcrypto
     22  LIBS     = strlcpy.o
     23 diff --git a/ii.1 b/ii.1
     24 index 8e06af7..6d7704c 100644
     25 --- a/ii.1
     26 +++ b/ii.1
     27 @@ -21,6 +21,8 @@ and ii creates a new channel directory with in and out file.
     28  .IR servername >
     29  .RB [ \-p
     30  .IR port ]
     31 +.RB [ \-e
     32 +.IR ssl ]
     33  .RB [ \-k
     34  .IR "environment variable" ]
     35  .RB [ \-i
     36 @@ -42,6 +44,9 @@ connect to a UNIX domain socket instead of directly to a server.
     37  .BI \-p " port"
     38  lets you override the default port (6667)
     39  .TP
     40 +.BI \-e " ssl"
     41 +lets you connect using ssl encryption. The default ssl port is 6697.
     42 +.TP
     43  .BI \-k " environment variable"
     44  lets you specify an environment variable that contains your IRC password, e.g. IIPASS="foobar" ii -k IIPASS.
     45  This is done in order to prevent other users from eavesdropping the server password via the process list.
     46 diff --git a/ii.c b/ii.c
     47 index 426fcff..9a09135 100644
     48 --- a/ii.c
     49 +++ b/ii.c
     50 @@ -20,6 +20,10 @@
     51  #include <time.h>
     52  #include <unistd.h>
     53  
     54 +#include <openssl/rand.h>
     55 +#include <openssl/ssl.h>
     56 +#include <openssl/err.h>
     57 +
     58  char *argv0;
     59  
     60  #include "arg.h"
     61 @@ -43,6 +47,13 @@ struct Channel {
     62  	Channel *next;
     63  };
     64  
     65 +typedef struct {
     66 +	int use_ssl;
     67 +	int irc;
     68 +	SSL *sslHandle;
     69 +	SSL_CTX *sslContext;
     70 +} conn;
     71 +
     72  static Channel * channel_add(const char *);
     73  static Channel * channel_find(const char *);
     74  static Channel * channel_join(const char *);
     75 @@ -56,20 +67,23 @@ static int       channel_reopen(Channel *);
     76  static void      channel_rm(Channel *);
     77  static void      create_dirtree(const char *);
     78  static void      create_filepath(char *, size_t, const char *, const char *, const char *);
     79 -static void      ewritestr(int, const char *);
     80 -static void      handle_channels_input(int, Channel *);
     81 -static void      handle_server_output(int);
     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 int       isnumeric(const char *);
     87 -static void      loginkey(int, const char *);
     88 -static void      loginuser(int, const char *, const char *);
     89 -static void      proc_channels_input(int, Channel *, char *);
     90 -static void      proc_channels_privmsg(int, Channel *, char *);
     91 -static void      proc_server_cmd(int, char *);
     92 -static int       read_line(int, char *, size_t);
     93 -static void      run(int, const char *);
     94 +static void      loginkey(conn *, const char *);
     95 +static void      loginuser(conn *, const char *, const char *);
     96 +static void      proc_channels_input(conn *, Channel *, char *);
     97 +static void      proc_channels_privmsg(conn *, Channel *, char *);
     98 +static void      proc_server_cmd(conn *, char *);
     99 +static int       sread(conn *, char *, size_t);
    100 +static int       read_line(conn *, char *, size_t);
    101 +static int       read_line_from_channel(int, char *, size_t);
    102 +static void      run(conn *, const char *);
    103  static void      setup(void);
    104  static void      sighandler(int);
    105 -static int       tcpopen(const char *, const char *);
    106 +static void      tcpopen(conn *ircfd, const char *, const char *);
    107  static size_t    tokenize(char **, size_t, char *, int);
    108  static int       udsopen(const char *);
    109  static void      usage(void);
    110 @@ -87,20 +101,29 @@ static void
    111  usage(void)
    112  {
    113  	fprintf(stderr, "usage: %s <-s host> [-i <irc dir>] [-p <port>] "
    114 -	        "[-u <sockname>] [-n <nick>] [-k <password>] "
    115 +		"[-e <ssl>] [-u <sockname>] [-n <nick>] [-k <password>] "
    116  	        "[-f <fullname>]\n", argv0);
    117  	exit(1);
    118  }
    119  
    120 +static int
    121 +swrite(conn *ircfd, const char *msg, size_t len)
    122 +{
    123 +	if (ircfd->use_ssl)
    124 +		return SSL_write(ircfd->sslHandle, msg, len);
    125 +
    126 +	return write(ircfd->irc, msg, len);
    127 +}
    128 +
    129  static void
    130 -ewritestr(int fd, const char *s)
    131 +ewritestr(conn *fd, const char *s)
    132  {
    133  	size_t len, off = 0;
    134  	int w = -1;
    135  
    136  	len = strlen(s);
    137  	for (off = 0; off < len; off += w) {
    138 -		if ((w = write(fd, s + off, len - off)) == -1)
    139 +		if ((w = swrite(fd, s + off, len - off)) == -1)
    140  			break;
    141  	}
    142  	if (w == -1) {
    143 @@ -319,14 +342,14 @@ channel_leave(Channel *c)
    144  }
    145  
    146  static void
    147 -loginkey(int ircfd, const char *key)
    148 +loginkey(conn *ircfd, const char *key)
    149  {
    150  	snprintf(msg, sizeof(msg), "PASS %s\r\n", key);
    151  	ewritestr(ircfd, msg);
    152  }
    153  
    154  static void
    155 -loginuser(int ircfd, const char *host, const char *fullname)
    156 +loginuser(conn *ircfd, const char *host, const char *fullname)
    157  {
    158  	snprintf(msg, sizeof(msg), "NICK %s\r\nUSER %s localhost %s :%s\r\n",
    159  	         nick, nick, host, fullname);
    160 @@ -359,12 +382,15 @@ udsopen(const char *uds)
    161  	return fd;
    162  }
    163  
    164 -static int
    165 -tcpopen(const char *host, const char *service)
    166 +static void
    167 +tcpopen(conn *ircfd, const char *host, const char *service)
    168  {
    169  	struct addrinfo hints, *res = NULL, *rp;
    170  	int fd = -1, e;
    171  
    172 +	ircfd->sslHandle = NULL;
    173 +	ircfd->sslContext = NULL;
    174 +
    175  	memset(&hints, 0, sizeof(hints));
    176  	hints.ai_family = AF_UNSPEC; /* allow IPv4 or IPv6 */
    177  	hints.ai_flags = AI_NUMERICSERV; /* avoid name lookup for port */
    178 @@ -393,7 +419,19 @@ tcpopen(const char *host, const char *service)
    179  	}
    180  
    181  	freeaddrinfo(res);
    182 -	return fd;
    183 +	ircfd->irc = fd;
    184 +	if (!ircfd->use_ssl)
    185 +		return;
    186 +
    187 +	//SSL_load_error_strings();
    188 +	//SSL_library_init();
    189 +	ircfd->sslContext = SSL_CTX_new(SSLv23_client_method());
    190 +	if (ircfd->sslContext == NULL)
    191 +		ERR_print_errors_fp(stderr);
    192 +	ircfd->sslHandle = SSL_new(ircfd->sslContext);
    193 +	if (!SSL_set_fd(ircfd->sslHandle, ircfd->irc) ||
    194 +	    (SSL_connect(ircfd->sslHandle) != 1))
    195 +		ERR_print_errors_fp(stderr);
    196  }
    197  
    198  static int
    199 @@ -445,7 +483,7 @@ channel_print(Channel *c, const char *buf)
    200  }
    201  
    202  static void
    203 -proc_channels_privmsg(int ircfd, Channel *c, char *buf)
    204 +proc_channels_privmsg(conn *ircfd, Channel *c, char *buf)
    205  {
    206  	snprintf(msg, sizeof(msg), "<%s> %s", nick, buf);
    207  	channel_print(c, msg);
    208 @@ -454,7 +492,7 @@ proc_channels_privmsg(int ircfd, Channel *c, char *buf)
    209  }
    210  
    211  static void
    212 -proc_channels_input(int ircfd, Channel *c, char *buf)
    213 +proc_channels_input(conn *ircfd, Channel *c, char *buf)
    214  {
    215  	char *p = NULL;
    216  	size_t buflen;
    217 @@ -546,7 +584,7 @@ proc_channels_input(int ircfd, Channel *c, char *buf)
    218  }
    219  
    220  static void
    221 -proc_server_cmd(int fd, char *buf)
    222 +proc_server_cmd(conn *fd, char *buf)
    223  {
    224  	Channel *c;
    225  	const char *channel;
    226 @@ -665,8 +703,33 @@ proc_server_cmd(int fd, char *buf)
    227  		channel_print(c, msg);
    228  }
    229  
    230 +
    231 +static int
    232 +sread(conn *fd, char *buf, size_t bufsize)
    233 +{
    234 +	if (fd->use_ssl)
    235 +		return SSL_read(fd->sslHandle, buf, bufsize);
    236 +
    237 +	return read(fd->irc, buf, bufsize);
    238 +}
    239 +
    240 +static int
    241 +read_line(conn *fd, char *buf, size_t bufsiz)
    242 +{
    243 +	size_t i = 0;
    244 +	char c = '\0';
    245 +
    246 +	do {
    247 +		if (sread(fd, &c, sizeof(char)) != sizeof(char))
    248 +			return -1;
    249 +		buf[i++] = c;
    250 +	} while (c != '\n' && i < bufsiz);
    251 +	buf[i - 1] = '\0'; /* eliminates '\n' */
    252 +	return 0;
    253 +}
    254 +
    255  static int
    256 -read_line(int fd, char *buf, size_t bufsiz)
    257 +read_line_from_channel(int fd, char *buf, size_t bufsiz)
    258  {
    259  	size_t i = 0;
    260  	char c = '\0';
    261 @@ -681,11 +744,11 @@ read_line(int fd, char *buf, size_t bufsiz)
    262  }
    263  
    264  static void
    265 -handle_channels_input(int ircfd, Channel *c)
    266 +handle_channels_input(conn *ircfd, Channel *c)
    267  {
    268  	char buf[IRC_MSG_MAX];
    269  
    270 -	if (read_line(c->fdin, buf, sizeof(buf)) == -1) {
    271 +	if (read_line_from_channel(c->fdin, buf, sizeof(buf)) == -1) {
    272  		if (channel_reopen(c) == -1)
    273  			channel_rm(c);
    274  		return;
    275 @@ -694,7 +757,7 @@ handle_channels_input(int ircfd, Channel *c)
    276  }
    277  
    278  static void
    279 -handle_server_output(int ircfd)
    280 +handle_server_output(conn *ircfd)
    281  {
    282  	char buf[IRC_MSG_MAX];
    283  
    284 @@ -727,7 +790,7 @@ setup(void)
    285  }
    286  
    287  static void
    288 -run(int ircfd, const char *host)
    289 +run(conn *ircfd, const char *host)
    290  {
    291  	Channel *c, *tmp;
    292  	fd_set rdset;
    293 @@ -737,9 +800,9 @@ run(int ircfd, const char *host)
    294  
    295  	snprintf(ping_msg, sizeof(ping_msg), "PING %s\r\n", host);
    296  	while (isrunning) {
    297 -		maxfd = ircfd;
    298 +		maxfd = ircfd->irc;
    299  		FD_ZERO(&rdset);
    300 -		FD_SET(ircfd, &rdset);
    301 +		FD_SET(ircfd->irc, &rdset);
    302  		for (c = channels; c; c = c->next) {
    303  			if (c->fdin > maxfd)
    304  				maxfd = c->fdin;
    305 @@ -761,7 +824,7 @@ run(int ircfd, const char *host)
    306  			ewritestr(ircfd, ping_msg);
    307  			continue;
    308  		}
    309 -		if (FD_ISSET(ircfd, &rdset)) {
    310 +		if (FD_ISSET(ircfd->irc, &rdset)) {
    311  			handle_server_output(ircfd);
    312  			last_response = time(NULL);
    313  		}
    314 @@ -779,9 +842,12 @@ main(int argc, char *argv[])
    315  	Channel *c, *tmp;
    316  	struct passwd *spw;
    317  	const char *key = NULL, *fullname = NULL, *host = "";
    318 -	const char *uds = NULL, *service = "6667";
    319 +	const char *uds = NULL;
    320 +	const char *service = "6667";
    321 +	const char *sservice = "6697";
    322  	char prefix[PATH_MAX];
    323 -	int ircfd, r;
    324 +	int r, defaultPort = 1;
    325 +	conn ircfd;
    326  
    327  	/* use nickname and home dir of user by default */
    328  	if (!(spw = getpwuid(getuid()))) {
    329 @@ -806,6 +872,7 @@ main(int argc, char *argv[])
    330  		break;
    331  	case 'p':
    332  		service = EARGF(usage());
    333 +		defaultPort = 0;
    334  		break;
    335  	case 's':
    336  		host = EARGF(usage());
    337 @@ -813,6 +880,11 @@ main(int argc, char *argv[])
    338  	case 'u':
    339  		uds = EARGF(usage());
    340  		break;
    341 +	case 'e':
    342 +		if (defaultPort)
    343 +			service = sservice;
    344 +		ircfd.use_ssl = 1;
    345 +		break;
    346  	default:
    347  		usage();
    348  		break;
    349 @@ -822,9 +894,9 @@ main(int argc, char *argv[])
    350  		usage();
    351  
    352  	if (uds)
    353 -		ircfd = udsopen(uds);
    354 +		ircfd.irc = udsopen(uds);
    355  	else
    356 -		ircfd = tcpopen(host, service);
    357 +		tcpopen(&ircfd, host, service);
    358  
    359  #ifdef __OpenBSD__
    360  	/* OpenBSD pledge(2) support */
    361 @@ -843,10 +915,10 @@ main(int argc, char *argv[])
    362  
    363  	channelmaster = channel_add(""); /* master channel */
    364  	if (key)
    365 -		loginkey(ircfd, key);
    366 -	loginuser(ircfd, host, fullname && *fullname ? fullname : nick);
    367 +		loginkey(&ircfd, key);
    368 +	loginuser(&ircfd, host, fullname && *fullname ? fullname : nick);
    369  	setup();
    370 -	run(ircfd, host);
    371 +	run(&ircfd, host);
    372  	if (channelmaster)
    373  		channel_leave(channelmaster);
    374  
    375 @@ -855,5 +927,13 @@ main(int argc, char *argv[])
    376  		channel_leave(c);
    377  	}
    378  
    379 +	if (ircfd.use_ssl) {
    380 +		SSL_shutdown(ircfd.sslHandle);
    381 +		SSL_free(ircfd.sslHandle);
    382 +		SSL_CTX_free(ircfd.sslContext);
    383 +	}
    384 +
    385 +	close(ircfd.irc);
    386 +
    387  	return 0;
    388  }
    389 -- 
    390 2.28.0
    391 
    392 From 6c237478845fa047a5f414f9c032b2674da8f30b Mon Sep 17 00:00:00 2001
    393 From: Alexandre Hannedouche <hannedouche.alex@gmail.com>
    394 Date: Tue, 11 Aug 2020 22:51:08 +0200
    395 Subject: [PATCH] porting ssl patch to 1.8
    396 
    397 ---
    398  config.mk |   2 +-
    399  ii.1      |   5 ++
    400  ii.c      | 154 +++++++++++++++++++++++++++++++++++++++++-------------
    401  3 files changed, 123 insertions(+), 38 deletions(-)
    402 
    403 diff --git a/config.mk b/config.mk
    404 index 957bae0..9becc42 100644
    405 --- a/config.mk
    406 +++ b/config.mk
    407 @@ -10,5 +10,5 @@ DOCPREFIX = ${PREFIX}/share/doc
    408  # remove NEED_STRLCPY from CFLAGS and
    409  # remove strlcpy.o from LIBS
    410  CFLAGS   = -DNEED_STRLCPY -Os
    411 -LDFLAGS  = -s
    412 +LDFLAGS  = -s -lssl -lcrypto
    413  LIBS     = strlcpy.o
    414 diff --git a/ii.1 b/ii.1
    415 index 8e06af7..6d7704c 100644
    416 --- a/ii.1
    417 +++ b/ii.1
    418 @@ -21,6 +21,8 @@ and ii creates a new channel directory with in and out file.
    419  .IR servername >
    420  .RB [ \-p
    421  .IR port ]
    422 +.RB [ \-e
    423 +.IR ssl ]
    424  .RB [ \-k
    425  .IR "environment variable" ]
    426  .RB [ \-i
    427 @@ -42,6 +44,9 @@ connect to a UNIX domain socket instead of directly to a server.
    428  .BI \-p " port"
    429  lets you override the default port (6667)
    430  .TP
    431 +.BI \-e " ssl"
    432 +lets you connect using ssl encryption. The default ssl port is 6697.
    433 +.TP
    434  .BI \-k " environment variable"
    435  lets you specify an environment variable that contains your IRC password, e.g. IIPASS="foobar" ii -k IIPASS.
    436  This is done in order to prevent other users from eavesdropping the server password via the process list.
    437 diff --git a/ii.c b/ii.c
    438 index 426fcff..9a09135 100644
    439 --- a/ii.c
    440 +++ b/ii.c
    441 @@ -20,6 +20,10 @@
    442  #include <time.h>
    443  #include <unistd.h>
    444  
    445 +#include <openssl/rand.h>
    446 +#include <openssl/ssl.h>
    447 +#include <openssl/err.h>
    448 +
    449  char *argv0;
    450  
    451  #include "arg.h"
    452 @@ -43,6 +47,13 @@ struct Channel {
    453  	Channel *next;
    454  };
    455  
    456 +typedef struct {
    457 +	int use_ssl;
    458 +	int irc;
    459 +	SSL *sslHandle;
    460 +	SSL_CTX *sslContext;
    461 +} conn;
    462 +
    463  static Channel * channel_add(const char *);
    464  static Channel * channel_find(const char *);
    465  static Channel * channel_join(const char *);
    466 @@ -56,20 +67,23 @@ static int       channel_reopen(Channel *);
    467  static void      channel_rm(Channel *);
    468  static void      create_dirtree(const char *);
    469  static void      create_filepath(char *, size_t, const char *, const char *, const char *);
    470 -static void      ewritestr(int, const char *);
    471 -static void      handle_channels_input(int, Channel *);
    472 -static void      handle_server_output(int);
    473 +static int       swrite(conn *, const char *, size_t);
    474 +static void      ewritestr(conn *, const char *);
    475 +static void      handle_channels_input(conn *, Channel *);
    476 +static void      handle_server_output(conn *);
    477  static int       isnumeric(const char *);
    478 -static void      loginkey(int, const char *);
    479 -static void      loginuser(int, const char *, const char *);
    480 -static void      proc_channels_input(int, Channel *, char *);
    481 -static void      proc_channels_privmsg(int, Channel *, char *);
    482 -static void      proc_server_cmd(int, char *);
    483 -static int       read_line(int, char *, size_t);
    484 -static void      run(int, const char *);
    485 +static void      loginkey(conn *, const char *);
    486 +static void      loginuser(conn *, const char *, const char *);
    487 +static void      proc_channels_input(conn *, Channel *, char *);
    488 +static void      proc_channels_privmsg(conn *, Channel *, char *);
    489 +static void      proc_server_cmd(conn *, char *);
    490 +static int       sread(conn *, char *, size_t);
    491 +static int       read_line(conn *, char *, size_t);
    492 +static int       read_line_from_channel(int, char *, size_t);
    493 +static void      run(conn *, const char *);
    494  static void      setup(void);
    495  static void      sighandler(int);
    496 -static int       tcpopen(const char *, const char *);
    497 +static void      tcpopen(conn *ircfd, const char *, const char *);
    498  static size_t    tokenize(char **, size_t, char *, int);
    499  static int       udsopen(const char *);
    500  static void      usage(void);
    501 @@ -87,20 +101,29 @@ static void
    502  usage(void)
    503  {
    504  	fprintf(stderr, "usage: %s <-s host> [-i <irc dir>] [-p <port>] "
    505 -	        "[-u <sockname>] [-n <nick>] [-k <password>] "
    506 +		"[-e <ssl>] [-u <sockname>] [-n <nick>] [-k <password>] "
    507  	        "[-f <fullname>]\n", argv0);
    508  	exit(1);
    509  }
    510  
    511 +static int
    512 +swrite(conn *ircfd, const char *msg, size_t len)
    513 +{
    514 +	if (ircfd->use_ssl)
    515 +		return SSL_write(ircfd->sslHandle, msg, len);
    516 +
    517 +	return write(ircfd->irc, msg, len);
    518 +}
    519 +
    520  static void
    521 -ewritestr(int fd, const char *s)
    522 +ewritestr(conn *fd, const char *s)
    523  {
    524  	size_t len, off = 0;
    525  	int w = -1;
    526  
    527  	len = strlen(s);
    528  	for (off = 0; off < len; off += w) {
    529 -		if ((w = write(fd, s + off, len - off)) == -1)
    530 +		if ((w = swrite(fd, s + off, len - off)) == -1)
    531  			break;
    532  	}
    533  	if (w == -1) {
    534 @@ -319,14 +342,14 @@ channel_leave(Channel *c)
    535  }
    536  
    537  static void
    538 -loginkey(int ircfd, const char *key)
    539 +loginkey(conn *ircfd, const char *key)
    540  {
    541  	snprintf(msg, sizeof(msg), "PASS %s\r\n", key);
    542  	ewritestr(ircfd, msg);
    543  }
    544  
    545  static void
    546 -loginuser(int ircfd, const char *host, const char *fullname)
    547 +loginuser(conn *ircfd, const char *host, const char *fullname)
    548  {
    549  	snprintf(msg, sizeof(msg), "NICK %s\r\nUSER %s localhost %s :%s\r\n",
    550  	         nick, nick, host, fullname);
    551 @@ -359,12 +382,15 @@ udsopen(const char *uds)
    552  	return fd;
    553  }
    554  
    555 -static int
    556 -tcpopen(const char *host, const char *service)
    557 +static void
    558 +tcpopen(conn *ircfd, const char *host, const char *service)
    559  {
    560  	struct addrinfo hints, *res = NULL, *rp;
    561  	int fd = -1, e;
    562  
    563 +	ircfd->sslHandle = NULL;
    564 +	ircfd->sslContext = NULL;
    565 +
    566  	memset(&hints, 0, sizeof(hints));
    567  	hints.ai_family = AF_UNSPEC; /* allow IPv4 or IPv6 */
    568  	hints.ai_flags = AI_NUMERICSERV; /* avoid name lookup for port */
    569 @@ -393,7 +419,19 @@ tcpopen(const char *host, const char *service)
    570  	}
    571  
    572  	freeaddrinfo(res);
    573 -	return fd;
    574 +	ircfd->irc = fd;
    575 +	if (!ircfd->use_ssl)
    576 +		return;
    577 +
    578 +	//SSL_load_error_strings();
    579 +	//SSL_library_init();
    580 +	ircfd->sslContext = SSL_CTX_new(SSLv23_client_method());
    581 +	if (ircfd->sslContext == NULL)
    582 +		ERR_print_errors_fp(stderr);
    583 +	ircfd->sslHandle = SSL_new(ircfd->sslContext);
    584 +	if (!SSL_set_fd(ircfd->sslHandle, ircfd->irc) ||
    585 +	    (SSL_connect(ircfd->sslHandle) != 1))
    586 +		ERR_print_errors_fp(stderr);
    587  }
    588  
    589  static int
    590 @@ -445,7 +483,7 @@ channel_print(Channel *c, const char *buf)
    591  }
    592  
    593  static void
    594 -proc_channels_privmsg(int ircfd, Channel *c, char *buf)
    595 +proc_channels_privmsg(conn *ircfd, Channel *c, char *buf)
    596  {
    597  	snprintf(msg, sizeof(msg), "<%s> %s", nick, buf);
    598  	channel_print(c, msg);
    599 @@ -454,7 +492,7 @@ proc_channels_privmsg(int ircfd, Channel *c, char *buf)
    600  }
    601  
    602  static void
    603 -proc_channels_input(int ircfd, Channel *c, char *buf)
    604 +proc_channels_input(conn *ircfd, Channel *c, char *buf)
    605  {
    606  	char *p = NULL;
    607  	size_t buflen;
    608 @@ -546,7 +584,7 @@ proc_channels_input(int ircfd, Channel *c, char *buf)
    609  }
    610  
    611  static void
    612 -proc_server_cmd(int fd, char *buf)
    613 +proc_server_cmd(conn *fd, char *buf)
    614  {
    615  	Channel *c;
    616  	const char *channel;
    617 @@ -665,8 +703,33 @@ proc_server_cmd(int fd, char *buf)
    618  		channel_print(c, msg);
    619  }
    620  
    621 +
    622 +static int
    623 +sread(conn *fd, char *buf, size_t bufsize)
    624 +{
    625 +	if (fd->use_ssl)
    626 +		return SSL_read(fd->sslHandle, buf, bufsize);
    627 +
    628 +	return read(fd->irc, buf, bufsize);
    629 +}
    630 +
    631 +static int
    632 +read_line(conn *fd, char *buf, size_t bufsiz)
    633 +{
    634 +	size_t i = 0;
    635 +	char c = '\0';
    636 +
    637 +	do {
    638 +		if (sread(fd, &c, sizeof(char)) != sizeof(char))
    639 +			return -1;
    640 +		buf[i++] = c;
    641 +	} while (c != '\n' && i < bufsiz);
    642 +	buf[i - 1] = '\0'; /* eliminates '\n' */
    643 +	return 0;
    644 +}
    645 +
    646  static int
    647 -read_line(int fd, char *buf, size_t bufsiz)
    648 +read_line_from_channel(int fd, char *buf, size_t bufsiz)
    649  {
    650  	size_t i = 0;
    651  	char c = '\0';
    652 @@ -681,11 +744,11 @@ read_line(int fd, char *buf, size_t bufsiz)
    653  }
    654  
    655  static void
    656 -handle_channels_input(int ircfd, Channel *c)
    657 +handle_channels_input(conn *ircfd, Channel *c)
    658  {
    659  	char buf[IRC_MSG_MAX];
    660  
    661 -	if (read_line(c->fdin, buf, sizeof(buf)) == -1) {
    662 +	if (read_line_from_channel(c->fdin, buf, sizeof(buf)) == -1) {
    663  		if (channel_reopen(c) == -1)
    664  			channel_rm(c);
    665  		return;
    666 @@ -694,7 +757,7 @@ handle_channels_input(int ircfd, Channel *c)
    667  }
    668  
    669  static void
    670 -handle_server_output(int ircfd)
    671 +handle_server_output(conn *ircfd)
    672  {
    673  	char buf[IRC_MSG_MAX];
    674  
    675 @@ -727,7 +790,7 @@ setup(void)
    676  }
    677  
    678  static void
    679 -run(int ircfd, const char *host)
    680 +run(conn *ircfd, const char *host)
    681  {
    682  	Channel *c, *tmp;
    683  	fd_set rdset;
    684 @@ -737,9 +800,9 @@ run(int ircfd, const char *host)
    685  
    686  	snprintf(ping_msg, sizeof(ping_msg), "PING %s\r\n", host);
    687  	while (isrunning) {
    688 -		maxfd = ircfd;
    689 +		maxfd = ircfd->irc;
    690  		FD_ZERO(&rdset);
    691 -		FD_SET(ircfd, &rdset);
    692 +		FD_SET(ircfd->irc, &rdset);
    693  		for (c = channels; c; c = c->next) {
    694  			if (c->fdin > maxfd)
    695  				maxfd = c->fdin;
    696 @@ -761,7 +824,7 @@ run(int ircfd, const char *host)
    697  			ewritestr(ircfd, ping_msg);
    698  			continue;
    699  		}
    700 -		if (FD_ISSET(ircfd, &rdset)) {
    701 +		if (FD_ISSET(ircfd->irc, &rdset)) {
    702  			handle_server_output(ircfd);
    703  			last_response = time(NULL);
    704  		}
    705 @@ -779,9 +842,12 @@ main(int argc, char *argv[])
    706  	Channel *c, *tmp;
    707  	struct passwd *spw;
    708  	const char *key = NULL, *fullname = NULL, *host = "";
    709 -	const char *uds = NULL, *service = "6667";
    710 +	const char *uds = NULL;
    711 +	const char *service = "6667";
    712 +	const char *sservice = "6697";
    713  	char prefix[PATH_MAX];
    714 -	int ircfd, r;
    715 +	int r, defaultPort = 1;
    716 +	conn ircfd;
    717  
    718  	/* use nickname and home dir of user by default */
    719  	if (!(spw = getpwuid(getuid()))) {
    720 @@ -806,6 +872,7 @@ main(int argc, char *argv[])
    721  		break;
    722  	case 'p':
    723  		service = EARGF(usage());
    724 +		defaultPort = 0;
    725  		break;
    726  	case 's':
    727  		host = EARGF(usage());
    728 @@ -813,6 +880,11 @@ main(int argc, char *argv[])
    729  	case 'u':
    730  		uds = EARGF(usage());
    731  		break;
    732 +	case 'e':
    733 +		if (defaultPort)
    734 +			service = sservice;
    735 +		ircfd.use_ssl = 1;
    736 +		break;
    737  	default:
    738  		usage();
    739  		break;
    740 @@ -822,9 +894,9 @@ main(int argc, char *argv[])
    741  		usage();
    742  
    743  	if (uds)
    744 -		ircfd = udsopen(uds);
    745 +		ircfd.irc = udsopen(uds);
    746  	else
    747 -		ircfd = tcpopen(host, service);
    748 +		tcpopen(&ircfd, host, service);
    749  
    750  #ifdef __OpenBSD__
    751  	/* OpenBSD pledge(2) support */
    752 @@ -843,10 +915,10 @@ main(int argc, char *argv[])
    753  
    754  	channelmaster = channel_add(""); /* master channel */
    755  	if (key)
    756 -		loginkey(ircfd, key);
    757 -	loginuser(ircfd, host, fullname && *fullname ? fullname : nick);
    758 +		loginkey(&ircfd, key);
    759 +	loginuser(&ircfd, host, fullname && *fullname ? fullname : nick);
    760  	setup();
    761 -	run(ircfd, host);
    762 +	run(&ircfd, host);
    763  	if (channelmaster)
    764  		channel_leave(channelmaster);
    765  
    766 @@ -855,5 +927,13 @@ main(int argc, char *argv[])
    767  		channel_leave(c);
    768  	}
    769  
    770 +	if (ircfd.use_ssl) {
    771 +		SSL_shutdown(ircfd.sslHandle);
    772 +		SSL_free(ircfd.sslHandle);
    773 +		SSL_CTX_free(ircfd.sslContext);
    774 +	}
    775 +
    776 +	close(ircfd.irc);
    777 +
    778  	return 0;
    779  }
    780 -- 
    781 2.28.0
    782