void ContactsRpcOperation::runGetContacts()
{
    TLContactsContacts result;
    result.tlType = TLValue::ContactsContacts;

    LocalUser *self = layer()->getUser();

    const QVector<UserContact> importedContacts = self->importedContacts();
    result.contacts.reserve(importedContacts.size());
    result.users.reserve(importedContacts.size());

    TLUser userInfo;
    TLContact outputContact;
    for (const UserContact &contact : importedContacts) {
        if (contact.id) {
            const AbstractUser *contactUser = api()->getAbstractUser(contact.id);
            Utils::setupTLUser(&userInfo, contactUser, self);
            result.users.append(userInfo);

            outputContact.userId = contact.id;
            outputContact.mutual = userInfo.flags & TLUser::MutualContact;
            result.contacts.append(outputContact);
        } else {
            ++result.savedCount;
        }
    }

    sendRpcReply(result);
}
void ContactsRpcOperation::runImportContacts()
{
    qDebug() << Q_FUNC_INFO;
    TLContactsImportedContacts result;

    LocalUser *self = layer()->getUser();

    for (const TLInputContact &c : m_importContacts.contacts) {
        UserContact contact;
        contact.phone = api()->normalizeIdentifier(c.phone);
        contact.firstName = c.firstName;
        contact.lastName = c.lastName;

        AbstractUser *registeredUser = api()->getAbstractUser(contact.phone);
        if (registeredUser) {
            contact.id = registeredUser->id();
        } else {
            result.retryContacts.append(c.clientId);
        }
        self->importContact(contact);
        if (registeredUser) {
            result.users.append(TLUser());
            Utils::setupTLUser(&result.users.last(), registeredUser, self);

            TLImportedContact imported;
            imported.clientId = c.clientId;
            imported.userId = contact.id;
            result.imported.append(imported);
        }
    }

    sendRpcReply(result);
}
Beispiel #3
0
	CmdResult Handle (const std::vector<std::string> &parameters, User *src)
	{
		std::map<std::string,int> closed;

		for (LocalUserList::const_iterator u = ServerInstance->Users->local_users.begin(); u != ServerInstance->Users->local_users.end(); ++u)
		{
			LocalUser* user = *u;
			if (user->registered != REG_ALL)
			{
				ServerInstance->Users->QuitUser(user, "Closing all unknown connections per request");
				std::string key = ConvToStr(user->GetIPString())+"."+ConvToStr(user->GetServerPort());
				closed[key]++;
			}
		}

		int total = 0;
		for (std::map<std::string,int>::iterator ci = closed.begin(); ci != closed.end(); ci++)
		{
			src->WriteNotice("*** Closed " + ConvToStr(ci->second) + " unknown " + (ci->second == 1 ? "connection" : "connections") +
				" from [" + ci->first + "]");
			total += ci->second;
		}
		if (total)
			src->WriteNotice("*** " + ConvToStr(total) + " unknown " + (total == 1 ? "connection" : "connections") + " closed");
		else
			src->WriteNotice("*** No unknown connections found");

		return CMD_SUCCESS;
	}
Beispiel #4
0
	void SendAlert(unsigned int numeric, const std::string& nick)
	{
		const IRCv3::Monitor::WatcherList* list = manager.GetWatcherList(nick);
		if (!list)
			return;

		for (IRCv3::Monitor::WatcherList::const_iterator i = list->begin(); i != list->end(); ++i)
		{
			LocalUser* curr = *i;
			curr->WriteNumeric(numeric, nick);
		}
	}
Beispiel #5
0
	CmdResult Handle (const std::vector<std::string> &parameters, User *user)
	{
		User* u = ServerInstance->FindNick(parameters[0]);
		Channel* c = ServerInstance->FindChan(parameters[1]);

		if ((!c) || (!u) || (u->registered != REG_ALL))
		{
			if (!c)
			{
				user->WriteNumeric(401, "%s %s :No such nick/channel",user->nick.c_str(), parameters[1].c_str());
			}
			else
			{
				user->WriteNumeric(401, "%s %s :No such nick/channel",user->nick.c_str(), parameters[0].c_str());
			}

			return CMD_FAILURE;
		}

		if (IS_LOCAL(user))
		{
			if (c->GetPrefixValue(user) < HALFOP_VALUE)
			{
				user->WriteNumeric(ERR_CHANOPRIVSNEEDED, "%s %s :You must be a channel %soperator", user->nick.c_str(), c->name.c_str(), c->GetPrefixValue(u) == HALFOP_VALUE ? "" : "half-");
				return CMD_FAILURE;
			}
		}

		/* Servers remember invites only for their local users, so act
		 * only if the target is local. Otherwise the command will be
		 * passed to the target users server.
		 */
		LocalUser* lu = IS_LOCAL(u);
		if (lu)
		{
			irc::string xname(c->name.c_str());
			if (!lu->IsInvited(xname))
			{
				user->SendText(":%s 505 %s %s %s :Is not invited to channel %s", user->server.c_str(), user->nick.c_str(), u->nick.c_str(), c->name.c_str(), c->name.c_str());
				return CMD_FAILURE;
			}

			user->SendText(":%s 494 %s %s %s :Uninvited", user->server.c_str(), user->nick.c_str(), c->name.c_str(), u->nick.c_str());
			lu->RemoveInvite(xname);
			lu->WriteNumeric(493, "%s :You were uninvited from %s by %s", u->nick.c_str(), c->name.c_str(), user->nick.c_str());

			std::string msg = "*** " + user->nick + " uninvited " + u->nick + ".";
			c->WriteChannelWithServ(ServerInstance->Config->ServerName, "NOTICE " + c->name + " :" + msg);
			ServerInstance->PI->SendChannelNotice(c, 0, msg);
		}

		return CMD_SUCCESS;
	}
Beispiel #6
0
	void SendAlert(User* user, const std::string& nick, unsigned int numeric, const char* numerictext, time_t shownts)
	{
		const IRCv3::Monitor::WatcherList* list = manager.GetWatcherList(nick);
		if (!list)
			return;

		Numeric::Numeric num(numeric);
		num.push(nick).push(user->ident).push(user->GetDisplayedHost()).push(ConvToStr(shownts)).push(numerictext);
		for (IRCv3::Monitor::WatcherList::const_iterator i = list->begin(); i != list->end(); ++i)
		{
			LocalUser* curr = *i;
			curr->WriteNumeric(num);
		}
	}
Beispiel #7
0
void User::WriteCommonQuit(const std::string &normal_text, const std::string &oper_text)
{
	char tb1[MAXBUF];
	char tb2[MAXBUF];

	if (this->registered != REG_ALL)
		return;

	already_sent_t uniq_id = ++LocalUser::already_sent_id;

	snprintf(tb1,MAXBUF,":%s QUIT :%s",this->GetFullHost().c_str(),normal_text.c_str());
	snprintf(tb2,MAXBUF,":%s QUIT :%s",this->GetFullHost().c_str(),oper_text.c_str());
	std::string out1 = tb1;
	std::string out2 = tb2;

	UserChanList include_c(chans);
	std::map<User*,bool> exceptions;

	FOREACH_MOD(I_OnBuildNeighborList,OnBuildNeighborList(this, include_c, exceptions));

	for (std::map<User*,bool>::iterator i = exceptions.begin(); i != exceptions.end(); ++i)
	{
		LocalUser* u = IS_LOCAL(i->first);
		if (u && !u->quitting)
		{
			u->already_sent = uniq_id;
			if (i->second)
				u->Write(IS_OPER(u) ? out2 : out1);
		}
	}
	for (UCListIter v = include_c.begin(); v != include_c.end(); ++v)
	{
		const UserMembList* ulist = (*v)->GetUsers();
		for (UserMembList::const_iterator i = ulist->begin(); i != ulist->end(); i++)
		{
			LocalUser* u = IS_LOCAL(i->first);
			if (u && !u->quitting && (u->already_sent != uniq_id))
			{
				u->already_sent = uniq_id;
				u->Write(IS_OPER(u) ? out2 : out1);
			}
		}
	}
}
Beispiel #8
0
	CmdResult HandleServerTarget(User* source, const Params& parameters)
	{
		// If the source isn't allowed to mass message users then reject
		// the attempt to mass-message users.
		if (!source->HasPrivPermission("users/mass-message"))
			return CMD_FAILURE;

		// Extract the server glob match from the target parameter.
		std::string servername(parameters[0], 1);

		// Fire the pre-message events.
		MessageTarget msgtarget(&servername);
		CTCTags::TagMessageDetails msgdetails(parameters.GetTags());
		if (!FirePreEvents(source, msgtarget, msgdetails))
			return CMD_FAILURE;

		// If the current server name matches the server name glob then send
		// the message out to the local users.
		if (InspIRCd::Match(ServerInstance->Config->ServerName, servername))
		{
			CTCTags::TagMessage message(source, "$*", parameters.GetTags());
			const UserManager::LocalList& list = ServerInstance->Users.GetLocalUsers();
			for (UserManager::LocalList::const_iterator iter = list.begin(); iter != list.end(); ++iter)
			{
				LocalUser* luser = IS_LOCAL(*iter);

				// Don't send to unregistered users or the user who is the source.
				if (luser->registered != REG_ALL || luser == source)
					continue;

				// Don't send to exempt users.
				if (msgdetails.exemptions.count(luser))
					continue;

				// Send to users if they have the capability.
				if (cap.get(luser))
					luser->Send(msgevprov, message);
			}
		}

		// Fire the post-message event.
		return FirePostEvent(source, msgtarget, msgdetails);
	}
static void GenerateStatsLl(User* user, string_list& results, char c)
{
	results.push_back(InspIRCd::Format("211 %s nick[ident@%s] sendq cmds_out bytes_out cmds_in bytes_in time_open", user->nick.c_str(), (c == 'l' ? "host" : "ip")));

	const UserManager::LocalList& list = ServerInstance->Users.GetLocalUsers();
	for (UserManager::LocalList::const_iterator i = list.begin(); i != list.end(); ++i)
	{
		LocalUser* u = *i;
		results.push_back("211 "+user->nick+" "+u->nick+"["+u->ident+"@"+(c == 'l' ? u->dhost : u->GetIPString())+"] "+ConvToStr(u->eh.getSendQSize())+" "+ConvToStr(u->cmds_out)+" "+ConvToStr(u->bytes_out)+" "+ConvToStr(u->cmds_in)+" "+ConvToStr(u->bytes_in)+" "+ConvToStr(ServerInstance->Time() - u->age));
	}
}
Beispiel #10
0
void User::Oper(OperInfo* info)
{
	ModeHandler* opermh = ServerInstance->Modes->FindMode('o', MODETYPE_USER);
	if (this->IsModeSet(opermh))
		this->UnOper();

	this->SetMode(opermh, true);
	this->oper = info;
	this->WriteCommand("MODE", "+o");
	FOREACH_MOD(OnOper, (this, info->name));

	std::string opername;
	if (info->oper_block)
		opername = info->oper_block->getString("name");

	if (IS_LOCAL(this))
	{
		LocalUser* l = IS_LOCAL(this);
		std::string vhost = oper->getConfig("vhost");
		if (!vhost.empty())
			l->ChangeDisplayedHost(vhost.c_str());
		std::string opClass = oper->getConfig("class");
		if (!opClass.empty())
			l->SetClass(opClass);
	}

	ServerInstance->SNO->WriteToSnoMask('o',"%s (%s@%s) is now an IRC operator of type %s (using oper '%s')",
		nick.c_str(), ident.c_str(), host.c_str(), oper->name.c_str(), opername.c_str());
	this->WriteNumeric(RPL_YOUAREOPER, ":You are now %s %s", strchr("aeiouAEIOU", oper->name[0]) ? "an" : "a", oper->name.c_str());

	ServerInstance->Logs->Log("OPER", LOG_DEFAULT, "%s opered as type: %s", GetFullRealHost().c_str(), oper->name.c_str());
	ServerInstance->Users->all_opers.push_back(this);

	// Expand permissions from config for faster lookup
	if (IS_LOCAL(this))
		oper->init();

	FOREACH_MOD(OnPostOper, (this, oper->name, opername));
}
Beispiel #11
0
void User::WriteCommonRaw(const std::string &line, bool include_self)
{
	if (this->registered != REG_ALL || quitting)
		return;

	LocalUser::already_sent_id++;

	IncludeChanList include_c(chans.begin(), chans.end());
	std::map<User*,bool> exceptions;

	exceptions[this] = include_self;

	FOREACH_MOD(OnBuildNeighborList, (this, include_c, exceptions));

	for (std::map<User*,bool>::iterator i = exceptions.begin(); i != exceptions.end(); ++i)
	{
		LocalUser* u = IS_LOCAL(i->first);
		if (u && !u->quitting)
		{
			u->already_sent = LocalUser::already_sent_id;
			if (i->second)
				u->Write(line);
		}
	}
	for (IncludeChanList::const_iterator v = include_c.begin(); v != include_c.end(); ++v)
	{
		Channel* c = (*v)->chan;
		const UserMembList* ulist = c->GetUsers();
		for (UserMembList::const_iterator i = ulist->begin(); i != ulist->end(); i++)
		{
			LocalUser* u = IS_LOCAL(i->first);
			if (u && u->already_sent != LocalUser::already_sent_id)
			{
				u->already_sent = LocalUser::already_sent_id;
				u->Write(line);
			}
		}
	}
}
Beispiel #12
0
void User::Oper(OperInfo* info)
{
	if (this->IsModeSet('o'))
		this->UnOper();

	this->modes[UM_OPERATOR] = 1;
	this->oper = info;
	this->WriteServ("MODE %s :+o", this->nick.c_str());
	FOREACH_MOD(I_OnOper, OnOper(this, info->name));

	std::string opername;
	if (info->oper_block)
		opername = info->oper_block->getString("name");

	if (IS_LOCAL(this))
	{
		LocalUser* l = IS_LOCAL(this);
		std::string vhost = oper->getConfig("vhost");
		if (!vhost.empty())
			l->ChangeDisplayedHost(vhost.c_str());
		std::string opClass = oper->getConfig("class");
		if (!opClass.empty())
			l->SetClass(opClass);
	}

	ServerInstance->SNO->WriteToSnoMask('o',"%s (%s@%s) is now an IRC operator of type %s (using oper '%s')",
		nick.c_str(), ident.c_str(), host.c_str(), oper->NameStr(), opername.c_str());
	this->WriteNumeric(381, "%s :You are now %s %s", nick.c_str(), strchr("aeiouAEIOU", oper->name[0]) ? "an" : "a", oper->NameStr());

	ServerInstance->Logs->Log("OPER", DEFAULT, "%s opered as type: %s", GetFullRealHost().c_str(), oper->NameStr());
	ServerInstance->Users->all_opers.push_back(this);

	// Expand permissions from config for faster lookup
	if (IS_LOCAL(this))
		oper->init();

	FOREACH_MOD(I_OnPostOper,OnPostOper(this, oper->name, opername));
}
Beispiel #13
0
void User::WriteCommonQuit(const std::string &normal_text, const std::string &oper_text)
{
	if (this->registered != REG_ALL)
		return;

	already_sent_t uniq_id = ++LocalUser::already_sent_id;

	const std::string normalMessage = ":" + this->GetFullHost() + " QUIT :" + normal_text;
	const std::string operMessage = ":" + this->GetFullHost() + " QUIT :" + oper_text;

	IncludeChanList include_c(chans.begin(), chans.end());
	std::map<User*,bool> exceptions;

	FOREACH_MOD(OnBuildNeighborList, (this, include_c, exceptions));

	for (std::map<User*,bool>::iterator i = exceptions.begin(); i != exceptions.end(); ++i)
	{
		LocalUser* u = IS_LOCAL(i->first);
		if (u && !u->quitting)
		{
			u->already_sent = uniq_id;
			if (i->second)
				u->Write(u->IsOper() ? operMessage : normalMessage);
		}
	}
	for (IncludeChanList::const_iterator v = include_c.begin(); v != include_c.end(); ++v)
	{
		const UserMembList* ulist = (*v)->chan->GetUsers();
		for (UserMembList::const_iterator i = ulist->begin(); i != ulist->end(); i++)
		{
			LocalUser* u = IS_LOCAL(i->first);
			if (u && (u->already_sent != uniq_id))
			{
				u->already_sent = uniq_id;
				u->Write(u->IsOper() ? operMessage : normalMessage);
			}
		}
	}
}
Beispiel #14
0
	ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string &parameter, bool adding)
	{
		LocalUser* user = IS_LOCAL(dest);

		/* For remote clients, we don't take any action, we just allow it.
		 * The local server where they are will set their cloak instead.
		 * This is fine, as we will receive it later.
		 */
		if (!user)
		{
			dest->SetMode(this, adding);
			return MODEACTION_ALLOW;
		}

		if (user->uuid == debounce_uid && debounce_ts == ServerInstance->Time())
		{
			// prevent spamming using /mode user +x-x+x-x+x-x
			if (++debounce_count > 2)
				return MODEACTION_DENY;
		}
		else
		{
			debounce_uid = user->uuid;
			debounce_count = 1;
			debounce_ts = ServerInstance->Time();
		}

		if (adding == user->IsModeSet(this))
			return MODEACTION_DENY;

		/* don't allow this user to spam modechanges */
		if (source == dest)
			user->CommandFloodPenalty += 5000;

		if (adding)
		{
			std::string* cloak = ext.get(user);

			if (!cloak)
			{
				/* Force creation of missing cloak */
				creator->OnUserConnect(user);
				cloak = ext.get(user);
			}
			if (cloak)
			{
				user->ChangeDisplayedHost(*cloak);
				user->SetMode(this, true);
				return MODEACTION_ALLOW;
			}
			else
				return MODEACTION_DENY;
		}
		else
		{
			/* User is removing the mode, so restore their real host
			 * and make it match the displayed one.
			 */
			user->SetMode(this, false);
			user->ChangeDisplayedHost(user->host.c_str());
			return MODEACTION_ALLOW;
		}
	}
Beispiel #15
0
/* add a client connection to the sockets list */
void UserManager::AddUser(int socket, ListenSocket* via, irc::sockets::sockaddrs* client, irc::sockets::sockaddrs* server)
{
	/* NOTE: Calling this one parameter constructor for User automatically
	 * allocates a new UUID and places it in the hash_map.
	 */
	LocalUser* New = NULL;
	try
	{
		New = new LocalUser(socket, client, server);
	}
	catch (...)
	{
		ServerInstance->Logs->Log("USERS", DEFAULT,"*** WTF *** Duplicated UUID! -- Crack smoking monkeys have been unleashed.");
		ServerInstance->SNO->WriteToSnoMask('a', "WARNING *** Duplicate UUID allocated!");
		return;
	}
	UserIOHandler* eh = &New->eh;

	/* Give each of the modules an attempt to hook the user for I/O */
	FOREACH_MOD(I_OnHookIO, OnHookIO(eh, via));

	if (eh->GetIOHook())
	{
		try
		{
			eh->GetIOHook()->OnStreamSocketAccept(eh, client, server);
		}
		catch (CoreException& modexcept)
		{
			ServerInstance->Logs->Log("SOCKET", DEBUG,"%s threw an exception: %s", modexcept.GetSource(), modexcept.GetReason());
		}
	}

	ServerInstance->Logs->Log("USERS", DEBUG,"New user fd: %d", socket);

	this->unregistered_count++;

	/* The users default nick is their UUID */
	New->nick.assign(New->uuid, 0, ServerInstance->Config->Limits.NickMax);
	(*(this->clientlist))[New->nick] = New;

	New->registered = REG_NONE;
	New->signon = ServerInstance->Time() + ServerInstance->Config->dns_timeout;
	New->lastping = 1;

	ServerInstance->Users->AddLocalClone(New);
	ServerInstance->Users->AddGlobalClone(New);

	New->localuseriter = this->local_users.insert(local_users.end(), New);

	if ((this->local_users.size() > ServerInstance->Config->SoftLimit) || (this->local_users.size() >= (unsigned int)ServerInstance->SE->GetMaxFds()))
	{
		ServerInstance->SNO->WriteToSnoMask('a', "Warning: softlimit value has been reached: %d clients", ServerInstance->Config->SoftLimit);
		this->QuitUser(New,"No more connections allowed");
		return;
	}

	/*
	 * First class check. We do this again in FullConnect after DNS is done, and NICK/USER is recieved.
	 * See my note down there for why this is required. DO NOT REMOVE. :) -- w00t
	 */
	New->SetClass();

	/*
	 * Check connect class settings and initialise settings into User.
	 * This will be done again after DNS resolution. -- w00t
	 */
	New->CheckClass();
	if (New->quitting)
		return;

	/*
	 * even with bancache, we still have to keep User::exempt current.
	 * besides that, if we get a positive bancache hit, we still won't f**k
	 * them over if they are exempt. -- w00t
	 */
	New->exempt = (ServerInstance->XLines->MatchesLine("E",New) != NULL);

	if (BanCacheHit *b = ServerInstance->BanCache->GetHit(New->GetIPString()))
	{
		if (!b->Type.empty() && !New->exempt)
		{
			/* user banned */
			ServerInstance->Logs->Log("BANCACHE", DEBUG, "BanCache: Positive hit for " + New->GetIPString());
			if (!ServerInstance->Config->MoronBanner.empty())
				New->WriteServ("NOTICE %s :*** %s", New->nick.c_str(), ServerInstance->Config->MoronBanner.c_str());
			this->QuitUser(New, b->Reason);
			return;
		}
		else
		{
			ServerInstance->Logs->Log("BANCACHE", DEBUG, "BanCache: Negative hit for " + New->GetIPString());
		}
	}
	else
	{
		if (!New->exempt)
		{
			XLine* r = ServerInstance->XLines->MatchesLine("Z",New);

			if (r)
			{
				r->Apply(New);
				return;
			}
		}
	}

	if (!ServerInstance->SE->AddFd(eh, FD_WANT_FAST_READ | FD_WANT_EDGE_WRITE))
	{
		ServerInstance->Logs->Log("USERS", DEBUG,"Internal error on new connection");
		this->QuitUser(New, "Internal error handling connection");
	}

	/* NOTE: even if dns lookups are *off*, we still need to display this.
	 * BOPM and other stuff requires it.
	 */
	New->WriteServ("NOTICE Auth :*** Looking up your hostname...");
	if (ServerInstance->Config->RawLog)
		New->WriteServ("NOTICE Auth :*** Raw I/O logging is enabled on this server. All messages, passwords, and commands are being recorded.");

	FOREACH_MOD(I_OnSetUserIP,OnSetUserIP(New));
	if (New->quitting)
		return;

	FOREACH_MOD(I_OnUserInit,OnUserInit(New));

	if (ServerInstance->Config->NoUserDns)
	{
		New->WriteServ("NOTICE %s :*** Skipping host resolution (disabled by server administrator)", New->nick.c_str());
		New->dns_done = true;
	}
	else
	{
		New->StartDNSLookup();
	}
}
Beispiel #16
0
	CmdResult HandleChannelTarget(User* source, const Params& parameters, const char* target, PrefixMode* pm)
	{
		Channel* chan = ServerInstance->FindChan(target);
		if (!chan)
		{
			// The target channel does not exist.
			source->WriteNumeric(Numerics::NoSuchChannel(parameters[0]));
			return CMD_FAILURE;
		}

		if (IS_LOCAL(source))
		{
			if (chan->IsModeSet(noextmsgmode) && !chan->HasUser(source))
			{
				// The noextmsg mode is set and the source is not in the channel.
				source->WriteNumeric(ERR_CANNOTSENDTOCHAN, chan->name, "Cannot send to channel (no external messages)");
				return CMD_FAILURE;
			}

			bool no_chan_priv = chan->GetPrefixValue(source) < VOICE_VALUE;
			if (no_chan_priv && chan->IsModeSet(moderatedmode))
			{
				// The moderated mode is set and the source has no status rank.
				source->WriteNumeric(ERR_CANNOTSENDTOCHAN, chan->name, "Cannot send to channel (+m)");
				return CMD_FAILURE;
			}

			if (no_chan_priv && ServerInstance->Config->RestrictBannedUsers != ServerConfig::BUT_NORMAL && chan->IsBanned(source))
			{
				// The source is banned in the channel and restrictbannedusers is enabled.
				if (ServerInstance->Config->RestrictBannedUsers == ServerConfig::BUT_RESTRICT_NOTIFY)
					source->WriteNumeric(ERR_CANNOTSENDTOCHAN, chan->name, "Cannot send to channel (you're banned)");
				return CMD_FAILURE;
			}
		}

		// Fire the pre-message events.
		MessageTarget msgtarget(chan, pm ? pm->GetPrefix() : 0);
		CTCTags::TagMessageDetails msgdetails(parameters.GetTags());
		if (!FirePreEvents(source, msgtarget, msgdetails))
			return CMD_FAILURE;

		unsigned int minrank = pm ? pm->GetPrefixRank() : 0;
		CTCTags::TagMessage message(source, chan, parameters.GetTags());
		const Channel::MemberMap& userlist = chan->GetUsers();
		for (Channel::MemberMap::const_iterator iter = userlist.begin(); iter != userlist.end(); ++iter)
		{
			LocalUser* luser = IS_LOCAL(iter->first);

			// Don't send to remote users or the user who is the source. 
			if (!luser || luser == source)
				continue;

			// Don't send to unprivileged or exempt users.
			if (iter->second->getRank() < minrank || msgdetails.exemptions.count(luser))
				continue;

			// Send to users if they have the capability.
			if (cap.get(luser))
				luser->Send(msgevprov, message);
		}
		return FirePostEvent(source, msgtarget, msgdetails);
	}
Beispiel #17
0
void User::DoHostCycle(const std::string &quitline)
{
	char buffer[MAXBUF];

	if (!ServerInstance->Config->CycleHosts)
		return;

	already_sent_t silent_id = ++LocalUser::already_sent_id;
	already_sent_t seen_id = ++LocalUser::already_sent_id;

	UserChanList include_c(chans);
	std::map<User*,bool> exceptions;

	FOREACH_MOD(I_OnBuildNeighborList,OnBuildNeighborList(this, include_c, exceptions));

	for (std::map<User*,bool>::iterator i = exceptions.begin(); i != exceptions.end(); ++i)
	{
		LocalUser* u = IS_LOCAL(i->first);
		if (u && !u->quitting)
		{
			if (i->second)
			{
				u->already_sent = seen_id;
				u->Write(quitline);
			}
			else
			{
				u->already_sent = silent_id;
			}
		}
	}
	for (UCListIter v = include_c.begin(); v != include_c.end(); ++v)
	{
		Channel* c = *v;
		snprintf(buffer, MAXBUF, ":%s JOIN %s", GetFullHost().c_str(), c->name.c_str());
		std::string joinline(buffer);
		Membership* memb = c->GetUser(this);
		std::string modeline = memb->modes;
		if (modeline.length() > 0)
		{
			for(unsigned int i=0; i < memb->modes.length(); i++)
				modeline.append(" ").append(nick);
			snprintf(buffer, MAXBUF, ":%s MODE %s +%s",
				ServerInstance->Config->CycleHostsFromUser ? GetFullHost().c_str() : ServerInstance->Config->ServerName.c_str(),
				c->name.c_str(), modeline.c_str());
			modeline = buffer;
		}

		const UserMembList *ulist = c->GetUsers();
		for (UserMembList::const_iterator i = ulist->begin(); i != ulist->end(); i++)
		{
			LocalUser* u = IS_LOCAL(i->first);
			if (u == NULL || u == this)
				continue;
			if (u->already_sent == silent_id)
				continue;

			if (u->already_sent != seen_id)
			{
				u->Write(quitline);
				u->already_sent = seen_id;
			}
			u->Write(joinline);
			if (modeline.length() > 0)
				u->Write(modeline);
		}
	}
}
Beispiel #18
0
	CmdResult Handle (const std::vector<std::string> &parameters, User *user)
	{
		int n_done = 0;
		reason = (parameters.size() < 4) ? "Please use this server/port instead" : parameters[3];
		bool redirect_all_immediately = false;
		redirect_new_users = true;
		bool direction = true;
		std::string n_done_s;

		/* No parameters: jumpserver disabled */
		if (!parameters.size())
		{
			if (port)
				user->WriteNotice("*** Disabled jumpserver (previously set to '" + redirect_to + ":" + ConvToStr(port) + "')");
			else
				user->WriteNotice("*** Jumpserver was not enabled.");

			port = 0;
			sslport = 0;
			redirect_to.clear();
			return CMD_SUCCESS;
		}

		port = 0;
		redirect_to.clear();

		if (parameters.size() >= 3)
		{
			for (std::string::const_iterator n = parameters[2].begin(); n != parameters[2].end(); ++n)
			{
				switch (*n)
				{
					case '+':
						direction = true;
					break;
					case '-':
						direction = false;
					break;
					case 'a':
						redirect_all_immediately = direction;
					break;
					case 'n':
						redirect_new_users = direction;
					break;
					default:
						user->WriteNotice("*** Invalid JUMPSERVER flag: " + ConvToStr(*n));
						return CMD_FAILURE;
					break;
				}
			}

			size_t delimpos = parameters[1].find(':');
			port = ConvToInt(parameters[1].substr(0, delimpos ? delimpos : std::string::npos));
			sslport = (delimpos == std::string::npos ? 0 : ConvToInt(parameters[1].substr(delimpos + 1)));

			if (parameters[1].find_first_not_of("0123456789:") != std::string::npos
				|| parameters[1].rfind(':') != delimpos
				|| port > 65535 || sslport > 65535)
			{
				user->WriteNotice("*** Invalid port number");
				return CMD_FAILURE;
			}

			if (redirect_all_immediately)
			{
				/* Redirect everyone but the oper sending the command */
				for (LocalUserList::const_iterator i = ServerInstance->Users->local_users.begin(); i != ServerInstance->Users->local_users.end(); ++i)
				{
					LocalUser* t = *i;
					if (!t->IsOper())
					{
						t->WriteNumeric(10, "%s %s %d :Please use this Server/Port instead", t->nick.c_str(), parameters[0].c_str(), GetPort(t));
						ServerInstance->Users->QuitUser(t, reason);
						n_done++;
					}
				}
				if (n_done)
				{
					n_done_s = ConvToStr(n_done);
				}
			}

			if (redirect_new_users)
				redirect_to = parameters[0];

			user->WriteNotice("*** Set jumpserver to server '" + parameters[0] + "' port '" + (port ? ConvToStr(port) : "Auto") + ", SSL " + (sslport ? ConvToStr(sslport) : "Auto") + "', flags '+" +
				(redirect_all_immediately ? "a" : "") + (redirect_new_users ? "n'" : "'") +
				(n_done ? " (" + n_done_s + "user(s) redirected): " : ": ") + reason);
		}

		return CMD_SUCCESS;
	}
Beispiel #19
0
/**
 * This function is called once a second from the mainloop.
 * It is intended to do background checking on all the user structs, e.g.
 * stuff like ping checks, registration timeouts, etc.
 */
void UserManager::DoBackgroundUserStuff()
{
    /*
     * loop over all local users..
     */
    for (LocalUserList::iterator i = local_users.begin(); i != local_users.end(); ++i)
    {
        LocalUser* curr = *i;

        if (curr->quitting)
            continue;

        if (curr->CommandFloodPenalty || curr->eh.getSendQSize())
        {
            unsigned int rate = curr->MyClass->GetCommandRate();
            if (curr->CommandFloodPenalty > rate)
                curr->CommandFloodPenalty -= rate;
            else
                curr->CommandFloodPenalty = 0;
            curr->eh.OnDataReady();
        }

        switch (curr->registered)
        {
        case REG_ALL:
            if (ServerInstance->Time() > curr->nping)
            {
                // This user didn't answer the last ping, remove them
                if (!curr->lastping)
                {
                    time_t time = ServerInstance->Time() - (curr->nping - curr->MyClass->GetPingTime());
                    const std::string message = "Ping timeout: " + ConvToStr(time) + (time == 1 ? " seconds" : " second");
                    this->QuitUser(curr, message);
                    continue;
                }

                curr->Write("PING :" + ServerInstance->Config->ServerName);
                curr->lastping = 0;
                curr->nping = ServerInstance->Time() + curr->MyClass->GetPingTime();
            }
            break;
        case REG_NICKUSER:
            if (AllModulesReportReady(curr))
            {
                /* User has sent NICK/USER, modules are okay, DNS finished. */
                curr->FullConnect();
                continue;
            }
            break;
        }

        if (curr->registered != REG_ALL && (ServerInstance->Time() > (curr->age + curr->MyClass->GetRegTimeout())))
        {
            /*
             * registration timeout -- didnt send USER/NICK/HOST
             * in the time specified in their connection class.
             */
            this->QuitUser(curr, "Registration timeout");
            continue;
        }
    }
}
Beispiel #20
0
/**
 * This function is called once a second from the mainloop.
 * It is intended to do background checking on all the user structs, e.g.
 * stuff like ping checks, registration timeouts, etc.
 */
void InspIRCd::DoBackgroundUserStuff()
{
	/*
	 * loop over all local users..
	 */
	LocalUserList::reverse_iterator count2 = this->Users->local_users.rbegin();
	while (count2 != this->Users->local_users.rend())
	{
		LocalUser *curr = *count2;
		count2++;

		if (curr->quitting)
			continue;

		if (curr->CommandFloodPenalty || curr->eh.getSendQSize())
		{
			unsigned int rate = curr->MyClass->GetCommandRate();
			if (curr->CommandFloodPenalty > rate)
				curr->CommandFloodPenalty -= rate;
			else
				curr->CommandFloodPenalty = 0;
			curr->eh.OnDataReady();
		}

		switch (curr->registered)
		{
			case REG_ALL:
				if (Time() > curr->nping)
				{
					// This user didn't answer the last ping, remove them
					if (!curr->lastping)
					{
						time_t time = this->Time() - (curr->nping - curr->MyClass->GetPingTime());
						char message[MAXBUF];
						snprintf(message, MAXBUF, "Ping timeout: %ld second%s", (long)time, time > 1 ? "s" : "");
						curr->lastping = 1;
						curr->nping = Time() + curr->MyClass->GetPingTime();
						this->Users->QuitUser(curr, message);
						continue;
					}

					curr->Write("PING :%s",this->Config->ServerName.c_str());
					curr->lastping = 0;
					curr->nping = Time()  +curr->MyClass->GetPingTime();
				}
				break;
			case REG_NICKUSER:
				if (AllModulesReportReady(curr))
				{
					/* User has sent NICK/USER, modules are okay, DNS finished. */
					curr->FullConnect();
					continue;
				}
				break;
		}

		if (curr->registered != REG_ALL && (Time() > (curr->age + curr->MyClass->GetRegTimeout())))
		{
			/*
			 * registration timeout -- didnt send USER/NICK/HOST
			 * in the time specified in their connection class.
			 */
			this->Users->QuitUser(curr, "Registration timeout");
			continue;
		}
	}
}
Beispiel #21
0
	CmdResult Handle (const std::vector<std::string> &parameters, User *user)
	{
		if (parameters.size() > 1 && parameters[1] != ServerInstance->Config->ServerName.c_str())
			return CMD_SUCCESS;

		User *targuser;
		Channel *targchan;
		std::string checkstr;
		std::string chliststr;

		checkstr = ":" + ServerInstance->Config->ServerName + " 304 " + user->nick + " :CHECK";

		targuser = ServerInstance->FindNick(parameters[0]);
		targchan = ServerInstance->FindChan(parameters[0]);

		/*
		 * Syntax of a /check reply:
		 *  :server.name 304 target :CHECK START <target>
		 *  :server.name 304 target :CHECK <field> <value>
		 *  :server.name 304 target :CHECK END
		 */

		user->SendText(checkstr + " START " + parameters[0]);

		if (targuser)
		{
			LocalUser* loctarg = IS_LOCAL(targuser);
			/* /check on a user */
			user->SendText(checkstr + " nuh " + targuser->GetFullHost());
			user->SendText(checkstr + " realnuh " + targuser->GetFullRealHost());
			user->SendText(checkstr + " realname " + targuser->fullname);
			user->SendText(checkstr + " modes +" + targuser->FormatModes());
			user->SendText(checkstr + " snomasks " + GetSnomasks(targuser));
			user->SendText(checkstr + " server " + targuser->server->GetName());
			user->SendText(checkstr + " uid " + targuser->uuid);
			user->SendText(checkstr + " signon " + timestring(targuser->signon));
			user->SendText(checkstr + " nickts " + timestring(targuser->age));
			if (loctarg)
				user->SendText(checkstr + " lastmsg " + timestring(loctarg->idle_lastmsg));

			if (targuser->IsAway())
			{
				/* user is away */
				user->SendText(checkstr + " awaytime " + timestring(targuser->awaytime));
				user->SendText(checkstr + " awaymsg " + targuser->awaymsg);
			}

			if (targuser->IsOper())
			{
				OperInfo* oper = targuser->oper;
				/* user is an oper of type ____ */
				user->SendText(checkstr + " opertype " + oper->name);
				if (loctarg)
				{
					std::string umodes;
					std::string cmodes;
					for(char c='A'; c < 'z'; c++)
					{
						ModeHandler* mh = ServerInstance->Modes->FindMode(c, MODETYPE_USER);
						if (mh && mh->NeedsOper() && loctarg->HasModePermission(c, MODETYPE_USER))
							umodes.push_back(c);
						mh = ServerInstance->Modes->FindMode(c, MODETYPE_CHANNEL);
						if (mh && mh->NeedsOper() && loctarg->HasModePermission(c, MODETYPE_CHANNEL))
							cmodes.push_back(c);
					}
					user->SendText(checkstr + " modeperms user="******" channel=" + cmodes);
					std::string opcmds;
					for(std::set<std::string>::iterator i = oper->AllowedOperCommands.begin(); i != oper->AllowedOperCommands.end(); i++)
					{
						opcmds.push_back(' ');
						opcmds.append(*i);
					}
					std::stringstream opcmddump(opcmds);
					user->SendText(checkstr + " commandperms", opcmddump);
					std::string privs;
					for(std::set<std::string>::iterator i = oper->AllowedPrivs.begin(); i != oper->AllowedPrivs.end(); i++)
					{
						privs.push_back(' ');
						privs.append(*i);
					}
					std::stringstream privdump(privs);
					user->SendText(checkstr + " permissions", privdump);
				}
			}

			if (loctarg)
			{
				user->SendText(checkstr + " clientaddr " + loctarg->client_sa.str());
				user->SendText(checkstr + " serveraddr " + loctarg->server_sa.str());

				std::string classname = loctarg->GetClass()->name;
				if (!classname.empty())
					user->SendText(checkstr + " connectclass " + classname);
			}
			else
				user->SendText(checkstr + " onip " + targuser->GetIPString());

			for (UCListIter i = targuser->chans.begin(); i != targuser->chans.end(); i++)
			{
				Channel* c = (*i)->chan;
				chliststr.append(c->GetPrefixChar(targuser)).append(c->name).append(" ");
			}

			std::stringstream dump(chliststr);

			user->SendText(checkstr + " onchans", dump);

			dumpExt(user, checkstr, targuser);
		}
		else if (targchan)
		{
			/* /check on a channel */
			user->SendText(checkstr + " timestamp " + timestring(targchan->age));

			if (targchan->topic[0] != 0)
			{
				/* there is a topic, assume topic related information exists */
				user->SendText(checkstr + " topic " + targchan->topic);
				user->SendText(checkstr + " topic_setby " + targchan->setby);
				user->SendText(checkstr + " topic_setat " + timestring(targchan->topicset));
			}

			user->SendText(checkstr + " modes " + targchan->ChanModes(true));
			user->SendText(checkstr + " membercount " + ConvToStr(targchan->GetUserCounter()));

			/* now the ugly bit, spool current members of a channel. :| */

			const UserMembList *ulist= targchan->GetUsers();

			/* note that unlike /names, we do NOT check +i vs in the channel */
			for (UserMembCIter i = ulist->begin(); i != ulist->end(); i++)
			{
				/*
			 	 * Unlike Asuka, I define a clone as coming from the same host. --w00t
			 	 */
				user->SendText("%s member %-3lu %s%s (%s@%s) %s ",
					checkstr.c_str(), ServerInstance->Users->GlobalCloneCount(i->first),
					targchan->GetAllPrefixChars(i->first), i->first->nick.c_str(),
					i->first->ident.c_str(), i->first->dhost.c_str(), i->first->fullname.c_str());
			}

			const ModeParser::ListModeList& listmodes = ServerInstance->Modes->GetListModes();
			for (ModeParser::ListModeList::const_iterator i = listmodes.begin(); i != listmodes.end(); ++i)
				dumpListMode(user, checkstr, (*i)->GetList(targchan));

			dumpExt(user, checkstr, targchan);
		}
		else
		{
			/*  /check on an IP address, or something that doesn't exist */
			long x = 0;

			/* hostname or other */
			for (user_hash::const_iterator a = ServerInstance->Users->clientlist->begin(); a != ServerInstance->Users->clientlist->end(); a++)
			{
				if (InspIRCd::Match(a->second->host, parameters[0], ascii_case_insensitive_map) || InspIRCd::Match(a->second->dhost, parameters[0], ascii_case_insensitive_map))
				{
					/* host or vhost matches mask */
					user->SendText(checkstr + " match " + ConvToStr(++x) + " " + a->second->GetFullRealHost() + " " + a->second->GetIPString() + " " + a->second->fullname);
				}
				/* IP address */
				else if (InspIRCd::MatchCIDR(a->second->GetIPString(), parameters[0]))
				{
					/* same IP. */
					user->SendText(checkstr + " match " + ConvToStr(++x) + " " + a->second->GetFullRealHost() + " " + a->second->GetIPString() + " " + a->second->fullname);
				}
			}

			user->SendText(checkstr + " matches " + ConvToStr(x));
		}

		user->SendText(checkstr + " END " + parameters[0]);

		return CMD_SUCCESS;
	}
Beispiel #22
0
/* add a client connection to the sockets list */
void UserManager::AddUser(int socket, ListenSocket* via, irc::sockets::sockaddrs* client, irc::sockets::sockaddrs* server)
{
	/* NOTE: Calling this one parameter constructor for User automatically
	 * allocates a new UUID and places it in the hash_map.
	 */
	LocalUser* New = NULL;
	try
	{
		New = new LocalUser(socket, client, server);
	}
	catch (...)
	{
		ServerInstance->Logs->Log("USERS", LOG_DEFAULT, "*** WTF *** Duplicated UUID! -- Crack smoking monkeys have been unleashed.");
		ServerInstance->SNO->WriteToSnoMask('a', "WARNING *** Duplicate UUID allocated!");
		return;
	}
	UserIOHandler* eh = &New->eh;

	// If this listener has an IO hook provider set then tell it about the connection
	if (via->iohookprov)
		via->iohookprov->OnAccept(eh, client, server);

	ServerInstance->Logs->Log("USERS", LOG_DEBUG, "New user fd: %d", socket);

	this->unregistered_count++;

	/* The users default nick is their UUID */
	New->nick = New->uuid;
	this->clientlist[New->nick] = New;

	New->registered = REG_NONE;
	New->signon = ServerInstance->Time();
	New->lastping = 1;

	this->AddClone(New);

	this->local_users.push_front(New);

	if (this->local_users.size() > ServerInstance->Config->SoftLimit)
	{
		ServerInstance->SNO->WriteToSnoMask('a', "Warning: softlimit value has been reached: %d clients", ServerInstance->Config->SoftLimit);
		this->QuitUser(New,"No more connections allowed");
		return;
	}

	/*
	 * First class check. We do this again in FullConnect after DNS is done, and NICK/USER is recieved.
	 * See my note down there for why this is required. DO NOT REMOVE. :) -- w00t
	 */
	New->SetClass();

	/*
	 * Check connect class settings and initialise settings into User.
	 * This will be done again after DNS resolution. -- w00t
	 */
	New->CheckClass(ServerInstance->Config->CCOnConnect);
	if (New->quitting)
		return;

	/*
	 * even with bancache, we still have to keep User::exempt current.
	 * besides that, if we get a positive bancache hit, we still won't f**k
	 * them over if they are exempt. -- w00t
	 */
	New->exempt = (ServerInstance->XLines->MatchesLine("E",New) != NULL);

	BanCacheHit* const b = ServerInstance->BanCache.GetHit(New->GetIPString());
	if (b)
	{
		if (!b->Type.empty() && !New->exempt)
		{
			/* user banned */
			ServerInstance->Logs->Log("BANCACHE", LOG_DEBUG, "BanCache: Positive hit for " + New->GetIPString());
			if (!ServerInstance->Config->XLineMessage.empty())
				New->WriteNumeric(ERR_YOUREBANNEDCREEP, ":" + ServerInstance->Config->XLineMessage);
			this->QuitUser(New, b->Reason);
			return;
		}
		else
		{
			ServerInstance->Logs->Log("BANCACHE", LOG_DEBUG, "BanCache: Negative hit for " + New->GetIPString());
		}
	}
	else
	{
		if (!New->exempt)
		{
			XLine* r = ServerInstance->XLines->MatchesLine("Z",New);

			if (r)
			{
				r->Apply(New);
				return;
			}
		}
	}

	if (!SocketEngine::AddFd(eh, FD_WANT_FAST_READ | FD_WANT_EDGE_WRITE))
	{
		ServerInstance->Logs->Log("USERS", LOG_DEBUG, "Internal error on new connection");
		this->QuitUser(New, "Internal error handling connection");
	}

	if (ServerInstance->Config->RawLog)
		New->WriteNotice("*** Raw I/O logging is enabled on this server. All messages, passwords, and commands are being recorded.");

	FOREACH_MOD(OnSetUserIP, (New));
	if (New->quitting)
		return;

	FOREACH_MOD(OnUserInit, (New));
}