[patch] net/icbirc: Correct IRC parsing

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

[patch] net/icbirc: Correct IRC parsing

Matthew Martin
Seems some icbirc users started having : prefixed nicks after updating
weechat. Even though weechat added a workaround, I think it would be
best to fix the IRC protocol parsing in icbirc to conform to the RFC.

I special cased RAWICB to bypass the correct parsing; I assumed people
manually typed those commands and I shouldn't break finger memory.

I don't use ICB, so this has only been compile tested. Once tested, this
should go upstream rather than living in the tree.

- Matthew Martin


diff --git Makefile Makefile
index d7bb3f1160b..a7b292d43da 100644
--- Makefile
+++ Makefile
@@ -3,7 +3,7 @@
 COMMENT= proxy IRC client with ICB server
 
 DISTNAME= icbirc-2.1
-REVISION= 2
+REVISION= 3
 CATEGORIES= net
 MASTER_SITES= http://www.benzedrine.ch/
 
diff --git patches/patch-irc_c patches/patch-irc_c
new file mode 100644
index 00000000000..ceb5f0172a0
--- /dev/null
+++ patches/patch-irc_c
@@ -0,0 +1,200 @@
+$OpenBSD$
+
+Index: irc.c
+--- irc.c.orig
++++ irc.c
+@@ -42,7 +42,7 @@ extern void scan(const char **, char *, size_t, const
+    const char *);
+ extern int sync_write(int, const char *, int);
+
+-static void irc_cmd(const char *, int, int);
++static void irc_cmd(char *, int, int);
+
+ static void irc_send_pong(int, const char *);
+
+@@ -93,44 +93,55 @@ irc_recv(const char *buf, unsigned len, int client_fd,
+ }
+
+ static void
+-irc_cmd(const char *cmd, int client_fd, int server_fd)
++irc_cmd(char *cmd, int client_fd, int server_fd)
+ {
+- if (!strncasecmp(cmd, "PASS ", 5)) {
+- cmd += 5;
+- scan(&cmd, irc_pass, sizeof(irc_pass), " ", " ");
+- } else if (!strncasecmp(cmd, "USER ", 5)) {
+- cmd += 5;
+- scan(&cmd, irc_ident, sizeof(irc_ident), " ", " ");
++ if (!strncasecmp(cmd, "RAWICB ", 7)) {
++ icb_send_raw(server_fd, cmd + 7);
++ return;
++ }
++
++ char *argv[10], *p;
++ int argc = 1;
++
++ for (p = cmd, argv[0] = p; argc < 10 && (p = strchr(p, ' ')) != NULL;
++    argc++) {
++ *p = 0;
++ p++;
++ while (*p == ' ')
++ p++;
++ if (*p == ':') {
++ argv[argc] = p + 1;
++ argc++;
++ break;
++ }
++ argv[argc] = p;
++ }
++
++ if (!strcasecmp(argv[0], "PASS")) {
++ strlcpy(irc_pass, argv[1], sizeof(irc_pass));
++ } else if (!strcasecmp(argv[0], "USER")) {
++ strlcpy(irc_ident, argv[1], sizeof(irc_ident));
+ if (!icb_logged_in && irc_nick[0] && irc_ident[0])
+ icb_send_login(server_fd, irc_nick,
+    irc_ident, irc_pass);
+- } else if (!strncasecmp(cmd, "NICK ", 5)) {
+- cmd += 5;
+- scan(&cmd, irc_nick, sizeof(irc_nick), " ", " ");
++ } else if (!strcasecmp(argv[0], "NICK")) {
++ strlcpy(irc_nick, argv[1], sizeof(irc_nick));
+ if (icb_logged_in)
+ icb_send_name(server_fd, irc_nick);
+ else if (irc_nick[0] && irc_ident[0])
+ icb_send_login(server_fd, irc_nick,
+    irc_ident, irc_pass);
+- } else if (!strncasecmp(cmd, "JOIN ", 5)) {
+- char group[128];
+-
+- cmd += 5;
+- if (*cmd == '#')
+- cmd++;
+- scan(&cmd, group, sizeof(group), " ", " ");
+- icb_send_group(server_fd, group);
+- } else if (!strncasecmp(cmd, "PART ", 5)) {
++ } else if (!strcasecmp(argv[0], "JOIN")) {
++ icb_send_group(server_fd,
++    argv[1] + (argv[1][0] == '#' ? 1 : 0));
++ } else if (!strcasecmp(argv[0], "PART")) {
+ in_irc_channel = 0;
+- } else if (!strncasecmp(cmd, "PRIVMSG ", 8) ||
+-    !strncasecmp(cmd, "NOTICE ", 7)) {
+- char dst[128];
++ } else if (!strcasecmp(argv[0], "PRIVMSG") ||
++    !strcasecmp(argv[0], "NOTICE")) {
+ char msg[8192];
+ unsigned i, j;
+
+- cmd += strncasecmp(cmd, "NOTICE ", 7) ? 8 : 7;
+- scan(&cmd, dst, sizeof(dst), " ", " ");
+- scan(&cmd, msg, sizeof(msg), " ", "");
++ strlcpy(msg, argv[2], sizeof(msg));
+ /* strip \001 found in CTCP messages */
+ i = 0;
+ while (msg[i]) {
+@@ -141,73 +152,52 @@ irc_cmd(const char *cmd, int client_fd, int server_fd)
+ } else
+ i++;
+ }
+- if (!strcmp(dst, irc_channel))
+- icb_send_openmsg(server_fd,
+-    msg + (msg[0] == ':' ? 1 : 0));
++ if (!strcmp(argv[1], irc_channel))
++ icb_send_openmsg(server_fd, msg);
+ else
+- icb_send_privmsg(server_fd, dst,
+-    msg + (msg[0] == ':' ? 1 : 0));
+- } else if (!strncasecmp(cmd, "MODE ", 5)) {
+- cmd += 5;
+- if (!strcmp(cmd, irc_channel))
++ icb_send_privmsg(server_fd, argv[1], msg);
++ } else if (!strcasecmp(argv[0], "MODE")) {
++ if (strcmp(argv[1], irc_channel))
++ return;
++ if (argc == 2)
+ icb_send_names(server_fd, irc_channel);
+- else if (!strncmp(cmd, irc_channel, strlen(irc_channel))) {
+- cmd += strlen(irc_channel);
+- if (strncmp(cmd, " +o ", 4)) {
++ else {
++ if (strcmp(argv[2], "+o")) {
+ printf("irc_cmd: invalid MODE args '%s'\n",
+-    cmd);
++    argv[2]);
+ return;
+ }
+- cmd += 4;
+- icb_send_pass(server_fd, cmd);
++ icb_send_pass(server_fd, argv[3]);
+ }
+- } else if (!strncasecmp(cmd, "TOPIC ", 6)) {
+- cmd += 6;
+- if (strncmp(cmd, irc_channel, strlen(irc_channel))) {
+- printf("irc_cmd: invalid TOPIC args '%s'\n", cmd);
++ } else if (!strcasecmp(argv[0], "TOPIC")) {
++ if (strcmp(argv[1], irc_channel)) {
++ printf("irc_cmd: invalid TOPIC channel '%s'\n",
++    argv[1]);
+ return;
+ }
+- cmd += strlen(irc_channel);
+- if (strncmp(cmd, " :", 2)) {
+- printf("irc_cmd: invalid TOPIC args '%s'\n", cmd);
+- return;
+- }
+- cmd += 2;
+- icb_send_topic(server_fd, cmd);
+- } else if (!strcasecmp(cmd, "LIST")) {
++ icb_send_topic(server_fd, argv[2]);
++ } else if (!strcasecmp(argv[0], "LIST")) {
+ icb_send_list(server_fd);
+- } else if (!strncasecmp(cmd, "NAMES ", 6)) {
+- cmd += 6;
+- icb_send_names(server_fd, cmd);
+- } else if (!strncasecmp(cmd, "WHOIS ", 6)) {
+- cmd += 6;
+- icb_send_whois(server_fd, cmd);
+- } else if (!strncasecmp(cmd, "WHO ", 4)) {
+- cmd += 4;
+- icb_send_who(server_fd, cmd);
+- } else if (!strncasecmp(cmd, "KICK ", 5)) {
+- char channel[128], nick[128];
+-
+- cmd += 5;
+- scan(&cmd, channel, sizeof(channel), " ", " ");
+- scan(&cmd, nick, sizeof(nick), " ", " ");
+- if (strcmp(channel, irc_channel)) {
+- printf("irc_cmd: invalid KICK args '%s'\n", cmd);
++ } else if (!strcasecmp(argv[0], "NAMES")) {
++ icb_send_names(server_fd, argv[1]);
++ } else if (!strcasecmp(argv[0], "WHOIS")) {
++ icb_send_whois(server_fd, argv[1]);
++ } else if (!strcasecmp(argv[0], "WHO")) {
++ icb_send_who(server_fd, argv[1]);
++ } else if (!strcasecmp(argv[0], "KICK")) {
++ if (strcmp(argv[1], irc_channel)) {
++ printf("irc_cmd: invalid KICK args '%s'\n", argv[1]);
+ return;
+ }
+- icb_send_boot(server_fd, nick);
+- } else if (!strncasecmp(cmd, "PING ", 5)) {
++ icb_send_boot(server_fd, argv[2]);
++ } else if (!strcasecmp(argv[0], "PING")) {
+ icb_send_noop(server_fd);
+- cmd += 5;
+- irc_send_pong(client_fd, cmd);
+- } else if (!strncasecmp(cmd, "RAWICB ", 7)) {
+- cmd += 7;
+- icb_send_raw(server_fd, cmd);
+- } else if (!strncasecmp(cmd, "QUIT ", 5)) {
++ irc_send_pong(client_fd, argv[1]);
++ } else if (!strcasecmp(argv[0], "QUIT")) {
+ printf("client QUIT\n");
+ terminate_client = 1;
+ } else
+- printf("irc_cmd: unknown cmd '%s'\n", cmd);
++ printf("irc_cmd: unknown command '%s'\n", argv[0]);
+ }
+
+ void

Reply | Threaded
Open this post in threaded view
|

Re: [patch] net/icbirc: Correct IRC parsing

Stuart Henderson
On 2019/07/11 12:40, Matthew Martin wrote:

> Seems some icbirc users started having : prefixed nicks after updating
> weechat. Even though weechat added a workaround, I think it would be
> best to fix the IRC protocol parsing in icbirc to conform to the RFC.
>
> I special cased RAWICB to bypass the correct parsing; I assumed people
> manually typed those commands and I shouldn't break finger memory.
>
> I don't use ICB, so this has only been compile tested. Once tested, this
> should go upstream rather than living in the tree.
>
> - Matthew Martin

Could someone who uses icbirc test and commit this please, the bug is
slightly annoying for other people on the channel :)

Diff forwarded below for ease of applying...


diff --git Makefile Makefile
index d7bb3f1160b..a7b292d43da 100644
--- Makefile
+++ Makefile
@@ -3,7 +3,7 @@
 COMMENT= proxy IRC client with ICB server
 
 DISTNAME= icbirc-2.1
-REVISION= 2
+REVISION= 3
 CATEGORIES= net
 MASTER_SITES= http://www.benzedrine.ch/
 
diff --git patches/patch-irc_c patches/patch-irc_c
new file mode 100644
index 00000000000..ceb5f0172a0
--- /dev/null
+++ patches/patch-irc_c
@@ -0,0 +1,200 @@
+$OpenBSD$
+
+Index: irc.c
+--- irc.c.orig
++++ irc.c
+@@ -42,7 +42,7 @@ extern void scan(const char **, char *, size_t, const
+    const char *);
+ extern int sync_write(int, const char *, int);
+
+-static void irc_cmd(const char *, int, int);
++static void irc_cmd(char *, int, int);
+
+ static void irc_send_pong(int, const char *);
+
+@@ -93,44 +93,55 @@ irc_recv(const char *buf, unsigned len, int client_fd,
+ }
+
+ static void
+-irc_cmd(const char *cmd, int client_fd, int server_fd)
++irc_cmd(char *cmd, int client_fd, int server_fd)
+ {
+- if (!strncasecmp(cmd, "PASS ", 5)) {
+- cmd += 5;
+- scan(&cmd, irc_pass, sizeof(irc_pass), " ", " ");
+- } else if (!strncasecmp(cmd, "USER ", 5)) {
+- cmd += 5;
+- scan(&cmd, irc_ident, sizeof(irc_ident), " ", " ");
++ if (!strncasecmp(cmd, "RAWICB ", 7)) {
++ icb_send_raw(server_fd, cmd + 7);
++ return;
++ }
++
++ char *argv[10], *p;
++ int argc = 1;
++
++ for (p = cmd, argv[0] = p; argc < 10 && (p = strchr(p, ' ')) != NULL;
++    argc++) {
++ *p = 0;
++ p++;
++ while (*p == ' ')
++ p++;
++ if (*p == ':') {
++ argv[argc] = p + 1;
++ argc++;
++ break;
++ }
++ argv[argc] = p;
++ }
++
++ if (!strcasecmp(argv[0], "PASS")) {
++ strlcpy(irc_pass, argv[1], sizeof(irc_pass));
++ } else if (!strcasecmp(argv[0], "USER")) {
++ strlcpy(irc_ident, argv[1], sizeof(irc_ident));
+ if (!icb_logged_in && irc_nick[0] && irc_ident[0])
+ icb_send_login(server_fd, irc_nick,
+    irc_ident, irc_pass);
+- } else if (!strncasecmp(cmd, "NICK ", 5)) {
+- cmd += 5;
+- scan(&cmd, irc_nick, sizeof(irc_nick), " ", " ");
++ } else if (!strcasecmp(argv[0], "NICK")) {
++ strlcpy(irc_nick, argv[1], sizeof(irc_nick));
+ if (icb_logged_in)
+ icb_send_name(server_fd, irc_nick);
+ else if (irc_nick[0] && irc_ident[0])
+ icb_send_login(server_fd, irc_nick,
+    irc_ident, irc_pass);
+- } else if (!strncasecmp(cmd, "JOIN ", 5)) {
+- char group[128];
+-
+- cmd += 5;
+- if (*cmd == '#')
+- cmd++;
+- scan(&cmd, group, sizeof(group), " ", " ");
+- icb_send_group(server_fd, group);
+- } else if (!strncasecmp(cmd, "PART ", 5)) {
++ } else if (!strcasecmp(argv[0], "JOIN")) {
++ icb_send_group(server_fd,
++    argv[1] + (argv[1][0] == '#' ? 1 : 0));
++ } else if (!strcasecmp(argv[0], "PART")) {
+ in_irc_channel = 0;
+- } else if (!strncasecmp(cmd, "PRIVMSG ", 8) ||
+-    !strncasecmp(cmd, "NOTICE ", 7)) {
+- char dst[128];
++ } else if (!strcasecmp(argv[0], "PRIVMSG") ||
++    !strcasecmp(argv[0], "NOTICE")) {
+ char msg[8192];
+ unsigned i, j;
+
+- cmd += strncasecmp(cmd, "NOTICE ", 7) ? 8 : 7;
+- scan(&cmd, dst, sizeof(dst), " ", " ");
+- scan(&cmd, msg, sizeof(msg), " ", "");
++ strlcpy(msg, argv[2], sizeof(msg));
+ /* strip \001 found in CTCP messages */
+ i = 0;
+ while (msg[i]) {
+@@ -141,73 +152,52 @@ irc_cmd(const char *cmd, int client_fd, int server_fd)
+ } else
+ i++;
+ }
+- if (!strcmp(dst, irc_channel))
+- icb_send_openmsg(server_fd,
+-    msg + (msg[0] == ':' ? 1 : 0));
++ if (!strcmp(argv[1], irc_channel))
++ icb_send_openmsg(server_fd, msg);
+ else
+- icb_send_privmsg(server_fd, dst,
+-    msg + (msg[0] == ':' ? 1 : 0));
+- } else if (!strncasecmp(cmd, "MODE ", 5)) {
+- cmd += 5;
+- if (!strcmp(cmd, irc_channel))
++ icb_send_privmsg(server_fd, argv[1], msg);
++ } else if (!strcasecmp(argv[0], "MODE")) {
++ if (strcmp(argv[1], irc_channel))
++ return;
++ if (argc == 2)
+ icb_send_names(server_fd, irc_channel);
+- else if (!strncmp(cmd, irc_channel, strlen(irc_channel))) {
+- cmd += strlen(irc_channel);
+- if (strncmp(cmd, " +o ", 4)) {
++ else {
++ if (strcmp(argv[2], "+o")) {
+ printf("irc_cmd: invalid MODE args '%s'\n",
+-    cmd);
++    argv[2]);
+ return;
+ }
+- cmd += 4;
+- icb_send_pass(server_fd, cmd);
++ icb_send_pass(server_fd, argv[3]);
+ }
+- } else if (!strncasecmp(cmd, "TOPIC ", 6)) {
+- cmd += 6;
+- if (strncmp(cmd, irc_channel, strlen(irc_channel))) {
+- printf("irc_cmd: invalid TOPIC args '%s'\n", cmd);
++ } else if (!strcasecmp(argv[0], "TOPIC")) {
++ if (strcmp(argv[1], irc_channel)) {
++ printf("irc_cmd: invalid TOPIC channel '%s'\n",
++    argv[1]);
+ return;
+ }
+- cmd += strlen(irc_channel);
+- if (strncmp(cmd, " :", 2)) {
+- printf("irc_cmd: invalid TOPIC args '%s'\n", cmd);
+- return;
+- }
+- cmd += 2;
+- icb_send_topic(server_fd, cmd);
+- } else if (!strcasecmp(cmd, "LIST")) {
++ icb_send_topic(server_fd, argv[2]);
++ } else if (!strcasecmp(argv[0], "LIST")) {
+ icb_send_list(server_fd);
+- } else if (!strncasecmp(cmd, "NAMES ", 6)) {
+- cmd += 6;
+- icb_send_names(server_fd, cmd);
+- } else if (!strncasecmp(cmd, "WHOIS ", 6)) {
+- cmd += 6;
+- icb_send_whois(server_fd, cmd);
+- } else if (!strncasecmp(cmd, "WHO ", 4)) {
+- cmd += 4;
+- icb_send_who(server_fd, cmd);
+- } else if (!strncasecmp(cmd, "KICK ", 5)) {
+- char channel[128], nick[128];
+-
+- cmd += 5;
+- scan(&cmd, channel, sizeof(channel), " ", " ");
+- scan(&cmd, nick, sizeof(nick), " ", " ");
+- if (strcmp(channel, irc_channel)) {
+- printf("irc_cmd: invalid KICK args '%s'\n", cmd);
++ } else if (!strcasecmp(argv[0], "NAMES")) {
++ icb_send_names(server_fd, argv[1]);
++ } else if (!strcasecmp(argv[0], "WHOIS")) {
++ icb_send_whois(server_fd, argv[1]);
++ } else if (!strcasecmp(argv[0], "WHO")) {
++ icb_send_who(server_fd, argv[1]);
++ } else if (!strcasecmp(argv[0], "KICK")) {
++ if (strcmp(argv[1], irc_channel)) {
++ printf("irc_cmd: invalid KICK args '%s'\n", argv[1]);
+ return;
+ }
+- icb_send_boot(server_fd, nick);
+- } else if (!strncasecmp(cmd, "PING ", 5)) {
++ icb_send_boot(server_fd, argv[2]);
++ } else if (!strcasecmp(argv[0], "PING")) {
+ icb_send_noop(server_fd);
+- cmd += 5;
+- irc_send_pong(client_fd, cmd);
+- } else if (!strncasecmp(cmd, "RAWICB ", 7)) {
+- cmd += 7;
+- icb_send_raw(server_fd, cmd);
+- } else if (!strncasecmp(cmd, "QUIT ", 5)) {
++ irc_send_pong(client_fd, argv[1]);
++ } else if (!strcasecmp(argv[0], "QUIT")) {
+ printf("client QUIT\n");
+ terminate_client = 1;
+ } else
+- printf("irc_cmd: unknown cmd '%s'\n", cmd);
++ printf("irc_cmd: unknown command '%s'\n", argv[0]);
+ }
+
+ void


----- End forwarded message -----