diff options
| author | Nakidai <nakidai@disroot.org> | 2026-02-01 20:41:03 +0300 |
|---|---|---|
| committer | Nakidai <nakidai@disroot.org> | 2026-02-01 20:41:03 +0300 |
| commit | 724205c1bc157b8933b1c63ec37014c2f07842ae (patch) | |
| tree | 72095dd58e091e2d849e8b36ac14af7b4df82aa8 | |
| parent | e50f850d763e3b1e6b06b4b312512a5b006eabbc (diff) | |
| download | libreircd-724205c1bc157b8933b1c63ec37014c2f07842ae.tar.gz libreircd-724205c1bc157b8933b1c63ec37014c2f07842ae.zip | |
Add validation
Now there can't be single \r or \n in the message, erroneous nicks and channel names are rejected, and usernames are stripped on '@'
| -rw-r--r-- | handle.c | 35 | ||||
| -rw-r--r-- | peer.c | 4 | ||||
| -rw-r--r-- | reply.c | 6 |
3 files changed, 44 insertions, 1 deletions
diff --git a/handle.c b/handle.c index e84f098..c595f06 100644 --- a/handle.c +++ b/handle.c @@ -16,6 +16,7 @@ #include "ircd.h" +#include <ctype.h> #include <stddef.h> #include <stdio.h> #include <string.h> @@ -27,6 +28,7 @@ static int join(struct Message *msg, struct Peer *peer) { size_t i; + char *cp; /* TODO: support comma separated list of channels, keys */ ensure(peer->type, reply(peer, 451), 0); @@ -34,6 +36,12 @@ join(struct Message *msg, struct Peer *peer) ensure(peer->channels_c != lengthof(peer->channels), reply(peer, 405, msg->params[0]), 0) ensure(*msg->params[0] == '#', reply(peer, 403, msg->params[0]), 0); + for (cp = msg->params[0]; *cp; ++cp) + ensure( + *cp != '\a' && *cp != ',' && *cp != ':', + reply(peer, 403, msg->params[0]) + ); + for (i = 0; i < peer->channels_c; ++i) ensure(strcmp(channels[i].name, msg->params[0]), (void)0, 0); @@ -97,10 +105,29 @@ static int nick(struct Message *msg, struct Peer *peer) { size_t i; + char *cp; ensure(msg->params[0] && msg->params[0], reply(peer, 431), 0); ensure(!(peer->modes & RESTRICTED), reply(peer, 484), 0); + cp = msg->params[0]; + ensure( + isupper(*cp) || islower(*cp) + || 0x5b <= *cp && *cp <= 0x60 + || 0x7b <= *cp && *cp <= 0x7d, + reply(peer, 432, msg->params[0]), + 0 + ); + for (++cp; *cp; ++cp) + ensure( + isupper(*cp) || islower(*cp) || isdigit(*cp) + || 0x5b <= *cp && *cp <= 0x60 + || 0x7b <= *cp && *cp <= 0x7d + || *cp == '-', + reply(peer, 432, msg->params[0]), + 0 + ); + for (i = 0; i < peers_c; ++i) if (peers[i].fd != peer->fd) ensure( @@ -257,11 +284,19 @@ static int user(struct Message *msg, struct Peer *peer) { size_t i; + char *cp; ensure(!peer->type, reply(peer, 462), 0); for (i = 0; i < 4; ++i) ensure(msg->params[i] && *msg->params[i], reply(peer, 461), 0); + for (cp = msg->params[0]; *cp; ++cp) + if (*cp == '@') + { + *cp = 0; + break; + } + user_reg(peer, NULL, msg->params[0], msg->params[3], msg->params[1]); return 0; diff --git a/peer.c b/peer.c index 3634834..13d0f2a 100644 --- a/peer.c +++ b/peer.c @@ -47,7 +47,9 @@ handle(struct Peer *peer) } *p = 0; - if (parse_message(peer->buf, &msg)) + if (memchr(peer->buf, '\n', sizeof(peer->buf)) + || memchr(peer->buf, '\r', sizeof(peer->buf)) + || parse_message(peer->buf, &msg)) { warnx("malformed input from %d", peer->fd); goto next; diff --git a/reply.c b/reply.c index 5da4094..c8d526b 100644 --- a/reply.c +++ b/reply.c @@ -130,6 +130,12 @@ vreply(const struct Peer *peer, int number, va_list ap) hostname, getnick(peer) ), _); + REPLY(432, WRITE( + ":%s 432 %s %s :Erroneous nickname", + hostname, + getnick(peer), + nick + ), nick, _); REPLY(433, WRITE( ":%s 433 %s %s :Nickname is already in use", hostname, |