Пример #1
0
	CmdResult Handle (const std::vector<std::string> &parameters, User *user)
	{
		std::string retbuf = "340 " + user->nick + " :";
		int nicks = 0;

		for (int i = 0; i < (int)parameters.size(); i++)
		{
			User *u = ServerInstance->FindNick(parameters[i]);
			if ((u) && (u->registered == REG_ALL))
			{
				retbuf = retbuf + u->nick + (u->IsOper() ? "*" : "") + "=";
				if (u->IsAway())
					retbuf += "-";
				else
					retbuf += "+";
				retbuf += u->ident + "@" + u->GetIPString() + " ";
				nicks++;
			}
		}

		if (nicks != 0)
			user->WriteServ(retbuf);

		/* Dont send to the network */
		return CMD_SUCCESS;
	}
Пример #2
0
    CmdResult Handle (const std::vector<std::string> &parameters, User *user)
    {
        std::string retbuf = "340 " + user->nick + " :";
        int nicks = 0;
        bool checked_privs = false;
        bool has_privs = false;

        for (int i = 0; i < (int)parameters.size(); i++)
        {
            User *u = ServerInstance->FindNick(parameters[i]);
            if ((u) && (u->registered == REG_ALL))
            {
                // Anyone may query their own IP
                if (u != user)
                {
                    if (!checked_privs)
                    {
                        // Do not trigger the insufficient priviliges message more than once
                        checked_privs = true;
                        has_privs = user->HasPrivPermission("users/auspex");
                        if (!has_privs)
                            user->WriteNumeric(ERR_NOPRIVILEGES, ":Permission Denied - You do not have the required operator privileges");
                    }

                    if (!has_privs)
                        continue;
                }

                retbuf = retbuf + u->nick + (u->IsOper() ? "*" : "") + "=";
                if (u->IsAway())
                    retbuf += "-";
                else
                    retbuf += "+";
                retbuf += u->ident + "@" + u->GetIPString() + " ";
                nicks++;
            }
        }

        if (nicks != 0)
            user->WriteServ(retbuf);

        return CMD_SUCCESS;
    }
Пример #3
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;
	}
Пример #4
0
/** Handle /GLINE
 */
CmdResult CommandGline::Handle (const std::vector<std::string>& parameters, User *user)
{
	std::string target = parameters[0];

	if (parameters.size() >= 3)
	{
		IdentHostPair ih;
		User* find = ServerInstance->FindNick(target);
		if ((find) && (find->registered == REG_ALL))
		{
			ih.first = "*";
			ih.second = find->GetIPString();
			target = std::string("*@") + find->GetIPString();
		}
		else
			ih = ServerInstance->XLines->IdentSplit(target);

		if (ih.first.empty())
		{
			user->WriteNotice("*** Target not found");
			return CMD_FAILURE;
		}

		if (ServerInstance->HostMatchesEveryone(ih.first+"@"+ih.second,user))
			return CMD_FAILURE;

		else if (target.find('!') != std::string::npos)
		{
			user->WriteNotice("*** G-Line cannot operate on nick!user@host masks");
			return CMD_FAILURE;
		}

		unsigned long duration = InspIRCd::Duration(parameters[1]);
		GLine* gl = new GLine(ServerInstance->Time(), duration, user->nick.c_str(), parameters[2].c_str(), ih.first.c_str(), ih.second.c_str());
		if (ServerInstance->XLines->AddLine(gl, user))
		{
			if (!duration)
			{
				ServerInstance->SNO->WriteToSnoMask('x',"%s added permanent G-line for %s: %s",user->nick.c_str(),target.c_str(), parameters[2].c_str());
			}
			else
			{
				time_t c_requires_crap = duration + ServerInstance->Time();
				std::string timestr = ServerInstance->TimeString(c_requires_crap);
				ServerInstance->SNO->WriteToSnoMask('x',"%s added timed G-line for %s, expires on %s: %s",user->nick.c_str(),target.c_str(),
						timestr.c_str(), parameters[2].c_str());
			}

			ServerInstance->XLines->ApplyLines();
		}
		else
		{
			delete gl;
			user->WriteNotice("** G-Line for " + target + " already exists");
		}

	}
	else
	{
		if (ServerInstance->XLines->DelLine(target.c_str(),"G",user))
		{
			ServerInstance->SNO->WriteToSnoMask('x',"%s removed G-line on %s",user->nick.c_str(),target.c_str());
		}
		else
		{
			user->WriteNotice("*** G-Line " + target + " not found in list, try /stats g.");
		}
	}

	return CMD_SUCCESS;
}
Пример #5
0
	CmdResult Handle(const std::vector<std::string>& parameters, User *user)
	{
		/* syntax: SHUN nick!user@host time :reason goes here */
		/* 'time' is a human-readable timestring, like 2d3h2s. */

		std::string target = parameters[0];

		User *find = ServerInstance->FindNick(target);
		if ((find) && (find->registered == REG_ALL))
			target = std::string("*!*@") + find->GetIPString();

		if (parameters.size() == 1)
		{
			if (ServerInstance->XLines->DelLine(target.c_str(), "SHUN", user))
			{
				ServerInstance->SNO->WriteToSnoMask('x',"%s removed SHUN on %s",user->nick.c_str(),target.c_str());
			}
			else
			{
				user->WriteNotice("*** Shun " + target + " not found in list, try /stats H.");
				return CMD_FAILURE;
			}
		}
		else
		{
			// Adding - XXX todo make this respect <insane> tag perhaps..
			unsigned long duration;
			std::string expr;
			if (parameters.size() > 2)
			{
				duration = InspIRCd::Duration(parameters[1]);
				expr = parameters[2];
			}
			else
			{
				duration = 0;
				expr = parameters[1];
			}

			Shun* r = new Shun(ServerInstance->Time(), duration, user->nick.c_str(), expr.c_str(), target.c_str());
			if (ServerInstance->XLines->AddLine(r, user))
			{
				if (!duration)
				{
					ServerInstance->SNO->WriteToSnoMask('x',"%s added permanent SHUN for %s: %s",
						user->nick.c_str(), target.c_str(), expr.c_str());
				}
				else
				{
					time_t c_requires_crap = duration + ServerInstance->Time();
					std::string timestr = ServerInstance->TimeString(c_requires_crap);
					ServerInstance->SNO->WriteToSnoMask('x', "%s added timed SHUN for %s to expire on %s: %s",
						user->nick.c_str(), target.c_str(), timestr.c_str(), expr.c_str());
				}
			}
			else
			{
				delete r;
				user->WriteNotice("*** Shun for " + target + " already exists");
				return CMD_FAILURE;
			}
		}
		return CMD_SUCCESS;
	}
Пример #6
0
	CmdResult Handle(const std::vector<std::string>& parameters, User *user)
	{
		std::string target = parameters[0];
		if (parameters.size() >= 3)
		{
			IdentHostPair ih;
			User* find = ServerInstance->FindNick(target);
			if ((find) && (find->registered == REG_ALL))
			{
				ih.first = "*";
				ih.second = find->GetIPString();
				target = std::string("*@") + find->GetIPString();
			}
			else
				ih = ServerInstance->XLines->IdentSplit(target);

			if (ih.first.empty())
			{
				user->WriteServ("NOTICE %s :*** Target not found", user->nick.c_str());
				return CMD_FAILURE;
			}

			if (ServerInstance->HostMatchesEveryone(ih.first+"@"+ih.second,user))
				return CMD_FAILURE;
			else if (target.find('!') != std::string::npos)
			{
				std::string message = "NOTICE %s :*** "+linename+"-Line cannot operate on nick!user@host masks";
				user->WriteServ(message);
				return CMD_FAILURE;
			}

			XLineFactory* xlf = ServerInstance->XLines->GetFactory(linename);
			if (!xlf)
				return CMD_FAILURE;

			long duration = ServerInstance->Duration(parameters[1]);
			XLine* al = xlf->Generate(ServerInstance->Time(), duration, user->nick, parameters[2], target);
			if (ServerInstance->XLines->AddLine(al, user))
			{
				if (!duration)
				{
					ServerInstance->SNO->WriteToSnoMask('x', "%s added permanent %s-line for %s: %s",user->nick.c_str(), linename.c_str(), target.c_str(), parameters[2].c_str());
				}
				else
				{
					time_t c_requires_crap = duration + ServerInstance->Time();
					std::string timestr = ServerInstance->TimeString(c_requires_crap);
					ServerInstance->SNO->WriteToSnoMask('x',"%s added timed %s-line for %s, expires on %s: %s",user->nick.c_str(),linename.c_str(),target.c_str(),timestr.c_str(), parameters[2].c_str());
				}
				ServerInstance->XLines->ApplyLines();
			}
			else
			{
				delete al;
				user->WriteServ("NOTICE %s :*** %s-Line for %s already exists",user->nick.c_str(),linename.c_str(),target.c_str());
			}
		}
		else
		{
			if (ServerInstance->XLines->DelLine(target.c_str(),linename,user))
			{
				ServerInstance->SNO->WriteToSnoMask('x',"%s removed %s-line on %s",user->nick.c_str(),linename.c_str(),target.c_str());
			}
			else
			{
				user->WriteServ("NOTICE %s :*** %s-Line %s not found in list, try /stats %c.",user->nick.c_str(),linename.c_str(),target.c_str(), statschar);
			}
		}

		return CMD_SUCCESS;
	}
Пример #7
0
/** Handle /KLINE
 */
CmdResult CommandKline::Handle (const std::vector<std::string>& parameters, User *user)
{
    std::string target = parameters[0];

	if (parameters.size() >= 3)
	{
		IdentHostPair ih;
		User* find = ServerInstance->FindNick(target.c_str());
		if (find)
		{
			ih.first = "*";
			ih.second = find->GetIPString();
			target = std::string("*@") + find->GetIPString();
		}
		else
			ih = ServerInstance->XLines->IdentSplit(target.c_str());

        if (ih.first.empty())
        {
            user->WriteServ("NOTICE %s :*** Target not found", user->nick.c_str());
            return CMD_FAILURE;
        }

		if (ServerInstance->HostMatchesEveryone(ih.first+"@"+ih.second,user))
			return CMD_FAILURE;

		if (target.find('!') != std::string::npos)
		{
			user->WriteServ("NOTICE %s :*** K-Line cannot operate on nick!user@host masks",user->nick.c_str());
			return CMD_FAILURE;
		}

		long duration = ServerInstance->Duration(parameters[1].c_str());
		KLine* kl = new KLine(ServerInstance, ServerInstance->Time(), duration, user->nick.c_str(), parameters[2].c_str(), ih.first.c_str(), ih.second.c_str());
		if (ServerInstance->XLines->AddLine(kl,user))
		{
			if (!duration)
			{
				ServerInstance->SNO->WriteToSnoMask('x',"%s added permanent K-line for %s: %s",user->nick.c_str(),target.c_str(), parameters[2].c_str());
			}
			else
			{
				time_t c_requires_crap = duration + ServerInstance->Time();
				ServerInstance->SNO->WriteToSnoMask('x',"%s added timed K-line for %s, expires on %s: %s",user->nick.c_str(),target.c_str(),
						ServerInstance->TimeString(c_requires_crap).c_str(), parameters[2].c_str());
			}

			ServerInstance->XLines->ApplyLines();
		}
		else
		{
			delete kl;
			user->WriteServ("NOTICE %s :*** K-Line for %s already exists",user->nick.c_str(),target.c_str());
		}
	}
	else
	{
		if (ServerInstance->XLines->DelLine(target.c_str(),"K",user))
		{
			ServerInstance->SNO->WriteToSnoMask('x',"%s Removed K-line on %s.",user->nick.c_str(),target.c_str());
		}
		else
		{
			user->WriteServ("NOTICE %s :*** K-Line %s not found in list, try /stats k.",user->nick.c_str(),target.c_str());
		}
	}

	return CMD_SUCCESS;
}
Пример #8
0
	/* SQL Request */
	virtual const char* OnRequest(Request* request) {
		if(strcmp(SQLRESID, request->GetId()) == 0) {
			SQLresult* res = static_cast<SQLresult*>(request);

			User* user = GetAssocUser(this, SQLutils, res->id).S().user;
			UnAssociate(this, SQLutils, res->id).S();

			if(user) {
				if(res->error.Id() == SQL_NO_ERROR) {
					std::string* wnick;
					bool result;

					if(res->Rows()) {
						int rowcount=res->Rows(),i;

						/* Clean Custom User Metadata */
						user->Shrink("sqlAllowedIdent");
						user->Shrink("sqlAllowedHost");
						user->Shrink("sqlvHost");
						user->Shrink("sqlTitle");
						user->Shrink("sqlumodes");

						std::string sqlvHost;
						std::string sqlTitle;
						std::string sqlumodes;
						std::string sqlAllowedIdent;
						std::string sqlAllowedHost;

						/* Get Data from SQL (using freeform query. "query" in modules.conf) */
						for (i=0; i<rowcount; ++i) {
							SQLfieldList& currow = res->GetRow();
							sqlAllowedIdent = currow[1].d.c_str();
							sqlAllowedHost = currow[2].d.c_str();
							sqlvHost = currow[3].d.c_str();
							sqlTitle = currow[4].d.c_str();
							sqlumodes = currow[5].d.c_str();
						}

						std::string* pAllowedIdent = new std::string(sqlAllowedIdent);
						std::string* pAllowedHost = new std::string(sqlAllowedHost);
						std::string* pvHost = new std::string(sqlvHost);
						std::string* pTitle = new std::string(sqlTitle);
						std::string* pumodes = new std::string(sqlumodes);

						user->Extend("sqlAllowedIdent",pAllowedIdent);
						user->Extend("sqlAllowedHost",pAllowedHost);
						user->Extend("sqlvHost",pvHost);
						user->Extend("sqlTitle",pTitle);
						user->Extend("sqlumodes",pumodes);

						/* Check Allowed Ident@Hostname from SQL */
						if (sqlAllowedIdent != "" && sqlAllowedHost != "") {
							char TheHost[MAXBUF];
							char TheIP[MAXBUF];
							char TheAllowedUHost[MAXBUF];

							snprintf(TheHost,MAXBUF,"%s@%s",user->ident.c_str(), user->host.c_str());
							snprintf(TheIP, MAXBUF,"%s@%s",user->ident.c_str(), user->GetIPString());
							snprintf(TheAllowedUHost, MAXBUF, "%s@%s", sqlAllowedIdent.c_str(), sqlAllowedHost.c_str());

							if (!OneOfMatches(TheHost,TheIP,TheAllowedUHost)) {
								if (killreasonUHost == "") { killreasonUHost = "Your ident or hostmask did not match the one registered to this nickname. Allowed: $allowedident@$allowedhost"; }
								std::string tmpKillReason = killreasonUHost;
								SearchAndReplace(tmpKillReason, "$allowedident", sqlAllowedIdent.c_str());
								SearchAndReplace(tmpKillReason, "$allowedhost", sqlAllowedHost.c_str());

								/* Run Failure SQL Insert Query (For Logging) */
								std::string repfquery = failurequery;
								if (repfquery != "") {
									if (user->GetExt("wantsnick", wnick)) {
										SearchAndReplace(repfquery, "$nick", *wnick);
									} else {
										SearchAndReplace(repfquery, "$nick", user->nick);
									}

									SearchAndReplace(repfquery, "$host", user->host);
									SearchAndReplace(repfquery, "$ip", user->GetIPString());
									SearchAndReplace(repfquery, "$reason", tmpKillReason.c_str());

									SQLrequest req = SQLrequest(this, SQLprovider, databaseid, SQLquery(repfquery));
									result = req.Send();
								}

								ServerInstance->Users->QuitUser(user, tmpKillReason);

								user->Extend("sqlauth_failed");
								return NULL;
							}
						}

						/* We got a result, auth user */
						user->Extend("sqlauthed");

						/* possible ghosting? */
						if (user->GetExt("wantsnick", wnick)) {
							/* no need to check ghosting, this is done in OnPreCommand
							 * and if ghosting is off, user wont have the Extend 
							 */
							User* InUse = ServerInstance->FindNickOnly(wnick->c_str());
							if (InUse) {
								/* change his nick to UUID so we can take it */
								//InUse->ForceNickChange(InUse->uuid.c_str());
								/* put user on cull list */
								ServerInstance->Users->QuitUser(InUse, "Ghosted by connecting user with same nick.");
							}
							/* steal the nick ;) */
							user->ForceNickChange(wnick->c_str());
							user->Shrink("wantsnick");
						}

						/* Set Account Name (for m_services_account +R/+M channels) */
						if (setaccount) {
							std::string* pAccount = new std::string(user->nick.c_str());

							user->Extend("accountname",pAccount);
						}

						/* Run Success SQL Update Query */
						std::string repsquery = successquery;
						if (successquery != "") {
							SearchAndReplace(repsquery, "$nick", user->nick);
							SearchAndReplace(repsquery, "$host", user->host);
							SearchAndReplace(repsquery, "$ip", user->GetIPString());

							SQLrequest req = SQLrequest(this, SQLprovider, databaseid, SQLquery(repsquery));
							result = req.Send();
						}

					/* Returned No Rows */
					} else {
						if (verbose) {
							/* No rows in result, this means there was no record matching the user */
							ServerInstance->SNO->WriteToSnoMask('A', "Forbidden connection from %s!%s@%s (SQL query returned no matches)", user->nick.c_str(), user->ident.c_str(), user->host.c_str());
						}

						/* Run Failure SQL Insert Query (For Logging) */
						std::string repfquery = failurequery;
						if (repfquery != "") {
							if (user->GetExt("wantsnick", wnick)) {
								SearchAndReplace(repfquery, "$nick", *wnick);
							} else {
								SearchAndReplace(repfquery, "$nick", user->nick);
							}

							SearchAndReplace(repfquery, "$host", user->host);
							SearchAndReplace(repfquery, "$ip", user->GetIPString());
							SearchAndReplace(repfquery, "$reason", killreason.c_str());

							SQLrequest req = SQLrequest(this, SQLprovider, databaseid, SQLquery(repfquery));
							result = req.Send();
						}

						/* Kill user that entered invalid credentials */
						ServerInstance->Users->QuitUser(user, killreason);

						user->Extend("sqlauth_failed");
					}
				/* SQL Failure */
				} else {
					if (verbose) {
						ServerInstance->SNO->WriteToSnoMask('A', "Forbidden connection from %s!%s@%s (SQL query failed: %s)", user->nick.c_str(), user->ident.c_str(), user->host.c_str(), res->error.Str());
					}
					
					user->Extend("sqlauth_failed");
				}
			} else {
				return NULL;
			}

			if (!user->GetExt("sqlauthed")) {
				ServerInstance->Users->QuitUser(user, killreason);
			}
			return SQLSUCCESS;
		}
		return NULL;
	}
Пример #9
0
void TreeSocket::ProcessConnectedLine(std::string& prefix, std::string& command, parameterlist& params)
{
	User* who = ServerInstance->FindUUID(prefix);
	std::string direction;

	if (!who)
	{
		TreeServer* ServerSource = Utils->FindServer(prefix);
		if (prefix.empty())
			ServerSource = MyRoot;

		if (ServerSource)
		{
			who = ServerSource->ServerUser;
		}
		else
		{
			/* It is important that we don't close the link here, unknown prefix can occur
			 * due to various race conditions such as the KILL message for a user somehow
			 * crossing the users QUIT further upstream from the server. Thanks jilles!
			 */

			if ((prefix.length() == UUID_LENGTH-1) && (isdigit(prefix[0])) &&
				((command == "FMODE") || (command == "MODE") || (command == "KICK") || (command == "TOPIC") || (command == "KILL") || (command == "ADDLINE") || (command == "DELLINE")))
			{
				/* Special case, we cannot drop these commands as they've been committed already on a
				 * part of the network by the time we receive them, so in this scenario pretend the
				 * command came from a server to avoid desync.
				 */

				who = ServerInstance->FindUUID(prefix.substr(0, 3));
				if (!who)
					who = this->MyRoot->ServerUser;
			}
			else
			{
				ServerInstance->Logs->Log("m_spanningtree", DEBUG, "Command '%s' from unknown prefix '%s'! Dropping entire command.",
					command.c_str(), prefix.c_str());
				return;
			}
		}
	}

	// Make sure prefix is still good
	direction = who->server;
	prefix = who->uuid;

	/*
	 * Check for fake direction here, and drop any instances that are found.
	 * What is fake direction? Imagine the following server setup:
	 *    0AA <-> 0AB <-> 0AC
	 * Fake direction would be 0AC sending a message to 0AB claiming to be from
	 * 0AA, or something similar. Basically, a message taking a path that *cannot*
	 * be correct.
	 *
	 * When would this be seen?
	 * Well, hopefully never. It could be caused by race conditions, bugs, or
	 * "miscreant" servers, though, so let's check anyway. -- w
	 *
	 * We also check here for totally invalid prefixes (prefixes that are neither
	 * a valid SID or a valid UUID, so that invalid UUID or SID never makes it
	 * to the higher level functions. -- B
	 */
	TreeServer* route_back_again = Utils->BestRouteTo(direction);
	if ((!route_back_again) || (route_back_again->GetSocket() != this))
	{
		if (route_back_again)
			ServerInstance->Logs->Log("m_spanningtree",DEBUG,"Protocol violation: Fake direction '%s' from connection '%s'",
				prefix.c_str(),linkID.c_str());
		return;
	}

	/*
	 * First up, check for any malformed commands (e.g. MODE without a timestamp)
	 * and rewrite commands where necessary (SVSMODE -> MODE for services). -- w
	 */
	if (command == "SVSMODE") // This isn't in an "else if" so we still force FMODE for changes on channels.
		command = "MODE";

	// TODO move all this into Commands
	if (command == "MAP")
	{
		Utils->Creator->HandleMap(params, who);
	}
	else if (command == "SERVER")
	{
		this->RemoteServer(prefix,params);
	}
	else if (command == "ERROR")
	{
		this->Error(params);
	}
	else if (command == "AWAY")
	{
		this->Away(prefix,params);
	}
	else if (command == "PING")
	{
		this->LocalPing(prefix,params);
	}
	else if (command == "PONG")
	{
		TreeServer *s = Utils->FindServer(prefix);
		if (s && s->bursting)
		{
			ServerInstance->SNO->WriteGlobalSno('l',"Server \002%s\002 has not finished burst, forcing end of burst (send ENDBURST!)", prefix.c_str());
			s->FinishBurst();
		}
		this->LocalPong(prefix,params);
	}
	else if (command == "VERSION")
	{
		this->ServerVersion(prefix,params);
	}
	else if (command == "ADDLINE")
	{
		this->AddLine(prefix,params);
	}
	else if (command == "DELLINE")
	{
		this->DelLine(prefix,params);
	}
	else if (command == "SAVE")
	{
		this->ForceNick(prefix,params);
	}
	else if (command == "OPERQUIT")
	{
		this->OperQuit(prefix,params);
	}
	else if (command == "IDLE")
	{
		this->Whois(prefix,params);
	}
	else if (command == "PUSH")
	{
		this->Push(prefix,params);
	}
	else if (command == "SQUIT")
	{
		if (params.size() == 2)
		{
			this->Squit(Utils->FindServer(params[0]),params[1]);
		}
	}
	else if (command == "SNONOTICE")
	{
		if (params.size() >= 2)
		{
			ServerInstance->SNO->WriteToSnoMask(params[0][0], "From " + who->nick + ": "+ params[1]);
			params[1] = ":" + params[1];
			Utils->DoOneToAllButSender(prefix, command, params, prefix);
		}
	}
	else if (command == "BURST")
	{
		// Set prefix server as bursting
		TreeServer* ServerSource = Utils->FindServer(prefix);
		if (!ServerSource)
		{
			ServerInstance->SNO->WriteGlobalSno('l', "WTF: Got BURST from a non-server(?): %s", prefix.c_str());
			return;
		}

		ServerSource->bursting = true;
		Utils->DoOneToAllButSender(prefix, command, params, prefix);
	}
	else if (command == "ENDBURST")
	{
		TreeServer* ServerSource = Utils->FindServer(prefix);
		if (!ServerSource)
		{
			ServerInstance->SNO->WriteGlobalSno('l', "WTF: Got ENDBURST from a non-server(?): %s", prefix.c_str());
			return;
		}

		ServerSource->FinishBurst();
		Utils->DoOneToAllButSender(prefix, command, params, prefix);
	}
	else if (command == "ENCAP")
	{
		this->Encap(who, params);
	}
	else if (command == "NICK")
	{
		if (params.size() != 2)
		{
			SendError("Protocol violation: Wrong number of parameters for NICK message");
			return;
		}

		if (IS_SERVER(who))
		{
			SendError("Protocol violation: Server changing nick");
			return;
		}

		if ((isdigit(params[0][0])) && (params[0] != who->uuid))
		{
			SendError("Protocol violation: User changing nick to an invalid UID - " + params[0]);
			return;
		}

		/* Update timestamp on user when they change nicks */
		who->age = atoi(params[1].c_str());

		/*
		 * On nick messages, check that the nick doesnt already exist here.
		 * If it does, perform collision logic.
		 */
		User* x = ServerInstance->FindNickOnly(params[0]);
		if ((x) && (x != who))
		{
			int collideret = 0;
			/* x is local, who is remote */
			collideret = this->DoCollision(x, who->age, who->ident, who->GetIPString(), who->uuid);
			if (collideret != 1)
			{
				/*
				 * Remote client lost, or both lost, parsing or passing on this
				 * nickchange would be pointless, as the incoming client's server will
				 * soon recieve SVSNICK to change its nick to its UID. :) -- w00t
				 */
				return;
			}
		}
		who->ForceNickChange(params[0].c_str());
		Utils->RouteCommand(route_back_again, command, params, who);
	}
	else
	{
		Command* cmd = ServerInstance->Parser->GetHandler(command);

		if (!cmd)
		{
			irc::stringjoiner pmlist(" ", params, 0, params.size() - 1);
			ServerInstance->Logs->Log("m_spanningtree", SPARSE, "Unrecognised S2S command :%s %s %s",
				who->uuid.c_str(), command.c_str(), pmlist.GetJoined().c_str());
			SendError("Unrecognised command '" + command + "' -- possibly loaded mismatched modules");
			return;
		}

		if (params.size() < cmd->min_params)
		{
			irc::stringjoiner pmlist(" ", params, 0, params.size() - 1);
			ServerInstance->Logs->Log("m_spanningtree", SPARSE, "Insufficient parameters for S2S command :%s %s %s",
				who->uuid.c_str(), command.c_str(), pmlist.GetJoined().c_str());
			SendError("Insufficient parameters for command '" + command + "'");
			return;
		}

		if ((!params.empty()) && (params.back().empty()) && (!cmd->allow_empty_last_param))
		{
			// the last param is empty and the command handler doesn't allow that, check if there will be enough params if we drop the last
			if (params.size()-1 < cmd->min_params)
				return;
			params.pop_back();
		}

		CmdResult res = cmd->Handle(params, who);

		if (res == CMD_INVALID)
		{
			irc::stringjoiner pmlist(" ", params, 0, params.size() - 1);
			ServerInstance->Logs->Log("m_spanningtree", SPARSE, "Error handling S2S command :%s %s %s",
				who->uuid.c_str(), command.c_str(), pmlist.GetJoined().c_str());
			SendError("Error handling '" + command + "' -- possibly loaded mismatched modules");
		}
		else if (res == CMD_SUCCESS)
			Utils->RouteCommand(route_back_again, command, params, who);
	}
}
Пример #10
0
	CmdResult Handle(const std::vector<std::string>& parameters, User* user)
	{
		std::string target = parameters[0];

		User* u = ServerInstance->FindNick(target);

		/* Allow just 'nick' if valid, otherwise force use of 'nick!user@host' */
		if (target.find('!') == std::string::npos || target.find('@') == std::string::npos)
		{
			if (u && u->registered == REG_ALL)
			{
				/* Use *!*@IP if valid nick is given */
				target = std::string("*!*@") + u->GetIPString();
			}
			else
			{
				user->WriteServ("NOTICE %s :*** NoCreate: No user '%s' found", user->nick.c_str(), target.c_str());
				return CMD_FAILURE;
			}
		}

		/* Adding */
		if (parameters.size() >= 3)
		{
			if (this->MaskIsInsane(target, user))
			{
				user->WriteServ("NOTICE %s :*** NoCreate mask %s flagged as insane",
					user->nick.c_str(), target.c_str());
				return CMD_FAILURE;
			}

			long duration = ServerInstance->Duration(parameters[1]);
			NoCreate* nc = new NoCreate(ServerInstance->Time(), duration, user->nick.c_str(), parameters[2].c_str(), target.c_str());

			if (ServerInstance->XLines->AddLine(nc, user))
			{
				if (!duration)
				{
					ServerInstance->SNO->WriteToSnoMask('x', "%s added permanent NoCreate %s: %s",
						user->nick.c_str(), target.c_str(), parameters[2].c_str());
				}
				else
				{
					ServerInstance->SNO->WriteToSnoMask('x', "%s added timed NoCreate %s, expires on %s: %s",
						user->nick.c_str(), target.c_str(),
						ServerInstance->TimeString(duration + ServerInstance->Time()).c_str(), parameters[2].c_str());
				}
			}
			else
			{
				delete nc;
				user->WriteServ("NOTICE %s :*** NoCreate %s already exists",
					user->nick.c_str(), target.c_str());
				return CMD_FAILURE;
			}
		}
		/* Removing */
		else
		{
			if (ServerInstance->XLines->DelLine(target.c_str(), "NOCREATE", user))
			{
				ServerInstance->SNO->WriteToSnoMask('x', "%s removed NoCreate %s",
					user->nick.c_str(), target.c_str());
			}
			else
			{
				user->WriteServ("NOTICE %s :*** NoCreate %s not found in list, try /stats N",
					user->nick.c_str(), target.c_str());
				return CMD_FAILURE;
			}
		}

		return CMD_SUCCESS;
	}
Пример #11
0
CmdResult CommandZline::Handle(User* user, const Params& parameters)
{
	std::string target = parameters[0];

	if (parameters.size() >= 3)
	{
		if (target.find('!') != std::string::npos)
		{
			user->WriteNotice("*** You cannot include a nickname in a Z-line, a Z-line must ban only an IP mask.");
			return CMD_FAILURE;
		}

		User *u = ServerInstance->FindNick(target);

		if ((u) && (u->registered == REG_ALL))
		{
			target = u->GetIPString();
		}

		const char* ipaddr = target.c_str();

		if (strchr(ipaddr,'@'))
		{
			while (*ipaddr != '@')
				ipaddr++;
			ipaddr++;
		}

		IPMatcher matcher;
		if (InsaneBan::MatchesEveryone(ipaddr, matcher, user, "Z", "ipmasks"))
			return CMD_FAILURE;

		unsigned long duration;
		if (!InspIRCd::Duration(parameters[1], duration))
		{
			user->WriteNotice("*** Invalid duration for Z-line.");
			return CMD_FAILURE;
		}
		ZLine* zl = new ZLine(ServerInstance->Time(), duration, user->nick.c_str(), parameters[2].c_str(), ipaddr);
		if (ServerInstance->XLines->AddLine(zl,user))
		{
			if (!duration)
			{
				ServerInstance->SNO.WriteToSnoMask('x',"%s added permanent Z-line for %s: %s", user->nick.c_str(), ipaddr, parameters[2].c_str());
			}
			else
			{
				time_t c_requires_crap = duration + ServerInstance->Time();
				std::string timestr = InspIRCd::TimeString(c_requires_crap);
				ServerInstance->SNO.WriteToSnoMask('x',"%s added timed Z-line for %s, expires on %s: %s",user->nick.c_str(),ipaddr,
						timestr.c_str(), parameters[2].c_str());
			}
			ServerInstance->XLines->ApplyLines();
		}
		else
		{
			delete zl;
			user->WriteNotice("*** Z-line for " + std::string(ipaddr) + " already exists.");
		}
	}
	else
	{
		std::string reason;

		if (ServerInstance->XLines->DelLine(target.c_str(), "Z", reason, user))
		{
			ServerInstance->SNO.WriteToSnoMask('x', "%s removed Z-line on %s: %s", user->nick.c_str(), target.c_str(), reason.c_str());
		}
		else
		{
			user->WriteNotice("*** Z-line " + target + " not found in list, try /stats Z.");
			return CMD_FAILURE;
		}
	}

	return CMD_SUCCESS;
}
Пример #12
0
CmdResult CommandZline::Handle (const std::vector<std::string>& parameters, User *user)
{
	std::string target = parameters[0];

	if (parameters.size() >= 3)
	{
		if (target.find('!') != std::string::npos)
		{
			user->WriteServ("NOTICE %s :*** You cannot include a nickname in a zline, a zline must ban only an IP mask",user->nick.c_str());
			return CMD_FAILURE;
		}

		User *u = ServerInstance->FindNick(target);

		if ((u) && (u->registered == REG_ALL))
		{
			target = u->GetIPString();
		}

		const char* ipaddr = target.c_str();

		if (strchr(ipaddr,'@'))
		{
			while (*ipaddr != '@')
				ipaddr++;
			ipaddr++;
		}

		if (ServerInstance->IPMatchesEveryone(ipaddr,user))
			return CMD_FAILURE;

		long duration = ServerInstance->Duration(parameters[1].c_str());

		ZLine* zl = new ZLine(ServerInstance->Time(), duration, user->nick.c_str(), parameters[2].c_str(), ipaddr);
		if (ServerInstance->XLines->AddLine(zl,user))
		{
			if (!duration)
			{
				ServerInstance->SNO->WriteToSnoMask('x',"%s added permanent Z-line for %s: %s", user->nick.c_str(), ipaddr, parameters[2].c_str());
			}
			else
			{
				time_t c_requires_crap = duration + ServerInstance->Time();
				std::string timestr = ServerInstance->TimeString(c_requires_crap);
				ServerInstance->SNO->WriteToSnoMask('x',"%s added timed Z-line for %s, expires on %s: %s",user->nick.c_str(),ipaddr,
						timestr.c_str(), parameters[2].c_str());
			}
			ServerInstance->XLines->ApplyLines();
		}
		else
		{
			delete zl;
			user->WriteServ("NOTICE %s :*** Z-Line for %s already exists",user->nick.c_str(),ipaddr);
		}
	}
	else
	{
		if (ServerInstance->XLines->DelLine(target.c_str(),"Z",user))
		{
			ServerInstance->SNO->WriteToSnoMask('x',"%s removed Z-line on %s",user->nick.c_str(),target.c_str());
		}
		else
		{
			user->WriteServ("NOTICE %s :*** Z-Line %s not found in list, try /stats Z.",user->nick.c_str(),target.c_str());
			return CMD_FAILURE;
		}
	}

	return CMD_SUCCESS;
}
Пример #13
0
	CmdResult Handle(User* user, const Params& parameters) override
	{
		/* syntax: SHUN nick!user@host time :reason goes here */
		/* 'time' is a human-readable timestring, like 2d3h2s. */

		std::string target = parameters[0];

		User *find = ServerInstance->FindNick(target);
		if ((find) && (find->registered == REG_ALL))
			target = std::string("*!*@") + find->GetIPString();

		if (parameters.size() == 1)
		{
			std::string reason;

			if (ServerInstance->XLines->DelLine(parameters[0].c_str(), "SHUN", reason, user))
			{
				ServerInstance->SNO.WriteToSnoMask('x', "%s removed SHUN on %s: %s", user->nick.c_str(), parameters[0].c_str(), reason.c_str());
			}
			else if (ServerInstance->XLines->DelLine(target.c_str(), "SHUN", reason, user))
			{
				ServerInstance->SNO.WriteToSnoMask('x', "%s removed SHUN on %s: %s", user->nick.c_str(), target.c_str(), reason.c_str());
			}
			else
			{
				user->WriteNotice("*** Shun " + parameters[0] + " not found in list, try /stats H.");
				return CMD_FAILURE;
			}
		}
		else
		{
			// Adding - XXX todo make this respect <insane> tag perhaps..
			unsigned long duration;
			std::string expr;
			if (parameters.size() > 2)
			{
				if (!InspIRCd::Duration(parameters[1], duration))
				{
					user->WriteNotice("*** Invalid duration for SHUN.");
					return CMD_FAILURE;
				}
				expr = parameters[2];
			}
			else
			{
				duration = 0;
				expr = parameters[1];
			}

			Shun* r = new Shun(ServerInstance->Time(), duration, user->nick.c_str(), expr.c_str(), target.c_str());
			if (ServerInstance->XLines->AddLine(r, user))
			{
				if (!duration)
				{
					ServerInstance->SNO.WriteToSnoMask('x', "%s added permanent SHUN for %s: %s",
						user->nick.c_str(), target.c_str(), expr.c_str());
				}
				else
				{
					ServerInstance->SNO.WriteToSnoMask('x', "%s added timed SHUN for %s to expire in %s (on %s): %s",
						user->nick.c_str(), target.c_str(), InspIRCd::DurationString(duration).c_str(),
						InspIRCd::TimeString(ServerInstance->Time() + duration).c_str(), expr.c_str());
				}
			}
			else
			{
				delete r;
				user->WriteNotice("*** Shun for " + target + " already exists.");
				return CMD_FAILURE;
			}
		}
		return CMD_SUCCESS;
	}