diff options
author | Sadie Powell <sadie@witchery.services> | 2024-11-24 23:56:57 +0000 |
---|---|---|
committer | Sadie Powell <sadie@witchery.services> | 2024-11-25 00:08:30 +0000 |
commit | 7019b27e591e0f5ce3727993e02198ae070885e9 (patch) | |
tree | 7752a85bb31f4bce07f63c3364a9f8d6c903daa2 | |
parent | 70227dc8823c0f9669e35dbf63593faaeef5410d (diff) |
Rework how guest nicks work.
- Use the config setting as a string template instead of as a prefix.
- Allow users of IRCds that have UIDs to use that as the guest nick.
- Fall back to a UID before killing if a guest nick can not be found.
-rw-r--r-- | data/nickserv.example.conf | 14 | ||||
-rw-r--r-- | include/modules/pseudoclients/nickserv.h | 1 | ||||
-rw-r--r-- | modules/nickserv/nickserv.cpp | 63 | ||||
-rw-r--r-- | modules/nickserv/ns_group.cpp | 9 | ||||
-rw-r--r-- | modules/nickserv/ns_register.cpp | 11 |
5 files changed, 65 insertions, 33 deletions
diff --git a/data/nickserv.example.conf b/data/nickserv.example.conf index a62379053..4d2ef3af8 100644 --- a/data/nickserv.example.conf +++ b/data/nickserv.example.conf @@ -203,13 +203,17 @@ module releasetimeout = 1m /* - * When a user's nick is forcibly changed to enforce a "nick kill", their new nick will start - * with this value. The rest will be made up of 6 or 7 digits. - * Make sure this is a valid nick and Nicklen+7 is not longer than the allowed Nicklen on your ircd. + * When a user's nick is forcibly changed to enforce nickname protection their new + * nick will be based on this value. Any # in the value will be replaced with a random + * number. If your IRCd has support for unique identifiers you can also set this to an + * empty string to change a user's nick to their unique identifier. * - * This directive is optional. If not set it defaults to "Guest" + * Make sure this is a valid nick and that it is is not longer than the maximum nick + * length on your IRCd. + * + * This directive is optional. If not set it defaults to "Guest####" */ - guestnickprefix = "Guest" + guestnick = "Guest####" /* * If set, Anope does not allow ownership of nick names, only ownership of accounts. diff --git a/include/modules/pseudoclients/nickserv.h b/include/modules/pseudoclients/nickserv.h index 58cf93bd9..f269537bf 100644 --- a/include/modules/pseudoclients/nickserv.h +++ b/include/modules/pseudoclients/nickserv.h @@ -19,4 +19,5 @@ public: virtual void Validate(User *u) = 0; virtual void Collide(User *u, NickAlias *na) = 0; virtual void Release(NickAlias *na) = 0; + virtual bool IsGuestNick(const Anope::string &nick) const = 0; }; diff --git a/modules/nickserv/nickserv.cpp b/modules/nickserv/nickserv.cpp index 04dd2e1e2..1328ecea5 100644 --- a/modules/nickserv/nickserv.cpp +++ b/modules/nickserv/nickserv.cpp @@ -174,6 +174,24 @@ public: OnShutdown(); } + bool IsGuestNick(const Anope::string &nick) const + { + const auto guestnick = Config->GetModule(this)->Get<Anope::string>("guestnick", "Guest####"); + if (guestnick.empty()) + return false; // No guest nick. + + const auto minlen = std::min(nick.length(), guestnick.length()); + for (size_t idx = 0; idx < minlen; ++idx) + { + if (guestnick[idx] == '#' && !isdigit(nick[idx])) + return false; + + if (Anope::tolower(guestnick[idx]) != Anope::tolower(nick[idx])) + return false; + } + return true; + } + void Validate(User *u) override { NickAlias *na = NickAlias::Find(u->nick); @@ -238,30 +256,47 @@ public: if (IRCD->CanSVSNick) { - unsigned nicklen = IRCD->MaxNick; - const Anope::string &guestprefix = Config->GetModule("nickserv")->Get<const Anope::string>("guestnickprefix", "Guest"); - + auto guestnickok = false; Anope::string guestnick; + for (auto i = 0; i < 10; ++i) + { + guestnick.clear(); + for (auto guestnickchr : Config->GetModule(this)->Get<Anope::string>("guestnick", "Guest####").substr(0, IRCD->MaxNick)) + { + if (guestnickchr == '#') + guestnick.append(Anope::ToString(abs(Anope::RandomNumber()) % 10)); + else + guestnick.push_back(guestnickchr); + } - int i = 0; - do + // A guest nick is valid if it is non-empty and is not in use. + if (!guestnick.empty() && !User::Find(guestnick, true)) + { + guestnickok = true; + break; + } + } + + // If we can't find a guest nick and the IRCd supports + // uids then we should use that as the backup guest + // nickname. + if (!guestnickok && IRCD->RequiresID) { - guestnick = guestprefix + Anope::ToString(static_cast<uint16_t>(Anope::RandomNumber())); - if (guestnick.length() > nicklen) - guestnick = guestnick.substr(0, nicklen); + guestnickok = true; + guestnick = u->GetUID(); } - while (User::Find(guestnick) && i++ < 10); - if (i == 11) - u->Kill(*NickServ, "Services nickname-enforcer kill"); - else + if (guestnickok) { u->SendMessage(*NickServ, _("Your nickname is now being changed to \002%s\002"), guestnick.c_str()); IRCD->SendForceNickChange(u, guestnick, Anope::CurTime); + return; } } - else - u->Kill(*NickServ, "Services nickname-enforcer kill"); + + // We can't change the user's nickname or we can't find an + // acceptable guest nick, give them the boot. + u->Kill(*NickServ, "Enforcement of services protected nickname"); } void Release(NickAlias *na) override diff --git a/modules/nickserv/ns_group.cpp b/modules/nickserv/ns_group.cpp index f2a7f33ae..3ccba782c 100644 --- a/modules/nickserv/ns_group.cpp +++ b/modules/nickserv/ns_group.cpp @@ -12,6 +12,8 @@ #include "module.h" #include "modules/ns_cert.h" +static ServiceReference<NickServService> nickserv("NickServService", "NickServ"); + class NSGroupRequest final : public IdentifyRequest { @@ -142,7 +144,6 @@ public: } NickAlias *target, *na = NickAlias::Find(source.GetNick()); - const Anope::string &guestnick = Config->GetModule("nickserv")->Get<const Anope::string>("guestnickprefix", "Guest"); time_t reg_delay = Config->GetModule("nickserv")->Get<time_t>("regdelay"); unsigned maxaliases = Config->GetModule(this->owner)->Get<unsigned>("maxaliases"); if (!(target = NickAlias::Find(nick))) @@ -165,12 +166,8 @@ public: source.Reply(NICK_IDENTIFY_REQUIRED); else if (maxaliases && target->nc->aliases->size() >= maxaliases && !target->nc->IsServicesOper()) source.Reply(_("There are too many nicks in your group.")); - else if (source.GetNick().length() <= guestnick.length() + 7 && - source.GetNick().length() >= guestnick.length() + 1 && - !source.GetNick().find_ci(guestnick) && !source.GetNick().substr(guestnick.length()).find_first_not_of("1234567890")) - { + else if (nickserv && nickserv->IsGuestNick(source.GetNick())) source.Reply(NICK_CANNOT_BE_REGISTERED, source.GetNick().c_str()); - } else { bool ok = false; diff --git a/modules/nickserv/ns_register.cpp b/modules/nickserv/ns_register.cpp index 4775fc594..692371c0e 100644 --- a/modules/nickserv/ns_register.cpp +++ b/modules/nickserv/ns_register.cpp @@ -13,6 +13,8 @@ static bool SendRegmail(User *u, const NickAlias *na, BotInfo *bi); +static ServiceReference<NickServService> nickserv("NickServService", "NickServ"); + class CommandNSConfirm final : public Command { @@ -133,7 +135,6 @@ public: { User *u = source.GetUser(); Anope::string u_nick = source.GetNick(); - size_t nicklen = u_nick.length(); Anope::string pass = params[0]; Anope::string email = params.size() > 1 ? params[1] : ""; const Anope::string &nsregister = Config->GetModule(this->owner)->Get<const Anope::string>("registration"); @@ -160,13 +161,7 @@ public: return; } - /* Prevent "Guest" nicks from being registered. -TheShadow */ - - /* Guest nick can now have a series of between 1 and 7 digits. - * --lara - */ - const Anope::string &guestnick = Config->GetModule("nickserv")->Get<const Anope::string>("guestnickprefix", "Guest"); - if (nicklen <= guestnick.length() + 7 && nicklen >= guestnick.length() + 1 && !u_nick.find_ci(guestnick) && u_nick.substr(guestnick.length()).find_first_not_of("1234567890") == Anope::string::npos) + if (nickserv && nickserv->IsGuestNick(u_nick)) { source.Reply(NICK_CANNOT_BE_REGISTERED, u_nick.c_str()); return; |