Add a parameter to IPcheck_connect_fail() to support IAuth IP spoofing.
[ircu2.10.12-pk.git] / ircd / m_nick.c
index ef31e88c7f486784a8f63088b222f8e6c6e790ee..b612f8672b9e0cd42c4002b41c81c69589d04663 100644 (file)
@@ -87,6 +87,7 @@
 #include "ircd.h"
 #include "ircd_chattr.h"
 #include "ircd_features.h"
+#include "ircd_log.h"
 #include "ircd_reply.h"
 #include "ircd_string.h"
 #include "msg.h"
@@ -96,8 +97,9 @@
 #include "s_misc.h"
 #include "s_user.h"
 #include "send.h"
+#include "sys.h"
 
-#include <assert.h>
+/* #include <assert.h> -- Now using assert in ircd_log.h */
 #include <stdlib.h>
 #include <string.h>
 
@@ -144,27 +146,25 @@ int m_nick(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
   char           nick[NICKLEN + 2];
   char*          arg;
   char*          s;
-  const char*    client_name;
 
   assert(0 != cptr);
   assert(cptr == sptr);
 
-  /*
-   * parv[0] will be empty for clients connecting for the first time
-   */
-  client_name = (*(cli_name(sptr))) ? cli_name(sptr) : "*";
+  if (IsServerPort(cptr))
+    return exit_client(cptr, cptr, &me, "Use a different port");
 
   if (parc < 2) {
     send_reply(sptr, ERR_NONICKNAMEGIVEN);
     return 0;
   }
+
   /*
    * Don't let them send make us send back a really long string of
    * garbage
    */
   arg = parv[1];
-  if (strlen(arg) > NICKLEN)
-    arg[NICKLEN] = '\0';
+  if (strlen(arg) > IRCD_MIN(NICKLEN, feature_int(FEAT_NICKLEN)))
+    arg[IRCD_MIN(NICKLEN, feature_int(FEAT_NICKLEN))] = '\0';
 
   if ((s = strchr(arg, '~')))
     *s = '\0';
@@ -245,8 +245,8 @@ int m_nick(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
    * the message below.
    */
   if (IsUnknown(acptr) && MyConnect(acptr)) {
-    ++ServerStats->is_ref;
-    IPcheck_connect_fail(cli_ip(acptr));
+    ServerStats->is_ref++;
+    IPcheck_connect_fail(acptr, 0);
     exit_client(cptr, acptr, &me, "Overridden by other sign on");
     return set_nick_name(cptr, sptr, nick, parc, parv);
   }
@@ -318,7 +318,7 @@ int ms_nick(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
    * creation) then reject it. If from a server and we reject it,
    * and KILL it. -avalon 4/4/92
    */
-  if (strlen(nick) != do_nick_name(nick))
+  if (!do_nick_name(nick) || strcmp(nick, parv[1]))
   {
     send_reply(sptr, ERR_ERRONEUSNICKNAME, parv[1]);
     
@@ -376,7 +376,7 @@ int ms_nick(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
   if (IsUnknown(acptr) && MyConnect(acptr))
   {
     ServerStats->is_ref++;
-    IPcheck_connect_fail(cli_ip(acptr));
+    IPcheck_connect_fail(acptr, 0);
     exit_client(cptr, acptr, &me, "Overridden by other sign on");
     return set_nick_name(cptr, sptr, nick, parc, parv);
   }
@@ -400,13 +400,15 @@ int ms_nick(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
    */
   if (IsServer(sptr))
   {
+    struct irc_in_addr ip;
     /*
      * A new NICK being introduced by a neighbouring
      * server (e.g. message type ":server NICK new ..." received)
      *
      * compare IP address and username
      */
-    differ =  (cli_ip(acptr).s_addr != htonl(base64toint(parv[parc - 3]))) ||
+    base64toip(parv[parc - 3], &ip);
+    differ =  (0 != memcmp(&cli_ip(acptr), &ip, sizeof(cli_ip(acptr)))) ||
               (0 != ircd_strcmp(cli_user(acptr)->username, parv[4]));
     sendto_opmask_butone(0, SNO_OLDSNO, "Nick collision on %C (%C %Tu <- "
                         "%C %Tu (%s user@host))", acptr, cli_from(acptr),
@@ -420,13 +422,13 @@ int ms_nick(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
      *
      * compare IP address and username
      */
-    differ =  (cli_ip(acptr).s_addr != cli_ip(sptr).s_addr) ||
-              (0 != ircd_strcmp(cli_user(acptr)->username, cli_user(sptr)->username));              
+    differ =  (0 != memcmp(&cli_ip(acptr), &cli_ip(sptr), sizeof(cli_ip(acptr)))) ||
+              (0 != ircd_strcmp(cli_user(acptr)->username, cli_user(sptr)->username));
     sendto_opmask_butone(0, SNO_OLDSNO, "Nick change collision from %C to "
                         "%C (%C %Tu <- %C %Tu)", sptr, acptr, cli_from(acptr),
                         cli_lastnick(acptr), cptr, lastnick);
   }
-  type = differ ? "older nick overruled" : "nick collision from same user@host";
+  type = differ ? "overruled by older nick" : "nick collision from same user@host";
   /*
    * Now remove (kill) the nick on our side if it is the youngest.
    * If no timestamp was received, we ignore the incoming nick
@@ -439,40 +441,32 @@ int ms_nick(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
   if ((differ && lastnick >= cli_lastnick(acptr)) ||
       (!differ && lastnick <= cli_lastnick(acptr)))
   {
-    /* We need to bounce this kill straight back... Although the nick message
-     * for acptr is probably waiting in their recvq from me, its also possible
-     * that sptr will change their nick on cptr before cptr receives the
-     * nick message for acptr, which would leave acptr and sptr both alive
-     * on cptr, but only acptr alive on me, i.e. desync. This extra kill
-     * message has been absent for a while in ircu although it was a major
-     * problem when it was tried on efnet, so I don't know how big an issue it
-     * is. Probably best that this be left here, anyway...
-     */
     ServerStats->is_kill++;
-    sendcmdto_one(&me, CMD_KILL, cptr, "%s :%s (%s)",
-                  nick, cli_name(&me), type);
-    /* But if this was a nick change and not a nick introduction,
-     * we also need to ensure that we remove our local state
-     * record of the original client... Also, the rest of the
-     * net should be informed...
-     */
     if (!IsServer(sptr))
     {
+      /* If this was a nick change and not a nick introduction, we
+       * need to ensure that we remove our record of the client, and
+       * send a KILL to the whole network.
+       */
       assert(!MyConnect(sptr));
       /* Inform the rest of the net... */
-      sendcmdto_serv_butone(&me, CMD_KILL, cptr, "%s :%s (%s)",
-                            nick, cli_name(&me), type);
+      sendcmdto_serv_butone(&me, CMD_KILL, 0, "%C :%s (%s)",
+                            sptr, cli_name(&me), type);
       /* Don't go sending off a QUIT message... */
       SetFlag(sptr, FLAG_KILLED);
       /* Remove them locally. */
       exit_client_msg(cptr, sptr, &me,
                       "Killed (%s (%s))",
                       feature_str(FEAT_HIS_SERVERNAME), type);
-      /*
-       * We have killed sptr off, zero out it's pointer so if it's used
-       * again we'll know about it --Bleep
+    }
+    else
+    {
+      /* If the origin is a server, this was a new client, so we only
+       * send the KILL in the direction it came from.  We have no
+       * client record that we would have to clean up.
        */
-      sptr = NULL;
+      sendcmdto_one(&me, CMD_KILL, cptr, "%s :%s (%s)",
+                    parv[parc - 2], cli_name(&me), type);
     }
     /* If the timestamps differ and we just killed sptr, we don't need to kill
      * acptr as well.
@@ -488,8 +482,8 @@ int ms_nick(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
   /*
    * This exits the client we had before getting the NICK message
    */
-  sendcmdto_serv_butone(&me, CMD_KILL, NULL, "%C :%s"
-                        " (%s)", acptr, feature_str(FEAT_HIS_SERVERNAME),
+  sendcmdto_serv_butone(&me, CMD_KILL, NULL, "%C :%s (%s)",
+                        acptr, feature_str(FEAT_HIS_SERVERNAME),
                         type);
   exit_client_msg(cptr, acptr, &me, "Killed (%s (%s))",
                   feature_str(FEAT_HIS_SERVERNAME), type);