diff --git a/ChangeLog.md b/ChangeLog.md index f4525425..de4156b8 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,3 +1,13 @@ +# ZNC 1.7.3 (2019-03-30) + +## Fixes +This is a security release to fix CVE-2019-9917. Thanks to LunarBNC for the bugreport. + +## New +Docker only: the znc image now supports --user option of docker run. + + + # ZNC 1.7.2 (2019-01-19) ## New diff --git a/modules/controlpanel.cpp b/modules/controlpanel.cpp index db22b574..913cdd6f 100644 --- a/modules/controlpanel.cpp +++ b/modules/controlpanel.cpp @@ -495,7 +495,7 @@ class CAdminMod : public CModule { #ifdef HAVE_ICU else if (sVar == "clientencoding") { pUser->SetClientEncoding(sValue); - PutModule("ClientEncoding = " + sValue); + PutModule("ClientEncoding = " + pUser->GetClientEncoding()); } #endif else diff --git a/src/IRCNetwork.cpp b/src/IRCNetwork.cpp index b92e7b30..3872ace9 100644 --- a/src/IRCNetwork.cpp +++ b/src/IRCNetwork.cpp @@ -1482,9 +1482,9 @@ void CIRCNetwork::SetBindHost(const CString& s) { } void CIRCNetwork::SetEncoding(const CString& s) { - m_sEncoding = s; + m_sEncoding = CZNC::Get().FixupEncoding(s); if (GetIRCSock()) { - GetIRCSock()->SetEncoding(s); + GetIRCSock()->SetEncoding(m_sEncoding); } } diff --git a/src/User.cpp b/src/User.cpp index 0198d9b0..428e0906 100644 --- a/src/User.cpp +++ b/src/User.cpp @@ -1264,9 +1264,9 @@ void CUser::SetAdmin(bool b) { m_bAdmin = b; } void CUser::SetDenySetBindHost(bool b) { m_bDenySetBindHost = b; } void CUser::SetDefaultChanModes(const CString& s) { m_sDefaultChanModes = s; } void CUser::SetClientEncoding(const CString& s) { - m_sClientEncoding = s; + m_sClientEncoding = CZNC::Get().FixupEncoding(s); for (CClient* pClient : GetAllClients()) { - pClient->SetEncoding(s); + pClient->SetEncoding(m_sClientEncoding); } } void CUser::SetQuitMsg(const CString& s) { m_sQuitMsg = s; } diff --git a/src/znc.cpp b/src/znc.cpp index 26d1bd08..bd127a41 100644 --- a/src/znc.cpp +++ b/src/znc.cpp @@ -2091,18 +2091,36 @@ void CZNC::ForceEncoding() { m_uiForceEncoding++; #ifdef HAVE_ICU for (Csock* pSock : GetManager()) { - if (pSock->GetEncoding().empty()) { - pSock->SetEncoding("UTF-8"); - } + pSock->SetEncoding(FixupEncoding(pSock->GetEncoding())); } #endif } void CZNC::UnforceEncoding() { m_uiForceEncoding--; } bool CZNC::IsForcingEncoding() const { return m_uiForceEncoding; } CString CZNC::FixupEncoding(const CString& sEncoding) const { - if (sEncoding.empty() && m_uiForceEncoding) { + if (!m_uiForceEncoding) { + return sEncoding; + } + if (sEncoding.empty()) { return "UTF-8"; } + const char* sRealEncoding = sEncoding.c_str(); + if (sEncoding[0] == '*' || sEncoding[0] == '^') { + sRealEncoding++; + } + if (!*sRealEncoding) { + return "UTF-8"; + } +#ifdef HAVE_ICU + UErrorCode e = U_ZERO_ERROR; + UConverter* cnv = ucnv_open(sRealEncoding, &e); + if (cnv) { + ucnv_close(cnv); + } + if (U_FAILURE(e)) { + return "UTF-8"; + } +#endif return sEncoding; } diff --git a/test/integration/tests/scripting.cpp b/test/integration/tests/scripting.cpp index 8c9fa6ca..3116f832 100644 --- a/test/integration/tests/scripting.cpp +++ b/test/integration/tests/scripting.cpp @@ -55,6 +55,13 @@ TEST_F(ZNCTest, Modpython) { ircd.Write(":n!u@h PRIVMSG nick :Hi\xF0, github issue #1229"); // "replacement character" client.ReadUntil("Hi\xEF\xBF\xBD, github issue"); + + // Non-existing encoding + client.Write("PRIVMSG *controlpanel :Set ClientEncoding $me Western"); + client.Write("JOIN #a\342"); + client.ReadUntil( + ":*controlpanel!znc@znc.in PRIVMSG nick :ClientEncoding = UTF-8"); + ircd.ReadUntil("JOIN #a\xEF\xBF\xBD"); } TEST_F(ZNCTest, ModpythonSocket) {