X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Fcommands.cpp;h=610b694bc31a8d033b491d4e1c73d3d5f6029ddc;hb=db11f2b24c6aeb5ab7ba4678638890bc68b1d0c1;hp=5144d7ae55200499cfe4f15eda5102de20a5873a;hpb=da8fe330c2b3445b370cb80ecae93c7fb34d441d;p=user%2Fhenk%2Fcode%2Finspircd.git diff --git a/src/commands.cpp b/src/commands.cpp index 5144d7ae5..610b694bc 100644 --- a/src/commands.cpp +++ b/src/commands.cpp @@ -50,6 +50,8 @@ #include "message.h" #include "mode.h" #include "xline.h" +#include "inspstring.h" +#include "dnsqueue.h" #ifdef GCC3 #define nspace __gnu_cxx @@ -60,8 +62,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]; @@ -89,7 +91,8 @@ extern time_t nb_start; extern bool nofork; -extern std::vector fd_reap; +extern time_t TIME; + extern std::vector module_names; extern char MyExecutable[1024]; @@ -116,28 +119,35 @@ const long duration_y = duration_w * 52; namespace nspace { - template<> struct nspace::hash - { - size_t operator()(const struct in_addr &a) const - { - size_t q; - memcpy(&q,&a,sizeof(size_t)); - return q; - } - }; - - template<> struct nspace::hash - { - size_t operator()(const string &s) const - { - char a[MAXBUF]; - static struct hash strhash; - strcpy(a,s.c_str()); - strlower(a); - return strhash(a); - } - }; -} +#ifdef GCC34 + template<> struct hash +#else + template<> struct nspace::hash +#endif + { + size_t operator()(const struct in_addr &a) const + { + size_t q; + memcpy(&q,&a,sizeof(size_t)); + return q; + } + }; +#ifdef GCC34 + template<> struct hash +#else + template<> struct nspace::hash +#endif + { + size_t operator()(const string &s) const + { + char a[MAXBUF]; + static struct hash strhash; + strlcpy(a,s.c_str(),MAXBUF); + strlower(a); + return strhash(a); + } + }; +} struct StrHashComp @@ -146,8 +156,10 @@ 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); + strlower(a); + strlower(b); return (strcasecmp(a,b) == 0); } @@ -188,7 +200,6 @@ extern address_cache IP; void handle_join(char **parameters, int pcnt, userrec *user) { chanrec* Ptr; - int i = 0; if (loop_call(handle_join,parameters,pcnt,user,0,0,1)) return; @@ -201,8 +212,6 @@ void handle_join(char **parameters, int pcnt, userrec *user) void handle_part(char **parameters, int pcnt, userrec *user) { - chanrec* Ptr; - if (pcnt > 1) { if (loop_call(handle_part,parameters,pcnt,user,0,pcnt-2,0)) @@ -224,21 +233,21 @@ void handle_kick(char **parameters, int pcnt, userrec *user) if ((!u) || (!Ptr)) { - WriteServ(user->fd,"401 %s %s :No suck nick/channel",user->nick, parameters[0]); + WriteServ(user->fd,"401 %s %s :No such nick/channel",user->nick, parameters[0]); 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'; @@ -248,17 +257,41 @@ 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); } // this must be propogated so that channel membership is kept in step network-wide - char buffer[MAXBUF]; snprintf(buffer,MAXBUF,"k %s %s %s :%s",user->nick,u->nick,Ptr->name,reason); NetSendToAll(buffer); } +void handle_loadmodule(char **parameters, int pcnt, userrec *user) +{ + if (LoadModule(parameters[0])) + { + WriteOpers("*** NEW MODULE: %s",parameters[0]); + WriteServ(user->fd,"975 %s %s :Module successfully loaded.",user->nick, parameters[0]); + } + else + { + WriteServ(user->fd,"974 %s %s :Failed to load module: %s",user->nick, parameters[0],ModuleError()); + } +} + +void handle_unloadmodule(char **parameters, int pcnt, userrec *user) +{ + if (UnloadModule(parameters[0])) + { + WriteOpers("*** MODULE UNLOADED: %s",parameters[0]); + WriteServ(user->fd,"973 %s %s :Module successfully unloaded.",user->nick, parameters[0]); + } + else + { + WriteServ(user->fd,"972 %s %s :Failed to unload module: %s",user->nick, parameters[0],ModuleError()); + } +} void handle_die(char **parameters, int pcnt, userrec *user) { @@ -277,7 +310,6 @@ void handle_die(char **parameters, int pcnt, userrec *user) void handle_restart(char **parameters, int pcnt, userrec *user) { - char restart[1024]; char *argv[32]; log(DEFAULT,"Restart: %s",user->nick); if (!strcmp(parameters[0],restartpass)) @@ -301,16 +333,16 @@ void handle_restart(char **parameters, int pcnt, userrec *user) sleep(1); for (int i = 0; i < 65536; i++) { - int on = 0; + int on = 1; struct linger linger = { 0 }; setsockopt(i, SOL_SOCKET, SO_REUSEADDR, (const char*)&on, sizeof(on)); linger.l_onoff = 1; - linger.l_linger = 0; + linger.l_linger = 1; setsockopt(i, SOL_SOCKET, SO_LINGER, (const char*)&linger,sizeof(linger)); Blocking(i); close(i); } - sleep(5); + sleep(2); execv(MyExecutable,argv); @@ -326,15 +358,23 @@ void handle_kill(char **parameters, int pcnt, userrec *user) { userrec *u = Find(parameters[0]); char killreason[MAXBUF]; - + log(DEBUG,"kill: %s %s",parameters[0],parameters[1]); if (u) { + log(DEBUG,"into kill mechanism"); + int MOD_RESULT = 0; + FOREACH_RESULT(OnKill(user,u,parameters[1])); + if (MOD_RESULT) { + log(DEBUG,"A module prevented the kill with result %d",MOD_RESULT); + return; + } + if (strcmp(ServerName,u->server)) { // 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]; @@ -345,25 +385,27 @@ void handle_kill(char **parameters, int pcnt, userrec *user) if (iter != clientlist.end()) { log(DEBUG,"deleting user hash value %d",iter->second); - if ((iter->second) && (user->registered == 7)) { - delete iter->second; - } - clientlist.erase(iter); + clientlist.erase(iter); + } + if (u->registered == 7) + { + purge_empty_chans(u); } - purge_empty_chans(); + delete u; } else { // local kill + log(DEFAULT,"LOCAL KILL: %s :%s!%s!%s (%s)", u->nick, ServerName,user->dhost,user->nick,parameters[1]); 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); } } else { - WriteServ(user->fd,"401 %s %s :No suck nick/channel",user->nick, parameters[0]); + WriteServ(user->fd,"401 %s %s :No such nick/channel",user->nick, parameters[0]); } } @@ -385,6 +427,7 @@ void handle_pass(char **parameters, int pcnt, userrec *user) WriteServ(user->fd,"462 %s :You may not reregister",user->nick); return; } + strlcpy(user->password,parameters[0],MAXBUF); if (!strcasecmp(parameters[0],Passwd(user))) { user->haspassed = true; @@ -459,6 +502,11 @@ void handle_topic(char **parameters, int pcnt, userrec *user) Ptr = FindChan(parameters[0]); if (Ptr) { + if (((Ptr) && (!has_channel(user,Ptr))) && (Ptr->secret)) + { + WriteServ(user->fd,"442 %s %s :You're not on that channel!",user->nick, Ptr->name); + return; + } if (Ptr->topicset) { WriteServ(user->fd,"332 %s %s :%s", user->nick, Ptr->name, Ptr->topic); @@ -471,7 +519,7 @@ void handle_topic(char **parameters, int pcnt, userrec *user) } else { - WriteServ(user->fd,"401 %s %s :No suck nick/channel",user->nick, parameters[0]); + WriteServ(user->fd,"401 %s %s :No such nick/channel",user->nick, parameters[0]); } } return; @@ -483,22 +531,35 @@ void handle_topic(char **parameters, int pcnt, userrec *user) Ptr = FindChan(parameters[0]); if (Ptr) { + if ((Ptr) && (!has_channel(user,Ptr))) + { + WriteServ(user->fd,"442 %s %s :You're not on that channel!",user->nick, Ptr->name); + return; + } if ((Ptr->topiclock) && (cstatus(user,Ptr)fd,"482 %s %s :You must be at least a half-operator to change modes on this channel", user->nick, Ptr->name); return; } - + 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); - Ptr->topicset = time(NULL); + + if (!strcasecmp(user->server,ServerName)) + { + int MOD_RESULT = 0; + FOREACH_RESULT(OnLocalTopicChange(user,Ptr,topic)); + if (MOD_RESULT) + return; + } + + strlcpy(Ptr->topic,topic,MAXBUF); + strlcpy(Ptr->setby,user->nick,NICKMAX); + Ptr->topicset = TIME; WriteChannel(Ptr,user,"TOPIC %s :%s",Ptr->name, Ptr->topic); // t token must go to ALL servers!!! @@ -508,7 +569,7 @@ void handle_topic(char **parameters, int pcnt, userrec *user) } else { - WriteServ(user->fd,"401 %s %s :No suck nick/channel",user->nick, parameters[0]); + WriteServ(user->fd,"401 %s %s :No such nick/channel",user->nick, parameters[0]); } } } @@ -518,18 +579,28 @@ void handle_names(char **parameters, int pcnt, userrec *user) { chanrec* c; + if (!pcnt) + { + WriteServ(user->fd,"366 %s * :End of /NAMES list.",user->nick); + return; + } + if (loop_call(handle_names,parameters,pcnt,user,0,pcnt-1,0)) return; c = FindChan(parameters[0]); if (c) { - /*WriteServ(user->fd,"353 %s = %s :%s", user->nick, c->name,*/ + if (((c) && (!has_channel(user,c))) && (c->secret)) + { + WriteServ(user->fd,"442 %s %s :You're not on that channel!",user->nick, c->name); + return; + } userlist(user,c); WriteServ(user->fd,"366 %s %s :End of /NAMES list.", user->nick, c->name); } else { - WriteServ(user->fd,"401 %s %s :No suck nick/channel",user->nick, parameters[0]); + WriteServ(user->fd,"401 %s %s :No such nick/channel",user->nick, parameters[0]); } } @@ -538,7 +609,7 @@ void handle_privmsg(char **parameters, int pcnt, userrec *user) userrec *dest; chanrec *chan; - user->idle_lastmsg = time(NULL); + user->idle_lastmsg = TIME; if (loop_call(handle_privmsg,parameters,pcnt,user,0,pcnt-2,0)) return; @@ -577,7 +648,7 @@ void handle_privmsg(char **parameters, int pcnt, userrec *user) else { /* no such nick/channel */ - WriteServ(user->fd,"401 %s %s :No suck nick/channel",user->nick, parameters[0]); + WriteServ(user->fd,"401 %s %s :No such nick/channel",user->nick, parameters[0]); } return; } @@ -617,7 +688,7 @@ void handle_privmsg(char **parameters, int pcnt, userrec *user) else { /* no such nick/channel */ - WriteServ(user->fd,"401 %s %s :No suck nick/channel",user->nick, parameters[0]); + WriteServ(user->fd,"401 %s %s :No such nick/channel",user->nick, parameters[0]); } } @@ -626,7 +697,7 @@ void handle_notice(char **parameters, int pcnt, userrec *user) userrec *dest; chanrec *chan; - user->idle_lastmsg = time(NULL); + user->idle_lastmsg = TIME; if (loop_call(handle_notice,parameters,pcnt,user,0,pcnt-2,0)) return; @@ -665,7 +736,7 @@ void handle_notice(char **parameters, int pcnt, userrec *user) else { /* no such nick/channel */ - WriteServ(user->fd,"401 %s %s :No suck nick/channel",user->nick, parameters[0]); + WriteServ(user->fd,"401 %s %s :No such nick/channel",user->nick, parameters[0]); } return; } @@ -697,7 +768,7 @@ void handle_notice(char **parameters, int pcnt, userrec *user) else { /* no such nick/channel */ - WriteServ(user->fd,"401 %s %s :No suck nick/channel",user->nick, parameters[0]); + WriteServ(user->fd,"401 %s %s :No such nick/channel",user->nick, parameters[0]); } } @@ -709,9 +780,39 @@ void handle_server(char **parameters, int pcnt, userrec *user) void handle_info(char **parameters, int pcnt, userrec *user) { - WriteServ(user->fd,"371 %s :The Inspire IRCd Project Has been brought to you by the following people..",user->nick); - WriteServ(user->fd,"371 %s :Craig Edwards, Craig McLure, and Others..",user->nick); - WriteServ(user->fd,"371 %s :Will finish this later when i can be arsed :p",user->nick); + WriteServ(user->fd,"371 %s :. o O (The Inspire Internet Relay Chat Server) O o .",user->nick); + WriteServ(user->fd,"371 %s : ",user->nick); + WriteServ(user->fd,"371 %s :Core developers: Craig Edwards (Brain)",user->nick); + WriteServ(user->fd,"371 %s : Craig McLure",user->nick); + WriteServ(user->fd,"371 %s : ",user->nick); + WriteServ(user->fd,"371 %s :Contributors: typobox43",user->nick); + WriteServ(user->fd,"371 %s : w00t",user->nick); + WriteServ(user->fd,"371 %s : Om",user->nick); + WriteServ(user->fd,"371 %s : Jazza",user->nick); + WriteServ(user->fd,"371 %s : ",user->nick); + WriteServ(user->fd,"371 %s :Testers: CC",user->nick); + WriteServ(user->fd,"371 %s : Piggles",user->nick); + WriteServ(user->fd,"371 %s : Foamy",user->nick); + WriteServ(user->fd,"371 %s : Hart",user->nick); + WriteServ(user->fd,"371 %s : RageD",user->nick); + WriteServ(user->fd,"371 %s : [ed]",user->nick); + WriteServ(user->fd,"371 %s : Azhrarn",user->nick); + WriteServ(user->fd,"371 %s : nenolod",user->nick); + WriteServ(user->fd,"371 %s : luigiman",user->nick); + WriteServ(user->fd,"371 %s : Chu",user->nick); + WriteServ(user->fd,"371 %s : aquanight",user->nick); + WriteServ(user->fd,"371 %s : xptek",user->nick); + WriteServ(user->fd,"371 %s : Grantlinks",user->nick); + WriteServ(user->fd,"371 %s : Rob",user->nick); + WriteServ(user->fd,"371 %s : angelic",user->nick); + WriteServ(user->fd,"371 %s : Jason",user->nick); + WriteServ(user->fd,"371 %s : ",user->nick); + WriteServ(user->fd,"371 %s :Thanks to irc-junkie and searchirc",user->nick); + WriteServ(user->fd,"371 %s :for the nice comments and the help",user->nick); + WriteServ(user->fd,"371 %s :you gave us in attracting users to",user->nick); + WriteServ(user->fd,"371 %s :this software.",user->nick); + WriteServ(user->fd,"371 %s : ",user->nick); + WriteServ(user->fd,"371 %s :Best experienced with: An IRC client.",user->nick); FOREACH_MOD OnInfo(user); WriteServ(user->fd,"374 %s :End of /INFO list",user->nick); } @@ -730,7 +831,6 @@ void handle_time(char **parameters, int pcnt, userrec *user) void handle_whois(char **parameters, int pcnt, userrec *user) { userrec *dest; - char *t; if (loop_call(handle_whois,parameters,pcnt,user,0,pcnt-1,0)) return; @@ -754,7 +854,7 @@ void handle_whois(char **parameters, int pcnt, userrec *user) { WriteServ(user->fd,"301 %s %s :%s",user->nick, dest->nick, dest->awaymsg); } - if (strchr(dest->modes,'o')) + if ((strchr(dest->modes,'o')) && (strcmp(dest->oper,""))) { 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); @@ -763,20 +863,20 @@ void handle_whois(char **parameters, int pcnt, userrec *user) if (!strcasecmp(user->server,dest->server)) { // idle time and signon line can only be sent if youre on the same server (according to RFC) - WriteServ(user->fd,"317 %s %s %d %d :seconds idle, signon time",user->nick, dest->nick, abs((dest->idle_lastmsg)-time(NULL)), dest->signon); + WriteServ(user->fd,"317 %s %s %d %d :seconds idle, signon time",user->nick, dest->nick, abs((dest->idle_lastmsg)-TIME), dest->signon); } WriteServ(user->fd,"318 %s %s :End of /WHOIS list.",user->nick, dest->nick); } else { - WriteServ(user->fd,"401 %s %s :No suck nick/channel",user->nick, parameters[0]); + WriteServ(user->fd,"401 %s %s :No such nick/channel",user->nick, parameters[0]); } } else { /* no such nick/channel */ - WriteServ(user->fd,"401 %s %s :No suck nick/channel",user->nick, parameters[0]); + WriteServ(user->fd,"401 %s %s :No such nick/channel",user->nick, parameters[0]); } } @@ -801,8 +901,8 @@ void handle_quit(char **parameters, int pcnt, userrec *user) reason[MAXQUIT-1] = '\0'; } - Write(user->fd,"ERROR :Closing link (%s@%s) [%s]",user->ident,user->host,parameters[0]); - WriteOpers("*** Client exiting: %s!%s@%s [%s]",user->nick,user->ident,user->host,parameters[0]); + Write(user->fd,"ERROR :Closing link (%s@%s) [%s%s]",user->ident,user->host,PrefixQuit,parameters[0]); + WriteOpers("*** Client exiting: %s!%s@%s [%s%s]",user->nick,user->ident,user->host,PrefixQuit,parameters[0]); WriteCommonExcept(user,"QUIT :%s%s",PrefixQuit,parameters[0]); char buffer[MAXBUF]; @@ -823,26 +923,30 @@ void handle_quit(char **parameters, int pcnt, userrec *user) AddWhoWas(user); } + FOREACH_MOD OnUserDisconnect(user); + /* push the socket on a stack of sockets due to be closed at the next opportunity */ - fd_reap.push_back(user->fd); + if (user->fd > -1) + { + shutdown(user->fd,2); + close(user->fd); + } if (iter != clientlist.end()) { clientlist.erase(iter); - log(DEBUG,"deleting user hash value %d",iter->second); - //if ((user) && (user->registered == 7)) { - //delete user; - //} } if (user->registered == 7) { - purge_empty_chans(); + purge_empty_chans(user); } + delete 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) @@ -858,7 +962,15 @@ void handle_who(char **parameters, int pcnt, userrec *user) // 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 ? 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; @@ -867,11 +979,11 @@ void handle_who(char **parameters, int pcnt, userrec *user) } if (Ptr) { - WriteServ(user->fd,"315 %s %s :End of /WHO list.",user->nick, Ptr->name); + WriteServ(user->fd,"315 %s %s :End of /WHO list.",user->nick , parameters[0]); } else { - WriteServ(user->fd,"315 %s %s :End of /WHO list.",user->nick, user->nick); + WriteServ(user->fd,"315 %s %s :End of /WHO list.",user->nick, parameters[0]); } return; } @@ -884,14 +996,23 @@ 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); + WriteServ(user->fd,"315 %s %s :End of /WHO list.",user->nick, parameters[0]); } else { - WriteServ(user->fd,"401 %s %s :No suck nick/channel",user->nick, parameters[0]); + WriteServ(user->fd,"401 %s %s :No such nick/channel",user->nick, parameters[0]); } } else @@ -899,7 +1020,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]); } @@ -914,11 +1043,20 @@ 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); } } } - WriteServ(user->fd,"315 %s %s :End of /WHO list.",user->nick, user->nick); + WriteServ(user->fd,"315 %s %s :End of /WHO list.",user->nick, parameters[0]); return; } } @@ -931,8 +1069,6 @@ void handle_wallops(char **parameters, int pcnt, userrec *user) void handle_list(char **parameters, int pcnt, userrec *user) { - chanrec* Ptr; - WriteServ(user->fd,"321 %s Channel :Users Name",user->nick); for (chan_hash::const_iterator i = chanlist.begin(); i != chanlist.end(); i++) { @@ -948,7 +1084,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)); } @@ -1001,10 +1137,9 @@ void handle_user(char **parameters, int pcnt, userrec *user) WriteServ(user->fd,"461 %s USER :Not enough parameters",user->nick); } 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); } } @@ -1017,6 +1152,7 @@ void handle_user(char **parameters, int pcnt, userrec *user) if (user->registered == 3) { /* user is registered now, bit 0 = USER command, bit 1 = sent a NICK command */ + FOREACH_MOD OnUserRegister(user); ConnectUser(user); } } @@ -1024,7 +1160,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]); @@ -1032,13 +1168,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); } } } @@ -1049,14 +1185,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); @@ -1067,12 +1203,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); } } @@ -1093,7 +1229,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); @@ -1132,11 +1268,31 @@ void handle_modules(char **parameters, int pcnt, userrec *user) { for (int i = 0; i < module_names.size(); i++) { - Version V = modules[i]->GetVersion(); - char modulename[MAXBUF]; - strncpy(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)); + Version V = modules[i]->GetVersion(); + char modulename[MAXBUF]; + char flagstate[MAXBUF]; + strcpy(flagstate,""); + if (V.Flags & VF_STATIC) + strlcat(flagstate,", static",MAXBUF); + if (V.Flags & VF_VENDOR) + strlcat(flagstate,", vendor",MAXBUF); + if (V.Flags & VF_COMMON) + strlcat(flagstate,", common",MAXBUF); + if (V.Flags & VF_SERVICEPROVIDER) + strlcat(flagstate,", service provider",MAXBUF); + if (!flagstate[0]) + strcpy(flagstate," "); + strlcpy(modulename,module_names[i].c_str(),256); + if (strchr(user->modes,'o')) + { + WriteServ(user->fd,"900 %s :0x%08lx %d.%d.%d.%d %s (%s)",user->nick,modules[i],V.Major,V.Minor,V.Revision,V.Build,CleanFilename(modulename),flagstate+2); + } + else + { + WriteServ(user->fd,"900 %s :%s",user->nick,CleanFilename(modulename)); + } } + WriteServ(user->fd,"901 %s :End of MODULES list",user->nick); } void handle_stats(char **parameters, int pcnt, userrec *user) @@ -1153,7 +1309,9 @@ void handle_stats(char **parameters, int pcnt, userrec *user) } - if (!strcasecmp(parameters[0],"c")) + FOREACH_MOD OnStats(*parameters[0]); + + if (*parameters[0] == 'c') { for (int i = 0; i < ConfValueEnum("link",&config_f); i++) { @@ -1165,7 +1323,7 @@ void handle_stats(char **parameters, int pcnt, userrec *user) } } - if (!strcasecmp(parameters[0],"i")) + if (*parameters[0] == 'i') { int idx = 0; for (ClassVector::iterator i = Classes.begin(); i != Classes.end(); i++) @@ -1175,7 +1333,7 @@ void handle_stats(char **parameters, int pcnt, userrec *user) } } - if (!strcasecmp(parameters[0],"y")) + if (*parameters[0] == 'y') { int idx = 0; for (ClassVector::iterator i = Classes.begin(); i != Classes.end(); i++) @@ -1185,7 +1343,7 @@ void handle_stats(char **parameters, int pcnt, userrec *user) } } - if (!strcmp(parameters[0],"U")) + if (*parameters[0] == 'U') { for (int i = 0; i < ConfValueEnum("uline",&config_f); i++) { @@ -1194,14 +1352,14 @@ void handle_stats(char **parameters, int pcnt, userrec *user) } } - if (!strcmp(parameters[0],"P")) + if (*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)); + WriteServ(user->fd,"249 %s :%s (%s@%s) Idle: %d",user->nick,i->second->nick,i->second->ident,i->second->dhost,(TIME - i->second->idle_lastmsg)); idx++; } } @@ -1209,28 +1367,33 @@ void handle_stats(char **parameters, int pcnt, userrec *user) //249 [Brain] :bwoadway-monitor (~wgmon@204.152.186.58) Idle: 18 } - if (!strcmp(parameters[0],"k")) + if (*parameters[0] == 'k') { stats_k(user); } - if (!strcmp(parameters[0],"g")) + if (*parameters[0] == 'g') { stats_g(user); } - if (!strcmp(parameters[0],"q")) + if (*parameters[0] == 'q') { stats_q(user); } - if (!strcmp(parameters[0],"Z")) + if (*parameters[0] == 'Z') { stats_z(user); } + if (*parameters[0] == 'e') + { + stats_e(user); + } + /* stats m (list number of times each command has been used, plus bytecount) */ - if (!strcmp(parameters[0],"m")) + if (*parameters[0] == 'm') { for (int i = 0; i < cmdlist.size(); i++) { @@ -1247,7 +1410,7 @@ void handle_stats(char **parameters, int pcnt, userrec *user) } /* stats z (debug and memory info) */ - if (!strcmp(parameters[0],"z")) + if (*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()); @@ -1260,7 +1423,7 @@ void handle_stats(char **parameters, int pcnt, userrec *user) } /* stats o */ - if (!strcmp(parameters[0],"o")) + if (*parameters[0] == 'o') { for (int i = 0; i < ConfValueEnum("oper",&config_f); i++) { @@ -1275,7 +1438,7 @@ void handle_stats(char **parameters, int pcnt, userrec *user) } /* stats l (show user I/O stats) */ - if (!strcmp(parameters[0],"l")) + if (*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++) @@ -1293,10 +1456,10 @@ void handle_stats(char **parameters, int pcnt, userrec *user) } /* stats u (show server uptime) */ - if (!strcmp(parameters[0],"u")) + if (*parameters[0] == 'u') { time_t current_time = 0; - current_time = time(NULL); + current_time = TIME; time_t server_uptime = current_time - startup_time; struct tm* stime; stime = gmtime(&server_uptime); @@ -1325,7 +1488,7 @@ void handle_connect(char **parameters, int pcnt, userrec *user) char Link_Pass[1024]; int LinkPort; bool found = false; - + for (int i = 0; i < ConfValueEnum("link",&config_f); i++) { if (!found) @@ -1376,7 +1539,54 @@ void handle_squit(char **parameters, int pcnt, userrec *user) } else { - WriteServ(user->fd,"NOTICE :*** Remote SQUIT not supported yet."); + if (!strcasecmp("*",parameters[0])) + { + WriteServ(user->fd,"NOTICE %s :*** You cannot issue an SQUIT this wide! If this is REALLY what you want, use a less wide mask.",user->nick); + WriteOpers("*** WARNING! %s tried to SQUIT all servers at once!",user->nick); + return; + } + if (!strcasecmp(ServerName,parameters[0])) + { + WriteServ(user->fd,"NOTICE %s :*** To take the local server out of the mesh, just use /SQUIT with no parameters instead.",user->nick); + return; + } + bool have_this_server = true; + int n_count = 0; + std::string server_to_squit = ""; + while (have_this_server) + { + have_this_server = false; + for (int j = 0; j < 32; j++) + { + if (me[j] != NULL) + { + for (int x = 0; x < me[j]->connectors.size(); x++) + { + if (match(me[j]->connectors[x].GetServerName().c_str(),parameters[0])) + { + // found a valid ircd_connector. + have_this_server = true; + server_to_squit = me[j]->connectors[x].GetServerName().c_str(); + break; + } + } + } + } + if (have_this_server) + { + WriteOpers("SQUIT command issued by %s to remove %s from the mesh",user->nick,server_to_squit.c_str()); + WriteServ(user->fd,"NOTICE %s :*** Removing remote server %s.",user->nick,server_to_squit.c_str()); + char buffer[MAXBUF]; + snprintf(buffer,MAXBUF,"& %s",server_to_squit.c_str()); + NetSendToAll(buffer); + DoSplit(server_to_squit.c_str()); + n_count++; + } + } + if (!n_count) + { + WriteServ(user->fd,"402 %s %s :Your pattern did not match any servers.",user->nick,parameters[0]); + } } } @@ -1402,7 +1612,7 @@ void handle_map(char **parameters, int pcnt, userrec *user) snprintf(line,MAXBUF,"006 %s :%s",user->nick,ServerName); while (strlen(line) < 50) strcat(line," "); - WriteServ(user->fd,"%s%d (%.2f%%)",line,local_count(),(float)(((float)local_count()/(float)usercnt())*100)); + WriteServ(user->fd,"%s%d (%.2f%%)",line,local_count(),(float)(((float)local_count()/(float)registered_usercount())*100)); for (int j = 0; j < 32; j++) { if (me[j] != NULL) @@ -1412,7 +1622,7 @@ void handle_map(char **parameters, int pcnt, userrec *user) snprintf(line,MAXBUF,"006 %s :%c-%s",user->nick,islast(me[j]->connectors[k].GetServerName().c_str()),me[j]->connectors[k].GetServerName().c_str()); while (strlen(line) < 50) strcat(line," "); - WriteServ(user->fd,"%s%d (%.2f%%)",line,map_count(me[j]->connectors[k].GetServerName().c_str()),(float)(((float)map_count(me[j]->connectors[k].GetServerName().c_str())/(float)usercnt())*100)); + WriteServ(user->fd,"%s%d (%.2f%%)",line,map_count(me[j]->connectors[k].GetServerName().c_str()),(float)(((float)map_count(me[j]->connectors[k].GetServerName().c_str())/(float)registered_usercount())*100)); } } } @@ -1422,8 +1632,6 @@ void handle_map(char **parameters, int pcnt, userrec *user) bool is_uline(const char* server) { char ServName[MAXBUF]; - int i,j; - for (int i = 0; i < ConfValueEnum("uline",&config_f); i++) { ConfValue("uline","server",i,ServName,&config_f); @@ -1434,7 +1642,18 @@ bool is_uline(const char* server) } return false; } - +int operstrcmp(char* data,char* input) +{ + int MOD_RESULT = 0; + FOREACH_RESULT(OnOperCompare(data,input)) + log(DEBUG,"operstrcmp: %d",MOD_RESULT); + if (MOD_RESULT == 1) + return 0; + if (MOD_RESULT == -1) + return 1; + log(DEBUG,"strcmp fallback: '%s' '%s' %d",data,input,strcmp(data,input)); + return strcmp(data,input); +} void handle_oper(char **parameters, int pcnt, userrec *user) { @@ -1442,47 +1661,77 @@ void handle_oper(char **parameters, int pcnt, userrec *user) char Password[MAXBUF]; char OperType[MAXBUF]; char TypeName[MAXBUF]; - char Hostname[MAXBUF]; - int i,j; + char HostName[MAXBUF]; + char TheHost[MAXBUF]; + int j; + bool found = false; + bool fail2 = false; + char global[MAXBUF]; + + snprintf(TheHost,MAXBUF,"%s@%s",user->ident,user->host); for (int i = 0; i < ConfValueEnum("oper",&config_f); i++) { ConfValue("oper","name",i,LoginName,&config_f); ConfValue("oper","password",i,Password,&config_f); - if ((!strcmp(LoginName,parameters[0])) && (!strcmp(Password,parameters[1]))) + ConfValue("oper","type",i,OperType,&config_f); + ConfValue("oper","host",i,HostName,&config_f); + if ((!strcmp(LoginName,parameters[0])) && (!operstrcmp(Password,parameters[1])) && (match(TheHost,HostName))) { - /* correct oper credentials */ - ConfValue("oper","type",i,OperType,&config_f); - WriteOpers("*** %s (%s@%s) is now an IRC operator of type %s",user->nick,user->ident,user->host,OperType); - WriteServ(user->fd,"381 %s :You are now an IRC operator of type %s",user->nick,OperType); - WriteServ(user->fd,"MODE %s :+o",user->nick); - char global[MAXBUF]; - snprintf(global,MAXBUF,"M %s +o",user->nick); - NetSendToAll(global); + fail2 = true; for (j =0; j < ConfValueEnum("type",&config_f); j++) { ConfValue("type","name",j,TypeName,&config_f); + 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); - strncpy(user->oper,TypeName,NICKMAX); + ConfValue("type","host",j,HostName,&config_f); + ChangeDisplayedHost(user,HostName); + strlcpy(user->oper,TypeName,NICKMAX); + found = true; + fail2 = false; + break; } } - if (!strchr(user->modes,'o')) - { - strcat(user->modes,"o"); - } + } + if (found) + break; + } + if (found) + { + /* correct oper credentials */ + WriteOpers("*** %s (%s@%s) is now an IRC operator of type %s",user->nick,user->ident,user->host,OperType); + WriteServ(user->fd,"381 %s :You are now an IRC operator of type %s",user->nick,OperType); + if (!strchr(user->modes,'o')) + { + strcat(user->modes,"o"); + WriteServ(user->fd,"MODE %s :+o",user->nick); + snprintf(global,MAXBUF,"M %s +o",user->nick); + NetSendToAll(global); FOREACH_MOD OnOper(user); - return; + log(DEFAULT,"OPER: %s!%s@%s opered as type: %s",user->nick,user->ident,user->host,OperType); + AddOper(user); + } + } + else + { + if (!fail2) + { + WriteServ(user->fd,"491 %s :Invalid oper credentials",user->nick); + WriteOpers("*** WARNING! Failed oper attempt by %s!%s@%s!",user->nick,user->ident,user->host); + log(DEFAULT,"OPER: Failed oper attempt by %s!%s@%s: user, host or password did not match.",user->nick,user->ident,user->host); + } + else + { + WriteServ(user->fd,"491 %s :Your oper block does not have a valid opertype associated with it",user->nick); + WriteOpers("*** CONFIGURATION ERROR! Oper block mismatch for OperType %s",OperType); + log(DEFAULT,"OPER: Failed oper attempt by %s!%s@%s: credentials valid, but oper type nonexistent.",user->nick,user->ident,user->host); } } - /* no such oper */ - WriteServ(user->fd,"491 %s :Invalid oper credentials",user->nick); - WriteOpers("*** WARNING! Failed oper attempt by %s!%s@%s!",user->nick,user->ident,user->host); + return; } void handle_nick(char **parameters, int pcnt, userrec *user) @@ -1497,7 +1746,7 @@ void handle_nick(char **parameters, int pcnt, userrec *user) log(DEBUG,"invalid parameter passed to handle_nick"); return; } - if (!strlen(parameters[0])) + if (!parameters[0][0]) { log(DEBUG,"zero length new nick passed to handle_nick"); return; @@ -1555,33 +1804,54 @@ void handle_nick(char **parameters, int pcnt, userrec *user) WriteCommon(user,"NICK %s",parameters[0]); - // Q token must go to ALL servers!!! + // N token must go to ALL servers!!! char buffer[MAXBUF]; snprintf(buffer,MAXBUF,"n %s %s",user->nick,parameters[0]); NetSendToAll(buffer); - } + char oldnick[NICKMAX]; + strlcpy(oldnick,user->nick,NICKMAX); + /* change the nick of the user in the users_hash */ user = ReHashNick(user->nick, parameters[0]); /* actually change the nick within the record */ 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); if (user->registered < 3) + { user->registered = (user->registered | 2); + // dont attempt to look up the dns until they pick a nick... because otherwise their pointer WILL change + // and unless we're lucky we'll get a duff one later on. + user->dns_done = (!lookup_dns(user->nick)); + if (user->dns_done) + log(DEBUG,"Aborting dns lookup of %s because dns server experienced a failure.",user->nick); + } if (user->registered == 3) { /* user is registered now, bit 0 = USER command, bit 1 = sent a NICK command */ + FOREACH_MOD OnUserRegister(user); ConnectUser(user); } + if (user->registered == 7) + { + FOREACH_MOD OnUserPostNick(user,oldnick); + } } +void handle_v(char token,char* params,serverrec* source,serverrec* reply, char* tcp_host) +{ + char* servername = strtok(params," "); + char* versionstr = strtok(NULL,"\r\n"); + ircd_connector* cn = reply->FindHost(servername); + cn->SetVersionString(versionstr); +} void handle_V(char token,char* params,serverrec* source,serverrec* reply, char* tcp_host) { @@ -1593,18 +1863,25 @@ void handle_V(char token,char* params,serverrec* source,serverrec* reply, char* userrec* user = Find(src); if (user) { - userrec* dst = Find(dest); - - if (dst) + // notice all - only issuable by a server + if (strcmp(dest,"*")) { - WriteTo(user, dst, "NOTICE %s :%s", dst->nick, text); + NoticeAll(user,true,"%s",text); } else { - chanrec* d = FindChan(dest); - if (d) + userrec* dst = Find(dest); + if (dst) { - ChanExceptSender(d, user, "NOTICE %s :%s", d->name, text); + WriteTo(user, dst, "NOTICE %s :%s", dst->nick, text); + } + else + { + chanrec* d = FindChan(dest); + if (d) + { + ChanExceptSender(d, user, "NOTICE %s :%s", d->name, text); + } } } } @@ -1666,9 +1943,9 @@ 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); - c->topicset = time(NULL); + strlcpy(c->topic,topic,MAXTOPIC); + strlcpy(c->setby,u->nick,NICKMAX); + c->topicset = TIME; } } @@ -1688,8 +1965,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); } } } @@ -1698,10 +1975,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] == ':') @@ -1728,7 +2005,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,' ')) { @@ -1759,14 +2036,28 @@ void handle_m(char token,char* params,serverrec* source,serverrec* reply, char* void handle_L(char token,char* params,serverrec* source,serverrec* reply, char* tcp_host) { - char* nick = strtok(params," "); - char* channel = strtok(NULL," :"); - char* reason = strtok(NULL,"\r\n"); + char* nick = NULL; + char* channel = NULL; + char* reason = NULL; + log(DEBUG,"L TOKEN PARS: '%s'",params); + if (strstr(params,":#")) + { + nick = strtok(params," "); + channel = strtok(NULL,"\r\n"); + channel++; + reason = ""; + } + else + { + nick = strtok(params," "); + channel = strtok(NULL," :"); + reason = strtok(NULL,"\r\n"); + reason++; + } userrec* user = Find(nick); - reason++; - if (user) + if ((user) && (channel) && (reason)) { - if (strcmp(reason,"")) + if ((!reason) && (*reason != '\0')) { del_channel(user,channel,reason,true); } @@ -1792,7 +2083,7 @@ void handle_K(char token,char* params,serverrec* source,serverrec* reply, char* { WriteTo(user, u, "KILL %s :%s!%s!%s!%s (%s)", u->nick, source->name, ServerName, user->dhost,user->nick,reason); WriteOpers("*** Remote kill from %s by %s: %s!%s@%s (%s)",source->name,user->nick,u->nick,u->ident,u->host,reason); - snprintf(kreason,MAXBUF,"[%s] Killed (%s (%s))",source->name,user->nick,reason); + snprintf(kreason,MAXBUF,"[%s] Killed (From: '%s' (%s))",source->name,user->nick,reason); kill_link(u,kreason); } } @@ -1820,13 +2111,14 @@ void handle_Q(char token,char* params,serverrec* source,serverrec* reply, char* if (iter != clientlist.end()) { log(DEBUG,"deleting user hash value %d",iter->second); - if ((iter->second) && (user->registered == 7)) { - delete iter->second; - } clientlist.erase(iter); } - purge_empty_chans(); + if (user->registered == 7) + { + purge_empty_chans(user); + } + delete user; } } @@ -1836,10 +2128,9 @@ void handle_n(char token,char* params,serverrec* source,serverrec* reply, char* char* newnick = strtok(NULL," "); userrec* user = Find(oldnick); - + if (user) { - WriteCommon(user,"NICK %s",newnick); if (is_uline(tcp_host)) { int MOD_RESULT = 0; @@ -1858,12 +2149,13 @@ void handle_n(char token,char* params,serverrec* source,serverrec* reply, char* // broadcast this because its a services thingy char buffer[MAXBUF]; snprintf(buffer,MAXBUF,"n %s %s",user->nick,newnick); - NetSendToAll(buffer); + NetSendToAllExcept(tcp_host,buffer); } + WriteCommon(user,"NICK %s",newnick); 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); } } @@ -1911,6 +2203,23 @@ 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); } @@ -1944,28 +2253,34 @@ 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); + strlcpy(clientlist[nick]->ip,ipaddr,32); clientlist[nick]->signon = TS; clientlist[nick]->nping = 0; // this is ignored for a remote user anyway. clientlist[nick]->lastping = 1; clientlist[nick]->port = 0; // so is this... clientlist[nick]->registered = 7; // this however we need to set for them to receive messages and appear online - clientlist[nick]->idle_lastmsg = time(NULL); // this is unrealiable and wont actually be used locally + clientlist[nick]->idle_lastmsg = TIME; // this is unrealiable and wont actually be used locally for (int i = 0; i < MAXCHANS; i++) { - clientlist[nick]->chans[i].channel = NULL; - clientlist[nick]->chans[i].uc_modes = 0; - } + clientlist[nick]->chans[i].channel = NULL; + clientlist[nick]->chans[i].uc_modes = 0; + } + FOREACH_MOD OnGlobalConnect(clientlist[nick]); + if (strchr(clientlist[nick]->modes,'o')) + { + FOREACH_MOD OnGlobalOper(clientlist[nick]); + } } void handle_F(char token,char* params,serverrec* source,serverrec* reply, char* tcp_host) { - long tdiff = time(NULL) - atoi(params); + long tdiff = TIME - atoi(params); if (tdiff) WriteOpers("TS split for %s -> %s: %d",source->name,reply->name,tdiff); } @@ -1978,7 +2293,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) @@ -1989,7 +2304,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) @@ -2169,7 +2484,7 @@ void handle_amp(char token,char* params,serverrec* source,serverrec* reply, char } } -long authcookie; +unsigned long authcookie; void handle_hash(char token,char* params,serverrec* source,serverrec* reply, char* tcp_host) { @@ -2180,7 +2495,8 @@ void handle_hash(char token,char* params,serverrec* source,serverrec* reply, cha char* create_time = strtok(NULL," "); char* duration = strtok(NULL," :"); char* reason = strtok(NULL,"\r\n"); - add_gline(atoi(duration),who,reason,mask); + reason++; + add_gline(atoi(duration),(const char*)who,(const char*)reason,(const char*)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)); @@ -2202,7 +2518,7 @@ void handle_dot(char token,char* params,serverrec* source,serverrec* reply, char char* who = strtok(NULL," "); if (mask) { - if (del_gline(mask)) + if (del_gline((const char*)mask)) { if (who) { @@ -2221,7 +2537,8 @@ void handle_add_sqline(char token,char* params,serverrec* source,serverrec* repl char* create_time = strtok(NULL," "); char* duration = strtok(NULL," :"); char* reason = strtok(NULL,"\r\n"); - add_qline(atoi(duration),who,reason,mask); + reason++; + add_qline(atoi(duration),(const char*)who,(const char*)reason,(const char*)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)); @@ -2244,7 +2561,7 @@ void handle_del_sqline(char token,char* params,serverrec* source,serverrec* repl char* who = strtok(NULL," "); if (mask) { - if (del_qline(mask)) + if (del_qline((const char*)mask)) { if (who) { @@ -2263,7 +2580,8 @@ void handle_add_szline(char token,char* params,serverrec* source,serverrec* repl char* create_time = strtok(NULL," "); char* duration = strtok(NULL," :"); char* reason = strtok(NULL,"\r\n"); - add_zline(atoi(duration),who,reason,mask); + reason++; + add_zline(atoi(duration),(const char*)who,(const char*)reason,(const char*)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)); @@ -2286,7 +2604,7 @@ void handle_del_szline(char token,char* params,serverrec* source,serverrec* repl char* who = strtok(NULL," "); if (mask) { - if (del_zline(mask)) + if (del_zline((const char*)mask)) { if (who) { @@ -2303,7 +2621,7 @@ void handle_pipe(char token,char* params,serverrec* source,serverrec* reply, cha userrec* u = Find(nick); if (u) { - strncpy(u->oper,type,NICKMAX); + strlcpy(u->oper,type,NICKMAX); } } @@ -2311,18 +2629,19 @@ void handle_pipe(char token,char* params,serverrec* source,serverrec* reply, cha void process_restricted_commands(char token,char* params,serverrec* source,serverrec* reply, char* tcp_host,char* ipaddr,int port) { char buffer[MAXBUF]; + int MOD_RESULT = 0; switch(token) { // Y // start netburst case 'Y': - nb_start = time(NULL); + nb_start = TIME; WriteOpers("Server %s is starting netburst.",tcp_host); // now broadcast this new servers address out to all servers that are linked to us, // except the newcomer. They'll all attempt to connect back to it. authcookie = rand()*rand(); - snprintf(buffer,MAXBUF,"~ %d",authcookie); + snprintf(buffer,MAXBUF,"~ %lu",(unsigned long)authcookie); NetSendToAll(buffer); break; // ~ @@ -2432,6 +2751,10 @@ void process_restricted_commands(char token,char* params,serverrec* source,serve case 'V': handle_V(token,params,source,reply,tcp_host); break; + // v + case 'v': + handle_v(token,params,source,reply,tcp_host); + break; // L : // User parting a channel case 'L': @@ -2495,18 +2818,22 @@ void process_restricted_commands(char token,char* params,serverrec* source,serve // F // end netburst case 'F': - WriteOpers("Server %s has completed netburst. (%d secs)",tcp_host,time(NULL)-nb_start); + WriteOpers("Server %s has completed netburst. (%d secs)",tcp_host,TIME-nb_start); handle_F(token,params,source,reply,tcp_host); nb_start = 0; // tell all the other servers to use this authcookie to connect back again // got '+ test3.chatspike.net 7010 -2016508415' from test.chatspike.net - snprintf(buffer,MAXBUF,"+ %s %s %d %d",tcp_host,ipaddr,port,authcookie); + snprintf(buffer,MAXBUF,"+ %s %s %d %lu",tcp_host,ipaddr,port,(unsigned long)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': - WriteOpers("Server %s has completed netburst. (%d secs)",tcp_host,time(NULL)-nb_start); + WriteOpers("Server %s has completed netburst. (%d secs)",tcp_host,TIME-nb_start); handle_F(token,params,source,reply,tcp_host); nb_start = 0; // tell everyone else about the new server name so they just add it in the disconnected @@ -2524,7 +2851,33 @@ void process_restricted_commands(char token,char* params,serverrec* source,serve break; // anything else default: - WriteOpers("WARNING! Unknown datagram type '%c'",token); + MOD_RESULT = 0; + string_list s; + char* data = strtok(params," "); + while (data) + { + if (*data == ':') + { + // the last item is a special case + data++; + char datalast[MAXBUF]; + strlcpy(datalast,data,MAXBUF); + data = strtok(NULL," "); + while (data) + { + strlcpy(datalast," ",MAXBUF); + strlcpy(datalast,data,MAXBUF); + data = strtok(NULL," "); + } + s.push_back(data); + break; + } + s.push_back(data); + data = strtok(NULL," "); + } + FOREACH_RESULT(OnMeshToken(token,s,source,reply,tcp_host,ipaddr,port)); + if (!MOD_RESULT) + WriteOpers("WARNING! Unknown datagram type '%c'",token); break; } } @@ -2532,7 +2885,7 @@ void process_restricted_commands(char token,char* params,serverrec* source,serve void handle_link_packet(char* udp_msg, char* tcp_host, serverrec *serv) { - if ((!strncmp(udp_msg,"USER ",5)) || (!strncmp(udp_msg,"NICK ",5))) + if ((!strncmp(udp_msg,"USER ",5)) || (!strncmp(udp_msg,"NICK ",5)) || (!strncmp(udp_msg,"PASS ",5)) || (!strncmp(udp_msg,"SERVER ",7))) { // a user on a server port, just close their connection. RemoveServer(tcp_host); @@ -2543,6 +2896,11 @@ void handle_link_packet(char* udp_msg, char* tcp_host, serverrec *serv) char token = udp_msg[0]; char* old = udp_msg; + if ((token != ':') && (strlen(udp_msg)>1) && (udp_msg[1] != ' ')) + { + WriteOpers("*** Discarded %d chars illegal data from %s",strlen(udp_msg),tcp_host); + } + if (token == ':') // leading :servername or details - strip them off (services does this, sucky) { char* src = udp_msg+1; @@ -2558,9 +2916,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: @@ -2573,6 +2931,10 @@ void handle_link_packet(char* udp_msg, char* tcp_host, serverrec *serv) { token = '*'; } + if (!strcmp(command,"PING")) + { + token = '*'; + } if (!strcmp(command,"NOTICE")) { snprintf(udp_msg,MAXBUF,"V %s %s",source,data); @@ -2601,14 +2963,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 @@ -2648,12 +3010,11 @@ void handle_link_packet(char* udp_msg, char* tcp_host, serverrec *serv) } - char* params = udp_msg + 2; char finalparam[1024]; strcpy(finalparam," :xxxx"); if (strstr(udp_msg," :")) { - strncpy(finalparam,strstr(udp_msg," :"),1024); + strlcpy(finalparam,strstr(udp_msg," :"),1024); } @@ -2708,6 +3069,8 @@ void handle_link_packet(char* udp_msg, char* tcp_host, serverrec *serv) char* revision = strtok(NULL," "); char* serverdesc = finalparam+2; + password = password; + WriteOpers("CONNECT from %s (%s) (their port: %d)",servername,tcp_host,atoi(myport)); ircd_connector* cn = serv->FindHost(servername); @@ -2716,7 +3079,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; @@ -2761,7 +3124,7 @@ void handle_link_packet(char* udp_msg, char* tcp_host, serverrec *serv) ConfValue("link","sendpass",i,Link_SendPass,&config_f); log(DEBUG,"(%d) Comparing against name='%s', ipaddr='%s', port='%s', recvpass='%s'",i,Link_ServerName,Link_IPAddr,Link_Port,Link_Pass); LinkPort = atoi(Link_Port); - if (!strcasecmp(Link_ServerName,servername)) + if ((!strcasecmp(Link_ServerName,servername)) && (!strcmp(Link_Pass,password))) { // we have a matching link line - // send a 'diminutive' server message back... @@ -2793,6 +3156,8 @@ void handle_link_packet(char* udp_msg, char* tcp_host, serverrec *serv) char* servername = strtok(params," "); char* password = strtok(NULL," "); char* serverdesc = finalparam+2; + + password = password; // TODO: we should do a check here to ensure that this server is one we recently initiated a // link with, and didnt hear an 's' or 'E' back from yet (these are the only two valid responses @@ -2808,7 +3173,7 @@ void handle_link_packet(char* udp_msg, char* tcp_host, serverrec *serv) char Link_Pass[1024]; char Link_SendPass[1024]; int LinkPort = 0; - + // search for a corresponding block in the config files for (int i = 0; i < ConfValueEnum("link",&config_f); i++) { @@ -2843,8 +3208,6 @@ void handle_link_packet(char* udp_msg, char* tcp_host, serverrec *serv) } } } - WriteOpers("\2WARNING!\2 %s sent us an authentication packet but we are not authenticating with this server right noe! Possible intrusion attempt!",tcp_host); - return; } } else { @@ -2874,6 +3237,28 @@ void handle_link_packet(char* udp_msg, char* tcp_host, serverrec *serv) char Link_Pass[1024]; char Link_SendPass[1024]; int LinkPort = 0; + + log(DEBUG,"U-token linked server detected.\n\nservername='%s' password='%s'\n\n",servername,password); + + + 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(),servername)) + { + char buffer[MAXBUF]; + sprintf(buffer,"E :Access is denied (Server exists in the mesh)"); + serv->SendPacket(buffer,tcp_host); + WriteOpers("CONNECT from %s denied, \"%s\" already exists!",tcp_host,servername); + RemoveServer(tcp_host); + return; + } + } + } + } // search for a corresponding block in the config files for (int i = 0; i < ConfValueEnum("link",&config_f); i++) @@ -2885,7 +3270,7 @@ void handle_link_packet(char* udp_msg, char* tcp_host, serverrec *serv) ConfValue("link","sendpass",i,Link_SendPass,&config_f); log(DEBUG,"(%d) Comparing against name='%s', ipaddr='%s', port='%s', recvpass='%s'",i,Link_ServerName,Link_IPAddr,Link_Port,Link_Pass); LinkPort = atoi(Link_Port); - if (!strcasecmp(Link_ServerName,servername)) + if ((!strcasecmp(Link_ServerName,servername)) && (!strcmp(Link_Pass,password))) { // matching link at this end too, we're all done! // at this point we must begin key exchange and insert this @@ -2899,28 +3284,31 @@ void handle_link_packet(char* udp_msg, char* tcp_host, serverrec *serv) if (!strcasecmp(me[j]->connectors[k].GetServerName().c_str(),tcp_host)) { char buffer[MAXBUF]; + log(DEBUG,"Found matching link block"); me[j]->connectors[k].SetDescription(serverdesc); me[j]->connectors[k].SetServerName(servername); me[j]->connectors[k].SetState(STATE_SERVICES); sprintf(buffer,"X 0"); serv->SendPacket(buffer,servername); + sprintf(buffer,"s %s %s %lu :%s",ServerName,Link_SendPass,LinkPort,ServerDesc); + 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; } } } - WriteOpers("\2WARNING!\2 %s sent us an authentication packet but we are not authenticating with this server right noe! Possible intrusion attempt!",tcp_host); - return; } } else { log(DEBUG,"Server names '%s' and '%s' don't match",Link_ServerName,servername); } } + log(DEBUG,"No matching link block found"); char buffer[MAXBUF]; sprintf(buffer,"E :Access is denied (no matching link block)"); serv->SendPacket(buffer,tcp_host); @@ -2936,9 +3324,6 @@ void handle_link_packet(char* udp_msg, char* tcp_host, serverrec *serv) return; } else { - - serverrec* source_server = NULL; - for (int j = 0; j < 32; j++) { if (me[j] != NULL) @@ -2963,20 +3348,20 @@ void handle_link_packet(char* udp_msg, char* tcp_host, serverrec *serv) } } -long duration(char* str) +long duration(const char* str) { char n_field[MAXBUF]; long total = 0; - char* str_end = str + strlen(str); + const char* str_end = str + strlen(str); n_field[0] = 0; - for (char* i = str; i < str_end; i++) + for (char* i = (char*)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')) { - strncat(n_field,i,10); + strlcat(n_field,i,10); } else { @@ -3045,6 +3430,34 @@ void handle_kline(char **parameters, int pcnt, userrec *user) apply_lines(); } +void handle_eline(char **parameters, int pcnt, userrec *user) +{ + if (pcnt >= 3) + { + add_eline(duration(parameters[1]),user->nick,parameters[2],parameters[0]); + if (!duration(parameters[1])) + { + WriteOpers("*** %s added permenant E-line for %s.",user->nick,parameters[0]); + } + else + { + WriteOpers("*** %s added timed E-line for %s, expires in %d seconds.",user->nick,parameters[0],duration(parameters[1])); + } + } + else + { + if (del_eline(parameters[0])) + { + WriteOpers("*** %s Removed E-line on %s.",user->nick,parameters[0]); + } + else + { + WriteServ(user->fd,"NOTICE %s :*** E-Line %s not found in list, try /stats e.",user->nick,parameters[0]); + } + } + // no need to apply the lines for an eline +} + void handle_gline(char **parameters, int pcnt, userrec *user) { char netdata[MAXBUF]; @@ -3052,7 +3465,7 @@ void handle_gline(char **parameters, int pcnt, userrec *user) { 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]); + snprintf(netdata,MAXBUF,"# %s %s %lu %lu :%s",parameters[0],user->nick,(unsigned long)TIME,(unsigned long)duration(parameters[1]),parameters[2]); NetSendToAll(netdata); if (!duration(parameters[1])) {