Add a way to disable certain capabilities

This is a way for admins to mitigate some issues caused by caps if such issues ever arise.

E.g. add this to global level in znc.conf:

DisableClientCap = sasl
DisableServerCap = chghost
DisableServerCap = message-tags

Then these caps will be NAKed to client / not requested from server.

Note that this mechanism doesn't fully prevent a cap from being activated, e.g. one could use *send_raw module to request it from server even when disabled.
This commit is contained in:
Alexey Sokolov
2025-05-08 21:55:40 +01:00
parent 1063b7f5d6
commit 1c197a5508
5 changed files with 58 additions and 4 deletions

View File

@@ -815,7 +815,8 @@ void CClient::RespondCap(const CString& sResponse) {
PutClient(":irc.znc.in CAP " + GetNick() + " " + sResponse);
}
static VCString MultiLine(const SCString& ssCaps) {
template <typename ManyStrings>
static VCString MultiLine(const ManyStrings& ssCaps) {
VCString vsRes = {""};
for (const CString& sCap : ssCaps) {
if (vsRes.back().length() + sCap.length() > 400) {
@@ -917,7 +918,15 @@ void CClient::HandleCap(const CMessage& Message) {
}
}
NETWORKMODULECALL(OnClientCapLs(this, ssOfferCaps), GetUser(), GetNetwork(), this, NOTHING);
VCString vsCaps = MultiLine(ssOfferCaps);
VCString vsFilteredCaps;
vsFilteredCaps.reserve(ssOfferCaps.size());
for (CString sCap : std::move(ssOfferCaps)) {
if (!CZNC::Get().GetClientCapBlacklist().count(
sCap.Token(0, false, "="))) {
vsFilteredCaps.push_back(std::move(sCap));
}
}
VCString vsCaps = MultiLine(vsFilteredCaps);
m_bInCap = true;
if (HasCap302()) {
m_bCapNotify = true;
@@ -961,7 +970,7 @@ void CClient::HandleCap(const CMessage& Message) {
NETWORKMODULECALL(IsClientCapSupported(this, sCap, bVal), GetUser(), GetNetwork(), this,
&bAccepted);
if (!bAccepted) {
if (!bAccepted || CZNC::Get().GetClientCapBlacklist().count(sCap)) {
// Some unsupported capability is requested
RespondCap("NAK :" + Message.GetParam(1));
return;