From 68a91231a9480d591b43b359ad9a02af1faef07b Mon Sep 17 00:00:00 2001 From: Nakidai Date: Thu, 5 Feb 2026 14:11:41 +0300 Subject: Add OPER/SETOPER SETOPER is a command for config, OPER is the one to authorize a user --- config.h | 3 +++ config.irc | 1 + handle.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ircd.h | 6 ++++++ reply.c | 16 ++++++++++++++++ 5 files changed, 83 insertions(+) diff --git a/config.h b/config.h index 1aefc9d..965d835 100644 --- a/config.h +++ b/config.h @@ -24,6 +24,7 @@ #define PARAM_MAX 15 #define MESSAGE_MAX 512 #define PEERS_MAX 100 +#define OPERS_MAX 8 #define CHANNELS_MAX 100 #define CHANNEL_USERS_MAX 100 @@ -39,4 +40,6 @@ #define PEER_PINGTIMEOUT 120 #define PEER_PONGTIMEOUT 20 +#define OPER_PASS_MAX 64 + #define POLL_TIMEOUT min(PEER_PINGTIMEOUT, PEER_PONGTIMEOUT) diff --git a/config.irc b/config.irc index d86cc62..54b6833 100644 --- a/config.irc +++ b/config.irc @@ -1,2 +1,3 @@ setcreation :Thu Jan 1 1970 at 00:00:00 UTC setinfo :The best IRC server ever \o/ +setoper oper : diff --git a/handle.c b/handle.c index b99e82d..fb08f73 100644 --- a/handle.c +++ b/handle.c @@ -24,6 +24,9 @@ #include +static struct Oper opers[OPERS_MAX]; +size_t opers_c; + static int names(struct Message *msg, struct Peer *peer); static int @@ -191,6 +194,26 @@ nick(struct Message *msg, struct Peer *peer) return 0; } +static int +oper(struct Message *msg, struct Peer *peer) +{ + size_t i; + + ensure(peer->type, reply(peer, 451), 0); + ensure(msg->params[0] && *msg->params[0], reply(peer, 461), 0); + ensure(msg->params[1] && *msg->params[1], reply(peer, 464), 0); + + for (i = 0; i < opers_c; ++i) + if (!strcmp(opers[i].nick, msg->params[0])) + break; + ensure(i != opers_c && !strcmp(opers[i].pass, msg->params[1]), reply(peer, 464), 0); + + peer->modes |= OPER; + reply(peer, 381); + + return 0; +} + static int part(struct Message *msg, struct Peer *peer) { @@ -342,6 +365,38 @@ setinfo(struct Message *msg, struct Peer *peer) return 0; } +static int +setoper(struct Message *msg, struct Peer *peer) +{ + size_t i; + + ensure(peer->type == CONFIG, reply(peer, 481, "You're not a config file"), 0); + ensure(msg->params[0] && *msg->params[0], reply(peer, 461), 0); + ensure(msg->params[1], reply(peer, 461), 0); + ensure( + !*msg->params[1] || *msg->params[1] && opers_c < OPERS_MAX, + reply(peer, 420, msg->params[0]), + 0 + ); + + for (i = 0; i < opers_c; ++i) + if (!strcmp(opers[i].nick, msg->params[0])) + break; + + if (*msg->params[1]) + { + ++opers_c; + strlcpy(opers[i].nick, msg->params[0], sizeof(opers->pass)); + strlcpy(opers[i].pass, msg->params[1], sizeof(opers->pass)); + } + else if (i < PEERS_MAX) + { + opers[i] = opers[--opers_c]; + } + + return 0; +} + static int user(struct Message *msg, struct Peer *peer) { @@ -422,6 +477,7 @@ static struct Handler { { "names", names }, { "nick", nick }, { "notice", privmsg }, + { "oper", oper }, { "part", part }, { "ping", ping }, { "pong", pong }, @@ -429,6 +485,7 @@ static struct Handler { { "quit", quit }, { "setcreation", setcreation }, { "setinfo", setinfo }, + { "setoper", setoper }, { "user", user }, { "whois", whois }, }; diff --git a/ircd.h b/ircd.h index f85d33f..d05614c 100644 --- a/ircd.h +++ b/ircd.h @@ -73,6 +73,12 @@ struct Channel size_t modes_c, users_c; }; +struct Oper +{ + char nick[PEER_NICK_MAX]; + char pass[OPER_PASS_MAX]; +}; + typedef int Handler(struct Message *msg, struct Peer *peer); extern struct Channel channels[CHANNELS_MAX]; diff --git a/reply.c b/reply.c index 6670ecf..c5609e9 100644 --- a/reply.c +++ b/reply.c @@ -146,6 +146,11 @@ vreply(const struct Peer *peer, int number, va_list ap) getnick(peer), channel ), channel, _); + REPLY(381, WRITE( + ":%s 381 %s :You are now an IRC operator", + hostname, + getnick(peer) + ), _); REPLY(401, WRITE( ":%s 401 %s %s :No such nick/channel", hostname, @@ -179,6 +184,12 @@ vreply(const struct Peer *peer, int number, va_list ap) hostname, getnick(peer) ), _); + REPLY(420, WRITE( + ":%s 420 %s %s :OPER list is full", + hostname, + getnick(peer), + nick + ), nick, _); REPLY(421, WRITE( ":%s 421 %s %s :Unknown command", hostname, @@ -224,6 +235,11 @@ vreply(const struct Peer *peer, int number, va_list ap) hostname, getnick(peer) ), _); + REPLY(464, WRITE( + ":%s 464 %s :Pasword incorrect", + hostname, + getnick(peer) + ), _); REPLY(471, WRITE( ":%s 471 %s %s :Cannot join channel (+l)", hostname, -- cgit 1.4.1