Пример #1
0
static int
ms_tmode(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{
    struct Channel *chptr = NULL;
    struct membership *msptr;

    /* Now, try to find the channel in question */
    if(!IsChanPrefix(parv[2][0]) || !check_channel_name(parv[2])) {
        sendto_one_numeric(source_p, ERR_BADCHANNAME, form_str(ERR_BADCHANNAME), parv[2]);
        return 0;
    }

    chptr = find_channel(parv[2]);

    if(chptr == NULL) {
        sendto_one_numeric(source_p, ERR_NOSUCHCHANNEL,
                           form_str(ERR_NOSUCHCHANNEL), parv[2]);
        return 0;
    }

    /* TS is higher, drop it. */
    if(atol(parv[1]) > chptr->channelts)
        return 0;

    if(IsServer(source_p)) {
        set_channel_mode(client_p, source_p, chptr, NULL, parc - 3, parv + 3);
    } else {
        msptr = find_channel_membership(chptr, source_p);

        set_channel_mode(client_p, source_p, chptr, msptr, parc - 3, parv + 3);
    }

    return 0;
}
Пример #2
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");
  }
}
Пример #3
0
static int
ms_mlock(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{
	struct Channel *chptr = NULL;

	/* Now, try to find the channel in question */
	if(!IsChanPrefix(parv[2][0]) || !check_channel_name(parv[2]))
	{
		sendto_one_numeric(source_p, ERR_BADCHANNAME, form_str(ERR_BADCHANNAME), parv[2]);
		return 0;
	}

	chptr = find_channel(parv[2]);

	if(chptr == NULL)
	{
		sendto_one_numeric(source_p, ERR_NOSUCHCHANNEL,
				   form_str(ERR_NOSUCHCHANNEL), parv[2]);
		return 0;
	}

	/* TS is higher, drop it. */
	if(atol(parv[1]) > chptr->channelts)
		return 0;

	if(IsServer(source_p))
		set_channel_mlock(client_p, source_p, chptr, parv[3], TRUE);

	return 0;
}
Пример #4
0
/*
 * m_mode - MODE command handler
 * parv[0] - sender
 * parv[1] - channel
 */
int m_mode(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
{
  struct Channel* chptr;
  static char     modebuf[MODEBUFLEN];
  static char     parabuf[MODEBUFLEN];
  char *mename = me.name;

  if(sptr->user && sptr->user->vlink)
    mename = sptr->user->vlink->name;
     
  /* Now, try to find the channel in question */
  if (parc > 1)
    {
      if( IsChanPrefix(parv[1][0]) )
        {
          /* Don't do any of this stuff at all
           * unless it looks like a channel name 
           */

          if (!check_channel_name(parv[1]))
            { 
              sendto_one(sptr, form_str(ERR_BADCHANNAME),
                         mename, parv[0], (unsigned char *)parv[1]);
              return 0;
            }

          chptr = hash_find_channel(parv[1], NullChn);
          if (!chptr)
            return user_mode(cptr, sptr, parc, parv);
        }
      else
        {
          /* if here, it has to be a non-channel name */
          return user_mode(cptr, sptr, parc, parv);
        }
    }
  else
    {
      sendto_one(sptr, form_str(ERR_NEEDMOREPARAMS),
                 mename, parv[0], "MODE");
      return 0;
    }

  if (parc < 3)
    {
      *modebuf = *parabuf = '\0';
      modebuf[1] = '\0';
      channel_modes(sptr, modebuf, parabuf, chptr, 0);
      sendto_one(sptr, form_str(RPL_CHANNELMODEIS), mename, parv[0],
                 chptr->chname, modebuf, parabuf);
      sendto_one(sptr, form_str(RPL_CREATIONTIME), mename, parv[0],
                 chptr->chname, chptr->channelts);
      return 0;
    }

  set_channel_mode(cptr, sptr, chptr, parc - 2, parv + 2);

  return 0;
}
Пример #5
0
/*! \brief MODE 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] = channel or nick name
 *      - parv[2] = modes to be added or removed
 */
static int
m_mode(struct Client *source_p, int parc, char *parv[])
{
  struct Channel *chptr = NULL;

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

  /* Now, try to find the channel in question */
  if (!IsChanPrefix(*parv[1]))
  {
    /* If here, it has to be a non-channel name */
    set_user_mode(source_p, parc, parv);
    return 0;
  }

  if ((chptr = hash_find_channel(parv[1])) == NULL)
  {
    sendto_one_numeric(source_p, &me, ERR_NOSUCHCHANNEL, parv[1]);
    return 0;
  }

  /* Now known the channel exists */
  if (parc < 3)
  {
    char modebuf[MODEBUFLEN] = "";
    char parabuf[MODEBUFLEN] = "";

    channel_modes(chptr, source_p, modebuf, parabuf);
    sendto_one_numeric(source_p, &me, RPL_CHANNELMODEIS, chptr->name, modebuf, parabuf);
    sendto_one_numeric(source_p, &me, RPL_CREATIONTIME, chptr->name, chptr->creationtime);
    return 0;
  }

  /*
   * bounce all modes from people we deop on sjoin
   * servers have always gotten away with murder,
   * including telnet servers *g* - Dianora
   */
  if (IsServer(source_p) || HasFlag(source_p, FLAGS_SERVICE))
    set_channel_mode(source_p, chptr, NULL, parc - 2, parv + 2);
  else
  {
    struct Membership *member = find_channel_link(source_p, chptr);

    /* Finish the flood grace period... */
    if (MyClient(source_p) && !IsFloodDone(source_p))
      if (!((parc == 3) && (parv[2][0] == 'b') && (parv[2][1] == '\0')))
        flood_endgrace(source_p);

    set_channel_mode(source_p, chptr, member, parc - 2, parv + 2);
  }

  return 0;
}
Пример #6
0
u_short
check_chan(user_t *cptr, char *chan)
{
	if (strlen(chan) > CHANLEN)
		return (cptr ? reply(CS, cptr->nick, "That is too long for a channel name.") : 1);
	if (!IsChanPrefix(*chan))
		return (cptr ? reply(CS, cptr->nick, "That is not a valid channel name.") : 1);
	for (; *chan; chan++)
		if (!IsChanChar(*chan))
			return (cptr ? reply(CS, cptr->nick, "The character '%c' is not allowed in a channel name.", *chan) : 1);
	return 0;
}
Пример #7
0
/*
 *
 *      parc    number of arguments ('sender' counted as one!)
 *      parv[0] pointer to 'sender' (may point to empty string) (not used)
 *      parv[1]..parv[parc-1]
 *              pointers to additional parameters, this is a NULL
 *              terminated list (parv[parc] == NULL).
 *
 * *WARNING*
 *      Numerics are mostly error reports. If there is something
 *      wrong with the message, just *DROP* it! Don't even think of
 *      sending back a neat error message -- big danger of creating
 *      a ping pong error message...
 *
 * Rewritten by Nemesi, Jan 1999, to support numeric nicks in parv[1]
 *
 * Called when we get a numeric message from a remote _server_ and we are
 * supposed to forward it somewhere. Note that we always ignore numerics sent
 * to 'me' and simply drop the message if we can't handle with this properly:
 * the savvy approach is NEVER generate an error in response to an... error :)
 */
static void
parse_handle_numeric(unsigned int numeric, struct Client *source_p, int parc, char *parv[])
{
  struct Client *target_p = NULL;
  struct Channel *chptr = NULL;

  /*
   * Avoid trash, we need it to come from a server and have a target
   */
  if (parc < 2 || !IsServer(source_p))
    return;

  /*
   * Who should receive this message ? Will we do something with it ?
   * Note that we use findUser functions, so the target can't be neither
   * a server, nor a channel (?) nor a list of targets (?) .. u2.10
   * should never generate numeric replies to non-users anyway
   * Ahem... it can be a channel actually, csc bots use it :\ --Nem
   */
  if (IsChanPrefix(*parv[1]))
    chptr = hash_find_channel(parv[1]);
  else
    target_p = find_person(source_p, parv[1]);

  if ((target_p == NULL || target_p->from == source_p->from) && chptr == NULL)
    return;

  /*
   * Remap low number numerics, not that I understand WHY.. --Nemesi
   */
  /*
   * Numerics below 100 talk about the current 'connection', you're not
   * connected to a remote server so it doesn't make sense to send them
   * remotely - but the information they contain may be useful, so we
   * remap them up. Weird, but true.  -- Isomer
   */
  if (numeric < 100)
    numeric += 100;

  if (target_p)
  {
    /* Fake it for server hiding, if it's our client */
    if ((ConfigServerHide.hide_servers || IsHidden(source_p)) && MyConnect(target_p) &&
        !HasUMode(target_p, UMODE_OPER))
      sendto_one_numeric(target_p, &me, numeric | SND_EXPLICIT, "%s", parv[2]);
    else
      sendto_one_numeric(target_p, source_p, numeric | SND_EXPLICIT, "%s", parv[2]);
  }
  else
    sendto_channel_butone(source_p, source_p, chptr, 0, "%u %s %s",
                          numeric, chptr->name, parv[2]);
}
Пример #8
0
int ValidateChannelWild( const char *channel_name )
{
	if( channel_name == NULL )
		return NS_FAILURE;
	/* Channel name must start with channel prefix */
	if( !IsChanPrefix( *channel_name ) )
		return NS_FAILURE;
	channel_name ++;
	while( *channel_name != '\0' )
	{
		if( !IsChanChar( *channel_name ) && !IsWildChar( *channel_name ) )
			return NS_FAILURE;
		channel_name++;
	}
	return NS_SUCCESS;
}
Пример #9
0
static void
resv_remove(struct Client *source_p, const char *name)
{
  unsigned int type_int = CONF_CRESV;
  const char *type_str = "channel";
  struct MaskItem *conf = NULL;

  if (!IsChanPrefix(*name))
  {
    type_int = CONF_NRESV;
    type_str = "nick";
  }

  if ((conf = find_exact_name_conf(type_int, NULL, name, NULL, NULL)) == NULL)
  {
    if (IsClient(source_p))
     sendto_one_notice(source_p, &me, ":A RESV does not exist for %s: %s", type_str, name);

    return;
  }

  if (!IsConfDatabase(conf))
  {
    if (IsClient(source_p))
      sendto_one_notice(source_p, &me, ":The RESV for %s: %s is in ircd.conf and must be removed by hand.",
                        type_str, name);
    return;
  }

  conf_free(conf);

  if (IsClient(source_p))
    sendto_one_notice(source_p, &me, ":The RESV has been removed on %s: %s", type_str, name);

  sendto_realops_flags(UMODE_SERVNOTICE, L_ALL, SEND_NOTICE,
                       "%s has removed the RESV for %s: %s",
                       get_oper_name(source_p), type_str, name);
  ilog(LOG_TYPE_RESV, "%s removed RESV for [%s]",
       get_oper_name(source_p), name);
}
Пример #10
0
/*
 * ms_topic
 *      parv[0] = sender prefix
 *      parv[1] = channel name
 *	parv[2] = topic_info
 *	parv[3] = topic_info time
 *	parv[4] = new channel topic
 *
 * Let servers always set a topic
 */
static void
ms_topic(struct Client *client_p, struct Client *source_p,
         int parc, char *parv[])
{
  struct Channel *chptr = NULL;

  if (!IsServer(source_p))
  {
    m_topic(client_p, source_p, parc, parv);
    return;
  }

  if (parc < 5)
    return;

  if (parv[1] && IsChanPrefix(*parv[1]))
  {
    if ((chptr = hash_find_channel(parv[1])) == NULL)
      return;

    set_channel_topic(chptr, parv[4], parv[2], atoi(parv[3]));

    if (ConfigServerHide.hide_servers)
    {
      sendto_channel_local(ALL_MEMBERS, NO, chptr, ":%s TOPIC %s :%s",
                           me.name, chptr->chname,
                           chptr->topic == NULL ? "" : chptr->topic);

    }
    else
    {
      sendto_channel_local(ALL_MEMBERS, NO, chptr, ":%s TOPIC %s :%s",
                           source_p->name, chptr->chname,
                           chptr->topic == NULL ? "" : chptr->topic);
    }
  }
}
Пример #11
0
static void
resv_remove(struct Client *source_p, const char *name)
{
  unsigned int type = CONF_CRESV;
  struct MaskItem *conf = NULL;

  if (!IsChanPrefix(*name))
    type = CONF_NRESV;

  if ((conf = find_exact_name_conf(type, NULL, name, NULL, NULL)) == NULL)
  {
    if (IsClient(source_p))
      sendto_one_notice(source_p, &me, ":No RESV for %s", name);

    return;
  }

  if (!IsConfDatabase(conf))
  {
    if (IsClient(source_p))
      sendto_one_notice(source_p, &me, ":The RESV for %s is in ircd.conf and must be removed by hand",
                        name);
    return;
  }

  conf_free(conf);

  if (IsClient(source_p))
    sendto_one_notice(source_p, &me, ":RESV for [%s] is removed", name);

  sendto_realops_flags(UMODE_SERVNOTICE, L_ALL, SEND_NOTICE,
                       "%s has removed the RESV for: [%s]",
                       get_oper_name(source_p), name);
  ilog(LOG_TYPE_RESV, "%s removed RESV for [%s]",
       get_oper_name(source_p), name);
}
Пример #12
0
/*
 * ms_tmode()
 *
 * inputs	- parv[0] = UID
 *		  parv[1] = TS
 *		  parv[2] = channel name
 *		  parv[3] = modestring
 */
static void
ms_tmode(struct Client *client_p, struct Client *source_p, int parc, char *parv[])
{
  struct Channel *chptr = NULL;
  struct Membership *member;

  if (!IsChanPrefix(parv[2][0]) || !check_channel_name(parv[2]))
  {
    sendto_one(source_p, form_str(ERR_BADCHANNAME),
               ID_or_name(&me, client_p), ID_or_name(source_p, client_p), parv[2]);
    return;
  }

  if ((chptr = hash_find_channel(parv[2])) == NULL)
  {
    sendto_one(source_p, form_str(ERR_NOSUCHCHANNEL),
               ID_or_name(&me, client_p), ID_or_name(source_p, client_p), parv[2]);
    return;
  }

  if (atol(parv[1]) > chptr->channelts)
    return;

  if (IsServer(source_p))
    set_channel_mode(client_p, source_p, chptr, NULL, parc - 3, parv + 3, chptr->chname);
  else
  {
    member = find_channel_link(source_p, chptr);

    /* XXX are we sure we just want to bail here? */
    if (has_member_flags(member, CHFL_DEOPPED))
      return;

    set_channel_mode(client_p, source_p, chptr, member, parc - 3, parv + 3, chptr->chname);
  }
}
Пример #13
0
static int
build_target_list(int p_or_n, char *command, struct Client *client_p,
                  struct Client *source_p, char *nicks_channels,
                  char *text)
{
  int type;
  char *p, *nick, *target_list, ncbuf[BUFSIZE];
  struct Channel *chptr=NULL;
  struct Client *target_p;

  /* Sigh, we can't mutilate parv[1] incase we need it to send to a hub */
  if (!ServerInfo.hub && (uplink != NULL) && IsCapable(uplink, CAP_LL))
  {
    strncpy(ncbuf, nicks_channels, BUFSIZE);
    target_list = ncbuf;
  }
  else
    target_list = nicks_channels; /* skip strcpy for non-lazyleafs */

  ntargets = 0;

  for (nick = strtoken(&p, target_list, ","); nick;
       nick = strtoken(&p, (char *)NULL, ","))
  {
    char *with_prefix;
    /*
     * channels are privmsg'd a lot more than other clients, moved up
     * here plain old channel msg?
     */

    if (IsChanPrefix(*nick))
    {
      /* ignore send of local channel to a server (should not happen) */
      if (IsServer(client_p) && *nick == '&')
        continue;

      if ((chptr = hash_find_channel(nick)) != NULL)
      {
        if (!duplicate_ptr(chptr))
        {
          if (ntargets >= ConfigFileEntry.max_targets)
	    {
	      sendto_one(source_p, form_str(source_p,ERR_TOOMANYTARGETS),
			 me.name, source_p->name, nick);
	      return (1);
	    }
          targets[ntargets].ptr = (void *)chptr;
          targets[ntargets++].type = ENTITY_CHANNEL;
        }
      }
      else
      {
        if (!ServerInfo.hub && (uplink != NULL) && IsCapable(uplink, CAP_LL))
          return -1;
        else if (p_or_n != NOTICE)
          sendto_one(source_p, form_str(source_p,ERR_NOSUCHNICK), me.name,
                     source_p->name, nick);
      }
      continue;
    }

    /* look for a privmsg to another client */
    if ((target_p = find_person(nick)) != NULL)
    {
      if (!duplicate_ptr(target_p))
      {
        if (ntargets >= ConfigFileEntry.max_targets)
	  {
	    sendto_one(source_p, form_str(source_p,ERR_TOOMANYTARGETS),
		       me.name, source_p->name, nick);
	    return (1);
	  }
        targets[ntargets].ptr = (void *)target_p;
        targets[ntargets].type = ENTITY_CLIENT;
        targets[ntargets++].flags = 0;
      }
      continue;
    }
    
    /* @#channel or +#channel message ? */

    type = 0;
    with_prefix = nick;
    /*  allow %+@ if someone wants to do that */
    for (;;)
    {
      if (*nick == '@')
        type |= MODE_CHANOP;
      else if (*nick == '%')
        type |= MODE_CHANOP | MODE_HALFOP;
      else if (*nick == '+')
        type |= MODE_CHANOP | MODE_HALFOP | MODE_VOICE;
      else
        break;
      nick++;
    }

    if (type != 0)
    {
      /* suggested by Mortiis */
      if (*nick == '\0')      /* if its a '\0' dump it, there is no recipient */
	{
	  sendto_one(source_p, form_str(source_p,ERR_NORECIPIENT),
		     me.name, source_p->name, command);
	  continue;
	}

      /* At this point, nick+1 should be a channel name i.e. #foo or &foo
       * if the channel is found, fine, if not report an error
       */

      if ((chptr = hash_find_channel(nick)) != NULL)
	{
	  if(!is_any_op(chptr, source_p) && !is_voiced(chptr, source_p))
	    {
	      sendto_one(source_p, form_str(source_p,ERR_CHANOPRIVSNEEDED), me.name,
			 source_p->name, with_prefix);
	      return(-1);
	    }

	  if (!duplicate_ptr(chptr))
	    {
	      if (ntargets >= ConfigFileEntry.max_targets)
		{
		  sendto_one(source_p, form_str(source_p,ERR_TOOMANYTARGETS),
			     me.name, source_p->name, nick);
		  return (1);
		}
	      targets[ntargets].ptr = (void *)chptr;
	      targets[ntargets].type = ENTITY_CHANOPS_ON_CHANNEL;
	      targets[ntargets++].flags = type;
	    }
	}
      else
	{
	  if (!ServerInfo.hub && (uplink != NULL) && IsCapable(uplink, CAP_LL))
	    return -1;
	  else if (p_or_n != NOTICE)
	    sendto_one(source_p, form_str(source_p,ERR_NOSUCHNICK), me.name,
		       source_p->name, nick);
	}
      continue;
    }

    if(IsOper(source_p) && ((*nick == '$') || strchr(nick, '@')))
    {
      handle_opers(p_or_n, command, client_p, source_p, nick, text);
    }
    else
    {
      if (!ServerInfo.hub && (uplink != NULL) && IsCapable(uplink, CAP_LL))
        return -1;
      else if(p_or_n != NOTICE)
        sendto_one(source_p, form_str(source_p,ERR_NOSUCHNICK),
	           me.name, source_p->name, nick);
    }
    /* continue; */
  }
  return (1);
}
Пример #14
0
/* parse_resv()
 *
 * inputs	- source_p, NULL supported
 *		- thing to resv
 *		- time_t if tkline
 *		- reason
 * outputs	- none
 * side effects	- parse resv, create if valid
 */
static void
parse_resv(struct Client *source_p, char *name, int tkline_time, char *reason)
{
  if (IsChanPrefix(*name))
  {
    struct MaskItem *conf = NULL;

    if ((conf = create_resv(name, reason, NULL)) == NULL)
    {
      if (IsClient(source_p))
        sendto_one_notice(source_p, &me, ":A RESV has already been placed on channel: %s", name);

      return;
    }

    conf->setat = CurrentTime;
    SetConfDatabase(conf);

    if (tkline_time)
    {
      if (IsClient(source_p))
        sendto_one_notice(source_p, &me, ":A %d minute %s RESV has been placed on channel: %s",
                          tkline_time/60, (MyClient(source_p) ? "local" : "remote"), name);

      sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
                           "%s has placed a %d minute %s RESV on channel: %s [%s]",
                           get_oper_name(source_p),
                           tkline_time/60,
                           (MyClient(source_p) ? "local" : "remote"),
                           conf->name, conf->reason);
      ilog(LOG_TYPE_RESV, "%s added temporary %d min. RESV for [%s] [%s]",
           get_oper_name(source_p), (int)tkline_time/60,
           conf->name, conf->reason);
      conf->until = CurrentTime + tkline_time;
    }
    else
    {
      if (IsClient(source_p))
        sendto_one_notice(source_p, &me, ":A %s RESV has been placed on channel %s",
                          (MyClient(source_p) ? "local" : "remote"), name);

      sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
                           "%s has placed a %s RESV on channel %s : [%s]",
                           get_oper_name(source_p),
                           (MyClient(source_p) ? "local" : "remote"),
                           conf->name, conf->reason);
      ilog(LOG_TYPE_RESV, "%s added RESV for [%s] [%s]",
           get_oper_name(source_p), conf->name, conf->reason);
    }
  }
  else
  {
    struct MaskItem *conf = NULL;

    if (!valid_wild_card_simple(name))
    {
      if (IsClient(source_p))
        sendto_one_notice(source_p, &me, ":Please include at least %u non-wildcard characters with the resv",
                          ConfigGeneral.min_nonwildcard_simple);

      return;
    }

    if (!HasUMode(source_p, UMODE_ADMIN) && has_wildcards(name))
    {
      if (IsClient(source_p))
        sendto_one_notice(source_p, &me, ":You must be an admin to perform a wildcard RESV");

      return;
    }

    if ((conf = create_resv(name, reason, NULL)) == NULL)
    {
      if (IsClient(source_p))
        sendto_one_notice(source_p, &me, ":A RESV has already been placed on nick %s", name);

      return;
    }

    conf->setat = CurrentTime;
    SetConfDatabase(conf);

    if (tkline_time)
    {
      if (IsClient(source_p))
        sendto_one_notice(source_p, &me, ":A %d minute %s RESV has been placed on nick %s : [%s]",
                          tkline_time/60, (MyClient(source_p) ? "local" : "remote"),
                          conf->name, conf->reason);

      sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
                           "%s has placed a %d minute %s RESV on nick %s : [%s]",
                           get_oper_name(source_p), tkline_time/60,
                           (MyClient(source_p) ? "local" : "remote"),
                           conf->name, conf->reason);
      ilog(LOG_TYPE_RESV, "%s added temporary %d min. RESV for [%s] [%s]",
           get_oper_name(source_p), (int)tkline_time/60, conf->name, conf->reason);
      conf->until = CurrentTime + tkline_time;
    }
    else
    {
      if (IsClient(source_p))
        sendto_one_notice(source_p, &me, ":A %s RESV has been placed on nick %s : [%s]",
                          (MyClient(source_p) ? "local" : "remote"), conf->name, conf->reason);

      sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
                           "%s has placed a %s RESV on nick %s : [%s]",
                           get_oper_name(source_p),
                           (MyClient(source_p) ? "local" : "remote"),
                           conf->name, conf->reason);
      ilog(LOG_TYPE_RESV, "%s added RESV for [%s] [%s]",
           get_oper_name(source_p), conf->name, conf->reason);
    }
  }
}
Пример #15
0
/* build_target_list()
 *
 * inputs	- pointer to given source (oper/client etc.)
 *		- pointer to list of nicks/channels
 *		- pointer to table to place results
 *		- pointer to text (only used if source_p is an oper)
 * output	- number of valid entities
 * side effects	- target_table is modified to contain a list of
 *		  pointers to channels or clients
 *		  if source client is an oper
 *		  all the classic old bizzare oper privmsg tricks
 *		  are parsed and sent as is, if prefixed with $
 *		  to disambiguate.
 *
 */
static int
build_target_list(int p_or_n, const char *command, struct Client *source_p,
                  char *nicks_channels, const char *text)
{
  int type = 0;
  char *p = NULL, *nick = NULL;
  char *target_list = NULL;
  struct Channel *chptr = NULL;
  struct Client *target_p = NULL;

  target_list = nicks_channels;

  ntargets = 0;

  for (nick = strtoken(&p, target_list, ","); nick;
       nick = strtoken(&p,        NULL, ","))
  {
    const char *with_prefix = NULL;

    /*
     * Channels are privmsg'd a lot more than other clients, moved up
     * here plain old channel msg?
     */
    if (IsChanPrefix(*nick))
    {
      if ((chptr = hash_find_channel(nick)))
      {
        if (!duplicate_ptr(chptr))
        {
          if (ntargets >= ConfigGeneral.max_targets)
          {
            sendto_one_numeric(source_p, &me, ERR_TOOMANYTARGETS,
                               nick, ConfigGeneral.max_targets);
            return 1;
          }

          targets[ntargets].ptr = chptr;
          targets[ntargets++].type = ENTITY_CHANNEL;
        }
      }
      else
      {
        if (p_or_n != NOTICE)
          sendto_one_numeric(source_p, &me, ERR_NOSUCHNICK, nick);
      }

      continue;
    }

    /* Look for a PRIVMSG/NOTICE to another client */
    if ((target_p = find_person(source_p, nick)))
    {
      if (!duplicate_ptr(target_p))
      {
        if (ntargets >= ConfigGeneral.max_targets)
        {
          sendto_one_numeric(source_p, &me, ERR_TOOMANYTARGETS,
                             nick, ConfigGeneral.max_targets);
          return 1;
        }

        targets[ntargets].ptr = target_p;
        targets[ntargets].type = ENTITY_CLIENT;
        targets[ntargets++].flags = 0;
      }

      continue;
    }

    /* @#channel or +#channel message ? */
    type = 0;
    with_prefix = nick;

    /* Allow %+@ if someone wants to do that */
    while (1)
    {
      if (*nick == '@')
        type |= CHFL_CHANOP;
      else if (*nick == '%')
        type |= CHFL_CHANOP | CHFL_HALFOP;
      else if (*nick == '+')
        type |= CHFL_CHANOP | CHFL_HALFOP | CHFL_VOICE;
      else
        break;
      ++nick;
    }

    if (type)
    {
      if (EmptyString(nick))  /* If it's a '\0' dump it, there is no recipient */
      {
        sendto_one_numeric(source_p, &me, ERR_NORECIPIENT, command);
        continue;
      }

      /*
       * At this point, nick+1 should be a channel name i.e. #foo or &foo
       * if the channel is found, fine, if not report an error
       */
      if ((chptr = hash_find_channel(nick)))
      {
        if (IsClient(source_p) && !HasFlag(source_p, FLAGS_SERVICE))
        {
          if (!has_member_flags(find_channel_link(source_p, chptr),
                                CHFL_CHANOP|CHFL_HALFOP|CHFL_VOICE))
          {
            sendto_one_numeric(source_p, &me, ERR_CHANOPRIVSNEEDED, with_prefix);
            return -1;
          }
        }

        if (!duplicate_ptr(chptr))
        {
          if (ntargets >= ConfigGeneral.max_targets)
          {
            sendto_one_numeric(source_p, &me, ERR_TOOMANYTARGETS,
                               nick, ConfigGeneral.max_targets);
            return 1;
          }

          targets[ntargets].ptr = chptr;
          targets[ntargets].type = ENTITY_CHANOPS_ON_CHANNEL;
          targets[ntargets++].flags = type;
        }
      }
      else
      {
        if (p_or_n != NOTICE)
          sendto_one_numeric(source_p, &me, ERR_NOSUCHNICK, nick);
      }

      continue;
    }

    if (*nick == '$' || strchr(nick, '@'))
      handle_special(p_or_n, command, source_p, nick, text);
    else
    {
      if (p_or_n != NOTICE)
      {
        if (!IsDigit(*nick) || MyClient(source_p))
          sendto_one_numeric(source_p, &me, ERR_NOSUCHNICK, nick);
      }
    }
  }

  return 1;
}
Пример #16
0
/* m_topic()
 *  parv[0] = sender prefix
 *  parv[1] = channel name
 *  parv[2] = new topic, if setting topic
 */
static void
m_topic(struct Client *client_p, struct Client *source_p,
        int parc, char *parv[])
{
  struct Channel *chptr = NULL;
  char *p;
  struct Membership *ms;
  const char *from, *to;

  if (!MyClient(source_p) && IsCapable(source_p->from, CAP_TS6) && HasID(source_p))
  {
    from = me.id;
    to = source_p->id;
  }
  else
  {
    from = me.name;
    to = source_p->name;
  }

  if ((p = strchr(parv[1], ',')) != NULL)
    *p = '\0';

  if (EmptyString(parv[1]))
  {
    sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS),
               from, to, "TOPIC");
    return;
  }

  if (MyClient(source_p) && !IsFloodDone(source_p))
    flood_endgrace(source_p);

  if (IsChanPrefix(*parv[1]))
  {
    if ((chptr = hash_find_channel(parv[1])) == NULL)
    {
      sendto_one(source_p, form_str(ERR_NOSUCHCHANNEL),
                 from, to, parv[1]);
      return;
    }

    /* setting topic */
    if (parc > 2)
    {
      if ((ms = find_channel_link(source_p, chptr)) == NULL && !IsService(source_p))
      {
        sendto_one(source_p, form_str(ERR_NOTONCHANNEL), me.name,
                   source_p->name, parv[1]);
        return;
      }

      if ((chptr->mode.mode & MODE_TOPICLIMIT) == 0 ||
          has_member_flags(ms, CHFL_CHANOP|CHFL_HALFOP) || IsGod(source_p) ||
          IsService(source_p))
      {
        char topic_info[USERHOST_REPLYLEN]; 
        if(!has_member_flags(ms, CHFL_CHANOP|CHFL_HALFOP) && 
                IsGod(source_p) && MyClient(source_p) &&
                (chptr->mode.mode & MODE_TOPICLIMIT) != 0)
        {              
          char tmp[IRCD_BUFSIZE];           
          ircsprintf(tmp, "%s is using God mode: TOPIC %s %s", source_p->name, 
                  chptr->chname, parv[2]);              
          sendto_gnotice_flags(UMODE_SERVNOTICE, L_ALL, me.name, &me, NULL, 
                  tmp);
          oftc_log(tmp);
        }
        ircsprintf(topic_info, "%s!%s@%s",
                   source_p->name, source_p->username, source_p->host);
        set_channel_topic(chptr, parv[2], topic_info, CurrentTime);

        sendto_server(client_p, chptr, CAP_TS6, NOCAPS,
                      ":%s TOPIC %s :%s",
                      ID(source_p), chptr->chname,
                      chptr->topic == NULL ? "" : chptr->topic);
        sendto_server(client_p, chptr, NOCAPS, CAP_TS6,
                      ":%s TOPIC %s :%s",
                      source_p->name, chptr->chname,
                      chptr->topic == NULL ? "" : chptr->topic);
        sendto_channel_local(ALL_MEMBERS, NO,
                             chptr, ":%s!%s@%s TOPIC %s :%s",
                             source_p->name,
                             source_p->username,
                             source_p->host,
                             chptr->chname, chptr->topic == NULL ?
                             "" : chptr->topic);
      }
      else
        sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED),
                   from, to, chptr->chname);
    }
    else /* only asking for topic */
    {
      if (!SecretChannel(chptr) || IsMember(source_p, chptr))
      {
        if (chptr->topic == NULL)
          sendto_one(source_p, form_str(RPL_NOTOPIC),
                     from, to, chptr->chname);
        else
        {
          sendto_one(source_p, form_str(RPL_TOPIC),
                     from, to,
                     chptr->chname, chptr->topic);

          sendto_one(source_p, form_str(RPL_TOPICWHOTIME),
                     from, to, chptr->chname,
                     chptr->topic_info,
                     chptr->topic_time);
        }
      }
      else
      {
        sendto_one(source_p, form_str(ERR_NOTONCHANNEL),
                   from, to, chptr->chname);
        return;
      }
    }
  }
  else
  {
    sendto_one(source_p, form_str(ERR_NOSUCHCHANNEL),
               from, to, parv[1]);
  }
}
Пример #17
0
/* parse_resv()
 *
 * inputs	- source_p, NULL supported
 *		- thing to resv
 *		- reason
 * outputs	- none
 * side effects	- parse resv, create if valid
 */
static void
parse_resv (struct Client *source_p, char *name, char *reason, int cluster)
{
  struct ConfItem *conf;

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

      if ((conf = create_channel_resv (name, reason, 0)) == NULL)
	{
	  if (!cluster)
	    sendto_one (source_p,
			":%s NOTICE %s :A RESV has already been placed on channel: %s",
			me.name, source_p->name, name);
	  return;
	}

      resv_p = (struct ResvChannel *) map_to_conf (conf);

      if (!cluster)
	sendto_one (source_p,
		    ":%s NOTICE %s :A %s RESV has been placed on channel: %s",
		    me.name, source_p->name,
		    (MyClient (source_p) ? "local" : "remote"), name);
      sendto_realops_flags (UMODE_ALL, L_ALL,
			    "%s has placed a %s RESV on channel: %s [%s]",
			    get_oper_name (source_p),
			    (MyClient (source_p) ? "local" : "remote"),
			    resv_p->name, resv_p->reason);
      write_conf_line (source_p, conf, NULL /* not used */ ,
		       0 /* not used */ );
    }
  else if (clean_resv_nick (name))
    {
      struct MatchItem *resv_p;

      if ((strchr (name, '*') || strchr (name, '?')) && !IsAdmin (source_p))
	{
	  if (!cluster)
	    sendto_one (source_p,
			":%s NOTICE %s :You must be an admin to perform a wildcard RESV",
			me.name, source_p->name);
	  return;
	}

      if ((conf = create_nick_resv (name, reason, 0)) == NULL)
	{
	  if (!cluster)
	    sendto_one (source_p,
			":%s NOTICE %s :A RESV has already been placed on nick: %s",
			me.name, source_p->name, name);
	  return;
	}

      resv_p = (struct MatchItem *) map_to_conf (conf);

      if (!cluster)
	sendto_one (source_p,
		    ":%s NOTICE %s :A %s RESV has been placed on nick: %s [%s]",
		    me.name, source_p->name,
		    (MyClient (source_p) ? "local" : "remote"),
		    conf->name, resv_p->reason);
      sendto_realops_flags (UMODE_ALL, L_ALL,
			    "%s has placed a %s RESV on nick: %s [%s]",
			    get_oper_name (source_p),
			    (MyClient (source_p) ? "local" : "remote"),
			    conf->name, resv_p->reason);
      write_conf_line (source_p, conf, NULL /* not used */ ,
		       0 /* not used */ );
    }
  else if (!cluster)
    sendto_one (source_p,
		":%s NOTICE %s :You have specified an invalid resv: [%s]",
		me.name, source_p->name, name);
}
Пример #18
0
/*
 * m_mode - MODE command handler
 * parv[0] - sender
 * parv[1] - channel
 */
static void
m_mode(struct Client *client_p, struct Client *source_p,
       int parc, char *parv[])
{
  struct Channel *chptr = NULL;
  struct Membership *member;
  static char modebuf[MODEBUFLEN];
  static char parabuf[MODEBUFLEN];

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

  /* Now, try to find the channel in question */
  if (!IsChanPrefix(*parv[1]))
  {
    /* if here, it has to be a non-channel name */
    set_user_mode(client_p, source_p, parc, parv);
    return;
  }

  if ((chptr = hash_find_channel(parv[1])) == NULL)
  {
    sendto_one(source_p, form_str(ERR_NOSUCHCHANNEL),
	       ID_or_name(&me, source_p->from),
	       ID_or_name(source_p, source_p->from),
	       parv[1]);
    return;
  }

  /* Now known the channel exists */
  if (parc < 3)
  {
    channel_modes(chptr, source_p, modebuf, parabuf);
    sendto_one(source_p, form_str(RPL_CHANNELMODEIS),
               me.name, source_p->name, chptr->chname, modebuf, parabuf);
    sendto_one(source_p, form_str(RPL_CREATIONTIME),
               me.name, source_p->name, chptr->chname, chptr->channelts);
  }
  /* bounce all modes from people we deop on sjoin
   * servers have always gotten away with murder,
   * including telnet servers *g* - Dianora
   *
   * XXX Is it worth the bother to make an ms_mode() ? - Dianora
   */
  else if (IsServer(source_p))
  {
    set_channel_mode(client_p, source_p, chptr, NULL, parc - 2, parv + 2,
                     chptr->chname);
  }
  else
  {
    member = find_channel_link(source_p, chptr);

    if (!has_member_flags(member, CHFL_DEOPPED))
    {
      /* Finish the flood grace period... */
      if (MyClient(source_p) && !IsFloodDone(source_p))
      {
        if (!((parc == 3) && (parv[2][0] == 'b') && (parv[2][1] == '\0')))
          flood_endgrace(source_p);
      }

      set_channel_mode(client_p, source_p, chptr, member, parc - 2, parv + 2,
                       chptr->chname);
    }
  }
}
Пример #19
0
/* parse_resv()
 *
 * inputs	- source_p, NULL supported
 *		- thing to resv
 *		- time_t if tkline
 *		- reason
 * outputs	- none
 * side effects	- parse resv, create if valid
 */
static void
parse_resv(struct Client *source_p, char *name, int tkline_time, char *reason)
{
	struct ConfItem *conf = NULL;
	int services = 0;

	if(IsServices(source_p))
		services = 1;

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

		if((conf = create_channel_resv(name, reason, 0)) == NULL)
		{
			if(!services)
				sendto_one(source_p,
					   ":%s NOTICE %s :A RESV has already been placed on channel: %s",
					   me.name, source_p->name, name);
			return;
		}

		resv_p = map_to_conf(conf);

		if(tkline_time != 0)
		{
			if(!services)
			{
				sendto_one(source_p,
					   ":%s NOTICE %s :A %d minute %s RESV has been placed on channel: %s",
					   me.name, source_p->name,
					   tkline_time / 60,
					   (MyClient(source_p) ? "local" : "remote"), name);
				sendto_realops_flags(UMODE_ALL, L_ALL,
						     "%s has placed a %d minute %s RESV on channel: %s [%s]",
						     get_oper_name(source_p),
						     tkline_time / 60,
						     (MyClient(source_p) ? "local" : "remote"),
						     resv_p->name, resv_p->reason);
			}
			ilog(L_TRACE, "%s added temporary %d min. RESV for [%s] [%s]",
			     source_p->name, (int) tkline_time / 60, conf->name, resv_p->reason);
			resv_p->hold = CurrentTime + tkline_time;
			add_temp_line(conf);
		}
		else
		{
			if(!services)
			{
				sendto_one(source_p,
					   ":%s NOTICE %s :A %s RESV has been placed on channel %s",
					   me.name, source_p->name,
					   (MyClient(source_p) ? "local" : "remote"), name);
				sendto_realops_flags(UMODE_ALL, L_ALL,
						     "%s has placed a %s RESV on channel %s : [%s]",
						     get_oper_name(source_p),
						     (MyClient(source_p) ? "local" : "remote"),
						     resv_p->name, resv_p->reason);
			}
			write_conf_line(source_p, conf, NULL /* not used */ , 0 /* not used */ );
		}
	}
	else
	{
		struct MatchItem *resv_p = NULL;

		if(!valid_wild_card_simple(name) && !IsServices(source_p))
		{
			sendto_one(source_p,
				   ":%s NOTICE %s :Please include at least %d non-wildcard characters with the resv",
				   me.name, source_p->name, ConfigFileEntry.min_nonwildcard_simple);
			return;
		}

		if(!IsAdmin(source_p) && !IsServices(source_p) && strpbrk(name, "*?#"))
		{
			sendto_one(source_p, ":%s NOTICE %s :You must be an admin to perform a "
				   "wildcard RESV", me.name, source_p->name);
			return;
		}

		if((conf = create_nick_resv(name, reason, 0)) == NULL)
		{
			if(!services)
				sendto_one(source_p,
					   ":%s NOTICE %s :A RESV has already been placed on nick %s",
					   me.name, source_p->name, name);
			return;
		}

		resv_p = map_to_conf(conf);

		if(tkline_time != 0)
		{
			if(!services)
			{
				sendto_one(source_p,
					   ":%s NOTICE %s :A %d minute %s RESV has been placed on nick %s : [%s]",
					   me.name, source_p->name,
					   tkline_time / 60,
					   (MyClient(source_p) ? "local" : "remote"),
					   conf->name, resv_p->reason);
				sendto_realops_flags(UMODE_ALL, L_ALL,
						     "%s has placed a %d minute %s RESV on nick %s : [%s]",
						     get_oper_name(source_p),
						     tkline_time / 60,
						     (MyClient(source_p) ? "local" : "remote"),
						     conf->name, resv_p->reason);
			}
			ilog(L_TRACE, "%s added temporary %d min. RESV for [%s] [%s]",
			     source_p->name, (int) tkline_time / 60, conf->name, resv_p->reason);
			resv_p->hold = CurrentTime + tkline_time;
			add_temp_line(conf);
		}
		else
		{
			if(!services)
			{
				sendto_one(source_p,
					   ":%s NOTICE %s :A %s RESV has been placed on nick %s : [%s]",
					   me.name, source_p->name,
					   (MyClient(source_p) ? "local" : "remote"),
					   conf->name, resv_p->reason);
				sendto_realops_flags(UMODE_ALL, L_ALL,
						     "%s has placed a %s RESV on nick %s : [%s]",
						     get_oper_name(source_p),
						     (MyClient(source_p) ? "local" : "remote"),
						     conf->name, resv_p->reason);
			}
			write_conf_line(source_p, conf, NULL /* not used */ , 0 /* not used */ );
		}
	}
}
Пример #20
0
static void
do_list(struct Client *source_p, int parc, char *parv[])
{
  struct ListTask *lt;
  int no_masked_channels;

  if (MyConnect(source_p))
  {
    if (source_p->localClient->list_task != NULL)
    {
      free_list_task(source_p->localClient->list_task, source_p);
      sendto_one(source_p, form_str(RPL_LISTEND), me.name, source_p->name);
      return;
    }
  }

  lt = (struct ListTask *) MyMalloc(sizeof(struct ListTask));
  lt->users_max = UINT_MAX;
  lt->created_max = UINT_MAX;
  lt->topicts_max = UINT_MAX;
  if (MyConnect(source_p))
    source_p->localClient->list_task = lt;
  no_masked_channels = 1;

  if (parc > 1)
  {
    char *opt, *save;
    dlink_list *list;
    int i, errors = 0;

    for (opt = strtoken(&save, parv[1], ","); opt != NULL;
         opt = strtoken(&save, NULL, ","))
      switch (*opt)
      {
        case '<': if ((i = atoi(opt + 1)) > 0)
		    lt->users_max = (unsigned int) i - 1;
                  else
		    errors = 1;
		  break;
        case '>': if ((i = atoi(opt + 1)) >= 0)
		    lt->users_min = (unsigned int) i + 1;
		  else
		    errors = 1;
		  break;
        case '-': break;
        case 'C':
	case 'c': switch (*++opt)
	          {
		    case '<': if ((i = atoi(opt + 1)) >= 0)
		                lt->created_max = (unsigned int) (CurrentTime
				                  - 60 * i);
			      else
			        errors = 1;
			      break;
		    case '>': if ((i = atoi(opt + 1)) >= 0)
		                lt->created_min = (unsigned int) (CurrentTime
				                  - 60 * i);
			      else
			        errors = 1;
			      break;
		    default: errors = 1;
		  }
		  break;
	case 'T':
	case 't': switch (*++opt)
	          {
		    case '<': if ((i = atoi(opt + 1)) >= 0)
		                lt->topicts_min = (unsigned int) (CurrentTime
				                  - 60 * i);
			      else
			        errors = 1;
			      break;
		    case '>': if ((i = atoi(opt + 1)) >= 0)
		                lt->topicts_max = (unsigned int) (CurrentTime
				                  - 60 * i);
			      else
			        errors = 1;
			      break;
		    default: errors = 1;
		  }
		  break;
        default: if (*opt == '!')
	         {
		   list = &lt->hide_mask;
		   opt++;
		 }
		 else list = &lt->show_mask;

		 if (has_wildcards(opt + !!IsChanPrefix(*opt)))
		 {
		   if (list == &lt->show_mask)
		     no_masked_channels = 0;
		 }
		 else if (!IsChanPrefix(*opt))
		   errors = 1;
		 if (!errors)
		 {
                   char *s;
		   DupString(s, opt);
		   dlinkAdd(s, make_dlink_node(), list);
		 }
      }
    if (errors)
    {
      free_list_task(lt, source_p);
      sendto_one(source_p, form_str(ERR_LISTSYNTAX),
                 MyConnect(source_p) ? me.name : ID(&me),
                 MyConnect(source_p) ? source_p->name : ID(source_p));
      return;
    }
  }


  if (MyConnect(source_p))
    dlinkAdd(source_p, make_dlink_node(), &listing_client_list);
  sendto_one(source_p, form_str(RPL_LISTSTART),
             MyConnect(source_p) ? me.name : ID(&me),
             MyConnect(source_p) ? source_p->name : ID(source_p));
  safe_list_channels(source_p, lt, no_masked_channels &&
                     lt->show_mask.head != NULL, !MyConnect(source_p));
}
Пример #21
0
/*
 * ms_bmask()
 *
 * inputs	- parv[0] = SID
 *		  parv[1] = TS
 *		  parv[2] = channel name
 *		  parv[3] = type of ban to add ('b' 'I' or 'e')
 *		  parv[4] = space delimited list of masks to add
 * outputs	- none
 * side effects	- propgates unchanged bmask line to CAP_TS6 servers,
 *		  sends plain modes to the others.  nothing is sent
 *		  to the server the issuing server is connected through
 */
static void
ms_bmask(struct Client *client_p, struct Client *source_p, int parc, char *parv[])
{
  static char modebuf[BUFSIZE];
  static char parabuf[BUFSIZE];
  static char banbuf[BUFSIZE];
  struct Channel *chptr;
  char *s, *t, *mbuf, *pbuf;
  long mode_type;
  int mlen;
  int plen = 0;
  int tlen;
  int modecount = 0;
  int needcap = NOCAPS;

  if(!IsChanPrefix(parv[2][0]) || !check_channel_name(parv[2]))
    return;

  if((chptr = hash_find_channel(parv[2])) == NULL)
    return;

  /* TS is higher, drop it. */
  if(atol(parv[1]) > chptr->channelts)
    return;

  switch(parv[3][0])
  {
    case 'b':
      mode_type = CHFL_BAN;
      break;

    case 'e':
      mode_type = CHFL_EXCEPTION;
      needcap = CAP_EX;
      break;

    case 'I':
      mode_type = CHFL_INVEX;
      needcap = CAP_IE;
      break;

    /* maybe we should just blindly propagate this? */
    default:
      return; 
  }

  parabuf[0] = '\0';
  s = banbuf;
  strlcpy(s, parv[4], sizeof(banbuf));

  /* only need to construct one buffer, for non-ts6 servers */
  mlen = ircsprintf(modebuf, ":%s MODE %s +",
                    source_p->name, chptr->chname);
  mbuf = modebuf + mlen;
  pbuf = parabuf;

  if((t = strchr(s, ' ')) != NULL)
    *t++ = '\0';

  while(s != NULL)
  {
    tlen = strlen(s);

    /* I dont even want to begin parsing this.. */
    if(tlen > MODEBUFLEN)
      break;

    if(tlen && add_id(source_p, chptr, s, mode_type))
    {
      /* this new one wont fit.. */
      if(mlen + MAXMODEPARAMS + plen + tlen > BUFSIZE - 4 ||
         modecount >= MAXMODEPARAMS)
      {
        *mbuf = '\0';
        *(pbuf - 1) = '\0';
        sendto_channel_local(ALL_MEMBERS, chptr, "%s %s",
                             modebuf, parabuf);
        sendto_server(client_p, NULL, chptr, needcap, CAP_TS6, NOFLAGS,
                      "%s %s",
                      modebuf, parabuf);

        mbuf = modebuf + mlen;
        pbuf = parabuf;
        plen = modecount = 0;
      }

      *mbuf++ = parv[3][0];
      plen = ircsprintf(pbuf, "%s ", s);
      pbuf += plen;
      modecount++;
    }

    s = t;

    if(s != NULL)
    {
      /* trailing space marking the end. */
      if(*s == '\0')
        break;

      if((t = strchr(s, ' ')) != NULL)
        *t++ = '\0';
    }
  }

  if(modecount)
  {
    *mbuf = *(pbuf - 1) = '\0';
    sendto_channel_local(ALL_MEMBERS, chptr, "%s %s", modebuf, parabuf);
    sendto_server(client_p, NULL, chptr, needcap, CAP_TS6, NOFLAGS,
                  "%s %s", modebuf, parabuf);
  }

  /* assumption here is that since the server sent BMASK, they are TS6, so they have an ID */
  sendto_server(client_p, NULL, chptr, CAP_TS6|needcap, NOCAPS, NOFLAGS,
                ":%s BMASK %lu %s %s :%s",
                 source_p->id, (unsigned long)chptr->channelts, chptr->chname,
                 parv[3], parv[4]);
}
Пример #22
0
static void
remove_resv(struct Client *source_p, const char *name)
{
	struct ConfItem *conf = NULL;
	int services = 0;

	if(IsServices(source_p))
		services = 1;

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

		if(resv_channel_list.head == NULL || !(resv_p = hash_find_resv(name)))
		{
			if(!services)
				sendto_one(source_p,
					   ":%s NOTICE %s :A RESV does not exist for channel: %s",
					   me.name, source_p->name, name);
			return;
		}

		if(resv_p->conf)
		{
			if(!services)
				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;
		}

		delete_channel_resv(resv_p);
		remove_conf_line(CRESV_TYPE, source_p, name, NULL);

		if(!services)
		{
			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
	{
		struct MatchItem *resv_p = NULL;

		if((conf = find_exact_name_conf(NRESV_TYPE, name, NULL, NULL, NULL)) == NULL)
		{
			if(!services)
				sendto_one(source_p,
					   ":%s NOTICE %s :A RESV does not exist for nick: %s",
					   me.name, source_p->name, name);
			return;
		}

		resv_p = map_to_conf(conf);

		if(resv_p->action)
		{
			if(!services)
				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;
		}

		delete_conf_item(conf);
		remove_conf_line(NRESV_TYPE, source_p, name, NULL);

		if(!services)
		{
			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);
		}
	}
}
Пример #23
0
/*
 * m_omode - MODE command handler
 * parv[0] - sender
 * parv[1] - channel
 */
static void
m_omode(struct Client *client_p, struct Client *source_p, int parc, char *parv[])
{
	struct Channel *chptr = NULL;
	struct membership *msptr;
	static char modebuf[MODEBUFLEN];
	static char parabuf[MODEBUFLEN];
	int n = 2;

	if(EmptyString(parv[1]))
	{
		sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS),
			   me.name, parv[0], "MODE");
		return;
	}

	/* Now, try to find the channel in question */
	if(!IsChanPrefix(parv[1][0]))
	{
		/* if here, it has to be a non-channel name */
		user_mode(client_p, source_p, parc, parv);
		return;
	}

	if(!check_channel_name(parv[1]))
	{
		sendto_one(source_p, form_str(ERR_BADCHANNAME),
			   me.name, parv[0], (unsigned char *) parv[1]);
		return;
	}

	chptr = hash_find_channel(parv[1]);

	if(chptr == NULL)
	{
		sendto_one(source_p, form_str(ERR_NOSUCHCHANNEL), me.name, parv[0], parv[1]);
		return;
	}

	sendto_wallops_flags(UMODE_WALLOP, &me, 
			     "OMODE called for [%s] by %s!%s@%s",
			     parv[1], source_p->name, source_p->username, source_p->host);
	ilog(L_NOTICE, "OMODE called for [%s] by %s!%s@%s",
	     parv[1], source_p->name, source_p->username, source_p->host);

	if(*chptr->chname != '&')
		sendto_server(NULL, NULL, NOCAPS, NOCAPS, 
			      ":%s WALLOPS :OMODE called for [%s] by %s!%s@%s",
			      me.name, parv[1], source_p->name, source_p->username,
			      source_p->host);

	/* Now know the channel exists */
	if(parc < n + 1)
	{
		channel_modes(chptr, source_p, modebuf, parabuf);
		sendto_one(source_p, form_str(RPL_CHANNELMODEIS),
			   me.name, parv[0], parv[1], modebuf, parabuf);

		sendto_one(source_p, form_str(RPL_CREATIONTIME),
			   me.name, parv[0], parv[1], chptr->channelts);
	}
	else if(IsServer(source_p))
	{
		set_channel_mode(client_p, source_p, chptr, NULL,
				 parc - n, parv + n, chptr->chname);
	}
	else
	{
		msptr = find_channel_membership(chptr, source_p);

		set_channel_mode(client_p, source_p->servptr, chptr, msptr, 
				 parc - n, parv + n, chptr->chname);
	}
}
Пример #24
0
static  int     m_message(struct Client *cptr,
                          struct Client *sptr,
                          int parc,
                          char *parv[],
                          int notice)
{
  struct Client       *acptr;
#ifdef NEED_TLD_FOR_MASS_NOTICE
  char  *s;
#endif
  struct Channel *chptr;
  char  *nick, *server, *host;
  char  errbuf[BUFSIZE];
  const char *cmd;
  int type=0, msgs=0;
#ifdef FLUD
  int flud;
#endif

  cmd = notice ? MSG_NOTICE : MSG_PRIVATE;

  if (parc < 2 || *parv[1] == '\0')
    {
      sendto_one(sptr, form_str(ERR_NORECIPIENT),
                 me.name, parv[0], cmd);
      return -1;
    }

  if (parc < 3 || *parv[2] == '\0')
    {
      sendto_one(sptr, form_str(ERR_NOTEXTTOSEND), me.name, parv[0]);
      return -1;
    }

  if (MyConnect(sptr))
    {
#ifdef ANTI_SPAMBOT
#ifndef ANTI_SPAMBOT_WARN_ONLY
      /* if its a spambot, just ignore it */
      if(sptr->join_leave_count >= MAX_JOIN_LEAVE_COUNT)
        return 0;
#endif
#endif
#ifdef NO_DUPE_MULTI_MESSAGES
      if (strchr(parv[1],','))
        parv[1] = canonize(parv[1]);
#endif
    }


  /*
  ** channels are privmsg'd a lot more than other clients, moved up here
  ** plain old channel msg ?
  */
  while(msgs < MAX_MULTI_MESSAGES)
  {
     if(!msgs)
        nick = strtok(parv[1], ",");
     else
        nick = strtok(NULL, ",");

     if(!nick && msgs == 0)
        nick = parv[1];
     else if(!nick)
        break;

  if( IsChanPrefix(*nick)
      && (IsPerson(sptr) && (chptr = hash_find_channel(nick, NullChn))))
    {
#ifdef FLUD
#ifdef DEATHFLUD
      if(!notice && check_for_ctcp(parv[2])
         && check_for_flud(sptr, NULL, chptr, 1))
        return 0;
      if((flud = check_for_spam(sptr, NULL, chptr, parv[2])))
        {
          if (check_for_flud(sptr, NULL, chptr, flud))
            return 0;
        }
#else /* DEATHFLUD */
      if(!notice)
	if(check_for_ctcp(parv[2]))
	  check_for_flud(sptr, NULL, chptr, 1);
#endif /* DEATHFLUD */
#endif /* FLUD */

      /* 
       * Channel color blocking. Usually set with the +c chanmode.
       * - Andre Guibert de Bruet <*****@*****.**>
       */
      if(chptr->mode.mode & MODE_NOCOLOR)
	strip_colour(parv[2]);

      switch (can_send(sptr, chptr))
        {
        case 0:
          sendto_channel_message_butone(cptr, sptr, chptr, cmd, parv[2]);
          break;
        case MODE_QUIETUNIDENT:
          if (!notice)
            sendto_one(sptr, form_str(ERR_QUIETUNIDENT),
                       me.name, parv[0], nick);
          break;
        case MODE_MODERATED:
          if (chptr->mode.mode & MODE_OPMODERATE)
            {
              /* The flag MODE_OPMODERATE will instruct sendto_channel_type()
	       * to put bare #channel in the message (instead of @#channel);
	       * it will still be sent to ops and servers with ops only.
	       * Strange things will happen if the user is not banned
	       * remotely.
	       * -- jilles
	       */
              sendto_channel_type(cptr, sptr, chptr,
			      MODE_CHANOP | MODE_OPMODERATE, nick, cmd,
			      parv[2]);
            }
          else
            {
              if (!notice)
                sendto_one(sptr, form_str(ERR_CANNOTSENDTOCHAN),
                           me.name, parv[0], nick);
            }
          break;
        default:
          break;
        }
      msgs++;
      continue;
    }
      
  /*
  ** @# type of channel msg?
  */

  if(*nick == '@')
    type = MODE_CHANOP;
  else if(*nick == '+')
    type = MODE_CHANOP|MODE_VOICE;

  if(type)
    {
      /* Strip if using DALnet chanop/voice prefix. */
      if (*(nick+1) == '@' || *(nick+1) == '+')
        {
          nick++;
          *nick = '@';
          type = MODE_CHANOP|MODE_VOICE;
        }

      /* suggested by Mortiis */
      if(!*nick)        /* if its a '\0' dump it, there is no recipient */
        {
          sendto_one(sptr, form_str(ERR_NORECIPIENT),
                     me.name, parv[0], cmd);
          return -1;
        }

      if (!IsPerson(sptr))      /* This means, servers can't send messages */
        return -1;

      /* At this point, nick+1 should be a channel name i.e. #foo or &foo
       * if the channel is found, fine, if not report an error
       */

      if ( (chptr = hash_find_channel(nick+1, NullChn)) )
        {
#ifdef FLUD
#ifdef DEATHFLUD
          if(!notice && check_for_ctcp(parv[2])
             && check_for_flud(sptr, NULL, chptr, 1))
            return 0;
          if((flud = check_for_spam(sptr, NULL, chptr, parv[2])))
            {
              if (check_for_flud(sptr, NULL, chptr, flud))
                return 0;
            }
#else /* DEATHFLUD */
          if(!notice)
            if(check_for_ctcp(parv[2]))
              check_for_flud(sptr, NULL, chptr, 1);
#endif /* DEATHFLUD */
#endif /* FLUD */

          if (!is_chan_op(sptr,chptr))
            {
              if (!notice)
                {
                  sendto_one(sptr, form_str(ERR_CANNOTSENDTOCHAN),
                             me.name, parv[0], nick);
                }
	msgs++;
	continue;
            }
          else
            {
              sendto_channel_type(cptr,
                                  sptr,
                                  chptr,
                                  type,
                                  nick+1,
                                  cmd,
                                  parv[2]);
            }
        }
      else
        {
	  if (!IsServer(sptr))
	    sendto_one(sptr, form_str(ERR_NOSUCHNICK),
		       me.name, parv[0], nick);
	  msgs++;
	  continue;
        }
      return 0;
    }

  /*
  ** nickname addressed?
  */
  if ((acptr = find_person(nick, NULL)))
    {
#ifdef FLUD
#ifdef DEATHFLUD
      if(!notice && MyConnect(sptr) && check_for_ctcp(parv[2])
         && check_for_flud(sptr, acptr, NULL, 1))
        return 0;
      if(MyConnect(sptr) && (flud = check_for_spam(sptr, acptr, NULL, parv[2])))
        {
          if (check_for_flud(sptr, acptr, NULL, flud))
            return 0;
        }
#else /* DEATHFLUD */
      if(!notice && MyConnect(sptr))
	if(check_for_ctcp(parv[2]))
	  if(check_for_flud(sptr, acptr, NULL, 1))
	    return 0;
#endif /* DEATHFLUD */
#endif /* FLUD */
#ifdef ANTI_DRONE_FLOOD
      if(MyConnect(acptr) && IsClient(sptr) && !NoFloodProtection(sptr) && DRONETIME)
        {
          if((acptr->first_received_message_time+DRONETIME) < CurrentTime)
            {
              acptr->received_number_of_privmsgs=1;
              acptr->first_received_message_time = CurrentTime;
              acptr->drone_noticed = 0;
            }
          else
            {
              if(acptr->received_number_of_privmsgs > DRONECOUNT)
                {
                  if(acptr->drone_noticed == 0) /* tiny FSM */
                    {
                      sendto_ops_flag(UMODE_BOTS,
				      "Possible Drone Flooder %s [%s@%s] on %s target: %s",
				      sptr->name, sptr->username,
				      sptr->host,
				      sptr->user->server, acptr->name);
                      acptr->drone_noticed = 1;
                    }
                  /* heuristic here, if target has been getting a lot
                   * of privmsgs from clients, and sendq is above halfway up
                   * its allowed sendq, then throw away the privmsg, otherwise
                   * let it through. This adds some protection, yet doesn't
                   * DOS the client.
                   * -Dianora
                   */
                  if(DBufLength(&acptr->sendQ) > (get_sendq(acptr)/2UL))
                    {
                      if(acptr->drone_noticed == 1) /* tiny FSM */
                        {
                          sendto_ops_flag(UMODE_BOTS,
					  "ANTI_DRONE_FLOOD SendQ protection activated for %s",
					  acptr->name);

                          sendto_one(acptr,     
				     ":%s NOTICE %s :*** Notice -- Server drone flood protection activated for %s",
                                     me.name, acptr->name, acptr->name);
                          acptr->drone_noticed = 2;
                        }
                    }

                  if(DBufLength(&acptr->sendQ) <= (get_sendq(acptr)/4UL))
                    {
                      if(acptr->drone_noticed == 2)
                        {
                          sendto_one(acptr,     
                                     ":%s NOTICE %s :*** Notice -- Server drone flood protection de-activated for %s",
                                     me.name, acptr->name, acptr->name);
                          acptr->drone_noticed = 1;
                        }
                    }
                  if(acptr->drone_noticed > 1)
                    return 0;
                }
              else
                acptr->received_number_of_privmsgs++;
            }
        }
#endif

      /*
       * Simple herustic here... If PRIVMSG is locked down via
       * F:noidprivmsg:1, then act like every client is +E.
       * Otherwise, assume the normal behaviour. All in a nice
       * single if statement. --nenolod
       */
      if (MyClient(sptr) && sptr != acptr &&
	   (GlobalSetOptions.noidprivmsg != 0 ||
	   HasUmode(acptr,UMODE_BLOCK_NOTID)) 
	   && !HasUmode(sptr,UMODE_IDENTIFIED)
	   && !sptr->user->servlogin[0]
	   && !HasUmode(acptr,UMODE_DONTBLOCK)
	   && !HasUmode(sptr,UMODE_DONTBLOCK))
        {
	  /* Replace errbuf with either the default or custom message,
	   * then send the numeric on...
	   *    --nenolod
	   */
	  if (GlobalSetOptions.noidprivmsg != 0 &&
		GlobalSetOptions.noidprivmsg_notice[0])
	    {
	      strncpy_irc(errbuf, GlobalSetOptions.noidprivmsg_notice, BUFSIZE);
	    }
	  else
	    {
	      ircsnprintf(errbuf, BUFSIZE, get_str(STR_NOTID_DEFAULT),
		nick);
	    }

          sendto_one(sptr, form_str(ERR_BLOCKING_NOTID),
	      me.name, parv[0], errbuf);
	  return 0;
        }

#ifdef  SILENCE
      /* only check silence masks at the recipient's server -- jilles */
      if (!MyConnect(acptr) || !is_silenced(sptr, acptr)) {
#endif
        if (MyConnect(sptr) && acptr->user && (sptr != acptr))
          {
#ifdef  NCTCP
            /* NCTCP (umode +C) checks  -- PMA */
            if (parv[2][0] == 1) /* is CTCP */
	      /* Huh? No way, NOCTCP means NOCTCP. */
/*               if (!HasUmode(sptr,UMODE_IMMUNE) && */
/*                   !HasUmode(acptr,UMODE_IMMUNE)) */
	      if (HasUmode(acptr,UMODE_NOCTCP) ||            /* block to +C */
		  (notice && HasUmode(sptr,UMODE_NOCTCP)))   /* block replies from +C */
		return 0;                                    /* kill it! */
#endif /* NCTCP */
            if (!notice && acptr->user->away)
              sendto_one(sptr, form_str(RPL_AWAY), me.name,
                         parv[0], acptr->name,
                         acptr->user->away);
          }
        {
          /* here's where we actually send the message */
          int is_ctcp = check_for_ctcp(parv[2]);
          int cap = is_ctcp ? CAP_IDENTIFY_CTCP : CAP_IDENTIFY_MSG;
          sendto_prefix_one(acptr, sptr, ":%s %s %s :%s%s",
                            parv[0], cmd, nick,
                            !(acptr->caps & cap) ? "" :
                            (HasUmode(sptr, UMODE_IDENTIFIED) ? "+" : "-"),
                            parv[2]);
        }
#ifdef SILENCE
      }
#endif

      msgs++;
      continue;
    }

  /* Everything below here should be reserved for opers 
   * as pointed out by Mortiis, user%[email protected] 
   * syntax could be used to flood without FLUD protection
   * its also a delightful way for non-opers to find users who
   * have changed nicks -Dianora
   *
   * Grrr it was pointed out to me that x@service is valid
   * for non-opers too, and wouldn't allow for flooding/stalking
   * -Dianora
   *
   * Valid or not, @servername is unacceptable, it reveals what server
   * a person is on. Auspexen only.
   *  -- asuffield
   */

        
  /*
  ** the following two cases allow masks in NOTICEs
  ** (for OPERs only) (with +M -- asuffield)
  **
  ** Armin, 8Jun90 ([email protected])
  */
  if ((*nick == '$' || *nick == '>'))
    {

      if(!HasUmode(sptr,UMODE_MASSNOTICE))
        {
          sendto_one(sptr, form_str(ERR_NOSUCHNICK),
                     me.name, parv[0], nick);
          return -1;
        }

#ifdef NEED_TLD_FOR_MASS_NOTICE
      if (!(s = (char *)strrchr(nick, '.')))
        {
          sendto_one(sptr, form_str(ERR_NOTOPLEVEL),
                     me.name, parv[0], nick);
          msgs++;
	  continue;
        }
      while (*++s)
        if (*s == '.' || *s == '*' || *s == '?')
          break;
      if (*s == '*' || *s == '?')
        {
          sendto_one(sptr, form_str(ERR_WILDTOPLEVEL),
                     me.name, parv[0], nick);
	  msgs++;
	  continue;
        }
#endif /* NEED_TLD_FOR_MASS_NOTICE */
        
      sendto_match_butone(IsServer(cptr) ? cptr : NULL, 
                          sptr, nick + 1,
                          (*nick == '>') ? MATCH_HOST :
                          MATCH_SERVER,
                          ":%s %s %s :%s", parv[0],
                          cmd, nick, parv[2]);
      msgs++;
      continue;
    }
        
  /*
  ** user[%host]@server addressed?
  */
  if ((server = (char *)strchr(nick, '@')) &&
      (acptr = find_server(server + 1)))
    {
      int count = 0;

      /* Disable the whole farping mess for non-auspexen
       *  -- asuffield
       */
      if (!HasUmode(sptr,UMODE_AUSPEX))
        {
          sendto_one(sptr, form_str(ERR_NOSUCHNICK),
                     me.name, parv[0], nick);
 	  msgs++;
	  continue;
        }

      /* Disable the user%host@server form for non-opers
       * -Dianora
       */

      /* Disabled. This isn't very useful and I don't feel like mucking around with privs for it
       *  -- asuffield */
      if((char *)strchr(nick,'%'))
        {
          sendto_one(sptr, form_str(ERR_NOSUCHNICK),
                     me.name, parv[0], nick);
 	  msgs++;
	  continue;
        }
        
      /*
      ** Not destined for a user on me :-(
      */
      if (!IsMe(acptr))
        {
          sendto_one(acptr,":%s %s %s :%s", parv[0],
                     cmd, nick, parv[2]);
          msgs++;
          continue;
        }

      *server = '\0';

      /* special case opers@server */
      /* We don't want this on OPN -- asuffield */
#if 0
      if(!irccmp(nick,"opers") && SendWallops(sptr))
        {
          sendto_realops("To opers: From %s: %s",sptr->name,parv[2]);
          msgs++;
          continue;
        }
#endif
        
      if ((host = (char *)strchr(nick, '%')))
        *host++ = '\0';

      /*
      ** Look for users which match the destination host
      ** (no host == wildcard) and if one and one only is
      ** found connected to me, deliver message!
      */
      acptr = find_userhost(nick, host, NULL, &count);
      if (server)
        *server = '@';
      if (host)
        *--host = '%';
      if (acptr)
        {
          if (count == 1)
            sendto_prefix_one(acptr, sptr,
                              ":%s %s %s :%s",
                              parv[0], cmd,
                              nick, parv[2]);
          else if (!notice)
            sendto_one(sptr,
                       form_str(ERR_TOOMANYTARGETS),
                       me.name, parv[0], nick, MAX_MULTI_MESSAGES);
        }
      if (acptr)
	{
	  msgs++;
	  continue;
	}
    }
  /* Let's not send these remotely for channels */
  if (MyConnect(sptr) || (nick[0] != '#'))
    sendto_one(sptr, form_str(ERR_NOSUCHNICK), me.name,
	       parv[0], nick);
  msgs++;
  }
  if (strtok(NULL, ","))
    sendto_one(sptr, form_str(ERR_TOOMANYTARGETS),
                     me.name, parv[0], cmd, MAX_MULTI_MESSAGES);
  return 0;
}
Пример #25
0
/*
 * m_mode - MODE command handler
 * parv[0] - sender
 * parv[1] - channel
 */
static void
m_mode(struct Client *client_p, struct Client *source_p,
       int parc, char *parv[])
{
  struct Channel *chptr = NULL;
  struct Membership *member;
  static char modebuf[MODEBUFLEN];
  static char parabuf[MODEBUFLEN];

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

  /* Now, try to find the channel in question */
  if (!IsChanPrefix(parv[1][0]))
  {
    /* if here, it has to be a non-channel name */
    set_user_mode(client_p, source_p, parc, parv);
    return;
  }

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

  chptr = hash_find_channel(parv[1]);

  if (chptr == NULL)
  {
      /* if chptr isn't found locally, it =could= exist
       * on the uplink. So ask.
       */
      
      /* LazyLinks */
      /* only send a mode upstream if a local client sent this request
       * -davidt
       */
      if (MyClient(source_p) && !ServerInfo.hub && uplink &&
	   IsCapable(uplink, CAP_LL))
	{
	  sendto_one(uplink, ":%s MODE %s %s",
                     ID_or_name(source_p, uplink),
		     parv[1], (parv[2] ? parv[2] : ""));
	  return;
	}
      else
	{
	  sendto_one(source_p, form_str(ERR_NOSUCHCHANNEL),
		     me.name, parv[0], parv[1]);
	  return;
	}
    }

  /* Now known the channel exists */
  if (parc < 3)
  {
    channel_modes(chptr, source_p, modebuf, parabuf);
    sendto_one(source_p, form_str(RPL_CHANNELMODEIS),
               me.name, parv[0], parv[1], modebuf, parabuf);
    sendto_one(source_p, form_str(RPL_CREATIONTIME),
               me.name, parv[0], parv[1], chptr->channelts);
  }
  /* bounce all modes from people we deop on sjoin
   * servers have always gotten away with murder,
   * including telnet servers *g* - Dianora
   *
   * XXX Is it worth the bother to make an ms_mode() ? - Dianora
   */
  else if (IsServer(source_p))
  {
    set_channel_mode(client_p, source_p, chptr, NULL, parc - 2, parv + 2,
                     chptr->chname);
  }
  else
  {
    member = find_channel_link(source_p, chptr);

    if (!has_member_flags(member, CHFL_DEOPPED))
    {
      /* Finish the flood grace period... */
      if (MyClient(source_p) && !IsFloodDone(source_p))
      {
        if (!((parc == 3) && (parv[2][0] == 'b') && (parv[2][1] == '\0')))
          flood_endgrace(source_p);
      }

      set_channel_mode(client_p, source_p, chptr, member, parc - 2, parv + 2,
                       chptr->chname);
    }
  }
}
Пример #26
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);
	}
    }
}
Пример #27
0
static void
do_list(struct Client *source_p, char *arg)
{
  struct ListTask *lt = NULL;
  int no_masked_channels = 1;

  if (source_p->connection->list_task)
  {
    free_list_task(source_p);
    sendto_one_numeric(source_p, &me, RPL_LISTEND);
    return;
  }

  lt = MyCalloc(sizeof(struct ListTask));
  lt->users_max = UINT_MAX;
  lt->created_max = UINT_MAX;
  lt->topicts_max = UINT_MAX;
  source_p->connection->list_task = lt;

  if (!EmptyString(arg))
  {
    char *opt, *save = NULL;
    dlink_list *list = NULL;
    int i = 0, errors = 0;

    for (opt = strtoken(&save,  arg, ","); opt;
         opt = strtoken(&save, NULL, ","))
    {
      switch (*opt)
      {
        case '<':
          if ((i = atoi(opt + 1)) > 0)
            lt->users_max = (unsigned int)i - 1;
          else
            errors = 1;
          break;
        case '>':
          if ((i = atoi(opt + 1)) >= 0)
            lt->users_min = (unsigned int)i + 1;
          else
            errors = 1;
          break;
        case 'C':
        case 'c':
          switch (*++opt)
          {
            case '<':
              if ((i = atoi(opt + 1)) >= 0)
                lt->created_max = (unsigned int)(CurrentTime - 60 * i);
              else
                errors = 1;
              break;
            case '>':
              if ((i = atoi(opt + 1)) >= 0)
                lt->created_min = (unsigned int)(CurrentTime - 60 * i);
              else
                errors = 1;
              break;
            default:
              errors = 1;
          }

          break;

        case 'T':
        case 't':
          switch (*++opt)
          {
            case '<':
              if ((i = atoi(opt + 1)) >= 0)
                lt->topicts_min = (unsigned int)(CurrentTime - 60 * i);
              else
                errors = 1;
              break;
            case '>':
              if ((i = atoi(opt + 1)) >= 0)
                lt->topicts_max = (unsigned int)(CurrentTime - 60 * i);
              else
                errors = 1;
              break;
            case ':':
              if (strlcpy(lt->topic, opt + 1, sizeof(lt->topic)) == 0)
                errors = 1;
              break;
            default:
              errors = 1;
          }

          break;

        default:
          if (*opt == '!')
          {
            list = &lt->hide_mask;
            opt++;
          }
          else
            list = &lt->show_mask;

          if (has_wildcards(opt + !!IsChanPrefix(*opt)))
          {
            if (list == &lt->show_mask)
              no_masked_channels = 0;
          }
          else if (!IsChanPrefix(*opt))
            errors = 1;

          if (!errors)
            dlinkAdd(xstrdup(opt), make_dlink_node(), list);
      }
    }

    if (errors)
    {
      free_list_task(source_p);
      sendto_one_numeric(source_p, &me, ERR_LISTSYNTAX);
      return;
    }
  }

  dlinkAdd(source_p, &lt->node, &listing_client_list);

  sendto_one_numeric(source_p, &me, RPL_LISTSTART);
  safe_list_channels(source_p, no_masked_channels && lt->show_mask.head != NULL);
}
Пример #28
0
static int
ms_bmask(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{
	static char modebuf[BUFSIZE];
	static char parabuf[BUFSIZE];
	struct Channel *chptr;
	rb_dlink_list *banlist;
	const char *s;
	char *t;
	char *mbuf;
	char *pbuf;
	long mode_type;
	int mlen;
	int plen = 0;
	int tlen;
	int arglen;
	int modecount = 0;
	int needcap = NOCAPS;
	int mems;
	struct Client *fakesource_p;

	if(!IsChanPrefix(parv[2][0]) || !check_channel_name(parv[2]))
		return 0;

	if((chptr = find_channel(parv[2])) == NULL)
		return 0;

	/* TS is higher, drop it. */
	if(atol(parv[1]) > chptr->channelts)
		return 0;

	switch (parv[3][0])
	{
	case 'b':
		banlist = &chptr->banlist;
		mode_type = CHFL_BAN;
		mems = ALL_MEMBERS;
		break;

	case 'e':
		banlist = &chptr->exceptlist;
		mode_type = CHFL_EXCEPTION;
		needcap = CAP_EX;
		mems = ONLY_HALFOPSANDUP;
		break;

	case 'I':
		banlist = &chptr->invexlist;
		mode_type = CHFL_INVEX;
		needcap = CAP_IE;
		mems = ONLY_HALFOPSANDUP;
		break;

	case 'Z':
		banlist = &chptr->quietlist;
		mode_type = CHFL_QUIET;
		mems = ALL_MEMBERS;
		break;
	/* XXX should use encap? */
	case 'y':
		banlist = &chptr->censorlist;
		mode_type = CHFL_CENSOR;
		mems = ALL_MEMBERS;
		break;
		/* maybe we should just blindly propagate this? */
	default:
		return 0;
	}

	parabuf[0] = '\0';
	s = LOCAL_COPY(parv[4]);

	/* Hide connecting server on netburst -- jilles */
	if (ConfigServerHide.flatten_links && !HasSentEob(source_p))
		fakesource_p = &me;
	else
		fakesource_p = source_p;
	mlen = rb_sprintf(modebuf, ":%s MODE %s +", fakesource_p->name, chptr->chname);
	mbuf = modebuf + mlen;
	pbuf = parabuf;

	while(*s == ' ')
		s++;

	/* next char isnt a space, point t to the next one */
	if((t = strchr(s, ' ')) != NULL)
	{
		*t++ = '\0';

		/* double spaces will break the parser */
		while(*t == ' ')
			t++;
	}

	/* couldve skipped spaces and got nothing.. */
	while(!EmptyString(s))
	{
		/* ban with a leading ':' -- this will break the protocol */
		if(*s == ':')
			goto nextban;

		tlen = strlen(s);

		/* I dont even want to begin parsing this.. */
		if(tlen > MODEBUFLEN)
			break;

		if(add_id(fakesource_p, chptr, s, banlist, mode_type))
		{
			/* this new one wont fit.. */
			if(mlen + MAXMODEPARAMS + plen + tlen > BUFSIZE - 5 ||
			   modecount >= MAXMODEPARAMS)
			{
				*mbuf = '\0';
				*(pbuf - 1) = '\0';
				sendto_channel_local(mems, chptr, "%s %s", modebuf, parabuf);
				sendto_server(client_p, chptr, needcap, CAP_TS6,
					      "%s %s", modebuf, parabuf);

				mbuf = modebuf + mlen;
				pbuf = parabuf;
				plen = modecount = 0;
			}

			*mbuf++ = parv[3][0];
			arglen = rb_sprintf(pbuf, "%s ", s);
			pbuf += arglen;
			plen += arglen;
			modecount++;
		}

	      nextban:
		s = t;

		if(s != NULL)
		{
			if((t = strchr(s, ' ')) != NULL)
			{
				*t++ = '\0';

				while(*t == ' ')
					t++;
			}
		}
	}

	if(modecount)
	{
		*mbuf = '\0';
		*(pbuf - 1) = '\0';
		sendto_channel_local(mems, chptr, "%s %s", modebuf, parabuf);
		sendto_server(client_p, chptr, needcap, CAP_TS6, "%s %s", modebuf, parabuf);
	}

	sendto_server(client_p, chptr, CAP_TS6 | needcap, NOCAPS, ":%s BMASK %ld %s %s :%s",
		      source_p->id, (long) chptr->channelts, chptr->chname, parv[3], parv[4]);
	return 0;
}
Пример #29
0
/*
 * mo_omode - MODE command handler
 * parv[1] - channel
 */
static int
mo_omode(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{
	struct Channel *chptr = NULL;
	struct membership *msptr;
	char params[512];
	int i;
	int wasonchannel;
	/* admins only */
	if (!IsOperAdmin(source_p)) {
		sendto_one(source_p, form_str(ERR_NOPRIVS), me.name, source_p->name, "admin");
		return 0;
	}
	/* Now, try to find the channel in question */
	if (!IsChanPrefix(parv[1][0]) || !check_channel_name(parv[1])) {
		sendto_one_numeric(source_p, ERR_BADCHANNAME,
		                   form_str(ERR_BADCHANNAME), parv[1]);
		return 0;
	}
	chptr = find_channel(parv[1]);
	if (chptr == NULL) {
		sendto_one_numeric(source_p, ERR_NOSUCHCHANNEL,
		                   form_str(ERR_NOSUCHCHANNEL), parv[1]);
		return 0;
	}
	/* Now know the channel exists */
	msptr = find_channel_membership(chptr, source_p);
	wasonchannel = msptr != NULL;
	if (is_any_op(msptr)) {
		sendto_one_notice(source_p, ":Use a normal MODE you idiot");
		return 0;
	}
	params[0] = '\0';
	for (i = 2; i < parc; i++) {
		if (i != 2)
			rb_strlcat(params, " ", sizeof params);
		rb_strlcat(params, parv[i], sizeof params);
	}
	sendto_wallops_flags(UMODE_WALLOP, &me,
	                     "OMODE called for [%s] [%s] by %s!%s@%s",
	                     parv[1], params, source_p->name, source_p->username, source_p->host);
	ilog(L_MAIN, "OMODE called for [%s] [%s] by %s",
	     parv[1], params, get_oper_name(source_p));
	if (*chptr->chname != '&')
		sendto_server(NULL, NULL, NOCAPS, NOCAPS,
		              ":%s WALLOPS :OMODE called for [%s] [%s] by %s!%s@%s",
		              me.name, parv[1], params, source_p->name, source_p->username,
		              source_p->host);
#if 0
	set_channel_mode(client_p, source_p->servptr, chptr, msptr,
	                 parc - 2, parv + 2);
#else
	if (parc == 4 && !strcmp(parv[2], "+y") && !irccmp(parv[3], source_p->name)) {
		/* Ownering themselves */
		if (!wasonchannel) {
			sendto_one_numeric(source_p, ERR_USERNOTINCHANNEL,
			                   form_str(ERR_USERNOTINCHANNEL), parv[3], chptr->chname);
			return 0;
		}
		sendto_channel_local(ALL_MEMBERS, chptr, ":%s MODE %s +y %s",
		                     me.name, parv[1], source_p->name);
		sendto_server(NULL, chptr, CAP_TS6, NOCAPS,
		              ":%s TMODE %ld %s +y %s",
		              me.id, (long) chptr->channelts, parv[1],
		              source_p->id);
		msptr->flags |= CHFL_OWNER;
	} else if (parc == 4 && !strcmp(parv[2], "+a") && !irccmp(parv[3], source_p->name)) {
		/* Admining themselves */
		if (!wasonchannel) {
			sendto_one_numeric(source_p, ERR_USERNOTINCHANNEL,
			                   form_str(ERR_USERNOTINCHANNEL), parv[3], chptr->chname);
			return 0;
		}
		sendto_channel_local(ALL_MEMBERS, chptr, ":%s MODE %s +a %s",
		                     me.name, parv[1], source_p->name);
		sendto_server(NULL, chptr, CAP_TS6, NOCAPS,
		              ":%s TMODE %ld %s +a %s",
		              me.id, (long) chptr->channelts, parv[1],
		              source_p->id);
		msptr->flags |= CHFL_ADMIN;
	} else if (parc == 4 && !strcmp(parv[2], "+o") && !irccmp(parv[3], source_p->name)) {
		/* Opping themselves */
		if (!wasonchannel) {
			sendto_one_numeric(source_p, ERR_USERNOTINCHANNEL,
			                   form_str(ERR_USERNOTINCHANNEL), parv[3], chptr->chname);
			return 0;
		}
		sendto_channel_local(ALL_MEMBERS, chptr, ":%s MODE %s +o %s",
		                     me.name, parv[1], source_p->name);
		sendto_server(NULL, chptr, CAP_TS6, NOCAPS,
		              ":%s TMODE %ld %s +o %s",
		              me.id, (long) chptr->channelts, parv[1],
		              source_p->id);
		msptr->flags |= CHFL_CHANOP;
	} else if (parc == 4 && !strcmp(parv[2], "+h") && !irccmp(parv[3], source_p->name)) {
		/* Halfopping themselves */
		if (!wasonchannel) {
			sendto_one_numeric(source_p, ERR_USERNOTINCHANNEL,
			                   form_str(ERR_USERNOTINCHANNEL), parv[3], chptr->chname);
			return 0;
		}
		sendto_channel_local(ALL_MEMBERS, chptr, ":%s MODE %s +h %s",
		                     me.name, parv[1], source_p->name);
		sendto_server(NULL, chptr, CAP_TS6, NOCAPS,
		              ":%s TMODE %ld %s +h %s",
		              me.id, (long) chptr->channelts, parv[1],
		              source_p->id);
		msptr->flags |= CHFL_HALFOP;
	} else if (ConfigChannel.use_owner) {
		/* I hope this is correct.
		 * -- Kabaka */
		/* Hack it so set_channel_mode() will accept */
		if (wasonchannel)
			msptr->flags |= CHFL_OWNER;
		else {
			add_user_to_channel(chptr, source_p, CHFL_CHANOP);
			msptr = find_channel_membership(chptr, source_p);
		}
		set_channel_mode(client_p, source_p, chptr, msptr,
		                 parc - 2, parv + 2);
		if (wasonchannel)
			msptr->flags &= ~CHFL_OWNER;
		else
			remove_user_from_channel(msptr);
	} else if (ConfigChannel.use_admin) {
		/* Hack it so set_channel_mode() will accept */
		if (wasonchannel)
			msptr->flags |= CHFL_ADMIN;
		else {
			add_user_to_channel(chptr, source_p, CHFL_CHANOP);
			msptr = find_channel_membership(chptr, source_p);
		}
		set_channel_mode(client_p, source_p, chptr, msptr,
		                 parc - 2, parv + 2);
		/* We know they were not opped before and they can't have opped
		 * themselves as set_channel_mode() does not allow that
		 * -- jilles */
		if (wasonchannel)
			msptr->flags &= ~CHFL_ADMIN;
		else
			remove_user_from_channel(msptr);
	} else {
		/* CHFL_ADMIN is only useful if admin is enabled
		 * so hack it with op if it is not. */
		if (wasonchannel)
			msptr->flags |= CHFL_CHANOP;
		else {
			add_user_to_channel(chptr, source_p, CHFL_CHANOP);
			msptr = find_channel_membership(chptr, source_p);
		}
		set_channel_mode(client_p, source_p, chptr, msptr,
		                 parc - 2, parv + 2);
		/* We know they were not opped before and they can't have opped
		 * themselves as set_channel_mode() does not allow that
		 * -- jilles */
		if (wasonchannel)
			msptr->flags &= ~CHFL_CHANOP;
		else
			remove_user_from_channel(msptr);
	}
#endif
	return 0;
}
Пример #30
0
/*
 * m_mode - MODE command handler
 * parv[1] - channel
 */
static int
m_mode(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{
	struct Channel *chptr = NULL;
	struct membership *msptr;
	int n = 2;
	const char *dest;
	int operspy = 0;

	dest = parv[1];

	if(IsOperSpy(source_p) && *dest == '!')
	{
		dest++;
		operspy = 1;

		if(EmptyString(dest))
		{
			sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS),
				   me.name, source_p->name, "MODE");
			return 0;
		}
	}

	/* Now, try to find the channel in question */
	if(!IsChanPrefix(*dest))
	{
		/* if here, it has to be a non-channel name */
		user_mode(client_p, source_p, parc, parv);
		return 0;
	}

	if(!check_channel_name(dest))
	{
		sendto_one_numeric(source_p, ERR_BADCHANNAME, form_str(ERR_BADCHANNAME), parv[1]);
		return 0;
	}

	chptr = find_channel(dest);

	if(chptr == NULL)
	{
		sendto_one_numeric(source_p, ERR_NOSUCHCHANNEL,
				   form_str(ERR_NOSUCHCHANNEL), parv[1]);
		return 0;
	}

	/* Now know the channel exists */
	if(parc < n + 1)
	{
		if(operspy)
			report_operspy(source_p, "MODE", chptr->chname);

		sendto_one(source_p, form_str(RPL_CHANNELMODEIS),
			   me.name, source_p->name, parv[1],
			   operspy ? channel_modes(chptr, &me) : channel_modes(chptr, source_p));

		sendto_one(source_p, form_str(RPL_CREATIONTIME),
			   me.name, source_p->name, parv[1], chptr->channelts);
	}
	else
	{
		msptr = find_channel_membership(chptr, source_p);

		/* Finish the flood grace period... */
		if(MyClient(source_p) && !IsFloodDone(source_p))
		{
			if(!((parc == 3) && (parv[2][0] == 'b') && (parv[2][1] == '\0')))
				flood_endgrace(source_p);
		}

		set_channel_mode(client_p, source_p, chptr, msptr, parc - n, parv + n);
	}

	return 0;
}