Пример #1
0
DLLFUNC CMD_FUNC(m_svsfline)
{
	if (!IsServer(sptr))
		return 0;

	if (parc < 2)
		return 0;

	switch (*parv[1])
	{
		  /* Allow non-U:lines to send ONLY SVSFLINE +, but don't send it out
		   * unless it is from a U:line -- codemastr */
	  case '+':
	  {
		  if (parc < 4)
			  return 0;
		  if (!Find_deny_dcc(parv[2]))
			  DCCdeny_add(parv[2], parv[3], DCCDENY_HARD, CONF_BAN_TYPE_AKILL);
		  if (IsULine(sptr))
			  sendto_serv_butone_token(cptr,
			      sptr->name,
			      MSG_SVSFLINE, TOK_SVSFLINE,
			      "+ %s :%s",
			      parv[2], parv[3]);
		  break;
	  }
	  case '-':
	  {
		  ConfigItem_deny_dcc *deny;
		  if (!IsULine(sptr))
			  return 0;
		  if (parc < 3)
			  return 0;
		  if (!(deny = Find_deny_dcc(parv[2])))
			break;
		  DCCdeny_del(deny);
		  sendto_serv_butone_token(cptr, sptr->name,
		 	MSG_SVSFLINE, TOK_SVSFLINE, "%s",
			      parv[2]);
		  break;
	  }
	  case '*':
	  {
		  if (!IsULine(sptr))
			  return 0;
		  dcc_wipe_services();
		  sendto_serv_butone_token(cptr, sptr->name,
		      MSG_SVSFLINE, TOK_SVSFLINE,
		      	"*");
		  break;
	  }

	}
	return 0;
}
Пример #2
0
DLLFUNC int m_rawto(aClient *cptr, aClient *sptr, int parc, char *parv[])
{
	aClient *acptr = NULL;
	if (!IsULine(sptr))
	{
		sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
		return -1;
	}
	if (parc < 3)
	{
		sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS),
		    me.name, parv[0], "RAWTO");
		return -1;
	}
	if ((acptr = find_client(parv[1], NULL)))
	{
		if (MyConnect(acptr))
		{
			sendto_one(acptr, "%s", parv[2]);
			return 0;
		}		
		else
		{
			sendto_one(acptr, ":%s %s %s :%s",
				parv[0], IsToken(acptr->from) ? TOK_RAWTO : MSG_RAWTO,
					parv[1], parv[2]);
			return 0;
		}
	}
	return 0;
}
Пример #3
0
DLLFUNC char *umsg_notice(aClient *cptr, aClient *sptr, aClient *acptr, char *text, int notice)
{
Hook *tmphook;
int found = 0;

	if (!notice || !IsULine(sptr))
		return text;

	/* We are going to deal with it ourselves! */
	
	for (tmphook = Hooks[HOOKTYPE_USERMSG]; tmphook; tmphook = tmphook->next)
	{
		if (tmphook->func.pcharfunc == umsg_notice)
		{
			found = 1;
			continue;
		}
		if (!found)
			continue;
		text = (*(tmphook->func.pcharfunc))(cptr, sptr, acptr, text, notice);
		if (!text)
			return NULL;
	}

	sendto_message_one(acptr, sptr, sptr->name, MSG_PRIVATE, acptr->name, text);

	return NULL; /* always! we dealt with it! */
}
Пример #4
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);
		}
	}
}
Пример #5
0
int m_svso(aClient *cptr, aClient *sptr, int parc, char *parv[])
{
        aClient *acptr;
        long fLag;

        if (!IsULine(sptr))
                return 0;

        if (parc < 3)
                return 0;

        if (!(acptr = find_person(parv[1], (aClient *)NULL)))
                return 0;

        if (!MyClient(acptr))
        {
                sendto_one(acptr, ":%s SVSO %s %s", parv[0], parv[1], parv[2]);
                return 0;
        }

        if (*parv[2] == '+')
        {
                int     *i, flag;
                char *m = NULL;
                for (m = (parv[2] + 1); *m; m++)
                {
                        for (i = oper_access; (flag = *i); i += 2)
                        {
                                if (*m == (char) *(i + 1))
                                {
                                        acptr->oflag |= flag;
                                        break;
                                }
                        }
                }
        }
        if (*parv[2] == '-')
        {
                fLag = acptr->umodes;
                if (IsOper(acptr) && !IsHideOper(acptr))
                {
                        IRCstats.operators--;
                        VERIFY_OPERCOUNT(acptr, "svso");
                }
                if (IsAnOper(acptr))
                        delfrom_fdlist(acptr->slot, &oper_fdlist);
                acptr->umodes &=
                    ~(UMODE_OPER | UMODE_LOCOP | UMODE_HELPOP |UMODE_SERVICES |
                    UMODE_SADMIN | UMODE_ADMIN | UMODE_COADMIN);
                acptr->umodes &=
                    ~(UMODE_NETADMIN | UMODE_WHOIS);
                acptr->umodes &=
                    ~(UMODE_KIX | UMODE_DEAF | UMODE_HIDEOPER | UMODE_VICTIM);
                acptr->oflag = 0;
		remove_oper_snomasks(acptr);
		RunHook2(HOOKTYPE_LOCAL_OPER, acptr, 0);
                send_umode_out(acptr, acptr, fLag);
        }
	return 0;
}
Пример #6
0
// this is where we handle the MODE command
DLLFUNC int f_handle_mode (aClient *cptr, aClient *sptr, aChannel *chptr, char *mbuf, char *pbuf, time_t sendts, int samode)
{
	int plusminus, securecount;
	char *p;
	if (f_config_ulinesecureaction == F_NOTHING)
		return MOD_SUCCESS;
	plusminus = 1;
	for (p = mbuf; *p; p++)
	{
		if (*p == '+')
			plusminus = 1;
		else if (*p == '-')
			plusminus = -1;
		else if (*p == 'z' && plusminus == 1 && (IsServer(sptr) || IsULine(sptr)))
		{
			securecount = f_count_secure_users(chptr);
			if (securecount < chptr->users)
			{
				sendto_snomask(SNO_EYES, "*** Uline %s set mode +z on %s: removing insecure users.",
					sptr->name, chptr->chname );
				if (f_config_ulinesecureaction == F_KICK || securecount > 0)
					kick_insecure_users(chptr);
				else
					f_part_insecure_users(chptr);
			}
		}
	}
	return MOD_SUCCESS;
}
Пример #7
0
/* show_servers
 * replies to stats v requests
 */
static void 
show_servers(aClient *cptr, char *name)
{
    aClient *cptr2;
    DLink *lp;
    int j = 0;

    for (lp = server_list; lp; lp = lp->next)
    {
    cptr2 = lp->value.cptr;

#ifdef HIDEULINEDSERVS
    if(IsULine(cptr2) && !IsAnOper(cptr))
        continue;
#endif
    j++;
    sendto_one(cptr, ":%s %d %s :%s (%s!%s@%s) Idle: %ld",
           me.name, RPL_STATSDEBUG, name, cptr2->name,
           (cptr2->serv->bynick[0] ? cptr2->serv->bynick : "Remote."),
           (cptr2->serv->byuser[0] ? cptr2->serv->byuser : "******"),
           (cptr2->serv->byhost[0] ? cptr2->serv->byhost : "*"),
           (long)(timeofday - cptr2->lasttime));
    }
    sendto_one(cptr, ":%s %d %s :%d Server%s", me.name, RPL_STATSDEBUG,
           name, j, (j == 1) ? "" : "s");
}
Пример #8
0
DLLFUNC char *privdeaf_checkmsg(aClient *cptr, aClient *sptr, aClient *acptr, char *text, int notice)
{
	if ((acptr->umodes & UMODE_PRIVDEAF) && !IsAnOper(sptr) && !IsULine(sptr) && !IsServer(sptr))
	{
		sendnotice(sptr, "Message to '%s' has not been sent. The user has +D set. This blocks private messages.", acptr->name);
		return NULL;
	} else
		return text;
}
Пример #9
0
DLLFUNC char *privdeaf_checkmsg(aClient *cptr, aClient *sptr, aClient *acptr, char *text, int notice)
{
	if ((acptr->umodes & UMODE_PRIVDEAF) && !IsAnOper(sptr) && !IsULine(sptr) && !IsServer(sptr))
	{
		sendnotice(sptr, "Message to '%s' not delivered: User does not accept private messages", acptr->name);
		return NULL;
	} else
		return text;
}
 char *nocolor_pre_usermsg(aClient *sptr, aClient *acptr, char *text, int notice)
 {
 	if (IsULine(sptr) || IsServer(sptr))
 		return text;

 	if (acptr->umodes & UMODE_STRIPCOLOR)
 		return StripColors(text);

 	return text;
 }
Пример #11
0
DLLFUNC char *restrictcolors_checkmsg(aClient *cptr, aClient *sptr, aChannel *chptr, char *text, int notice)
{
    if (IsULine(sptr) || IsServer(sptr))
       return text;

    if (chptr->mode.extmode && RESTRICT_COLORS && !is_chan_op(sptr, chptr) && !is_halfop(sptr, chptr))
       return StripColors(text);

    return text;
}
Пример #12
0
int  sendmodeto_one(aClient *cptr, char *from, char *name, char *mode, char *param, TS creationtime)
{
	if ((IsServer(cptr) && DoesOp(mode) && creationtime) ||
	    IsULine(cptr))
		sendto_one(cptr, ":%s MODE %s %s %s %lu", from,
		    name, mode, param, creationtime);
	else
		sendto_one(cptr, ":%s MODE %s %s %s", from, name, mode, param);

	return 0;
}
Пример #13
0
char *h_nocodes_chanmsg(aClient *cptr, aClient *sptr, aChannel *acptr, char *text, int notice)
{
static char retbuf[4096];
        if (IsULine(sptr) || IsServer(sptr)) {
                return text;
        }
        if (IsNoCodes(acptr)) {
		strncpyzt(retbuf, StripControlCodes(text), sizeof(retbuf));
		return retbuf;
        }
        else {
        return text;
        }
}
Пример #14
0
static void send_who_reply(aClient *sptr, aClient *acptr, 
			   char *channel, char *status, char *xstat)
{
	char *stat;
	char *host;
	int flat = (FLAT_MAP && !IsAnOper(sptr)) ? 1 : 0;

	stat = malloc(strlen(status) + strlen(xstat) + 1);
	sprintf(stat, "%s%s", status, xstat);

	if (IsAnOper(sptr))
	{
		if (who_flags & WF_REALHOST)
			host = acptr->user->realhost;
		else if (who_flags & WF_IP)
			host = (acptr->user->ip_str ? acptr->user->ip_str : 
			        acptr->user->realhost);
		else
			host = GetHost(acptr);
	}
	else
		host = GetHost(acptr);
					

	if (IsULine(acptr) && !IsOper(sptr) && HIDE_ULINES)
	        sendto_one(sptr, getreply(RPL_WHOREPLY), me.name, sptr->name,
        	     channel,       /* channel name */
	             acptr->user->username, /* user name */
        	     host,		    /* hostname */
	             "hidden",              /* let's hide the server from normal users if the server is a uline and HIDE_ULINES is on */
        	     acptr->name,           /* nick */
	             stat,                  /* status */
        	     0,                     /* hops (hidden) */
	             acptr->info            /* realname */
             	);

	else
		sendto_one(sptr, getreply(RPL_WHOREPLY), me.name, sptr->name,      
		     channel,       /* channel name */
		     acptr->user->username,      /* user name */
		     host,		         /* hostname */
		     acptr->user->server,        /* server name */
		     acptr->name,                /* nick */
		     stat,                       /* status */
		     flat ? 0 : acptr->hopcount, /* hops */ 
		     acptr->info                 /* realname */
		     );
	free(stat);
}
Пример #15
0
/*
** m_svsnick
**      parv[0] = sender
**      parv[1] = old nickname
**      parv[2] = new nickname
**      parv[3] = timestamp
*/
int  m_svsnick(aClient *cptr, aClient *sptr, int parc, char *parv[])
{
aClient *acptr;
aClient *ocptr; /* Other client */

	if (!IsULine(sptr) || parc < 4 || (strlen(parv[2]) > NICKLEN))
		return -1; /* This looks like an error anyway -Studded */

	if (hunt_server_token(cptr, sptr, MSG_SVSNICK, TOK_SVSNICK, "%s %s :%s", 1, parc, parv) != HUNTED_ISME)
		return 0; /* Forwarded, done */

	if (do_nick_name(parv[2]) == 0)
		return 0;

	if (!(acptr = find_person(parv[1], NULL)))
		return 0; /* User not found, bail out */

	if ((ocptr = find_client(parv[2], NULL)) && ocptr != acptr) /* Collision */
	{
		exit_client(acptr, acptr, sptr,
		                   "Nickname collision due to Services enforced "
		                   "nickname change, your nick was overruled");
		return 0;
	}

	if (acptr != ocptr)
		acptr->umodes &= ~UMODE_REGNICK;
	acptr->lastnick = TS2ts(parv[3]);
	sendto_common_channels(acptr, ":%s NICK :%s", parv[1], parv[2]);
	add_history(acptr, 1);
	sendto_serv_butone_token(NULL, parv[1], MSG_NICK, TOK_NICK,
	                         "%s :%ld", parv[2], TS2ts(parv[3]));

	(void)del_from_client_hash_table(acptr->name, acptr);
	hash_check_watch(acptr, RPL_LOGOFF);

	sendto_snomask(SNO_NICKCHANGE,
		"*** Notice -- %s (%s@%s) has been forced to change his/her nickname to %s", 
		acptr->name, acptr->user->username, acptr->user->realhost, parv[2]);
	RunHook2(HOOKTYPE_LOCAL_NICKCHANGE, acptr, parv[2]);

	strlcpy(acptr->name, parv[2], sizeof acptr->name);
	add_to_client_hash_table(parv[2], acptr);
	hash_check_watch(acptr, RPL_LOGON);

	return 0;
}
Пример #16
0
int m_svsnoop(aClient *cptr, aClient *sptr, int parc, char *parv[])
{
        aClient *acptr;

        if (!(IsULine(sptr) && parc > 2))
                return 0;
        /* svsnoop bugfix --binary */
        if (hunt_server_token(cptr, sptr, MSG_SVSNOOP, TOK_SVSNOOP, "%s :%s", 1, parc,
            parv) == HUNTED_ISME)
        {
                if (parv[2][0] == '+')
                {
                        SVSNOOP = 1;
                        sendto_ops("This server has been placed in NOOP mode");
                        for (acptr = &me; acptr; acptr = acptr->prev)
                        {
                                if (MyClient(acptr) && IsAnOper(acptr))
                                {
                                        if (IsOper(acptr))
                                        {
                                                IRCstats.operators--;
                                                VERIFY_OPERCOUNT(acptr, "svsnoop");
                                        }
					if (IsAnOper(acptr))
                                                delfrom_fdlist(acptr->slot, &oper_fdlist);
										if (IsTotalInvis(acptr)) {
											sendto_channels_inviso_join(acptr);
										}
                                        acptr->umodes &= ~(UMODE_OPER|UMODE_HELPOP|UMODE_SADMIN|UMODE_ADMIN|UMODE_LOCOP|UMODE_SERVICES|UMODE_NETADMIN);
										acptr->umodes &= ~(UMODE_WHOIS|UMODE_KIX|UMODE_HIDEOPER|UMODE_HIDEWHOIS|UMODE_TOTALINVIS|UMODE_MODEWALK|UMODE_NOFAKELAG);
                                        acptr->oflag = 0;
                                        remove_oper_snomasks(acptr);
										sendto_one(acptr, ":%s NOTICE %s :*** Your OFLAGS have been cleared, because this server has been placed in NOOP mode", me.name, acptr->name);
					RunHook2(HOOKTYPE_LOCAL_OPER, acptr, 0);
                                }
                        }

                }
                else
                {
                        SVSNOOP = 0;
                        sendto_ops("This server is no longer in NOOP mode");
                }
        }
	return 0;
}
Пример #17
0
/*
** m_svslusers
**      parv[0] = sender
**      parv[1] = server to update
**      parv[2] = max global users
**      parv[3] = max local users
**      If -1 is specified for either number, it is ignored and the current count
**      is kept.
*/
int  m_svslusers(aClient *cptr, aClient *sptr, int parc, char *parv[])
{
        if (!IsULine(sptr) || parc < 4)
		return -1;  
        if (hunt_server_token(cptr, sptr, MSG_SVSLUSERS, TOK_SVSLUSERS, "%s %s :%s", 1, parc,
		parv) == HUNTED_ISME)
        {
		int temp;
		temp = atoi(parv[2]);
		if (temp >= 0)
			IRCstats.global_max = temp;
		temp = atoi(parv[3]);
		if (temp >= 0) 
			IRCstats.me_max = temp;
        }
        return 0;
}
Пример #18
0
/*
** m_sanick() - PID - 08-08-2011
**
**      parv[0] - sender
**      parv[1] - nick to make join
**      parv[2] - channel(s) to join
*/
int m_sanick(aClient * cptr, aClient * sptr, int parc, char *parv[])  {
       aClient *acptr;
	char *param[3];
	int self = 0;
//	if (IsServer(sptr) || IsServices(sptr))
//		return 0; //Servers and Services should be invoking SVSNICK directly...
	if (!IsOper(sptr) && !IsAdmin(sptr) && !IsULine(sptr))   {
               sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
               return 0;
       }
	if (parv[1] == NULL || !parv[1] || !parv[2]) {
		sendnotice(sptr, "*** Usage: \2/sanick oldnick newnick\2");
		return 0;
	}
       if (parv[2] == NULL || !(acptr = find_person(parv[1], NULL))) {
		sendnotice(sptr, "*** No such user, %s.", parv[1]);
		return 0;
	}
	if (!strcmp(parv[2], parv[1]) || !strcmp(parv[2], parv[0])) {
		sendnotice(sptr, "*** Perhaps I should warn people that they have given an idiot IRCOp access?");
		return 0;
	}
	if (!strcmp(parv[0], parv[1]))
		self = 1;
	if (find_client(parv[2], NULL)) {
		sendnotice(sptr, "*** WARNING: User %s already exists!", parv[2]);
		return 0;
	}
	if(acptr->umodes & UMODE_REGNICK)
		acptr->umodes &= ~UMODE_REGNICK;
	param[0] = acptr->name;
	param[1] = parv[2];
	param[2] = NULL;
	sendnotice(acptr, "*** You were forced to change your nick to %s", parv[2]);
	do_cmd(acptr, acptr, "NICK", 2, param);
	if(self) {
		sendto_realops("%s used \2SANICK\2 to change their nick to %s.", parv[1], parv[2]);
		ircd_log(LOG_SACMDS,"SANICK: %s used SANICK to change their nick to %s", parv[1], parv[2]);
	} else {
		sendto_realops("%s used \2SANICK\2 to make %s change their nick to %s.", parv[0], parv[1], parv[2]);
		ircd_log(LOG_SACMDS,"SANICK: %s used SANICK to make %s change their nick to %s", acptr->name, parv[1], parv[2]);
	}
	return 0;
}
Пример #19
0
int  channel_canjoin(aClient *sptr, char *name)
{
	ConfigItem_deny_channel *p;

	if (IsOper(sptr))
		return 1;
	if (IsULine(sptr))
		return 1;
	if (!conf_deny_channel)
		return 1;
	p = Find_channel_allowed(name);
	if (p)
	{
		sendto_one(sptr, ":%s NOTICE %s :*** %s",
			me.name, sptr->name, p->reason);
		return 0;
	}
	return 1;
}
Пример #20
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);
		}
	}
}
Пример #21
0
void exit_server(aClient *lcptr, aClient *cptr, aClient *from, char *comment)
{
    char splitname[HOSTLEN + HOSTLEN + 2];

#ifdef HIDE_SPLIT_SERVERS
    ircsprintf(splitname, "%s %s", HIDDEN_SERVER_NAME, HIDDEN_SERVER_NAME);
#else
    /* Don't show uplink servers for a u:lined link! */
    if(IsULine(cptr))
        ircsprintf(splitname, "%s %s", cptr->name, cptr->name);
    else
        ircsprintf(splitname, "%s %s", cptr->uplink->name, cptr->name);
#endif

    Debug((DEBUG_NOTICE, "exit_server(%s, %s, %s)", cptr->name, from->name,
           comment));

    exit_one_server(cptr, cptr, from, lcptr, splitname, comment);
}
Пример #22
0
int nokick_can_kick(aClient *sptr, aClient *target, aChannel *chptr, char *comment,
                    long sptr_flags, long target_flags, char **reject_reason)
{
	static char errmsg[NICKLEN+256];

	if (IsNokick(target) && !IsULine(sptr) && MyClient(sptr) && !ValidatePermissionsForPath("override:kick:nokick",sptr,target,chptr,NULL))
	{
		ircsnprintf(errmsg, sizeof(errmsg), err_str(ERR_CANNOTDOCOMMAND),
				   me.name, sptr->name, "KICK",
				   "user is unkickable (user mode +q)");

		*reject_reason = errmsg;

		sendnotice(target,
			"*** umode q: %s tried to kick you from channel %s (%s)",
			sptr->name, chptr->chname, comment);
		
		return EX_ALWAYS_DENY;
	}

	return EX_ALLOW;
}
Пример #23
0
int  channel_canjoin(aClient *sptr, char *name)
{
	ConfigItem_deny_channel *p;
	aTKline *tklban;
	int ishold;
	if (!ValidatePermissionsForPath("channel:restricted",sptr,NULL,NULL,name))
		return 1;
	if (IsULine(sptr))
		return 1;
	if (!conf_deny_channel)
		return 1;
	p = Find_channel_allowed(sptr, name);
	if (p)
	{
		sendto_one(sptr, err_str(ERR_FORBIDDENCHANNEL), me.name, sptr->name, name, p->reason);
		return 0;
	}
	if ((tklban = find_qline(sptr, name, &ishold)))
	{
		sendto_one(sptr, err_str(ERR_FORBIDDENCHANNEL), me.name, sptr->name, name, tklban->reason);
		return 0;
	}
	return 1;
}
Пример #24
0
DLLFUNC int m_rmtkl(aClient *cptr, aClient *sptr, int parc, char *parv[])
{
aTKline *tk, *next = NULL;
TKLType *tkltype;
char *types, *uhmask, *cmask, *p;
char gmt[256], flag;
int tklindex;

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

	if (IsNotParam(1))
		return dumpit(sptr, rmtkl_help);

	if (IsNotParam(2))
	{
		sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "RMTKL");
		sendnotice(sptr, "Type '/RMTKL' for help");
		return 0;
	}

	types	= parv[1];
	uhmask	= parv[2];
	cmask	= IsParam(3) ? parv[3] : NULL;

	/* I don't add 'q' and 'Q' here. They are different. */
	if (strchr(types, '*'))
		types = "KzGZs";

	/* check access */
	if (!IsULine(sptr))
		for (p = types; *p; p++)
		{
			tkltype = find_TKLType_by_flag(*p);
			if (!tkltype->type)
				continue;
			if (((tkltype->type & TKL_GLOBAL) && !IsOper(sptr))
			    || !(sptr->oflag & tkltype->oflag))
			{
				sendto_one(sptr, err_str(ERR_NOPRIVILEGES),
					me.name, parv[0]);
				return -1;
			}
		}

	for (tkltype = tkl_types; tkltype->type; tkltype++)
	{
		flag		= tkltype->flag;
		tklindex	= tkl_hash(flag);

		if (!strchr(types, flag))
			continue;

		for (tk = tklines[tklindex]; tk; tk = next)
		{
			next = tk->next;

			if (tk->type != tkltype->type)
				continue;
			if (tk->type & TKL_NICK)
			{
				/*
				 * If it's a services hold (ie. NickServ is holding
				 * a nick), it's better not to touch it
				 */
				if (*tk->usermask == 'H')
					continue;
				if (match(uhmask, tk->hostmask))
					continue;
			}
			else
				if (match(uhmask, make_user_host(tk->usermask, tk->hostmask)))
					continue;

			if (cmask && _match(cmask, tk->reason))
				continue;

			strncpyzt(gmt, asctime(gmtime((TS *)&tk->set_at)),
				sizeof gmt);
			iCstrip(gmt);

			if (tk->type & TKL_NICK)
			{
				sendto_snomask(SNO_TKL, "%s removed %s %s (set at %s "
					"- reason: %s)",
					sptr->name, tkltype->txt, tk->hostmask, gmt,
					tk->reason);
				ircd_log(LOG_TKL, "%s removed %s %s (set at %s "
					"- reason: %s)",
					sptr->name, tkltype->txt, tk->hostmask,
					gmt, tk->reason);
			}
			else
			{
				sendto_snomask(SNO_TKL, "%s removed %s %s@%s (set at "
					"%s - reason: %s)",
					sptr->name, tkltype->txt, tk->usermask,
					tk->hostmask, gmt, tk->reason);
				ircd_log(LOG_TKL, "%s removed %s %s@%s (set at "
					"%s - reason: %s)",
					sptr->name, tkltype->txt, tk->usermask,
					tk->hostmask, gmt, tk->reason);
			}

			if ((tk->type & TKL_GLOBAL) && flag)
				sendto_serv_butone_token(&me, me.name, MSG_TKL, TOK_TKL,
					"- %c %s %s %s",
					flag, tk->usermask, tk->hostmask, parv[0]);
			if (tk->type & TKL_SHUN)
				tkl_check_local_remove_shun(tk);
			my_tkl_del_line(tk, tklindex);
		}
	}

	return 0;
}
Пример #25
0
/*
** m_nick
**	parv[0] = sender prefix
**	parv[1] = nickname
**  if from new client  -taz
**	parv[2] = nick password
**  if from server:
**      parv[2] = hopcount
**      parv[3] = timestamp
**      parv[4] = username
**      parv[5] = hostname
**      parv[6] = servername
**  if NICK version 1:
**      parv[7] = servicestamp
**	parv[8] = info
**  if NICK version 2:
**	parv[7] = servicestamp
**      parv[8] = umodes
**	parv[9] = virthost, * if none
**	parv[10] = info
**  if NICKIP:
**      parv[10] = ip
**      parv[11] = info
*/
DLLFUNC CMD_FUNC(m_nick)
{
	aTKline *tklban;
	int ishold;
	aClient *acptr, *serv = NULL;
	aClient *acptrs;
	char nick[NICKLEN + 2], *s;
	Membership *mp;
	time_t lastnick = (time_t) 0;
	int  differ = 1, update_watch = 1;
	unsigned char newusr = 0, removemoder = 1;
	/*
	 * If the user didn't specify a nickname, complain
	 */
	if (parc < 2)
	{
		sendto_one(sptr, err_str(ERR_NONICKNAMEGIVEN),
		    me.name, parv[0]);
		return 0;
	}

	strncpyzt(nick, parv[1], NICKLEN + 1);

	if (MyConnect(sptr) && sptr->user && !IsAnOper(sptr))
	{
		if ((sptr->user->flood.nick_c >= NICK_COUNT) && 
		    (TStime() - sptr->user->flood.nick_t < NICK_PERIOD))
		{
			/* Throttle... */
			sendto_one(sptr, err_str(ERR_NCHANGETOOFAST), me.name, sptr->name, nick,
				(int)(NICK_PERIOD - (TStime() - sptr->user->flood.nick_t)));
			return 0;
		}
	}

	/* For a local clients, do proper nickname checking via do_nick_name()
	 * and reject the nick if it returns false.
	 * For remote clients, do a quick check by using do_remote_nick_name(),
	 * if this returned false then reject and kill it. -- Syzop
	 */
	if ((IsServer(cptr) && !do_remote_nick_name(nick)) ||
	    (!IsServer(cptr) && !do_nick_name(nick)))
	{
		sendto_one(sptr, err_str(ERR_ERRONEUSNICKNAME),
		    me.name, parv[0], parv[1], "Illegal characters");

		if (IsServer(cptr))
		{
			ircstp->is_kill++;
			sendto_failops("Bad Nick: %s From: %s %s",
			    parv[1], parv[0], get_client_name(cptr, FALSE));
			sendto_one(cptr, ":%s KILL %s :%s (%s <- %s[%s])",
			    me.name, parv[1], me.name, parv[1],
			    nick, cptr->name);
			if (sptr != cptr)
			{	/* bad nick change */
				sendto_serv_butone(cptr,
				    ":%s KILL %s :%s (%s <- %s!%s@%s)",
				    me.name, parv[0], me.name,
				    get_client_name(cptr, FALSE),
				    parv[0],
				    sptr->user ? sptr->username : "",
				    sptr->user ? sptr->user->server :
				    cptr->name);
				sptr->flags |= FLAGS_KILLED;
				return exit_client(cptr, sptr, &me, "BadNick");
			}
		}
		return 0;
	}

	/* Kill quarantined opers early... */
	if (IsServer(cptr) && (sptr->from->flags & FLAGS_QUARANTINE) &&
	    (parc >= 11) && strchr(parv[8], 'o'))
	{
		ircstp->is_kill++;
		/* Send kill to uplink only, hasn't been broadcasted to the rest, anyway */
		sendto_one(cptr, ":%s KILL %s :%s (Quarantined: no global oper privileges allowed)",
			me.name, parv[1], me.name);
		sendto_realops("QUARANTINE: Oper %s on server %s killed, due to quarantine",
			parv[1], sptr->name);
		/* (nothing to exit_client or to free, since user was never added) */
		return 0;
	}

	/*
	   ** Protocol 4 doesn't send the server as prefix, so it is possible
	   ** the server doesn't exist (a lagged net.burst), in which case
	   ** we simply need to ignore the NICK. Also when we got that server
	   ** name (again) but from another direction. --Run
	 */
	/*
	   ** We should really only deal with this for msgs from servers.
	   ** -- Aeto
	 */
	if (IsServer(cptr) &&
	    (parc > 7
	    && (!(serv = (aClient *)find_server_b64_or_real(parv[6]))
	    || serv->from != cptr->from)))
	{
		sendto_realops("Cannot find server %s (%s)", parv[6],
		    backupbuf);
		return 0;
	}
	/*
	   ** Check against nick name collisions.
	   **
	   ** Put this 'if' here so that the nesting goes nicely on the screen :)
	   ** We check against server name list before determining if the nickname
	   ** is present in the nicklist (due to the way the below for loop is
	   ** constructed). -avalon
	 */
	/* I managed to f**k this up i guess --stskeeps */
	if ((acptr = find_server(nick, NULL)))
	{
		if (MyConnect(sptr))
		{
#ifdef GUEST
			if (IsUnknown(sptr))
			{
				RunHook4(HOOKTYPE_GUEST, cptr, sptr, parc, parv);
				return 0;
			}
#endif
			sendto_one(sptr, err_str(ERR_NICKNAMEINUSE), me.name,
			    BadPtr(parv[0]) ? "*" : parv[0], nick);
			return 0;	/* NICK message ignored */
		}
	}

	/*
	   ** Check for a Q-lined nickname. If we find it, and it's our
	   ** client, just reject it. -Lefler
	   ** Allow opers to use Q-lined nicknames. -Russell
	 */
	if (!stricmp("ircd", nick))
	{
		sendto_one(sptr, err_str(ERR_ERRONEUSNICKNAME), me.name,
		    BadPtr(parv[0]) ? "*" : parv[0], nick,
		    "Reserved for internal IRCd purposes");
		return 0;
	}
	if (!stricmp("irc", nick))
	{
		sendto_one(sptr, err_str(ERR_ERRONEUSNICKNAME), me.name,
		    BadPtr(parv[0]) ? "*" : parv[0], nick,
		    "Reserved for internal IRCd purposes");
		return 0;
	}
	if (MyClient(sptr)) /* local client changin nick afterwards.. */
	{
		int xx;
		spamfilter_build_user_string(spamfilter_user, nick, sptr);
		xx = dospamfilter(sptr, spamfilter_user, SPAMF_USER, NULL, 0, NULL);
		if (xx < 0)
			return xx;
	}
	if (!IsULine(sptr) && (tklban = find_qline(sptr, nick, &ishold)))
	{
		if (IsServer(sptr) && !ishold) /* server introducing new client */
		{
			acptrs =
			    (aClient *)find_server_b64_or_real(sptr->user ==
			    NULL ? (char *)parv[6] : (char *)sptr->user->
			    server);
			/* (NEW: no unregistered q:line msgs anymore during linking) */
			if (!acptrs || (acptrs->serv && acptrs->serv->flags.synced))
				sendto_snomask(SNO_QLINE, "Q:lined nick %s from %s on %s", nick,
				    (*sptr->name != 0
				    && !IsServer(sptr) ? sptr->name : "<unregistered>"),
				    acptrs ? acptrs->name : "unknown server");
		}
		
		if (IsServer(cptr) && IsPerson(sptr) && !ishold) /* remote user changing nick */
		{
			sendto_snomask(SNO_QLINE, "Q:lined nick %s from %s on %s", nick,
				sptr->name, sptr->srvptr ? sptr->srvptr->name : "<unknown>");
		}

		if (!IsServer(cptr)) /* local */
		{
			if (ishold)
			{
				sendto_one(sptr, err_str(ERR_ERRONEUSNICKNAME),
				    me.name, BadPtr(parv[0]) ? "*" : parv[0],
				    nick, tklban->reason);
				return 0;
			}
			if (!IsOper(cptr))
			{
				sptr->since += 4; /* lag them up */
				sendto_one(sptr, err_str(ERR_ERRONEUSNICKNAME),
				    me.name, BadPtr(parv[0]) ? "*" : parv[0],
				    nick, tklban->reason);
				sendto_snomask(SNO_QLINE, "Forbidding Q-lined nick %s from %s.",
				    nick, get_client_name(cptr, FALSE));
				return 0;	/* NICK message ignored */
			}
		}
	}
	/*
	   ** acptr already has result from previous find_server()
	 */
	if (acptr)
	{
		/*
		   ** We have a nickname trying to use the same name as
		   ** a server. Send out a nick collision KILL to remove
		   ** the nickname. As long as only a KILL is sent out,
		   ** there is no danger of the server being disconnected.
		   ** Ultimate way to jupiter a nick ? >;-). -avalon
		 */
		sendto_failops("Nick collision on %s(%s <- %s)",
		    sptr->name, acptr->from->name,
		    get_client_name(cptr, FALSE));
		ircstp->is_kill++;
		sendto_one(cptr, ":%s KILL %s :%s (%s <- %s)",
		    me.name, sptr->name, me.name, acptr->from->name,
		    /* NOTE: Cannot use get_client_name
		       ** twice here, it returns static
		       ** string pointer--the other info
		       ** would be lost
		     */
		    get_client_name(cptr, FALSE));
		sptr->flags |= FLAGS_KILLED;
		return exit_client(cptr, sptr, &me, "Nick/Server collision");
	}

	if (MyClient(cptr) && !IsOper(cptr))
		cptr->since += 3;	/* Nick-flood prot. -Donwulff */

	if (!(acptr = find_client(nick, NULL)))
		goto nickkilldone;	/* No collisions, all clear... */
	/*
	   ** If the older one is "non-person", the new entry is just
	   ** allowed to overwrite it. Just silently drop non-person,
	   ** and proceed with the nick. This should take care of the
	   ** "dormant nick" way of generating collisions...
	 */
	/* Moved before Lost User Field to fix some bugs... -- Barubary */
	if (IsUnknown(acptr) && MyConnect(acptr))
	{
		/* This may help - copying code below */
		if (acptr == cptr)
			return 0;
		acptr->flags |= FLAGS_KILLED;
		exit_client(NULL, acptr, &me, "Overridden");
		goto nickkilldone;
	}
	/* A sanity check in the user field... */
	if (acptr->user == NULL)
	{
		/* This is a Bad Thing */
		sendto_failops("Lost user field for %s in change from %s",
		    acptr->name, get_client_name(cptr, FALSE));
		ircstp->is_kill++;
		sendto_one(acptr, ":%s KILL %s :%s (Lost user field!)",
		    me.name, acptr->name, me.name);
		acptr->flags |= FLAGS_KILLED;
		/* Here's the previous versions' desynch.  If the old one is
		   messed up, trash the old one and accept the new one.
		   Remember - at this point there is a new nick coming in!
		   Handle appropriately. -- Barubary */
		exit_client(NULL, acptr, &me, "Lost user field");
		goto nickkilldone;
	}
	/*
	   ** If acptr == sptr, then we have a client doing a nick
	   ** change between *equivalent* nicknames as far as server
	   ** is concerned (user is changing the case of his/her
	   ** nickname or somesuch)
	 */
	if (acptr == sptr) {
		if (strcmp(acptr->name, nick) != 0)
		{
			/* Allows change of case in his/her nick */
			removemoder = 0; /* don't set the user -r */
			goto nickkilldone;	/* -- go and process change */
		} else
			/*
			 ** This is just ':old NICK old' type thing.
			 ** Just forget the whole thing here. There is
			 ** no point forwarding it to anywhere,
			 ** especially since servers prior to this
			 ** version would treat it as nick collision.
			 */
			return 0;	/* NICK Message ignored */
	}
	/*
	   ** Note: From this point forward it can be assumed that
	   ** acptr != sptr (point to different client structures).
	 */
	/*
	   ** Decide, we really have a nick collision and deal with it
	 */
	if (!IsServer(cptr))
	{
		/*
		   ** NICK is coming from local client connection. Just
		   ** send error reply and ignore the command.
		 */
#ifdef GUEST
		if (IsUnknown(sptr))
		{
			RunHook4(HOOKTYPE_GUEST, cptr, sptr, parc, parv);
			return 0;
		}
#endif
		sendto_one(sptr, err_str(ERR_NICKNAMEINUSE),
		    /* parv[0] is empty when connecting */
		    me.name, BadPtr(parv[0]) ? "*" : parv[0], nick);
		return 0;	/* NICK message ignored */
	}
	/*
	   ** NICK was coming from a server connection.
	   ** This means we have a race condition (two users signing on
	   ** at the same time), or two net fragments reconnecting with
	   ** the same nick.
	   ** The latter can happen because two different users connected
	   ** or because one and the same user switched server during a
	   ** net break.
	   ** If we have the old protocol (no TimeStamp and no user@host)
	   ** or if the TimeStamps are equal, we kill both (or only 'new'
	   ** if it was a "NICK new"). Otherwise we kill the youngest
	   ** when user@host differ, or the oldest when they are the same.
	   ** --Run
	   **
	 */
	if (IsServer(sptr))
	{
		/*
		   ** A new NICK being introduced by a neighbouring
		   ** server (e.g. message type "NICK new" received)
		 */
		if (parc > 3)
		{
			lastnick = TS2ts(parv[3]);
			if (parc > 5)
				differ = (mycmp(acptr->user->username, parv[4])
				    || mycmp(acptr->user->realhost, parv[5]));
		}
		sendto_failops("Nick collision on %s (%s %ld <- %s %ld)",
		    acptr->name, acptr->from->name, acptr->lastnick,
		    cptr->name, lastnick);
		/*
		   **    I'm putting the KILL handling here just to make it easier
		   ** to read, it's hard to follow it the way it used to be.
		   ** Basically, this is what it will do.  It will kill both
		   ** users if no timestamp is given, or they are equal.  It will
		   ** kill the user on our side if the other server is "correct"
		   ** (user@host differ and their user is older, or user@host are
		   ** the same and their user is younger), otherwise just kill the
		   ** user an reintroduce our correct user.
		   **    The old code just sat there and "hoped" the other server
		   ** would kill their user.  Not anymore.
		   **                                               -- binary
		 */
		if (!(parc > 3) || (acptr->lastnick == lastnick))
		{
			ircstp->is_kill++;
			sendto_serv_butone(NULL,
			    ":%s KILL %s :%s (Nick Collision)",
			    me.name, acptr->name, me.name);
			acptr->flags |= FLAGS_KILLED;
			(void)exit_client(NULL, acptr, &me,
			    "Nick collision with no timestamp/equal timestamps");
			return 0;	/* We killed both users, now stop the process. */
		}

		if ((differ && (acptr->lastnick > lastnick)) ||
		    (!differ && (acptr->lastnick < lastnick)) || acptr->from == cptr)	/* we missed a QUIT somewhere ? */
		{
			ircstp->is_kill++;
			sendto_serv_butone(cptr,
			    ":%s KILL %s :%s (Nick Collision)",
			    me.name, acptr->name, me.name);
			acptr->flags |= FLAGS_KILLED;
			(void)exit_client(NULL, acptr, &me, "Nick collision");
			goto nickkilldone;	/* OK, we got rid of the "wrong" user,
						   ** now we're going to add the user the
						   ** other server introduced.
						 */
		}

		if ((differ && (acptr->lastnick < lastnick)) ||
		    (!differ && (acptr->lastnick > lastnick)))
		{
			/*
			 * Introduce our "correct" user to the other server
			 */

			sendto_one(cptr, ":%s KILL %s :%s (Nick Collision)",
			    me.name, parv[1], me.name);
			send_umode(NULL, acptr, 0, SEND_UMODES, buf);
			sendto_one_nickcmd(cptr, acptr, buf);
			if (acptr->user->away)
				sendto_one(cptr, ":%s AWAY :%s", acptr->name,
				    acptr->user->away);
			send_user_joins(cptr, acptr);
			return 0;	/* Ignore the NICK */
		}
		return 0;
	}
	else
	{
		/*
		   ** A NICK change has collided (e.g. message type ":old NICK new").
		 */
		if (parc > 2)
			lastnick = TS2ts(parv[2]);
		differ = (mycmp(acptr->user->username, sptr->user->username) ||
		    mycmp(acptr->user->realhost, sptr->user->realhost));
		sendto_failops
		    ("Nick change collision from %s to %s (%s %ld <- %s %ld)",
		    sptr->name, acptr->name, acptr->from->name, acptr->lastnick,
		    sptr->from->name, lastnick);
		if (!(parc > 2) || lastnick == acptr->lastnick)
		{
			ircstp->is_kill += 2;
			sendto_serv_butone(NULL,	/* First kill the new nick. */
			    ":%s KILL %s :%s (Self Collision)",
			    me.name, acptr->name, me.name);
			sendto_serv_butone(cptr,	/* Tell my servers to kill the old */
			    ":%s KILL %s :%s (Self Collision)",
			    me.name, sptr->name, me.name);
			sptr->flags |= FLAGS_KILLED;
			acptr->flags |= FLAGS_KILLED;
			(void)exit_client(NULL, sptr, &me, "Self Collision");
			(void)exit_client(NULL, acptr, &me, "Self Collision");
			return 0;	/* Now that I killed them both, ignore the NICK */
		}
		if ((differ && (acptr->lastnick > lastnick)) ||
		    (!differ && (acptr->lastnick < lastnick)))
		{
			/* sptr (their user) won, let's kill acptr (our user) */
			ircstp->is_kill++;
			sendto_serv_butone(cptr,
			    ":%s KILL %s :%s (Nick collision: %s <- %s)",
			    me.name, acptr->name, me.name,
			    acptr->from->name, sptr->from->name);
			acptr->flags |= FLAGS_KILLED;
			(void)exit_client(NULL, acptr, &me, "Nick collision");
			goto nickkilldone;	/* their user won, introduce new nick */
		}
		if ((differ && (acptr->lastnick < lastnick)) ||
		    (!differ && (acptr->lastnick > lastnick)))
		{
			/* acptr (our user) won, let's kill sptr (their user),
			   ** and reintroduce our "correct" user
			 */
			ircstp->is_kill++;
			/* Kill the user trying to change their nick. */
			sendto_serv_butone(cptr,
			    ":%s KILL %s :%s (Nick collision: %s <- %s)",
			    me.name, sptr->name, me.name,
			    sptr->from->name, acptr->from->name);
			sptr->flags |= FLAGS_KILLED;
			(void)exit_client(NULL, sptr, &me, "Nick collision");
			/*
			 * Introduce our "correct" user to the other server
			 */
			/* Kill their user. */
			sendto_one(cptr, ":%s KILL %s :%s (Nick Collision)",
			    me.name, parv[1], me.name);
			send_umode(NULL, acptr, 0, SEND_UMODES, buf);
			sendto_one_nickcmd(cptr, acptr, buf);
			if (acptr->user->away)
				sendto_one(cptr, ":%s AWAY :%s", acptr->name,
				    acptr->user->away);

			send_user_joins(cptr, acptr);
			return 0;	/* their user lost, ignore the NICK */
		}

	}
	return 0;		/* just in case */
      nickkilldone:
	if (IsServer(sptr))
	{
		/* A server introducing a new client, change source */

		sptr = make_client(cptr, serv);
		add_client_to_list(sptr);
		if (parc > 2)
			sptr->hopcount = TS2ts(parv[2]);
		if (parc > 3)
			sptr->lastnick = TS2ts(parv[3]);
		else		/* Little bit better, as long as not all upgraded */
			sptr->lastnick = TStime();
		if (sptr->lastnick < 0)
		{
			sendto_realops
			    ("Negative timestamp recieved from %s, resetting to TStime (%s)",
			    cptr->name, backupbuf);
			sptr->lastnick = TStime();
		}
		newusr = 1;
	}
	else if (sptr->name[0] && IsPerson(sptr))
	{
		/*
		   ** If the client belongs to me, then check to see
		   ** if client is currently on any channels where it
		   ** is currently banned.  If so, do not allow the nick
		   ** change to occur.
		   ** Also set 'lastnick' to current time, if changed.
		 */
		if (MyClient(sptr))
		{
			for (mp = sptr->user->channel; mp; mp = mp->next)
			{
				if (!is_skochanop(sptr, mp->chptr) && is_banned(sptr, mp->chptr, BANCHK_NICK))
				{
					sendto_one(sptr,
					    err_str(ERR_BANNICKCHANGE),
					    me.name, parv[0],
					    mp->chptr->chname);
					return 0;
				}
				if (CHECK_TARGET_NICK_BANS && !is_skochanop(sptr, mp->chptr) && is_banned_with_nick(sptr, mp->chptr, BANCHK_NICK, nick))
				{
					sendto_one(sptr,
					    ":%s 437 %s %s :Cannot change to a nickname banned on channel",
					    me.name, parv[0],
					    mp->chptr->chname);
					return 0;
				}
				if (!IsOper(sptr) && !IsULine(sptr)
				    && mp->chptr->mode.mode & MODE_NONICKCHANGE
				    && !is_chanownprotop(sptr, mp->chptr))
				{
					sendto_one(sptr,
					    err_str(ERR_NONICKCHANGE),
					    me.name, parv[0],
					    mp->chptr->chname);
					return 0;
				}
			}

			if (TStime() - sptr->user->flood.nick_t >= NICK_PERIOD)
			{
				sptr->user->flood.nick_t = TStime();
				sptr->user->flood.nick_c = 1;
			} else
				sptr->user->flood.nick_c++;

			sendto_snomask(SNO_NICKCHANGE, "*** Notice -- %s (%s@%s) has changed his/her nickname to %s",
				sptr->name, sptr->user->username, sptr->user->realhost, nick);

			RunHook2(HOOKTYPE_LOCAL_NICKCHANGE, sptr, nick);
		} else {
			if (!IsULine(sptr))
				sendto_snomask(SNO_FNICKCHANGE, "*** Notice -- %s (%s@%s) has changed his/her nickname to %s",
					sptr->name, sptr->user->username, sptr->user->realhost, nick);

			RunHook3(HOOKTYPE_REMOTE_NICKCHANGE, cptr, sptr, nick);
		}
		/*
		 * Client just changing his/her nick. If he/she is
		 * on a channel, send note of change to all clients
		 * on that channel. Propagate notice to other servers.
		 */
		if (mycmp(parv[0], nick) ||
		    /* Next line can be removed when all upgraded  --Run */
		    (!MyClient(sptr) && parc > 2
		    && TS2ts(parv[2]) < sptr->lastnick))
			sptr->lastnick = (MyClient(sptr)
			    || parc < 3) ? TStime() : TS2ts(parv[2]);
		if (sptr->lastnick < 0)
		{
			sendto_realops("Negative timestamp (%s)", backupbuf);
			sptr->lastnick = TStime();
		}
		add_history(sptr, 1);
		sendto_common_channels(sptr, ":%s NICK :%s", parv[0], nick);
		sendto_serv_butone_token(cptr, parv[0], MSG_NICK, TOK_NICK,
		    "%s %ld", nick, sptr->lastnick);
		if (removemoder)
			sptr->umodes &= ~UMODE_REGNICK;
	}
	else if (!sptr->name[0])
	{
#ifdef NOSPOOF
		/*
		 * Client setting NICK the first time.
		 *
		 * Generate a random string for them to pong with.
		 */
		sptr->nospoof = getrandom32();

		if (PINGPONG_WARNING)
			sendto_one(sptr, ":%s NOTICE %s :*** If you are having problems"
			    " connecting due to ping timeouts, please"
			    " type /quote pong %X or /raw pong %X now.",
			    me.name, nick, sptr->nospoof, sptr->nospoof);

		sendto_one(sptr, "PING :%X", sptr->nospoof);
#endif /* NOSPOOF */
#ifdef CONTACT_EMAIL
		sendto_one(sptr,
		    ":%s NOTICE %s :*** If you need assistance with a"
		    " connection problem, please email " CONTACT_EMAIL
		    " with the name and version of the client you are"
		    " using, and the server you tried to connect to: %s",
		    me.name, nick, me.name);
#endif /* CONTACT_EMAIL */
#ifdef CONTACT_URL
		sendto_one(sptr,
		    ":%s NOTICE %s :*** If you need assistance with"
		    " connecting to this server, %s, please refer to: "
		    CONTACT_URL, me.name, nick, me.name);
#endif /* CONTACT_URL */

		/* Copy password to the passwd field if it's given after NICK
		 * - originally by taz, modified by Wizzu
		 */
		if ((parc > 2) && (strlen(parv[2]) <= PASSWDLEN)
		    && !(sptr->listener->umodes & LISTENER_JAVACLIENT))
		{
			if (sptr->passwd)
				MyFree(sptr->passwd);
			sptr->passwd = MyMalloc(strlen(parv[2]) + 1);
			(void)strcpy(sptr->passwd, parv[2]);
		}
		/* This had to be copied here to avoid problems.. */
		(void)strcpy(sptr->name, nick);
		if (sptr->user && IsNotSpoof(sptr))
		{
			/*
			   ** USER already received, now we have NICK.
			   ** *NOTE* For servers "NICK" *must* precede the
			   ** user message (giving USER before NICK is possible
			   ** only for local client connection!). register_user
			   ** may reject the client and call exit_client for it
			   ** --must test this and exit m_nick too!!!
			 */
#ifndef NOSPOOF
			if (USE_BAN_VERSION && MyConnect(sptr))
				sendto_one(sptr, ":IRC!IRC@%s PRIVMSG %s :\1VERSION\1",
					me.name, nick);
#endif
			sptr->lastnick = TStime();	/* Always local client */
			if (register_user(cptr, sptr, nick,
			    sptr->user->username, NULL, NULL, NULL) == FLUSH_BUFFER)
				return FLUSH_BUFFER;
			strcpy(nick, sptr->name); /* don't ask, but I need this. do not remove! -- Syzop */
			update_watch = 0;
			newusr = 1;
		}
	}
	/*
	 *  Finally set new nick name.
	 */
	if (update_watch && sptr->name[0])
	{
		(void)del_from_client_hash_table(sptr->name, sptr);
		if (IsPerson(sptr))
			hash_check_watch(sptr, RPL_LOGOFF);
	}
	(void)strcpy(sptr->name, nick);
	(void)add_to_client_hash_table(nick, sptr);
	if (IsServer(cptr) && parc > 7)
	{
		parv[3] = nick;
		do_cmd(cptr, sptr, "USER", parc - 3, &parv[3]);
		if (GotNetInfo(cptr) && !IsULine(sptr))
			sendto_fconnectnotice(sptr->name, sptr->user, sptr, 0, NULL);
	}
	else if (IsPerson(sptr) && update_watch)
		hash_check_watch(sptr, RPL_LOGON);

#ifdef NEWCHFLOODPROT
	if (sptr->user && !newusr && !IsULine(sptr))
	{
		for (mp = sptr->user->channel; mp; mp = mp->next)
		{
			aChannel *chptr = mp->chptr;
			if (chptr && !(mp->flags & (CHFL_CHANOP|CHFL_VOICE|CHFL_CHANOWNER|CHFL_HALFOP|CHFL_CHANPROT)) &&
			    chptr->mode.floodprot && do_chanflood(chptr->mode.floodprot, FLD_NICK) && MyClient(sptr))
			{
				do_chanflood_action(chptr, FLD_NICK, "nick");
			}
		}	
	}
#endif
	if (newusr && !MyClient(sptr) && IsPerson(sptr))
	{
		RunHook(HOOKTYPE_REMOTE_CONNECT, sptr);
	}

	return 0;
}
Пример #26
0
/*
 *  exit_client 
 * This is old "m_bye". Name  changed, because this is not a
 * protocol function, but a general server utility function.
 * 
 *      This function exits a client of *any* type (user, server, etc) 
 * from this server. Also, this generates all necessary prototol 
 * messages that this exit may cause. 
 * 
 *   1) If the client is a local client, then this implicitly exits
 * all other clients depending on this connection (e.g. remote
 * clients having 'from'-field that points to this. 
 * 
 *   2) If the client is a remote client, then only this is exited. 
 * 
 * For convenience, this function returns a suitable value for 
 * m_function return value: 
 * 
 *      FLUSH_BUFFER    if (cptr == sptr) 
 *      0 if (cptr != sptr)
 */
int 
exit_client(aClient *cptr, aClient *sptr, aClient *from, char *comment)
{
#ifdef  FNAME_USERLOG
    time_t on_for;
#endif
    
    if (MyConnect(sptr)) 
    {
        call_hooks(CHOOK_SIGNOFF, sptr);

        if (IsUnknown(sptr))
            Count.unknown--;
        if (IsAnOper(sptr)) 
            remove_from_list(&oper_list, sptr, NULL);
        if (sptr->flags & FLAGS_HAVERECVQ)
        {
            /* mark invalid, will be deleted in do_recvqs() */
            DLink *lp = find_dlink(recvq_clients, sptr);
            if (lp)
                lp->flags = -1;
        }
        if (IsClient(sptr))
            Count.local--;
        if (IsNegoServer(sptr))
            sendto_realops("Lost server %s during negotiation: %s", 
                           sptr->name, comment);
        
        if (IsServer(sptr)) 
        {
            Count.myserver--;
            if (IsULine(sptr))
                Count.myulined--;
            remove_from_list(&server_list, sptr, NULL);
            if (server_list == NULL) 
                server_was_split = YES;
        }
        sptr->flags |= FLAGS_CLOSING;
        if (IsPerson(sptr)) 
        {
            Link *lp, *next;
            LOpts *lopt = sptr->user->lopt;
            /* poof goes their watchlist! */
            hash_del_watch_list(sptr);
            /* if they have listopts, axe those, too */
            if(lopt != NULL) 
            {
                remove_from_list(&listing_clients, sptr, NULL);
                for (lp = lopt->yeslist; lp; lp = next) 
                {
                    next = lp->next;
                    MyFree(lp->value.cp);
                    free_link(lp);
                }
                for (lp = lopt->nolist; lp; lp = next) 
                {
                    next = lp->next;
                    MyFree(lp->value.cp);
                    free_link(lp);
                }
                                
                MyFree(sptr->user->lopt);
                sptr->user->lopt = NULL;
            }
            sendto_realops_lev(CCONN_LEV,
                               "Client exiting: %s (%s@%s) [%s] [%s]",
                               sptr->name, sptr->user->username,
                               sptr->user->host,
                               (sptr->flags & FLAGS_NORMALEX) ?
                               "Client Quit" : comment,
                               sptr->hostip);
        }
#ifdef FNAME_USERLOG
        on_for = timeofday - sptr->firsttime;
#endif
#if defined(USE_SYSLOG) && defined(SYSLOG_USERS)
        if (IsPerson(sptr))
            syslog(LOG_NOTICE, "%s (%3d:%02d:%02d): %s!%s@%s %d/%d\n",
                   myctime(sptr->firsttime),
                   on_for / 3600, (on_for % 3600) / 60,
                   on_for % 60, sptr->name,
                   sptr->user->username, sptr->user->host,
                   sptr->sendK, sptr->receiveK);
#endif
#if defined(FNAME_USERLOG)
        {
            char        linebuf[300];
            static int  logfile = -1;
            static long lasttime;
            
            /*
             * This conditional makes the logfile active only after it's
             * been created - thus logging can be turned off by removing
             * the file.
             * 
             * stop NFS hangs...most systems should be able to open a file in
             * 3 seconds. -avalon (curtesy of wumpus)
             * 
             * Keep the logfile open, syncing it every 10 seconds -Taner
             */
            if (IsPerson(sptr)) 
            {
                if (logfile == -1) 
                {
                    alarm(3);
                    logfile = open(FNAME_USERLOG, O_WRONLY | O_APPEND);
                    alarm(0);
                }
                ircsprintf(linebuf, "%s (%3d:%02d:%02d): %s!%s@%s %d/%d\n",
                           myctime(sptr->firsttime), on_for / 3600,
                           (on_for % 3600) / 60, on_for % 60,
                           sptr->name, sptr->user->username,
                           sptr->user->host, sptr->sendK, sptr->receiveK);
                alarm(3);
                write(logfile, linebuf, strlen(linebuf));
                alarm(0);
                /* Resync the file evey 10 seconds*/
                if (timeofday - lasttime > 10) 
                {
                    alarm(3);
                    close(logfile);
                    alarm(0);
                    logfile = -1;
                    lasttime = timeofday;
                }
            }
        }
#endif
        if (sptr->fd >= 0) 
        {
            if (cptr != NULL && sptr != cptr)
              sendto_one(&me, sptr, "ERROR :Closing Link: %s %s (%s)",
                           IsPerson(sptr) ? sptr->sockhost : "0.0.0.0", 
                           sptr->name, comment);
            else
              sendto_one(&me, sptr, "ERROR :Closing Link: %s (%s)",
                           IsPerson(sptr) ? sptr->sockhost : "0.0.0.0", 
                           comment);
        }
        /*
         * * Currently only server connections can have * depending
         * remote clients here, but it does no * harm to check for all
         * local clients. In * future some other clients than servers
         * might * have remotes too... *
         * 
         * Close the Client connection first and mark it * so that no
         * messages are attempted to send to it. *, The following *must*
         * make MyConnect(sptr) == FALSE!). * It also makes sptr->from ==
         * NULL, thus it's unnecessary * to test whether "sptr != acptr"
         * in the following loops.
         */
        if (IsServer(sptr)) 
        {
            sendto_ops("%s was connected for %lu seconds.  %lu/%lu "
                       "sendK/recvK.", sptr->name,
		       (long)(timeofday - sptr->firsttime),
                       sptr->sendK, sptr->receiveK);
#ifdef USE_SYSLOG
            syslog(LOG_NOTICE, "%s was connected for %lu seconds.  %lu/%lu "
                   "sendK/recvK.", sptr->name, 
                        (u_long) timeofday - sptr->firsttime,
                   sptr->sendK, sptr->receiveK);
#endif
            close_connection(sptr);
            sptr->sockerr = 0;
            sptr->flags |= FLAGS_DEADSOCKET;
        }
        else
        {
            close_connection(sptr);
            sptr->sockerr = 0;
            sptr->flags |= FLAGS_DEADSOCKET;
        }
                
    }
    exit_one_client(cptr, sptr, from, comment);
    return cptr == sptr ? FLUSH_BUFFER : 0;
}
Пример #27
0
/*
 * do_svssno() 
 * parv[0] - sender
 * parv[1] - username to change snomask for
 * parv[2] - snomasks to change
 * show_change determines whether to show the change to the user
 */
int  do_svssno(aClient *cptr, aClient *sptr, int parc, char *parv[], int show_change)
{
	char *p;
	aClient *acptr;
	int what = MODE_ADD, i;

	if (!IsULine(sptr))
		return 0;

	if (parc < 2)
		return 0;

	if (parv[1][0] == '#') 
		return 0;

	if (!(acptr = find_person(parv[1], NULL)))
		return 0;

	if (hunt_server_token(cptr, sptr,
	                      show_change ? MSG_SVS2SNO : MSG_SVSSNO,
	                      show_change ? TOK_SVS2SNO : TOK_SVSSNO,
	                      "%s %s", 1, parc, parv) != HUNTED_ISME)
	{
		return 0;
	}

	if (MyClient(acptr))
	{
		if (parc == 2)
			acptr->user->snomask = 0;
		else
		{
			for (p = parv[2]; p && *p; p++) {
				switch (*p) {
					case '+':
						what = MODE_ADD;
						break;
					case '-':
						what = MODE_DEL;
						break;
					default:
				 	 for (i = 0; i <= Snomask_highest; i++)
				 	 {
				 	 	if (!Snomask_Table[i].flag)
				 	 		continue;
		 	 			if (*p == Snomask_Table[i].flag)
				 	 	{
				 	 		if (what == MODE_ADD)
					 	 		acptr->user->snomask |= Snomask_Table[i].mode;
			 			 	else
			 	 				acptr->user->snomask &= ~Snomask_Table[i].mode;
				 	 	}
				 	 }				
				}
			}
		}
	}

	if (show_change)
		sendto_one(acptr, rpl_str(RPL_SNOMASK), me.name, acptr->name, get_sno_str(acptr));

	return 0;
}
Пример #28
0
static void 
serv_info(aClient *cptr, char *name)
{
    static char Lformat[] = ":%s %d %s %s %u %u %u %u %u :%u %u %s";
    long        sendK, receiveK, uptime;
    aClient    *acptr;
    DLink      *lp;
    int         i = 0;

    sendK = receiveK = 0;

    for (lp = server_list; lp; lp = lp->next)
    {
        acptr = lp->value.cptr;

#ifdef HIDEULINEDSERVS
        if (IsULine(acptr) && !IsAnOper(cptr))
            continue;
#endif
        sendK += acptr->sendK;
        receiveK += acptr->receiveK;
        sendto_one(cptr, Lformat, me.name, RPL_STATSLINKINFO,
                    name, ( (MyClient(cptr) && IsAdmin(cptr))
                            ? get_client_name(acptr, FALSE)
                            : get_client_name(acptr, HIDEME) ),
                    (int) SBufLength(&acptr->sendQ),
                    (int) acptr->sendM, (int) acptr->sendK,
                    (int) acptr->receiveM, (int) acptr->receiveK,
                    timeofday - acptr->firsttime, timeofday - acptr->since,
                    IsServer(acptr) ? (DoesTS(acptr) ? "TS" : "NoTS") : "-");


        if(RC4EncLink(acptr))
            sendto_one(cptr, ":%s %d %s : - RC4 encrypted", me.name, 
                        RPL_STATSDEBUG, name);

        if(ZipOut(acptr))
        {
            unsigned long ib, ob;
            double rat;

            zip_out_get_stats(acptr->serv->zip_out, &ib, &ob, &rat);
            if(ib)
            {
                sendto_one(cptr, ":%s %d %s : - [O] Zip inbytes %lu, "
                            "outbytes %lu (%3.2f%%)", me.name, RPL_STATSDEBUG,
                             name, ib, ob, rat);
            }
        }

        if(ZipIn(acptr))
        {
            unsigned long ib, ob;
            double rat;

            zip_in_get_stats(acptr->serv->zip_in, &ib, &ob, &rat);
            if(ob)
            {
                sendto_one(cptr, ":%s %d %s : - [I] Zip inbytes %lu, "
                            "outbytes %lu (%3.2f%%)", me.name, RPL_STATSDEBUG,
                             name, ib, ob, rat);
            }
        }
        i++;
    }
    sendto_one(cptr, ":%s %d %s :%u total server%s",
           me.name, RPL_STATSDEBUG, name, i, (i == 1) ? "" : "s");
    sendto_one(cptr, ":%s %d %s :Sent total : %7.2f %s",
           me.name, RPL_STATSDEBUG, name, _GMKv(sendK), _GMKs(sendK));
    sendto_one(cptr, ":%s %d %s :Recv total : %7.2f %s",
           me.name, RPL_STATSDEBUG, name, _GMKv(receiveK),
           _GMKs(receiveK));

    uptime = (timeofday - me.since);
    sendto_one(cptr, ":%s %d %s :Server send: %7.2f %s (%4.1f K/s total,"
                     " %4.1f K/s current)", me.name, RPL_STATSDEBUG, name,
                     _GMKv(me.sendK), _GMKs(me.sendK), 
                    (float) ((float) me.sendK / (float) uptime), curSendK);
    sendto_one(cptr, ":%s %d %s :Server recv: %7.2f %s (%4.1f K/s total,"
                     " %4.1f K/s current)", me.name, RPL_STATSDEBUG, name, 
                    _GMKv(me.receiveK), _GMKs(me.receiveK),
                    (float) ((float) me.receiveK / (float) uptime), curRecvK);
}
Пример #29
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
}
Пример #30
0
/*
 * m_nick 
 * parv[0] = sender prefix 
 * parv[1] = nickname 
 * parv[2] = hopcount when new user; TS when nick change 
 * parv[3] = TS
 * ---- new user only below ---- 
 * parv[4] = umode 
 * parv[5] = username 
 * parv[6] = hostname 
 * parv[7] = server 
 * parv[8] = serviceid
 * parv[9] = IP
 * parv[10] = ircname
 * -- endif
 */
int m_nick(aClient *cptr, aClient *sptr, int parc, char *parv[])
{
    struct simBan *ban;
    aClient    *acptr, *uplink;
    Link       *lp, *lp2;
    char        nick[NICKLEN + 2];
    ts_val      newts = 0;
    int         sameuser = 0, samenick = 0;
  
    if (parc < 2)
    {
	sendto_one(sptr, err_str(ERR_NONICKNAMEGIVEN),
		   me.name, parv[0]);
	return 0;
    }
  
    if (!IsServer(sptr) && IsServer(cptr) && parc > 2)
	newts = atol(parv[2]);
    else if (IsServer(sptr) && parc > 3)
	newts = atol(parv[3]);
    else
	parc = 2;
    /*
     * parc == 2 on a normal client sign on (local) and a normal client 
     * nick change 
     * parc == 4 on a normal server-to-server client nick change
     * parc == 11 on a normal TS style server-to-server NICK introduction
     */
    if ((IsServer(sptr) || (parc > 4)) && (parc < 11))
    {
	/*
	 * We got the wrong number of params. Someone is trying to trick
	 * us. Kill it. -ThemBones As discussed with ThemBones, not much
	 * point to this code now sending a whack of global kills would
	 * also be more annoying then its worth, just note the problem,
	 * and continue -Dianora
	 */
	sendto_realops("IGNORING BAD NICK: %s[%s@%s] on %s (from %s)", parv[1],
		       (parc >= 6) ? parv[5] : "-",
		       (parc >= 7) ? parv[6] : "-",
		       (parc >= 8) ? parv[7] : "-", parv[0]);
	return 0;
     
    }
   
    strncpyzt(nick, parv[1], NICKLEN + 1);
    /*
     * if do_nick_name() returns a null name OR if the server sent a
     * nick name and do_nick_name() changed it in some way (due to rules
     * of nick creation) then reject it. If from a server and we reject
     * it, and KILL it. -avalon 4/4/92
     */
    if (do_nick_name(nick) == 0 || (IsServer(cptr) && strcmp(nick, parv[1])))
    {
	sendto_one(sptr, err_str(ERR_ERRONEUSNICKNAME),
		   me.name, parv[0], parv[1], "Erroneous Nickname");
	
	if (IsServer(cptr))
	{
	    ircstp->is_kill++;
        sendto_realops_lev(DEBUG_LEV, "Bad Nick: %s From: %s Via: %s",
			       parv[1], parv[0],
			       get_client_name(cptr, HIDEME));
	    sendto_one(cptr, ":%s KILL %s :%s (Bad Nick)",
		       me.name, parv[1], me.name);
	    if (sptr != cptr) { /* bad nick change */     
		sendto_serv_butone(cptr, ":%s KILL %s :%s (Bad Nick)", me.name,
				   parv[0], me.name);
		sptr->flags |= FLAGS_KILLED;
		return exit_client(cptr, sptr, &me, "BadNick");
	    }
	}
	return 0;
    }
    /*
     * Check against nick name collisions.
     * 
     * Put this 'if' here so that the nesting goes nicely on the screen
     * :) We check against server name list before determining if the
     * nickname is present in the nicklist (due to the way the below
     * for loop is constructed). -avalon
     */
    do
    {
	if ((acptr = find_server(nick, NULL)))
	    if (MyConnect(sptr))
	    {
		sendto_one(sptr, err_str(ERR_NICKNAMEINUSE), me.name,
			   BadPtr(parv[0]) ? "*" : parv[0], nick);
		return 0;
	    }
	
	/* 
	 * acptr already has result from find_server
	 * Well. unless we have a capricious server on the net, a nick can
	 * never be the same as a server name - Dianora
	 * That's not the only case; maybe someone broke do_nick_name
	 * or changed it so they could use "." in nicks on their network 
	 * - sedition
	 */
     
	if (acptr)
	{
	    /*
	     * We have a nickname trying to use the same name as a
	     * server. Send out a nick collision KILL to remove the
	     * nickname. As long as only a KILL is sent out, there is no
	     * danger of the server being disconnected.  Ultimate way to
	     * jupiter a nick ? >;-). -avalon
	     */
	    sendto_realops_lev(SKILL_LEV, "Nick collision on %s", sptr->name);
	    ircstp->is_kill++;
	    sendto_one(cptr, ":%s KILL %s :%s (Nick Collision)", me.name, 
		       sptr->name, me.name);
	    sptr->flags |= FLAGS_KILLED;
	    return exit_client(cptr, sptr, &me, "Nick/Server collision");
	}
	
	if (!(acptr = find_client(nick, NULL)))
	    break;
     
	/*
	 * If acptr == sptr, then we have a client doing a nick change
	 * between *equivalent* nicknames as far as server is concerned
	 * (user is changing the case of his/her nickname or somesuch)
	 */
	if (acptr == sptr)
	{
	    if (strcmp(acptr->name, nick) == 0) 
		return 0;
	    else
		break;
	} /* If user is changing nick to itself no point in propogating */
     
	/*
	 * Note: From this point forward it can be assumed that acptr !=
	 * sptr (point to different client structures).
	 *
	 * If the older one is "non-person", the new entry is just 
	 * allowed to overwrite it. Just silently drop non-person, and
	 * proceed with the nick. This should take care of the "dormant
	 * nick" way of generating collisions...
	 */
	if (IsUnknown(acptr))
	{
	    if (MyConnect(acptr))
	    {
		exit_client(NULL, acptr, &me, "Overridden");
		break;
	    }
	    else if (!(acptr->user))
	    {
		sendto_realops_lev(SKILL_LEV, "Nick Collision on %s", parv[1]);
		sendto_serv_butone(NULL, ":%s KILL %s :%s (Nick Collision)",
				   me.name, acptr->name, me.name);
		acptr->flags |= FLAGS_KILLED;
		/* Having no USER struct should be ok... */
		return exit_client(cptr, acptr, &me,
				   "Got TS NICK before Non-TS USER");
	    }
	}
     
	if (!IsServer(cptr))
	{
	    /*
	     * NICK is coming from local client connection. Just send
	     * error reply and ignore the command.
	     * parv[0] is empty on connecting clients
	     */
	    sendto_one(sptr, err_str(ERR_NICKNAMEINUSE),
		       me.name, BadPtr(parv[0]) ? "*" : parv[0], nick);
	    return 0;
	}
	/*
	 * NICK was coming from a server connection. Means that the same
	 * nick is registered for different users by different server.
	 * This is either a race condition (two users coming online about
	 * same time, or net reconnecting) or just two net fragments
	 * becoming joined and having same nicks in use. We cannot have
	 * TWO users with same nick--purge this NICK from the system with
	 * a KILL... >;)
	 *
	 * Changed to something reasonable like IsServer(sptr) (true if
	 * "NICK new", false if ":old NICK new") -orabidoo
	 */
     
	if (IsServer(sptr))
	{
	    /*
	     * A new NICK being introduced by a neighbouring server (e.g.
	     * message type "NICK new" received)
	     */
	    if (!newts || !acptr->tsinfo || (newts == acptr->tsinfo))
	    {
		sendto_realops_lev(SKILL_LEV, "Nick collision on %s", parv[1]);
		ircstp->is_kill++;
		sendto_one(acptr, err_str(ERR_NICKCOLLISION),
			   me.name, acptr->name, acptr->name);
		sendto_serv_butone(NULL, ":%s KILL %s :%s (Nick Collision)",
				   me.name, acptr->name, me.name);
		acptr->flags |= FLAGS_KILLED;
		return exit_client(cptr, acptr, &me, "Nick collision");
	    }
	    else
	    {
		/* XXX This looks messed up to me XXX - Raist */
		sameuser = (acptr->user) &&
		    mycmp(acptr->user->username, parv[5]) == 0 &&
		    mycmp(acptr->user->host, parv[6]) == 0;
		if ((sameuser && newts < acptr->tsinfo) || 
		    (!sameuser && newts > acptr->tsinfo))
		{
		    return 0;
		}
		else
		{
		    sendto_realops_lev(SKILL_LEV, "Nick collision on %s",parv[1]);
		    ircstp->is_kill++;
		    sendto_one(acptr, err_str(ERR_NICKCOLLISION),
			       me.name, acptr->name, acptr->name);
		    sendto_serv_butone(sptr, ":%s KILL %s :%s (Nick Collision)",
				       me.name, acptr->name, me.name);
		    acptr->flags |= FLAGS_KILLED;
		    (void) exit_client(cptr, acptr, &me, "Nick collision");
		    break;
		}
	    }
	}
	/*
	 * * A NICK change has collided (e.g. message type * ":old NICK
	 * new". This requires more complex cleanout. * Both clients must be
	 * purged from this server, the "new" * must be killed from the
	 * incoming connection, and "old" must * be purged from all outgoing
	 * connections.
	 */
	if (!newts || !acptr->tsinfo || (newts == acptr->tsinfo) ||
	    !sptr->user)
	{
	    sendto_realops_lev(SKILL_LEV, "Nick change collision: %s", parv[1]);
	    ircstp->is_kill++;
	    sendto_one(acptr, err_str(ERR_NICKCOLLISION),
		       me.name, acptr->name, acptr->name);
	    sendto_serv_butone(NULL, ":%s KILL %s :%s (Nick Collision)",me.name,
			       sptr->name, me.name);
	    ircstp->is_kill++;
	    sendto_serv_butone(NULL, ":%s KILL %s :%s (Nick Collision)",me.name,
			       acptr->name, me.name);
	    acptr->flags |= FLAGS_KILLED;
	    (void) exit_client(NULL, acptr, &me, "Nick collision(new)");
	    sptr->flags |= FLAGS_KILLED;
	    return exit_client(cptr, sptr, &me, "Nick collision(old)");
	}
	else
	{
	    /* XXX This looks messed up XXX */
	    sameuser = mycmp(acptr->user->username, sptr->user->username) == 0
		&& mycmp(acptr->user->host, sptr->user->host) == 0;
	    if ((sameuser && newts < acptr->tsinfo) ||
		(!sameuser && newts > acptr->tsinfo)) {
		if (sameuser)
		    sendto_realops_lev(SKILL_LEV, 
				   "Nick change collision from %s to %s",
				   sptr->name, acptr->name);
		ircstp->is_kill++;
		sendto_serv_butone(cptr, ":%s KILL %s :%s (Nick Collision)", me.name,
				   sptr->name, me.name);
		sptr->flags |= FLAGS_KILLED;
		if (sameuser)
		    return exit_client(cptr, sptr, &me, "Nick collision(old)");
		else
		    return exit_client(cptr, sptr, &me, "Nick collision(new)");
	    } 
	    else
	    {
		sendto_realops_lev(SKILL_LEV, "Nick collision on %s", acptr->name);
		
		ircstp->is_kill++;
		sendto_one(acptr, err_str(ERR_NICKCOLLISION),
			   me.name, acptr->name, acptr->name);
		sendto_serv_butone(sptr, ":%s KILL %s :%s (Nick Collision)",me.name,
				   acptr->name, me.name);
		acptr->flags |= FLAGS_KILLED;
		(void) exit_client(cptr, acptr, &me, "Nick collision");
	    }
	}
    } while (0);
    
    if (IsServer(sptr))
    {
	uplink = find_server(parv[7], NULL);
	if(!uplink)
	{
	    /* if we can't find the server this nick is on, 
	     * complain loudly and ignore it. - lucas */
	    sendto_realops("Remote nick %s on UNKNOWN server %s",
			   nick, parv[7]);
	    return 0;
	}
	sptr = make_client(cptr, uplink);
	
	/* If this is on a U: lined server, it's a U: lined client. */
	if(IsULine(uplink))
	    sptr->flags|=FLAGS_ULINE;
     
	add_client_to_list(sptr);
	if (parc > 2)
	    sptr->hopcount = atoi(parv[2]);
	if (newts)
	{
	    sptr->tsinfo = newts;
	}
	else
	{
	    newts = sptr->tsinfo = (ts_val) timeofday;
	    ts_warn("Remote nick %s introduced without a TS", nick);
	}
	/* copy the nick in place */
	(void) strcpy(sptr->name, nick);
	(void) add_to_client_hash_table(nick, sptr);
	if (parc >= 10)
	{
	    int *s, flag;
	    char *m;
       
	    /* parse the usermodes -orabidoo */
	    m = &parv[4][1];
	    while (*m)
	    {
		for (s = user_modes; (flag = *s); s += 2)
		    if (*m == *(s + 1))
		    {
			if ((flag == UMODE_o) || (flag == UMODE_O))
			    Count.oper++;
			sptr->umode |= flag & SEND_UMODES;
			break;
		    }
		m++;
	    }
	    if (parc==10)
	    {
		return do_user(nick, cptr, sptr, parv[5], parv[6],
			       parv[7], strtoul(parv[8], NULL, 0),
			       "0.0.0.0", parv[9]);
	    } else if (parc==11)
	    {
		return do_user(nick, cptr, sptr, parv[5], parv[6], parv[7],
			       strtoul(parv[8], NULL, 0),
			       parv[9], parv[10]);
	    }
	}
    }
    else if (sptr->name[0])
    {
#ifdef DONT_CHECK_QLINE_REMOTE
	if (MyConnect(sptr))
	{
#endif
	    if ((ban = check_mask_simbanned(nick, SBAN_NICK)))
	    {
#ifndef DONT_CHECK_QLINE_REMOTE
		if (!MyConnect(sptr))
		    sendto_realops("Restricted nick %s from %s on %s", nick,
				   (*sptr->name != 0 && !IsServer(sptr)) ?
				   sptr->name : "<unregistered>",
				   (sptr->user == NULL) ? ((IsServer(sptr)) ?
							   parv[6] : me.name) :
				   sptr->user->server);
#endif
		
		if (MyConnect(sptr) && (!IsServer(cptr)) && (!IsOper(cptr))
		    && (!IsULine(sptr)))
		{
		    sendto_one(sptr, err_str(ERR_ERRONEUSNICKNAME), me.name,
			       BadPtr(parv[0]) ? "*" : parv[0], nick,
			       BadPtr(ban->reason) ? "Erroneous Nickname" :
			       ban->reason);
                    if (call_hooks(CHOOK_FORBID, cptr, nick, ban) != FLUSH_BUFFER)
		        sendto_realops_lev(REJ_LEV,
			    	           "Forbidding restricted nick %s from %s",
				           nick, get_client_name(cptr, FALSE));
		    return 0;
		}
	    }
#ifdef DONT_CHECK_QLINE_REMOTE
	}
#endif
	if (MyConnect(sptr))
	{
	    if (IsRegisteredUser(sptr))
	    {
	 
		/* before we change their nick, make sure they're not banned
		 * on any channels, and!! make sure they're not changing to
		 * a banned nick -sed */
		/* a little cleaner - lucas */
	 
		for (lp = sptr->user->channel; lp; lp = lp->next)
		{
		    if (can_send(sptr, lp->value.chptr, NULL))
		    { 
			sendto_one(sptr, err_str(ERR_BANNICKCHANGE), me.name,
				   sptr->name, lp->value.chptr->chname);
			return 0;
		    }
		    if (nick_is_banned(lp->value.chptr, nick, sptr) != NULL)
		    {
			sendto_one(sptr, err_str(ERR_BANONCHAN), me.name,
				   sptr->name, nick, lp->value.chptr->chname);
			return 0;
		    }
		}
#ifdef ANTI_NICK_FLOOD
		if ((sptr->last_nick_change + MAX_NICK_TIME) < NOW)
		    sptr->number_of_nick_changes = 0;
		sptr->last_nick_change = NOW;
		sptr->number_of_nick_changes++;
	 
		if (sptr->number_of_nick_changes > MAX_NICK_CHANGES && 
		    !IsAnOper(sptr))
		{
		    sendto_one(sptr,
			       ":%s NOTICE %s :*** Notice -- Too many nick "
			       "changes. Wait %d seconds before trying again.",
			       me.name, sptr->name, MAX_NICK_TIME);
		    return 0;
		}
#endif
		/* If it changed nicks, -r it */
		if ((sptr->umode & UMODE_r) && (mycmp(parv[0], nick) != 0))
		{
		    unsigned int oldumode;
		    char mbuf[BUFSIZE];

		    oldumode = sptr->umode;
		    sptr->umode &= ~UMODE_r;
		    send_umode(sptr, sptr, oldumode, ALL_UMODES, mbuf);
		}

                /* LOCAL NICKHANGE */
                /*
                 * Client just changing his/her nick. If he/she is on a
                 * channel, send note of change to all clients on that channel.
                 * Propagate notice to other servers.
                 */
                /* if the nickname is different, set the TS */
                if (mycmp(parv[0], nick))
                {
                  sptr->tsinfo = newts ? newts : (ts_val) timeofday;
                }

		sendto_common_channels(sptr, ":%s NICK :%s", parv[0], 
				       nick);
		if (sptr->user)
		{
		    add_history(sptr, 1);
			
		    sendto_serv_butone(cptr, ":%s NICK %s :%ld",
				       parv[0], nick, sptr->tsinfo);
		}
	    }
	}
	else
	{
            /* REMOTE NICKCHANGE */
            /*
             * Client just changing his/her nick. If he/she is on a
             * channel, send note of change to all clients on that channel.
             * Propagate notice to other servers.
             */
            /* if the nickname is different, set the TS */
            if (mycmp(parv[0], nick))
            {
              sptr->tsinfo = newts ? newts : (ts_val) timeofday;
            }

	    sendto_common_channels(sptr, ":%s NICK :%s", parv[0], nick);
	    if (sptr->user)
	    {
		add_history(sptr, 1);
		
		sendto_serv_butone(cptr, ":%s NICK %s :%ld",
				   parv[0], nick, sptr->tsinfo);
	    }

	    /* If it changed nicks, -r it */
	    if (mycmp(parv[0], nick))
		sptr->umode &= ~UMODE_r;

	    /*
	     * Flush the banserial for the channels the user is in, since this
	     * could be a SVSNICK induced nick change, which overrides any ban
	     * checking on the originating server.
	     */
	    flush_user_banserial(sptr);
	}
        /* Remove dccallow entries for users who don't share common channel(s) unless they only change their nick capitalization -Kobi_S */
        if(sptr->user && mycmp(parv[0], nick))
        {
            for(lp = sptr->user->dccallow; lp; lp = lp2)
            {
                lp2 = lp->next;
                if(lp->flags == DCC_LINK_ME)
                    continue;
                if(!find_shared_chan(sptr, lp->value.cptr))
                {
                    sendto_one(lp->value.cptr, ":%s %d %s :%s has been removed from "
                               "your DCC allow list for signing off",
                               me.name, RPL_DCCINFO, lp->value.cptr->name, parv[0]);
                    del_dccallow(lp->value.cptr, sptr, 1);
                }
            }
        }
    } 
    else
    {
	/* Client setting NICK the first time */
	if (MyConnect(sptr))
	{
	    if ((ban = check_mask_simbanned(nick, SBAN_NICK)))
	    {
		if (MyConnect(sptr) && (!IsServer(cptr)) && (!IsOper(cptr))
		    && (!IsULine(sptr)))
		{
		    sendto_one(sptr, err_str(ERR_ERRONEUSNICKNAME), me.name,
			       BadPtr(parv[0]) ? "*" : parv[0], nick,
			       BadPtr(ban->reason) ? "Erroneous Nickname" :
			       ban->reason);
                    if (call_hooks(CHOOK_FORBID, cptr, nick, ban) != FLUSH_BUFFER)
		        sendto_realops_lev(REJ_LEV,
				           "Forbidding restricted nick %s from %s", nick,
				           get_client_name(cptr, FALSE));
		    return 0;
		}
	    }
	}
	
	strcpy(sptr->name, nick);
	sptr->tsinfo = timeofday;
	if (sptr->user)
	{
	    /* USER already received, now we have NICK */
       
	    if (register_user(cptr, sptr, nick, sptr->user->username, NULL)
		== FLUSH_BUFFER)
		return FLUSH_BUFFER;
	}
    }

    /* Finally set new nick name. */
    if (sptr->name[0])
    {
        del_from_client_hash_table(sptr->name, sptr);
        samenick = mycmp(sptr->name, nick) ? 0 : 1;
        if (IsPerson(sptr))
        {
            if (!samenick)
                hash_check_watch(sptr, RPL_LOGOFF);
#ifdef RWHO_PROBABILITY
            probability_change(sptr->name, nick);
#endif
        }
    }
    strcpy(sptr->name, nick);
    add_to_client_hash_table(nick, sptr);
    if (IsPerson(sptr) && !samenick)
	hash_check_watch(sptr, RPL_LOGON);
    return 0;
}