Ejemplo n.º 1
0
// Parts all insecure users on a +z channel (NOT KICK)
void f_part_insecure_users (aChannel *chptr)
{
	Member *member, *mb2;
	aClient *cptr;
	char *comment = "Insecure user not allowed on secure channel (+z)";
	for (member = chptr->members; member; member = mb2)
	{
		mb2 = member->next;
		cptr = member->cptr;
		if (MyClient(cptr) && !IsSecureConnect(cptr) && !IsULine(cptr))
		{
			RunHook4(HOOKTYPE_LOCAL_PART, cptr, &me, chptr, comment);
			if ((chptr->mode.mode & MODE_AUDITORIUM) && is_chanownprotop(cptr, chptr))
			{
				sendto_chanops_butone(cptr, chptr, ":%s!%s@%s PART %s :%s",
					cptr->name, cptr->user->username, GetHost(cptr), chptr->chname, comment);
				sendto_prefix_one(cptr, &me, ":%s!%s@%s PART %s :%s",
					cptr->name, cptr->user->username, GetHost(cptr), chptr->chname, comment);
			} 
			else
			{
				sendto_channel_butserv(chptr, &me, ":%s!%s@%s PART %s :%s",
					cptr->name, cptr->user->username, GetHost(cptr), chptr->chname, comment);
			}
			sendto_one(cptr, err_str(ERR_SECUREONLYCHAN), me.name, cptr->name, chptr->chname);
			sendto_serv_butone_token(&me, cptr->name, MSG_PART, TOK_PART, "%s :%s", chptr->chname, comment);
			remove_user_from_channel(cptr, chptr);
		}
	}
}
Ejemplo n.º 2
0
/* This function adds as an extra (weird) operoverride.
 * Currently it's only used if you try to operoverride for a +z channel,
 * if you then do '/join #chan override' it will put the channel -z and allow you directly in.
 * This is to avoid attackers from using 'race conditions' to prevent you from joining.
 * PARAMETERS: sptr = the client, chptr = the channel, mval = mode value (eg MODE_ONLYSECURE),
 *             mchar = mode char (eg 'z')
 * RETURNS: 1 if operoverride, 0 if not.
 */
int extended_operoverride(aClient *sptr, aChannel *chptr, char *key, int mval, char mchar)
{
    unsigned char invited = 0;
    Link *lp;

    if (!IsAnOper(sptr) || !OPCanOverride(sptr))
        return 0;

    for (lp = sptr->user->invited; lp; lp = lp->next)
        if (lp->value.chptr == chptr)
        {
            invited = 1;
            break;
        }
    if (invited)
    {
        if (key && !strcasecmp(key, "override"))
        {
            sendto_channelprefix_butone(NULL, &me, chptr, PREFIX_OP|PREFIX_ADMIN|PREFIX_OWNER,
                                        ":%s NOTICE @%s :setting channel -%c due to OperOverride request from %s",
                                        me.name, chptr->chname, mchar, sptr->name);
            sendto_serv_butone(&me, ":%s MODE %s -%c 0", me.name, chptr->chname, mchar);
            sendto_channel_butserv(chptr, &me, ":%s MODE %s -%c", me.name, chptr->chname, mchar);
            chptr->mode.mode &= ~mval;
            return 1;
        }
    }
    return 0;
}
Ejemplo n.º 3
0
void do_chanflood_action(aChannel *chptr, int what, char *text)
{
long modeflag = 0;
aCtab *tab = &cFlagTab[0];
char m;

	m = chptr->mode.floodprot->a[what];
	if (!m)
		return;

	/* [TODO: add extended channel mode support] */
	
	while(tab->mode != 0x0)
	{
		if (tab->flag == m)
		{
			modeflag = tab->mode;
			break;
		}
		tab++;
	}

	if (!modeflag)
		return;
		
	if (!(chptr->mode.mode & modeflag))
	{
		char comment[1024], target[CHANNELLEN + 8];
		ircsprintf(comment, "*** Channel %sflood detected (limit is %d per %d seconds), setting mode +%c",
			text, chptr->mode.floodprot->l[what], chptr->mode.floodprot->per, m);
		ircsprintf(target, "%%%s", chptr->chname);
		sendto_channelprefix_butone_tok(NULL, &me, chptr,
			PREFIX_HALFOP|PREFIX_OP|PREFIX_ADMIN|PREFIX_OWNER,
			MSG_NOTICE, TOK_NOTICE, target, comment, 0);
		sendto_serv_butone(&me, ":%s MODE %s +%c 0", me.name, chptr->chname, m);
		sendto_channel_butserv(chptr, &me, ":%s MODE %s +%c", me.name, chptr->chname, m);
		chptr->mode.mode |= modeflag;
		if (chptr->mode.floodprot->r[what]) /* Add remove-chanmode timer... */
		{
			chanfloodtimer_add(chptr, m, modeflag, TStime() + ((long)chptr->mode.floodprot->r[what] * 60) - 5);
			/* (since the chanflood timer event is called every 10s, we do -5 here so the accurancy will
			 *  be -5..+5, without it it would be 0..+10.)
			 */
		}
	}
}
Ejemplo n.º 4
0
/** Kicks all insecure users on a +z channel */
static void secureonly_kick_insecure_users(aChannel *chptr)
{
	Member *member, *mb2;
	aClient *cptr;
	int i = 0;
	Hook *h;
	char *comment = "Insecure user not allowed on secure channel (+z)";

	if (!IsSecureOnly(chptr))
		return;

	for (member = chptr->members; member; member = mb2)
	{
		mb2 = member->next;
		cptr = member->cptr;
		if (MyClient(cptr) && !IsSecureConnect(cptr) && !IsULine(cptr))
		{
			RunHook5(HOOKTYPE_LOCAL_KICK, &me, &me, cptr, chptr, comment);

			i = 0;
			for (h = Hooks[HOOKTYPE_VISIBLE_IN_CHANNEL]; h; h = h->next)
			{
				i = (*(h->func.intfunc))(cptr,chptr);
				if (i != 0)
					break;
			}

			if (i != 0 && !(is_skochanop(cptr, chptr) || has_voice(cptr,chptr)))
			{
				sendto_chanops_butone(cptr, chptr, ":%s KICK %s %s :%s", me.name, chptr->chname, cptr->name, comment);
				sendto_prefix_one(cptr, &me, ":%s KICK %s %s :%s", me.name, chptr->chname, cptr->name, comment);
			}
			else
			{
				sendto_channel_butserv(chptr, &me, ":%s KICK %s %s :%s", me.name, chptr->chname, cptr->name, comment);
			}

			sendto_server(&me, 0, 0, ":%s KICK %s %s :%s", me.name, chptr->chname, cptr->name, comment);

			remove_user_from_channel(cptr, chptr);
		}
	}
}
Ejemplo n.º 5
0
/* Routine that actually makes a user join the channel
 * this does no actual checking (banned, etc.) it just adds the user
 */
DLLFUNC void _join_channel(aChannel *chptr, aClient *cptr, aClient *sptr, int flags)
{
    char *parv[] = { 0, 0 };
    /*
       **  Complete user entry to the new channel (if any)
     */
    add_user_to_channel(chptr, sptr, flags);
    /*
       ** notify all other users on the new channel
     */
    if (chptr->mode.mode & MODE_AUDITORIUM)
    {
        if (MyClient(sptr))
            sendto_one(sptr, ":%s!%s@%s JOIN :%s",
                       sptr->name, sptr->user->username,
                       GetHost(sptr), chptr->chname);
        sendto_chanops_butone(NULL, chptr, ":%s!%s@%s JOIN :%s",
                              sptr->name, sptr->user->username,
                              GetHost(sptr), chptr->chname);
    }
    else
        sendto_channel_butserv(chptr, sptr,
                               ":%s JOIN :%s", sptr->name, chptr->chname);

    sendto_serv_butone_token_opt(cptr, OPT_NOT_SJ3, sptr->name, MSG_JOIN,
                                 TOK_JOIN, "%s", chptr->chname);

#ifdef JOIN_INSTEAD_OF_SJOIN_ON_REMOTEJOIN
    if ((MyClient(sptr) && !(flags & CHFL_CHANOP)) || !MyClient(sptr))
        sendto_serv_butone_token_opt(cptr, OPT_SJ3, sptr->name, MSG_JOIN,
                                     TOK_JOIN, "%s", chptr->chname);
    if (flags && !(flags & CHFL_DEOPPED))
    {
#endif
        /* I _know_ that the "@%s " look a bit wierd
           with the space and all .. but its to get around
           a SJOIN bug --stskeeps */
        sendto_serv_butone_token_opt(cptr, OPT_SJ3|OPT_SJB64,
                                     me.name, MSG_SJOIN, TOK_SJOIN,
                                     "%B %s :%s%s ", (long)chptr->creationtime,
                                     chptr->chname, chfl_to_sjoin_symbol(flags), sptr->name);
        sendto_serv_butone_token_opt(cptr, OPT_SJ3|OPT_NOT_SJB64,
                                     me.name, MSG_SJOIN, TOK_SJOIN,
                                     "%li %s :%s%s ", chptr->creationtime,
                                     chptr->chname, chfl_to_sjoin_symbol(flags), sptr->name);
#ifdef JOIN_INSTEAD_OF_SJOIN_ON_REMOTEJOIN
    }
#endif

    if (MyClient(sptr))
    {
        /*
           ** Make a (temporal) creationtime, if someone joins
           ** during a net.reconnect : between remote join and
           ** the mode with TS. --Run
         */
        if (chptr->creationtime == 0)
        {
            chptr->creationtime = TStime();
            sendto_serv_butone_token(cptr, me.name,
                                     MSG_MODE, TOK_MODE, "%s + %lu",
                                     chptr->chname, chptr->creationtime);
        }
        del_invite(sptr, chptr);
        if (flags && !(flags & CHFL_DEOPPED))
        {
#ifndef PREFIX_AQ
            if ((flags & CHFL_CHANOWNER) || (flags & CHFL_CHANPROT))
            {
                /* +ao / +qo for when PREFIX_AQ is off */
                sendto_serv_butone_token_opt(cptr, OPT_NOT_SJ3,
                                             me.name,
                                             MSG_MODE, TOK_MODE, "%s +o%c %s %s %lu",
                                             chptr->chname, chfl_to_chanmode(flags), sptr->name, sptr->name,
                                             chptr->creationtime);
            } else {
#endif
                /* +v/+h/+o (and +a/+q if PREFIX_AQ is on) */
                sendto_serv_butone_token_opt(cptr, OPT_NOT_SJ3,
                                             me.name,
                                             MSG_MODE, TOK_MODE, "%s +%c %s %lu",
                                             chptr->chname, chfl_to_chanmode(flags), sptr->name,
                                             chptr->creationtime);
#ifndef PREFIX_AQ
            }
#endif
        }
        if (chptr->topic)
        {
            sendto_one(sptr, rpl_str(RPL_TOPIC),
                       me.name, sptr->name, chptr->chname, chptr->topic);
            sendto_one(sptr,
                       rpl_str(RPL_TOPICWHOTIME), me.name,
                       sptr->name, chptr->chname, chptr->topic_nick,
                       chptr->topic_time);
        }
        if (chptr->users == 1 && (MODES_ON_JOIN
#ifdef EXTCMODE
                                  || iConf.modes_on_join.extmodes)
#endif
           )
        {
#ifdef EXTCMODE
            int i;
            chptr->mode.extmode =  iConf.modes_on_join.extmodes;
            /* Param fun */
            for (i = 0; i <= Channelmode_highest; i++)
            {
                if (!Channelmode_Table[i].flag || !Channelmode_Table[i].paracount)
                    continue;
                if (chptr->mode.extmode & Channelmode_Table[i].mode)
                {
                    CmodeParam *p;
                    p = Channelmode_Table[i].put_param(NULL, iConf.modes_on_join.extparams[i]);
                    AddListItem(p, chptr->mode.extmodeparam);
                }
            }
#endif
            chptr->mode.mode = MODES_ON_JOIN;
#ifdef NEWCHFLOODPROT
            if (iConf.modes_on_join.floodprot.per)
            {
                chptr->mode.floodprot = MyMalloc(sizeof(ChanFloodProt));
                memcpy(chptr->mode.floodprot, &iConf.modes_on_join.floodprot, sizeof(ChanFloodProt));
            }
#else
            chptr->mode.kmode = iConf.modes_on_join.kmode;
            chptr->mode.per = iConf.modes_on_join.per;
            chptr->mode.msgs = iConf.modes_on_join.msgs;
#endif
            *modebuf = *parabuf = 0;
            channel_modes(sptr, modebuf, parabuf, chptr);
            /* This should probably be in the SJOIN stuff */
            sendto_serv_butone_token(&me, me.name, MSG_MODE, TOK_MODE,
                                     "%s %s %s %lu", chptr->chname, modebuf, parabuf,
                                     chptr->creationtime);
            sendto_one(sptr, ":%s MODE %s %s %s", me.name, chptr->chname, modebuf, parabuf);
        }
        parv[0] = sptr->name;
        parv[1] = chptr->chname;
        do_cmd(cptr, sptr, "NAMES", 2, parv);
        RunHook4(HOOKTYPE_LOCAL_JOIN, cptr, sptr,chptr,parv);
    } else {
        RunHook4(HOOKTYPE_REMOTE_JOIN, cptr, sptr, chptr, parv); /* (rarely used) */
    }

#ifdef NEWCHFLOODPROT
    /* I'll explain this only once:
     * 1. if channel is +f
     * 2. local client OR synced server
     * 3. then, increase floodcounter
     * 4. if we reached the limit AND only if source was a local client.. do the action (+i).
     * Nr 4 is done because otherwise you would have a noticeflood with 'joinflood detected'
     * from all servers.
     */
    if (chptr->mode.floodprot && (MyClient(sptr) || sptr->srvptr->serv->flags.synced) &&
            !IsULine(sptr) && do_chanflood(chptr->mode.floodprot, FLD_JOIN) && MyClient(sptr))
    {
        do_chanflood_action(chptr, FLD_JOIN, "join");
    }
#endif
}
Ejemplo n.º 6
0
/*
** m_part
**	parv[0] = sender prefix
**	parv[1] = channel
**	parv[2] = comment (added by Lefler)
*/
DLLFUNC CMD_FUNC(m_part)
{
	aChannel *chptr;
	Membership *lp;
	char *p = NULL, *name;
	char *commentx = (parc > 2 && parv[2]) ? parv[2] : NULL;
	char *comment;
	int n;
	
	if (parc < 2 || parv[1][0] == '\0')
	{
		sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS),
		    me.name, parv[0], "PART");
		return 0;
	}

	if (MyClient(sptr))
	{
		if (IsShunned(sptr))
			commentx = NULL;
		if (STATIC_PART)
		{
			if (!strcasecmp(STATIC_PART, "yes") || !strcmp(STATIC_PART, "1"))
				commentx = NULL;
			else if (!strcasecmp(STATIC_PART, "no") || !strcmp(STATIC_PART, "0"))
				; /* keep original reason */
			else
				commentx = STATIC_PART;
		}
		if (commentx)
		{
			n = dospamfilter(sptr, commentx, SPAMF_PART, parv[1], 0, NULL);
			if (n == FLUSH_BUFFER)
				return n;
			if (n < 0)
				commentx = NULL;
		}
	}

	for (; (name = strtoken(&p, parv[1], ",")); parv[1] = NULL)
	{
		chptr = get_channel(sptr, name, 0);
		if (!chptr)
		{
			sendto_one(sptr, err_str(ERR_NOSUCHCHANNEL),
			    me.name, parv[0], name);
			continue;
		}
		if (check_channelmask(sptr, cptr, name))
			continue;

		/* 'commentx' is the general part msg, but it can be changed
		 * per-channel (eg some chans block badwords, strip colors, etc)
		 * so we copy it to 'comment' and use that in this for loop :)
		 */
		comment = commentx;

		if (!(lp = find_membership_link(sptr->user->channel, chptr)))
		{
			/* Normal to get get when our client did a kick
			   ** for a remote client (who sends back a PART),
			   ** so check for remote client or not --Run
			 */
			if (MyClient(sptr))
				sendto_one(sptr,
				    err_str(ERR_NOTONCHANNEL), me.name,
				    parv[0], name);
			continue;
		}

		if (!IsAnOper(sptr) && !is_chanownprotop(sptr, chptr)) {
#ifdef STRIPBADWORDS
			int blocked = 0;
#endif
			/* Banned? No comment allowed ;) */
			if (comment && is_banned(sptr, chptr, BANCHK_MSG))
				comment = NULL;
			/* And other things... */
			if ((chptr->mode.mode & MODE_NOCOLOR) && comment) {
				if (strchr((char *)comment, 3) || strchr((char *)comment, 27)) {
					comment = NULL;
				}
			}
			if ((chptr->mode.mode & MODE_MODERATED) && comment &&
				 !has_voice(sptr, chptr) && !is_halfop(sptr, chptr))
			{
				comment = NULL;
			}
			if ((chptr->mode.mode & MODE_STRIP) && comment) {
				comment = (char *)StripColors(comment);
			}
#ifdef STRIPBADWORDS
 #ifdef STRIPBADWORDS_CHAN_ALWAYS
			if (comment)
			{
				comment = (char *)stripbadwords_channel(comment, &blocked);
			}
 #else
			if ((chptr->mode.extmode & EXTMODE_STRIPBADWORDS) && comment) {
				comment = (char *)stripbadwords_channel(comment, &blocked);
			}
 #endif
#endif
			
		}
		/* +M and not logged in to services? */
		if ((chptr->mode.mode & MODE_MODREG) && !IsLoggedIn(sptr) && !IsAnOper(sptr))
			comment = NULL;

		if (MyConnect(sptr))
		{
			Hook *tmphook;
			for (tmphook = Hooks[HOOKTYPE_PRE_LOCAL_PART]; tmphook; tmphook = tmphook->next) {
				comment = (*(tmphook->func.pcharfunc))(sptr, chptr, comment);
				if (!comment)
					break;
			}
		}

		/* Send to other servers... */
		if (!comment)
			sendto_serv_butone_token(cptr, parv[0],
			    MSG_PART, TOK_PART, "%s", chptr->chname);
		else
			sendto_serv_butone_token(cptr, parv[0],
			    MSG_PART, TOK_PART, "%s :%s", chptr->chname,
			    comment);

		if (1)
		{
			if ((chptr->mode.mode & MODE_AUDITORIUM) && !is_chanownprotop(sptr, chptr))
			{
				if (!comment)
				{
					sendto_chanops_butone(NULL,
					    chptr, ":%s!%s@%s PART %s",
					    sptr->name, sptr->user->username, GetHost(sptr),
					    chptr->chname);
					if (!is_chan_op(sptr, chptr) && MyClient(sptr))
						sendto_one(sptr, ":%s!%s@%s PART %s",
						    sptr->name, sptr->user->username, GetHost(sptr), chptr->chname);
				}
				else
				{
					sendto_chanops_butone(NULL,
					    chptr,
					    ":%s!%s@%s PART %s %s",
					    sptr->name,
					    sptr->user->username,
					    GetHost(sptr),
					    chptr->chname, comment);
					if (!is_chan_op(cptr, chptr) && MyClient(sptr))
						sendto_one(sptr,
						    ":%s!%s@%s PART %s %s",
						    sptr->name, sptr->user->username, GetHost(sptr),
						    chptr->chname, comment);
				}
			}
			else
			{


				if (!comment)

					sendto_channel_butserv(chptr,
					    sptr, PARTFMT, parv[0],
					    chptr->chname);
				else
					sendto_channel_butserv(chptr,
					    sptr, PARTFMT2, parv[0],
					    chptr->chname, comment);
			}
			if (MyClient(sptr))
				RunHook4(HOOKTYPE_LOCAL_PART, cptr, sptr, chptr, comment);
			else
				RunHook4(HOOKTYPE_REMOTE_PART, cptr, sptr, chptr, comment);

			remove_user_from_channel(sptr, chptr);
		}
	}
	return 0;
}
Ejemplo n.º 7
0
/*
 * * DoNumeric (replacement for the old do_numeric) *
 * 
 * parc         number of arguments ('sender' counted as one!)
 * parv[0]      pointer to 'sender' (may point to empty string)
 * 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...
 */
int do_numeric(int numeric, aClient *cptr, aClient *sptr, int parc, 
	       char *parv[])
{
    aClient    *acptr;
    aChannel   *chptr;
    char       *nick, *p;
    int         i;

    if (parc < 1 || !IsServer(sptr))
	return 0;
    /* Remap low number numerics. */
    if (numeric < 100)
	numeric += 100;
    /*
     * Prepare the parameter portion of the message into 'buffer'. 
     * (Because the buffer is twice as large as the message buffer for
     * the socket, no overflow can occur here... ...on current
     * assumptions--bets are off, if these are changed --msa) 
     * Note: if buffer is non-empty, it will begin with SPACE.
     */
    buffer[0] = '\0';
    if (parc > 1)
    {
	int bpos = 0;
	char *p;

	for (i = 2; i < (parc - 1); i++)
	{
	    buffer[bpos++] = ' ';
	    for(p = parv[i]; *p; p++)
		buffer[bpos++] = *p;
	}
	buffer[bpos++] = ' ';
	buffer[bpos++] = ':';
	for(p = parv[parc - 1]; *p; p++)
	    buffer[bpos++] = *p;
	buffer[bpos] = '\0';
    }
    for (; (nick = strtoken(&p, parv[1], ",")); parv[1] = NULL)
    {
	if ((acptr = find_client(nick, (aClient *) NULL)))
	{
	    int dohide;

	    /*
	     * Drop to bit bucket if for me... ...one might consider
	     * sendto_ops * here... --msa * And so it was done. -avalon *
	     * And regretted. Dont do it that way. Make sure * it goes
	     * only to non-servers. -avalon * Check added to make sure
	     * servers don't try to loop * with numerics which can happen
	     * with nick collisions. * - Avalon
	     */

#ifdef HIDE_NUMERIC_SOURCE
	    dohide = MyClient(acptr) ? 1 : 0;
#else
	    dohide = 0;
#endif

	    if (!IsMe(acptr) && IsPerson(acptr))
		sendto_prefix_one(acptr, dohide ? &me : sptr, ":%s %d %s%s",
				  dohide ? me.name : parv[0], numeric, nick, buffer);
	    else if (IsServer(acptr) && acptr->from != cptr)
		sendto_prefix_one(acptr, sptr, ":%s %d %s%s",
				  parv[0], numeric, nick, buffer);
	}
	else if ((chptr = find_channel(nick, (aChannel *) NULL)))
	{
	    int dohide;

#ifdef HIDE_NUMERIC_SOURCE
	    dohide = 1;
#else
	    dohide = 0;
#endif
	    sendto_channel_butserv(chptr, dohide ? &me : sptr, ":%s %d %s%s",
				   dohide ? me.name : parv[0], numeric, 
				   chptr->chname, buffer);

	    sendto_channel_remote_butone(cptr, sptr, chptr, 
					 parv[0], numeric, 
					 chptr->chname, buffer);

	}
    }
    return 0;
}
Ejemplo n.º 8
0
int  check_for_chan_flood(aClient *cptr, aClient *sptr, aChannel *chptr)
{
	Membership *lp;
	MembershipL *lp2;
	int c_limit, t_limit, banthem;

	if (!MyClient(sptr))
		return 0;
	if (IsOper(sptr) || IsULine(sptr))
		return 0;
	if (is_skochanop(sptr, chptr))
		return 0;

	if (!(lp = find_membership_link(sptr->user->channel, chptr)))
		return 0;

	lp2 = (MembershipL *) lp;

#ifdef NEWCHFLOODPROT
	if (!chptr->mode.floodprot || !chptr->mode.floodprot->l[FLD_TEXT])
		return 0;
	c_limit = chptr->mode.floodprot->l[FLD_TEXT];
	t_limit = chptr->mode.floodprot->per;
	banthem = (chptr->mode.floodprot->a[FLD_TEXT] == 'b') ? 1 : 0;
#else
	if ((chptr->mode.msgs < 1) || (chptr->mode.per < 1))
		return 0;
	c_limit = chptr->mode.msgs;
	t_limit = chptr->mode.per;
	banthem = chptr->mode.kmode;
#endif
	/* if current - firstmsgtime >= mode.per, then reset,
	 * if nummsg > mode.msgs then kick/ban
	 */
	Debug((DEBUG_ERROR, "Checking for flood +f: firstmsg=%d (%ds ago), new nmsgs: %d, limit is: %d:%d",
		lp2->flood.firstmsg, TStime() - lp2->flood.firstmsg, lp2->flood.nmsg + 1,
		c_limit, t_limit));
	if ((TStime() - lp2->flood.firstmsg) >= t_limit)
	{
		/* reset */
		lp2->flood.firstmsg = TStime();
		lp2->flood.nmsg = 1;
		return 0; /* forget about it.. */
	}

	/* increase msgs */
	lp2->flood.nmsg++;

	if ((lp2->flood.nmsg) > c_limit)
	{
		char comment[1024], mask[1024];
		ircsprintf(comment,
		    "Flooding (Limit is %i lines per %i seconds)",
		    c_limit, t_limit);
		if (banthem)
		{		/* ban. */
			ircsprintf(mask, "*!*@%s", GetHost(sptr));
			add_listmode(&chptr->banlist, &me, chptr, mask);
			sendto_serv_butone(&me, ":%s MODE %s +b %s 0",
			    me.name, chptr->chname, mask);
			sendto_channel_butserv(chptr, &me,
			    ":%s MODE %s +b %s", me.name, chptr->chname, mask);
		}
		sendto_channel_butserv(chptr, &me,
		    ":%s KICK %s %s :%s", me.name,
		    chptr->chname, sptr->name, comment);
		sendto_serv_butone_token(cptr, me.name,
			MSG_KICK, TOK_KICK, 
			"%s %s :%s",
		   chptr->chname, sptr->name, comment);
		remove_user_from_channel(sptr, chptr);
		return 1;
	}
	return 0;
}
Ejemplo n.º 9
0
/* m_sajoin() - Lamego - Wed Jul 21 20:04:48 1999
   Copied off PTlink IRCd (C) PTlink coders team.
   Coded for Sadmin by Stskeeps
   also Modified by NiQuiL ([email protected])
	parv[0] - sender
	parv[1] - nick to make join
	parv[2] - channel(s) to join
*/
DLLFUNC CMD_FUNC(m_sajoin)
{
	aClient *acptr;
	char jbuf[BUFSIZE];
	int did_anything = 0;

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

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

	if (!(acptr = find_person(parv[1], NULL)))
	{
		sendto_one(sptr, err_str(ERR_NOSUCHNICK), me.name, parv[0], parv[1]);
		return 0;
	}
	if (MyClient(acptr))
	{
		char *name, *p = NULL;
		int i, parted = 0;
	
		*jbuf = 0;

		/* Now works like m_join */
		for (i = 0, name = strtoken(&p, parv[2], ","); name; name = strtoken(&p,
		     NULL, ","))
		{
			aChannel *chptr;
			Membership *lp;

			if (strlen(name) > CHANNELLEN)
				name[CHANNELLEN] = 0;
			clean_channelname(name);
			if (*name == '0' && !atoi(name))
			{
				(void)strcpy(jbuf, "0");
				i = 1;
				parted = 1;
				continue;
			}
			if (check_channelmask(sptr, cptr, name) == -1 || *name == '0' ||
			    !IsChannelName(name))
			{
				sendto_one(sptr,
				    err_str(ERR_NOSUCHCHANNEL), me.name,
				    parv[0], name);
				continue;
			}

			chptr = get_channel(acptr, name, 0);
			if (!parted && chptr && (lp = find_membership_link(acptr->user->channel, chptr)))
			{
				sendto_one(sptr, err_str(ERR_USERONCHANNEL), me.name, parv[0], 
					   parv[1], name);
				continue;
			}
			if (*jbuf)
				(void)strlcat(jbuf, ",", sizeof jbuf);
			(void)strlncat(jbuf, name, sizeof jbuf, sizeof(jbuf) - i - 1);
			i += strlen(name) + 1;
		}
		if (!*jbuf)
			return -1;
		i = 0;
		strcpy(parv[2], jbuf);
		*jbuf = 0;
		for (name = strtoken(&p, parv[2], ","); name; name = strtoken(&p, NULL, ","))
		{
			int flags;
			aChannel *chptr;
			Membership *lp;

			if (*name == '0' && !atoi(name))
			{
				did_anything = 1;
				while ((lp = acptr->user->channel))
				{
					chptr = lp->chptr;
					sendto_channel_butserv(chptr, acptr,
					    ":%s PART %s :%s", acptr->name, chptr->chname,
					    "Left all channels");
					if (MyConnect(acptr))
						RunHook4(HOOKTYPE_LOCAL_PART, acptr, acptr, chptr,
							 "Left all channels");
					remove_user_from_channel(acptr, chptr);
				}
				sendto_serv_butone_token(acptr, acptr->name,
				    MSG_JOIN, TOK_JOIN, "0");
				strcpy(jbuf, "0");
				i = 1;
				continue;
			}
			flags = (ChannelExists(name)) ? CHFL_DEOPPED : CHFL_CHANOP;
			chptr = get_channel(acptr, name, CREATE);
			if (chptr && (lp = find_membership_link(acptr->user->channel, chptr)))
				continue;
			if ((chptr->mode.mode & MODE_ONLYSECURE) && !IsSecure(acptr))
			{
				sendnotice(sptr, "You cannot SAJOIN %s to %s because the channel is +z and the user is not connected via SSL",
					acptr->name, chptr->chname);
				continue;
			}
			join_channel(chptr, acptr, acptr, flags);
			did_anything = 1;
			if (*jbuf)
				(void)strlcat(jbuf, ",", sizeof jbuf);
			(void)strlncat(jbuf, name, sizeof jbuf, sizeof(jbuf) - i - 1);
			i += strlen(name) + 1;
		}
		
		if (did_anything)
		{
			sendnotice(acptr, "*** You were forced to join %s", jbuf);
			sendto_realops("%s used SAJOIN to make %s join %s", sptr->name, acptr->name,
				       jbuf);
			sendto_serv_butone(&me, ":%s GLOBOPS :%s used SAJOIN to make %s join %s",
					   me.name, sptr->name, acptr->name, jbuf);
			/* Logging function added by XeRXeS */
			ircd_log(LOG_SACMDS,"SAJOIN: %s used SAJOIN to make %s join %s",
				sptr->name, parv[1], jbuf);
		}
	}
	else
	{
		sendto_one(acptr, ":%s SAJOIN %s %s", parv[0],
		    parv[1], parv[2]);

		/* Logging function added by XeRXeS */
		ircd_log(LOG_SACMDS,"SAJOIN: %s used SAJOIN to make %s join %s",
			sptr->name, parv[1], parv[2]);
	}

	return 0;
}
Ejemplo n.º 10
0
/*
** Exit one client, local or remote. Assuming all dependants have
** been already removed, and socket closed for local client.
*/
static	void	exit_one_client(aClient *cptr, aClient *sptr, aClient *from,
	const char *comment)
{
	Reg	aClient *acptr;
	Reg	int	i;
	Reg	Link	*lp;
	invLink		*ilp;

	/*
	**  For a server or user quitting, propagage the information to
	**  other servers (except to the one where is came from (cptr))
	*/
	if (IsMe(sptr))
	{
		sendto_flag(SCH_ERROR,
			    "ERROR: tried to exit me! : %s", comment);
		return;	/* ...must *never* exit self!! */
	}
	else if (IsServer(sptr))
	{
		/*
		** Old sendto_serv_but_one() call removed because we now
		** need to send different names to different servers
		** (domain name matching)
		*/
		if (!IsMasked(sptr))
		{
			istat.is_serv--;
		}
		if (!IsBursting(sptr))
		{
			istat.is_eobservers--;
		}
	 	for (i = fdas.highest; i >= 0; i--)
		{
			if (!(acptr = local[fdas.fd[i]]) || !IsServer(acptr) ||
			    acptr == cptr || IsMe(acptr))
			{
				continue;
			}
			if (!(sptr->flags & FLAGS_SQUIT))
			{
				/* Make sure we only send the last SQUIT
				** to a 2.11. */
				continue;
			}
			if ((acptr->flags & FLAGS_HIDDEN) &&
				!IsMasked(sptr))
			{
				/* We need a special SQUIT reason, so
				** the remote server can send the
				** right quit message. */
				sendto_one(acptr, ":%s SQUIT %s :%s %s",
					sptr->serv->up->serv->sid,
					sptr->serv->sid,
					sptr->serv->up->name,
					sptr->name);
			}
			else
			{
				sendto_one(acptr, ":%s SQUIT %s :%s",
					sptr->serv->up->serv->sid,
					sptr->serv->sid, comment);
			}
		}
#ifdef	USE_SERVICES
		check_services_butone(SERVICE_WANT_SQUIT, sptr->serv, sptr,
				      ":%s SQUIT %s :%s", from->name,
				      sptr->name, comment);
#endif
		del_from_sid_hash_table(sptr->serv);
		remove_server_from_tree(sptr);
		/* remove server from svrtop */
		unregister_server(sptr);
	}
	else if (!IsPerson(sptr) && !IsService(sptr))
	{
				    /* ...this test is *dubious*, would need
				    ** some thougth.. but for now it plugs a
				    ** nasty hole in the server... --msa
				    */
		; /* Nothing */
	}
	else if (sptr->name[0] && !IsService(sptr)) /* clean with QUIT... */
	{
		/*
		** If this exit is generated from "m_kill", then there
		** is no sense in sending the QUIT--KILL's have been
		** sent instead.
		*/
		if ((sptr->flags & FLAGS_KILLED) == 0)
		{
			if ((sptr->flags & FLAGS_SPLIT) == 0)
			{
				sendto_serv_butone(cptr, ":%s QUIT :%s",
						   sptr->user->uid, comment);
#ifdef	USE_SERVICES
				check_services_butone(SERVICE_WANT_QUIT|
						      SERVICE_WANT_RQUIT, 
						      (sptr->user) ?
						      sptr->user->servp
						      : NULL, cptr,
						      ":%s QUIT :%s",
						      sptr->name, comment);
#endif
			}
			else
			{
				if (sptr->flags & FLAGS_HIDDEN)
					/* joys of hostmasking */
					for (i = fdas.highest; i >= 0; i--)
					{
						if (!(acptr =local[fdas.fd[i]])
						    || acptr == cptr
						    || IsMe(acptr))
							continue;
						if (acptr->flags & FLAGS_HIDDEN)
							sendto_one(acptr,
								":%s QUIT :%s",
								sptr->user->uid,
								comment);
					}
#ifdef	USE_SERVICES
				check_services_butone(SERVICE_WANT_QUIT, 
					      (sptr->user) ? sptr->user->servp
						      : NULL, cptr,
						      ":%s QUIT :%s",
						      sptr->name, comment);
#endif
			}
		}
#ifdef USE_SERVICES
		else
		{
			/* Send QUIT to services which desire such as well.
			** Services with both _QUIT and _KILL will get both
			** for now --jv
			*/
			check_services_butone(SERVICE_WANT_QUIT, 
					     (sptr->user) ? sptr->user->servp
						      : NULL, cptr,
						      ":%s QUIT :%s",
						      sptr->name, comment);

		}
#endif
		/*
		** If a person is on a channel, send a QUIT notice
		** to every client (person) on the same channel (so
		** that the client can show the "**signoff" message).
		** (Note: The notice is to the local clients *only*)
		*/
		if (sptr->user)
		{
			if (IsInvisible(sptr))
			{
				istat.is_user[1]--;
				sptr->user->servp->usercnt[1]--;
			}
			else
			{
				istat.is_user[0]--;
				sptr->user->servp->usercnt[0]--;
			}
			if (IsAnOper(sptr))
			{
				sptr->user->servp->usercnt[2]--;
				istat.is_oper--;
			}
			sendto_common_channels(sptr, ":%s QUIT :%s",
						sptr->name, comment);

			if (!(acptr = cptr ? cptr : sptr->from))
				acptr = sptr;
			while ((lp = sptr->user->channel))
			{
				/*
				** Mark channels from where remote chop left,
				** this will eventually lock the channel.
				** close_connection() has already been called,
				** it makes MyConnect == False - krys
				*/
				if (sptr != cptr)
				{
					if (*lp->value.chptr->chname == '!')
					{
						if (!(sptr->flags &FLAGS_QUIT))
							lp->value.chptr->history = timeofday + LDELAYCHASETIMELIMIT;
					}
					else if (
#ifndef BETTER_CDELAY
						 !(sptr->flags & FLAGS_QUIT) &&
#endif
						 is_chan_op(sptr, lp->value.chptr))
					{
						lp->value.chptr->history = timeofday + DELAYCHASETIMELIMIT;
					}
				}
				if (IsAnonymous(lp->value.chptr) &&
				    !IsQuiet(lp->value.chptr))
				{
					sendto_channel_butserv(lp->value.chptr, sptr, ":%s PART %s :None", sptr->name, lp->value.chptr->chname);
				}
				remove_user_from_channel(sptr,lp->value.chptr);
			}

			/* Clean up invitefield */
			while ((ilp = sptr->user->invited))
			{
				del_invite(sptr, ilp->chptr);
				/* again, this is all that is needed */
			}

			/* remove from uid hash table */
			if (sptr->user)
			{
				del_from_uid_hash_table(sptr->user->uid, sptr);
			}

			/* Add user to history */
#ifndef BETTER_NDELAY
			add_history(sptr, (sptr->flags & FLAGS_QUIT) ?
				    &me : NULL);
#else
			add_history(sptr, (sptr == cptr) ? &me : NULL);
#endif
			off_history(sptr);
#ifdef USE_HOSTHASH
			del_from_hostname_hash_table(sptr->user->host,
						     sptr->user);
#endif
#ifdef USE_IPHASH
			del_from_ip_hash_table(sptr->user->sip, sptr->user);
#endif
		    }
	    }
	else if (sptr->name[0] && IsService(sptr))
	    {
		/*
		** If this exit is generated from "m_kill", then there
		** is no sense in sending the QUIT--KILL's have been
		** sent instead.
		*/
		if ((sptr->flags & FLAGS_KILLED) == 0)
		{
			/*
			** A service quitting is annoying, It has to be sent
			** to connected servers depending on 
			** sptr->service->dist
			*/
			for (i = fdas.highest; i >= 0; i--)
			    {
				if (!(acptr = local[fdas.fd[i]])
				    || !IsServer(acptr) || acptr == cptr
				    || IsMe(acptr))
				{
					continue;
				}
				if (match(sptr->service->dist, acptr->name) && 
					match(sptr->service->dist, acptr->serv->sid))
				{
					continue;
				}
				sendto_one(acptr, ":%s QUIT :%s", sptr->name,
					   comment);
			}
		}
#ifdef	USE_SERVICES
		check_services_butone(SERVICE_WANT_SERVICE, NULL, NULL,
				      ":%s QUIT :%s", sptr->name, comment);
#endif
		/* MyConnect(sptr) is always FALSE here */
		if (cptr == sptr)
		{
			sendto_flag(SCH_NOTICE, "Service %s disconnected",
				    get_client_name(sptr, TRUE));
		}
		sendto_flag(SCH_SERVICE, "Received QUIT %s from %s (%s)",
			    sptr->name, from->name, comment);
		istat.is_service--;
	    }

	/* Remove sptr from the client list */
	if (del_from_client_hash_table(sptr->name, sptr) != 1)
	{
		Debug((DEBUG_ERROR, "%#x !in tab %s[%s] %#x %#x %#x %d %d %#x",
			sptr, sptr->name,
			sptr->from ? sptr->from->sockhost : "??host",
			sptr->from, sptr->next, sptr->prev, sptr->fd,
			sptr->status, sptr->user));
	}
	remove_client_from_list(sptr);
	return;
}