Ejemplo n.º 1
0
/*! \brief NICK command handler (called by servers and remotely
 *         connected clients)
 *
 * \param client_p Pointer to allocated Client struct with physical connection
 *                 to this server, i.e. with an open socket connected.
 * \param source_p Pointer to allocated Client struct from which the message
 *                 originally comes from.  This can be a local or remote client.
 * \param parc     Integer holding the number of supplied arguments.
 * \param parv     Argument vector where parv[0] .. parv[parc-1] are non-NULL
 *                 pointers.
 * \note Valid arguments for this command are:
 *
 * server -> server nick change
 *  - parv[0] = sender prefix
 *  - parv[1] = nickname
 *  - parv[2] = TS when nick change
 *
 * server introducing new nick (without services support)
 *  - parv[0] = sender prefix
 *  - parv[1] = nickname
 *  - parv[2] = hop count
 *  - parv[3] = TS
 *  - parv[4] = umode
 *  - parv[5] = username
 *  - parv[6] = hostname
 *  - parv[7] = server
 *  - parv[8] = ircname
 *
 * server introducing new nick (with services support)
 *  - parv[0] = sender prefix
 *  - parv[1] = nickname
 *  - parv[2] = hop count
 *  - parv[3] = TS
 *  - parv[4] = umode
 *  - parv[5] = username
 *  - parv[6] = hostname
 *  - parv[7] = server
 *  - parv[8] = services id (timestamp)
 *  - parv[9] = ircname
 */
static void
ms_nick(struct Client *client_p, struct Client *source_p,
        int parc, char *parv[])
{
  struct Client *target_p = NULL;
  time_t newts = 0;
  const char *svsid = "0";

  if (parc < 3 || EmptyString(parv[parc - 1]))
    return;

  if (parc >= 9)
  {
    struct Client *server_p = hash_find_server(parv[7]);

    if (server_p == NULL)
    {
      sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
                           "Invalid server %s from %s for NICK %s",
                           parv[7], source_p->name, parv[1]);
      sendto_one(client_p, ":%s KILL %s :%s (Server doesn't exist!)",
                 me.name, parv[1], me.name);
      return;
    }

    if (check_clean_nick(client_p, source_p, parv[1], server_p) ||
        check_clean_user(client_p, parv[1], parv[5], server_p) ||
        check_clean_host(client_p, parv[1], parv[6], server_p))
      return;

    if (IsServer(source_p))
      newts = atol(parv[3]);
    if (IsServer(source_p) && parc == 10)
      svsid = parv[8];
  }
  else if (parc == 3)
  {
    if (IsServer(source_p))
      /* Servers can't change nicks.. */
      return;

    if (check_clean_nick(client_p, source_p, parv[1],
                         source_p->servptr))
      return;

    newts = atol(parv[2]);
  }

  /* If the nick doesnt exist, allow it and process like normal */
  if ((target_p = hash_find_client(parv[1])) == NULL)
    nick_from_server(client_p, source_p, parc, parv, newts, svsid, parv[1], parv[parc-1]);
  else if (IsUnknown(target_p))
  {
    /* We're not living in the past anymore, an unknown client is local only. */
    exit_client(target_p, &me, "Overridden");
    nick_from_server(client_p, source_p, parc, parv, newts, svsid, parv[1], parv[parc-1]);
  }
  else if (target_p == source_p)
  {
    if (strcmp(target_p->name, parv[1]))
      nick_from_server(client_p, source_p, parc, parv, newts, svsid, parv[1], parv[parc-1]);
  }
  else
    perform_nick_collides(source_p, client_p, target_p, parc, parv,
                          newts, svsid, parv[1], parv[parc-1], NULL);
}
Ejemplo n.º 2
0
static int
perform_nick_collides(struct Client *source_p, struct Client *client_p,
		      struct Client *target_p, int parc, char *parv[], time_t newts, char *nick)
{
	int sameuser;

	/* server introducing new nick */
	if(IsServer(source_p))
	{
		/* if we dont have a ts, or their TS's are the same, kill both */
		if(!newts || !target_p->tsinfo || (newts == target_p->tsinfo))
		{
			sendto_realops_flags(UMODE_ALL, L_ALL,
					     "Nick collision on %s(%s <- %s)(both killed)",
					     target_p->name, target_p->from->name, client_p->name);

			kill_client_serv_butone(NULL, target_p,
						"%s (Nick collision (new))", me.name);
			ServerStats->is_kill++;
			sendto_one(target_p, form_str(ERR_NICKCOLLISION),
				   me.name, target_p->name, target_p->name);

			target_p->flags |= FLAGS_KILLED;
			exit_client(client_p, target_p, &me, "Nick collision (new)");
			return 0;
		}
		/* the timestamps are different */
		else
		{
			sameuser = (target_p->user) && !irccmp(target_p->username, parv[5])
				&& !irccmp(target_p->host, parv[6]);

			/* if the users are the same (loaded a client on a different server)
			 * and the new users ts is older, or the users are different and the
			 * new users ts is newer, ignore the new client and let it do the kill
			 */
			if((sameuser && newts < target_p->tsinfo) ||
			   (!sameuser && newts > target_p->tsinfo))
			{
				return 0;
			}
			else
			{
				if(sameuser)
					sendto_realops_flags(UMODE_ALL, L_ALL,
							     "Nick collision on %s(%s <- %s)(older killed)",
							     target_p->name, target_p->from->name,
							     client_p->name);
				else
					sendto_realops_flags(UMODE_ALL, L_ALL,
							     "Nick collision on %s(%s <- %s)(newer killed)",
							     target_p->name, target_p->from->name,
							     client_p->name);

				ServerStats->is_kill++;
				sendto_one(target_p, form_str(ERR_NICKCOLLISION),
					   me.name, target_p->name, target_p->name);

				/* if it came from a LL server, itd have been source_p,
				 * so we dont need to mark target_p as known
				 */
				kill_client_serv_butone(source_p, target_p,
							"%s (Nick collision (new))", me.name);

				target_p->flags |= FLAGS_KILLED;
				(void) exit_client(client_p, target_p, &me, "Nick collision");

				nick_from_server(client_p, source_p, parc, parv, newts, nick);
				return 0;
			}
		}
	}

	/* its a client changing nick and causing a collide */
	if(!newts || !target_p->tsinfo || (newts == target_p->tsinfo) || !source_p->user)
	{
		sendto_realops_flags(UMODE_ALL, L_ALL,
				     "Nick change collision from %s to %s(%s <- %s)(both killed)",
				     source_p->name, target_p->name, target_p->from->name,
				     client_p->name);

		ServerStats->is_kill++;
		sendto_one(target_p, form_str(ERR_NICKCOLLISION),
			   me.name, target_p->name, target_p->name);

		/* if we got the message from a LL, it knows about source_p */
		kill_client_serv_butone(NULL, source_p, "%s (Nick change collision)", me.name);

		ServerStats->is_kill++;

		kill_client_serv_butone(NULL, target_p, "%s (Nick change collision)", me.name);

		target_p->flags |= FLAGS_KILLED;
		exit_client(NULL, target_p, &me, "Nick collision(new)");
		source_p->flags |= FLAGS_KILLED;
		exit_client(client_p, source_p, &me, "Nick collision(old)");
		return 0;
	}
	else
	{
		sameuser = !irccmp(target_p->username, source_p->username) &&
			!irccmp(target_p->host, source_p->host);

		if((sameuser && newts < target_p->tsinfo) ||
		   (!sameuser && newts > target_p->tsinfo))
		{
			if(sameuser)
				sendto_realops_flags(UMODE_ALL, L_ALL,
						     "Nick change collision from %s to %s(%s <- %s)(older killed)",
						     source_p->name, target_p->name,
						     target_p->from->name, client_p->name);
			else
				sendto_realops_flags(UMODE_ALL, L_ALL,
						     "Nick change collision from %s to %s(%s <- %s)(newer killed)",
						     source_p->name, target_p->name,
						     target_p->from->name, client_p->name);

			ServerStats->is_kill++;

			/* this won't go back to the incoming link, so LL doesnt matter */
			kill_client_serv_butone(client_p, source_p,
						"%s (Nick change collision)", me.name);

			source_p->flags |= FLAGS_KILLED;

			if(sameuser)
				exit_client(client_p, source_p, &me, "Nick collision(old)");
			else
				exit_client(client_p, source_p, &me, "Nick collision(new)");
			return 0;
		}
		else
		{
			if(sameuser)
				sendto_realops_flags(UMODE_ALL, L_ALL,
						     "Nick collision on %s(%s <- %s)(older killed)",
						     target_p->name, target_p->from->name,
						     client_p->name);
			else
				sendto_realops_flags(UMODE_ALL, L_ALL,
						     "Nick collision on %s(%s <- %s)(newer killed)",
						     target_p->name, target_p->from->name,
						     client_p->name);

			kill_client_serv_butone(source_p, target_p, "%s (Nick collision)", me.name);

			ServerStats->is_kill++;
			sendto_one(target_p, form_str(ERR_NICKCOLLISION),
				   me.name, target_p->name, target_p->name);

			target_p->flags |= FLAGS_KILLED;
			(void) exit_client(client_p, target_p, &me, "Nick collision");
		}
	}

	/* we should only ever call nick_from_server() here, as
	 * this is a client changing nick, not a new client
	 */
	nick_from_server(client_p, source_p, parc, parv, newts, nick);

	return 0;
}
Ejemplo n.º 3
0
static void
perform_nick_collides(struct Client *source_p, struct Client *client_p, 
                      struct Client *target_p, int parc, char *parv[], 
                      time_t newts, const char *svsid, char *nick, char *gecos, char *uid)
{
  int sameuser = 0;
  
  /* Server introducing new nick */
  if (IsServer(source_p))
  {
    /* If we don't have a TS, or their TS's are the same, kill both */
    if (!newts || !target_p->tsinfo || (newts == target_p->tsinfo))
    {
      sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
                           "Nick collision on %s(%s <- %s)(both killed)",
                           target_p->name, target_p->from->name,
                           client_p->name);
      
      /* if we have a UID, issue a kill for it */
      if (uid)
        sendto_one(client_p, ":%s KILL %s :%s (Nick collision (new))",
                   me.id, uid, me.name);

      kill_client_ll_serv_butone(NULL, target_p,
                                 "%s (Nick collision (new))", me.name);
      ++ServerStats.is_kill;
      sendto_one(target_p, form_str(ERR_NICKCOLLISION),
                 me.name, target_p->name, target_p->name);

      AddFlag(target_p, FLAGS_KILLED);
      exit_client(target_p, &me, "Nick collision (new)");
      return;
    }
    /* the timestamps are different */
    else
    {
      sameuser = !irccmp(target_p->username, parv[5]) &&
                 !irccmp(target_p->host, parv[6]);
   
      /*
       * If the users are the same (loaded a client on a different server)
       * and the new users ts is older, or the users are different and the
       * new users ts is newer, ignore the new client and let it do the kill
       */
      if ((sameuser && newts < target_p->tsinfo) ||
         (!sameuser && newts > target_p->tsinfo))
      {
        if (uid)
          sendto_one(client_p, ":%s KILL %s :%s (Nick collision (new))",
                     me.id, uid, me.name);
        return;
      }
      else
      {
        if (sameuser)
          sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
                               "Nick collision on %s(%s <- %s)(older killed)",
                               target_p->name, target_p->from->name,
                               client_p->name);
        else
          sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
                               "Nick collision on %s(%s <- %s)(newer killed)",
                               target_p->name, target_p->from->name,
                               client_p->name);

        ++ServerStats.is_kill;
        sendto_one(target_p, form_str(ERR_NICKCOLLISION),
                   me.name, target_p->name, target_p->name);

        /* if it came from a LL server, itd have been source_p,
         * so we dont need to mark target_p as known
         */
        kill_client_ll_serv_butone(source_p, target_p,
                                   "%s (Nick collision (new))", me.name);

        AddFlag(target_p, FLAGS_KILLED);
        exit_client(target_p, &me, "Nick collision");

        if (!uid && (parc == 9 || parc == 10))
          nick_from_server(client_p, source_p, parc, parv, newts, svsid, nick, gecos);
        else if (uid && (parc == 10 || parc == 11))
          uid_from_server(client_p, source_p, parc, parv, newts, svsid, nick, gecos);
        return;
      }
    }
  }

  /* its a client changing nick and causing a collide */
  if (!newts || !target_p->tsinfo || (newts == target_p->tsinfo))
  {
      sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
                 "Nick change collision from %s to %s(%s <- %s)(both killed)",
                 source_p->name, target_p->name, target_p->from->name,
                 client_p->name);
    
      sendto_one(target_p, form_str(ERR_NICKCOLLISION), me.name,
                 target_p->name, target_p->name);

      ++ServerStats.is_kill;
      kill_client_ll_serv_butone(NULL, source_p, "%s (Nick change collision)",
                                 me.name);

      ++ServerStats.is_kill;
      kill_client_ll_serv_butone(NULL, target_p, "%s (Nick change collision)",
                                 me.name);

      AddFlag(target_p, FLAGS_KILLED);
      exit_client(target_p, &me, "Nick collision (new)");

      AddFlag(source_p, FLAGS_KILLED);
      exit_client(source_p, &me, "Nick collision (old)");
      return;
  }
  else
  {
    sameuser = !irccmp(target_p->username, source_p->username) &&
               !irccmp(target_p->host, source_p->host);

    if ((sameuser && newts < target_p->tsinfo) ||
        (!sameuser && newts > target_p->tsinfo))
    {
      if (sameuser)
        sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
             "Nick change collision from %s to %s(%s <- %s)(older killed)",
             source_p->name, target_p->name, target_p->from->name,
             client_p->name);
      else
        sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
             "Nick change collision from %s to %s(%s <- %s)(newer killed)",
             source_p->name, target_p->name, target_p->from->name,
             client_p->name);

      ++ServerStats.is_kill;
      kill_client_ll_serv_butone(client_p, source_p,
                                 "%s (Nick change collision)", me.name);
      AddFlag(source_p, FLAGS_KILLED);

      if (sameuser)
        exit_client(source_p, &me, "Nick collision (old)");
      else
        exit_client(source_p, &me, "Nick collision (new)");
      return;
    }
    else
    {
      if (sameuser)
        sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
                             "Nick collision on %s(%s <- %s)(older killed)",
                             target_p->name, target_p->from->name,
                             client_p->name);
      else
        sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
                             "Nick collision on %s(%s <- %s)(newer killed)",
                             target_p->name, target_p->from->name,
                             client_p->name);

      kill_client_ll_serv_butone(source_p, target_p,
                                 "%s (Nick collision)", me.name);

      ++ServerStats.is_kill;
      sendto_one(target_p, form_str(ERR_NICKCOLLISION),
                 me.name, target_p->name, target_p->name);

      AddFlag(target_p, FLAGS_KILLED);
      exit_client(target_p, &me, "Nick collision");
    }
  }

  /*
   * we should only ever call nick_from_server() here, as
   * this is a client changing nick, not a new client
   */
  nick_from_server(client_p, source_p, parc, parv, newts, svsid, nick, gecos);
}
Ejemplo n.º 4
0
/*
 * ms_nick()
 *      
 * server -> server nick change
 *    parv[0] = sender prefix
 *    parv[1] = nickname
 *    parv[2] = TS when nick change
 *
 * server introducing new nick
 *    parv[0] = sender prefix
 *    parv[1] = nickname
 *    parv[2] = hop count
 *    parv[3] = TS
 *    parv[4] = umode
 *    parv[5] = username
 *    parv[6] = hostname
 *    parv[7] = server
 *    parv[8] = ircname
 */
static void
ms_nick(struct Client *client_p, struct Client *source_p, int parc, char *parv[])
{
	struct Client *target_p;
	char nick[NICKLEN];
	time_t newts = 0;

	if(parc < 2 || BadPtr(parv[1]))
	{
		sendto_one(source_p, form_str(ERR_NONICKNAMEGIVEN), me.name, parv[0]);
		return;
	}

	/* parc == 3 on nickchange, parc == 9 on new nick */
	if((IsClient(source_p) && (parc != 3)) || (IsServer(source_p) && ((parc != 9) && (parc != 10))))
	{
		char tbuf[BUFSIZE] = { 0 };
		int j;

		for (j = 0; j < parc; j++)
		{
			strcat(tbuf, parv[j]);
			strcat(tbuf, " ");
		}

		sendto_realops_flags(UMODE_ALL, L_ALL,
				     "Dropping server %s due to (invalid) command 'NICK' "
				     "with only %d arguments.  (Buf: '%s')",
				     client_p->name, parc, tbuf);
		ilog(L_CRIT, "Insufficient parameters (%d) for command 'NICK' from %s.  Buf: %s",
		     parc, client_p->name, tbuf);
		exit_client(client_p, client_p, client_p,
			    "Not enough arguments to server command.");
		return;
	}

	/* fix the length of the nick */
	strlcpy(nick, parv[1], sizeof(nick));

    if ((parc == 9) || (parc == 10))
	{
		if (check_clean_nick(client_p, source_p, nick, parv[1], parv[7]))
			return;
	}
	else
	{
		if (check_clean_nick(client_p, source_p, nick, parv[1], (char *)source_p->user->server))
			return;
	}

	if(parc == 9 || parc == 10)
	{
		if(check_clean_user(client_p, nick, parv[5], parv[7]) ||
		   check_clean_host(client_p, nick, parv[6], parv[7]))
			return;

		/* check the length of the clients gecos */
		if(strlen(parv[(parc > 9)? 9 : 8]) > REALLEN)
		{
			sendto_realops_flags(UMODE_ALL, L_ALL,
					     "Long realname from server %s for %s", parv[7],
					     parv[1]);
			parv[(parc > 9)? 9 : 8][REALLEN] = '\0';
		}

		if(IsServer(source_p))
			newts = atol(parv[3]);
	}
	else
	{
		if(!IsServer(source_p))
			newts = atol(parv[2]);
	}

	/* if the nick doesnt exist, allow it and process like normal */
	if(!(target_p = find_client(nick)))
	{
		nick_from_server(client_p, source_p, parc, parv, newts, nick);
		return;
	}

	/* we're not living in the past anymore, an unknown client is local only. */
	if(IsUnknown(target_p))
	{
		exit_client(NULL, target_p, &me, "Overridden");
		nick_from_server(client_p, source_p, parc, parv, newts, nick);
		return;
	}

	if(target_p == source_p)
	{
		if(strcmp(target_p->name, nick))
		{
			/* client changing case of nick */
			nick_from_server(client_p, source_p, parc, parv, newts, nick);
			return;
		}
		else
			/* client not changing nicks at all */
			return;
	}

	perform_nick_collides(source_p, client_p, target_p, parc, parv, newts, nick);


}