+/*
+ * WEBIRC
+ * This is used for the webirc method of CGIIRC auth, and is (really) the best way to do these things.
+ * Syntax: WEBIRC password client hostname ip
+ * Where password is a shared key, client is the name of the "client" and version (e.g. cgiirc), hostname
+ * is the resolved host of the client issuing the command and IP is the real IP of the client.
+ *
+ * How it works:
+ * To tie in with the rest of cgiirc module, and to avoid race conditions, /webirc is only processed locally
+ * and simply sets metadata on the user, which is later decoded on full connect to give something meaningful.
+ */
+class CommandWebirc : public Command
+{
+ public:
+ bool notify;
+ StringExtItem realhost;
+ StringExtItem realip;
+
+ CGIHostlist Hosts;
+ CommandWebirc(Module* Creator)
+ : Command(Creator, "WEBIRC", 4),
+ realhost("cgiirc_realhost", Creator), realip("cgiirc_realip", Creator)
+ {
+ works_before_reg = true;
+ this->syntax = "password client hostname ip";
+ }
+ CmdResult Handle(const std::vector<std::string> ¶meters, User *user)
+ {
+ if(user->registered == REG_ALL)
+ return CMD_FAILURE;
+
+ for(CGIHostlist::iterator iter = Hosts.begin(); iter != Hosts.end(); iter++)
+ {
+ if(InspIRCd::Match(user->host, iter->hostmask, ascii_case_insensitive_map) || InspIRCd::MatchCIDR(user->GetIPString(), iter->hostmask, ascii_case_insensitive_map))
+ {
+ if(iter->type == WEBIRC && parameters[0] == iter->password)
+ {
+ realhost.set(user, user->host);
+ realip.set(user, user->GetIPString());
+
+ // Check if we're happy with the provided hostname. If it's problematic then make sure we won't set a host later, just the IP
+ bool host_ok = (parameters[2].length() <= ServerInstance->Config->Limits.MaxHost);
+ const std::string& newhost = (host_ok ? parameters[2] : parameters[3]);
+
+ if (notify)
+ ServerInstance->SNO->WriteGlobalSno('w', "Connecting user %s detected as using CGI:IRC (%s), changing real host to %s from %s", user->nick.c_str(), user->host.c_str(), newhost.c_str(), user->host.c_str());
+
+ // Where the magic happens - change their IP
+ ChangeIP(user, parameters[3]);
+ // And follow this up by changing their host
+ user->host = user->dhost = newhost;
+ user->InvalidateCache();
+
+ return CMD_SUCCESS;
+ }
+ }
+ }
+
+ ServerInstance->SNO->WriteGlobalSno('w', "Connecting user %s tried to use WEBIRC, but didn't match any configured webirc blocks.", user->GetFullRealHost().c_str());
+ return CMD_FAILURE;
+ }
+};
+
+