sites

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

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