Пример #1
0
/*! \brief UID command handler (called by servers)
 *
 * \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 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] = ip
 *  - parv[8] = uid
 *  - parv[9] = ircname (gecos)
 *
 * 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] = ip
 *  - parv[ 8] = uid
 *  - parv[ 9] = services id (timestamp)
 *  - parv[10] = ircname (gecos)
 */
static void
ms_uid(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 < 10 || EmptyString(parv[parc-1]))
    return;

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

  newts = atol(parv[3]);
  svsid = parc == 11 ? parv[9] : "0";

  /*
   * If there is an ID collision, kill our client, and kill theirs.
   * This may generate 401's, but it ensures that both clients always
   * go, even if the other server refuses to do the right thing.
   */
  if ((target_p = hash_find_id(parv[8])) != NULL)
  {
    sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
                         "ID collision on %s(%s <- %s)(both killed)",
                         target_p->name, target_p->from->name,
                         client_p->name);
    kill_client_ll_serv_butone(NULL, target_p, "%s (ID collision)",
                               me.name);

    ++ServerStats.is_kill;
    AddFlag(target_p, FLAGS_KILLED);
    exit_client(target_p, &me, "ID Collision");
    return;
  }

  if ((target_p = hash_find_client(parv[1])) == NULL)
    uid_from_server(client_p, source_p, parc, parv, newts, svsid, parv[1], parv[parc-1]);
  else if (IsUnknown(target_p))
  {
    exit_client(target_p, &me, "Overridden");
    uid_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], parv[8]);
}
Пример #2
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);
}
Пример #3
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);


}