summary refs log tree commit diff
diff options
context:
space:
mode:
authorNakidai <nakidai@disroot.org>2026-02-05 14:11:41 +0300
committerNakidai <nakidai@disroot.org>2026-02-05 14:11:41 +0300
commit68a91231a9480d591b43b359ad9a02af1faef07b (patch)
treed09fe703286c6450a266e83580b7e6eddec87961
parent5c240d0121aa82ad4ced73b70d3a1674ae81c764 (diff)
downloadlibreircd-68a91231a9480d591b43b359ad9a02af1faef07b.tar.gz
libreircd-68a91231a9480d591b43b359ad9a02af1faef07b.zip
Add OPER/SETOPER
SETOPER is a command for config, OPER is the one to authorize a user
-rw-r--r--config.h3
-rw-r--r--config.irc1
-rw-r--r--handle.c57
-rw-r--r--ircd.h6
-rw-r--r--reply.c16
5 files changed, 83 insertions, 0 deletions
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 :<very secure password goes here>
diff --git a/handle.c b/handle.c
index b99e82d..fb08f73 100644
--- a/handle.c
+++ b/handle.c
@@ -24,6 +24,9 @@
 #include <err.h>
 
 
+static struct Oper opers[OPERS_MAX];
+size_t opers_c;
+
 static int names(struct Message *msg, struct Peer *peer);
 
 static int
@@ -192,6 +195,26 @@ nick(struct Message *msg, struct Peer *peer)
 }
 
 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)
 {
 	size_t i;
@@ -343,6 +366,38 @@ setinfo(struct Message *msg, struct Peer *peer)
 }
 
 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)
 {
 	size_t i;
@@ -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,