1 /* +------------------------------------+
2 * | Inspire Internet Relay Chat Daemon |
3 * +------------------------------------+
5 * InspIRCd is copyright (C) 2002-2006 ChatSpike-Dev.
7 * <brain@chatspike.net>
8 * <Craig@chatspike.net>
10 * Written by Craig Edwards, Craig McLure, and others.
11 * This program is free but copyrighted software; see
12 * the file COPYING for details.
14 * ---------------------------------------------------
17 #include "inspircd_config.h"
18 #include "configreader.h"
26 /* $ModDesc: Provides masking of user hostnames */
27 /* $ModDep: m_hash.h */
29 /* Used to vary the output a little more depending on the cloak keys */
30 static const char* xtab[] = {"F92E45D871BCA630", "A1B9D80C72E653F4", "1ABC078934DEF562", "ABCDEF5678901234"};
32 /** Handles user mode +x
34 class CloakUser : public ModeHandler
46 CloakUser(InspIRCd* Instance, Module* Source, Module* Hash) : ModeHandler(Instance, 'x', 0, 0, false, MODETYPE_USER, false), Sender(Source), HashProvider(Hash)
50 ModeAction OnModeChange(userrec* source, userrec* dest, chanrec* channel, std::string ¶meter, bool adding)
52 /* Only opers can change other users modes */
53 if ((source != dest) && (!*source->oper))
54 return MODEACTION_DENY;
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.
60 return MODEACTION_ALLOW;
64 if(!dest->IsModeSet('x'))
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.
75 char* n1 = strchr(dest->host,'.');
76 char* n2 = strchr(dest->host,':');
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.
86 unsigned int iv[] = { key1, key2, key3, key4 };
87 std::string a = (n1 ? n1 : n2);
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]);
96 /* Generate a cloak using specialized Hash */
97 std::string hostcloak = prefix + "-" + std::string(HashSumRequest(Sender, HashProvider, dest->host).Send()).substr(0,8) + a;
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
105 if ((insp_aton(dest->host,&testaddr) < 1) && (hostcloak.length() <= 64))
107 // if they have a hostname, make something appropriate
112 b = ((b.find(':') == std::string::npos) ? Cloak4(dest->host) : Cloak6(dest->host));
114 dest->ChangeDisplayedHost(b.c_str());
117 dest->SetMode('x',true);
118 return MODEACTION_ALLOW;
123 if (dest->IsModeSet('x'))
125 /* User is removing the mode, so just restore their real host
126 * and make it match the displayed one.
128 dest->ChangeDisplayedHost(dest->host);
129 dest->SetMode('x',false);
130 return MODEACTION_ALLOW;
134 return MODEACTION_DENY;
137 std::string Cloak4(const char* ip)
139 unsigned int iv[] = { key1, key2, key3, key4 };
140 irc::sepstream seps(ip, '.');
142 std::string octet[4];
145 for (int j = 0; j < 4; j++)
147 octet[j] = seps.GetToken();
148 i[j] = atoi(octet[j].c_str());
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];
155 /* Reset the Hash module and send it our IV */
156 HashResetRequest(Sender, HashProvider).Send();
157 HashKeyRequest(Sender, HashProvider, iv).Send();
159 /* Send the Hash module a different hex table for each octet group's Hash sum */
160 for (int k = 0; k < 4; k++)
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);
165 /* Stick them all together */
166 return std::string().append(ra[0]).append(".").append(ra[1]).append(".").append(ra[2]).append(".").append(ra[3]);
169 std::string Cloak6(const char* ip)
171 unsigned int iv[] = { key1, key2, key3, key4 };
172 std::vector<std::string> hashies;
173 std::string item = "";
176 /* Reset the Hash module and send it our IV */
177 HashResetRequest(Sender, HashProvider).Send();
178 HashKeyRequest(Sender, HashProvider, iv).Send();
180 for (const char* input = ip; *input; input++)
183 if (item.length() > 5)
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));
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));
199 /* Stick them all together */
200 return irc::stringjoiner(":", hashies, 0, hashies.size() - 1).GetJoined();
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);
214 prefix = ServerInstance->Config->Network;
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!");
222 class ModuleCloaking : public Module
230 ModuleCloaking(InspIRCd* Me)
233 /* Attempt to locate the Hash service provider, bail if we can't find it */
234 HashModule = ServerInstance->FindModule("m_md5.so");
236 throw ModuleException("Can't find m_md5.so. Please load m_md5.so before m_cloaking.so.");
238 /* Create new mode handler object */
239 cu = new CloakUser(ServerInstance, this, HashModule);
241 /* Register it with the core */
242 ServerInstance->AddMode(cu, 'x');
247 virtual ~ModuleCloaking()
249 ServerInstance->Modes->DelMode(cu);
253 virtual Version GetVersion()
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);
260 virtual void OnRehash(const std::string ¶meter)
265 void Implements(char* List)
267 List[I_OnRehash] = 1;
271 // stuff down here is the module-factory stuff. For basic modules you can ignore this.
273 class ModuleCloakingFactory : public ModuleFactory
276 ModuleCloakingFactory()
280 ~ModuleCloakingFactory()
284 virtual Module * CreateModule(InspIRCd* Me)
286 return new ModuleCloaking(Me);
292 extern "C" void * init_module( void )
294 return new ModuleCloakingFactory;