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 }