]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/modules/m_cloaking.cpp
8c88a862a660c56e6790cabdbf67a07ddc913135
[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_hash.h"
25
26 /* $ModDesc: Provides masking of user hostnames */
27 /* $ModDep: m_hash.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* HashProvider;
44         
45  public:
46         CloakUser(InspIRCd* Instance, Module* Source, Module* Hash) : ModeHandler(Instance, 'x', 0, 0, false, MODETYPE_USER, false), Sender(Source), HashProvider(Hash)
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                                 char* n1 = strchr(dest->host,'.');
76                                 char* n2 = strchr(dest->host,':');
77                         
78                                 if (n1 || n2)
79                                 {
80                                         /* InspIRCd users have two hostnames; A displayed
81                                          * hostname which can be modified by modules (e.g.
82                                          * to create vhosts, implement chghost, etc) and a
83                                          * 'real' hostname which you shouldnt write to.
84                                          */
85
86                                         unsigned int iv[] = { key1, key2, key3, key4 };
87                                         std::string a = (n1 ? n1 : n2);
88                                         std::string b;
89                                         insp_inaddr testaddr;
90
91                                         /** Reset the Hash module, and send it our IV and hex table */
92                                         HashResetRequest(Sender, HashProvider).Send();
93                                         HashKeyRequest(Sender, HashProvider, iv).Send();
94                                         HashHexRequest(Sender, HashProvider, xtab[(*dest->host) % 4]);
95
96                                         /* Generate a cloak using specialized Hash */
97                                         std::string hostcloak = prefix + "-" + HashSumRequest(Sender, HashProvider, dest->host).Send() + a;
98
99                                         /* Fix by brain - if the cloaked host is > the max length of a host (64 bytes
100                                          * according to the DNS RFC) then tough titty, they get cloaked as an IP. 
101                                          * Their ISP shouldnt go to town on subdomains, or they shouldnt have a kiddie
102                                          * vhost.
103                                          */
104
105                                         if ((insp_aton(dest->host,&testaddr) < 1) && (hostcloak.length() <= 64))
106                                         {
107                                                 // if they have a hostname, make something appropriate
108                                                 b = hostcloak;
109                                         }
110                                         else
111                                         {
112                                                 b = ((b.find(':') == std::string::npos) ? Cloak4(dest->host) : Cloak6(dest->host));
113                                         }
114                                         dest->ChangeDisplayedHost(b.c_str());
115                                 }
116                                 
117                                 dest->SetMode('x',true);
118                                 return MODEACTION_ALLOW;
119                         }
120                 }
121                 else
122                 {
123                         if (dest->IsModeSet('x'))
124                         {
125                                 /* User is removing the mode, so just restore their real host
126                                  * and make it match the displayed one.
127                                  */
128                                 dest->ChangeDisplayedHost(dest->host);
129                                 dest->SetMode('x',false);
130                                 return MODEACTION_ALLOW;
131                         }
132                 }
133
134                 return MODEACTION_DENY;
135         }
136
137         std::string Cloak4(const char* ip)
138         {
139                 unsigned int iv[] = { key1, key2, key3, key4 };
140                 irc::sepstream seps(ip, '.');
141                 std::string ra[4];;
142                 std::string octet[4];
143                 int i[4];
144
145                 for (int j = 0; j < 4; j++)
146                 {
147                         octet[j] = seps.GetToken();
148                         i[j] = atoi(octet[j].c_str());
149                 }
150
151                 octet[3] = octet[0] + "." + octet[1] + "." + octet[2] + "." + octet[3];
152                 octet[2] = octet[0] + "." + octet[1] + "." + octet[2];
153                 octet[1] = octet[0] + "." + octet[1];
154
155                 /* Reset the Hash module and send it our IV */
156                 HashResetRequest(Sender, HashProvider).Send();
157                 HashKeyRequest(Sender, HashProvider, iv).Send();
158
159                 /* Send the Hash module a different hex table for each octet group's Hash sum */
160                 for (int k = 0; k < 3; k++)
161                 {
162                         HashHexRequest(Sender, HashProvider, xtab[(iv[k]+i[k]) % 4]).Send();
163                         ra[k] = std::string(HashSumRequest(Sender, HashProvider, octet[k]).Send()).substr(0,6);
164                 }
165                 /* Stick them all together */
166                 return std::string().append(ra[0]).append(".").append(ra[1]).append(".").append(ra[2]).append(".").append(ra[3]);
167         }
168
169         std::string Cloak6(const char* ip)
170         {
171                 unsigned int iv[] = { key1, key2, key3, key4 };
172                 std::vector<std::string> hashies;
173                 std::string item = "";
174                 int rounds = 0;
175
176                 /* Reset the Hash module and send it our IV */
177                 HashResetRequest(Sender, HashProvider).Send();
178                 HashKeyRequest(Sender, HashProvider, iv).Send();
179
180                 for (const char* input = ip; *input; input++)
181                 {
182                         item += *input;
183                         if (item.length() > 5)
184                         {
185                                 /* Send the Hash module a different hex table for each octet group's Hash sum */
186                                 HashHexRequest(Sender, HashProvider, xtab[(key1+rounds) % 4]).Send();
187                                 hashies.push_back(std::string(HashSumRequest(Sender, HashProvider, item).Send()).substr(0,10));
188                                 item = "";
189                         }
190                         rounds++;
191                 }
192                 if (!item.empty())
193                 {
194                         /* Send the Hash module a different hex table for each octet group's Hash sum */
195                         HashHexRequest(Sender, HashProvider, xtab[(key1+rounds) % 4]).Send();
196                         hashies.push_back(std::string(HashSumRequest(Sender, HashProvider, item).Send()).substr(0,10));
197                         item = "";
198                 }
199                 /* Stick them all together */
200                 return irc::stringjoiner(":", hashies, 0, hashies.size() - 1).GetJoined();
201         }
202         
203         void DoRehash()
204         {
205                 ConfigReader Conf(ServerInstance);
206                 key1 = key2 = key3 = key4 = 0;
207                 key1 = Conf.ReadInteger("cloak","key1",0,true);
208                 key2 = Conf.ReadInteger("cloak","key2",0,true);
209                 key3 = Conf.ReadInteger("cloak","key3",0,true);
210                 key4 = Conf.ReadInteger("cloak","key4",0,true);
211                 prefix = Conf.ReadValue("cloak","prefix",0);
212
213                 if (prefix.empty())
214                         prefix = ServerInstance->Config->Network;
215
216                 if (!key1 && !key2 && !key3 && !key4)
217                         throw ModuleException("You have not defined cloak keys for m_cloaking!!! THIS IS INSECURE AND SHOULD BE CHECKED!");
218         }
219 };
220
221
222 class ModuleCloaking : public Module
223 {
224  private:
225         
226         CloakUser* cu;
227         Module* HashModule;
228
229  public:
230         ModuleCloaking(InspIRCd* Me)
231                 : Module::Module(Me)
232         {
233                 /* Attempt to locate the Hash service provider, bail if we can't find it */
234                 HashModule = ServerInstance->FindModule("m_md5.so");
235                 if (!HashModule)
236                         throw ModuleException("Can't find m_md5.so. Please load m_md5.so before m_cloaking.so.");
237
238                 /* Create new mode handler object */
239                 cu = new CloakUser(ServerInstance, this, HashModule);
240
241                 /* Register it with the core */         
242                 ServerInstance->AddMode(cu, 'x');
243
244                 OnRehash("");
245         }
246         
247         virtual ~ModuleCloaking()
248         {
249                 ServerInstance->Modes->DelMode(cu);
250                 DELETE(cu);
251         }
252         
253         virtual Version GetVersion()
254         {
255                 // returns the version number of the module to be
256                 // listed in /MODULES
257                 return Version(1,1,0,2,VF_COMMON|VF_VENDOR,API_VERSION);
258         }
259
260         virtual void OnRehash(const std::string &parameter)
261         {
262                 cu->DoRehash();
263         }
264
265         void Implements(char* List)
266         {
267                 List[I_OnRehash] = 1;
268         }
269 };
270
271 // stuff down here is the module-factory stuff. For basic modules you can ignore this.
272
273 class ModuleCloakingFactory : public ModuleFactory
274 {
275  public:
276         ModuleCloakingFactory()
277         {
278         }
279         
280         ~ModuleCloakingFactory()
281         {
282         }
283         
284         virtual Module * CreateModule(InspIRCd* Me)
285         {
286                 return new ModuleCloaking(Me);
287         }
288         
289 };
290
291
292 extern "C" void * init_module( void )
293 {
294         return new ModuleCloakingFactory;
295 }