X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;ds=sidebyside;f=src%2Fcommands.cpp;h=b149da7e8fb8984538a710fac7871587aa4b33c4;hb=71552d40b60e57b8658d7660df5b9145af4d03af;hp=aa23b4b9583a6ea22b1e5ed21ffa54f0a41b6ffd;hpb=f9af620855b2bfe0d7d61a3f162e6790c7d1e882;p=user%2Fhenk%2Fcode%2Finspircd.git diff --git a/src/commands.cpp b/src/commands.cpp index aa23b4b95..b149da7e8 100644 --- a/src/commands.cpp +++ b/src/commands.cpp @@ -1,3 +1,19 @@ +/* +------------------------------------+ + * | Inspire Internet Relay Chat Daemon | + * +------------------------------------+ + * + * Inspire is copyright (C) 2002-2004 ChatSpike-Dev. + * E-mail: + * + * + * + * Written by Craig Edwards, Craig McLure, and others. + * This program is free but copyrighted software; see + * the file COPYING for details. + * + * --------------------------------------------------- + */ + #include "inspircd.h" #include "inspircd_io.h" #include "inspircd_util.h" @@ -33,6 +49,7 @@ #include "wildcard.h" #include "message.h" #include "mode.h" +#include "xline.h" #ifdef GCC3 #define nspace __gnu_cxx @@ -43,8 +60,8 @@ using namespace std; extern int MODCOUNT; -extern vector modules; -extern vector factory; +extern std::vector modules; +extern std::vector factory; extern int LogLevel; extern char ServerName[MAXBUF]; @@ -67,12 +84,15 @@ extern int WHOWAS_MAX; extern int DieDelay; extern time_t startup_time; extern int NetBufferSize; +extern int MaxWhoResults; extern time_t nb_start; +extern bool nofork; + extern std::vector fd_reap; extern std::vector module_names; -extern char bannerBuffer[MAXBUF]; +extern char MyExecutable[1024]; extern int boundPortCount; extern int portCount; extern int UDPportCount; @@ -86,6 +106,14 @@ extern serverrec* me[32]; extern FILE *log_file; +extern ClassVector Classes; + +const long duration_m = 60; +const long duration_h = duration_m * 60; +const long duration_d = duration_h * 24; +const long duration_w = duration_d * 7; +const long duration_y = duration_w * 52; + namespace nspace { template<> struct nspace::hash @@ -104,7 +132,7 @@ namespace nspace { char a[MAXBUF]; static struct hash strhash; - strcpy(a,s.c_str()); + strlcpy(a,s.c_str(),MAXBUF); strlower(a); return strhash(a); } @@ -118,8 +146,8 @@ struct StrHashComp bool operator()(const string& s1, const string& s2) const { char a[MAXBUF],b[MAXBUF]; - strcpy(a,s1.c_str()); - strcpy(b,s2.c_str()); + strlcpy(a,s1.c_str(),MAXBUF); + strlcpy(b,s2.c_str(),MAXBUF); return (strcasecmp(a,b) == 0); } @@ -200,17 +228,17 @@ void handle_kick(char **parameters, int pcnt, userrec *user) return; } - if (!has_channel(u,Ptr)) + if (!has_channel(user,Ptr)) { WriteServ(user->fd,"442 %s %s :You're not on that channel!",user->nick, parameters[0]); return; } - + char reason[MAXBUF]; if (pcnt > 2) { - strncpy(reason,parameters[2],MAXBUF); + strlcpy(reason,parameters[2],MAXBUF); if (strlen(reason)>MAXKICK) { reason[MAXKICK-1] = '\0'; @@ -220,7 +248,7 @@ void handle_kick(char **parameters, int pcnt, userrec *user) } else { - strcpy(reason,user->nick); + strlcpy(reason,user->nick,MAXBUF); kick_channel(user,u,Ptr,reason); } @@ -249,13 +277,44 @@ void handle_die(char **parameters, int pcnt, userrec *user) void handle_restart(char **parameters, int pcnt, userrec *user) { - log(DEBUG,"restart: %s",user->nick); + char restart[1024]; + char *argv[32]; + log(DEFAULT,"Restart: %s",user->nick); if (!strcmp(parameters[0],restartpass)) { - WriteOpers("*** RESTART command from %s!%s@%s, Pretending to restart till this is finished :D",user->nick,user->ident,user->host); - sleep(DieDelay); - Exit(ERROR); - /* Will finish this later when i can be arsed :) */ + WriteOpers("*** RESTART command from %s!%s@%s, restarting server.",user->nick,user->ident,user->host); + + argv[0] = MyExecutable; + argv[1] = "-wait"; + if (nofork) + { + argv[2] = "-nofork"; + } + else + { + argv[2] = NULL; + } + argv[3] = NULL; + + // close ALL file descriptors + send_error("Server restarting."); + sleep(1); + for (int i = 0; i < 65536; i++) + { + int on = 0; + struct linger linger = { 0 }; + setsockopt(i, SOL_SOCKET, SO_REUSEADDR, (const char*)&on, sizeof(on)); + linger.l_onoff = 1; + linger.l_linger = 0; + setsockopt(i, SOL_SOCKET, SO_LINGER, (const char*)&linger,sizeof(linger)); + Blocking(i); + close(i); + } + sleep(5); + + execv(MyExecutable,argv); + + exit(0); } else { @@ -275,7 +334,7 @@ void handle_kill(char **parameters, int pcnt, userrec *user) { // remote kill WriteOpers("*** Remote kill by %s: %s!%s@%s (%s)",user->nick,u->nick,u->ident,u->host,parameters[1]); - sprintf(killreason,"[%s] Killed (%s (%s))",ServerName,user->nick,parameters[1]); + snprintf(killreason,MAXBUF,"[%s] Killed (%s (%s))",ServerName,user->nick,parameters[1]); WriteCommonExcept(u,"QUIT :%s",killreason); // K token must go to ALL servers!!! char buffer[MAXBUF]; @@ -298,7 +357,7 @@ void handle_kill(char **parameters, int pcnt, userrec *user) // local kill WriteTo(user, u, "KILL %s :%s!%s!%s (%s)", u->nick, ServerName,user->dhost,user->nick,parameters[1]); WriteOpers("*** Local Kill by %s: %s!%s@%s (%s)",user->nick,u->nick,u->ident,u->host,parameters[1]); - sprintf(killreason,"Killed (%s (%s))",user->nick,parameters[1]); + snprintf(killreason,MAXBUF,"Killed (%s (%s))",user->nick,parameters[1]); kill_link(u,killreason); } } @@ -372,6 +431,13 @@ void handle_invite(char **parameters, int pcnt, userrec *user) WriteServ(user->fd,"442 %s %s :You're not on that channel!",user->nick, c->name); return; } + + int MOD_RESULT = 0; + FOREACH_RESULT(OnUserPreInvite(user,u,c)); + if (MOD_RESULT == 1) { + return; + } + u->InviteTo(c->name); WriteFrom(u->fd,user,"INVITE %s :%s",u->nick,c->name); WriteServ(user->fd,"341 %s %s %s",user->nick,u->nick,c->name); @@ -424,14 +490,14 @@ void handle_topic(char **parameters, int pcnt, userrec *user) } char topic[MAXBUF]; - strncpy(topic,parameters[1],MAXBUF); + strlcpy(topic,parameters[1],MAXBUF); if (strlen(topic)>MAXTOPIC) { topic[MAXTOPIC-1] = '\0'; } - strcpy(Ptr->topic,topic); - strcpy(Ptr->setby,user->nick); + strlcpy(Ptr->topic,topic,MAXBUF); + strlcpy(Ptr->setby,user->nick,NICKMAX); Ptr->topicset = time(NULL); WriteChannel(Ptr,user,"TOPIC %s :%s",Ptr->name, Ptr->topic); @@ -494,10 +560,12 @@ void handle_privmsg(char **parameters, int pcnt, userrec *user) int MOD_RESULT = 0; - FOREACH_RESULT(OnUserPreMessage(user,chan,TYPE_CHANNEL,std::string(parameters[1]))); + std::string temp = parameters[1]; + FOREACH_RESULT(OnUserPreMessage(user,chan,TYPE_CHANNEL,temp)); if (MOD_RESULT) { return; } + parameters[1] = (char*)temp.c_str(); ChanExceptSender(chan, user, "PRIVMSG %s :%s", chan->name, parameters[1]); @@ -525,10 +593,12 @@ void handle_privmsg(char **parameters, int pcnt, userrec *user) int MOD_RESULT = 0; - FOREACH_RESULT(OnUserPreMessage(user,dest,TYPE_USER,std::string(parameters[1]))); + std::string temp = parameters[1]; + FOREACH_RESULT(OnUserPreMessage(user,dest,TYPE_USER,temp)); if (MOD_RESULT) { return; } + parameters[1] = (char*)temp.c_str(); @@ -577,11 +647,13 @@ void handle_notice(char **parameters, int pcnt, userrec *user) } int MOD_RESULT = 0; - - FOREACH_RESULT(OnUserPreNotice(user,chan,TYPE_CHANNEL,std::string(parameters[1]))); + + std::string temp = parameters[1]; + FOREACH_RESULT(OnUserPreNotice(user,chan,TYPE_CHANNEL,temp)); if (MOD_RESULT) { return; } + parameters[1] = (char*)temp.c_str(); ChanExceptSender(chan, user, "NOTICE %s :%s", chan->name, parameters[1]); @@ -603,10 +675,12 @@ void handle_notice(char **parameters, int pcnt, userrec *user) { int MOD_RESULT = 0; - FOREACH_RESULT(OnUserPreNotice(user,dest,TYPE_USER,std::string(parameters[1]))); + std::string temp = parameters[1]; + FOREACH_RESULT(OnUserPreNotice(user,dest,TYPE_USER,temp)); if (MOD_RESULT) { return; } + parameters[1] = (char*)temp.c_str(); if (!strcmp(dest->server,user->server)) { @@ -627,6 +701,11 @@ void handle_notice(char **parameters, int pcnt, userrec *user) } } +void handle_server(char **parameters, int pcnt, userrec *user) +{ + WriteServ(user->fd,"666 %s :You cannot identify as a server, you are a USER. IRC Operators informed.",user->nick); + WriteOpers("*** WARNING: %s attempted to issue a SERVER command and is registered as a user!",user->nick); +} void handle_info(char **parameters, int pcnt, userrec *user) { @@ -677,7 +756,8 @@ void handle_whois(char **parameters, int pcnt, userrec *user) } if (strchr(dest->modes,'o')) { - WriteServ(user->fd,"313 %s %s :is an IRC operator",user->nick, dest->nick); + WriteServ(user->fd,"313 %s %s :is %s %s on %s",user->nick, dest->nick, + (strchr("aeiou",dest->oper[0]) ? "an" : "a"),dest->oper, Network); } FOREACH_MOD OnWhois(user,dest); if (!strcasecmp(user->server,dest->server)) @@ -763,6 +843,7 @@ void handle_quit(char **parameters, int pcnt, userrec *user) void handle_who(char **parameters, int pcnt, userrec *user) { chanrec* Ptr = NULL; + char tmp[10]; /* theres more to do here, but for now just close the socket */ if (pcnt == 1) @@ -771,12 +852,25 @@ void handle_who(char **parameters, int pcnt, userrec *user) { if (user->chans[0].channel) { - Ptr = user->chans[0].channel; + int n_list = 0; for (user_hash::const_iterator i = clientlist.begin(); i != clientlist.end(); i++) { - if ((common_channels(user,i->second)) && (isnick(i->second->nick))) + Ptr = i->second->chans[0].channel; + // suggested by phidjit and FCS + if ((!common_channels(user,i->second)) && (isnick(i->second->nick))) { - WriteServ(user->fd,"352 %s %s %s %s %s %s Hr@ :0 %s",user->nick, Ptr->name, i->second->ident, i->second->dhost, i->second->server, i->second->nick, i->second->fullname); + // Bug Fix #29 + strcpy(tmp, ""); + if (strcmp(i->second->awaymsg, "")) { + strncat(tmp, "G", 9); + } else { + strncat(tmp, "H", 9); + } + if (strchr(i->second->modes,'o')) { strncat(tmp, "*", 9); } + WriteServ(user->fd,"352 %s %s %s %s %s %s %s :0 %s",user->nick, Ptr ? Ptr->name : "*", i->second->ident, i->second->dhost, i->second->server, i->second->nick, tmp, i->second->fullname); + n_list++; + if (n_list > MaxWhoResults) + break; } } } @@ -799,7 +893,16 @@ void handle_who(char **parameters, int pcnt, userrec *user) { if ((has_channel(i->second,Ptr)) && (isnick(i->second->nick))) { - WriteServ(user->fd,"352 %s %s %s %s %s %s Hr@ :0 %s",user->nick, Ptr->name, i->second->ident, i->second->dhost, i->second->server, i->second->nick, i->second->fullname); + // Fix Bug #29 - Part 2.. + strcpy(tmp, ""); + if (strcmp(i->second->awaymsg, "")) { + strncat(tmp, "G", 9); + } else { + strncat(tmp, "H", 9); + } + if (strchr(i->second->modes,'o')) { strncat(tmp, "*", 9); } + strcat(tmp, cmode(i->second, Ptr)); + WriteServ(user->fd,"352 %s %s %s %s %s %s %s :0 %s",user->nick, Ptr->name, i->second->ident, i->second->dhost, i->second->server, i->second->nick, tmp, i->second->fullname); } } WriteServ(user->fd,"315 %s %s :End of /WHO list.",user->nick, Ptr->name); @@ -814,7 +917,15 @@ void handle_who(char **parameters, int pcnt, userrec *user) userrec* u = Find(parameters[0]); if (u) { - WriteServ(user->fd,"352 %s %s %s %s %s %s Hr@ :0 %s",user->nick, u->nick, u->ident, u->dhost, u->server, u->nick, u->fullname); + // Bug Fix #29 -- Part 29.. + strcpy(tmp, ""); + if (strcmp(u->awaymsg, "")) { + strncat(tmp, "G" ,9); + } else { + strncat(tmp, "H" ,9); + } + if (strchr(u->modes,'o')) { strncat(tmp, "*" ,9); } + WriteServ(user->fd,"352 %s %s %s %s %s %s %s :0 %s",user->nick, u->nick, u->ident, u->dhost, u->server, u->nick, tmp, u->fullname); } WriteServ(user->fd,"315 %s %s :End of /WHO list.",user->nick, parameters[0]); } @@ -829,7 +940,16 @@ void handle_who(char **parameters, int pcnt, userrec *user) { if (strchr(i->second->modes,'o')) { - WriteServ(user->fd,"352 %s %s %s %s %s %s Hr@ :0 %s",user->nick, user->nick, i->second->ident, i->second->dhost, i->second->server, i->second->nick, i->second->fullname); + // If i were a rich man.. I wouldn't need to me making these bugfixes.. + // But i'm a poor bastard with nothing better to do. + strcpy(tmp, ""); + if (strcmp(i->second->awaymsg, "")) { + strncat(tmp, "G" ,9); + } else { + strncat(tmp, "H" ,9); + } + + WriteServ(user->fd,"352 %s %s %s %s %s %s %s* :0 %s",user->nick, user->nick, i->second->ident, i->second->dhost, i->second->server, i->second->nick, tmp, i->second->fullname); } } } @@ -863,7 +983,7 @@ void handle_list(char **parameters, int pcnt, userrec *user) void handle_rehash(char **parameters, int pcnt, userrec *user) { WriteServ(user->fd,"382 %s %s :Rehashing",user->nick,CleanFilename(CONFIG_FILE)); - ReadConfig(); + ReadConfig(false,user); FOREACH_MOD OnRehash(); WriteOpers("%s is rehashing config file %s",user->nick,CleanFilename(CONFIG_FILE)); } @@ -918,8 +1038,8 @@ void handle_user(char **parameters, int pcnt, userrec *user) else { WriteServ(user->fd,"NOTICE Auth :No ident response, ident prefixed with ~"); strcpy(user->ident,"~"); /* we arent checking ident... but these days why bother anyway? */ - strncat(user->ident,parameters[0],IDENTMAX); - strncpy(user->fullname,parameters[3],128); + strlcat(user->ident,parameters[0],IDENTMAX); + strlcpy(user->fullname,parameters[3],128); user->registered = (user->registered | 1); } } @@ -939,7 +1059,7 @@ void handle_user(char **parameters, int pcnt, userrec *user) void handle_userhost(char **parameters, int pcnt, userrec *user) { char Return[MAXBUF],junk[MAXBUF]; - sprintf(Return,"302 %s :",user->nick); + snprintf(Return,MAXBUF,"302 %s :",user->nick); for (int i = 0; i < pcnt; i++) { userrec *u = Find(parameters[i]); @@ -947,13 +1067,13 @@ void handle_userhost(char **parameters, int pcnt, userrec *user) { if (strchr(u->modes,'o')) { - sprintf(junk,"%s*=+%s@%s ",u->nick,u->ident,u->host); - strcat(Return,junk); + snprintf(junk,MAXBUF,"%s*=+%s@%s ",u->nick,u->ident,u->host); + strlcat(Return,junk,MAXBUF); } else { - sprintf(junk,"%s=+%s@%s ",u->nick,u->ident,u->host); - strcat(Return,junk); + snprintf(junk,MAXBUF,"%s=+%s@%s ",u->nick,u->ident,u->host); + strlcat(Return,junk,MAXBUF); } } } @@ -964,14 +1084,14 @@ void handle_userhost(char **parameters, int pcnt, userrec *user) void handle_ison(char **parameters, int pcnt, userrec *user) { char Return[MAXBUF]; - sprintf(Return,"303 %s :",user->nick); + snprintf(Return,MAXBUF,"303 %s :",user->nick); for (int i = 0; i < pcnt; i++) { userrec *u = Find(parameters[i]); if (u) { - strcat(Return,u->nick); - strcat(Return," "); + strlcat(Return,u->nick,MAXBUF); + strlcat(Return," ",MAXBUF); } } WriteServ(user->fd,Return); @@ -982,12 +1102,12 @@ void handle_away(char **parameters, int pcnt, userrec *user) { if (pcnt) { - strcpy(user->awaymsg,parameters[0]); + strlcpy(user->awaymsg,parameters[0],512); WriteServ(user->fd,"306 %s :You have been marked as being away",user->nick); } else { - strcpy(user->awaymsg,""); + strlcpy(user->awaymsg,"",512); WriteServ(user->fd,"305 %s :You are no longer marked as being away",user->nick); } } @@ -1008,7 +1128,7 @@ void handle_whowas(char **parameters, int pcnt, userrec* user) char b[MAXBUF]; timeinfo = localtime(&rawtime); - strcpy(b,asctime(timeinfo)); + strlcpy(b,asctime(timeinfo),MAXBUF); b[strlen(b)-1] = '\0'; WriteServ(user->fd,"314 %s %s %s %s * :%s",user->nick,i->second->nick,i->second->ident,i->second->dhost,i->second->fullname); @@ -1049,13 +1169,14 @@ void handle_modules(char **parameters, int pcnt, userrec *user) { Version V = modules[i]->GetVersion(); char modulename[MAXBUF]; - strncpy(modulename,module_names[i].c_str(),256); + strlcpy(modulename,module_names[i].c_str(),256); WriteServ(user->fd,"900 %s :0x%08lx %d.%d.%d.%d %s",user->nick,modules[i],V.Major,V.Minor,V.Revision,V.Build,CleanFilename(modulename)); } } void handle_stats(char **parameters, int pcnt, userrec *user) { + char Link_ServerName[MAXBUF],Link_IPAddr[MAXBUF],Link_Port[MAXBUF]; if (pcnt != 1) { return; @@ -1066,8 +1187,85 @@ void handle_stats(char **parameters, int pcnt, userrec *user) parameters[0][1] = '\0'; } + + if (!strcasecmp(parameters[0],"c")) + { + for (int i = 0; i < ConfValueEnum("link",&config_f); i++) + { + ConfValue("link","name",i,Link_ServerName,&config_f); + ConfValue("link","ipaddr",i,Link_IPAddr,&config_f); + ConfValue("link","port",i,Link_Port,&config_f); + WriteServ(user->fd,"213 %s C *@%s * %s %s 0 M",user->nick,Link_IPAddr,Link_ServerName,Link_Port); + WriteServ(user->fd,"244 %s H * * %s",user->nick,Link_ServerName); + } + } + + if (!strcasecmp(parameters[0],"i")) + { + int idx = 0; + for (ClassVector::iterator i = Classes.begin(); i != Classes.end(); i++) + { + WriteServ(user->fd,"215 %s I * * * %d %d %s *",user->nick,MAXCLIENTS,idx,ServerName); + idx++; + } + } + + if (!strcasecmp(parameters[0],"y")) + { + int idx = 0; + for (ClassVector::iterator i = Classes.begin(); i != Classes.end(); i++) + { + WriteServ(user->fd,"218 %s Y %d %d 0 %d %d",user->nick,idx,120,i->flood,i->registration_timeout); + idx++; + } + } + + if (!strcmp(parameters[0],"U")) + { + for (int i = 0; i < ConfValueEnum("uline",&config_f); i++) + { + ConfValue("uline","server",i,Link_ServerName,&config_f); + WriteServ(user->fd,"248 %s U %s",user->nick,Link_ServerName); + } + } + + if (!strcmp(parameters[0],"P")) + { + int idx = 0; + for (user_hash::iterator i = clientlist.begin(); i != clientlist.end(); i++) + { + if (strchr(i->second->modes,'o')) + { + WriteServ(user->fd,"249 %s :%s (%s@%s) Idle: %d",user->nick,i->second->nick,i->second->ident,i->second->dhost,(time(NULL) - i->second->idle_lastmsg)); + idx++; + } + } + WriteServ(user->fd,"249 %s :%d OPER(s)",user->nick,idx); + //249 [Brain] :bwoadway-monitor (~wgmon@204.152.186.58) Idle: 18 + } + + if (!strcmp(parameters[0],"k")) + { + stats_k(user); + } + + if (!strcmp(parameters[0],"g")) + { + stats_g(user); + } + + if (!strcmp(parameters[0],"q")) + { + stats_q(user); + } + + if (!strcmp(parameters[0],"Z")) + { + stats_z(user); + } + /* stats m (list number of times each command has been used, plus bytecount) */ - if (!strcasecmp(parameters[0],"m")) + if (!strcmp(parameters[0],"m")) { for (int i = 0; i < cmdlist.size(); i++) { @@ -1084,7 +1282,7 @@ void handle_stats(char **parameters, int pcnt, userrec *user) } /* stats z (debug and memory info) */ - if (!strcasecmp(parameters[0],"z")) + if (!strcmp(parameters[0],"z")) { WriteServ(user->fd,"249 %s :Users(HASH_MAP) %d (%d bytes, %d buckets)",user->nick,clientlist.size(),clientlist.size()*sizeof(userrec),clientlist.bucket_count()); WriteServ(user->fd,"249 %s :Channels(HASH_MAP) %d (%d bytes, %d buckets)",user->nick,chanlist.size(),chanlist.size()*sizeof(chanrec),chanlist.bucket_count()); @@ -1097,7 +1295,7 @@ void handle_stats(char **parameters, int pcnt, userrec *user) } /* stats o */ - if (!strcasecmp(parameters[0],"o")) + if (!strcmp(parameters[0],"o")) { for (int i = 0; i < ConfValueEnum("oper",&config_f); i++) { @@ -1112,7 +1310,7 @@ void handle_stats(char **parameters, int pcnt, userrec *user) } /* stats l (show user I/O stats) */ - if (!strcasecmp(parameters[0],"l")) + if (!strcmp(parameters[0],"l")) { WriteServ(user->fd,"211 %s :server:port nick bytes_in cmds_in bytes_out cmds_out",user->nick); for (user_hash::iterator i = clientlist.begin(); i != clientlist.end(); i++) @@ -1130,7 +1328,7 @@ void handle_stats(char **parameters, int pcnt, userrec *user) } /* stats u (show server uptime) */ - if (!strcasecmp(parameters[0],"u")) + if (!strcmp(parameters[0],"u")) { time_t current_time = 0; current_time = time(NULL); @@ -1302,8 +1500,11 @@ void handle_oper(char **parameters, int pcnt, userrec *user) if (!strcmp(TypeName,OperType)) { /* found this oper's opertype */ + snprintf(global,MAXBUF,"| %s %s",user->nick,TypeName); + NetSendToAll(global); ConfValue("type","host",j,Hostname,&config_f); ChangeDisplayedHost(user,Hostname); + strlcpy(user->oper,TypeName,NICKMAX); } } if (!strchr(user->modes,'o')) @@ -1360,6 +1561,12 @@ void handle_nick(char **parameters, int pcnt, userrec *user) *parameters[0]++; } } + if (matches_qline(parameters[0])) + { + WriteOpers("*** Q-Lined nickname %s from %s!%s@%s: %s",parameters[0],user->nick,user->ident,user->host,matches_qline(parameters[0])); + WriteServ(user->fd,"432 %s %s :Invalid nickname: %s",user->nick,parameters[0],matches_qline(parameters[0])); + return; + } if ((Find(parameters[0])) && (Find(parameters[0]) != user)) { WriteServ(user->fd,"433 %s %s :Nickname is already in use.",user->nick,parameters[0]); @@ -1396,7 +1603,7 @@ void handle_nick(char **parameters, int pcnt, userrec *user) if (!user) return; if (!user->nick) return; - strncpy(user->nick, parameters[0],NICKMAX); + strlcpy(user->nick, parameters[0],NICKMAX); log(DEBUG,"new nick set: %s",user->nick); @@ -1407,7 +1614,6 @@ void handle_nick(char **parameters, int pcnt, userrec *user) /* user is registered now, bit 0 = USER command, bit 1 = sent a NICK command */ ConnectUser(user); } - log(DEBUG,"exit nickchange: %s",user->nick); } @@ -1495,8 +1701,8 @@ void handle_t(char token,char* params,serverrec* source,serverrec* reply, char* if ((c) && (u)) { WriteChannelLocal(c,u,"TOPIC %s :%s",c->name,topic); - strncpy(c->topic,topic,MAXTOPIC); - strncpy(c->setby,u->nick,NICKMAX); + strlcpy(c->topic,topic,MAXTOPIC); + strlcpy(c->setby,u->nick,NICKMAX); c->topicset = time(NULL); } } @@ -1517,8 +1723,8 @@ void handle_T(char token,char* params,serverrec* source,serverrec* reply, char* if (TS <= c->topicset) { WriteChannelLocal(c,NULL,"TOPIC %s :%s",c->name,topic); - strncpy(c->topic,topic,MAXTOPIC); - strncpy(c->setby,setby,NICKMAX); + strlcpy(c->topic,topic,MAXTOPIC); + strlcpy(c->setby,setby,NICKMAX); } } } @@ -1527,10 +1733,10 @@ void handle_M(char token,char* params,serverrec* source,serverrec* reply, char* { char* pars[128]; char original[MAXBUF],target[MAXBUF]; - strncpy(original,params,MAXBUF); + strlcpy(original,params,MAXBUF); int index = 0; char* parameter = strtok(params," "); - strncpy(target,parameter,MAXBUF); + strlcpy(target,parameter,MAXBUF); while (parameter) { if (parameter[0] == ':') @@ -1557,7 +1763,7 @@ void handle_m(char token,char* params,serverrec* source,serverrec* reply, char* // m blah #chatspike +b *!test@*4 char* pars[128]; char original[MAXBUF]; - strncpy(original,params,MAXBUF); + strlcpy(original,params,MAXBUF); if (!strchr(params,' ')) { @@ -1678,6 +1884,11 @@ void handle_n(char token,char* params,serverrec* source,serverrec* reply, char* kill_link(user,"Nickname collision"); return; } + if (matches_qline(newnick)) + { + kill_link(user,"Nickname collision"); + return; + } // broadcast this because its a services thingy char buffer[MAXBUF]; @@ -1687,7 +1898,7 @@ void handle_n(char token,char* params,serverrec* source,serverrec* reply, char* user = ReHashNick(user->nick, newnick); if (!user) return; if (!user->nick) return; - strncpy(user->nick, newnick,NICKMAX); + strlcpy(user->nick, newnick,NICKMAX); log(DEBUG,"new nick set: %s",user->nick); } } @@ -1735,7 +1946,25 @@ void handle_H(char token,char* params,serverrec* source,serverrec* reply, char* ircd_connector s; s.SetState(STATE_DISCONNECTED); s.SetServerName(params); + + for (int j = 0; j < 32; j++) + { + if (me[j] != NULL) + { + for (int k = 0; k < me[j]->connectors.size(); k++) + { + if (!strcasecmp(me[j]->connectors[k].GetServerName().c_str(),params)) + { + // dont allow a server to be added twice + log(DEBUG,"ULined server %s already in the map!",params); + return; + } + } + } + } + source->connectors.push_back(s); + WriteOpers("Non-Mesh server %s has joined the network",params); } void handle_N(char token,char* params,serverrec* source,serverrec* reply, char* tcp_host) @@ -1746,6 +1975,7 @@ void handle_N(char token,char* params,serverrec* source,serverrec* reply, char* char* dhost = strtok(NULL," "); char* ident = strtok(NULL," "); char* modes = strtok(NULL," "); + char* ipaddr = strtok(NULL," "); char* server = strtok(NULL," :"); char* gecos = strtok(NULL,"\r\n"); gecos++; @@ -1766,12 +1996,12 @@ void handle_N(char token,char* params,serverrec* source,serverrec* reply, char* // routines know to route any messages to this record away to whatever server // theyre on. clientlist[nick]->fd = -1; - strncpy(clientlist[nick]->nick, nick,NICKMAX); - strncpy(clientlist[nick]->host, host,160); - strncpy(clientlist[nick]->dhost, dhost,160); - strncpy(clientlist[nick]->server, server,256); - strncpy(clientlist[nick]->ident, ident,10); // +1 char to compensate for tilde - strncpy(clientlist[nick]->fullname, gecos,128); + strlcpy(clientlist[nick]->nick, nick,NICKMAX); + strlcpy(clientlist[nick]->host, host,160); + strlcpy(clientlist[nick]->dhost, dhost,160); + strlcpy(clientlist[nick]->server, server,256); + strlcpy(clientlist[nick]->ident, ident,10); // +1 char to compensate for tilde + strlcpy(clientlist[nick]->fullname, gecos,128); clientlist[nick]->signon = TS; clientlist[nick]->nping = 0; // this is ignored for a remote user anyway. clientlist[nick]->lastping = 1; @@ -1800,7 +2030,7 @@ void handle_a(char token,char* params,serverrec* source,serverrec* reply, char* userrec* user = Find(nick); if (user) - strncpy(user->fullname,gecos,MAXBUF); + strlcpy(user->fullname,gecos,MAXBUF); } void handle_b(char token,char* params,serverrec* source,serverrec* reply, char* tcp_host) @@ -1811,7 +2041,7 @@ void handle_b(char token,char* params,serverrec* source,serverrec* reply, char* userrec* user = Find(nick); if (user) - strncpy(user->dhost,host,160); + strlcpy(user->dhost,host,160); } void handle_plus(char token,char* params,serverrec* source,serverrec* reply, char* tcp_host) @@ -1851,6 +2081,12 @@ void handle_R(char token,char* params,serverrec* source,serverrec* reply, char* { char* server = strtok(params," "); char* data = strtok(NULL,"\r\n"); + if ((!data) || (!server)) + { + log(DEBUG,"Someones playing silly buggers, attempting to send to a null server or send a null message (BUG?)"); + return; + } + log(DEBUG,"Forwarded packet '%s' to '%s'",data,server); NetSendToOne(server,data); } @@ -1987,6 +2223,142 @@ void handle_amp(char token,char* params,serverrec* source,serverrec* reply, char long authcookie; +void handle_hash(char token,char* params,serverrec* source,serverrec* reply, char* tcp_host) +{ + // # : + log(DEBUG,"Adding G-line"); + char* mask = strtok(params," "); + char* who = strtok(NULL," "); + char* create_time = strtok(NULL," "); + char* duration = strtok(NULL," :"); + char* reason = strtok(NULL,"\r\n"); + add_gline(atoi(duration),who,reason,mask); + // we must update the creation time on this gline + // now that we've added it, or it wont expire at the right time. + gline_set_creation_time(mask,atoi(create_time)); + if (!atoi(duration)) + { + WriteOpers("*** %s Added permenant G-Line on %s.",who,mask); + } + else + { + WriteOpers("*** %s Added timed G-Line on %s to expire in %d seconds.",who,mask,atoi(duration)); + } + apply_lines(); +} + +void handle_dot(char token,char* params,serverrec* source,serverrec* reply, char* tcp_host) +{ + log(DEBUG,"Removing G-line"); + char* mask = strtok(params," "); + char* who = strtok(NULL," "); + if (mask) + { + if (del_gline(mask)) + { + if (who) + { + WriteOpers("*** %s Removed G-line on %s.",who,mask); + } + } + } +} + +void handle_add_sqline(char token,char* params,serverrec* source,serverrec* reply, char* tcp_host) +{ + // { : + log(DEBUG,"Adding Q-line"); + char* mask = strtok(params," "); + char* who = strtok(NULL," "); + char* create_time = strtok(NULL," "); + char* duration = strtok(NULL," :"); + char* reason = strtok(NULL,"\r\n"); + add_qline(atoi(duration),who,reason,mask); + // we must update the creation time on this gline + // now that we've added it, or it wont expire at the right time. + qline_set_creation_time(mask,atoi(create_time)); + qline_make_global(mask); + if (!atoi(duration)) + { + WriteOpers("*** %s Added permenant Q-Line on %s.",who,mask); + } + else + { + WriteOpers("*** %s Added timed Q-Line on %s to expire in %d seconds.",who,mask,atoi(duration)); + } + apply_lines(); +} + +void handle_del_sqline(char token,char* params,serverrec* source,serverrec* reply, char* tcp_host) +{ + log(DEBUG,"Removing Q-line"); + char* mask = strtok(params," "); + char* who = strtok(NULL," "); + if (mask) + { + if (del_qline(mask)) + { + if (who) + { + WriteOpers("*** %s Removed Q-line on %s.",who,mask); + } + } + } +} + +void handle_add_szline(char token,char* params,serverrec* source,serverrec* reply, char* tcp_host) +{ + // } : + log(DEBUG,"Adding Z-line"); + char* mask = strtok(params," "); + char* who = strtok(NULL," "); + char* create_time = strtok(NULL," "); + char* duration = strtok(NULL," :"); + char* reason = strtok(NULL,"\r\n"); + add_zline(atoi(duration),who,reason,mask); + // we must update the creation time on this gline + // now that we've added it, or it wont expire at the right time. + zline_set_creation_time(mask,atoi(create_time)); + zline_make_global(mask); + if (!atoi(duration)) + { + WriteOpers("*** %s Added permenant Z-Line on %s.",who,mask); + } + else + { + WriteOpers("*** %s Added timed Z-Line on %s to expire in %d seconds.",who,mask,atoi(duration)); + } + apply_lines(); +} + +void handle_del_szline(char token,char* params,serverrec* source,serverrec* reply, char* tcp_host) +{ + log(DEBUG,"Removing Z-line"); + char* mask = strtok(params," "); + char* who = strtok(NULL," "); + if (mask) + { + if (del_zline(mask)) + { + if (who) + { + WriteOpers("*** %s Removed Q-line on %s.",who,mask); + } + } + } +} + +void handle_pipe(char token,char* params,serverrec* source,serverrec* reply, char* tcp_host) +{ + char* nick = strtok(params," "); + char* type = strtok(params," "); + userrec* u = Find(nick); + if (u) + { + strlcpy(u->oper,type,NICKMAX); + } +} + void process_restricted_commands(char token,char* params,serverrec* source,serverrec* reply, char* tcp_host,char* ipaddr,int port) { @@ -2122,6 +2494,11 @@ void process_restricted_commands(char token,char* params,serverrec* source,serve case 'Q': handle_Q(token,params,source,reply,tcp_host); break; + // H + // introduce non-meshable server (such as a services server) + case 'H': + handle_H(token,params,source,reply,tcp_host); + break; // K : // remote kill case 'K': @@ -2132,6 +2509,41 @@ void process_restricted_commands(char token,char* params,serverrec* source,serve case '@': handle_AT(token,params,source,reply,tcp_host); break; + // # : + // add gline + case '#': + handle_hash(token,params,source,reply,tcp_host); + break; + // . + // remove gline + case '.': + handle_dot(token,params,source,reply,tcp_host); + break; + // # : + // add gline + case '{': + handle_add_sqline(token,params,source,reply,tcp_host); + break; + // . + // remove gline + case '[': + handle_del_sqline(token,params,source,reply,tcp_host); + break; + // # : + // add gline + case '}': + handle_add_szline(token,params,source,reply,tcp_host); + break; + // . + // remove gline + case ']': + handle_del_szline(token,params,source,reply,tcp_host); + break; + // | + // set opertype + case '|': + handle_pipe(token,params,source,reply,tcp_host); + break; // F // end netburst case 'F': @@ -2143,6 +2555,10 @@ void process_restricted_commands(char token,char* params,serverrec* source,serve snprintf(buffer,MAXBUF,"+ %s %s %d %d",tcp_host,ipaddr,port,authcookie); NetSendToAllExcept(tcp_host,buffer); break; + case '/': + WriteOpers("Server %s is IRCServices-based server (assumes-SVSMODE) - Nickname Services: %s",tcp_host,params); + strlcpy(source->nickserv,params,NICKMAX); + break; // F // end netburst with no mesh creation case 'f': @@ -2198,9 +2614,9 @@ void handle_link_packet(char* udp_msg, char* tcp_host, serverrec *serv) char data[MAXBUF]; char source[MAXBUF]; char command[MAXBUF]; - strcpy(data,udp_msg); - strcpy(source,src); - strcpy(command,comd); + strlcpy(data,udp_msg,512); + strlcpy(source,src,MAXBUF); + strlcpy(command,comd,MAXBUF); udp_msg = old; // unused numeric: @@ -2209,6 +2625,10 @@ void handle_link_packet(char* udp_msg, char* tcp_host, serverrec *serv) { token = '*'; } + if (!strcmp(command,"432")) + { + token = '*'; + } if (!strcmp(command,"NOTICE")) { snprintf(udp_msg,MAXBUF,"V %s %s",source,data); @@ -2237,14 +2657,14 @@ void handle_link_packet(char* udp_msg, char* tcp_host, serverrec *serv) } if (!strcmp(command,"SVSMODE")) { - snprintf(udp_msg,MAXBUF,"M %s",data); + snprintf(udp_msg,MAXBUF,"m %s %s",source,data); log(DEBUG,"Rewrote SVSMODE from services to: '%s'",udp_msg); token = udp_msg[0]; } if (!strcmp(command,"SVS2MODE")) { - snprintf(udp_msg,MAXBUF,"M %s",data); - log(DEBUG,"Rewrote SVSMODE from services to: '%s'",udp_msg); + snprintf(udp_msg,MAXBUF,"m %s %s",source,data); + log(DEBUG,"Rewrote SVS2MODE from services to: '%s'",udp_msg); token = udp_msg[0]; } // todo: this wont work without u:lines @@ -2261,6 +2681,26 @@ void handle_link_packet(char* udp_msg, char* tcp_host, serverrec *serv) log(DEBUG,"Rewrote KICK from services to: '%s'",udp_msg); token = udp_msg[0]; } + if (!strcmp(command,"KILL")) + { + snprintf(udp_msg,MAXBUF,"K %s %s",source,data); + log(DEBUG,"Rewrote KILL from services to: '%s'",udp_msg); + token = udp_msg[0]; + } + if (!strcmp(command,"SVSJOIN")) + { + snprintf(udp_msg,MAXBUF,"J %s",data); + NetSendToOne(tcp_host,udp_msg); + char* nick = strtok(data," "); + char* chan = strtok(NULL," "); + log(DEBUG,"Rewrote SVSJOIN from services to: '%s'",udp_msg); + userrec* u = Find(nick); + if (u) + { + add_channel(u,chan,"",true); + } + token = udp_msg[0]; + } } @@ -2269,7 +2709,7 @@ void handle_link_packet(char* udp_msg, char* tcp_host, serverrec *serv) char finalparam[1024]; strcpy(finalparam," :xxxx"); if (strstr(udp_msg," :")) { - strncpy(finalparam,strstr(udp_msg," :"),1024); + strlcpy(finalparam,strstr(udp_msg," :"),1024); } @@ -2332,7 +2772,7 @@ void handle_link_packet(char* udp_msg, char* tcp_host, serverrec *serv) { WriteOpers("CONNECT aborted: Server %s already exists from %s",servername,ServerName); char buffer[MAXBUF]; - sprintf(buffer,"E :Server %s already exists!",servername); + snprintf(buffer,MAXBUF,"E :Server %s already exists!",servername); serv->SendPacket(buffer,tcp_host); RemoveServer(tcp_host); return; @@ -2521,9 +2961,11 @@ void handle_link_packet(char* udp_msg, char* tcp_host, serverrec *serv) sprintf(buffer,"X 0"); serv->SendPacket(buffer,servername); DoSync(me[j],servername); - NetSendMyRoutingTable(); - sprintf(buffer,"H %s",servername); + snprintf(buffer,MAXBUF,"H %s",servername); NetSendToAllExcept(servername,buffer); + WriteOpers("Non-Mesh server %s has joined the network",servername); + log(DEBUG,"******** SENDING MY ROUTING TABLE! *******"); + NetSendMyRoutingTable(); return; } } @@ -2578,3 +3020,176 @@ void handle_link_packet(char* udp_msg, char* tcp_host, serverrec *serv) } } +long duration(char* str) +{ + char n_field[MAXBUF]; + long total = 0; + char* str_end = str + strlen(str); + n_field[0] = 0; + + for (char* i = str; i < str_end; i++) + { + // if we have digits, build up a string for the value in n_field, + // up to 10 digits in size. + if ((*i >= '0') && (*i <= '9')) + { + strlcat(n_field,i,10); + } + else + { + // we dont have a digit, check for numeric tokens + switch (tolower(*i)) + { + case 's': + total += atoi(n_field); + break; + + case 'm': + total += (atoi(n_field)*duration_m); + break; + + case 'h': + total += (atoi(n_field)*duration_h); + break; + + case 'd': + total += (atoi(n_field)*duration_d); + break; + + case 'w': + total += (atoi(n_field)*duration_w); + break; + + case 'y': + total += (atoi(n_field)*duration_y); + break; + } + n_field[0] = 0; + } + } + // add trailing seconds + total += atoi(n_field); + + return total; +} + + +void handle_kline(char **parameters, int pcnt, userrec *user) +{ + if (pcnt >= 3) + { + add_kline(duration(parameters[1]),user->nick,parameters[2],parameters[0]); + if (!duration(parameters[1])) + { + WriteOpers("*** %s added permenant K-line for %s.",user->nick,parameters[0]); + } + else + { + WriteOpers("*** %s added timed K-line for %s, expires in %d seconds.",user->nick,parameters[0],duration(parameters[1])); + } + } + else + { + if (del_kline(parameters[0])) + { + WriteOpers("*** %s Removed K-line on %s.",user->nick,parameters[0]); + } + else + { + WriteServ(user->fd,"NOTICE %s :*** K-Line %s not found in list, try /stats k.",user->nick,parameters[0]); + } + } + apply_lines(); +} + +void handle_gline(char **parameters, int pcnt, userrec *user) +{ + char netdata[MAXBUF]; + if (pcnt >= 3) + { + add_gline(duration(parameters[1]),user->nick,parameters[2],parameters[0]); + // # : + snprintf(netdata,MAXBUF,"# %s %s %ld %ld :%s",parameters[0],user->nick,time(NULL),duration(parameters[1]),parameters[2]); + NetSendToAll(netdata); + if (!duration(parameters[1])) + { + WriteOpers("*** %s added permenant G-line for %s.",user->nick,parameters[0]); + } + else + { + WriteOpers("*** %s added timed G-line for %s, expires in %d seconds.",user->nick,parameters[0],duration(parameters[1])); + } + } + else + { + if (del_gline(parameters[0])) + { + // . + snprintf(netdata,MAXBUF,". %s %s",parameters[0],user->nick); + WriteOpers("*** %s Removed G-line on %s.",user->nick,parameters[0]); + } + else + { + WriteServ(user->fd,"NOTICE %s :*** G-Line %s not found in list, try /stats g.",user->nick,parameters[0]); + } + } + apply_lines(); +} + +void handle_zline(char **parameters, int pcnt, userrec *user) +{ + if (pcnt >= 3) + { + add_zline(duration(parameters[1]),user->nick,parameters[2],parameters[0]); + if (!duration(parameters[1])) + { + WriteOpers("*** %s added permenant Z-line for %s.",user->nick,parameters[0]); + } + else + { + WriteOpers("*** %s added timed Z-line for %s, expires in %d seconds.",user->nick,parameters[0],duration(parameters[1])); + } + } + else + { + if (del_zline(parameters[0])) + { + WriteOpers("*** %s Removed Z-line on %s.",user->nick,parameters[0]); + } + else + { + WriteServ(user->fd,"NOTICE %s :*** Z-Line %s not found in list, try /stats Z.",user->nick,parameters[0]); + } + } + apply_lines(); +} + +void handle_qline(char **parameters, int pcnt, userrec *user) +{ + if (pcnt >= 3) + { + add_qline(duration(parameters[1]),user->nick,parameters[2],parameters[0]); + if (!duration(parameters[1])) + { + WriteOpers("*** %s added permenant Q-line for %s.",user->nick,parameters[0]); + } + else + { + WriteOpers("*** %s added timed Q-line for %s, expires in %d seconds.",user->nick,parameters[0],duration(parameters[1])); + } + } + else + { + if (del_qline(parameters[0])) + { + WriteOpers("*** %s Removed Q-line on %s.",user->nick,parameters[0]); + } + else + { + WriteServ(user->fd,"NOTICE %s :*** Q-Line %s not found in list, try /stats k.",user->nick,parameters[0]); + } + } + apply_lines(); +} + +