Beispiel #1
0
CmdResult CommandOper::HandleLocal(const std::vector<std::string>& parameters, LocalUser *user)
{
	char TheHost[MAXBUF];
	char TheIP[MAXBUF];
	bool match_login = false;
	bool match_pass = false;
	bool match_hosts = false;

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

	OperIndex::iterator i = ServerInstance->Config->oper_blocks.find(parameters[0]);
	if (i != ServerInstance->Config->oper_blocks.end())
	{
		OperInfo* ifo = i->second;
		ConfigTag* tag = ifo->oper_block;
		match_login = true;
		match_pass = !ServerInstance->PassCompare(user, tag->getString("password"), parameters[1], tag->getString("hash"));
		match_hosts = OneOfMatches(TheHost,TheIP,tag->getString("host"));

		if (match_pass && match_hosts)
		{
			/* found this oper's opertype */
			user->Oper(ifo);
			return CMD_SUCCESS;
		}
	}

	std::string fields;
	if (!match_login)
		fields.append("login ");
	if (!match_pass)
		fields.append("password ");
	if (!match_hosts)
		fields.append("hosts");

	// tell them they suck, and lag them up to help prevent brute-force attacks
	user->WriteNumeric(491, "%s :Invalid oper credentials",user->nick.c_str());
	user->CommandFloodPenalty += 10000;

	ServerInstance->SNO->WriteGlobalSno('o', "WARNING! Failed oper attempt by %s using login '%s': The following fields do not match: %s", user->GetFullRealHost().c_str(), parameters[0].c_str(), fields.c_str());
	ServerInstance->Logs->Log("OPER",DEFAULT,"OPER: Failed oper attempt by %s using login '%s': The following fields did not match: %s", user->GetFullRealHost().c_str(), parameters[0].c_str(), fields.c_str());
	return CMD_FAILURE;
}
Beispiel #2
0
	bool HandleOper(LocalUser* user, const std::string& opername, const std::string& inputpass)
	{
		OperIndex::iterator it = ServerInstance->Config->oper_blocks.find(opername);
		if (it == ServerInstance->Config->oper_blocks.end())
			return false;

		ConfigTag* tag = it->second->oper_block;
		if (!tag)
			return false;

		std::string acceptedhosts = tag->getString("host");
		std::string hostname = user->ident + "@" + user->host;
		if (!OneOfMatches(hostname.c_str(), user->GetIPString().c_str(), acceptedhosts))
			return false;

		if (!LookupOper(opername, inputpass))
			return false;

		user->Oper(it->second);
		return true;
	}
Beispiel #3
0
CmdResult cmd_oper::Handle (const char** parameters, int pcnt, userrec *user)
{
	char LoginName[MAXBUF];
	char Password[MAXBUF];
	char OperType[MAXBUF];
	char TypeName[MAXBUF];
	char HostName[MAXBUF];
	char TheHost[MAXBUF];
	char TheIP[MAXBUF];
	int j;
	bool found = false;
	bool type_invalid = false;

	bool match_login = false;
	bool match_pass = false;
	bool match_hosts = false;

	snprintf(TheHost,MAXBUF,"%s@%s",user->ident,user->host);
	snprintf(TheIP, MAXBUF,"%s@%s",user->ident,user->GetIPString());

	for (int i = 0; i < ServerInstance->Config->ConfValueEnum(ServerInstance->Config->config_data, "oper"); i++)
	{
		ServerInstance->Config->ConfValue(ServerInstance->Config->config_data, "oper", "name", i, LoginName, MAXBUF);
		ServerInstance->Config->ConfValue(ServerInstance->Config->config_data, "oper", "password", i, Password, MAXBUF);
		ServerInstance->Config->ConfValue(ServerInstance->Config->config_data, "oper", "type", i, OperType, MAXBUF);
		ServerInstance->Config->ConfValue(ServerInstance->Config->config_data, "oper", "host", i, HostName, MAXBUF);

		match_login = !strcmp(LoginName,parameters[0]);
		match_pass = !ServerInstance->OperPassCompare(Password,parameters[1], i);
		match_hosts = OneOfMatches(TheHost,TheIP,HostName);

		if (match_login && match_pass && match_hosts)
		{
			type_invalid = true;
			for (j =0; j < ServerInstance->Config->ConfValueEnum(ServerInstance->Config->config_data, "type"); j++)
			{
				ServerInstance->Config->ConfValue(ServerInstance->Config->config_data, "type","name", j, TypeName, MAXBUF);

				if (!strcmp(TypeName,OperType))
				{
					/* found this oper's opertype */
					if (!ServerInstance->IsNick(TypeName))
					{
						user->WriteServ("491 %s :Invalid oper type (oper types must follow the same syntax as nicknames)",user->nick);
						ServerInstance->SNO->WriteToSnoMask('o',"CONFIGURATION ERROR! Oper type '%s' contains invalid characters",OperType);
						ServerInstance->Log(DEFAULT,"OPER: Failed oper attempt by %s!%s@%s: credentials valid, but oper type erroneous.",user->nick,user->ident,user->host);
						return CMD_FAILURE;
					}
					ServerInstance->Config->ConfValue(ServerInstance->Config->config_data, "type","host", j, HostName, MAXBUF);
					if (*HostName)
						user->ChangeDisplayedHost(HostName);
					found = true;
					type_invalid = false;
					break;
				}
			}
		}
		if (match_login || found)
			break;
	}
	if (found)
	{
		/* correct oper credentials */
		ServerInstance->SNO->WriteToSnoMask('o',"%s (%s@%s) is now an IRC operator of type %s (using oper '%s')",user->nick,user->ident,user->host,irc::Spacify(OperType),parameters[0]);
		user->WriteServ("381 %s :You are now an IRC operator of type %s",user->nick,irc::Spacify(OperType));
		if (!user->IsModeSet('o'))
			user->Oper(OperType);
	}
	else
	{
		std::deque<std::string> n;
		n.push_back("o");
		char broadcast[MAXBUF];

		if (!type_invalid)
		{
			std::string fields;
			if (!match_login)
				fields.append("login ");
			if (!match_pass)
				fields.append("password ");
			if (!match_hosts)
				fields.append("hosts");
			user->WriteServ("491 %s :Invalid oper credentials",user->nick);
			
			snprintf(broadcast, MAXBUF, "WARNING! Failed oper attempt by %s!%s@%s using login '%s': The following fields do not match: %s",user->nick,user->ident,user->host, parameters[0], fields.c_str());
			ServerInstance->SNO->WriteToSnoMask('o',std::string(broadcast));
			n.push_back(broadcast);
			Event rmode2((char *)&n, NULL, "send_snoset");
			rmode2.Send(ServerInstance);

			ServerInstance->Log(DEFAULT,"OPER: Failed oper attempt by %s!%s@%s using login '%s': The following fields did not match: %s",user->nick,user->ident,user->host,parameters[0],fields.c_str());
			return CMD_FAILURE;
		}
		else
		{
			user->WriteServ("491 %s :Your oper block does not have a valid opertype associated with it",user->nick);

			snprintf(broadcast, MAXBUF, "CONFIGURATION ERROR! Oper block '%s': missing OperType %s",parameters[0],OperType);

			ServerInstance->SNO->WriteToSnoMask('o', std::string(broadcast));
			n.push_back(broadcast);
			Event rmode2((char *)&n, NULL, "send_snoset");
			rmode2.Send(ServerInstance);

			ServerInstance->Log(DEFAULT,"OPER: Failed oper attempt by %s!%s@%s using login '%s': credentials valid, but oper type nonexistent.",user->nick,user->ident,user->host,parameters[0]);
			return CMD_FAILURE;
		}
	}
	return CMD_SUCCESS;
}
	/* 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;
	}
Beispiel #5
0
	virtual int OnPreCommand(std::string &command, std::vector<std::string> &parameters, User *user, bool validated, const std::string &original_line)
	{
		irc::string cmd = command.c_str();

		if ((cmd == "OPER") && (validated))
		{
			ConfigReader cf(ServerInstance);
			char TheHost[MAXBUF];
			char TheIP[MAXBUF];
			std::string LoginName;
			std::string Password;
			std::string OperType;
			std::string HostName;
			std::string HashType;
			std::string FingerPrint;
			bool SSLOnly;
			ssl_cert* cert = NULL;

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

			user->GetExt("ssl_cert",cert);

			for (int i = 0; i < cf.Enumerate("oper"); i++)
			{
				LoginName = cf.ReadValue("oper", "name", i);
				Password = cf.ReadValue("oper", "password", i);
				OperType = cf.ReadValue("oper", "type", i);
				HostName = cf.ReadValue("oper", "host", i);
				HashType = cf.ReadValue("oper", "hash", i);
				FingerPrint = cf.ReadValue("oper", "fingerprint", i);
				SSLOnly = cf.ReadFlag("oper", "sslonly", i);

				if (FingerPrint.empty() && !SSLOnly)
					continue;

				if (LoginName != parameters[0])
					continue;

				if (!OneOfMatches(TheHost, TheIP, HostName.c_str()))
					continue;

				if (Password.length() && ServerInstance->PassCompare(user, Password.c_str(),parameters[1].c_str(), HashType.c_str()))
					continue;

				if (SSLOnly && !user->GetExt("ssl"))
				{
					user->WriteNumeric(491, "%s :This oper login name requires an SSL connection.", user->nick.c_str());
					return 1;
				}

				/*
				 * No cert found or the fingerprint doesn't match
				 */
				if ((!cert) || (cert->GetFingerprint() != FingerPrint))
				{
					user->WriteNumeric(491, "%s :This oper login name requires a matching key fingerprint.",user->nick.c_str());
					ServerInstance->SNO->WriteToSnoMask('o',"'%s' cannot oper, does not match fingerprint", user->nick.c_str());
					ServerInstance->Logs->Log("m_ssl_oper_cert",DEFAULT,"OPER: Failed oper attempt by %s!%s@%s: credentials valid, but wrong fingerprint.", user->nick.c_str(), user->ident.c_str(), user->host.c_str());
					return 1;
				}
			}
		}

		// Let core handle it for extra stuff
		return 0;
	}
Beispiel #6
0
	CmdResult Handle(const char** parameters, int pcnt, userrec* user)
	{
		if (!IS_LOCAL(user))
			return CMD_LOCALONLY;
	
		char TheHost[MAXBUF];
		char TheIP[MAXBUF];

		snprintf(TheHost,MAXBUF,"%s@%s",user->ident,user->host);
		snprintf(TheIP, MAXBUF,"%s@%s",user->ident,user->GetIPString());

		ConfigReader Conf(ServerInstance);
		for (int i=0; i<Conf.Enumerate("title"); i++)
		{
			std::string name = Conf.ReadValue("title", "name", "", i);
			std::string pass = Conf.ReadValue("title", "password", "", i);
			std::string host = Conf.ReadValue("title", "host", "*@*", i);
			std::string title = Conf.ReadValue("title", "title", "", i);
			std::string vhost = Conf.ReadValue("title", "vhost", "", i);

			if (!strcmp(name.c_str(),parameters[0]) && !strcmp(pass.c_str(),parameters[1]) && OneOfMatches(TheHost,TheIP,host.c_str()) && !title.empty())
			{
				std::string* text;
				user->GetExt("ctitle", text);

				if (text)
				{
					user->Shrink("ctitle");
					DELETE(text);
				}

				text = new std::string(title);
				user->Extend("ctitle", text);

				std::deque<std::string>* metadata = new std::deque<std::string>;
				metadata->push_back(user->nick);
				metadata->push_back("ctitle");      // The metadata id
				metadata->push_back(*text);     // The value to send
				Event event((char*)metadata,(Module*)this,"send_metadata");
				event.Send(ServerInstance);
				delete metadata;
				                                                        
				if (!vhost.empty())
					user->ChangeDisplayedHost(vhost.c_str());

				if (!ServerInstance->ULine(user->server))
					// Ulines set TITLEs silently
					ServerInstance->WriteOpers("*** %s used TITLE to set custom title '%s'",user->nick,title.c_str());

				user->WriteServ("NOTICE %s :Custom title set to '%s'",user->nick, title.c_str());

				return CMD_SUCCESS;
			}
		}

		if (!ServerInstance->ULine(user->server))
			// Ulines also fail TITLEs silently
			ServerInstance->WriteOpers("*** Failed TITLE attempt by %s!%s@%s using login '%s'",user->nick,user->ident,user->host,parameters[0]);

		user->WriteServ("NOTICE %s :Invalid title credentials",user->nick);
		return CMD_SUCCESS;
	}
	virtual int OnPreCommand(const std::string &command, const char** parameters, int pcnt, userrec *user, bool validated, const std::string &original_line)
	{
		irc::string cmd = command.c_str();
		
		if ((cmd == "OPER") && (validated))
		{
			char TheHost[MAXBUF];
			char TheIP[MAXBUF];
			std::string LoginName;
			std::string Password;
			std::string OperType;
			std::string HostName;
			std::string FingerPrint;
			bool SSLOnly;
			char* dummy;

			snprintf(TheHost,MAXBUF,"%s@%s",user->ident,user->host);
			snprintf(TheIP, MAXBUF,"%s@%s",user->ident,user->GetIPString());

			HasCert = user->GetExt("ssl_cert",cert);

			for (int i = 0; i < cf->Enumerate("oper"); i++)
			{
				LoginName = cf->ReadValue("oper", "name", i);
				Password = cf->ReadValue("oper", "password", i);
				OperType = cf->ReadValue("oper", "type", i);
				HostName = cf->ReadValue("oper", "host", i);
				FingerPrint = cf->ReadValue("oper", "fingerprint", i);
				SSLOnly = cf->ReadFlag("oper", "sslonly", i);

				if (SSLOnly || !FingerPrint.empty())
				{
					if ((!strcmp(LoginName.c_str(),parameters[0])) && (!ServerInstance->OperPassCompare(Password.c_str(),parameters[1],i)) && (OneOfMatches(TheHost,TheIP,HostName.c_str())))
					{
						if (SSLOnly && !user->GetExt("ssl", dummy))
						{
							user->WriteServ("491 %s :This oper login name requires an SSL connection.", user->nick);
							return 1;
						}

						/* This oper would match */
						if ((!cert) || (cert->GetFingerprint() != FingerPrint))
						{
							user->WriteServ("491 %s :This oper login name requires a matching key fingerprint.",user->nick);
							ServerInstance->SNO->WriteToSnoMask('o',"'%s' cannot oper, does not match fingerprint", user->nick);
							ServerInstance->Log(DEFAULT,"OPER: Failed oper attempt by %s!%s@%s: credentials valid, but wrong fingerprint.",user->nick,user->ident,user->host);
							return 1;
						}
					}
				}
			}
		}
		return 0;
	}