Ejemplo n.º 1
0
	bool FirePreEvents(User* source, MessageTarget& msgtarget, CTCTags::TagMessageDetails& msgdetails)
	{
		// Inform modules that a TAGMSG wants to be sent.
		ModResult modres;
		FIRST_MOD_RESULT_CUSTOM(tagevprov, CTCTags::EventListener, OnUserPreTagMessage, modres, (source, msgtarget, msgdetails));
		if (modres == MOD_RES_DENY)
		{
			// Inform modules that a module blocked the TAGMSG.
			FOREACH_MOD_CUSTOM(tagevprov, CTCTags::EventListener, OnUserTagMessageBlocked, (source, msgtarget, msgdetails));
			return false;
		}

		// Inform modules that a TAGMSG is about to be sent.
		FOREACH_MOD_CUSTOM(tagevprov, CTCTags::EventListener, OnUserTagMessage, (source, msgtarget, msgdetails));
		return true;
	}
Ejemplo n.º 2
0
static void SendSASL(const parameterlist& params)
{
	if (!ServerInstance->PI->SendEncapsulatedData(sasl_target, "SASL", params))
	{
		FOREACH_MOD_CUSTOM(*saslevprov, SASLEventListener, OnSASLAuth, (params));
	}
}
Ejemplo n.º 3
0
	CmdResult FirePostEvent(User* source, const MessageTarget& msgtarget, const CTCTags::TagMessageDetails& msgdetails)
	{
		// If the source is local then update its idle time.
		LocalUser* lsource = IS_LOCAL(source);
		if (lsource)
			lsource->idle_lastmsg = ServerInstance->Time();

		// Inform modules that a TAGMSG was sent.
		FOREACH_MOD_CUSTOM(tagevprov, CTCTags::EventListener, OnUserPostTagMessage, (source, msgtarget, msgdetails));
		return CMD_SUCCESS;
	}
Ejemplo n.º 4
0
void TreeServer::SQuitInternal(unsigned int& num_lost_servers)
{
	ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "Server %s lost in split", GetName().c_str());

	for (ChildServers::const_iterator i = Children.begin(); i != Children.end(); ++i)
	{
		TreeServer* server = *i;
		server->SQuitInternal(num_lost_servers);
	}

	// Mark server as dead
	isdead = true;
	num_lost_servers++;
	RemoveHash();

	if (!Utils->Creator->dying)
		FOREACH_MOD_CUSTOM(Utils->Creator->GetEventProvider(), SpanningTreeEventListener, OnServerSplit, (this));
}
Ejemplo n.º 5
0
void ModuleSpanningTree::OnUnloadModule(Module* mod)
{
	if (!Utils)
		return;
	ServerInstance->PI->SendMetaData("modules", "-" + mod->ModuleSourceFile);

	if (mod == this)
	{
		// We are being unloaded, inform modules about all servers splitting which cannot be done later when the servers are actually disconnected
		const server_hash& servers = Utils->serverlist;
		for (server_hash::const_iterator i = servers.begin(); i != servers.end(); ++i)
		{
			TreeServer* server = i->second;
			if (!server->IsRoot())
				FOREACH_MOD_CUSTOM(GetEventProvider(), ServerEventListener, OnServerSplit, (server));
		}
		return;
	}

	// Some other module is being unloaded. If it provides an IOHook we use, we must close that server connection now.

restart:
	// Close all connections which use an IO hook provided by this module
	const TreeServer::ChildServers& list = Utils->TreeRoot->GetChildren();
	for (TreeServer::ChildServers::const_iterator i = list.begin(); i != list.end(); ++i)
	{
		TreeSocket* sock = (*i)->GetSocket();
		if (sock->GetModHook(mod))
		{
			sock->SendError("SSL module unloaded");
			sock->Close();
			// XXX: The list we're iterating is modified by TreeServer::SQuit() which is called by Close()
			goto restart;
		}
	}

	for (SpanningTreeUtilities::TimeoutList::const_iterator i = Utils->timeoutlist.begin(); i != Utils->timeoutlist.end(); ++i)
	{
		TreeSocket* sock = i->first;
		if (sock->GetModHook(mod))
			sock->Close();
	}
}
Ejemplo n.º 6
0
void DataKeeper::Save(Module* currmod)
{
	this->mod = currmod;

	const ExtensionManager::ExtMap& allexts = ServerInstance->Extensions.GetExts();
	for (ExtensionManager::ExtMap::const_iterator i = allexts.begin(); i != allexts.end(); ++i)
	{
		ExtensionItem* ext = i->second;
		if (ext->creator == mod)
			handledexts.push_back(ProviderInfo(ext));
	}

	CreateModeList(MODETYPE_USER);
	DoSaveUsers();

	CreateModeList(MODETYPE_CHANNEL);
	DoSaveChans();

	FOREACH_MOD_CUSTOM(*reloadevprov, ReloadModule::EventListener, OnReloadModuleSave, (mod, this->moddata));

	ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "Saved data about %lu users %lu chans %lu modules", (unsigned long)userdatalist.size(), (unsigned long)chandatalist.size(), (unsigned long)moddata.list.size());
}
Ejemplo n.º 7
0
	CmdResult Handle (const std::vector<std::string> &parameters, User *user)
	{
		std::string subcommand(parameters[0].length(), ' ');
		std::transform(parameters[0].begin(), parameters[0].end(), subcommand.begin(), ::toupper);

		if (subcommand == "REQ")
		{
			if (parameters.size() < 2)
				return CMD_FAILURE;

			CapEvent Data(creator, user, CapEvent::CAPEVENT_REQ);

			// tokenize the input into a nice list of requested caps
			std::string cap_;
			irc::spacesepstream cap_stream(parameters[1]);

			while (cap_stream.GetToken(cap_))
			{
				std::transform(cap_.begin(), cap_.end(), cap_.begin(), ::tolower);
				Data.wanted.push_back(cap_);
			}

			reghold.set(user, 1);
			FOREACH_MOD_CUSTOM(capevprov, GenericCap, OnCapEvent, (Data));

			if (Data.ack.size() > 0)
			{
				std::string AckResult = irc::stringjoiner(Data.ack);
				user->WriteCommand("CAP", "ACK :" + AckResult);
			}

			if (Data.wanted.size() > 0)
			{
				std::string NakResult = irc::stringjoiner(Data.wanted);
				user->WriteCommand("CAP", "NAK :" + NakResult);
			}
		}
		else if (subcommand == "END")
		{
			reghold.set(user, 0);
		}
		else if ((subcommand == "LS") || (subcommand == "LIST"))
		{
			CapEvent Data(creator, user, subcommand == "LS" ? CapEvent::CAPEVENT_LS : CapEvent::CAPEVENT_LIST);

			reghold.set(user, 1);
			FOREACH_MOD_CUSTOM(capevprov, GenericCap, OnCapEvent, (Data));

			std::string Result = irc::stringjoiner(Data.wanted);
			user->WriteCommand("CAP", subcommand + " :" + Result);
		}
		else if (subcommand == "CLEAR")
		{
			CapEvent Data(creator, user, CapEvent::CAPEVENT_CLEAR);

			reghold.set(user, 1);
			FOREACH_MOD_CUSTOM(capevprov, GenericCap, OnCapEvent, (Data));

			std::string Result = irc::stringjoiner(Data.ack);
			user->WriteCommand("CAP", "ACK :" + Result);
		}
		else
		{
			user->WriteNumeric(ERR_INVALIDCAPSUBCOMMAND, "%s :Invalid CAP subcommand", subcommand.c_str());
			return CMD_FAILURE;
		}

		return CMD_SUCCESS;
	}
Ejemplo n.º 8
0
	CmdResult HandleLocal(LocalUser* user, const Params& parameters) override
	{
		if (user->registered == REG_ALL || realhost.get(user))
			return CMD_FAILURE;

		for (std::vector<WebIRCHost>::const_iterator iter = hosts.begin(); iter != hosts.end(); ++iter)
		{
			// If we don't match the host then skip to the next host.
			if (!iter->Matches(user, parameters[0], sslapi))
				continue;

			irc::sockets::sockaddrs ipaddr;
			if (!irc::sockets::aptosa(parameters[3], user->client_sa.port(), ipaddr))
			{
				WriteLog("Connecting user %s (%s) tried to use WEBIRC but gave an invalid IP address.",
					user->uuid.c_str(), user->GetIPString().c_str());
				ServerInstance->Users.QuitUser(user, "WEBIRC: IP address is invalid: " + parameters[3]);
				return CMD_FAILURE;
			}

			// The user matched a WebIRC block!
			gateway.set(user, parameters[1]);
			realhost.set(user, user->GetRealHost());
			realip.set(user, user->GetIPString());

			WriteLog("Connecting user %s is using a WebIRC gateway; changing their IP from %s to %s.",
				user->uuid.c_str(), user->GetIPString().c_str(), parameters[3].c_str());

			// If we have custom flags then deal with them.
			WebIRC::FlagMap flags;
			const bool hasflags = (parameters.size() > 4);
			if (hasflags)
			{
				// Parse the flags.
				irc::spacesepstream flagstream(parameters[4]);
				for (std::string flag; flagstream.GetToken(flag); )
				{
					// Does this flag have a value?
					const size_t separator = flag.find('=');
					if (separator == std::string::npos)
					{
						flags[flag];
						continue;
					}

					// The flag has a value!
					const std::string key = flag.substr(0, separator);
					const std::string value = flag.substr(separator + 1);
					flags[key] = value;
				}
			}

			// Inform modules about the WebIRC attempt.
			FOREACH_MOD_CUSTOM(webircevprov, WebIRC::EventListener, OnWebIRCAuth, (user, (hasflags ? &flags : NULL)));

			// Set the IP address sent via WEBIRC. We ignore the hostname and lookup
			// instead do our own DNS lookups because of unreliable gateways.
			user->SetClientIP(ipaddr);
			return CMD_SUCCESS;
		}

		WriteLog("Connecting user %s (%s) tried to use WEBIRC but didn't match any configured WebIRC hosts.",
			user->uuid.c_str(), user->GetIPString().c_str());
		ServerInstance->Users.QuitUser(user, "WEBIRC: you don't match any configured WebIRC hosts.");
		return CMD_FAILURE;
	}
Ejemplo n.º 9
0
/** When we create a new server, we call this constructor to initialize it.
 * This constructor initializes the server's Route and Parent, and sets up
 * the ping timer for the server.
 */
TreeServer::TreeServer(const std::string& Name, const std::string& Desc, const std::string& id, TreeServer* Above, TreeSocket* Sock, bool Hide)
	: Server(Name, Desc)
	, Parent(Above), Socket(Sock), sid(id), behind_bursting(Parent->behind_bursting), isdead(false)
	, pingtimer(this)
	, ServerUser(new FakeUser(id, this))
	, age(ServerInstance->Time()), UserCount(0), OperCount(0), rtt(0), StartBurst(0), Hidden(Hide)
{
	ServerInstance->Logs->Log(MODNAME, LOG_DEBUG, "New server %s behind_bursting %u", GetName().c_str(), behind_bursting);
	CheckULine();

	ServerInstance->Timers.AddTimer(&pingtimer);

	/* find the 'route' for this server (e.g. the one directly connected
	 * to the local server, which we can use to reach it)
	 *
	 * In the following example, consider we have just added a TreeServer
	 * class for server G on our network, of which we are server A.
	 * To route traffic to G (marked with a *) we must send the data to
	 * B (marked with a +) so this algorithm initializes the 'Route'
	 * value to point at whichever server traffic must be routed through
	 * to get here. If we were to try this algorithm with server B,
	 * the Route pointer would point at its own object ('this').
	 *
	 *            A
	 *           / \
	 *        + B   C
	 *         / \   \
	 *        D   E   F
	 *       /         \
	 *    * G           H
	 *
	 * We only run this algorithm when a server is created, as
	 * the routes remain constant while ever the server exists, and
	 * do not need to be re-calculated.
	 */

	Route = Above;
	if (Route == Utils->TreeRoot)
	{
		Route = this;
	}
	else
	{
		while (this->Route->GetParent() != Utils->TreeRoot)
		{
			this->Route = Route->GetParent();
		}
	}

	/* Because recursive code is slow and takes a lot of resources,
	 * we store two representations of the server tree. The first
	 * is a recursive structure where each server references its
	 * children and its parent, which is used for netbursts and
	 * netsplits to dump the whole dataset to the other server,
	 * and the second is used for very fast lookups when routing
	 * messages and is instead a hash_map, where each item can
	 * be referenced by its server name. The AddHashEntry()
	 * call below automatically inserts each TreeServer class
	 * into the hash_map as it is created. There is a similar
	 * maintainance call in the destructor to tidy up deleted
	 * servers.
	 */

	this->AddHashEntry();
	Parent->Children.push_back(this);

	FOREACH_MOD_CUSTOM(Utils->Creator->GetEventProvider(), SpanningTreeEventListener, OnServerLink, (this));
}