unrealircd

- supernets unrealircd source & configuration
git clone git://git.acid.vegas/unrealircd.git
Log | Files | Refs | Archive | README | LICENSE

kill.c (5053B)

      1 /*
      2  *   Unreal Internet Relay Chat Daemon, src/modules/kill.c
      3  *   (C) 2000-2001 Carsten V. Munk and the UnrealIRCd Team
      4  *   Moved to modules by Fish (Justin Hammond)
      5  *
      6  *   This program is free software; you can redistribute it and/or modify
      7  *   it under the terms of the GNU General Public License as published by
      8  *   the Free Software Foundation; either version 1, or (at your option)
      9  *   any later version.
     10  *
     11  *   This program is distributed in the hope that it will be useful,
     12  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
     13  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14  *   GNU General Public License for more details.
     15  *
     16  *   You should have received a copy of the GNU General Public License
     17  *   along with this program; if not, write to the Free Software
     18  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
     19  */
     20 
     21 #include "unrealircd.h"
     22 
     23 CMD_FUNC(cmd_kill);
     24 
     25 ModuleHeader MOD_HEADER
     26   = {
     27 	"kill",
     28 	"5.0",
     29 	"command /kill",
     30 	"UnrealIRCd Team",
     31 	"unrealircd-6",
     32     };
     33 
     34 MOD_INIT()
     35 {
     36 	CommandAdd(modinfo->handle, "KILL", cmd_kill, 2, CMD_USER|CMD_SERVER);
     37 	MARK_AS_OFFICIAL_MODULE(modinfo);
     38 	return MOD_SUCCESS;
     39 }
     40 
     41 MOD_LOAD()
     42 {
     43 	return MOD_SUCCESS;
     44 }
     45 
     46 MOD_UNLOAD()
     47 {
     48 	return MOD_SUCCESS;
     49 }
     50 
     51 
     52 /** The KILL command - this forcefully terminates a users' connection.
     53  * parv[1] = kill victim(s) - comma separated list
     54  * parv[2] = reason
     55  */
     56 CMD_FUNC(cmd_kill)
     57 {
     58 	char targetlist[BUFSIZE];
     59 	char reason[BUFSIZE];
     60 	char buf2[BUFSIZE];
     61 	char *str;
     62 	char *nick, *save = NULL;
     63 	Client *target;
     64 	Hook *h;
     65 	int ntargets = 0;
     66 	int maxtargets = max_targets_for_command("KILL");
     67 
     68 	if ((parc < 3) || BadPtr(parv[2]))
     69 	{
     70 		sendnumeric(client, ERR_NEEDMOREPARAMS, "KILL");
     71 		return;
     72 	}
     73 
     74 	if (!IsServer(client->direction) && !ValidatePermissionsForPath("kill:global",client,NULL,NULL,NULL) && !ValidatePermissionsForPath("kill:local",client,NULL,NULL,NULL))
     75 	{
     76 		sendnumeric(client, ERR_NOPRIVILEGES);
     77 		return;
     78 	}
     79 
     80 	if (MyUser(client))
     81 		strlcpy(targetlist, canonize(parv[1]), sizeof(targetlist));
     82 	else
     83 		strlcpy(targetlist, parv[1], sizeof(targetlist));
     84 
     85 	strlncpy(reason, parv[2], sizeof(reason), iConf.quit_length);
     86 
     87 	for (nick = strtoken(&save, targetlist, ","); nick; nick = strtoken(&save, NULL, ","))
     88 	{
     89 		MessageTag *mtags = NULL;
     90 
     91 		if (MyUser(client) && (++ntargets > maxtargets))
     92 		{
     93 			sendnumeric(client, ERR_TOOMANYTARGETS, nick, maxtargets, "KILL");
     94 			break;
     95 		}
     96 
     97 		target = find_user(nick, NULL);
     98 
     99 		/* If a local user issued the /KILL then we will "chase" the user.
    100 		 * In other words: we'll check the history for recently changed nicks.
    101 		 * We don't do this for remote KILL requests as we have UID for that.
    102 		 */
    103 		if (!target && MyUser(client))
    104 		{
    105 			target = get_history(nick, KILLCHASETIMELIMIT);
    106 			if (target)
    107 				sendnotice(client, "*** KILL changed from %s to %s", nick, target->name);
    108 		}
    109 
    110 		if (!target)
    111 		{
    112 			sendnumeric(client, ERR_NOSUCHNICK, nick);
    113 			continue;
    114 		}
    115 
    116 		if ((!MyConnect(target) && MyUser(client) && !ValidatePermissionsForPath("kill:global",client,target,NULL,NULL))
    117 		    || (MyConnect(target) && MyUser(client)
    118 		    && !ValidatePermissionsForPath("kill:local",client,target,NULL,NULL)))
    119 		{
    120 			sendnumeric(client, ERR_NOPRIVILEGES);
    121 			continue;
    122 		}
    123 
    124 		/* Hooks can plug-in here to reject a kill */
    125 		if (MyUser(client))
    126 		{
    127 			int ret = EX_ALLOW;
    128 			for (h = Hooks[HOOKTYPE_PRE_KILL]; h; h = h->next)
    129 			{
    130 				/* note: parameters are: client, victim, reason. reason can be NULL !! */
    131 				ret = (*(h->func.intfunc))(client, target, reason);
    132 				if (ret != EX_ALLOW)
    133 					break;
    134 			}
    135 			if ((ret == EX_DENY) || (ret == EX_ALWAYS_DENY))
    136 				continue; /* reject kill for this particular user */
    137 		}
    138 
    139 		/* From here on, the kill is probably going to be successful. */
    140 
    141 		unreal_log(ULOG_INFO, "kill", "KILL_COMMAND", client,
    142 		           "Client killed: $target.details [by: $client] ($reason)",
    143 		           log_data_client("target", target),
    144 		           log_data_string("reason", reason));
    145 
    146 		new_message(client, recv_mtags, &mtags);
    147 
    148 		/* Victim gets a little notification (s)he is about to die */
    149 		if (MyConnect(target))
    150 		{
    151 			sendto_prefix_one(target, client, NULL, ":%s KILL %s :%s",
    152 			    client->name, target->name, reason);
    153 		}
    154 
    155 		if (MyConnect(target) && MyConnect(client))
    156 		{
    157 			/* Local kill. This is handled as if it were a QUIT */
    158 		}
    159 		else
    160 		{
    161 			/* Kill from one server to another (we may be src, victim or something in-between) */
    162 
    163 			/* Broadcast it to other servers */
    164 			sendto_server(client, 0, 0, mtags, ":%s KILL %s :%s",
    165 			              client->id, target->id, reason);
    166 
    167 			/* Don't send a QUIT for this */
    168 			SetKilled(target);
    169 
    170 			ircsnprintf(buf2, sizeof(buf2), "Killed by %s (%s)", client->name, reason);
    171 		}
    172 
    173 		if (MyUser(client))
    174 			RunHook(HOOKTYPE_LOCAL_KILL, client, target, reason);
    175 
    176 		ircsnprintf(buf2, sizeof(buf2), "Killed by %s (%s)", client->name, reason);
    177 		exit_client(target, mtags, buf2);
    178 
    179 		free_message_tags(mtags);
    180 
    181 		if (IsDead(client))
    182 			return; /* stop processing if we killed ourselves */
    183 	}
    184 }