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