示例#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 UID command handler
 *
 * \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/UID (without services support)
 *      - parv[0] = command
 *      - 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/UID (with services support)
 *      - parv[ 0] = command
 *      - 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 (account name)
 *      - parv[10] = ircname (gecos)
 */
static int
ms_uid(struct Client *source_p, int parc, char *parv[])
{
  struct Client *target_p = NULL;

  if (check_clean_nick(source_p, parv[1], source_p) ||
      check_clean_user(source_p, parv[1], parv[5], source_p) ||
      check_clean_host(source_p, parv[1], parv[6], source_p))
    return 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])))
  {
    sendto_realops_flags(UMODE_SERVNOTICE, L_ALL, SEND_NOTICE,
                         "ID collision on %s(%s <- %s)(both killed)",
                         target_p->name, target_p->from->name,
                         source_p->from->name);

    sendto_server(NULL, 0, 0, ":%s KILL %s :%s (ID collision)",
                  me.id, target_p->id, me.name);

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

  if ((target_p = hash_find_client(parv[1])) == NULL)
    uid_from_server(source_p, parc, parv);
  else if (IsUnknown(target_p))
  {
    exit_client(target_p, "Overridden by other sign on");
    uid_from_server(source_p, parc, parv);
  }
  else if (perform_uid_introduction_collides(source_p, target_p, parc, parv))
    uid_from_server(source_p, parc, parv);
  return 0;
}
示例#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);
}