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; }
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; }
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; }
virtual int OnPreCommand(std::string &command, std::vector<std::string> ¶meters, 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; }
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; }