Ejemplo n.º 1
0
static int
me_forcepart(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{
    struct Client *target_p;
    const char *user, *channels, *reason;
    const char default_reason[] = "Leaving";
    int chasing = 0;

    user = parv[1];
    channels = parv[2];

    if(EmptyString(parv[2]))
        return 0;
    else
        channels = parv[2];

    if(EmptyString(parv[3]))
        reason = default_reason;
    else
    {
        char *s;
        s = LOCAL_COPY(parv[3]);
        if(strlen(s) > (size_t) REASONLEN)
            s[REASONLEN] = '\0';
        reason = s;
    }

    /* Find the user */
    if((target_p = find_chasing(source_p, user, &chasing)) == NULL)
        return 0;

    if(IsServer(target_p) || IsMe(target_p))
        return 0;

    ilog(L_MAIN, "FORCEPART called for [%s] by %s!%s@%s",
         target_p->name, source_p->name, source_p->username, source_p->host);

    if(!MyClient(target_p))
    {
        struct Client *cptr = target_p->servptr;
        sendto_one(cptr, ":%s ENCAP %s FORCEPART %s :%s",
                   get_id(source_p, cptr), cptr->name, get_id(target_p, cptr), channels);
        return 0;
    }

    forcepart_channels(client_p, source_p, target_p, channels, reason);

    return 0;
}
Ejemplo n.º 2
0
/*
** mo_forcejoin
**      parv[1] = forcejoin victim
**      parv[2] = forcejoin channel list
*/
static int
mo_forcejoin(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{
	struct Client *target_p;
	const char *user, *chanlist;
	int chasing = 0;

	user = parv[1];

	if(!IsOperForce(source_p))
	{
		sendto_one(source_p, form_str(ERR_NOPRIVS), me.name, source_p->name, "force");
		return 0;
	}

	if(EmptyString(parv[2]))
	{
		sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS), me.name, source_p->name, "FORCEJOIN");
		return 0;
	}
	else
		chanlist = parv[2];

	if((target_p = find_chasing(source_p, user, &chasing)) == NULL)
		return 0;

	sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
			     "Received FORCEJOIN message for %s!%s@%s. From %s (Channels: %s)",
			     target_p->name, target_p->username, target_p->orighost, 
			     source_p->name, chanlist);

	ilog(L_MAIN, "FORCEJOIN called for [%s] by %s!%s@%s",
	     target_p->name, source_p->name, source_p->username, source_p->host);

	if(!MyClient(target_p))
	{
		struct Client *cptr = target_p->servptr;
		sendto_one(cptr, ":%s ENCAP %s FORCEJOIN %s :%s", 
			   get_id(source_p, cptr), cptr->name, get_id(target_p, cptr), chanlist);
		return 0;
	}

	user_join_override(client_p, source_p, target_p, chanlist);

	return 0;
}
Ejemplo n.º 3
0
/*
 * me_forcejoin
 *      parv[1] = forcejoin victim
 *      parv[2] = forcejoin channel list 
 */
static int
me_forcejoin(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{
	struct Client *target_p;
	const char *user, *chanlist;
	int chasing = 0;

	user = parv[1];
	
	if(EmptyString(parv[2]))
		return 0;
	else
		chanlist = parv[2];

	/* Find the user */
	if((target_p = find_chasing(source_p, user, &chasing)) == NULL)
		return 0;
	
	if(IsServer(target_p) || IsMe(target_p))
		return 0;
	
	ilog(L_MAIN, "FORCEJOIN called for [%s] by %s!%s@%s",
	     target_p->name, source_p->name, source_p->username, source_p->host);

	if(!MyClient(target_p))
	{
		struct Client *cptr = target_p->servptr;
		sendto_one(cptr, ":%s ENCAP %s FORCEJOIN %s :%s", 
			   get_id(source_p, cptr), cptr->name, get_id(target_p, cptr), chanlist);
		return 0;
	}

	user_join_override(client_p, source_p, target_p, chanlist);

	return 0;
}
Ejemplo n.º 4
0
/*
 * m_kick - generic message handler
 *
 * parv[0] = sender prefix
 * parv[1] = channel
 * parv[2] = client to kick
 * parv[parc-1] = kick comment
 */
int m_kick(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
{
  struct Client *who;
  struct Channel *chptr;
  struct Membership *member = 0;
  struct Membership* member2;
  char *name, *comment;

  ClrFlag(sptr, FLAG_TS8);

  if (parc < 3 || *parv[1] == '\0')
    return need_more_params(sptr, "KICK");

  name = parv[1];

  /* simple checks */
  if (!(chptr = get_channel(sptr, name, CGT_NO_CREATE)))
    return send_reply(sptr, ERR_NOSUCHCHANNEL, name);

  if (!(member2 = find_member_link(chptr, sptr)) || IsZombie(member2)
      || !IsChanOp(member2))
    return send_reply(sptr, ERR_CHANOPRIVSNEEDED, name);

  if (!(who = find_chasing(sptr, parv[2], 0)))
    return 0; /* find_chasing sends the reply for us */

  /* Don't allow the channel service to be kicked */
  if (IsChannelService(who))
    return send_reply(sptr, ERR_ISCHANSERVICE, cli_name(who), chptr->chname);

  /* Prevent kicking opers from local channels -DM- */
  if (IsLocalChannel(chptr->chname) && HasPriv(who, PRIV_DEOP_LCHAN))
    return send_reply(sptr, ERR_ISOPERLCHAN, cli_name(who), chptr->chname);

  /* check if kicked user is actually on the channel */
  if (!(member = find_member_link(chptr, who)) || IsZombie(member))
    return send_reply(sptr, ERR_USERNOTINCHANNEL, cli_name(who), chptr->chname);

  /* Don't allow to kick member with a higher op-level,
   * or members with the same op-level unless both are MAXOPLEVEL.
   */
  if (OpLevel(member) < OpLevel(member2)
      || (OpLevel(member) == OpLevel(member2)
          && OpLevel(member) < MAXOPLEVEL))
    return send_reply(sptr, ERR_NOTLOWEROPLEVEL, cli_name(who), chptr->chname,
	OpLevel(member2), OpLevel(member), "kick",
	OpLevel(member) == OpLevel(member2) ? "the same" : "a higher");

  /* We rely on ircd_snprintf to truncate the comment */
  comment = EmptyString(parv[parc - 1]) ? parv[0] : parv[parc - 1];

  if (!IsLocalChannel(name))
    sendcmdto_serv_butone(sptr, CMD_KICK, cptr, "%H %C :%s", chptr, who,
			  comment);

  if (IsDelayedJoin(member)) {
    /* If it's a delayed join, only send the KICK to the person doing
     * the kicking and the victim */
    if (MyUser(who))
      sendcmdto_one(sptr, CMD_KICK, who, "%H %C :%s", chptr, who, comment);
    sendcmdto_one(who, CMD_JOIN, sptr, "%H", chptr);
    sendcmdto_one(sptr, CMD_KICK, sptr, "%H %C :%s", chptr, who, comment);
    CheckDelayedJoins(chptr);
  } else
    sendcmdto_channel_butserv_butone(sptr, CMD_KICK, chptr, NULL, 0, "%H %C :%s", chptr, who,
                                     comment);

  make_zombie(member, who, cptr, sptr, chptr);

  return 0;
}
Ejemplo n.º 5
0
/*
** m_kick
**      parv[1] = channel
**      parv[2] = client to kick
**      parv[3] = kick comment
*/
static int
m_kick(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{
	struct membership *msptr;
	struct Client *who;
	struct Channel *chptr;
	int chasing = 0;
	char *comment;
	const char *name;
	char *p = NULL;
	char text[10];
	const char *user;
	static char buf[BUFSIZE];
	int is_override = 0;

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

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

	name = parv[1];

	chptr = find_channel(name);
	if(chptr == NULL)
	{
		sendto_one_numeric(source_p, ERR_NOSUCHCHANNEL, form_str(ERR_NOSUCHCHANNEL), name);
		return 0;
	}

	user = parv[2];		/* strtoken(&p2, parv[2], ","); */

	if(!(who = find_chasing(source_p, user, &chasing)))
	{
		return 0;
	}

	if(!IsServer(source_p))
	{
		msptr = find_channel_membership(chptr, source_p);

		if((msptr == NULL) && MyConnect(source_p))
		{
			sendto_one_numeric(source_p, ERR_NOTONCHANNEL,
					   form_str(ERR_NOTONCHANNEL), name);
			return 0;
		}

		if(!can_kick_deop(msptr, find_channel_membership(chptr, who)))
		{
			if(MyConnect(source_p))
			{
				if(IsOverride(source_p))
					is_override = 1;
				else
				{
					sendto_one(source_p, ":%s 482 %s %s :You do not have the proper privileges to kick this user",
							me.name, source_p->name, name);
					return 0;
				}
			}

			/* If its a TS 0 channel, do it the old way */
			else if(chptr->channelts == 0)
			{
				sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED),
					   get_id(&me, source_p), get_id(source_p, source_p), name);
				return 0;
			}
		}

		/* Its a user doing a kick, but is not showing as chanop locally
		 * its also not a user ON -my- server, and the channel has a TS.
		 * There are two cases we can get to this point then...
		 *
		 *     1) connect burst is happening, and for some reason a legit
		 *        op has sent a KICK, but the SJOIN hasn't happened yet or 
		 *        been seen. (who knows.. due to lag...)
		 *
		 *     2) The channel is desynced. That can STILL happen with TS
		 *        
		 *     Now, the old code roger wrote, would allow the KICK to 
		 *     go through. Thats quite legit, but lets weird things like
		 *     KICKS by users who appear not to be chanopped happen,
		 *     or even neater, they appear not to be on the channel.
		 *     This fits every definition of a desync, doesn't it? ;-)
		 *     So I will allow the KICK, otherwise, things are MUCH worse.
		 *     But I will warn it as a possible desync.
		 *
		 *     -Dianora
		 */
	}

	if((p = strchr(parv[2], ',')))
		*p = '\0';

	msptr = find_channel_membership(chptr, who);

	if(msptr != NULL)
	{
		if(MyClient(source_p) && IsService(who))
		{
			sendto_one(source_p, form_str(ERR_ISCHANSERVICE),
				   me.name, source_p->name, who->name, chptr->chname);
			return 0;
		}

		if(MyClient(source_p) && chptr->mode.mode & MODE_NOKICK)
		{
			sendto_one_numeric(source_p, ERR_NOKICK,
					form_str(ERR_NOKICK),
					chptr->chname);
			return 0;
		}

		if (MyClient(source_p) && chptr->mode.mode & MODE_NOOPERKICK && IsOper(who))
		{
			sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
					"Overriding KICK from %s on %s in %s (channel is +M)",
					source_p->name, who->name, chptr->chname);
			sendto_one_numeric(source_p, ERR_ISCHANSERVICE,
					"%s %s :Cannot kick IRC operators from that channel.",
					who->name, chptr->chname);
			return 0;
		}

		if(MyClient(source_p))
		{
			hook_data_channel_approval hookdata;

			hookdata.client = source_p;
			hookdata.chptr = chptr;
			hookdata.target = who;
			hookdata.approved = 1;

			call_hook(h_can_kick, &hookdata);

			if (!hookdata.approved)
				return 0;
		}

		comment = LOCAL_COPY((EmptyString(parv[3])) ? who->name : parv[3]);
		if(strlen(comment) > (size_t) REASONLEN)
			comment[REASONLEN] = '\0';

		if(is_override)
		{
			sendto_wallops_flags(UMODE_WALLOP, &me,
					"%s is overriding KICK [%s] on [%s] [%s]",
					get_oper_name(source_p), who->name, chptr->chname, comment);
			sendto_server(NULL, chptr, NOCAPS, NOCAPS,
					":%s WALLOPS :%s is overriding KICK [%s] on [%s] [%s]",
					me.name, get_oper_name(source_p), who->name, chptr->chname, comment);
		}

		/* jdc
		 * - In the case of a server kicking a user (i.e. CLEARCHAN),
		 *   the kick should show up as coming from the server which did
		 *   the kick.
		 * - Personally, flame and I believe that server kicks shouldn't
		 *   be sent anyways.  Just waiting for some oper to abuse it...
		 */
		if(IsServer(source_p))
			sendto_channel_local(ALL_MEMBERS, chptr, ":%s KICK %s %s :%s",
					     source_p->name, name, who->name, comment);
		else
			sendto_channel_local(ALL_MEMBERS, chptr,
					     ":%s!%s@%s KICK %s %s :%s",
					     source_p->name, source_p->username,
					     source_p->host, name, who->name, comment);

		sendto_server(client_p, chptr, CAP_TS6, NOCAPS,
			      ":%s KICK %s %s :%s",
			      use_id(source_p), chptr->chname, use_id(who), comment);
		remove_user_from_channel(msptr);

		rb_snprintf(text, sizeof(text), "K%s", who->id);

		/* we don't need to track NOREJOIN stuff unless it's our client being kicked */
		if(MyClient(who) && chptr->mode.mode & MODE_NOREJOIN)
			channel_metadata_time_add(chptr, text, rb_current_time(), "KICKNOREJOIN");
	}
	else if (MyClient(source_p))
		sendto_one_numeric(source_p, ERR_USERNOTINCHANNEL,
				   form_str(ERR_USERNOTINCHANNEL), user, name);

	return 0;
}
Ejemplo n.º 6
0
/*
** m_okick
**      parv[0] = sender prefix
**      parv[1] = channel
**      parv[2] = client to kick
**      parv[3] = kick comment
*/
static void m_okick(struct Client *client_p,
                  struct Client *source_p,
                  int parc,
                  char *parv[])
{
  struct Client *who;
  struct Channel *chptr;
  int   chasing = 0;
  char  *comment;
  char  *name;
  char  *p = NULL;
  char  *user;
  static char     buf[BUFSIZE];

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

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

  comment = (EmptyString(parv[3])) ? parv[2] : parv[3];
  if (strlen(comment) > (size_t) TOPICLEN)
    comment[TOPICLEN] = '\0';

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

  name = parv[1];

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


  if( (p = strchr(parv[2],',')) )
    *p = '\0';

  user = parv[2]; /* strtoken(&p2, parv[2], ","); */

  if (!(who = find_chasing(source_p, user, &chasing)))
    {
      return;
    }

  if (IsMember(who, chptr))
    {
      sendto_channel_local(ALL_MEMBERS, chptr, ":%s KICK %s %s :%s",
          me.name, chptr->chname, who->name, comment);
      sendto_server(&me, chptr, NOCAPS, NOCAPS,
                    ":%s KICK %s %s :%s",
                    me.name, chptr->chname,
                    who->name, comment);
      remove_user_from_channel(chptr, who);
   }
}
Ejemplo n.º 7
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);
  }
}
Ejemplo n.º 8
0
static int
m_remove(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{
	struct membership *msptr;
	struct Client *who;
	struct Channel *chptr;
	int chasing = 0;
	char *comment;
	const char *name;
	char *p = NULL;
	const char *user;
	static char buf[BUFSIZE];

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

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

	name = parv[1];

	chptr = find_channel(name);
	if(chptr == NULL)
	{
		sendto_one_numeric(source_p, ERR_NOSUCHCHANNEL, form_str(ERR_NOSUCHCHANNEL), name);
		return 0;
	}

	if(!IsServer(source_p))
	{
		msptr = find_channel_membership(chptr, source_p);

		if((msptr == NULL) && MyConnect(source_p))
		{
			sendto_one_numeric(source_p, ERR_NOTONCHANNEL,
					   form_str(ERR_NOTONCHANNEL), name);
			return 0;
		}

		if(get_channel_access(source_p, msptr, MODE_ADD) < CHFL_CHANOP)
		{
			if(MyConnect(source_p))
			{
				sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED),
					   me.name, source_p->name, name);
				return 0;
			}

			/* If its a TS 0 channel, do it the old way */
			if(chptr->channelts == 0)
			{
				sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED),
					   get_id(&me, source_p), get_id(source_p, source_p), name);
				return 0;
			}
		}

		/* Its a user doing a kick, but is not showing as chanop locally
		 * its also not a user ON -my- server, and the channel has a TS.
		 * There are two cases we can get to this point then...
		 *
		 *     1) connect burst is happening, and for some reason a legit
		 *        op has sent a KICK, but the SJOIN hasn't happened yet or
		 *        been seen. (who knows.. due to lag...)
		 *
		 *     2) The channel is desynced. That can STILL happen with TS
		 *
		 *     Now, the old code roger wrote, would allow the KICK to
		 *     go through. Thats quite legit, but lets weird things like
		 *     KICKS by users who appear not to be chanopped happen,
		 *     or even neater, they appear not to be on the channel.
		 *     This fits every definition of a desync, doesn't it? ;-)
		 *     So I will allow the KICK, otherwise, things are MUCH worse.
		 *     But I will warn it as a possible desync.
		 *
		 *     -Dianora
		 */
	}

	if((p = strchr(parv[2], ',')))
		*p = '\0';

	user = parv[2];		/* strtoken(&p2, parv[2], ","); */

	if(!(who = find_chasing(source_p, user, &chasing)))
	{
		return 0;
	}

	msptr = find_channel_membership(chptr, who);

	if(msptr != NULL)
	{
		if(MyClient(source_p) && IsService(who))
		{
			sendto_one(source_p, form_str(ERR_ISCHANSERVICE),
				   me.name, source_p->name, who->name, chptr->chname);
			return 0;
		}

		if(MyClient(source_p))
		{
			hook_data_channel_approval hookdata;

			hookdata.client = source_p;
			hookdata.chptr = chptr;
			hookdata.msptr = msptr;
			hookdata.target = who;
			hookdata.approved = 1;
			hookdata.dir = MODE_ADD;	/* ensure modules like override speak up */

			call_hook(h_can_kick, &hookdata);

			if (!hookdata.approved)
				return 0;
		}

		comment = LOCAL_COPY((EmptyString(parv[3])) ? who->name : parv[3]);
		if(strlen(comment) > (size_t) REASONLEN)
			comment[REASONLEN] = '\0';

		/* jdc
		 * - In the case of a server kicking a user (i.e. CLEARCHAN),
		 *   the kick should show up as coming from the server which did
		 *   the kick.
		 * - Personally, flame and I believe that server kicks shouldn't
		 *   be sent anyways.  Just waiting for some oper to abuse it...
		 */
		sendto_channel_local(ALL_MEMBERS, chptr,
				     ":%s!%s@%s PART %s :requested by %s (%s)",
				     who->name, who->username,
				     who->host, name, source_p->name, comment);

		sendto_server(client_p, chptr, CAP_REMOVE, NOCAPS,
			      ":%s REMOVE %s %s :%s",
			      use_id(source_p), chptr->chname, use_id(who), comment);
		sendto_server(client_p, chptr, NOCAPS, CAP_REMOVE,
			      ":%s KICK %s %s :%s",
			      use_id(source_p), chptr->chname, use_id(who), comment);

		remove_user_from_channel(msptr);
	}
	else if (MyClient(source_p))
		sendto_one_numeric(source_p, ERR_USERNOTINCHANNEL,
				   form_str(ERR_USERNOTINCHANNEL), user, name);

	return 0;
}
Ejemplo n.º 9
0
/*
** m_kick
**      parv[0] = sender prefix
**      parv[1] = channel
**      parv[2] = client to kick
**      parv[3] = kick comment
*/
static void m_kick(struct Client *client_p,
                  struct Client *source_p,
                  int parc,
                  char *parv[])
{
  struct Client *who;
  struct Channel *chptr;
  int   chasing = 0;
  char  *comment;
  char  *name;
  char  *p = (char *)NULL;
  char  *user;
  static char     buf[BUFSIZE];

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

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

  comment = (BadPtr(parv[3])) ? parv[2] : parv[3];
  if (strlen(comment) > (size_t) TOPICLEN)
    comment[TOPICLEN] = '\0';

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

  name = parv[1];

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


  if (!IsServer(source_p) && !is_chan_op(chptr, source_p) ) 
    { 
      /* was a user, not a server, and user isn't seen as a chanop here */
      
      if(MyConnect(source_p))
        {
          /* user on _my_ server, with no chanops.. so go away */
          
          sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED),
                     me.name, parv[0], name);
          return;
        }

      if(chptr->channelts == 0)
        {
          /* If its a TS 0 channel, do it the old way */
          
          sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED),
                     me.name, parv[0], name);
          return;
        }

      /* Its a user doing a kick, but is not showing as chanop locally
       * its also not a user ON -my- server, and the channel has a TS.
       * There are two cases we can get to this point then...
       *
       *     1) connect burst is happening, and for some reason a legit
       *        op has sent a KICK, but the SJOIN hasn't happened yet or 
       *        been seen. (who knows.. due to lag...)
       *
       *     2) The channel is desynced. That can STILL happen with TS
       *        
       *     Now, the old code roger wrote, would allow the KICK to 
       *     go through. Thats quite legit, but lets weird things like
       *     KICKS by users who appear not to be chanopped happen,
       *     or even neater, they appear not to be on the channel.
       *     This fits every definition of a desync, doesn't it? ;-)
       *     So I will allow the KICK, otherwise, things are MUCH worse.
       *     But I will warn it as a possible desync.
       *
       *     -Dianora
       */
    }

  if( (p = strchr(parv[2],',')) )
    *p = '\0';

  user = parv[2]; /* strtoken(&p2, parv[2], ","); */

  if (!(who = find_chasing(source_p, user, &chasing)))
    {
      return;
    }

  if (IsMember(who, chptr))
    {
      /* jdc
       * - In the case of a server kicking a user (i.e. CLEARCHAN),
       *   the kick should show up as coming from the server which did
       *   the kick.
       * - Personally, flame and I believe that server kicks shouldn't
       *   be sent anyways.  Just waiting for some oper to abuse it...
       */
      if (IsServer(source_p))
      {
        sendto_channel_local(ALL_MEMBERS, chptr, ":%s KICK %s %s :%s",
          source_p->name, name, who->name, comment);
      }
#ifdef ANONOPS
      else if(chptr->mode.mode & MODE_HIDEOPS)
	{
	  /* jdc -- Non-chanops get kicked from me.name, not
	   *        who->name (themselves).
	   */
	  sendto_channel_local(NON_CHANOPS, chptr,
			       ":%s KICK %s %s :%s",
			       me.name,
			       name, who->name, comment);

	  sendto_channel_local(ONLY_CHANOPS, chptr,
			       ":%s!%s@%s KICK %s %s :%s",
			       source_p->name,
			       source_p->username,
			       source_p->host,
			       name,
			       who->name, comment);
	}
      else
#endif
	{
	  sendto_channel_local(ALL_MEMBERS, chptr,
			       ":%s!%s@%s KICK %s %s :%s",
			       source_p->name,
			       source_p->username,
			       source_p->host,
			       name, who->name, comment);
	}

      sendto_server(client_p, NOCAPS, NOCAPS,
                    ":%s KICK %s %s :%s",
                    parv[0], chptr->chname,
                    who->name, comment);
      remove_user_from_channel(chptr, who);
    }
  else
    sendto_one(source_p, form_str(ERR_USERNOTINCHANNEL),
               me.name, parv[0], user, name);
}
Ejemplo n.º 10
0
/*
 * mo_forcepart
 *	parv[1] = forcepart victim
 *	parv[2] = channels to part
 *	parv[3] = reason
 */
static int
mo_forcepart(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{
    struct Client *target_p;
    const char *user, *channels, *reason;
    const char default_reason[] = "Leaving";
    int chasing = 0;

    user = parv[1];
    channels = parv[2];

    if(!IsOper(source_p))
    {
        sendto_one(source_p, form_str(ERR_NOPRIVS), me.name, source_p->name);
        return 0;
    }

    /* if target_p == NULL then let the oper know */
    if((target_p = find_chasing(source_p, user, &chasing)) == NULL)
    {
        sendto_one(source_p, form_str(ERR_NOSUCHNICK), me.name, source_p->name, user);
        return 0;
    }

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

    if(EmptyString(parv[3]))
        reason = default_reason;
    else
    {
        char *s;
        s = LOCAL_COPY(parv[3]);
        if(strlen(s) > (size_t) REASONLEN)
            s[REASONLEN] = '\0';
        reason = s;
    }

    if(!IsClient(target_p))
        return 0;

    if(!MyClient(target_p) && (!IsOperAdmin(source_p)))
    {
        sendto_one_notice(source_p, ":Nick %s is not on your server and you do not have admin priv",
                          target_p->name);
        return 0;
    }

    sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
                           "Received FORCEPART message for %s!%s@%s. From %s (Channels: %s)",
                           target_p->name, target_p->username, target_p->host, source_p->name, channels);
    ilog(L_MAIN, "FORCEPART called for %s %s by %s!%s@%s (part reason %s)",
         user, channels, source_p->name, source_p->username, source_p->host, reason);

    sendto_one_notice(target_p, ":You have been forced to part %s",
                      channels);

    if(!MyClient(target_p))
    {
        struct Client *cptr = target_p->servptr;
        sendto_one(cptr, ":%s ENCAP %s FORCEPART %s :%s",
                   get_id(source_p, cptr), cptr->name, get_id(target_p, cptr), channels);
        return 0;
    }

    forcepart_channels(client_p, source_p, target_p, channels, reason);

    return 0;
}
Ejemplo n.º 11
0
/* m_kick()
 *  parv[0] = sender prefix
 *  parv[1] = channel
 *  parv[2] = client to kick
 *  parv[3] = kick comment
 */
static void 
m_kick(struct Client *client_p, struct Client *source_p,
       int parc, char *parv[])
{
  struct Client *who;
  struct Channel *chptr;
  int chasing = 0;
  int gmode_used = 0;
  char *comment;
  char *name;
  char *p = NULL;
  char *user;
  const char *from, *to;
  struct Membership *ms = NULL;
  struct Membership *ms_target;

  if (!MyConnect(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 (*parv[2] == '\0')
  {
    sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS),
               from, to, "KICK");
    return;
  }

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

  comment = (EmptyString(parv[3])) ? parv[2] : parv[3];
  if (strlen(comment) > (size_t)KICKLEN)
    comment[KICKLEN] = '\0';

  name = parv[1];
  while (*name == ',')
    name++;

  if ((p = strchr(name,',')) != NULL)
    *p = '\0';
  if (*name == '\0')
    return;

  if ((chptr = hash_find_channel(name)) == NULL)
  {
    sendto_one(source_p, form_str(ERR_NOSUCHCHANNEL),
               from, to, name);
    return;
  }

  if (!IsServer(source_p))
  {
    if ((ms = find_channel_link(source_p, chptr)) == NULL)
    {
      if (MyConnect(source_p))
      {
        sendto_one(source_p, form_str(ERR_NOTONCHANNEL),
                  me.name, source_p->name, name);
        return;
      }
    }

    if(chptr->mode.mode & MODE_NOCOLOR && msg_has_colors(comment))
        comment = strip_color(comment);
    if (!has_member_flags(ms, CHFL_CHANOP|CHFL_HALFOP))
    {
    /* was a user, not a server, and user isn't seen as a chanop here */
      if (IsGod(source_p) && MyConnect(source_p))
        gmode_used = TRUE;
      else if (MyConnect(source_p))
      {
        /* user on _my_ server, with no chanops.. so go away */
        sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED),
            me.name, source_p->name, name);
        return;
      }

      if (chptr->channelts == 0 && !IsGod(source_p))
      {
        /* If its a TS 0 channel, do it the old way */
        sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED),
              me.name, source_p->name, name);
        return;
      }
      /* Its a user doing a kick, but is not showing as chanop locally
       * its also not a user ON -my- server, and the channel has a TS.
       * There are two cases we can get to this point then...
       *
       *     1) connect burst is happening, and for some reason a legit
       *        op has sent a KICK, but the SJOIN hasn't happened yet or 
       *        been seen. (who knows.. due to lag...)
       *
       *     2) The channel is desynced. That can STILL happen with TS
       *        
       *     Now, the old code roger wrote, would allow the KICK to 
       *     go through. Thats quite legit, but lets weird things like
       *     KICKS by users who appear not to be chanopped happen,
       *     or even neater, they appear not to be on the channel.
       *     This fits every definition of a desync, doesn't it? ;-)
       *     So I will allow the KICK, otherwise, things are MUCH worse.
       *     But I will warn it as a possible desync.
       *
       *     -Dianora
       */
    }
  }

  user = parv[2];

  while (*user == ',')
    user++;

  if ((p = strchr(user, ',')) != NULL)
    *p = '\0';

  if (*user == '\0')
    return;

  if ((who = find_chasing(client_p, source_p, user, &chasing)) == NULL)
    return;

  if ((ms_target = find_channel_link(who, chptr)) != NULL)
  {
    if (IsGod(who))
    {
      char tmp[IRCD_BUFSIZE];
      ircsprintf(tmp, "%s is using God mode: to evade KICK from %s: %s %s %s",
          who->name, source_p->name, chptr->chname, parv[2], parv[3] ? parv[3] : "");
      sendto_gnotice_flags(UMODE_SERVNOTICE, L_ALL, me.name, &me, NULL, tmp);
      oftc_log(tmp);

      return;
    }

    if(IsService(who))
      return;

#ifdef HALFOPS
    /* half ops cannot kick other halfops on private channels */
    if (has_member_flags(ms, CHFL_HALFOP) && !has_member_flags(ms, CHFL_CHANOP))
    {
      if (((chptr->mode.mode & MODE_PRIVATE) && has_member_flags(ms_target,
        CHFL_CHANOP|CHFL_HALFOP)) || has_member_flags(ms_target, CHFL_CHANOP))
      {
        sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED),
                   me.name, source_p->name, name);
        return;
      }
    }
#endif

    /* jdc
     * - In the case of a server kicking a user (i.e. CLEARCHAN),
     *   the kick should show up as coming from the server which did
     *   the kick.
     * - Personally, flame and I believe that server kicks shouldn't
     *   be sent anyways.  Just waiting for some oper to abuse it...
     */
    if (IsServer(source_p))
      sendto_channel_local(ALL_MEMBERS, NO, chptr, ":%s KICK %s %s :%s",
                           source_p->name, name, who->name, comment);
    else
      sendto_channel_local(ALL_MEMBERS, NO, chptr, ":%s!%s@%s KICK %s %s :%s",
                           source_p->name, source_p->username,
                           source_p->host, name, who->name, comment);

    sendto_server(client_p, NULL, chptr, CAP_TS6, NOCAPS, NOFLAGS,
                  ":%s KICK %s %s :%s",
                  ID(source_p), chptr->chname, ID(who), comment);
    sendto_server(client_p, NULL, chptr, NOCAPS, CAP_TS6, NOFLAGS,
                  ":%s KICK %s %s :%s", source_p->name, chptr->chname,
                  who->name, comment);

    remove_user_from_channel(ms_target);
    if(gmode_used)
    {
      char tmp[IRCD_BUFSIZE];
      ircsprintf(tmp, "%s is using God mode: KICK %s %s %s",
          source_p->name, chptr->chname, parv[2], parv[3] ? parv[3] : "");
      sendto_gnotice_flags(UMODE_SERVNOTICE, L_ALL, me.name, &me, NULL, tmp);
      oftc_log(tmp);
    }
  }
  else
    sendto_one(source_p, form_str(ERR_USERNOTINCHANNEL),
               from, to, user, name);
}
Ejemplo n.º 12
0
/*
** m_okick
**      parv[0] = sender prefix
**      parv[1] = channel
**      parv[2] = client to kick
**      parv[3] = kick comment
*/
static int
mo_okick(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{
	struct Client *who;
	struct Client *target_p;
	struct Channel *chptr;
	struct membership *msptr;
	int chasing = 0;
	char *comment;
	char *name;
	char *p = NULL;
	char *user;
	static char buf[BUFSIZE];

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

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

	comment = (EmptyString(LOCAL_COPY(parv[3]))) ? LOCAL_COPY(parv[2]) : LOCAL_COPY(parv[3]);
	if(strlen(comment) > (size_t)REASONLEN)
		comment[REASONLEN] = '\0';

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

	name = LOCAL_COPY(parv[1]);

	chptr = find_channel(name);
	if(!chptr)
	{
		sendto_one_numeric(source_p, ERR_NOSUCHCHANNEL, form_str(ERR_NOSUCHCHANNEL), name);
		return 0;
	}


	if((p = strchr(parv[2], ',')))
		*p = '\0';
	user = LOCAL_COPY(parv[2]);	// strtoken(&p2, parv[2], ","); 
	if(!(who = find_chasing(source_p, user, &chasing)))
	{
		return 0;
	}

	if((target_p = find_client(user)) == NULL)
	{
		sendto_one(source_p, form_str(ERR_NOSUCHNICK), me.name, parv[0], user);
		return 0;
	}

	if((msptr = find_channel_membership(chptr, target_p)) == NULL)
	{
		sendto_one(source_p, form_str(ERR_USERNOTINCHANNEL),
			   me.name, parv[0], parv[1], parv[2]);
		return 0;
	}

	sendto_channel_local(ALL_MEMBERS, chptr, ":%s KICK %s %s :%s",
			     me.name, chptr->chname, who->name, comment);
	sendto_server(&me, chptr, NOCAPS, NOCAPS,
		      ":%s KICK %s %s :%s", me.name, chptr->chname, who->name, comment);
	remove_user_from_channel(msptr);
	return 0;
}
Ejemplo n.º 13
0
/*
** m_okick
**      parv[1] = channel
**      parv[2] = client to kick
**      parv[3] = kick comment
*/
static int
mo_okick(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{
	struct Client *who;
	struct Client *target_p;
	struct Channel *chptr;
	struct membership *msptr;
	int chasing = 0;
	char *comment;
	char *name;
	char *p = NULL;
	char *user;
	char text[10];
	static char buf[BUFSIZE];

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

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

	comment = (EmptyString(LOCAL_COPY(parv[3]))) ? LOCAL_COPY(parv[2]) : LOCAL_COPY(parv[3]);
	if(strlen(comment) > (size_t) TOPICLEN)
		comment[TOPICLEN] = '\0';

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

	name = LOCAL_COPY(parv[1]);

	chptr = find_channel(name);
	if(!chptr)
	{
		sendto_one_numeric(source_p, ERR_NOSUCHCHANNEL, form_str(ERR_NOSUCHCHANNEL), name);
		return 0;
	}


	if((p = strchr(parv[2], ',')))
		*p = '\0';
	user = LOCAL_COPY(parv[2]);	// strtoken(&p2, parv[2], ","); 
	if(!(who = find_chasing(source_p, user, &chasing)))
	{
		return 0;
	}

	if((target_p = find_client(user)) == NULL)
	{
		sendto_one(source_p, form_str(ERR_NOSUCHNICK), me.name, source_p->name, user);
		return 0;
	}

	if((msptr = find_channel_membership(chptr, target_p)) == NULL)
	{
		sendto_one(source_p, form_str(ERR_USERNOTINCHANNEL),
			   me.name, source_p->name, parv[1], parv[2]);
		return 0;
	}

	sendto_realops_snomask(SNO_GENERAL, L_ALL,
			       "OKICK called for %s %s by %s!%s@%s",
			       chptr->chname, target_p->name,
			       source_p->name, source_p->username, source_p->host);
	ilog(L_MAIN, "OKICK called for %s %s by %s",
	     chptr->chname, target_p->name,
	     get_oper_name(source_p));

	sendto_channel_local(ALL_MEMBERS, chptr, ":%s KICK %s %s :%s",
			     me.name, chptr->chname, who->name, comment);
	sendto_server(&me, chptr, CAP_TS6, NOCAPS,
		      ":%s KICK %s %s :%s", me.id, chptr->chname, who->id, comment);
	remove_user_from_channel(msptr);

	rb_snprintf(text, sizeof(text), "K%s", who->id);

	/* we don't need to track NOREJOIN stuff unless it's our client being kicked */
	if(MyClient(who) && chptr->mode.mode & MODE_NOREJOIN)
		channel_metadata_time_add(chptr, text, rb_current_time(), "KICKNOREJOIN");
	return 0;
}
Ejemplo n.º 14
0
/* mo_dline()
 *
 * inputs  - pointer to server
 *    - pointer to client
 *    - parameter count
 *    - parameter list
 * output  -
 * side effects - D line is added
 *
 */
static void
mo_dline(struct Client *client_p, struct Client *source_p,
         int parc, char *parv[])
{
  char def_reason[] = CONF_NOREASON;
  char *dlhost = NULL, *oper_reason = NULL, *reason = NULL;
  char *target_server = NULL;
  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 (!HasOFlag(source_p, OPER_FLAG_DLINE))
  {
    sendto_one(source_p, form_str(ERR_NOPRIVS),
               me.name, source_p->name, "dline");
    return;
  }

  if (parse_aline("DLINE", source_p,  parc, parv, AWILD, &dlhost,
                  NULL, &tkline_time, &target_server, &reason) < 0)
    return;

  if (target_server != NULL)
  {
    if (HasID(source_p))
    {
      sendto_server(NULL, CAP_DLN | CAP_TS6, NOCAPS,
                    ":%s DLINE %s %lu %s :%s",
                    source_p->id, target_server, (unsigned long)tkline_time,
                    dlhost, reason);
      sendto_server(NULL, CAP_DLN, CAP_TS6,
                    ":%s DLINE %s %lu %s :%s",
                    source_p->name, target_server, (unsigned long)tkline_time,
                    dlhost, reason);
    }
    else
      sendto_server(NULL, CAP_DLN, NOCAPS,
                    ":%s DLINE %s %lu %s :%s",
                    source_p->name, target_server, (unsigned long)tkline_time,
                    dlhost, reason);

    /* Allow ON to apply local kline as well if it matches */
    if (!match(target_server, me.name))
      return;
  }
  else
    cluster_a_line(source_p, "DLINE", CAP_DLN, SHARED_DLINE,
                   "%d %s :%s", tkline_time, dlhost, reason);

  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);
}
Ejemplo n.º 15
0
/* mo_dline()
 *
 * inputs	- pointer to server
 *		- pointer to client
 *		- parameter count
 *		- parameter list
 * output	-
 * side effects - D line is added
 *
 */
static void
mo_dline(struct Client *client_p, struct Client *source_p,
         int parc, char *parv[])
{
  char def_reason[] = CONF_NOREASON;
  char *dlhost = NULL, *reason = NULL;
  char *target_server = NULL;
  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 (!HasOFlag(source_p, OPER_FLAG_DLINE))
  {
    sendto_one(source_p, form_str(ERR_NOPRIVS),
               me.name, source_p->name, "dline");
    return;
  }

  if (parse_aline("DLINE", source_p,  parc, parv, AWILD, &dlhost,
                  NULL, &tkline_time, &target_server, &reason) < 0)
    return;

  if (target_server != NULL)
  {
    if (HasID(source_p))
    {
      sendto_server(NULL, CAP_DLN|CAP_TS6, NOCAPS,
                    ":%s DLINE %s %lu %s :%s",
                    source_p->id, target_server, (unsigned long)tkline_time,
                    dlhost, reason);
      sendto_server(NULL, CAP_DLN, CAP_TS6,
                    ":%s DLINE %s %lu %s :%s",
                    source_p->name, target_server, (unsigned long)tkline_time,
                    dlhost, reason);
    }
    else
      sendto_server(NULL, CAP_DLN, NOCAPS,
                    ":%s DLINE %s %lu %s :%s",
                    source_p->name, target_server, (unsigned long)tkline_time,
                    dlhost, reason);

    /* Allow ON to apply local kline as well if it matches */
    if (match(target_server, me.name))
      return;
  }
  else
    cluster_a_line(source_p, "DLINE", CAP_DLN, SHARED_DLINE,
                   "%d %s :%s", tkline_time, dlhost, reason);

  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;
}
Ejemplo n.º 16
0
/*
 * m_kick - generic message handler
 *
 * parv[0] = sender prefix
 * parv[1] = channel
 * parv[2] = client to kick
 * parv[parc-1] = kick comment
 */
int m_kick(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
{
  struct Client *who;
  struct Channel *chptr;
  struct Membership *member = 0;
  char *name, *comment;

  ClrFlag(sptr, FLAG_TS8);

  if (parc < 3 || *parv[1] == '\0')
    return need_more_params(sptr, "KICK");

  name = parv[1];

  /* simple checks */
  if (!(chptr = get_channel(sptr, name, CGT_NO_CREATE)))
    return send_reply(sptr, ERR_NOSUCHCHANNEL, name);

  if (!is_chan_op(sptr, chptr)  && !is_half_op(sptr, chptr))
    return send_reply(sptr, ERR_CHANOPRIVSNEEDED, name);

  if (!(who = find_chasing(sptr, parv[2], 0)))
    return 0; /* find_chasing sends the reply for us */

  /* Don't allow the channel service to be kicked */
  /*
   * ASUKA_X:
   * Allow +X'ed users to kick +k'ed, but not U-lined services.
   * --Bigfoot
   */
  if (IsChannelService(who) && IsService(cli_user(who)->server))
    return send_reply(sptr, ERR_ISCHANSERVICE, cli_name(who), chptr->chname, "a network service");

  if (IsChannelService(who) && !IsXtraOp(sptr) && (who!=sptr))
    return send_reply(sptr, ERR_ISCHANSERVICE, cli_name(who), chptr->chname, "an IRC operator");

  /* Don't allow halfops to kick chanops */
  if (is_chan_op(who, chptr) && is_half_op(sptr, chptr) && !is_chan_op(sptr, chptr))
     return send_reply(sptr, ERR_HALFCANTKICKOP, name);

  /* Prevent kicking opers from local channels -DM- */
  if (IsLocalChannel(chptr->chname) && HasPriv(who, PRIV_DEOP_LCHAN))
    return send_reply(sptr, ERR_ISOPERLCHAN, cli_name(who), chptr->chname);

  /* check if kicked user is actually on the channel */
  if (!(member = find_member_link(chptr, who)) || IsZombie(member))
    return send_reply(sptr, ERR_USERNOTINCHANNEL, cli_name(who), chptr->chname);

  /* We rely on ircd_snprintf to truncate the comment */
  comment = EmptyString(parv[parc - 1]) ? parv[0] : parv[parc - 1];

  if (!IsLocalChannel(name))
    sendcmdto_serv_butone(sptr, CMD_KICK, cptr, "%H %C :%s", chptr, who,
			  comment);

  sendcmdto_channel_butserv_butone((IsServer(sptr) ? &me : sptr), CMD_KICK,
				   chptr, NULL, 0, "%H %C :%s", chptr, who,
				   comment);

  make_zombie(member, who, cptr, sptr, chptr);

  return 0;
}
Ejemplo n.º 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, *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;
  }
}
Ejemplo n.º 18
0
/*
** m_okick
**      parv[1] = channel
**      parv[2] = client to kick
**      parv[3] = kick comment
*/
static void
mo_okick(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{
	struct Client *who;
	struct Client *target_p;
	struct Channel *chptr;
	struct membership *msptr;
	int chasing = 0;
	char *comment;
	char *name;
	char *p = NULL;
	char *user;
	static char buf[BUFSIZE];

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

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

	comment = (EmptyString(LOCAL_COPY(parv[3]))) ? LOCAL_COPY(parv[2]) : LOCAL_COPY(parv[3]);
	if(strlen(comment) > (size_t) TOPICLEN)
		comment[TOPICLEN] = '\0';

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

	name = LOCAL_COPY(parv[1]);

	chptr = find_channel(name);
	if(!chptr)
	{
		sendto_one_numeric(source_p, ERR_NOSUCHCHANNEL, form_str(ERR_NOSUCHCHANNEL), name);
		return;
	}


	if((p = strchr(parv[2], ',')))
		*p = '\0';
	user = LOCAL_COPY(parv[2]);	// strtoken(&p2, parv[2], ",");
	if(!(who = find_chasing(source_p, user, &chasing)))
	{
		return;
	}

	if((target_p = find_client(user)) == NULL)
	{
		sendto_one(source_p, form_str(ERR_NOSUCHNICK), user);
		return;
	}

	if((msptr = find_channel_membership(chptr, target_p)) == NULL)
	{
		sendto_one(source_p, form_str(ERR_USERNOTINCHANNEL), parv[1], parv[2]);
		return;
	}

	sendto_wallops_flags(UMODE_WALLOP, &me,
			     "OKICK called for %s %s by %s!%s@%s",
			     chptr->chname, target_p->name,
			     source_p->name, source_p->username, source_p->host);
	ilog(L_MAIN, "OKICK called for %s %s by %s",
	     chptr->chname, target_p->name,
	     get_oper_name(source_p));
	/* only sends stuff for #channels remotely */
	sendto_server(NULL, chptr, NOCAPS, NOCAPS,
			":%s WALLOPS :OKICK called for %s %s by %s!%s@%s",
			me.name, chptr->chname, target_p->name,
			source_p->name, source_p->username, source_p->host);

	sendto_channel_local(&me, ALL_MEMBERS, chptr, ":%s KICK %s %s :%s",
			     me.name, chptr->chname, who->name, comment);
	sendto_server(&me, chptr, CAP_TS6, NOCAPS,
		      ":%s KICK %s %s :%s", me.id, chptr->chname, who->id, comment);
	remove_user_from_channel(msptr);
}
Ejemplo n.º 19
0
/*
** m_kick
**      parv[0] = sender prefix
**      parv[1] = channel
**      parv[2] = client to kick
**      parv[3] = kick comment
*/
static int
m_kick(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{
    struct membership *msptr;
    struct Client *who;
    struct Channel *chptr;
    int chasing = 0;
    int halfop = 0;
    char *comment;
    const char *name;
    char *p = NULL;
    const char *user;
    static char buf[BUFSIZE];

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

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

    name = parv[1];

    chptr = find_channel(name);
    if (chptr == NULL)
    {
        sendto_one_numeric(source_p, ERR_NOSUCHCHANNEL, form_str(ERR_NOSUCHCHANNEL), name);
        return 0;
    }

    if (!IsServer(source_p))
    {
        msptr = find_channel_membership(chptr, source_p);

        if ((msptr == NULL) && MyConnect(source_p))
        {
            sendto_one_numeric(source_p, ERR_NOTONCHANNEL,
                               form_str(ERR_NOTONCHANNEL), name);
            return 0;
        }

        if (!is_chanop(msptr) && !is_halfop(msptr))
        {
            if (MyConnect(source_p))
            {
                sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED),
                           me.name, source_p->name, name);
                return 0;
            }

            /* If its a TS 0 channel, do it the old way */
            if (chptr->channelts == 0)
            {
                sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED),
                           get_id(&me, source_p), get_id(source_p, source_p), name);
                return 0;
            }
        }
        halfop = !is_chanop(msptr) && is_halfop(msptr);

        /* Its a user doing a kick, but is not showing as chanop locally
         * its also not a user ON -my- server, and the channel has a TS.
         * There are two cases we can get to this point then...
         *
         *     1) connect burst is happening, and for some reason a legit
         *        op has sent a KICK, but the SJOIN hasn't happened yet or
         *        been seen. (who knows.. due to lag...)
         *
         *     2) The channel is desynced. That can STILL happen with TS
         *
         *     Now, the old code roger wrote, would allow the KICK to
         *     go through. Thats quite legit, but lets weird things like
         *     KICKS by users who appear not to be chanopped happen,
         *     or even neater, they appear not to be on the channel.
         *     This fits every definition of a desync, doesn't it? ;-)
         *     So I will allow the KICK, otherwise, things are MUCH worse.
         *     But I will warn it as a possible desync.
         *
         *     -Dianora
         */
    }

    if ((p = strchr(parv[2], ',')))
        *p = '\0';

    user = parv[2];

    if (!(who = find_chasing(source_p, user, &chasing)))
    {
        return 0;
    }

    msptr = find_channel_membership(chptr, who);

    if (msptr != NULL)
    {
        if (MyClient(source_p) && IsService(who))
        {
            sendto_one(source_p, form_str(ERR_ISCHANSERVICE),
                       me.name, source_p->name, who->name, chptr->chname);
            return 0;
        }

        if (halfop && (is_chanop(msptr) || is_halfop(msptr)))
        {
            if (MyConnect(source_p))
            {
                sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED),
                           me.name, source_p->name, name);
                return 0;
            }

            /* If its a TS 0 channel, do it the old way */
            if (chptr->channelts == 0)
            {
                sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED),
                           get_id(&me, source_p), get_id(source_p, source_p), name);
                return 0;
            }
        }

        comment = LOCAL_COPY_N((EmptyString(parv[3])) ? who->name : parv[3], REASONLEN);

        /* jdc
         * - In the case of a server kicking a user (i.e. CLEARCHAN),
         *   the kick should show up as coming from the server which did
         *   the kick.
         * - Personally, flame and I believe that server kicks shouldn't
         *   be sent anyways.  Just waiting for some oper to abuse it...
         */
        if (IsServer(source_p))
            sendto_channel_local(ALL_MEMBERS, chptr, ":%s KICK %s %s :%s",
                                 source_p->name, name, who->name, comment);
        else
            sendto_channel_local(ALL_MEMBERS, chptr,
                                 ":%s!%s@%s KICK %s %s :%s",
                                 source_p->name, source_p->username,
                                 IsCloaked(source_p) ? source_p->virthost : source_p->host,
                                 name, who->name, comment);

        sendto_server(client_p, chptr, CAP_TS6, NOCAPS,
                      ":%s KICK %s %s :%s",
                      use_id(source_p), chptr->chname, use_id(who), comment);
        sendto_server(client_p, chptr, NOCAPS, CAP_TS6,
                      ":%s KICK %s %s :%s",
                      source_p->name, chptr->chname, who->name, comment);
        remove_user_from_channel(msptr);
    }
    else if (MyClient(source_p))
        sendto_one_numeric(source_p, ERR_USERNOTINCHANNEL,
                           form_str(ERR_USERNOTINCHANNEL), user, name);

    return 0;
}
Ejemplo n.º 20
0
/*
 * m_kline
 * Add a local user@host ban.
 *
 *    parv[0] = sender
 *    parv[1] = duration (optional)
 *    parv[2] = nick or user@host mask
 *    parv[3] = reason (optional)
 */
int
m_kline(aClient *cptr, aClient *sptr, int parc, char *parv[])
{
    char rbuf[512];
    char hostbuf[HOSTIPLEN+3+1];
    char *target;
    char *user;
    char *host;
    char *reason = "<no reason>";
    int tkminutes = DEFAULT_KLINE_TIME;
    int tkseconds;
    long lval;
    struct userBan *ban;
    struct userBan *existing;
    aClient *acptr;

    if (!OPCanKline(sptr))
    {
        sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
        return 0;
    }

    if (parc < 2)
    {
        sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0],
                   "KLINE");
        return 0;
    }

    lval = strtol(parv[1], &target, 10);
    if (*target != 0)
    {
        target = parv[1];
        if (parc > 2 && !BadPtr(parv[2]))
            reason = parv[2];
    }
    else
    {
        /* valid expiration time */
        tkminutes = lval;

        if (parc < 3)
        {
            sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0],
                       "KLINE");
            return 0;
        }

        target = parv[2];

        if (parc > 3 && !BadPtr(parv[3]))
            reason = parv[3];
    }

    /* negative times, or times greater than a year, are permanent */
    if (tkminutes < 0 || tkminutes > (365 * 24 * 60))
        tkminutes = 0;
    tkseconds = tkminutes * 60;

    if ((host = strchr(target, '@')))
    {
        *host++ = 0;
        user = target;
    }
    else if (strchr(target, '*'))
    {
        user = "******";
        host = target;
    }
    else
    {
        if (!(acptr = find_chasing(sptr, target, NULL)))
            return 0;
        
        if (!acptr->user)
            return 0;
        
        user = acptr->user->username;
	if (acptr->ip_family == AF_INET)
	{
	    ircsprintf(hostbuf, "%s/24", acptr->hostip);
	    host = hostbuf;
	}
	else
	    host = acptr->hostip;
    }

    if (!match(user, "akjhfkahfasfjd") &&
        !match(host, "ldksjfl.kss...kdjfd.jfklsjf"))
    {
        sendto_one(sptr, ":%s NOTICE %s :KLINE: %s@%s mask is too wide",
                   me.name, parv[0], user, host);
        return 0;
    }

    if (strchr(host, ' ') || !(ban = make_hostbased_ban(user, host)))
    {
        sendto_one(sptr, ":%s NOTICE %s :KLINE: invalid ban mask %s@%s",
                   me.name, parv[0], user, host);
        return 0;
    }

    ban->flags |= UBAN_LOCAL;

    /* only looks for duplicate klines, not akills */
    if ((existing = find_userban_exact(ban, UBAN_LOCAL)))
    {
        sendto_one(sptr, ":%s NOTICE %s :KLINE: %s@%s is already %s: %s",
                   me.name, parv[0], user, host, LOCAL_BANNED_NAME,
                   existing->reason ? existing->reason : "<no reason>");
        userban_free(ban);
        return 0;
    }

    if (user_match_ban(sptr, ban))
    {
        sendto_one(sptr, ":%s NOTICE %s :KLINE: %s@%s matches you, rejected",
                   me.name, parv[0], user, host);
        userban_free(ban);
        return 0;
    }

    ircsnprintf(rbuf, sizeof(rbuf), "%s (%s)", reason, smalldate(0));
    ban->reason = MyMalloc(strlen(rbuf) + 1);
    strcpy(ban->reason, rbuf);

    if (tkseconds)
    {
        ban->flags |= UBAN_TEMPORARY;
        ban->timeset = NOW;
        ban->duration = tkseconds;
    }

    add_hostbased_userban(ban);

    if (!tkminutes || tkminutes >= KLINE_MIN_STORE_TIME)
        klinestore_add(ban);

    userban_sweep(ban);

    host = get_userban_host(ban, rbuf, sizeof(rbuf));

    if (tkminutes)
        sendto_realops("%s added temporary %d min. "LOCAL_BAN_NAME" for"
                       " [%s@%s] [%s]", parv[0], tkminutes, user, host,
                       reason);
    else
        sendto_realops("%s added "LOCAL_BAN_NAME" for [%s@%s] [%s]", parv[0],
                       user, host, reason);

    return 0;
}