示例#1
0
static void
m_identify(struct Client *client_p, struct Client *source_p,
           int parc, char *parv[])
{
  struct Client *target_p = NULL;

  if (EmptyString(parv[1]))
  {
    sendto_one(source_p, form_str(ERR_NOTEXTTOSEND),
               me.name, source_p->name);
    return;
  }

  if (IsChanPrefix(*parv[1]))
  {
    if ((target_p = hash_find_server(ConfigFileEntry.service_name)))
      sendto_one(target_p, ":%s PRIVMSG ChanServ@%s :IDENTIFY %s",
                 source_p->name, ConfigFileEntry.service_name, parv[1]);
    else
      sendto_one(source_p, form_str(ERR_SERVICESDOWN),
                 me.name, source_p->name, "ChanServ");
  }
  else
  {
    if ((target_p = hash_find_server(ConfigFileEntry.service_name)))
      sendto_one(target_p, ":%s PRIVMSG NickServ@%s :IDENTIFY %s",
                 source_p->name, ConfigFileEntry.service_name, parv[1]);
    else
      sendto_one(source_p, form_str(ERR_SERVICESDOWN),
                 me.name, source_p->name, "NickServ");
  }
}
示例#2
0
static void
m_chanserv(struct Client *client_p, struct Client *source_p,
           int parc, char *parv[])
{
  struct Client *target_p = NULL;

  assert(client_p && source_p);
  assert(client_p == source_p);

  if (EmptyString(parv[1]))
  {
    sendto_one(source_p, form_str(ERR_NOTEXTTOSEND),
               me.name, source_p->name);
    return;
  }

  if ((target_p = hash_find_server(ConfigFileEntry.service_name)))
  {
    sendto_one(target_p, ":%s PRIVMSG ChanServ@%s :%s",
               source_p->name, ConfigFileEntry.service_name, parv[1]);
    return;
  }

  sendto_one(source_p, form_str(ERR_SERVICESDOWN),
             me.name, source_p->name, "ChanServ");
}
示例#3
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);
}
示例#4
0
/* handle_special()
 *
 * inputs	- client pointer
 *		- nick stuff to grok for opers
 *		- text to send if grok
 * output	- none
 * side effects	- old style username@server is handled here for non opers
 *		  opers are allowed username%hostname@server
 *		  all the traditional oper type messages are also parsed here.
 *		  i.e. "/msg #some.host."
 *		  However, syntax has been changed.
 *		  previous syntax "/msg #some.host.mask"
 *		  now becomes     "/msg $#some.host.mask"
 *		  previous syntax of: "/msg $some.server.mask" remains
 *		  This disambiguates the syntax.
 *
 * XXX		  N.B. dalnet changed it to nick@server as have other servers.
 *		  we will stick with tradition for now.
 *		- Dianora
 */
static void
handle_special(int p_or_n, const char *command, struct Client *source_p,
               const char *nick, const char *text)
{
  struct Client *target_p = NULL;
  const char *server = NULL, *s = NULL;

  /*
   * user[%host]@server addressed?
   */
  if ((server = strchr(nick, '@')))
  {
    if ((target_p = hash_find_server(server + 1)) == NULL)
    {
      sendto_one_numeric(source_p, &me, ERR_NOSUCHSERVER, server + 1);
      return;
    }

    if (!HasUMode(source_p, UMODE_OPER) && strchr(nick, '%'))
    {
      sendto_one_numeric(source_p, &me, ERR_NOSUCHNICK, nick);
      return;
    }

    if (!IsMe(target_p))
    {
      sendto_one(target_p, ":%s %s %s :%s", source_p->id, command, nick, text);
      return;
    }

    sendto_one_numeric(source_p, &me, ERR_NOSUCHNICK, nick);
    return;
  }

  if (!HasUMode(source_p, UMODE_OPER))
  {
    sendto_one_numeric(source_p, &me, ERR_NOPRIVILEGES);
    return;
  }

  /*
   * The following two cases allow masks in NOTICEs
   * (for OPERs only)
   *
   * Armin, 8Jun90 ([email protected])
   */
  if (*nick == '$')
  {
    if (*(nick + 1) == '$' || *(nick + 1) == '#')
      ++nick;
    else if (MyClient(source_p))
    {
      sendto_one_notice(source_p, &me, ":The command %s %s is no longer supported, please use $%s",
                        command, nick, nick);
      return;
    }

    if ((s = strrchr(nick, '.')) == NULL)
    {
      sendto_one_numeric(source_p, &me, ERR_NOTOPLEVEL, nick);
      return;
    }

    while (*++s)
      if (*s == '.' || *s == '*' || *s == '?')
        break;

    if (*s == '*' || *s == '?')
    {
      sendto_one_numeric(source_p, &me, ERR_WILDTOPLEVEL, nick);
      return;
    }

    sendto_match_butone(IsServer(source_p->from) ? source_p->from : NULL, source_p,
                        nick + 1, (*nick == '#') ? MATCH_HOST : MATCH_SERVER,
                        "%s $%s :%s", command, nick, text);
  }
}
示例#5
0
/*! \brief CONNECT 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:
 *      - parv[0] = command
 *      - parv[1] = target server
 *      - parv[2] = port number
 *      - parv[3] = nickname/servername
 */
static int
mo_connect(struct Client *source_p, int parc, char *parv[])
{
  int port = 0, tmpport = 0;
  struct MaskItem *conf = NULL;
  const struct Client *target_p = NULL;

  if (EmptyString(parv[1]))
  {
    sendto_one_numeric(source_p, &me, ERR_NEEDMOREPARAMS, "CONNECT");
    return 0;
  }

  if (parc > 3)
  {
    if (!HasOFlag(source_p, OPER_FLAG_CONNECT_REMOTE))
    {
      sendto_one_numeric(source_p, &me, ERR_NOPRIVS, "connect:remote");
      return 0;
    }

    if (hunt_server(source_p, ":%s CONNECT %s %s :%s", 3, parc, parv) != HUNTED_ISME)
      return 0;
  }
  else if (!HasOFlag(source_p, OPER_FLAG_CONNECT))
  {
    sendto_one_numeric(source_p, &me, ERR_NOPRIVS, "connect");
    return 0;
  }

  /*
   * Try to find the name, then host, if both fail notify ops and bail
   */
  if (!(conf = find_matching_name_conf(CONF_SERVER, parv[1], NULL, NULL, 0)) &&
      !(conf = find_matching_name_conf(CONF_SERVER, NULL, NULL, parv[1], 0)))
  {
    sendto_one_notice(source_p, &me, ":Connect: Host %s not listed in configuration file", parv[1]);
    return 0;
  }

  if ((target_p = hash_find_server(conf->name)))
  {
    sendto_one_notice(source_p, &me, ":Connect: Server %s already exists from %s.",
                      target_p->name, target_p->from->name);
    return 0;
  }

  /*
   * Get port number from user, if given. If not specified,
   * use the default from configuration structure. If missing
   * from there, then use the precompiled default.
   */
  tmpport = port = conf->port;

  if (parc > 2 && !EmptyString(parv[2]))
  {
    if ((port = atoi(parv[2])) <= 0)
    {
      sendto_one_notice(source_p, &me, ":Connect: Illegal port number");
      return 0;
    }
  }
  else if (port <= 0 && (port = PORTNUM) <= 0)
  {
    sendto_one_notice(source_p, &me, ":Connect: missing port number");
    return 0;
  }

  if (find_servconn_in_progress(conf->name))
  {
    sendto_one_notice(source_p, &me, ":Connect: a connection to %s "
                      "is already in progress.", conf->name);
    return 0;
  }

  /*
   * Notify all operators about remote connect requests
   */
  ilog(LOG_TYPE_IRCD, "CONNECT From %s : %s %s",
       source_p->name, parv[1], parv[2] ? parv[2] : "");

  conf->port = port;

  /*
   * At this point we should be calling connect_server with a valid
   * connect{} block and a valid port in the connect{} block
   */
  if (serv_connect(conf, source_p))
  {
    if (!ConfigServerHide.hide_server_ips && HasUMode(source_p, UMODE_ADMIN))
      sendto_one_notice(source_p, &me, ":*** Connecting to %s[%s].%d",
                        conf->host, conf->name, conf->port);
    else
      sendto_one_notice(source_p, &me, ":*** Connecting to %s.%d",
                        conf->name, conf->port);
  }
  else
    sendto_one_notice(source_p, &me, ":*** Couldn't connect to %s.%d",
                      conf->name, conf->port);

  /*
   * Client is either connecting with all the data it needs or has been
   * destroyed
   */
  conf->port = tmpport;
  return 0;
}
示例#6
0
/*! \brief CONNECT 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:
 *      - parv[0] = command
 *      - parv[1] = target server
 *      - parv[2] = port number
 *      - parv[3] = nickname/servername
 */
static int
ms_connect(struct Client *source_p, int parc, char *parv[])
{
  int port = 0, tmpport = 0;
  struct MaskItem *conf = NULL;
  const struct Client *target_p = NULL;

  if (parc < 4 || EmptyString(parv[3]))
  {
    sendto_one_numeric(source_p, &me, ERR_NEEDMOREPARAMS, "CONNECT");
    return 0;
  }

  if (hunt_server(source_p, ":%s CONNECT %s %s :%s", 3, parc, parv) != HUNTED_ISME)
    return 0;

  /*
   * Try to find the name, then host, if both fail notify ops and bail
   */
  if (!(conf = find_matching_name_conf(CONF_SERVER, parv[1], NULL, NULL, 0)) &&
      !(conf = find_matching_name_conf(CONF_SERVER, NULL, NULL, parv[1], 0)))
  {
    sendto_one_notice(source_p, &me, ":Connect: Host %s not listed in configuration file", parv[1]);
    return 0;
  }

  if ((target_p = hash_find_server(conf->name)))
  {
    sendto_one_notice(source_p, &me, ":Connect: Server %s already exists from %s.",
                      target_p->name, target_p->from->name);
    return 0;
  }

  /*
   * Get port number from user, if given. If not specified,
   * use the default from configuration structure. If missing
   * from there, then use the precompiled default.
   */
  tmpport = port = conf->port;

  if (parc > 2 && !EmptyString(parv[2]))
  {
    port = atoi(parv[2]);

    /*
     * If someone sends port 0, and we have a config port.. use it
     */
    if (port == 0 && conf->port)
      port = conf->port;
    else if (port <= 0)
    {
      sendto_one_notice(source_p, &me, ":Connect: Illegal port number");
      return 0;
    }
  }
  else if (port <= 0 && (port = PORTNUM) <= 0)
  {
    sendto_one_notice(source_p, &me, ":Connect: missing port number");
    return 0;
  }

  if (find_servconn_in_progress(conf->name))
  {
    sendto_one_notice(source_p, &me, ":Connect: a connection to %s "
                      "is already in progress.", conf->name);
    return 0;
  }

  /*
   * Notify all operators about remote connect requests
   */
  sendto_realops_flags(UMODE_ALL, L_ALL, SEND_GLOBAL, "from %s: Remote CONNECT %s %d from %s",
                       me.name, parv[1], port, source_p->name);
  sendto_server(NULL, 0, 0,
                ":%s GLOBOPS :Remote CONNECT %s %d from %s",
                me.id, parv[1], port, source_p->name);

  ilog(LOG_TYPE_IRCD, "CONNECT From %s : %s %d",
       source_p->name, parv[1], port);

  conf->port = port;

  /*
   * At this point we should be calling connect_server with a valid
   * connect{} block and a valid port in the connect{} block
   */
  if (serv_connect(conf, source_p))
    sendto_one_notice(source_p, &me, ":*** Connecting to %s.%d",
                      conf->name, conf->port);
  else
    sendto_one_notice(source_p, &me, ":*** Couldn't connect to %s.%d",
                      conf->name, conf->port);
  /*
   * Client is either connecting with all the data it needs or has been
   * destroyed
   */
  conf->port = tmpport;
  return 0;
}