]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/modules/m_cloaking.cpp
95b54b5229c5bc1881330fb776f5bd55774374df
[user/henk/code/inspircd.git] / src / modules / m_cloaking.cpp
1 /*       +------------------------------------+
2  *       | Inspire Internet Relay Chat Daemon |
3  *       +------------------------------------+
4  *
5  *  InspIRCd is copyright (C) 2002-2006 ChatSpike-Dev.
6  *                       E-mail:
7  *                <brain@chatspike.net>
8  *                <Craig@chatspike.net>
9  *     
10  * Written by Craig Edwards, Craig McLure, and others.
11  * This program is free but copyrighted software; see
12  *            the file COPYING for details.
13  *
14  * ---------------------------------------------------
15  */
16
17 #include "inspircd_config.h"
18 #include "configreader.h"
19 #include "inspircd.h"
20 #include "users.h"
21 #include "channels.h"
22 #include "modules.h"
23
24 #include "m_md5.h"
25
26 /* $ModDesc: Provides masking of user hostnames */
27 /* $ModDep: m_md5.h */
28
29 /* Used to vary the output a little more depending on the cloak keys */
30 static const char* xtab[] = {"F92E45D871BCA630", "A1B9D80C72E653F4", "1ABC078934DEF562", "ABCDEF5678901234"};
31
32 /** Handles user mode +x
33  */
34 class CloakUser : public ModeHandler
35 {
36         
37         std::string prefix;
38         unsigned int key1;
39         unsigned int key2;
40         unsigned int key3;
41         unsigned int key4;
42         Module* Sender;
43         Module* MD5Provider;
44         
45  public:
46         CloakUser(InspIRCd* Instance, Module* Source, Module* MD5) : ModeHandler(Instance, 'x', 0, 0, false, MODETYPE_USER, false), Sender(Source), MD5Provider(MD5)
47         {
48         }
49
50         ModeAction OnModeChange(userrec* source, userrec* dest, chanrec* channel, std::string &parameter, bool adding)
51         {
52                 /* Only opers can change other users modes */
53                 if ((source != dest) && (!*source->oper))
54                         return MODEACTION_DENY;
55
56                 /* For remote clients, we dont take any action, we just allow it.
57                  * The local server where they are will set their cloak instead.
58                  */
59                 if (!IS_LOCAL(dest))
60                         return MODEACTION_ALLOW;
61
62                 if (adding)
63                 {
64                         if(!dest->IsModeSet('x'))
65                         {
66                                 /* The mode is being turned on - so attempt to
67                                  * allocate the user a cloaked host using a non-reversible
68                                  * algorithm (its simple, but its non-reversible so the
69                                  * simplicity doesnt really matter). This algorithm
70                                  * will not work if the user has only one level of domain
71                                  * naming in their hostname (e.g. if they are on a lan or
72                                  * are connecting via localhost) -- this doesnt matter much.
73                                  */
74                         
75                                 if (strchr(dest->host,'.') || strchr(dest->host,':'))
76                                 {
77                                         /* InspIRCd users have two hostnames; A displayed
78                                          * hostname which can be modified by modules (e.g.
79                                          * to create vhosts, implement chghost, etc) and a
80                                          * 'real' hostname which you shouldnt write to.
81                                          */
82
83                                         unsigned int iv[] = { key1, key2, key3, key4 };
84                                         char* n = strstr(dest->host,".");
85                                         if (!n)
86                                                 n = strstr(dest->host,":");
87
88                                         std::string a = n;
89
90                                         std::string b;
91                                         insp_inaddr testaddr;
92
93                                         /** Reset the MD5 module, and send it our IV and hex table */
94                                         MD5ResetRequest(Sender, MD5Provider).Send();
95                                         MD5KeyRequest(Sender, MD5Provider, iv).Send();
96                                         MD5HexRequest(Sender, MD5Provider, xtab[0]);
97
98                                         /* Generate a cloak using specialized MD5 */
99                                         std::string hostcloak = prefix + "-" + MD5SumRequest(Sender, MD5Provider, dest->host).Send() + a;
100
101                                         /* Fix by brain - if the cloaked host is > the max length of a host (64 bytes
102                                          * according to the DNS RFC) then tough titty, they get cloaked as an IP. 
103                                          * Their ISP shouldnt go to town on subdomains, or they shouldnt have a kiddie
104                                          * vhost.
105                                          */
106
107                                         if ((insp_aton(dest->host,&testaddr) < 1) && (hostcloak.length() <= 64))
108                                         {
109                                                 // if they have a hostname, make something appropriate
110                                                 b = hostcloak;
111                                         }
112                                         else
113                                         {
114                                                 b = ((b.find(':') == std::string::npos) ? Cloak4(dest->host) : Cloak6(dest->host));
115                                         }
116                                         dest->ChangeDisplayedHost(b.c_str());
117                                 }
118                                 
119                                 dest->SetMode('x',true);
120                                 return MODEACTION_ALLOW;
121                         }
122                 }
123                 else
124                 {
125                         if (dest->IsModeSet('x'))
126                         {
127                                 /* User is removing the mode, so just restore their real host
128                                  * and make it match the displayed one.
129                                  */
130                                 dest->ChangeDisplayedHost(dest->host);
131                                 dest->SetMode('x',false);
132                                 return MODEACTION_ALLOW;
133                         }
134                 }
135
136                 return MODEACTION_DENY;
137         }
138
139         std::string Cloak4(const char* ip)
140         {
141                 unsigned int iv[] = { key1, key2, key3, key4 };
142                 irc::sepstream seps(ip, '.');
143                 std::string ra1, ra2, ra3, ra4;
144                 std::string octet1 = seps.GetToken();
145                 std::string octet2 = seps.GetToken();
146                 std::string octet3 = seps.GetToken();
147                 std::string octet4 = seps.GetToken();
148                 int i1 = atoi(octet1.c_str());
149                 int i2 = atoi(octet2.c_str());
150                 int i3 = atoi(octet3.c_str());
151                 int i4 = atoi(octet4.c_str());
152
153                 octet4 = octet1 + "." + octet2 + "." + octet3 + "." + octet4;
154                 octet3 = octet1 + "." + octet2 + "." + octet3;
155                 octet2 = octet1 + "." + octet2;
156
157                 /* Reset the MD5 module and send it our IV */
158                 MD5ResetRequest(Sender, MD5Provider).Send();
159                 MD5KeyRequest(Sender, MD5Provider, iv).Send();
160
161                 /* Send the MD5 module a different hex table for each octet group's MD5 sum */
162                 MD5HexRequest(Sender, MD5Provider, xtab[(key1+i1) % 4]).Send();
163                 ra1 = std::string(MD5SumRequest(Sender, MD5Provider, octet1).Send()).substr(0,6);
164
165                 MD5HexRequest(Sender, MD5Provider, xtab[(key2+i2) % 4]).Send();
166                 ra2 = std::string(MD5SumRequest(Sender, MD5Provider, octet2).Send()).substr(0,6);
167
168                 MD5HexRequest(Sender, MD5Provider, xtab[(key3+i3) % 4]).Send();
169                 ra3 = std::string(MD5SumRequest(Sender, MD5Provider, octet3).Send()).substr(0,6);
170
171                 MD5HexRequest(Sender, MD5Provider, xtab[(key4+i4) % 4]).Send();
172                 ra4 = std::string(MD5SumRequest(Sender, MD5Provider, octet4).Send()).substr(0,6);
173
174                 /* Stick them all together */
175                 return std::string().append(ra1).append(".").append(ra2).append(".").append(ra3).append(".").append(ra4);
176         }
177
178         std::string Cloak6(const char* ip)
179         {
180                 unsigned int iv[] = { key1, key2, key3, key4 };
181                 std::vector<std::string> hashies;
182                 std::string item = "";
183                 int rounds = 0;
184
185                 /* Reset the MD5 module and send it our IV */
186                 MD5ResetRequest(Sender, MD5Provider).Send();
187                 MD5KeyRequest(Sender, MD5Provider, iv).Send();
188
189                 for (const char* input = ip; *input; input++)
190                 {
191                         item += *input;
192                         if (item.length() > 5)
193                         {
194                                 /* Send the MD5 module a different hex table for each octet group's MD5 sum */
195                                 MD5HexRequest(Sender, MD5Provider, xtab[(key1+rounds) % 4]).Send();
196                                 hashies.push_back(std::string(MD5SumRequest(Sender, MD5Provider, item).Send()).substr(0,10));
197                                 item = "";
198                         }
199                         rounds++;
200                 }
201                 if (!item.empty())
202                 {
203                         /* Send the MD5 module a different hex table for each octet group's MD5 sum */
204                         MD5HexRequest(Sender, MD5Provider, xtab[(key1+rounds) % 4]).Send();
205                         hashies.push_back(std::string(MD5SumRequest(Sender, MD5Provider, item).Send()).substr(0,10));
206                         item = "";
207                 }
208                 /* Stick them all together */
209                 return irc::stringjoiner(":", hashies, 0, hashies.size() - 1).GetJoined();
210         }
211         
212         void DoRehash()
213         {
214                 ConfigReader Conf(ServerInstance);
215                 key1 = key2 = key3 = key4 = 0;
216                 key1 = Conf.ReadInteger("cloak","key1",0,true);
217                 key2 = Conf.ReadInteger("cloak","key2",0,true);
218                 key3 = Conf.ReadInteger("cloak","key3",0,true);
219                 key4 = Conf.ReadInteger("cloak","key4",0,true);
220                 prefix = Conf.ReadValue("cloak","prefix",0);
221
222                 if (prefix.empty())
223                         prefix = ServerInstance->Config->Network;
224
225                 if (!key1 && !key2 && !key3 && !key4)
226                 {
227                         ModuleException ex("You have not defined cloak keys for m_cloaking!!! THIS IS INSECURE AND SHOULD BE CHECKED!");
228                         throw (ex);
229                 }
230         }
231 };
232
233
234 class ModuleCloaking : public Module
235 {
236  private:
237         
238         CloakUser* cu;
239         Module* MD5Module;
240
241  public:
242         ModuleCloaking(InspIRCd* Me)
243                 : Module::Module(Me)
244         {
245                 /* Attempt to locate the MD5 service provider, bail if we can't find it */
246                 MD5Module = ServerInstance->FindModule("m_md5.so");
247                 if (!MD5Module)
248                         throw ModuleException("Can't find m_md5.so. Please load m_md5.so before m_cloaking.so.");
249
250                 /* Create new mode handler object */
251                 cu = new CloakUser(ServerInstance, this, MD5Module);
252
253                 /* Register it with the core */         
254                 ServerInstance->AddMode(cu, 'x');
255
256                 OnRehash("");
257         }
258         
259         virtual ~ModuleCloaking()
260         {
261                 ServerInstance->Modes->DelMode(cu);
262                 DELETE(cu);
263         }
264         
265         virtual Version GetVersion()
266         {
267                 // returns the version number of the module to be
268                 // listed in /MODULES
269                 return Version(1,1,0,2,VF_COMMON|VF_VENDOR,API_VERSION);
270         }
271
272         virtual void OnRehash(const std::string &parameter)
273         {
274                 cu->DoRehash();
275         }
276
277         void Implements(char* List)
278         {
279                 List[I_OnRehash] = 1;
280         }
281 };
282
283 // stuff down here is the module-factory stuff. For basic modules you can ignore this.
284
285 class ModuleCloakingFactory : public ModuleFactory
286 {
287  public:
288         ModuleCloakingFactory()
289         {
290         }
291         
292         ~ModuleCloakingFactory()
293         {
294         }
295         
296         virtual Module * CreateModule(InspIRCd* Me)
297         {
298                 return new ModuleCloaking(Me);
299         }
300         
301 };
302
303
304 extern "C" void * init_module( void )
305 {
306         return new ModuleCloakingFactory;
307 }