Exemplo n.º 1
0
void Kill::Run(MessageSource &source, const std::vector<Anope::string> &params)
{
	User *u = User::Find(params[0]);
	ServiceBot *bi;

	if (!u)
		return;

	/* Recover if someone kills us. */
	if (u->server == Me && (bi = dynamic_cast<ServiceBot *>(u)))
	{
		static time_t last_time = 0;

		if (last_time == Anope::CurTime)
		{
			Anope::QuitReason = "Kill loop detected. Are Services U:Lined?";
			Anope::Quitting = true;
			return;
		}
		last_time = Anope::CurTime;

		bi->OnKill();
	}
	else
		u->KillInternal(source, params[1]);
}
Exemplo n.º 2
0
	void OnUserKicked(const MessageSource &source, User *target, const Anope::string &channel, ChannelStatus &status, const Anope::string &kickmsg) override
	{
		ServiceBot *bi = ServiceBot::Find(target->GetUID());
		if (bi)
			/* Bots get rejoined */
			bi->Join(channel, &status);
	}
Exemplo n.º 3
0
	void OnLeaveChannel(User *u, Channel *c) override
	{
		/* Channel is persistent, it shouldn't be deleted and the service bot should stay */
		if (c->ci && c->ci->HasFieldS("PERSIST"))
			return;
	
		/* Channel is syncing from a netburst, don't destroy it as more users are probably wanting to join immediately
		 * We also don't part the bot here either, if necessary we will part it after the sync
		 */
		if (c->syncing)
			return;

		/* Additionally, do not delete this channel if ChanServ/a BotServ bot is inhabiting it */
		if (inhabit && inhabit->HasExt(c))
			return;

		if (c->ci)
		{
			ServiceBot *bot = c->ci->GetBot();

			/* This is called prior to removing the user from the channnel, so c->users.size() - 1 should be safe */
			if (bot && u != bot && c->users.size() - 1 <= Config->GetModule(this)->Get<unsigned>("minusers") && c->FindUser(bot))
				bot->Part(c);
		}
	}
Exemplo n.º 4
0
	void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
	{
		const Anope::string &chan = params[0];
		const Anope::string &nick = params[1];

		if (Anope::ReadOnly)
		{
			source.Reply(_("Sorry, bot assignment is temporarily disabled."));
			return;
		}

		ChanServ::Channel *ci = ChanServ::Find(chan);
		if (ci == NULL)
		{
			source.Reply(_("Channel \002{0}\002 isn't registered."), chan);
			return;
		}

		ServiceBot *bi = ServiceBot::Find(nick, true);
		if (!bi)
		{
			source.Reply(_("Bot \002{0}\002 does not exist."), nick);
			return;
		}

		ChanServ::AccessGroup access = source.AccessFor(ci);
 		if (!access.HasPriv("ASSIGN") && !source.HasPriv("botserv/administration"))
		{
			source.Reply(_("Access denied. You do not have privilege \002{0}\002 on \002{1}\002."), "ASSIGN", ci->GetName());
			return;
		}

		if (ci->HasFieldS("BS_NOBOT"))
		{
			source.Reply(_("Access denied. \002{0}\002 may not have a bot assigned to it because a Services Operator has disallowed it."), ci->GetName());
			return;
		}

		if (bi->bi->GetOperOnly() && !source.HasPriv("botserv/administration"))
		{
			source.Reply(_("Access denied. Bot \002{0}\002 is for operators only."), bi->nick);
			return;
		}

		if (ci->GetBot() == bi)
		{
			source.Reply(_("Bot \002{0}\002 is already assigned to \002{1}\002."), ci->GetBot()->nick, ci->GetName());
			return;
		}

		bool override = !access.HasPriv("ASSIGN");
		Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "for " << bi->nick;

		bi->Assign(source.GetUser(), ci);
		source.Reply(_("Bot \002{0}\002 has been assigned to \002{1}\002."), bi->nick, ci->GetName());
	}
Exemplo n.º 5
0
	void OnChanRegistered(ChanServ::Channel *ci) override
	{
		const Anope::string &bot = Config->GetModule(this)->Get<Anope::string>("bot");
		if (bot.empty())
			return;

		ServiceBot *bi = ServiceBot::Find(bot, true);
		if (bi == NULL)
		{
			Log(this) << "bs_autoassign is configured to assign bot " << bot << ", but it does not exist?";
			return;
		}

		bi->Assign(NULL, ci);
	}
Exemplo n.º 6
0
	void SendTopic(const MessageSource &source, Channel *c) override
	{
		ServiceBot *bi = source.GetBot();
		bool needjoin = c->FindUser(bi) == NULL;

		if (needjoin)
		{
			ChannelStatus status;

			status.AddMode('o');
			bi->Join(c, &status);
		}

		IRCDProto::SendTopic(source, c);

		if (needjoin)
			bi->Part(c);
	}
Exemplo n.º 7
0
void Privmsg::Run(MessageSource &source, const std::vector<Anope::string> &params)
{
	const Anope::string &receiver = params[0];
	Anope::string message = params[1];

	User *u = source.GetUser();

	if (IRCD->IsChannelValid(receiver))
	{
		Channel *c = Channel::Find(receiver);
		if (c)
		{
			EventManager::Get()->Dispatch(&Event::Privmsg::OnPrivmsg, u, c, message);
		}
	}
	else
	{
		/* If a server is specified (nick@server format), make sure it matches
		 * us, and strip it off. */
		Anope::string botname = receiver;
		size_t s = receiver.find('@');
		bool nick_only = false;
		if (s != Anope::string::npos)
		{
			Anope::string servername(receiver.begin() + s + 1, receiver.end());
			botname = botname.substr(0, s);
			nick_only = true;
			if (!servername.equals_ci(Me->GetName()))
				return;
		}
		else if (!IRCD->RequiresID && Config->UseStrictPrivmsg)
		{
			ServiceBot *bi = ServiceBot::Find(receiver);
			if (!bi)
				return;
			Log(LOG_DEBUG) << "Ignored PRIVMSG without @ from " << u->nick;
			u->SendMessage(bi, _("\"/msg %s\" is no longer supported.  Use \"/msg %s@%s\" or \"/%s\" instead."), bi->nick.c_str(), bi->nick.c_str(), Me->GetName().c_str(), bi->nick.c_str());
			return;
		}

		ServiceBot *bi = ServiceBot::Find(botname, nick_only);

		if (bi)
		{
			if (message[0] == '\1' && message[message.length() - 1] == '\1')
			{
				if (message.substr(0, 6).equals_ci("\1PING "))
				{
					Anope::string buf = message;
					buf.erase(buf.begin());
					buf.erase(buf.end() - 1);
					IRCD->SendCTCP(bi, u->nick, "%s", buf.c_str());
				}
				else if (message.substr(0, 9).equals_ci("\1VERSION\1"))
				{
					Module *enc = ModuleManager::FindFirstOf(ENCRYPTION);
					IRCD->SendCTCP(bi, u->nick, "VERSION Anope-%s %s :%s - (%s) -- %s", Anope::Version().c_str(), Me->GetName().c_str(), IRCD->GetProtocolName().c_str(), enc ? enc->name.c_str() : "(none)", Anope::VersionBuildString().c_str());
				}
				return;
			}

			EventReturn MOD_RESULT = EventManager::Get()->Dispatch(&Event::BotPrivmsg::OnBotPrivmsg, u, bi, message);
			if (MOD_RESULT == EVENT_STOP)
				return;

			bi->OnMessage(u, message);
		}
	}

	return;
}
Exemplo n.º 8
0
void Anope::Init(int ac, char **av)
{
	/* Set file creation mask and group ID. */
#if defined(DEFUMASK) && HAVE_UMASK
	umask(DEFUMASK);
#endif

	/* Parse command line arguments */
	ParseCommandLineArguments(ac, av);

	if (GetCommandLineArgument("version", 'v'))
	{
		Log(LOG_TERMINAL) << "Anope-" << Anope::Version() << " -- " << Anope::VersionBuildString();
		throw CoreException();
	}

	if (GetCommandLineArgument("help", 'h'))
	{
		Log(LOG_TERMINAL) << "Anope-" << Anope::Version() << " -- " << Anope::VersionBuildString();
		Log(LOG_TERMINAL) << "Anope IRC Services (http://www.anope.org)";
		Log(LOG_TERMINAL) << "Usage ./" << Anope::ServicesBin << " [options] ...";
		Log(LOG_TERMINAL) << "-c, --config=filename.conf";
		Log(LOG_TERMINAL) << "    --confdir=conf file direcory";
		Log(LOG_TERMINAL) << "    --dbdir=database directory";
		Log(LOG_TERMINAL) << "-d, --debug[=level]";
		Log(LOG_TERMINAL) << "-h, --help";
		Log(LOG_TERMINAL) << "    --localedir=locale directory";
		Log(LOG_TERMINAL) << "    --logdir=logs directory";
		Log(LOG_TERMINAL) << "    --modulesdir=modules directory";
		Log(LOG_TERMINAL) << "-e, --noexpire";
		Log(LOG_TERMINAL) << "-n, --nofork";
		Log(LOG_TERMINAL) << "    --nothird";
		Log(LOG_TERMINAL) << "    --protocoldebug";
		Log(LOG_TERMINAL) << "-r, --readonly";
		Log(LOG_TERMINAL) << "-s, --support";
		Log(LOG_TERMINAL) << "-v, --version";
		Log(LOG_TERMINAL) << "";
		Log(LOG_TERMINAL) << "Further support is available from http://www.anope.org";
		Log(LOG_TERMINAL) << "Or visit us on IRC at irc.anope.org #anope";
		throw CoreException();
	}

	if (GetCommandLineArgument("nofork", 'n'))
		Anope::NoFork = true;

	if (GetCommandLineArgument("support", 's'))
	{
		Anope::NoFork = Anope::NoThird = true;
		++Anope::Debug;
	}

	if (GetCommandLineArgument("readonly", 'r'))
		Anope::ReadOnly = true;

	if (GetCommandLineArgument("nothird"))
		Anope::NoThird = true;

	if (GetCommandLineArgument("noexpire", 'e'))
		Anope::NoExpire = true;

	if (GetCommandLineArgument("protocoldebug"))
		Anope::ProtocolDebug = true;

	Anope::string arg;
	if (GetCommandLineArgument("debug", 'd', arg))
	{
		if (!arg.empty())
		{
			int level = arg.is_number_only() ? convertTo<int>(arg) : -1;
			if (level > 0)
				Anope::Debug = level;
			else
				throw CoreException("Invalid option given to --debug");
		}
		else
			++Anope::Debug;
	}

	if (GetCommandLineArgument("config", 'c', arg))
	{
		if (arg.empty())
			throw CoreException("The --config option requires a file name");
		ServicesConf = Configuration::File(arg, false);
	}

	if (GetCommandLineArgument("confdir", 0, arg))
	{
		if (arg.empty())
			throw CoreException("The --confdir option requires a path");
		Anope::ConfigDir = arg;
	}

	if (GetCommandLineArgument("dbdir", 0, arg))
	{
		if (arg.empty())
			throw CoreException("The --dbdir option requires a path");
		Anope::DataDir = arg;
	}

	if (GetCommandLineArgument("localedir", 0, arg))
	{
		if (arg.empty())
			throw CoreException("The --localedir option requires a path");
		Anope::LocaleDir = arg;
	}

	if (GetCommandLineArgument("modulesdir", 0, arg))
	{
		if (arg.empty())
			throw CoreException("The --modulesdir option requires a path");
		Anope::ModuleDir = arg;
	}

	if (GetCommandLineArgument("logdir", 0, arg))
	{
		if (arg.empty())
			throw CoreException("The --logdir option requires a path");
		Anope::LogDir = arg;
	}

	/* Chdir to Services data directory. */
	if (chdir(Anope::ServicesDir.c_str()) < 0)
	{
		throw CoreException("Unable to chdir to " + Anope::ServicesDir + ": " + Anope::LastError());
	}

	Log(LOG_TERMINAL) << "Anope " << Anope::Version() << ", " << Anope::VersionBuildString();

#ifdef _WIN32
	if (!SupportedWindowsVersion())
		throw CoreException(GetWindowsVersion() + " is not a supported version of Windows");
#else
	/* If we're root, issue a warning now */
	if (!getuid() && !getgid())
	{
		/* If we are configured to setuid later, don't issue a warning */
		Configuration::Block *options = Config->GetBlock("options");
		if (options->Get<Anope::string>("user").empty())
		{
			std::cerr << "WARNING: You are currently running Anope as the root superuser. Anope does not" << std::endl;
			std::cerr << "         require root privileges to run, and it is discouraged that you run Anope" << std::endl;
			std::cerr << "         as the root superuser." << std::endl;
			sleep(3);
		}
	}
#endif

#ifdef _WIN32
	Log(LOG_TERMINAL) << "Using configuration file " << Anope::ConfigDir << "\\" << ServicesConf.GetName();
#else
	Log(LOG_TERMINAL) << "Using configuration file " << Anope::ConfigDir << "/" << ServicesConf.GetName();

	/* Fork to background */
	if (!Anope::NoFork)
	{
		/* Install these before fork() - it is possible for the child to
		 * connect and kill() the parent before it is able to install the
		 * handler.
		 */
		struct sigaction sa, old_sigusr2, old_sigchld;

		sa.sa_flags = 0;
		sigemptyset(&sa.sa_mask);
		sa.sa_handler = parent_signal_handler;

		sigaction(SIGUSR2, &sa, &old_sigusr2);
		sigaction(SIGCHLD, &sa, &old_sigchld);

		int i = fork();
		if (i > 0)
		{
			sigset_t mask;

			sigemptyset(&mask);
			sigsuspend(&mask);

			exit(Anope::ReturnValue);
		}
		else if (i == -1)
		{
			Log() << "Error, unable to fork: " << Anope::LastError();
			Anope::NoFork = true;
		}

		/* Child doesn't need these */
		sigaction(SIGUSR2, &old_sigusr2, NULL);
		sigaction(SIGCHLD, &old_sigchld, NULL);
	}

#endif

	/* Initialize the socket engine. Note that some engines can not survive a fork(), so this must be here. */
	SocketEngine::Init();

	ServiceManager::Init();
	EventManager::Init();

	new BotInfoType();
	new XLineType(nullptr);
	new OperBlockType();

	/* Read configuration file; exit if there are problems. */
	try
	{
		Config = new Configuration::Conf();
	}
	catch (const ConfigException &ex)
	{
		Log(LOG_TERMINAL) << ex.GetReason();
		Log(LOG_TERMINAL) << "*** Support resources: Read through the anope.conf self-contained";
		Log(LOG_TERMINAL) << "*** documentation. Read the documentation files found in the 'docs'";
		Log(LOG_TERMINAL) << "*** folder. Visit our portal located at http://www.anope.org/. Join";
		Log(LOG_TERMINAL) << "*** our support channel on /server irc.anope.org channel #anope.";
		throw CoreException("Configuration file failed to validate");
	}

	/* Create me */
	Configuration::Block *block = Config->GetBlock("serverinfo");
	Me = new Server(NULL, block->Get<Anope::string>("name"), 0, block->Get<Anope::string>("description"), block->Get<Anope::string>("id"));
	for (std::pair<Anope::string, User *> p : UserListByNick)
	{
		User *u = p.second;
		if (u->type != UserType::BOT)
			continue;

		ServiceBot *bi = anope_dynamic_static_cast<ServiceBot *>(u);
		bi->server = Me;
		++Me->users;
	}

	/* Announce ourselves to the logfile. */
	Log() << "Anope " << Anope::Version() << " starting up" << (Anope::Debug || Anope::ReadOnly ? " (options:" : "") << (Anope::Debug ? " debug" : "") << (Anope::ReadOnly ? " readonly" : "") << (Anope::Debug || Anope::ReadOnly ? ")" : "");

	InitSignals();

	/* Initialize multi-language support */
	Language::InitLanguages();

	/* Initialize random number generator */
	block = Config->GetBlock("options");
	srand(block->Get<unsigned>("seed") ^ time(NULL));

	ModeManager::Apply(nullptr);

	/* load modules */
	Log() << "Loading modules...";
	for (int i = 0; i < Config->CountBlock("module"); ++i)
		ModuleManager::LoadModule(Config->GetBlock("module", i)->Get<Anope::string>("name"), NULL);

#ifndef _WIN32
	/* We won't background later, so we should setuid now */
	if (Anope::NoFork)
		setuidgid();
#endif

	Module *protocol = ModuleManager::FindFirstOf(PROTOCOL);
	if (protocol == NULL)
		throw CoreException("You must load a protocol module!");

	/* Write our PID to the PID file. */
	write_pidfile();

	Log() << "Using IRCd protocol " << protocol->name;

	/* Auto assign sid if applicable */
	if (IRCD->RequiresID)
	{
		Anope::string sid = IRCD->SID_Retrieve();
		if (Me->GetSID() == Me->GetName())
			Me->SetSID(sid);
		for (std::pair<Anope::string, User *> p : UserListByNick)
		{
			User *u = p.second;
			if (u->type != UserType::BOT)
				continue;

			ServiceBot *bi = anope_dynamic_static_cast<ServiceBot *>(u);
			bi->GenerateUID();
		}
	}

	/* Load up databases */
	Log() << "Loading databases...";
	EventReturn MOD_RESULT = EventManager::Get()->Dispatch(&Event::LoadDatabase::OnLoadDatabase);;
	static_cast<void>(MOD_RESULT);
	Log() << "Databases loaded";

	for (channel_map::const_iterator it = ChannelList.begin(), it_end = ChannelList.end(); it != it_end; ++it)
		it->second->Sync();
}
Exemplo n.º 9
0
	void Execute(CommandSource &source, const std::vector<Anope::string> &params) override
	{
		const Anope::string &query = params[0];

		ServiceBot *bi = ServiceBot::Find(query, true);
		ChanServ::Channel *ci = ChanServ::Find(query);
		InfoFormatter info(source.nc);

		if (bi)
		{
			source.Reply(_("Information for bot \002%s\002:"), bi->nick.c_str());
			info[_("Mask")] = bi->GetIdent() + "@" + bi->host;
			info[_("Real name")] = bi->realname;
			if (bi->bi)
			{
				info[_("Created")] = Anope::strftime(bi->bi->GetCreated(), source.GetAccount());
				info[_("Options")] = bi->bi->GetOperOnly() ? _("Private") : _("None");
			}
			info[_("Used on")] = stringify(bi->GetChannelCount()) + " channel(s)";

			EventManager::Get()->Dispatch(&Event::ServiceBotEvent::OnServiceBot, source, bi, ci, info);

			std::vector<Anope::string> replies;
			info.Process(replies);

			for (unsigned i = 0; i < replies.size(); ++i)
				source.Reply(replies[i]);

			if (source.HasPriv("botserv/administration"))
			{
				Anope::string buf;
				for (ChanServ::Channel *ci2 : bi->GetChannels())
					buf += " " + ci2->GetName();
				source.Reply(buf);
			}

		}
		else if (ci)
		{
			if (!source.AccessFor(ci).HasPriv("INFO") && !source.HasPriv("botserv/administration"))
			{
				source.Reply(_("Access denied. You do not have privilege \002{0}\002 on \002{1}\002."), "INFO", ci->GetName());
				return;
			}

			source.Reply(_("Information for channel \002{0}\002:"), ci->GetName());
			info[_("Bot nick")] = ci->GetBot() ? ci->GetBot()->nick : _("not assigned yet");

			EventManager::Get()->Dispatch(&Event::ServiceBotEvent::OnServiceBot, source, bi, ci, info);

			std::vector<Anope::string> replies;
			info.Process(replies);

			for (unsigned i = 0; i < replies.size(); ++i)
				source.Reply(replies[i]);
		}
		else
		{
			source.Reply(_("\002{0}\002 is not a valid bot or registered channel."), query);
		}
	}