Skip to content

Commit

Permalink
Send a MODE request when JOINing
Browse files Browse the repository at this point in the history
This kind of reverts/fixes f1cb09b.

Robby found a bug with evil ChanServ which goes like this:

- You join an empty, but registered channel and the IRCd applies its default
  modes (+nt), but ZNC didn't ask for MODE, so doesn't know this.
- ChanServ applies whatever channel modes it wants to apply. This causes ZNC to
  see a mode change (e.g. +s).

The result of this is that ZNC thinks that the channel has mode +s and it will
tell every client that connects to it about this.

The fix is to send a MODE request when JOINing. To make sure that we don't
confuse clients, we block the reply.

Signed-off-by: Uli Schlachter <psychon@znc.in>
  • Loading branch information
psychon committed Sep 22, 2011
1 parent 4b1e714 commit 7683592
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 0 deletions.
1 change: 1 addition & 0 deletions Chan.cpp
Expand Up @@ -55,6 +55,7 @@ CChan::~CChan() {

void CChan::Reset() {
m_bIsOn = false;
m_bModeKnown = false;
m_musModes.clear();
m_sTopic = "";
m_sTopicOwner = "";
Expand Down
3 changes: 3 additions & 0 deletions Chan.h
Expand Up @@ -101,6 +101,7 @@ class CChan {
// !wrappers

// Setters
void SetModeKnown(bool b) { m_bModeKnown = b; }
void SetIsOn(bool b) { m_bIsOn = b; if (!b) { Reset(); } }
void SetKey(const CString& s) { m_sKey = s; }
void SetTopic(const CString& s) { m_sTopic = s; }
Expand All @@ -119,6 +120,7 @@ class CChan {
// !Setters

// Getters
bool IsModeKnown() const { return m_bModeKnown; }
bool HasMode(unsigned char uMode) const;
CString GetOptions() const;
CString GetModeArg(unsigned char uMode) const;
Expand Down Expand Up @@ -163,6 +165,7 @@ class CChan {
unsigned int m_uBufferCount;
vector<CString> m_vsBuffer;

bool m_bModeKnown;
map<unsigned char, CString> m_musModes;
};

Expand Down
18 changes: 18 additions & 0 deletions IRCSock.cpp
Expand Up @@ -193,6 +193,15 @@ void CIRCSock::ReadLine(const CString& sData) {

if (pChan) {
pChan->SetModes(sRest.Token(1, true));

// We don't SetModeKnown(true) here,
// because a 329 will follow
if (!pChan->IsModeKnown()) {
// When we JOIN, we send a MODE
// request. This makes sure the
// reply isn't forwarded.
return;
}
}
}
break;
Expand All @@ -203,6 +212,14 @@ void CIRCSock::ReadLine(const CString& sData) {
if (pChan) {
unsigned long ulDate = sLine.Token(4).ToULong();
pChan->SetCreationDate(ulDate);

if (!pChan->IsModeKnown()) {
pChan->SetModeKnown(true);
// When we JOIN, we send a MODE
// request. This makes sure the
// reply isn't forwarded.
return;
}
}
}
break;
Expand Down Expand Up @@ -436,6 +453,7 @@ void CIRCSock::ReadLine(const CString& sData) {
pChan->ResetJoinTries();
pChan->Enable();
pChan->SetIsOn(true);
PutIRC("MODE " + sChan);
}
} else {
pChan = m_pNetwork->FindChan(sChan);
Expand Down

0 comments on commit 7683592

Please sign in to comment.