Files
znc/modules/crypt.cpp
Alexey Sokolov b2dcad5fd4 Change ZNC license to Apache 2.0
The following people agreed with the change, in alphabetical order:
(people who approved in several ways are listed only once)
By email:
- Adam (from Anope)
- Austin Morton
- Brian Campbell
- Christian Walde
- Daniel Holbert
- Daniel Wallace
- Falk Seidel
- Heiko Hund
- Ingmar Runge
- Jim Hull
- Kyle Fuller
- Lee Aylward
- Martin Martimeo
- Matt Harper
- Michael J Edgar
- Michael Ziegler
- Nick Bebout
- Paul Driver
- Perry Nguyen
- Philippe (cycomate)
- Reuben Morais
- Roland Hieber
- Sebastian Ramacher
- Stefan Rado
- Stéphan Kochen
- Thomas Ward
- Toon Schoenmakers
- Veit Wahlich
- Wulf C. Krueger

By IRC:
- CNU
- Jonas Gorski
- Joshua M. Clulow
- Prozac/SHiZNO
- SilverLeo
- Uli Schlachter

At https://github.com/znc/znc/issues/311 :
- Alexey Sokolov
- Elizabeth Myers
- flakes
- Jens-Andre Koch
- Jyzee
- KindOne/ineedalifetoday
- Lee Williams
- Mantas Mikulėnas
- md-5
- Reed Loden

At the last few pull requests' comments:
- Allan Odgaard
- Jacob Baines
- Lluís Batlle i Rossell
- ravomavain
- protomouse

The following commits' authors didn't respond:
Trivial changes:
- f70f1086fd
- 4ca8b50e45

The changes which are not presented in master anymore:
- 5512ed2ea0
- 960a4498f7
- 0f739de2c0
- 7f53cc810b

Fix #311
Fix #218
2013-06-14 00:43:34 +04:00

168 lines
4.8 KiB
C++

/*
* Copyright (C) 2004-2013 ZNC, see the NOTICE file for details.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
//! @author prozac@rottenboy.com
//
// The encryption here was designed to be compatible with mircryption's CBC mode.
//
// TODO:
//
// 1) Encrypt key storage file
// 2) Secure key exchange using pub/priv keys and the DH algorithm
// 3) Some way of notifying the user that the current channel is in "encryption mode" verses plain text
// 4) Temporarily disable a target (nick/chan)
//
// NOTE: This module is currently NOT intended to secure you from your shell admin.
// The keys are currently stored in plain text, so anyone with access to your account (or root) can obtain them.
// It is strongly suggested that you enable SSL between znc and your client otherwise the encryption stops at znc and gets sent to your client in plain text.
//
#include <znc/Chan.h>
#include <znc/User.h>
#include <znc/IRCNetwork.h>
#define REQUIRESSL 1
class CCryptMod : public CModule {
public:
MODCONSTRUCTOR(CCryptMod) {}
virtual ~CCryptMod() {}
virtual EModRet OnUserMsg(CString& sTarget, CString& sMessage) {
sTarget.TrimLeft("\244");
if (sMessage.Left(2) == "``") {
sMessage.LeftChomp(2);
return CONTINUE;
}
MCString::iterator it = FindNV(sTarget.AsLower());
if (it != EndNV()) {
CChan* pChan = m_pNetwork->FindChan(sTarget);
if (pChan) {
if (!pChan->AutoClearChanBuffer())
pChan->AddBuffer(":\244" + _NAMEDFMT(m_pNetwork->GetIRCNick().GetNickMask()) + " PRIVMSG " + _NAMEDFMT(sTarget) + " :" + _NAMEDFMT(sMessage));
m_pUser->PutUser(":\244" + m_pNetwork->GetIRCNick().GetNickMask() + " PRIVMSG " + sTarget + " :" + sMessage, NULL, m_pClient);
}
CString sMsg = MakeIvec() + sMessage;
sMsg.Encrypt(it->second);
sMsg.Base64Encode();
sMsg = "+OK *" + sMsg;
PutIRC("PRIVMSG " + sTarget + " :" + sMsg);
return HALTCORE;
}
return CONTINUE;
}
virtual EModRet OnPrivMsg(CNick& Nick, CString& sMessage) {
FilterIncoming(Nick.GetNick(), Nick, sMessage);
return CONTINUE;
}
virtual EModRet OnChanMsg(CNick& Nick, CChan& Channel, CString& sMessage) {
FilterIncoming(Channel.GetName(), Nick, sMessage);
return CONTINUE;
}
void FilterIncoming(const CString& sTarget, CNick& Nick, CString& sMessage) {
if (sMessage.Left(5) == "+OK *") {
MCString::iterator it = FindNV(sTarget.AsLower());
if (it != EndNV()) {
sMessage.LeftChomp(5);
sMessage.Base64Decode();
sMessage.Decrypt(it->second);
sMessage.LeftChomp(8);
sMessage = sMessage.c_str();
Nick.SetNick("\244" + Nick.GetNick());
}
}
}
virtual void OnModCommand(const CString& sCommand) {
CString sCmd = sCommand.Token(0);
if (sCmd.Equals("DELKEY")) {
CString sTarget = sCommand.Token(1);
if (!sTarget.empty()) {
if (DelNV(sTarget.AsLower())) {
PutModule("Target [" + sTarget + "] deleted");
} else {
PutModule("Target [" + sTarget + "] not found");
}
} else {
PutModule("Usage DelKey <#chan|Nick>");
}
} else if (sCmd.Equals("SETKEY")) {
CString sTarget = sCommand.Token(1);
CString sKey = sCommand.Token(2, true);
// Strip "cbc:" from beginning of string incase someone pastes directly from mircryption
sKey.TrimPrefix("cbc:");
if (!sKey.empty()) {
SetNV(sTarget.AsLower(), sKey);
PutModule("Set encryption key for [" + sTarget + "] to [" + sKey + "]");
} else {
PutModule("Usage: SetKey <#chan|Nick> <Key>");
}
} else if (sCmd.Equals("LISTKEYS")) {
if (BeginNV() == EndNV()) {
PutModule("You have no encryption keys set.");
} else {
CTable Table;
Table.AddColumn("Target");
Table.AddColumn("Key");
for (MCString::iterator it = BeginNV(); it != EndNV(); ++it) {
Table.AddRow();
Table.SetCell("Target", it->first);
Table.SetCell("Key", it->second);
}
PutModule(Table);
}
} else if (sCmd.Equals("HELP")) {
PutModule("Try: SetKey, DelKey, ListKeys");
} else {
PutModule("Unknown command, try 'Help'");
}
}
CString MakeIvec() {
CString sRet;
time_t t;
time(&t);
int r = rand();
sRet.append((char*) &t, 4);
sRet.append((char*) &r, 4);
return sRet;
}
};
template<> void TModInfo<CCryptMod>(CModInfo& Info) {
Info.SetWikiPage("crypt");
}
NETWORKMODULEDEFS(CCryptMod, "Encryption for channel/private messages")