Broken 353 and 366 /names replies sent for joined channels upon connecting to ZNC #899

Open
opened 2026-10-05 04:51:37 +02:00 by adam · 12 comments
Owner

When connecting to ZNC, I see plenty of messages like 353 mk-fg = #control +mk-fg being dumped into the server buffer by the client (one for each previously-joined channel), which seem to happen because ZNC sends lines like :353 mk-fg = #control +mk-fg for each channel that client joins.
I think correct IRC protocol would be to send 353 mk-fg = #control +mk-fg without that leading colon.

ZNC never sends NAMES to the server in question and generates these (broken) lines internally in CChan::AttachUser, so it looks like incorrect behavior on the part of ZNC itself.

Confirmed by seeing these lines coming from ZNC in wireshark: https://i.imgur.com/LmrdUGf.jpg

IRCd in question probably does something weird wrt its "[:source]" part of the messages (like not sending it in some cases), but that doesn't seem to be a violation of the IRC protocol, as "[:source]" is optional afaict, and maybe should be handled without breaking protocol on client connections regardless.

ZNC version: 1.7.2-1 (Archlinux package)
OS: Archlinux amd64 (latest, rolling release)

When connecting to ZNC, I see plenty of messages like `353 mk-fg = #control +mk-fg` being dumped into the server buffer by the client (one for each previously-joined channel), which seem to happen because ZNC sends lines like `:353 mk-fg = #control +mk-fg` for each channel that client joins. I think correct IRC protocol would be to send `353 mk-fg = #control +mk-fg` without that leading colon. ZNC never sends NAMES to the server in question and generates these (broken) lines internally in CChan::AttachUser, so it looks like incorrect behavior on the part of ZNC itself. Confirmed by seeing these lines coming from ZNC in wireshark: https://i.imgur.com/LmrdUGf.jpg IRCd in question probably does something weird wrt its "[:source]" part of the messages (like not sending it in some cases), but that doesn't seem to be a violation of the IRC protocol, as "[:source]" is optional afaict, and maybe should be handled without breaking protocol on client connections regardless. ZNC version: 1.7.2-1 (Archlinux package) OS: Archlinux amd64 (latest, rolling release) <!-- github-sync-id:408455809 -->
Author
Owner

What's the IRC server that is used here? In the screenshot that you showed on IRC, there was a space after the colon and the 353.

What's the IRC server that is used here? In the screenshot that you showed on IRC, there was a space after the colon and the `353`. <!-- github-comment-id:462067608 -->
Author
Owner

In the screenshot that you showed on IRC, there was a space after the colon and the 353.

Don't think it's the case, exact hex + ascii for this, as copied from wireshark is:

0000   3a 33 35 33 20 6d 6b 2d 66 67 20 3d 20 23 63 6f  :353 mk-fg = #co
0010   6e 74 72 6f 6c 20 3a 2b 6d 6b 2d 66 67           ntrol :+mk-fg

And decoding it via e.g. python2 -c "print '3a 33 35 33 20 6d 6b 2d 66 67 20 3d 20 23 63 6f 6e 74 72 6f 6c 20 3a 2b 6d 6b 2d 66 67'.replace(' ', '').decode('hex')" yields :353 mk-fg = #control :+mk-fg - no space after colon.

Or am I misunderstanding specific space/colon place that you mean?

> In the screenshot that you showed on IRC, there was a space after the colon and the 353. Don't think it's the case, exact hex + ascii for this, as copied from wireshark is: ``` 0000 3a 33 35 33 20 6d 6b 2d 66 67 20 3d 20 23 63 6f :353 mk-fg = #co 0010 6e 74 72 6f 6c 20 3a 2b 6d 6b 2d 66 67 ntrol :+mk-fg ``` And decoding it via e.g. `python2 -c "print '3a 33 35 33 20 6d 6b 2d 66 67 20 3d 20 23 63 6f 6e 74 72 6f 6c 20 3a 2b 6d 6b 2d 66 67'.replace(' ', '').decode('hex')"` yields `:353 mk-fg = #control :+mk-fg` - no space after colon. Or am I misunderstanding specific space/colon place that you mean? <!-- github-comment-id:462068086 -->
Author
Owner

You've also asked about 001 message upon connecting in #znc on freenode.

ZNC gives this one to client:

0000   30 30 31 20 7a 6e 63 20 3a 57 65 6c 63 6f 6d 65  001 znc :Welcome
0010   20 74 6f 20 74 68 65 20 72 64 69 72 63 64 20 64   to the rdircd d
0020   69 73 63 6f 72 64 2d 69 72 63 20 62 72 69 64 67  iscord-irc bridg
0030   65 2c 20 6d 6b 2d 66 67                          e, mk-fg

And this is what server sends to ZNC upon connecting:
"001 mk-fg :Welcome to the rdircd discord-irc bridge, mk-fg\r\n"

Log for stuff being sent to ZNC upon connection:

2019-02-09T21:14:14.881 :: +7.001 :: irc.tEq :: --- :: conn 127.0.0.1 42018
2019-02-09T21:14:14.882 :: +0.002 :: irc.tEq ::  >> :: "NOTICE * :*** rdircd ready\r\n"
2019-02-09T21:14:14.885 :: +0.002 :: irc.tEq :: <<  :: "CAP LS\r"
2019-02-09T21:14:14.885 :: +0.001 :: irc.tEq :: <<  :: "PASS +dl+NLv-5Aoo++V**3WYZXro~h%XAS%(E,ow{^o\r"
2019-02-09T21:14:14.886 :: +0.001 :: irc.tEq :: <<  :: "NICK mk-fg\r"
2019-02-09T21:14:14.887 :: +0.001 :: irc.tEq :: <<  :: "USER discord \"discord\" \"discord\" :discord\r"
2019-02-09T21:14:14.889 :: +0.002 :: irc.tEq ::  >> :: "CAP * LS :\r\n"
2019-02-09T21:14:14.894 :: +0.005 :: irc.tEq ::  >> :: "NOTICE * :*** registration completed\r\n"
2019-02-09T21:14:14.895 :: +0.005 :: irc.tEq ::  >> :: "001 mk-fg :Welcome to the rdircd discord-irc bridge, mk-fg\r\n"
2019-02-09T21:14:14.897 :: +0.005 :: irc.tEq ::  >> :: "002 mk-fg :Your host is wyrm, running rdircd 1.89\r\n"
2019-02-09T21:14:14.899 :: +0.005 :: irc.tEq ::  >> :: "003 mk-fg :This server was created at 2019-02-09 16:13:49 UTC\r\n"
2019-02-09T21:14:14.901 :: +0.005 :: irc.tEq ::  >> :: "004 mk-fg wyrm rdircd-1.89 DOQRSZaghilopswz CFILMPQSbcefgijklmnopqrstvz\r\n"
2019-02-09T21:14:14.903 :: +0.009 :: irc.tEq ::  >> :: "005 mk-fg AWAYLEN=200 CASEMAPPING=ascii CHANLIMIT=#:512 CHANTYPES=# CHANMODES=eIbq,k,flj,CFLMPQScgimnprstz CHANNELLEN=80 ELIST=C NETWORK=rdircd NICKLEN=64 PREFIX=(ov)@+ :are supported by this server\r\n"
2019-02-09T21:14:14.905 :: +0.009 :: irc.tEq ::  >> :: "005 mk-fg SAFELIST STATUSMSG=@+ TOPICLEN=390 USERLEN=32 :are supported by this server\r\n"
2019-02-09T21:14:15.033 :: +0.130 :: irc.tEq ::  >> :: "251 mk-fg :There are 1 users and 0 invisible on 5 server(s)\r\n"
2019-02-09T21:14:15.034 :: +0.001 :: irc.tEq ::  >> :: "252 mk-fg 0 :IRC Operators online\r\n"
2019-02-09T21:14:15.036 :: +0.001 :: irc.tEq ::  >> :: "253 mk-fg 0 :unknown connection(s)\r\n"
2019-02-09T21:14:15.037 :: +0.001 :: irc.tEq ::  >> :: "254 mk-fg 191 :channels formed\r\n"
2019-02-09T21:14:15.039 :: +0.001 :: irc.tEq ::  >> :: "255 mk-fg :I have 1 client(s) and 5 server(s)\r\n"
2019-02-09T21:14:15.041 :: +0.006 :: irc.tEq ::  >> :: "265 mk-fg 1 1 :Current local users 1, max 1\r\n"
2019-02-09T21:14:15.042 :: +0.006 :: irc.tEq ::  >> :: "266 mk-fg 1 1 :Current global users 1, max 1\r\n"
2019-02-09T21:14:15.044 :: +0.003 :: irc.tEq ::  >> :: "422 mk-fg :MOTD File is missing\r\n"
2019-02-09T21:14:15.046 :: +0.002 :: irc.tEq :: <<  :: "CAP END\r"
2019-02-09T21:14:15.047 :: +0.001 :: irc.tEq :: <<  :: "WHO mk-fg\r"
2019-02-09T21:14:15.048 :: +0.001 :: irc.tEq :: <<  :: "JOIN #control,#debug,#monitor\r"
2019-02-09T21:14:15.051 :: +0.003 :: irc.tEq ::  >> :: "352 mk-fg * discord 127.0.0.1 wyrm mk-fg H :0 mk-fg\r\n"
2019-02-09T21:14:15.052 :: +0.001 :: irc.tEq ::  >> :: "315 mk-fg mk-fg :End of /WHO list.\r\n"
2019-02-09T21:14:15.055 :: +0.003 :: irc.tEq ::  >> :: ":mk-fg JOIN #control\r\n"
2019-02-09T21:14:15.056 :: +0.001 :: irc.tEq ::  >> :: "MODE #control +v mk-fg\r\n"
2019-02-09T21:14:15.058 :: +0.001 :: irc.tEq ::  >> :: ":mk-fg JOIN #debug\r\n"
2019-02-09T21:14:15.059 :: +0.001 :: irc.tEq ::  >> :: "MODE #debug +v mk-fg\r\n"
2019-02-09T21:14:15.061 :: +0.003 :: irc.tEq ::  >> :: ":mk-fg JOIN #monitor\r\n"
2019-02-09T21:14:15.062 :: +0.001 :: irc.tEq ::  >> :: "MODE #monitor +v mk-fg\r\n"
...

EDIT: there's PASS command in there, but it's not a security issue of any kind to expose it in this case.

You've also asked about 001 message upon connecting in #znc on freenode. ZNC gives this one to client: ``` 0000 30 30 31 20 7a 6e 63 20 3a 57 65 6c 63 6f 6d 65 001 znc :Welcome 0010 20 74 6f 20 74 68 65 20 72 64 69 72 63 64 20 64 to the rdircd d 0020 69 73 63 6f 72 64 2d 69 72 63 20 62 72 69 64 67 iscord-irc bridg 0030 65 2c 20 6d 6b 2d 66 67 e, mk-fg ``` And this is what server sends to ZNC upon connecting: `"001 mk-fg :Welcome to the rdircd discord-irc bridge, mk-fg\r\n"` Log for stuff being sent to ZNC upon connection: ``` 2019-02-09T21:14:14.881 :: +7.001 :: irc.tEq :: --- :: conn 127.0.0.1 42018 2019-02-09T21:14:14.882 :: +0.002 :: irc.tEq :: >> :: "NOTICE * :*** rdircd ready\r\n" 2019-02-09T21:14:14.885 :: +0.002 :: irc.tEq :: << :: "CAP LS\r" 2019-02-09T21:14:14.885 :: +0.001 :: irc.tEq :: << :: "PASS +dl+NLv-5Aoo++V**3WYZXro~h%XAS%(E,ow{^o\r" 2019-02-09T21:14:14.886 :: +0.001 :: irc.tEq :: << :: "NICK mk-fg\r" 2019-02-09T21:14:14.887 :: +0.001 :: irc.tEq :: << :: "USER discord \"discord\" \"discord\" :discord\r" 2019-02-09T21:14:14.889 :: +0.002 :: irc.tEq :: >> :: "CAP * LS :\r\n" 2019-02-09T21:14:14.894 :: +0.005 :: irc.tEq :: >> :: "NOTICE * :*** registration completed\r\n" 2019-02-09T21:14:14.895 :: +0.005 :: irc.tEq :: >> :: "001 mk-fg :Welcome to the rdircd discord-irc bridge, mk-fg\r\n" 2019-02-09T21:14:14.897 :: +0.005 :: irc.tEq :: >> :: "002 mk-fg :Your host is wyrm, running rdircd 1.89\r\n" 2019-02-09T21:14:14.899 :: +0.005 :: irc.tEq :: >> :: "003 mk-fg :This server was created at 2019-02-09 16:13:49 UTC\r\n" 2019-02-09T21:14:14.901 :: +0.005 :: irc.tEq :: >> :: "004 mk-fg wyrm rdircd-1.89 DOQRSZaghilopswz CFILMPQSbcefgijklmnopqrstvz\r\n" 2019-02-09T21:14:14.903 :: +0.009 :: irc.tEq :: >> :: "005 mk-fg AWAYLEN=200 CASEMAPPING=ascii CHANLIMIT=#:512 CHANTYPES=# CHANMODES=eIbq,k,flj,CFLMPQScgimnprstz CHANNELLEN=80 ELIST=C NETWORK=rdircd NICKLEN=64 PREFIX=(ov)@+ :are supported by this server\r\n" 2019-02-09T21:14:14.905 :: +0.009 :: irc.tEq :: >> :: "005 mk-fg SAFELIST STATUSMSG=@+ TOPICLEN=390 USERLEN=32 :are supported by this server\r\n" 2019-02-09T21:14:15.033 :: +0.130 :: irc.tEq :: >> :: "251 mk-fg :There are 1 users and 0 invisible on 5 server(s)\r\n" 2019-02-09T21:14:15.034 :: +0.001 :: irc.tEq :: >> :: "252 mk-fg 0 :IRC Operators online\r\n" 2019-02-09T21:14:15.036 :: +0.001 :: irc.tEq :: >> :: "253 mk-fg 0 :unknown connection(s)\r\n" 2019-02-09T21:14:15.037 :: +0.001 :: irc.tEq :: >> :: "254 mk-fg 191 :channels formed\r\n" 2019-02-09T21:14:15.039 :: +0.001 :: irc.tEq :: >> :: "255 mk-fg :I have 1 client(s) and 5 server(s)\r\n" 2019-02-09T21:14:15.041 :: +0.006 :: irc.tEq :: >> :: "265 mk-fg 1 1 :Current local users 1, max 1\r\n" 2019-02-09T21:14:15.042 :: +0.006 :: irc.tEq :: >> :: "266 mk-fg 1 1 :Current global users 1, max 1\r\n" 2019-02-09T21:14:15.044 :: +0.003 :: irc.tEq :: >> :: "422 mk-fg :MOTD File is missing\r\n" 2019-02-09T21:14:15.046 :: +0.002 :: irc.tEq :: << :: "CAP END\r" 2019-02-09T21:14:15.047 :: +0.001 :: irc.tEq :: << :: "WHO mk-fg\r" 2019-02-09T21:14:15.048 :: +0.001 :: irc.tEq :: << :: "JOIN #control,#debug,#monitor\r" 2019-02-09T21:14:15.051 :: +0.003 :: irc.tEq :: >> :: "352 mk-fg * discord 127.0.0.1 wyrm mk-fg H :0 mk-fg\r\n" 2019-02-09T21:14:15.052 :: +0.001 :: irc.tEq :: >> :: "315 mk-fg mk-fg :End of /WHO list.\r\n" 2019-02-09T21:14:15.055 :: +0.003 :: irc.tEq :: >> :: ":mk-fg JOIN #control\r\n" 2019-02-09T21:14:15.056 :: +0.001 :: irc.tEq :: >> :: "MODE #control +v mk-fg\r\n" 2019-02-09T21:14:15.058 :: +0.001 :: irc.tEq :: >> :: ":mk-fg JOIN #debug\r\n" 2019-02-09T21:14:15.059 :: +0.001 :: irc.tEq :: >> :: "MODE #debug +v mk-fg\r\n" 2019-02-09T21:14:15.061 :: +0.003 :: irc.tEq :: >> :: ":mk-fg JOIN #monitor\r\n" 2019-02-09T21:14:15.062 :: +0.001 :: irc.tEq :: >> :: "MODE #monitor +v mk-fg\r\n" ... ``` EDIT: there's PASS command in there, but it's not a security issue of any kind to expose it in this case. <!-- github-comment-id:462068683 -->
Author
Owner

What's the IRC server that is used here?

It's my own script - https://github.com/mk-fg/reliable-discord-client-irc-daemon
So would appreciate if you can spot and suggest what it does wrong when that connection happens.

Obvious fix would be adding some dummy ":source" prefix to every line from server, but that looks like a workaround in this case, as mentioned in the initial report.

> What's the IRC server that is used here? It's my own script - https://github.com/mk-fg/reliable-discord-client-irc-daemon So would appreciate if you can spot and suggest what it does wrong when that connection happens. Obvious fix would be adding some dummy ":source" prefix to every line from server, but that looks like a workaround in this case, as mentioned in the initial report. <!-- github-comment-id:462068874 -->
Author
Owner

... there was a space after the colon and the 353.

Btw, do see CString sPre = ":" + m_pNetwork->GetIRCServer() + " 353 " + ... in Chan.cpp, which should add that space, and that code didn't change for a while according to git, so guess either that 353 isn't generated there, message gets mangled later, or Arch package changes that part.

EDIT: it looks like line indeed might be parsed via BufLine.ToMessage() and re-assembled, which might be what's messing it up due to that empty source part.

> ... there was a space after the colon and the 353. Btw, do see `CString sPre = ":" + m_pNetwork->GetIRCServer() + " 353 " + ...` in Chan.cpp, which should add that space, and that code didn't change for a while according to git, so guess either that 353 isn't generated there, message gets mangled later, or Arch package changes that part. EDIT: it looks like line indeed might be parsed via BufLine.ToMessage() and re-assembled, which might be what's messing it up due to that empty source part. <!-- github-comment-id:462070101 -->
Author
Owner

It's my own script - https://github.com/mk-fg/reliable-discord-client-irc-daemon

Okay... I did not figure out what that uses to generate the 001s, but whatever.

My reading of RFC 2812 requires servers to send a prefix for all numerics (source: https://tools.ietf.org/html/rfc2812#section-2.4)

The numeric reply MUST be sent as one message consisting of the sender prefix, the three-digit numeric, and the target of the reply.

ZNC uses the prefix of 001 to figure out the server name, see the call to SetIRCServer in IRCSock.cpp. Since you send 001 without a prefix, the IRC server is set to an empty string. Then, when ZNC later "invents" numeric replies, it uses this empty server name as prefix and things go downhill from there.

ZNC could be more robust here (I guess using some default in GetIRCServer in case the current server name is empty), but I'd also say that relable-discorc-client-irc-daemon could send prefixes.

> It's my own script - https://github.com/mk-fg/reliable-discord-client-irc-daemon Okay... I did not figure out what that uses to generate the 001s, but whatever. My reading of RFC 2812 requires servers to send a prefix for all numerics (source: https://tools.ietf.org/html/rfc2812#section-2.4) > The numeric reply MUST be sent as one message consisting of the sender prefix, the three-digit numeric, and the target of the reply. ZNC uses the prefix of 001 to figure out the server name, see the call to `SetIRCServer` in `IRCSock.cpp`. Since you send 001 without a prefix, the IRC server is set to an empty string. Then, when ZNC later "invents" numeric replies, it uses this empty server name as prefix and things go downhill from there. ZNC could be more robust here (I guess using some default in `GetIRCServer` in case the current server name is empty), but I'd also say that relable-discorc-client-irc-daemon could send prefixes. <!-- github-comment-id:462075447 -->
Author
Owner

I can understand the confusion about the prefix being optional here because the previous section 2.3 says:

Each IRC message may consist of up to three main parts: the prefix (OPTIONAL), the command, and the command parameters (maximum of fifteen (15)).

However, "numeric replies" are specified as distinct from "messages" so the quoted "MUST" in 2.4 should taken to mean the prefix is not optional in numeric replies.

This is definitely a bug with the discord bridge, but yeah, would be worth hardening ZNC.

I can understand the confusion about the prefix being optional here because the previous section 2.3 says: > Each IRC message may consist of up to three main parts: the prefix (OPTIONAL), the command, and the command parameters (maximum of fifteen (15)). However, "numeric replies" are specified as distinct from "messages" so the quoted "MUST" in 2.4 should taken to mean the prefix is not optional in numeric replies. This is definitely a bug with the discord bridge, but yeah, would be worth hardening ZNC. <!-- github-comment-id:462077065 -->
Author
Owner

I was mostly going by modern.ircdocs.horse when implementing that, where numeric-replies section says that they're non-special, and as such that part should be optional, guess I'll file a bug there.

I was mostly going by modern.ircdocs.horse when implementing that, where [numeric-replies](https://modern.ircdocs.horse/#numeric-replies) section says that they're non-special, and as such that part should be optional, guess I'll file a bug there. <!-- github-comment-id:462077169 -->
Author
Owner

Well, that part of modern is basically a copy/paste of the rfcs and has that same MUST. It could definitely be clarified, but it's not in conflict or incorrect.

Well, that part of modern is basically a copy/paste of the rfcs and has that same MUST. It could definitely be clarified, but it's not in conflict or incorrect. <!-- github-comment-id:462077278 -->
Author
Owner

Oh, you're right, sorry, I just read it and somehow missed the "MUST" part, my bad, definitely not incorrect.

Oh, you're right, sorry, I just read it and somehow missed the "MUST" part, my bad, definitely not incorrect. <!-- github-comment-id:462077384 -->
Author
Owner

I filed a clarifying PR for modern: https://github.com/ircdocs/modern-irc/pull/72

I filed a clarifying PR for modern: https://github.com/ircdocs/modern-irc/pull/72 <!-- github-comment-id:462078239 -->
Author
Owner

Thanks!

Thanks! <!-- github-comment-id:462078323 -->
Sign in to join this conversation.
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: adam/znc#899