/** * FORCECommand.cc * Glines a specific mask * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. * * $Id: FORCEGLINECommand.cc,v 1.39 2009/06/09 05:55:55 hidden1 Exp $ */ #include #include #include #include "ccontrol.h" #include "CControlCommands.h" #include "StringTokenizer.h" #include "Network.h" #include "misc.h" #include "Gline.h" #include "ip.h" #include "ELog.h" #include "Constants.h" #include "gnuworld_config.h" RCSTAG( "$Id: FORCEGLINECommand.cc,v 1.39 2009/06/09 05:55:55 hidden1 Exp $" ) ; namespace gnuworld { using std::string ; // Input: forcegline *@blah.net reason // Input: forcegline 3600 *@blah.net reason // // Output: C GL * +*@lamer.net 3600 :Banned (*@lamer) ... // namespace uworld { bool FORCEGLINECommand::Exec( iClient* theClient, const string& Message ) { StringTokenizer st( Message ) ; if( st.size() < 3 ) { Usage( theClient ) ; return true ; } StringTokenizer::size_type pos = 1 ; bool Forced = false; ccUser* tmpUser = bot->IsAuth(theClient); bot->MsgChanLog("FORCEGLINE %s\n",st.assemble(1).c_str()); if(!strcasecmp(st[pos],"-fu")) { Forced = true; pos++; if( st.size() < 4 ) { Usage( theClient ) ; return true ; } } time_t gLength = bot->getDefaultGlineLength() ; // (pos) is the index of the next token, the user@host mask. if(string::npos != st[pos].find_first_of('#')) { bot->Notice(theClient,"I don't think glining that host is such a good idea, lose the #"); return true; } if(st[pos].substr(0,1) == "$") { bot->Notice(theClient,"Please use SGLINE to set that gline"); return true; } string::size_type atPos = st[ pos ].find_first_of( '@' ) ; if( string::npos == atPos ) { // User has only specified hostname, not a user name bot->Notice( theClient, "GLINE: Please specify gline mask in the " "format: user@host" ) ; return true ; } string userName = st[ pos ].substr( 0, pos ) ; string hostName = st[ pos ].substr( pos + 1 ) ; string Length; Length.assign(st[pos+1]); unsigned int ResStart = 2; bool Ok = true; if (IsTimeSpec(st[2])) { gLength = extractTime( st[2], 1 ); } else { gLength = bot->getDefaultGlineLength() ; ResStart = 1; } //ccUser *tmpAuth = bot->IsAuth(theClient); if(!tmpUser) { // We shouldnt have got here in the first place, but check it anyway return false; } if((Forced) && (tmpUser->getType() < operLevel::SMTLEVEL)) { bot->Notice(theClient,"Only SMT+ can use the -fu option"); return false; } unsigned int Users; int gCheck = bot->checkGline(st[pos],gLength,Users); if(gCheck & gline::NEG_TIME) { bot->Notice(theClient,"You can't gline for a negative amount of time!"); Ok = false; } if(gCheck & gline::HUH_NO_HOST) { bot->Notice(theClient,"I don't think glining that host is such a good idea, do you?"); Ok = false; } if(gCheck & gline::BAD_HOST) { bot->Notice(theClient,"illegal host"); Ok = false; } if(gCheck & gline::BAD_CIDRMASK) { bot->Notice(theClient,"The IP listed is not on a bit boundary for the CIDR mask specified."); Ok = false; } if(gCheck & gline::BAD_CIDRLEN) { bot->Notice(theClient,"Bad CIDR length - try something more specific."); Ok = false; } if(gCheck & gline::BAD_CIDROVERRIDE) { bot->Notice(theClient,"For CIDR glines, you must enter all 4 parts of the IP."); Ok = false; } if(gCheck & gline::BAD_TIME) { bot->Notice(theClient,"Glining for more than %d seconds is not allowed",gline::MFGLINE_TIME); Ok = false; } if((gCheck & gline::FU_NEEDED_USERS) && (Ok)) { if(!Forced) { Ok = false; if(tmpUser->getFlags() < operLevel::SMTLEVEL) { bot->Notice(theClient,"Sorry, you can't set a gline which affects more than %d users", gline::MFGLINE_USERS); } else { bot->Notice(theClient,"This gline affects more than %d users, please use the -fu flag", gline::MFGLINE_USERS); } } } if((gCheck & gline::FU_NEEDED_TIME) && (Ok)) { if(!Forced) { Ok = false; if(tmpUser->getFlags() < operLevel::SMTLEVEL) { bot->Notice(theClient,"Sorry, you can't set a gline for more than %d seconds", gline::MFGLINE_TIME); } else { bot->Notice(theClient,"This gline is for more than %d seconds, please use the -fu flag", gline::MFGLINE_TIME); } } } if((gCheck & gline::HUH_IS_IP_OF_OPER) && (Ok)) { if (bot->isGlinedException(userName + "@" + hostName) > 0) { bot->Notice(theClient,"There is someone who previously opered from that host. G-line sent (forced)"); } else { bot->Notice(theClient,"There is someone who previously opered from that host (%s). Send the gline again to force.", bot->getLastNUHOfOperFromIP(hostName).c_str()); bot->addGlinedException(userName + "@" + hostName); Ok = false; } } if((gCheck & gline::HUH_IS_EXCEPTION) && (Ok)) { if (bot->isGlinedException(userName + "@" + hostName) > 0) { bot->Notice(theClient,"There is an exception for that host. G-line sent (forced)"); } else { bot->Notice(theClient,"There is an exception for that host. Send the gline again to force."); bot->addGlinedException(userName + "@" + hostName); Ok = false; } } /*if((gCheck & gline::FORCE_NEEDED_HOST) && (Ok)) { bot->MsgChanLog("%s is using forcegline to gline a wildcard host (%s@%s)" ,theClient->getNickName().c_str() ,userName.c_str(),hostName.c_str()); } if((gCheck & gline::FORCE_NEEDED_TIME) && (Ok)) { bot->MsgChanLog("%s is using forcegline to gline for %d seconds" ,theClient->getNickName().c_str(),gLength); } if(gCheck & gline::FORCE_NEEDED_WILDTIME) { bot->MsgChanLog("%s is using forcegline to gline a wildcard host for more than %d seconds" ,theClient->getNickName().c_str() ,gline::MGLINE_WILD_TIME); }*/ if(!Ok) { bot->Notice(theClient,"Please fix all of the above, and try again"); return false; } if(gCheck & gline::GLINE_OK) { bot->Notice(theClient,"Please use the GLINE command to set that gline"); return false; } // Avoid passing a reference to a temporary variable. string nickUserHost = theClient->getRealNickUserHost() ; char Us[100]; Us[0] = '\0'; sprintf(Us,"%d",Users); string Reason = st.assemble( pos + ResStart ); StringTokenizer ReasonTokenizer(Reason,'|'); Reason = string("[") + Us + "] " + ReasonTokenizer[0]; if(Reason.size() > gline::MAX_REASON_LENGTH) { bot->Notice(theClient,"Gline reason can't be more than %d characters", gline::MAX_REASON_LENGTH); return false; } /*server->setGline( nickUserHost, st[ pos ], string("[") + Us + "] " + Reason, //st.assemble( pos + ResStart ) + "[" + Us + "]", gLength , bot) ;*/ ccGline *TmpGline = bot->findGline(st[pos]); bool Up = false; if(TmpGline) Up = true; else TmpGline = new ccGline(bot->SQLDb); TmpGline->setHost(st [ pos ]); TmpGline->setExpires(unsigned(::time(0) + gLength)); TmpGline->setAddedBy(nickUserHost); TmpGline->setReason(Reason); TmpGline->setAddedOn(::time(0)); TmpGline->setLastUpdated(::time(0)); bot->addGlineToUplink(TmpGline); if(Up) { TmpGline->Update(); } else { TmpGline->Insert(); //We need to update the Id TmpGline->loadData(TmpGline->getHost()); bot->addGline(TmpGline); } return true ; } } }