~vcs-imports-ii/znc/master

839 by psychon
Switch to the copyright headers the GPLv2 wants us to have
1
/*
2930 by Alexey Sokolov
Change ZNC license to Apache 2.0
2
 * Copyright (C) 2004-2013 ZNC, see the NOTICE file for details.
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *     http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
839 by psychon
Switch to the copyright headers the GPLv2 wants us to have
15
 */
16
751 by prozacx
Added contact info
17
//! @author prozac@rottenboy.com
954 by psychon
And fix a shitload of trailing whitespaces and space / tab mixups in ZNC
18
//
538 by prozacx
Encryption module
19
// The encryption here was designed to be compatible with mircryption's CBC mode.
954 by psychon
And fix a shitload of trailing whitespaces and space / tab mixups in ZNC
20
//
538 by prozacx
Encryption module
21
// TODO:
954 by psychon
And fix a shitload of trailing whitespaces and space / tab mixups in ZNC
22
//
538 by prozacx
Encryption module
23
// 1) Encrypt key storage file
24
// 2) Secure key exchange using pub/priv keys and the DH algorithm
25
// 3) Some way of notifying the user that the current channel is in "encryption mode" verses plain text
26
// 4) Temporarily disable a target (nick/chan)
954 by psychon
And fix a shitload of trailing whitespaces and space / tab mixups in ZNC
27
//
538 by prozacx
Encryption module
28
// NOTE: This module is currently NOT intended to secure you from your shell admin.
29
//       The keys are currently stored in plain text, so anyone with access to your account (or root) can obtain them.
30
//       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.
954 by psychon
And fix a shitload of trailing whitespaces and space / tab mixups in ZNC
31
//
538 by prozacx
Encryption module
32
2516.2.1 by Alexey Sokolov
Move ZNC headers into own directory.
33
#include <znc/Chan.h>
34
#include <znc/User.h>
35
#include <znc/IRCNetwork.h>
538 by prozacx
Encryption module
36
37
#define REQUIRESSL	1
2887.1.2 by Allan Odgaard
crypt: Use ASCII for nick prefix and make it configurable
38
#define NICK_PREFIX_KEY	"[nick-prefix]"
538 by prozacx
Encryption module
39
40
class CCryptMod : public CModule {
2887.1.2 by Allan Odgaard
crypt: Use ASCII for nick prefix and make it configurable
41
	CString NickPrefix() {
42
		MCString::iterator it = FindNV(NICK_PREFIX_KEY);
43
		return it != EndNV() ? it->second : "*";
44
	}
45
538 by prozacx
Encryption module
46
public:
47
	MODCONSTRUCTOR(CCryptMod) {}
872 by psychon
Remove some code from crypt which makes no sense
48
	virtual ~CCryptMod() {}
538 by prozacx
Encryption module
49
50
	virtual EModRet OnUserMsg(CString& sTarget, CString& sMessage) {
2887.1.2 by Allan Odgaard
crypt: Use ASCII for nick prefix and make it configurable
51
		sTarget.TrimLeft(NickPrefix());
744 by prozacx
Added support for to talk unencrypted
52
53
		if (sMessage.Left(2) == "``") {
54
			sMessage.LeftChomp(2);
55
			return CONTINUE;
56
		}
57
538 by prozacx
Encryption module
58
		MCString::iterator it = FindNV(sTarget.AsLower());
59
60
		if (it != EndNV()) {
2439 by Kyle Fuller
Make all the modules support networks
61
			CChan* pChan = m_pNetwork->FindChan(sTarget);
1081 by psychon
crypt: Fix bug where a usermsg was not forwarded to other clients
62
			if (pChan) {
2692 by Alexey Sokolov
Rename (non-) KeepBuffer to AutoClearChanBuffer.
63
				if (!pChan->AutoClearChanBuffer())
2887.1.2 by Allan Odgaard
crypt: Use ASCII for nick prefix and make it configurable
64
					pChan->AddBuffer(":" + NickPrefix() + _NAMEDFMT(m_pNetwork->GetIRCNick().GetNickMask()) + " PRIVMSG " + _NAMEDFMT(sTarget) + " :{text}", sMessage);
65
				m_pUser->PutUser(":" + NickPrefix() + m_pNetwork->GetIRCNick().GetNickMask() + " PRIVMSG " + sTarget + " :" + sMessage, NULL, m_pClient);
540 by prozacx
Do the buffer adding manually before modifying the message
66
			}
67
742 by prozacx
Don't encrypt reference to message so that other modules can access it
68
			CString sMsg = MakeIvec() + sMessage;
69
			sMsg.Encrypt(it->second);
70
			sMsg.Base64Encode();
71
			sMsg = "+OK *" + sMsg;
540 by prozacx
Do the buffer adding manually before modifying the message
72
742 by prozacx
Don't encrypt reference to message so that other modules can access it
73
			PutIRC("PRIVMSG " + sTarget + " :" + sMsg);
540 by prozacx
Do the buffer adding manually before modifying the message
74
			return HALTCORE;
538 by prozacx
Encryption module
75
		}
76
77
		return CONTINUE;
78
	}
79
80
	virtual EModRet OnPrivMsg(CNick& Nick, CString& sMessage) {
81
		FilterIncoming(Nick.GetNick(), Nick, sMessage);
82
		return CONTINUE;
83
	}
84
85
	virtual EModRet OnChanMsg(CNick& Nick, CChan& Channel, CString& sMessage) {
86
		FilterIncoming(Channel.GetName(), Nick, sMessage);
87
		return CONTINUE;
88
	}
89
90
	void FilterIncoming(const CString& sTarget, CNick& Nick, CString& sMessage) {
91
		if (sMessage.Left(5) == "+OK *") {
92
			MCString::iterator it = FindNV(sTarget.AsLower());
93
94
			if (it != EndNV()) {
95
				sMessage.LeftChomp(5);
96
				sMessage.Base64Decode();
97
				sMessage.Decrypt(it->second);
98
				sMessage.LeftChomp(8);
99
				sMessage = sMessage.c_str();
2887.1.2 by Allan Odgaard
crypt: Use ASCII for nick prefix and make it configurable
100
				Nick.SetNick(NickPrefix() + Nick.GetNick());
538 by prozacx
Encryption module
101
			}
102
		}
103
104
	}
105
106
	virtual void OnModCommand(const CString& sCommand) {
107
		CString sCmd = sCommand.Token(0);
108
1224 by kroimon
Use CString::Equals() everywhere.
109
		if (sCmd.Equals("DELKEY")) {
538 by prozacx
Encryption module
110
			CString sTarget = sCommand.Token(1);
111
112
			if (!sTarget.empty()) {
113
				if (DelNV(sTarget.AsLower())) {
114
					PutModule("Target [" + sTarget + "] deleted");
115
				} else {
116
					PutModule("Target [" + sTarget + "] not found");
117
				}
118
			} else {
119
				PutModule("Usage DelKey <#chan|Nick>");
120
			}
1224 by kroimon
Use CString::Equals() everywhere.
121
		} else if (sCmd.Equals("SETKEY")) {
538 by prozacx
Encryption module
122
			CString sTarget = sCommand.Token(1);
123
			CString sKey = sCommand.Token(2, true);
124
125
			// Strip "cbc:" from beginning of string incase someone pastes directly from mircryption
1224 by kroimon
Use CString::Equals() everywhere.
126
			sKey.TrimPrefix("cbc:");
538 by prozacx
Encryption module
127
128
			if (!sKey.empty()) {
129
				SetNV(sTarget.AsLower(), sKey);
130
				PutModule("Set encryption key for [" + sTarget + "] to [" + sKey + "]");
131
			} else {
132
				PutModule("Usage: SetKey <#chan|Nick> <Key>");
133
			}
1224 by kroimon
Use CString::Equals() everywhere.
134
		} else if (sCmd.Equals("LISTKEYS")) {
538 by prozacx
Encryption module
135
			if (BeginNV() == EndNV()) {
136
				PutModule("You have no encryption keys set.");
137
			} else {
138
				CTable Table;
139
				Table.AddColumn("Target");
140
				Table.AddColumn("Key");
141
1756 by psychon
Fix a bunch of style suggestions from cppcheck[1]
142
				for (MCString::iterator it = BeginNV(); it != EndNV(); ++it) {
538 by prozacx
Encryption module
143
					Table.AddRow();
144
					Table.SetCell("Target", it->first);
145
					Table.SetCell("Key", it->second);
146
				}
147
2887.1.2 by Allan Odgaard
crypt: Use ASCII for nick prefix and make it configurable
148
				MCString::iterator it = FindNV(NICK_PREFIX_KEY);
149
				if (it == EndNV()) {
150
					Table.AddRow();
151
					Table.SetCell("Target", NICK_PREFIX_KEY);
152
					Table.SetCell("Key", NickPrefix());
153
				}
154
1160 by psychon
Use the new CModule::PutModule(const CTable&) in various modules
155
				PutModule(Table);
538 by prozacx
Encryption module
156
			}
1224 by kroimon
Use CString::Equals() everywhere.
157
		} else if (sCmd.Equals("HELP")) {
538 by prozacx
Encryption module
158
			PutModule("Try: SetKey, DelKey, ListKeys");
159
		} else {
160
			PutModule("Unknown command, try 'Help'");
161
		}
162
	}
163
164
	CString MakeIvec() {
165
		CString sRet;
166
		time_t t;
167
		time(&t);
168
		int r = rand();
169
		sRet.append((char*) &t, 4);
170
		sRet.append((char*) &r, 4);
171
172
		return sRet;
173
	}
174
};
175
2379.1.4 by Alexey Sokolov
Add link to wiki page from any nonextra module.
176
template<> void TModInfo<CCryptMod>(CModInfo& Info) {
177
	Info.SetWikiPage("crypt");
178
}
179
2439 by Kyle Fuller
Make all the modules support networks
180
NETWORKMODULEDEFS(CCryptMod, "Encryption for channel/private messages")