diff options
author | Sadie Powell <sadie@witchery.services> | 2023-11-14 15:02:04 +0000 |
---|---|---|
committer | Sadie Powell <sadie@witchery.services> | 2023-11-14 15:02:04 +0000 |
commit | b28180d680f974b7d3cf72667681b8cda6a39b0a (patch) | |
tree | 45ce01374a4eb95c7b9bca73f25bc28dfefb2721 | |
parent | 0f1f0c5a221d199fefc38e116a98fb4ff2c0a4f3 (diff) |
Implement support for the ANONYMOUS SASL mechanism.
-rw-r--r-- | include/protocol.h | 2 | ||||
-rw-r--r-- | modules/m_sasl.cpp | 44 | ||||
-rw-r--r-- | modules/protocol/inspircd.cpp | 32 | ||||
-rw-r--r-- | modules/protocol/solanum.cpp | 10 | ||||
-rw-r--r-- | modules/protocol/unrealircd.cpp | 14 | ||||
-rw-r--r-- | src/protocol.cpp | 2 |
6 files changed, 80 insertions, 24 deletions
diff --git a/include/protocol.h b/include/protocol.h index 4f7990b51..9967012c0 100644 --- a/include/protocol.h +++ b/include/protocol.h @@ -64,6 +64,8 @@ class CoreExport IRCDProto : public Service bool CanCertFP; /* Can we send arbitrary message tags? */ bool CanSendTags; + /* Can users log out before being fully connected? */ + bool CanSVSLogout; /* Whether this IRCd requires unique IDs for each user or server. See TS6/P10. */ bool RequiresID; /* If this IRCd has unique ids, whether the IDs and nicknames are ambiguous */ diff --git a/modules/m_sasl.cpp b/modules/m_sasl.cpp index d14118e3c..c7e3a0585 100644 --- a/modules/m_sasl.cpp +++ b/modules/m_sasl.cpp @@ -124,6 +124,42 @@ class External : public Mechanism } }; +class Anonymous : public Mechanism +{ + public: + Anonymous(Module *o) : Mechanism(o, "ANONYMOUS") { } + + void ProcessMessage(Session *sess, const SASL::Message &m) override + { + if (!IRCD->CanSVSLogout && !User::Find(sess->uid)) + { + // This IRCd can't log users out yet. + sasl->Fail(sess); + delete sess; + return; + } + + if (m.type == "S") + { + sasl->SendMessage(sess, "C", "+"); + } + else if (m.type == "C") + { + Anope::string decoded; + Anope::B64Decode(m.data, decoded); + + Anope::string user = "A user"; + if (!sess->hostname.empty() && !sess->ip.empty()) + user = sess->hostname + " (" + sess->ip + ")"; + if (!decoded.empty()) + user += " [" + decoded + "]"; + + Log(this->owner, "sasl", Config->GetClient("NickServ")) << user << " unidentified using SASL ANONYMOUS"; + sasl->Succeed(sess, nullptr); + } + } +}; + class SASLService : public SASL::Service, public Timer { std::map<Anope::string, SASL::Session *> sessions; @@ -257,7 +293,10 @@ class SASLService : public SASL::Service, public Timer NickAlias *na = NickAlias::Find(nc->display); if (user) { - user->Identify(na); + if (na) + user->Identify(na); + else + user->Logout(); } else { @@ -302,6 +341,7 @@ class ModuleSASL : public Module { SASLService sasl; + Anonymous anonymous; Plain plain; External *external = nullptr; @@ -322,7 +362,7 @@ class ModuleSASL : public Module public: ModuleSASL(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR), - sasl(this), plain(this) + sasl(this), anonymous(this), plain(this) { try { diff --git a/modules/protocol/inspircd.cpp b/modules/protocol/inspircd.cpp index e76d745e3..3183e59ee 100644 --- a/modules/protocol/inspircd.cpp +++ b/modules/protocol/inspircd.cpp @@ -75,6 +75,7 @@ class InspIRCdProto : public IRCDProto CanSQLineChannel = true; CanSZLine = true; CanSVSHold = true; + CanSVSLogout = true; CanCertFP = true; CanSendTags = true; RequiresID = true; @@ -461,27 +462,30 @@ class InspIRCdProto : public IRCDProto { SendAccount(uid, na); - if (!na->GetVhostIdent().empty()) - UplinkSocket::Message(Me) << "ENCAP " << uid.substr(0, 3) << " CHGIDENT " << uid << " " << na->GetVhostIdent(); - if (!na->GetVhostHost().empty()) - UplinkSocket::Message(Me) << "ENCAP " << uid.substr(0, 3) << " CHGHOST " << uid << " " << na->GetVhostHost(); - - SASLUser su; - su.uid = uid; - su.acc = na->nc->display; - su.created = Anope::CurTime; - - for (std::list<SASLUser>::iterator it = saslusers.begin(); it != saslusers.end();) + // Expire old pending sessions or other sessions for this user. + for (auto it = saslusers.begin(); it != saslusers.end(); ) { - SASLUser &u = *it; - + const SASLUser &u = *it; if (u.created + 30 < Anope::CurTime || u.uid == uid) it = saslusers.erase(it); else ++it; } - saslusers.push_back(su); + if (na) + { + if (!na->GetVhostIdent().empty()) + UplinkSocket::Message(Me) << "ENCAP " << uid.substr(0, 3) << " CHGIDENT " << uid << " " << na->GetVhostIdent(); + if (!na->GetVhostHost().empty()) + UplinkSocket::Message(Me) << "ENCAP " << uid.substr(0, 3) << " CHGHOST " << uid << " " << na->GetVhostHost(); + + // Mark this SASL session as pending user introduction. + SASLUser su; + su.uid = uid; + su.acc = na->nc->display; + su.created = Anope::CurTime; + saslusers.push_back(su); + } } bool IsExtbanValid(const Anope::string &mask) override diff --git a/modules/protocol/solanum.cpp b/modules/protocol/solanum.cpp index 1ba740d04..c01c4f551 100644 --- a/modules/protocol/solanum.cpp +++ b/modules/protocol/solanum.cpp @@ -43,6 +43,7 @@ class SolanumProto : public IRCDProto CanSZLine = true; CanSVSNick = true; CanSVSHold = true; + CanSVSLogout = true; CanSetVHost = true; RequiresID = true; MaxModes = 4; @@ -158,8 +159,13 @@ class SolanumProto : public IRCDProto void SendSVSLogin(const Anope::string &uid, NickAlias *na) override { Server *s = Server::Find(uid.substr(0, 3)); - UplinkSocket::Message(Me) << "ENCAP " << (s ? s->GetName() : uid.substr(0, 3)) << " SVSLOGIN " << uid << " * " << (!na->GetVhostIdent().empty() ? na->GetVhostIdent() : '*') - << " " << (!na->GetVhostHost().empty() ? na->GetVhostHost() : '*') << " " << na->nc->display; + + UplinkSocket::Message(Me) << "ENCAP " << (s ? s->GetName() : uid.substr(0, 3)) << " SVSLOGIN " << uid << " * " + << (na && !na->GetVhostIdent().empty() ? na->GetVhostIdent() : '*') + << " " + << (na && !na->GetVhostHost().empty() ? na->GetVhostHost() : '*') + << " " + << (na ? na->nc->display : "0"); } }; diff --git a/modules/protocol/unrealircd.cpp b/modules/protocol/unrealircd.cpp index a6b0aaef8..88826b7da 100644 --- a/modules/protocol/unrealircd.cpp +++ b/modules/protocol/unrealircd.cpp @@ -34,6 +34,7 @@ class UnrealIRCdProto : public IRCDProto CanSQLineChannel = true; CanSZLine = true; CanSVSHold = true; + CanSVSLogout = true; CanCertFP = true; RequiresID = true; MaxModes = 12; @@ -401,11 +402,14 @@ class UnrealIRCdProto : public IRCDProto distmask = uid.substr(0, p); } - if (!na->GetVhostIdent().empty()) - UplinkSocket::Message(Me) << "CHGIDENT " << uid << " " << na->GetVhostIdent(); - if (!na->GetVhostHost().empty()) - UplinkSocket::Message(Me) << "CHGHOST " << uid << " " << na->GetVhostHost(); - UplinkSocket::Message(Me) << "SVSLOGIN " << distmask << " " << uid << " " << na->nc->display; + if (na) + { + if (!na->GetVhostIdent().empty()) + UplinkSocket::Message(Me) << "CHGIDENT " << uid << " " << na->GetVhostIdent(); + if (!na->GetVhostHost().empty()) + UplinkSocket::Message(Me) << "CHGHOST " << uid << " " << na->GetVhostHost(); + } + UplinkSocket::Message(Me) << "SVSLOGIN " << distmask << " " << uid << " " << (na ? na->nc->display : "0"); } bool IsIdentValid(const Anope::string &ident) override diff --git a/src/protocol.cpp b/src/protocol.cpp index 090187819..98953cabc 100644 --- a/src/protocol.cpp +++ b/src/protocol.cpp @@ -25,7 +25,7 @@ IRCDProto::IRCDProto(Module *creator, const Anope::string &p) : Service(creator, { DefaultPseudoclientModes = "+io"; CanSVSNick = CanSVSJoin = CanSetVHost = CanSetVIdent = CanSNLine = CanSQLine = CanSQLineChannel - = CanSZLine = CanSVSHold = CanCertFP = CanSendTags = RequiresID = AmbiguousID = false; + = CanSZLine = CanSVSHold = CanCertFP = CanSendTags = CanSVSLogout = RequiresID = AmbiguousID = false; MaxModes = 3; MaxLine = 512; |