]> git.netwichtig.de Git - user/henk/code/inspircd.git/blobdiff - src/modules/m_spanningtree/treesocket1.cpp
Test code that pretends to send a hashed value if its got a challenge - don't use...
[user/henk/code/inspircd.git] / src / modules / m_spanningtree / treesocket1.cpp
index ae972a37e0d3dde88c3019a1208c600444a21407..8ccd83b3a24f4bcce2450d5aa4f612bfd74ad8d2 100644 (file)
@@ -1,3 +1,16 @@
+/*       +------------------------------------+
+ *       | Inspire Internet Relay Chat Daemon |
+ *       +------------------------------------+
+ *
+ *  InspIRCd: (C) 2002-2007 InspIRCd Development Team
+ * See: http://www.inspircd.org/wiki/index.php/Credits
+ *
+ * This program is free but copyrighted software; see
+ *            the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
 #include "configreader.h"
 #include "users.h"
 #include "channels.h"
@@ -31,6 +44,7 @@ TreeSocket::TreeSocket(SpanningTreeUtilities* Util, InspIRCd* SI, std::string ho
 {
        myhost = host;
        this->LinkState = LISTENER;
+       theirchallenge = ourchallenge = "";
        if (listening && Hook)
                InspSocketHookRequest(this, (Module*)Utils->Creator, Hook).Send();
 }
@@ -39,6 +53,7 @@ TreeSocket::TreeSocket(SpanningTreeUtilities* Util, InspIRCd* SI, std::string ho
        : InspSocket(SI, host, port, listening, maxtime, bindto), Utils(Util), Hook(HookMod)
 {
        myhost = ServerName;
+       theirchallenge = ourchallenge = "";
        this->LinkState = CONNECTING;
        if (Hook)
                InspSocketHookRequest(this, (Module*)Utils->Creator, Hook).Send();
@@ -52,6 +67,7 @@ TreeSocket::TreeSocket(SpanningTreeUtilities* Util, InspIRCd* SI, int newfd, cha
        : InspSocket(SI, newfd, ip), Utils(Util), Hook(HookMod)
 {
        this->LinkState = WAIT_AUTH_1;
+       theirchallenge = ourchallenge = "";
        /* If we have a transport module hooked to the parent, hook the same module to this
         * socket, and set a timer waiting for handshake before we send CAPAB etc.
         */
@@ -85,6 +101,35 @@ TreeSocket::~TreeSocket()
                InspSocketUnhookRequest(this, (Module*)Utils->Creator, Hook).Send();
 }
 
+const std::string& TreeSocket::GetOurChallenge()
+{
+       return this->ourchallenge;
+}
+
+void TreeSocket::SetOurChallenge(const std::string &c)
+{
+       this->ourchallenge = c;
+}
+
+const std::string& TreeSocket::GetTheirChallenge()
+{
+       return this->theirchallenge;
+}
+
+void TreeSocket::SetTheirChallenge(const std::string &c)
+{
+       this->theirchallenge = c;
+}
+
+std::string TreeSocket::MakePass(const std::string &password)
+{
+       if ((this->GetOurChallenge() != "") && (this->GetTheirChallenge() != ""))
+       {
+               return password + ":" + this->GetTheirChallenge();
+       }
+       return password;
+}
+
 /** When an outbound connection finishes connecting, we receive
  * this event, and must send our SERVER string to the other
  * side. If the other side is happy, as outlined in the server
@@ -109,10 +154,7 @@ bool TreeSocket::OnConnected()
                                else
                                        this->SendCapabilities();
                                /* found who we're supposed to be connecting to, send the neccessary gubbins. */
-                               if (Hook)
-                                       Instance->Timers->AddTimer(new HandshakeTimer(Instance, this, &(*x), this->Utils));
-                               else
-                                       this->WriteLine(std::string("SERVER ")+this->Instance->Config->ServerName+" "+x->SendPass+" 0 :"+this->Instance->Config->ServerDesc);
+                               Instance->Timers->AddTimer(new HandshakeTimer(Instance, this, &(*x), this->Utils));
                                return true;
                        }
                }
@@ -194,6 +236,14 @@ std::string TreeSocket::MyCapabilities()
        return capabilities;
 }
 
+std::string TreeSocket::RandString(unsigned int length)
+{
+       std::string out;
+       for (unsigned int i = 0; i < length; i++)
+               out += static_cast<char>((rand() % 26) + 65);
+       return out;
+}
+
 void TreeSocket::SendCapabilities()
 {
        irc::commasepstream modulelist(MyCapabilities());
@@ -226,7 +276,8 @@ void TreeSocket::SendCapabilities()
 #ifdef SUPPORT_IP6LINKS
        ip6support = 1;
 #endif
-       this->WriteLine("CAPAB CAPABILITIES :NICKMAX="+ConvToStr(NICKMAX)+" HALFOP="+ConvToStr(this->Instance->Config->AllowHalfop)+" CHANMAX="+ConvToStr(CHANMAX)+" MAXMODES="+ConvToStr(MAXMODES)+" IDENTMAX="+ConvToStr(IDENTMAX)+" MAXQUIT="+ConvToStr(MAXQUIT)+" MAXTOPIC="+ConvToStr(MAXTOPIC)+" MAXKICK="+ConvToStr(MAXKICK)+" MAXGECOS="+ConvToStr(MAXGECOS)+" MAXAWAY="+ConvToStr(MAXAWAY)+" IP6NATIVE="+ConvToStr(ip6)+" IP6SUPPORT="+ConvToStr(ip6support)+" PROTOCOL="+ConvToStr(ProtocolVersion));
+       this->SetOurChallenge(RandString(20));
+       this->WriteLine("CAPAB CAPABILITIES :NICKMAX="+ConvToStr(NICKMAX)+" HALFOP="+ConvToStr(this->Instance->Config->AllowHalfop)+" CHANMAX="+ConvToStr(CHANMAX)+" MAXMODES="+ConvToStr(MAXMODES)+" IDENTMAX="+ConvToStr(IDENTMAX)+" MAXQUIT="+ConvToStr(MAXQUIT)+" MAXTOPIC="+ConvToStr(MAXTOPIC)+" MAXKICK="+ConvToStr(MAXKICK)+" MAXGECOS="+ConvToStr(MAXGECOS)+" MAXAWAY="+ConvToStr(MAXAWAY)+" IP6NATIVE="+ConvToStr(ip6)+" IP6SUPPORT="+ConvToStr(ip6support)+" PROTOCOL="+ConvToStr(ProtocolVersion)+" CHALLENGE="+this->GetOurChallenge());
 
        this->WriteLine("CAPAB END");
 }
@@ -334,6 +385,15 @@ bool TreeSocket::Capab(const std::deque<std::string> &params)
                        reason = "Maximum GECOS (fullname) lengths differ or remote GECOS length not specified";
                if (((this->CapKeys.find("MAXAWAY") == this->CapKeys.end()) || ((this->CapKeys.find("MAXAWAY") != this->CapKeys.end()) && (this->CapKeys.find("MAXAWAY")->second != ConvToStr(MAXAWAY)))))
                        reason = "Maximum awaymessage lengths differ or remote awaymessage length not specified";
+
+               /* Challenge response, store their challenge for our password */
+               std::map<std::string,std::string>::iterator n = this->CapKeys.find("CHALLENGE");
+               if (n != this->CapKeys.end())
+               {
+                       /* Challenge-response is on now */
+                       this->SetTheirChallenge(n->second);
+               }
+
                if (reason.length())
                {
                        this->WriteLine("ERROR :CAPAB negotiation failed: "+reason);
@@ -356,8 +416,9 @@ bool TreeSocket::Capab(const std::deque<std::string> &params)
        else if ((params[0] == "CAPABILITIES") && (params.size() == 2))
        {
                irc::tokenstream capabs(params[1]);
-               std::string item = "*";
-               while ((item = capabs.GetToken()) != "")
+               std::string item;
+               bool more = true;
+               while ((more = capabs.GetToken(item)))
                {
                        /* Process each key/value pair */
                        std::string::size_type equals = item.rfind('=');
@@ -500,276 +561,24 @@ bool TreeSocket::ForceMode(const std::string &source, std::deque<std::string> &p
                        return true;
        }
 
-       /* TS is equal: Merge the mode changes, use voooodoooooo on modes
-        * with parameters.
+       /* TS is equal or less: Merge the mode changes into ours and pass on.
         */
-       if (TS == ourTS)
+       if (TS <= ourTS)
        {
-               ModeHandler* mh = NULL;
-               unsigned long paramptr = 3;
-               std::string to_bounce = "";
-               std::string to_keep = "";
-               std::vector<std::string> params_to_keep;
-               std::string params_to_bounce = "";
-               bool adding = true;
-               char cur_change = 1;
-               char old_change = 0;
-               char old_bounce_change = 0;
-               /* Merge modes, basically do special stuff to mode with params */
-               for (std::string::iterator x = params[2].begin(); x != params[2].end(); x++)
-               {
-                       switch (*x)
-                       {
-                               case '-':
-                                       adding = false;
-                               break;
-                               case '+':
-                                       adding = true;
-                               break;
-                               default:
-                                       if (adding)
-                                       {
-                                               /* We only care about whats being set,
-                                                * not whats being unset
-                                                */
-                                               mh = this->Instance->Modes->FindMode(*x, chan ? MODETYPE_CHANNEL : MODETYPE_USER);
-                                               if ((mh) && (mh->GetNumParams(adding) > 0) && (!mh->IsListMode()))
-                                               {
-                                                       /* We only want to do special things to
-                                                        * modes with parameters, we are going to rewrite
-                                                        * those parameters
-                                                        */
-                                                       ModePair ret;
-                                                       adding ? cur_change = '+' : cur_change = '-';
-                                                       ret = mh->ModeSet(smode ? NULL : who, dst, chan, params[paramptr]);
-                                                       /* The mode is set here, check which we should keep */
-                                                       if (ret.first)
-                                                       {
-                                                               bool which_to_keep = mh->CheckTimeStamp(TS, ourTS, params[paramptr], ret.second, chan);
-                                                               if (which_to_keep == true)
-                                                               {
-                                                                       /* Keep ours, bounce theirs:
-                                                                        * Send back ours to them and
-                                                                        * drop their mode changs
-                                                                        */
-                                                                       adding ? cur_change = '+' : cur_change = '-';
-                                                                       if (cur_change != old_bounce_change)
-                                                                               to_bounce += cur_change;
-                                                                       to_bounce += *x;
-                                                                       old_bounce_change = cur_change;
-                                                                       if ((mh->GetNumParams(adding) > 0) && (paramptr < params.size()))
-                                                                               params_to_bounce.append(" ").append(ret.second);
-                                                               }
-                                                               else
-                                                               {
-                                                                       /* Keep theirs: Accept their mode change,
-                                                                        * do nothing else
-                                                                        */
-                                                                       adding ? cur_change = '+' : cur_change = '-';
-                                                                       if (cur_change != old_change)
-                                                                               to_keep += cur_change;
-                                                                       to_keep += *x;
-                                                                       old_change = cur_change;
-                                                                       if ((mh->GetNumParams(adding) > 0) && (paramptr < params.size()))
-                                                                               params_to_keep.push_back(params[paramptr]);
-                                                               }
-                                                       }
-                                                       else
-                                                       {
-                                                               /* Mode isnt set here, we want it */
-                                                               adding ? cur_change = '+' : cur_change = '-';
-                                                               if (cur_change != old_change)
-                                                                       to_keep += cur_change;
-                                                               to_keep += *x;
-                                                               old_change = cur_change;
-                                                               if ((mh->GetNumParams(adding) > 0) && (paramptr < params.size()))
-                                                                       params_to_keep.push_back(params[paramptr]);
-                                                       }
-                                                       paramptr++;
-                                               }
-                                               else
-                                               {
-                                                       mh = this->Instance->Modes->FindMode(*x, chan ? MODETYPE_CHANNEL : MODETYPE_USER);
-                                                       if (mh)
-                                                       {
-                                                               adding ? cur_change = '+' : cur_change = '-';
-
-                                                               /* Just keep this, safe to merge with no checks
-                                                                * it has no parameters
-                                                                */
-
-                                                               if (cur_change != old_change)
-                                                                       to_keep += cur_change;
-                                                               to_keep += *x;
-                                                               old_change = cur_change;
-
-                                                               if ((mh->GetNumParams(adding) > 0) && (paramptr < params.size()))
-                                                               {
-                                                                       params_to_keep.push_back(params[paramptr++]);
-                                                               }
-                                                       }
-                                               }
-                                       }
-                                       else
-                                       {
-                                               mh = this->Instance->Modes->FindMode(*x, chan ? MODETYPE_CHANNEL : MODETYPE_USER);
-                                               if (mh)
-                                               {
-                                                       /* Taking a mode away */
-                                                       adding ? cur_change = '+' : cur_change = '-';
-                                                       if (cur_change != old_change)
-                                                               to_keep += cur_change;
-                                                       to_keep += *x;
-                                                       old_change = cur_change;
-                                                       if ((mh->GetNumParams(adding) > 0) && (paramptr < params.size()))
-                                                               params_to_keep.push_back(params[paramptr++]);
-                                               }
-                                       }
-                               break;
-                       }
-               }
-               if (to_bounce.length())
-               {
-                       std::deque<std::string> newparams;
-                       newparams.push_back(params[0]);
-                       newparams.push_back(ConvToStr(ourTS));
-                       newparams.push_back(to_bounce+params_to_bounce);
-                       Utils->DoOneToOne(this->Instance->Config->ServerName,"FMODE",newparams,sourceserv);
-               }
-               if (to_keep.length())
+               if (smode)
                {
-                       unsigned int n = 2;
-                       unsigned int q = 0;
-                       modelist[0] = params[0].c_str();
-                       modelist[1] = to_keep.c_str();
-                       if (params_to_keep.size() > 0)
-                       {
-                               for (q = 0; (q < params_to_keep.size()) && (q < 64); q++)
-                               {
-                                       modelist[n++] = params_to_keep[q].c_str();
-                               }
-                       }
-                       if (smode)
-                       {
-                               this->Instance->SendMode(modelist, n, who);
-                       }
-                       else
-                       {
-                               this->Instance->CallCommandHandler("MODE", modelist, n, who);
-                       }
-                       /* HOT POTATO! PASS IT ON! */
-                       Utils->DoOneToAllButSender(source,"FMODE",params,sourceserv);
+                       this->Instance->SendMode(modelist, n, who);
                }
-       }
-       else
-       /* U-lined servers always win regardless of their TS */
-       if (TS > ourTS)
-       {
-               /* Bounce the mode back to its sender.* We use our lower TS, so the other end
-                * SHOULD accept it, if its clock is right.
-                *
-                * NOTE: We should check that we arent bouncing anything thats already set at this end.
-                * If we are, bounce +ourmode to 'reinforce' it. This prevents desyncs.
-                * e.g. They send +l 50, we have +l 10 set. rather than bounce -l 50, we bounce +l 10.
-                *
-                * Thanks to jilles for pointing out this one-hell-of-an-issue before i even finished
-                * writing the code. It took me a while to come up with this solution.
-                *
-                * XXX: BE SURE YOU UNDERSTAND THIS CODE FULLY BEFORE YOU MESS WITH IT.
-                */
-               std::deque<std::string> newparams;      /* New parameter list we send back */
-               newparams.push_back(params[0]);  /* Target, user or channel */
-               newparams.push_back(ConvToStr(ourTS));  /* Timestamp value of the target */
-               newparams.push_back("");                /* This contains the mode string. For now
-                                                        * it's empty, we fill it below.
-                                                        */
-               /* Intelligent mode bouncing. Don't just invert, reinforce any modes which are already
-                * set to avoid a desync here.
-                */
-               std::string modebounce = "";
-               bool adding = true;
-               unsigned int t = 3;
-               ModeHandler* mh = NULL;
-               char cur_change = 1;
-               char old_change = 0;
-               for (std::string::iterator x = params[2].begin(); x != params[2].end(); x++)
-               {
-                       /* Iterate over all mode chars in the sent set */
-                       switch (*x)
-                       {
-                               /* Adding or subtracting modes? */
-                               case '-':
-                                       adding = false;
-                               break;
-                               case '+':
-                                       adding = true;
-                               break;
-                               default:
-                                       /* Find the mode handler for this mode */
-                                       mh = this->Instance->Modes->FindMode(*x, chan ? MODETYPE_CHANNEL : MODETYPE_USER);
-                                       /* Got a mode handler?
-                                        * This also prevents us bouncing modes we have no handler for.
-                                        */
-                                       if (mh)
-                                       {
-                                               ModePair ret;
-                                               std::string p = "";
-                                               /* Does the mode require a parameter right now?
-                                                * If it does, fetch it if we can
-                                                */
-                                               if ((mh->GetNumParams(adding) > 0) && (t < params.size()))
-                                                       p = params[t++];
-                                               /* Call the ModeSet method to determine if its set with the
-                                                * given parameter here or not.
-                                                */
-                                               ret = mh->ModeSet(smode ? NULL : who, dst, chan, p);
-                                               /* XXX: Really. Dont ask.
-                                                * Determine from if its set combined with what the current
-                                                * 'state' is (adding or not) as to wether we should 'invert'
-                                                * or 'reinforce' the mode change
-                                                */
-                                               (!ret.first ? (adding ? cur_change = '-' : cur_change = '+') : (!adding ? cur_change = '-' : cur_change = '+'));
-                                               /* Quickly determine if we have 'flipped' from + to -,
-                                                * or - to +, to prevent unneccessary +/- chars in the
-                                                * output string that waste bandwidth
-                                                */
-                                               if (cur_change != old_change)
-                                                       modebounce += cur_change;
-                                               old_change = cur_change;
-                                               /* Add the mode character to the output string */
-                                               modebounce += mh->GetModeChar();
-                                               /* We got a parameter back from ModeHandler::ModeSet,
-                                                * are we supposed to be sending one out right now?
-                                                */
-                                               if (ret.second.length())
-                                               {
-                                                       if (mh->GetNumParams(cur_change == '+') > 0)
-                                                               /* Yes we're supposed to be sending out
-                                                                * the parameter. Make sure it goes
-                                                                */
-                                                               newparams.push_back(ret.second);
-                                               }
-                                       }
-                               break;
-                       }
-               }
-
-               /* Update the parameters for FMODE with the new 'bounced' string */
-               newparams[2] = modebounce;
-               /* Only send it back the way it came, no need to send it anywhere else */
-               Utils->DoOneToOne(this->Instance->Config->ServerName,"FMODE",newparams,sourceserv);
-       }
-       else
-       {
-               /* Allow the mode, route it to either server or user command handling */
-               if (smode)
-                       this->Instance->SendMode(modelist,n,who);
                else
+               {
                        this->Instance->CallCommandHandler("MODE", modelist, n, who);
+               }
                /* HOT POTATO! PASS IT ON! */
                Utils->DoOneToAllButSender(source,"FMODE",params,sourceserv);
        }
-       /* Are we supposed to free the userrec? */
+       /* If the TS is greater than ours, we drop the mode and dont pass it anywhere.
+        */
+
        if (smode)
                DELETE(who);
 
@@ -880,6 +689,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 */
@@ -897,6 +707,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.
@@ -921,18 +738,13 @@ 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]);
-       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);
+       irc::tokenstream users(nicklist);
+       std::string item;
+
        /* Now, process every 'prefixes,nick' pair */
-       while (item != "")
+       while (users.GetToken(item))
        {
                /* Find next user */
-               item = users.GetToken();
                const char* usr = item.c_str();
                /* Safety check just to make sure someones not sent us an FJOIN full of spaces
                 * (is this even possible?) */
@@ -1004,7 +816,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?
                                 */
@@ -1086,19 +901,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. :-)
         */
@@ -1108,25 +910,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;
@@ -1144,9 +981,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);
@@ -1171,7 +1006,9 @@ bool TreeSocket::IntroduceClient(const std::string &source, std::deque<std::stri
                _new->SetSockAddr(AF_INET, params[6].c_str(), 0);
 
        Instance->AddGlobalClone(_new);
-       this->Instance->SNO->WriteToSnoMask('C',"Client connecting at %s: %s!%s@%s [%s]",_new->server,_new->nick,_new->ident,_new->host, _new->GetIPString());
+
+       if (!this->Instance->SilentULine(_new->server))
+               this->Instance->SNO->WriteToSnoMask('C',"Client connecting at %s: %s!%s@%s [%s]",_new->server,_new->nick,_new->ident,_new->host, _new->GetIPString());
 
        params[7] = ":" + params[7];
        Utils->DoOneToAllButSender(source,"NICK", params, source);