Exemple #1
0
static void
me_undline(struct Client *client_p, struct Client *source_p,
           int parc, char *parv[])
{
  const char *addr = NULL;

  if (parc != 3 || EmptyString(parv[2]))
    return;

  addr = parv[2];

  if (!IsClient(source_p) || match(parv[1], me.name))
    return;

  if (HasFlag(source_p, FLAGS_SERVICE) || find_matching_name_conf(CONF_ULINE,
                                   source_p->servptr->name,
                                   source_p->username, source_p->host,
                                   SHARED_UNDLINE))
  {
    if (remove_dline_match(addr))
    {
      sendto_one(source_p,
                 ":%s NOTICE %s :D-Line for [%s] is removed",
                 me.name, source_p->name, addr);
      sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
                           "%s has removed the D-Line for: [%s]",
                           get_oper_name(source_p), addr);
      ilog(LOG_TYPE_DLINE, "%s removed temporary D-Line for [%s]",
           get_oper_name(source_p), addr);
    }
    else
      sendto_one(source_p, ":%s NOTICE %s :No D-Line for [%s] found",
                 me.name, source_p->name, addr);
  }
}
Exemple #2
0
/*! \brief REHASH 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 mask
 *      - parv[2] = option [CONF, DNS, MOTD]
 */
static int
ms_rehash(struct Client *source_p, int parc, char *parv[])
{
  const char *const option = parv[2];
  const char *const server = parv[1];

  sendto_match_servs(source_p, server, 0, "REHASH %s %s", server, option);

  if (match(server, me.name))
    return 0;

  if (!find_matching_name_conf(CONF_SHARED, source_p->servptr->name,
                               source_p->username, source_p->host,
                               SHARED_REHASH))
    return 0;

  for (const struct RehashStruct *tab = rehash_cmd_table; tab->handler; ++tab)
  {
    if (irccmp(tab->option, option))
      continue;

    tab->handler(source_p);
    return 0;
  }

  return 0;
}
Exemple #3
0
/*! \brief NICK command handler (called by unregistered,
 *         locally 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:
 *      - parv[0] = sender prefix
 *      - parv[1] = nickname
 */
static void
mr_nick(struct Client *client_p, struct Client *source_p,
        int parc, char *parv[])
{
  char nick[NICKLEN + 1] = { '\0' };
  char *s = NULL;
  struct Client *target_p = NULL;
  struct MaskItem *conf = NULL;

  if (parc < 2 || EmptyString(parv[1]))
  {
    sendto_one(source_p, form_str(ERR_NONICKNAMEGIVEN), me.name,
               source_p->name[0] ? source_p->name : "*");
    return;
  }

  /* Terminate the nick at the first ~ */
  if ((s = strchr(parv[1], '~')) != NULL)
    *s = '\0';

  /* Copy the nick and terminate it */
  strlcpy(nick, parv[1], IRCD_MIN(sizeof(nick), ServerInfo.max_nick_length + 1));

  /* Check the nickname is ok */
  if (!valid_nickname(nick, 1))
  {
    sendto_one(source_p, form_str(ERR_ERRONEUSNICKNAME), me.name,
               source_p->name[0] ? source_p->name : "*", parv[1],
               "Erroneous Nickname");
    return;
  }

  /* Check if the nick is resv'd */
  if ((conf = find_matching_name_conf(CONF_NRESV, nick, NULL, NULL, 0)))
  {
    ++conf->count;
    sendto_one(source_p, form_str(ERR_ERRONEUSNICKNAME), me.name,
               source_p->name[0] ? source_p->name : "*", nick, conf->reason);
    sendto_realops_flags(UMODE_REJ, L_ALL, SEND_NOTICE,
                         "Forbidding reserved nick [%s] from user %s",
                         nick, get_client_name(client_p, HIDE_IP));
    return;
  }

  if ((target_p = hash_find_client(nick)) == NULL)
    set_initial_nick(source_p, nick);
  else if (source_p == target_p)
    strlcpy(source_p->name, nick, sizeof(source_p->name));
  else
    sendto_one(source_p, form_str(ERR_NICKNAMEINUSE), me.name, "*", nick);
}
Exemple #4
0
/* ms_unresv()
 *     parv[0] = sender prefix
 *     parv[1] = target server
 *     parv[2] = resv to remove
 */
static void
ms_unresv(struct Client *client_p, struct Client *source_p, int parc, char *parv[])
{
	if((parc != 3) || EmptyString(parv[2]))
		return;

	sendto_match_servs(source_p, parv[1], CAP_CLUSTER, "UNRESV %s %s", parv[1], parv[2]);

	if(!IsClient(source_p) || !match(parv[1], me.name))
		return;

	if(find_matching_name_conf(ULINE_TYPE, source_p->servptr->name,
				   source_p->username, source_p->realhost, SHARED_UNRESV))
		remove_resv(source_p, parv[2]);
}
Exemple #5
0
/*! \brief NICK command handler (called by unregistered,
 *         locally 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:
 *      - parv[0] = sender prefix
 *      - parv[1] = nickname
 */
static void
mr_nick(struct Client *client_p, struct Client *source_p,
        int parc, char *parv[])
{
  struct Client *target_p = NULL;
  char nick[NICKLEN];
  char *s = NULL;

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

  /* Terminate the nick at the first ~ */
  if ((s = strchr(parv[1], '~')) != NULL)
    *s = '\0';

  /* copy the nick and terminate it */
  strlcpy(nick, parv[1], sizeof(nick));

  /* check the nickname is ok */
  if (!clean_nick_name(nick, 1))
  {
    sendto_one(source_p, form_str(ERR_ERRONEUSNICKNAME),
               me.name, EmptyString(parv[0]) ? "*" : parv[0], parv[1]);
    return;
  }

  /* check if the nick is resv'd */
  if (find_matching_name_conf(NRESV_TYPE, nick, NULL, NULL, 0) &&
      !IsExemptResv(source_p))
  {
    sendto_one(source_p, form_str(ERR_ERRONEUSNICKNAME),
               me.name, EmptyString(parv[0]) ? "*" : parv[0], nick);
    return;
  }

  if ((target_p = find_client(nick)) == NULL)
    set_initial_nick(source_p, nick);
  else if (source_p == target_p)
    strlcpy(source_p->name, nick, sizeof(source_p->name));
  else
    sendto_one(source_p, form_str(ERR_NICKNAMEINUSE), me.name, "*", nick);
}
Exemple #6
0
/* ms_resv()
 *   parv[0] = command
 *   parv[1] = target server
 *   parv[2] = channel/nick to resv
 *   parv[3] = reason
 */
static int
ms_resv(struct Client *source_p, int parc, char *parv[])
{
  if (parc != 4 || EmptyString(parv[3]))
    return 0;

  sendto_match_servs(source_p, parv[1], CAP_CLUSTER, "RESV %s %s :%s",
                     parv[1], parv[2], parv[3]);

  if (match(parv[1], me.name))
    return 0;

  if (HasFlag(source_p, FLAGS_SERVICE) ||
      find_matching_name_conf(CONF_ULINE, source_p->servptr->name,
                              source_p->username, source_p->host,
                              SHARED_RESV))
    parse_resv(source_p, parv[2], 0, parv[3]);
  return 0;
}
Exemple #7
0
/*! \brief UNRESV 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] = channel/nick
 */
static int
ms_unresv(struct Client *source_p, int parc, char *parv[])
{
  if (parc != 3 || EmptyString(parv[2]))
    return 0;

  sendto_match_servs(source_p, parv[1], CAPAB_CLUSTER, "UNRESV %s %s",
                     parv[1], parv[2]);

  if (match(parv[1], me.name))
    return 0;

  if (HasFlag(source_p, FLAGS_SERVICE) ||
      find_matching_name_conf(CONF_SHARED, source_p->servptr->name,
                              source_p->username, source_p->host,
                              SHARED_UNRESV))
    resv_remove(source_p, parv[2]);

  return 0;
}
Exemple #8
0
/*! \brief NICK 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] = nickname
 */
static int
mr_nick(struct Client *source_p, int parc, char *parv[])
{
  char nick[NICKLEN + 1] = "";
  struct Client *target_p = NULL;
  struct MaskItem *conf = NULL;

  if (parc < 2 || EmptyString(parv[1]))
  {
    sendto_one_numeric(source_p, &me, ERR_NONICKNAMEGIVEN);
    return 0;
  }

  /* Copy the nick and terminate it */
  strlcpy(nick, parv[1], IRCD_MIN(sizeof(nick), ConfigServerInfo.max_nick_length + 1));

  /* Check the nickname is ok */
  if (!valid_nickname(nick, 1))
  {
    sendto_one_numeric(source_p, &me, ERR_ERRONEUSNICKNAME, parv[1], "Erroneous Nickname");
    return 0;
  }

  /* Check if the nick is resv'd */
  if ((conf = find_matching_name_conf(CONF_NRESV, nick, NULL, NULL, 0)))
  {
    ++conf->count;
    sendto_one_numeric(source_p, &me, ERR_ERRONEUSNICKNAME, nick, conf->reason);
    sendto_realops_flags(UMODE_REJ, L_ALL, SEND_NOTICE,
                         "Forbidding reserved nick %s from user %s",
                         nick, get_client_name(source_p, HIDE_IP));
    return 0;
  }

  if ((target_p = hash_find_client(nick)) == NULL || target_p == source_p)
    set_initial_nick(source_p, nick);
  else
    sendto_one_numeric(source_p, &me, ERR_NICKNAMEINUSE, target_p->name);

  return 0;
}
Exemple #9
0
/*! \brief UNKLINE 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] = user mask
 *      - parv[3] = host mask
 */
static int
ms_unkline(struct Client *source_p, int parc, char *parv[])
{
  const char *kuser, *khost;

  if (parc != 4 || EmptyString(parv[3]))
    return 0;

  sendto_match_servs(source_p, parv[1], CAP_UNKLN, "UNKLINE %s %s %s",
                     parv[1], parv[2], parv[3]);

  kuser = parv[2];
  khost = parv[3];

  if (match(parv[1], me.name))
    return 0;

  if (HasFlag(source_p, FLAGS_SERVICE) ||
      find_matching_name_conf(CONF_ULINE, source_p->servptr->name,
                              source_p->username, source_p->host,
                              SHARED_UNKLINE))
  {
    if (remove_kline_match(khost, kuser))
    {
      if (IsClient(source_p))
        sendto_one_notice(source_p, &me, ":K-Line for [%s@%s] is removed", kuser, khost);

      sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
                           "%s has removed the K-Line for: [%s@%s]",
                           get_oper_name(source_p), kuser, khost);
      ilog(LOG_TYPE_KLINE, "%s removed K-Line for [%s@%s]",
           get_oper_name(source_p), kuser, khost);
    }
    else if (IsClient(source_p))
      sendto_one_notice(source_p, &me, ":No K-Line for [%s@%s] found", kuser, khost);
  }

  return 0;
}
Exemple #10
0
/*! \brief NICK 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] = nickname
 */
static int
m_nick(struct Client *source_p, int parc, char *parv[])
{
  char nick[NICKLEN + 1] = "";
  struct Client *target_p = NULL;
  struct MaskItem *conf = NULL;

  assert(MyClient(source_p));

  if (parc < 2 || EmptyString(parv[1]))
  {
    sendto_one_numeric(source_p, &me, ERR_NONICKNAMEGIVEN);
    return 0;
  }

  /* Mark end of grace period, to prevent nickflooding */
  if (!IsFloodDone(source_p))
    flood_endgrace(source_p);

  /* Terminate nick to NICKLEN */
  strlcpy(nick, parv[1], IRCD_MIN(sizeof(nick), ConfigServerInfo.max_nick_length + 1));

  /* Check the nickname is ok */
  if (!valid_nickname(nick, 1))
  {
    sendto_one_numeric(source_p, &me, ERR_ERRONEUSNICKNAME, nick, "Erroneous Nickname");
    return 0;
  }

  if (!HasFlag(source_p, FLAGS_EXEMPTRESV) &&
      !(HasUMode(source_p, UMODE_OPER) && HasOFlag(source_p, OPER_FLAG_NICK_RESV)) &&
      (conf = find_matching_name_conf(CONF_NRESV, nick, NULL, NULL, 0)))
  {
    ++conf->count;
    sendto_one_numeric(source_p, &me, ERR_ERRONEUSNICKNAME, nick, conf->reason);
    sendto_realops_flags(UMODE_REJ, L_ALL, SEND_NOTICE,
                         "Forbidding reserved nick %s from user %s",
                         nick, get_client_name(source_p, HIDE_IP));
    return 0;
  }

  if ((target_p = hash_find_client(nick)) == NULL)
    change_local_nick(source_p, nick);
  else if (target_p == source_p)
  {
    /*
     * If (target_p == source_p) the client is changing nicks between
     * equivalent nicknames ie: [nick] -> {nick}
     */

    /* Check the nick isn't exactly the same */
    if (strcmp(target_p->name, nick))
      change_local_nick(source_p, nick);
  }
  else if (IsUnknown(target_p))
  {
    /*
     * If the client that has the nick isn't registered yet (nick but no
     * user) then drop the unregged client
     */
    exit_client(target_p, "Overridden by other sign on");
    change_local_nick(source_p, nick);
  }
  else
    sendto_one_numeric(source_p, &me, ERR_NICKNAMEINUSE, target_p->name);

  return 0;
}
Exemple #11
0
static void
ms_dline(struct Client *client_p, struct Client *source_p,
         int parc, char *parv[])
{
  char def_reason[] = CONF_NOREASON;
  char *dlhost, *reason;
  const char *creason;
  const struct Client *target_p = NULL;
  struct irc_ssaddr daddr;
  struct MaskItem *conf=NULL;
  time_t tkline_time=0;
  int bits = 0, aftype = 0, t = 0;
  const char *current_date = NULL;
  time_t cur_time;
  char hostip[HOSTIPLEN + 1];
  char buffer[IRCD_BUFSIZE];

  if (parc != 5 || EmptyString(parv[4]))
    return;

  /* parv[0]  parv[1]        parv[2]      parv[3]  parv[4] */
  /* oper     target_server  tkline_time  host     reason  */
  sendto_match_servs(source_p, parv[1], CAP_DLN,
                     "DLINE %s %s %s :%s",
                     parv[1], parv[2], parv[3], parv[4]);

  if (match(parv[1], me.name))
    return;

  tkline_time = valid_tkline(parv[2], TK_SECONDS);
  dlhost = parv[3];
  reason = parv[4];

  if (HasFlag(source_p, FLAGS_SERVICE) || find_matching_name_conf(CONF_ULINE, source_p->servptr->name,
                              source_p->username, source_p->host,
                              SHARED_DLINE))
  {
    if (!IsClient(source_p))
      return;
    if ((t = parse_netmask(dlhost, NULL, &bits)) == HM_HOST)
    {
      if ((target_p = find_chasing(client_p, source_p, dlhost, NULL)) == NULL)
        return;

      if (!MyConnect(target_p))
      {
        sendto_one(source_p,
                   ":%s NOTICE %s :Can't DLINE nick on another server",
                   me.name, source_p->name);
        return;
      }

      if (IsExemptKline(target_p))
      {
        sendto_one(source_p,
                   ":%s NOTICE %s :%s is E-lined", me.name,
                   source_p->name, target_p->name);
        return;
      }

      getnameinfo((struct sockaddr *)&target_p->localClient->ip,
                  target_p->localClient->ip.ss_len, hostip,
                  sizeof(hostip), NULL, 0, NI_NUMERICHOST);
      dlhost = hostip;
      t = parse_netmask(dlhost, NULL, &bits);
      assert(t == HM_IPV4 || t == HM_IPV6);
    }

    if (bits < 8)
    {
      sendto_one(source_p,
                 ":%s NOTICE %s :For safety, bitmasks less than 8 require conf access.",
                 me.name, source_p->name);
      return;
    }

#ifdef IPV6
    if (t == HM_IPV6)
      aftype= AF_INET6;
    else
#endif
      aftype = AF_INET;

    parse_netmask(dlhost, &daddr, NULL);

    if ((conf = find_dline_conf(&daddr, aftype)) != NULL)
    {
      creason = conf->reason ? conf->reason : def_reason;
      if (IsConfExemptKline(conf))
        sendto_one(source_p,
                   ":%s NOTICE %s :[%s] is (E)d-lined by [%s] - %s",
                   me.name, source_p->name, dlhost, conf->host, creason);
      else
        sendto_one(source_p,
                   ":%s NOTICE %s :[%s] already D-lined by [%s] - %s",
                   me.name, source_p->name, dlhost, conf->host, creason);
      return;
    }

    cur_time = CurrentTime;
    current_date = smalldate(cur_time);

    if (!valid_comment(source_p, reason, 1))
      return;

    conf = conf_make(CONF_DLINE);
    conf->host = xstrdup(dlhost);

    if (tkline_time != 0)
      snprintf(buffer, sizeof(buffer), "Temporary D-line %d min. - %s (%s)",
               (int)(tkline_time/60), reason, current_date);
    else
      snprintf(buffer, sizeof(buffer), "%s (%s)", reason, current_date);

    conf->reason = xstrdup(buffer);
    apply_dline(source_p, conf, tkline_time);
    rehashed_klines = 1;
  }
}
Exemple #12
0
static void
remove_resv (struct Client *source_p, char *name, int cluster)
{
  struct ConfItem *conf;

  if (IsChanPrefix (*name))
    {
      struct ResvChannel *resv_p;

      if (resv_channel_list.head == NULL || !(resv_p = hash_find_resv (name)))
	{
	  if (!cluster)
	    sendto_one (source_p,
			":%s NOTICE %s :A RESV does not exist for channel: %s",
			me.name, source_p->name, name);
	  return;
	}
      else if (resv_p->conf)
	{
	  if (!cluster)
	    sendto_one (source_p,
			":%s NOTICE %s :The RESV for channel: %s is in ircd.conf and must be removed by hand.",
			me.name, source_p->name, name);
	  return;
	}
      else
	{
	  delete_channel_resv (resv_p);
	  (void) remove_conf_line (CRESV_TYPE, source_p, name, NULL);

	  if (!cluster)
	    sendto_one (source_p,
			":%s NOTICE %s :The RESV has been removed on channel: %s",
			me.name, source_p->name, name);
	  sendto_realops_flags (UMODE_ALL, L_ALL,
				"%s has removed the RESV for channel: %s",
				get_oper_name (source_p), name);
	}
    }
  else if (clean_resv_nick (name))
    {
      struct MatchItem *resv_p;
      conf = find_matching_name_conf (NRESV_TYPE, name, NULL, NULL, 0);

      if (conf == NULL)
	{
	  if (!cluster)
	    sendto_one (source_p,
			":%s NOTICE %s :A RESV does not exist for nick: %s",
			me.name, source_p->name, name);
	  return;
	}
      resv_p = (struct MatchItem *) map_to_conf (conf);
      if (resv_p->action)
	{
	  if (!cluster)
	    sendto_one (source_p,
			":%s NOTICE %s :The RESV for nick: %s is in ircd.conf and must be removed by hand.",
			me.name, source_p->name, name);
	  return;
	}
      else
	{
	  delete_conf_item (conf);
	  (void) remove_conf_line (NRESV_TYPE, source_p, name, NULL);

	  if (!cluster)
	    sendto_one (source_p,
			":%s NOTICE %s :The RESV has been removed on nick: %s",
			me.name, source_p->name, name);
	  sendto_realops_flags (UMODE_ALL, L_ALL,
				"%s has removed the RESV for nick: %s",
				get_oper_name (source_p), name);
	}
    }
}
/*
 * ms_connect - CONNECT command handler
 * 
 * Added by Jto 11 Feb 1989
 *
 * m_connect
 *      parv[0] = sender prefix
 *      parv[1] = servername
 *      parv[2] = port number
 *      parv[3] = remote server
 */
static void
ms_connect(struct Client *client_p, struct Client *source_p,
           int parc, char *parv[])
{
  int port;
  int tmpport;
  struct ConfItem *conf = NULL;
  struct AccessItem *aconf = NULL;
  struct Client *target_p;

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

  if (*parv[1] == '\0')
  {
    sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS),
               me.name, source_p->name, "CONNECT");
    return;
  }

  if ((target_p = find_server(parv[1])))
  {
    sendto_one(source_p,
	       ":%s NOTICE %s :Connect: Server %s already exists from %s.",
               me.name, source_p->name, parv[1], target_p->from->name);
    return;
  }

  /*
   * try to find the name, then host, if both fail notify ops and bail
   */
  if ((conf = find_matching_name_conf(SERVER_TYPE,
				      parv[1], NULL, NULL, 0)) != NULL)
    aconf = (struct AccessItem *)map_to_conf(conf);
  else if ((conf = find_matching_name_conf(SERVER_TYPE,
					   NULL, NULL, parv[1], 0)) != NULL)
    aconf = (struct AccessItem *)map_to_conf(conf);

  if (aconf == NULL)
  {
    sendto_one(source_p,
	       ":%s NOTICE %s :Connect: Host %s not listed in ircd.conf",
	       me.name, source_p->name, parv[1]);
    return;
  }

  assert(aconf != NULL);

  /* Get port number from user, if given. If not specified,
   * use the default form configuration structure. If missing
   * from there, then use the precompiled default.
   */
  tmpport = port = aconf->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 && aconf->port)
      port = aconf->port;
    else if (port <= 0)
    {
      sendto_one(source_p, ":%s NOTICE %s :Connect: Illegal port number",
                 me.name, source_p->name);
      return;
    }
  }
  else if (port <= 0 && (port = PORTNUM) <= 0)
  {
    sendto_one(source_p, ":%s NOTICE %s :Connect: missing port number",
               me.name, source_p->name);
    return;
  }

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

  /*
   * Notify all operators about remote connect requests
   */
  sendto_wallops_flags(UMODE_WALLOP, &me, "Remote CONNECT %s %d from %s",
                       parv[1], port, source_p->name);
  sendto_server(NULL, NULL, NULL, NOCAPS, NOCAPS, NOFLAGS,
                ":%s WALLOPS :Remote CONNECT %s %d from %s",
                me.name, parv[1], port, source_p->name);

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

  aconf->port = port;

  /* at this point we should be calling connect_server with a valid
   * C:line and a valid port in the C:line
   */
  if (serv_connect(aconf, source_p))
    sendto_one(source_p, ":%s NOTICE %s :*** Connecting to %s.%d",
               me.name, source_p->name, conf->name, aconf->port);
  else
    sendto_one(source_p, ":%s NOTICE %s :*** Couldn't connect to %s.%d",
               me.name, source_p->name, conf->name, aconf->port);
  /* client is either connecting with all the data it needs or has been
   * destroyed
   */
  aconf->port = tmpport;
}
Exemple #14
0
/*! \brief NICK command handler (called by already registered,
 *         locally 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:
 *      - parv[0] = sender prefix
 *      - parv[1] = nickname
 */
static void
m_nick(struct Client *client_p, struct Client *source_p,
       int parc, char *parv[])
{
  char nick[NICKLEN];
  struct Client *target_p = NULL;

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

  /* mark end of grace period, to prevent nickflooding */
  if (!IsFloodDone(source_p))
    flood_endgrace(source_p);

  /* terminate nick to NICKLEN */
  strlcpy(nick, parv[1], sizeof(nick));

  /* check the nickname is ok */
  if (!clean_nick_name(nick, 1))
  {
    sendto_one(source_p, form_str(ERR_ERRONEUSNICKNAME),
               me.name, source_p->name, nick);
    return;
  }

  if (find_matching_name_conf(NRESV_TYPE, nick,
			     NULL, NULL, 0) && !IsExemptResv(source_p) &&
     !(IsOper(source_p) && ConfigFileEntry.oper_pass_resv))
  {
    sendto_one(source_p, form_str(ERR_ERRONEUSNICKNAME),
               me.name, source_p->name, nick);
    return;
  }

  if ((target_p = find_client(nick)) == NULL)
    change_local_nick(client_p, source_p, nick);
  else if (target_p == source_p)
  {
    /*
     * If (target_p == source_p) the client is changing nicks between
     * equivalent nicknames ie: [nick] -> {nick}
     */

    /* check the nick isnt exactly the same */
    if (strcmp(target_p->name, nick))
      change_local_nick(client_p, source_p, nick);
  }
  else if (IsUnknown(target_p))
  {
    /*
     * if the client that has the nick isn't registered yet (nick but no
     * user) then drop the unregged client
     */
    exit_client(target_p, &me, "Overridden");
    change_local_nick(client_p, source_p, nick);
  }
  else
    sendto_one(source_p, form_str(ERR_NICKNAMEINUSE), me.name,
               source_p->name, nick);
}
/*
 * mo_connect - CONNECT command handler
 * 
 * Added by Jto 11 Feb 1989
 *
 * m_connect
 *      parv[0] = sender prefix
 *      parv[1] = servername
 *      parv[2] = port number
 *      parv[3] = remote server
 */
static void
mo_connect(struct Client* client_p, struct Client* source_p,
           int parc, char* parv[])
{
  int port;
  int tmpport;
  struct ConfItem *conf = NULL;
  struct AccessItem *aconf = NULL;
  struct Client *target_p;

  /* always privileged with handlers */
  if (MyConnect(source_p) && !IsOperRemote(source_p) && parc > 3)
  {
    sendto_one(source_p, form_str(ERR_NOPRIVS),
               me.name, source_p->name, "connect");
    return;
  }

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

  if (*parv[1] == '\0')
  {
    sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS),
               me.name, source_p->name, "CONNECT");
    return;
  }

  if ((target_p = find_server(parv[1])))
  {
    sendto_one(source_p,
	       ":%s NOTICE %s :Connect: Server %s already exists from %s.",
               me.name, source_p->name, parv[1], target_p->from->name);
    return;
  }

  /*
   * try to find the name, then host, if both fail notify ops and bail
   */
  if ((conf = find_matching_name_conf(SERVER_TYPE,
				      parv[1], NULL, NULL, 0)) != NULL)
    aconf = (struct AccessItem *)map_to_conf(conf);
  else if ((conf = find_matching_name_conf(SERVER_TYPE,
					   NULL, NULL, parv[1], 0)) != NULL)
    aconf = (struct AccessItem *)map_to_conf(conf);
  
  if (conf == NULL)
  {
    sendto_one(source_p,
	       ":%s NOTICE %s :Connect: Host %s not listed in ircd.conf",
	       me.name, source_p->name, parv[1]);
    return;
  }
    
  /* Get port number from user, if given. If not specified,
   * use the default form configuration structure. If missing
   * from there, then use the precompiled default.
   */
  tmpport = port = aconf->port;

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

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

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

  aconf->port = port;

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

  /* client is either connecting with all the data it needs or has been
   * destroyed
   */
  aconf->port = tmpport;
}
Exemple #16
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;
}
Exemple #17
0
static void
ms_dline(struct Client *client_p, struct Client *source_p,
         int parc, char *parv[])
{
  char def_reason[] = CONF_NOREASON;
  char *dlhost, *oper_reason, *reason;
  const char *creason;
  const struct Client *target_p = NULL;
  struct sockaddr_storage daddr;
  struct AccessItem *aconf = NULL;
  time_t tkline_time = 0;
  int bits, t;
  char hostip[HOSTIPLEN + 1];

  if (parc != 5 || EmptyString(parv[4]))
    return;

  /* parv[0]  parv[1]        parv[2]      parv[3]  parv[4] */
  /* oper     target_server  tkline_time  host     reason  */
  sendto_match_servs(source_p, parv[1], CAP_DLN,
                     "DLINE %s %s %s :%s",
                     parv[1], parv[2], parv[3], parv[4]);

  if (!match(parv[1], me.name))
    return;

  tkline_time = valid_tkline(parv[2], TK_SECONDS);
  dlhost = parv[3];
  reason = parv[4];

  if (HasFlag(source_p, FLAGS_SERVICE)
      || find_matching_name_conf(ULINE_TYPE, source_p->servptr->name,
                                 source_p->username, source_p->host,
                                 SHARED_DLINE))
  {
    if (!IsClient(source_p))
      return;

    if ((t = parse_netmask(dlhost, NULL, &bits)) == HM_HOST)
    {
      if ((target_p = find_chasing(client_p, source_p, dlhost, NULL)) == NULL)
        return;

      if (!MyConnect(target_p))
      {
        sendto_one(source_p,
                   ":%s NOTICE %s :Can't DLINE nick on another server",
                   me.name, source_p->name);
        return;
      }

      if (IsExemptKline(target_p))
      {
        sendto_one(source_p,
                   ":%s NOTICE %s :%s is E-lined", me.name,
                   source_p->name, target_p->name);
        return;
      }

      ip_to_string(&target_p->ip, hostip, sizeof(hostip));

      dlhost = hostip;
      t = parse_netmask(dlhost, NULL, &bits);
      assert(t == HM_IPV4 || t == HM_IPV6);
    }

    if (bits < 8)
    {
      sendto_one(source_p,
                 ":%s NOTICE %s :For safety, bitmasks less than 8 require conf access.",
                 me.name, source_p->name);
      return;
    }

    if (t == HM_IPV6)
      t = AF_INET6;
    else
      t = AF_INET;

    parse_netmask(dlhost, &daddr, NULL);

    if ((aconf = find_dline_conf(&daddr, t)) != NULL)
    {
      creason = aconf->reason ? aconf->reason : def_reason;

      if (IsConfExemptKline(aconf))
        sendto_one(source_p,
                   ":%s NOTICE %s :[%s] is (E)d-lined by [%s] - %s",
                   me.name, source_p->name, dlhost, aconf->host, creason);
      else
        sendto_one(source_p,
                   ":%s NOTICE %s :[%s] already D-lined by [%s] - %s",
                   me.name, source_p->name, dlhost, aconf->host, creason);

      return;
    }

    /* Look for an oper reason */
    if ((oper_reason = strchr(reason, '|')) != NULL)
      * oper_reason++ = '\0';

    if (!valid_comment(source_p, reason, 1))
      return;

    apply_conf_ban(source_p, DLINE_TYPE, NULL, dlhost, reason, oper_reason,
                   tkline_time);
  }
}
Exemple #18
0
/*! \brief NICK command handler (called by already registered,
 *         locally 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:
 *      - parv[0] = sender prefix
 *      - parv[1] = nickname
 */
static void
m_nick(struct Client *client_p, struct Client *source_p,
       int parc, char *parv[])
{
  char nick[NICKLEN + 1] = { '\0' };
  struct Client *target_p = NULL;
  struct MaskItem *conf = NULL;

  assert(source_p == client_p);

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

  /* mark end of grace period, to prevent nickflooding */
  if (!IsFloodDone(source_p))
    flood_endgrace(source_p);

  /* terminate nick to NICKLEN */
  strlcpy(nick, parv[1], IRCD_MIN(sizeof(nick), ServerInfo.max_nick_length + 1));

  /* check the nickname is ok */
  if (!valid_nickname(nick, 1))
  {
    sendto_one(source_p, form_str(ERR_ERRONEUSNICKNAME), me.name,
               source_p->name, nick, "Erroneous Nickname");
    return;
  }

  if (!IsExemptResv(source_p) &&
      !(HasUMode(source_p, UMODE_OPER) && ConfigFileEntry.oper_pass_resv) &&
      (conf = find_matching_name_conf(CONF_NRESV, nick, NULL, NULL, 0)))
  {
    ++conf->count;
    sendto_one(source_p, form_str(ERR_ERRONEUSNICKNAME),
               me.name, source_p->name, nick, conf->reason);
    sendto_realops_flags(UMODE_REJ, L_ALL, SEND_NOTICE,
                         "Forbidding reserved nick [%s] from user %s",
                         nick, get_client_name(client_p, HIDE_IP));
    return;
  }

  if ((target_p = hash_find_client(nick)) == NULL)
    change_local_nick(source_p, nick);
  else if (target_p == source_p)
  {
    /*
     * If (target_p == source_p) the client is changing nicks between
     * equivalent nicknames ie: [nick] -> {nick}
     */

    /* Check the nick isn't exactly the same */
    if (strcmp(target_p->name, nick))
      change_local_nick(source_p, nick);
  }
  else if (IsUnknown(target_p))
  {
    /*
     * If the client that has the nick isn't registered yet (nick but no
     * user) then drop the unregged client
     */
    exit_client(target_p, &me, "Overridden");
    change_local_nick(source_p, nick);
  }
  else
    sendto_one(source_p, form_str(ERR_NICKNAMEINUSE), me.name,
               source_p->name, nick);
}
Exemple #19
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;
}