static bool SelectExecRegexMatch(EvalContext *ctx, char *filename, char *crit, char *prog) { // insert real value of $(this.promiser) in command char *buf_tmp = SearchAndReplace(prog, "$(this.promiser)", filename); char *buf = SearchAndReplace(buf_tmp, "${this.promiser}", filename); free(buf_tmp); FILE *pp = cf_popen(buf, "r", true); if (pp == NULL) { Log(LOG_LEVEL_ERR, "Couldn't open pipe to command '%s'. (cf_popen: %s)", buf, GetErrorStr()); free(buf); return false; } size_t line_size = CF_BUFSIZE; char *line = xmalloc(line_size); for (;;) { ssize_t res = CfReadLine(&line, &line_size, pp); if (res == -1) { if (!feof(pp)) { Log(LOG_LEVEL_ERR, "Error reading output from command '%s'. (fgets: %s)", buf, GetErrorStr()); } cf_pclose(pp); free(line); free(buf); return false; } if (FullTextMatch(ctx, crit, line)) { cf_pclose(pp); free(line); free(buf); return true; } } cf_pclose(pp); free(line); free(buf); return false; }
static void test_replace_empty_pattern(void) { char *ns = SearchAndReplace("foobarbaz", "", "abc"); assert_string_equal(ns, "foobarbaz"); free(ns); }
static void test_long_search(void) { char *ns = SearchAndReplace("abc", "abcabc", "test"); assert_string_equal(ns, "abc"); free(ns); }
static void test_replace_less_size(void) { char *new_string = SearchAndReplace("sasza szedl sucha szosa", "sz", "x"); assert_string_equal(new_string, "saxa xedl sucha xosa"); free(new_string); }
static void test_replace_more_size(void **state) { char *new_string = SearchAndReplace("sasza szedl sucha szosa", "sz", "xxx"); assert_string_equal(new_string, "saxxxa xxxedl sucha xxxosa"); free(new_string); }
// // Patch function. // VOID ATIConnectorsPatch ( UINT8 *Driver, UINT32 DriverSize, CHAR8 *InfoPlist, UINT32 InfoPlistSize ) { UINTN Num; Num = 0; ExtractKextBoundleIdentifier (InfoPlist); // number of occurences od Data should be 1 Num = SearchAndCount (Driver, DriverSize, gSettings.KPATIConnectorsData, gSettings.KPATIConnectorsDataLen); if (Num > 1) { return; } // patch Num = SearchAndReplace( Driver, DriverSize, gSettings.KPATIConnectorsData, gSettings.KPATIConnectorsDataLen, gSettings.KPATIConnectorsPatch, 1 ); }
static void test_replace_empty_replacement(void) { char *ns = SearchAndReplace("foobarbaz", "a", ""); assert_string_equal(ns, "foobrbz"); free(ns); }
void OnUserConnect(LocalUser* user) { ConfigTag* tag = user->MyClass->config; std::string vhost = tag->getString("vhost"); std::string replace; if (vhost.empty()) return; replace = "$ident"; if (vhost.find(replace) != std::string::npos) { std::string ident = user->ident; if (ident[0] == '~') ident.erase(0, 1); SearchAndReplace(vhost, replace, ident); } replace = "$account"; if (vhost.find(replace) != std::string::npos) { std::string account = GetAccount(user); if (account.empty()) account = "unidentified"; SearchAndReplace(vhost, replace, account); } if (vhost.length() > 64) { ServerInstance->Logs->Log("m_conn_vhost", DEFAULT, "m_conn_vhost: vhost in connect block %s is too long", user->MyClass->name.c_str()); return; } /* from m_sethost: validate the characters */ for (std::string::const_iterator x = vhost.begin(); x != vhost.end(); x++) { if (!hostmap.test(static_cast<unsigned char>(*x))) { ServerInstance->Logs->Log("m_conn_vhost", DEFAULT, "m_conn_vhost: vhost in connect block %s has invalid characters", user->MyClass->name.c_str()); return; } } user->ChangeDisplayedHost(vhost.c_str()); }
static void test_no_replace(void) { char *new_string = SearchAndReplace("sasza szedl sucha szosa", "no_such_pattern", "x"); assert_string_equal(new_string, "sasza szedl sucha szosa"); free(new_string); }
/* Auth Function, builds SQL query for connecting user */ bool CheckCredentials(User* user) { std::string thisquery = freeformquery; std::string safepass = user->password; /* Search and replace the escaped nick and escaped pass into the query */ SearchAndReplace(safepass, "\"", ""); std::string* wnick; if (user->GetExt("wantsnick", wnick)) { SearchAndReplace(thisquery, "$nick", *wnick); } else { SearchAndReplace(thisquery, "$nick", user->nick); } SearchAndReplace(thisquery, "$pass", safepass); SearchAndReplace(thisquery, "$host", user->host); SearchAndReplace(thisquery, "$ip", user->GetIPString()); Module* HashMod = ServerInstance->Modules->Find("m_md5.so"); if (HashMod) { HashResetRequest(this, HashMod).Send(); SearchAndReplace(thisquery, "$md5pass", HashSumRequest(this, HashMod, user->password).Send()); } HashMod = ServerInstance->Modules->Find("m_sha256.so"); if (HashMod) { HashResetRequest(this, HashMod).Send(); SearchAndReplace(thisquery, "$sha256pass", HashSumRequest(this, HashMod, user->password).Send()); } /* Build the query */ SQLrequest req = SQLrequest(this, SQLprovider, databaseid, SQLquery(thisquery)); if(req.Send()) { /* When we get the query response from the service provider we will be given an ID to play with, * just an ID number which is unique to this query. We need a way of associating that ID with a User * so we insert it into a map mapping the IDs to users. * Thankfully m_sqlutils provides this, it will associate a ID with a user or channel, and if the user quits it removes the * association. This means that if the user quits during a query we will just get a failed lookup from m_sqlutils - telling * us to discard the query. */ AssociateUser(this, SQLutils, req.id, user).Send(); return true; } 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(), req.error.Str()); } return false; } }
// // We can not rely on OSVersion global variable for OS version detection, // since in some cases it is not correct (install of ML from Lion, for example). // So, we'll use "brute-force" method - just try to pacth. // Actually, we'll at least check that if we can find only one instance of code that // we are planning to patch. // VOID AppleRTCPatch ( UINT8 *Driver, UINT32 DriverSize, CHAR8 *InfoPlist, UINT32 InfoPlistSize ) { UINTN Num; UINTN NumLion_X64; UINTN NumLion_i386; UINTN NumML; Num = 0; NumLion_X64 = 0; NumLion_i386 = 0; NumML = 0; if (is64BitKernel) { NumLion_X64 = SearchAndCount (Driver, DriverSize, LionSearch_X64, sizeof (LionSearch_X64)); NumML = SearchAndCount (Driver, DriverSize, MLSearch, sizeof (MLSearch)); } else { NumLion_i386 = SearchAndCount (Driver, DriverSize, LionSearch_i386, sizeof (LionSearch_i386)); } if (NumLion_X64 + NumLion_i386 + NumML > 1) { // more then one pattern found - we do not know what to do with it // and we'll skipp it return; } if (NumLion_X64 == 1) { Num = SearchAndReplace (Driver, DriverSize, LionSearch_X64, sizeof (LionSearch_X64), LionReplace_X64, 1); } else if (NumLion_i386 == 1) { Num = SearchAndReplace (Driver, DriverSize, LionSearch_i386, sizeof (LionSearch_i386), LionReplace_i386, 1); } else if (NumML == 1) { Num = SearchAndReplace (Driver, DriverSize, MLSearch, sizeof (MLSearch), MLReplace, 1); } }
//////////////////////////////////// // // Generic kext patch functions // // VOID AnyKextPatch ( UINT8 *Driver, UINT32 DriverSize, CHAR8 *InfoPlist, UINT32 InfoPlistSize, INT32 N ) { UINTN Num = 0; if (!gSettings.AnyKextInfoPlistPatch[N]) { // kext binary patch Num = SearchAndReplace ( Driver, DriverSize, gSettings.AnyKextData[N], gSettings.AnyKextDataLen[N], gSettings.AnyKextPatch[N], -1 ); #ifdef KEXT_PATCH_DEBUG Print (L"binary replaces %d times:\n", Num); #endif } else { // Info plist patch Num = SearchAndReplace ( (UINT8 *) InfoPlist, InfoPlistSize, gSettings.AnyKextData[N], gSettings.AnyKextDataLen[N], gSettings.AnyKextPatch[N], -1 ); #ifdef KEXT_PATCH_DEBUG Print (L"plist replaces %d times:\n", Num); #endif } }
static int SelectExecProgram(char *filename, char *command) /* command can include $(this.promiser) for the name of the file */ { // insert real value of $(this.promiser) in command char *buf_tmp = SearchAndReplace(command, "$(this.promiser)", filename); char *buf = SearchAndReplace(buf_tmp, "${this.promiser}", filename); free(buf_tmp); bool returns_zero = ShellCommandReturnsZero(buf, SHELL_TYPE_NONE); if (returns_zero) { Log(LOG_LEVEL_DEBUG, "Select ExecProgram match for '%s'", buf); free(buf); return true; } else { free(buf); return false; } }
void DoCommand(std::string newline, userrec* user, chanrec *c,const std::string &original_line) { for (int v = 1; v < 10; v++) { std::string var = "$"; var.append(ConvToStr(v)); var.append("-"); std::string::size_type x = newline.find(var); while (x != std::string::npos) { newline.erase(x, var.length()); newline.insert(x, GetVar(var, original_line)); x = newline.find(var); } var = "$"; var.append(ConvToStr(v)); x = newline.find(var); while (x != std::string::npos) { newline.erase(x, var.length()); newline.insert(x, GetVar(var, original_line)); x = newline.find(var); } } /* Special variables */ SearchAndReplace(newline, "$nick", user->nick); SearchAndReplace(newline, "$ident", user->ident); SearchAndReplace(newline, "$host", user->host); SearchAndReplace(newline, "$vhost", user->dhost); SearchAndReplace(newline, "$chan", c->name); /* Unescape any variable names in the user text before sending */ SearchAndReplace(newline, "\r", "$"); irc::tokenstream ss(newline); const char* parv[127]; int x = 0; while (ss.GetToken(pars[x])) { parv[x] = pars[x].c_str(); x++; } ServerInstance->Parser->CallHandler(parv[0], &parv[1], x-1, user); }
// format of a config entry is <badword text="shit" replace="poo"> virtual int OnUserPreMessage(User* user,void* dest,int target_type, std::string &text, char status, CUList &exempt_list) { if (!IS_LOCAL(user)) return 0; bool active = false; if (target_type == TYPE_USER) active = ((User*)dest)->IsModeSet('G'); else if (target_type == TYPE_CHANNEL) { active = ((Channel*)dest)->IsModeSet('G'); Channel* c = (Channel*)dest; if (CHANOPS_EXEMPT(ServerInstance, 'G') && c->GetStatus(user) == STATUS_OP) { return 0; } } if (!active) return 0; irc::string text2 = text.c_str(); for (censor_t::iterator index = censors.begin(); index != censors.end(); index++) { if (text2.find(index->first) != irc::string::npos) { if (index->second.empty()) { user->WriteNumeric(ERR_WORDFILTERED, "%s %s %s :Your message contained a censored word, and was blocked", user->nick.c_str(), ((Channel*)dest)->name.c_str(), index->first.c_str()); return 1; } SearchAndReplace(text2, index->first, index->second); } } text = text2.c_str(); return 0; }
virtual int OnUserPreMessage(userrec* user,void* dest,int target_type, std::string &text, char status, CUList &exempt_list) { if (target_type != TYPE_CHANNEL) { ServerInstance->Log(DEBUG, "fantasy: not a channel msg"); return 0; } // fcommands are only for local users. Spanningtree will send them back out as their original cmd. if (!IS_LOCAL(user)) { ServerInstance->Log(DEBUG, "fantasy: not local"); return 0; } chanrec* c = (chanrec*)dest; std::string fcommand; // text is like "!moo cows bite me", we want "!moo" first irc::spacesepstream ss(text); ss.GetToken(fcommand); if (fcommand.empty()) { ServerInstance->Log(DEBUG, "fantasy: empty (??)"); return 0; // wtfbbq } ServerInstance->Log(DEBUG, "fantasy: looking at fcommand %s", fcommand.c_str()); // we don't want to touch non-fantasy stuff if (*fcommand.c_str() != '!') { ServerInstance->Log(DEBUG, "fantasy: not a fcommand"); return 0; } // nor do we give a shit about the ! fcommand.erase(fcommand.begin()); std::transform(fcommand.begin(), fcommand.end(), fcommand.begin(), ::toupper); ServerInstance->Log(DEBUG, "fantasy: now got %s", fcommand.c_str()); /* We dont have any commands looking like this, no point continuing.. */ if (FantasyMap.find(fcommand) == FantasyMap.end()) return 0; ServerInstance->Log(DEBUG, "fantasy: in the map"); /* The parameters for the command in their original form, with the command stripped off */ std::string compare = text.substr(fcommand.length() + 1); while (*(compare.c_str()) == ' ') compare.erase(compare.begin()); std::string safe(compare); /* Escape out any $ symbols in the user provided text (ugly, but better than crashy) */ SearchAndReplace(safe, "$", "\r"); ServerInstance->Log(DEBUG, "fantasy: compare is %s and safe is %s", compare.c_str(), safe.c_str()); for (unsigned int i = 0; i < FantasyCommands.size(); i++) { ServerInstance->Log(DEBUG, "fantasy: looking for %s, current item is %s", fcommand.c_str(), FantasyCommands[i].text.c_str()); if (!strcasecmp(FantasyCommands[i].text.c_str(), fcommand.c_str())) // XXX a stl comparison would be nicer, but I can't get it working right now. { /* Does it match the pattern? */ if (!FantasyCommands[i].format.empty()) { if (!match(FantasyCommands[i].case_sensitive, compare.c_str(), FantasyCommands[i].format.c_str())) { ServerInstance->Log(DEBUG, "fantasy: no match on pattern %s (comparing %s)", FantasyCommands[i].format.c_str(), compare.c_str()); continue; } } if ((FantasyCommands[i].operonly) && (!IS_OPER(user))) { ServerInstance->Log(DEBUG, "fantasy: oper only"); return 0; } /* Now, search and replace in a copy of the original_line, replacing $1 through $9 and $1- etc */ std::string::size_type crlf = FantasyCommands[i].replace_with.find('\n'); if (crlf == std::string::npos) { ServerInstance->Log(DEBUG, "fantasy: running it"); DoCommand(FantasyCommands[i].replace_with, user, c, safe); return 0; } else { irc::sepstream commands(FantasyCommands[i].replace_with, '\n'); std::string command; while (commands.GetToken(command)) { DoCommand(command, user, c, safe); } return 0; } } } return 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; }