1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
|
//
// 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 "main.h"
#include "User.h"
#include "Nick.h"
#include "Modules.h"
#include "Chan.h"
#include "String.h"
#define REQUIRESSL 1
class CCryptMod : public CModule {
public:
MODCONSTRUCTOR(CCryptMod) {}
virtual ~CCryptMod() {
time_t t;
time(&t);
srand((long) t);
}
virtual EModRet OnRaw(CString& sLine) {
return CONTINUE;
}
virtual EModRet OnUserMsg(CString& sTarget, CString& sMessage) {
sTarget.TrimLeft("\244");
MCString::iterator it = FindNV(sTarget.AsLower());
if (it != EndNV()) {
CChan* pChan = m_pUser->FindChan(sTarget);
if ((pChan) && (pChan->KeepBuffer())) {
pChan->AddBuffer(":\244" + m_pUser->GetIRCNick().GetNickMask() + " PRIVMSG " + sTarget + " :" + sMessage);
}
sMessage = MakeIvec() + sMessage;
sMessage.Encrypt(it->second);
sMessage.Base64Encode();
sMessage = "+OK *" + sMessage;
PutIRC("PRIVMSG " + sTarget + " :" + sMessage);
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.CaseCmp("DELKEY") == 0) {
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.CaseCmp("SETKEY") == 0) {
CString sTarget = sCommand.Token(1);
CString sKey = sCommand.Token(2, true);
// Strip "cbc:" from beginning of string incase someone pastes directly from mircryption
if (sKey.Left(4).CaseCmp("cbc:") == 0) {
sKey.LeftChomp(4);
}
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.CaseCmp("LISTKEYS") == 0) {
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);
}
if (Table.size()) {
unsigned int uTableIdx = 0;
CString sLine;
while (Table.GetLine(uTableIdx++, sLine)) {
PutModule(sLine);
}
}
}
} else if (sCmd.CaseCmp("HELP") == 0) {
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;
}
};
MODULEDEFS(CCryptMod, "Encryption for channel/private messages")
|