]> git.netwichtig.de Git - user/henk/code/inspircd.git/blobdiff - src/modules/m_spanningtree/treesocket1.cpp
Check validity (length) of all NICK parameters to make sure we're not introducing...
[user/henk/code/inspircd.git] / src / modules / m_spanningtree / treesocket1.cpp
index d5aeb223c1b37e6e105d71bf5d55c7d0a58a81f2..2ead91c8ed3fc8e285a54423d9bea03e5ccb8376 100644 (file)
@@ -628,6 +628,7 @@ bool TreeSocket::ForceJoin(const std::string &source, std::deque<std::string> &p
        userrec* who = NULL;                /* User we are currently checking */
        std::string channel = params[0];        /* Channel name, as a string */
        time_t TS = atoi(params[1].c_str());    /* Timestamp given to us for remote side */
+       std::string nicklist = params[2];
        bool created = false;
 
        /* Try and find the channel */
@@ -645,6 +646,13 @@ bool TreeSocket::ForceJoin(const std::string &source, std::deque<std::string> &p
                ourTS = chan->age;
        else
                created = true; /* don't perform deops, and set TS to correct time after processing. */
+
+       /* do this first, so our mode reversals are correctly received by other servers
+        * if there is a TS collision.
+        */
+       params[2] = ":" + params[2];
+       Utils->DoOneToAllButSender(source,"FJOIN",params,source);
+
        /* In 1.1, if they have the newer channel, we immediately clear
         * all status modes from our users. We then accept their modes.
         * If WE have the newer channel its the other side's job to do this.
@@ -669,13 +677,9 @@ bool TreeSocket::ForceJoin(const std::string &source, std::deque<std::string> &p
                }
        }
        /* Put the final parameter of the FJOIN into a tokenstream ready to split it */
-       irc::tokenstream users(params[2]);
+       irc::tokenstream users(nicklist);
        std::string item = "*";
-       /* do this first, so our mode reversals are correctly received by other servers
-        * if there is a TS collision.
-        */
-       params[2] = ":" + params[2];
-       Utils->DoOneToAllButSender(source,"FJOIN",params,source);
+
        /* Now, process every 'prefixes,nick' pair */
        while (item != "")
        {
@@ -752,7 +756,10 @@ bool TreeSocket::ForceJoin(const std::string &source, std::deque<std::string> &p
                                /* Finally, we can actually place the user into the channel.
                                 * We're sure its right. Final answer, phone a friend.
                                 */
-                               chanrec::JoinUser(this->Instance, who, channel.c_str(), true, "");
+                               if (created)
+                                       chanrec::JoinUser(this->Instance, who, channel.c_str(), true, "", TS);
+                               else
+                                       chanrec::JoinUser(this->Instance, who, channel.c_str(), true, "");
                                /* Have we already queued up MAXMODES modes with parameters
                                 * (+qaohv) ready to be sent to the server?
                                 */
@@ -834,19 +841,6 @@ bool TreeSocket::ForceJoin(const std::string &source, std::deque<std::string> &p
                for (unsigned int f = 2; f < modectr; f++)
                        free(mode_users[f]);
        }
-       /* if we newly created the channel, set it's TS properly. */
-       if (created)
-       {
-               /* find created channel .. */
-               chan = this->Instance->FindChan(channel);
-               if (chan)
-                       /* w00t said this shouldnt be needed but it is.
-                        * This isnt strictly true, as chan can be NULL
-                        * if a nick collision has occured and therefore
-                        * the channel was never created.
-                        */
-                       chan->age = TS;
-       }
        /* All done. That wasnt so bad was it, you can wipe
         * the sweat from your forehead now. :-)
         */
@@ -856,25 +850,60 @@ bool TreeSocket::ForceJoin(const std::string &source, std::deque<std::string> &p
 /** NICK command */
 bool TreeSocket::IntroduceClient(const std::string &source, std::deque<std::string> &params)
 {
-       if (params.size() < 8)
-               return true;
-       if (params.size() > 8)
+       /** Do we have enough parameters:
+        * NICK age nick host dhost ident +modes ip :gecos
+        */
+       if (params.size() != 8)
        {
                this->WriteLine(std::string(":")+this->Instance->Config->ServerName+" KILL "+params[1]+" :Invalid client introduction ("+params[1]+"?)");
                return true;
        }
-       // NICK age nick host dhost ident +modes ip :gecos
-       //       0    1   2     3     4      5   6     7
-       time_t age = atoi(params[0].c_str());
 
+       time_t age = atoi(params[0].c_str());
        const char* tempnick = params[1].c_str();
-       Instance->Log(DEBUG,"New remote client %s",tempnick);
 
+       /** Check parameters for validity before introducing the client, discovered by dmb.
+        * XXX: Can we make this neater?
+        */
+       if (!age)
+       {
+               this->WriteLine(std::string(":")+this->Instance->Config->ServerName+" KILL "+params[1]+" :Invalid client introduction (Invalid TS?)");
+               return true;
+       }
+       else if (params[1].length() > NICKMAX)
+       {
+               this->WriteLine(std::string(":")+this->Instance->Config->ServerName+" KILL "+params[1]+" :Invalid client introduction ("+params[1]+" > NICKMAX?)");
+               return true;
+       }
+       else if (params[2].length() > 64)
+       {
+               this->WriteLine(std::string(":")+this->Instance->Config->ServerName+" KILL "+params[1]+" :Invalid client introduction ("+params[2]+" > 64?)");
+               return true;
+       }
+       else if (params[3].length() > 64)
+       {
+               this->WriteLine(std::string(":")+this->Instance->Config->ServerName+" KILL "+params[1]+" :Invalid client introduction ("+params[3]+" > 64?)");
+               return true;
+       }
+       else if (params[4].length() > IDENTMAX)
+       {
+               this->WriteLine(std::string(":")+this->Instance->Config->ServerName+" KILL "+params[1]+" :Invalid client introduction ("+params[4]+" > IDENTMAX?)");
+               return true;
+       }
+       else if (params[7].length() > MAXGECOS)
+       {
+               this->WriteLine(std::string(":")+this->Instance->Config->ServerName+" KILL "+params[1]+" :Invalid client introduction ("+params[7]+" > MAXGECOS?)");
+               return true;
+       }
+
+       /** Our client looks ok, lets introduce it now
+        */
+       Instance->Log(DEBUG,"New remote client %s",tempnick);
        user_hash::iterator iter = this->Instance->clientlist->find(tempnick);
 
        if (iter != this->Instance->clientlist->end())
        {
-               // nick collision
+               /* nick collision */
                this->WriteLine(std::string(":")+this->Instance->Config->ServerName+" KILL "+tempnick+" :Nickname collision");
                userrec::QuitUser(this->Instance, iter->second, "Nickname collision");
                return true;
@@ -892,9 +921,7 @@ bool TreeSocket::IntroduceClient(const std::string &source, std::deque<std::stri
        _new->registered = REG_ALL;
        _new->signon = age;
 
-       /*
-        * we need to remove the + from the modestring, so we can do our stuff
-        */
+       /* we need to remove the + from the modestring, so we can do our stuff */
        std::string::size_type pos_after_plus = params[5].find_first_not_of('+');
        if (pos_after_plus != std::string::npos)
        params[5] = params[5].substr(pos_after_plus);