#include "module.h" #define AUTHOR "dengel + SGR" #define VERSION "1.07" /* ----------------------------------------------------------- * Name: cs_trapchan * Authors: dengel * SGR * Date: 28/01/2004 * ----------------------------------------------------------- * Functions: list_global_opers * Limitations: None known * Tested: Ultimate(2.8.x), Unreal(3.2), Viagra, Bahamut * ----------------------------------------------------------- * This version has been tested on Ultimate2.8.6, viagra * Unreal and Bahamut. * * This module allow services admins to create and activate * a 'trap channel', that will send a global oper notice or * KILL or AKILL any non-opers joining it. * * ----------------------------------------------------------- * * ChangeLog: * * 1: Dengel: * * - Original version created by dengel. * * 2: SGR: * * - Added 'Kill' and 'Globops' options, the (a)logging * system. Modded all referneces from JOINKILL to * TRAPCHAN. * * - Re-arranged and reconstructed checking 'if' * statments and moved the 1st non-null initialiser of * newchan to sort out a possible memory leak. * * - Added ModuleHELP for the TRAPCHAN command. * * - Added 'rejoin on kick' and added module conf * directives for configurable channel modes. * * - Added 'on load auto activate' system and checking for * if TRAP_CHAN is registered. * * - Removed unix-time info from alogs. * * - Added Multi-Channel support for up to 5 trap channels * * - Made join code able to parse JOIN strings with mutiple * channels in them, seperated by ,'s. * * - Added SJOIN support. Added Anope-1.7.x revision 340 * and later support. * * - Re-wrote join Code for Unreal. * * ----------------------------------------------------------- */ /* ---------------------------------------------------------------------- */ /* START OF CONFIGURATION BLOCK - please read the comments :) */ /* ---------------------------------------------------------------------- */ /* [REQUIRED] If you are using Anope-1.7.x or later, leave this alone. * Otherwise change it to '#undef ANOPE17x' (no quotes). * * THIS IS IMPORTANT * */ #define ANOPE17x /* Name of the trap channel [Mandatory] */ #define TRAP_CHAN "#AKill" /* Optional OTHER trap channels. */ #define TRAP_CHAN2 "#AKillX" //#define TRAP_CHAN3 "#AKill3" //#define TRAP_CHAN4 "#AKill4" //#define TRAP_CHAN5 "#AKill5" /* If the action used is AKILL for how long should it be set? * default == One day: 24*60*60 = 86400 [Mandatory] * Can use anope-time-format-spefiers. i.e. * it can be "1d4h" for 1day 4 hours etc.. */ #define TRAP_EXPIRY "86400" /* When the channel is active, what topic should it have? [Mandatory] */ #define TRAP_TOPIC "Spambot trap channel. \002Do not join!!!\002" /* This is the KILL [and AKILL] reason used when a user who joins the * TRAP_CHAN is removed from the network. */ #define TRAP_REASON "[Automatic KILL] You appear to be a SPAM bot; No SPAM bots are allowed on this network!" /* Setting MUST be 0, 1, 2, or 3 ONLY. [Mandatory] * * Set to 0 for NONE [Off] (Don't automatically activate) * Set to 1 for KILL (Automatically join channel and kill non-opers who join) [Recommended on small to medium networks] * Set to 2 for AKILL (Automatically join channel and Akill non-opers who join) * Set to 3 for GLOBOPS (Automatically join channel and send an global oper message when anyone joins it) */ #define DEFAULT_ACTION 1 /* Setting MUST be 0, 1 ONLY. [Mandatory] [Recommended on small to medium networks] * Set to 1 to log all kills, glopops and akills generated by this module to the logchan. * Set to 0 to disable this module from logging info to the logchannel. */ #define LOG_ALL 1 /* Set these to the modes the TRAP_CHAN should be set with. [Mandatory] * * Its recommended that these be left as they are, however, you IRCd may * support chan modes such as O, A, R, and other 'join restrictions' * which you may want revoked. Please keep to you IRCd's protocall given * MAXMODES setting. */ #define TRAP_CHAN_MODES1 "-psi" #define TRAP_CHAN_MODES2 "+nt" /* ---------------------------------------------------------------------- */ /* DO NOT EDIT BELOW THIS LINE UNLESS YOU KNOW WHAT YOU ARE DOING */ /* ---------------------------------------------------------------------- */ #define TRAP_CHAN_SYNTAX "Syntax: TRAP_CHAN [SETTINGS|ON|KILL|AKILL|GLOBOPS|OFF]" #ifdef ANOPE17x #ifdef wallops #undef wallops #endif #define wallops anope_cmd_global #endif int on_join_trapchan_check(char *, int , char **); int on_sjoin_trapchan_check(char *, int , char **); int myKickCheck(char *source, int , char **); void trapchan_takeaction(User *u, char *); int SGR_Module_Help_CHANSERV_TRAPCHAN_FULL(User *); void SGR_Module_Help_CHANSERV_TRAPCHAN(User *); void m_cs_activatetrapchans(char *, char *); void m_cs_activate_a_trapchan(char *); int m_cs_trapchan(User *); int is_a_trap_channel(char *); int cs_joinkillaction = 0; int AnopeInit(int argc, char **argv) { Command *c; Message *msg =NULL; c = createCommand("TRAPCHAN", m_cs_trapchan, is_services_admin, -1, -1, -1, -1, -1); moduleAddCommand(CHANSERV, c, MOD_UNIQUE); moduleAddHelp(c,SGR_Module_Help_CHANSERV_TRAPCHAN_FULL); moduleSetChanHelp(SGR_Module_Help_CHANSERV_TRAPCHAN); msg = createMessage("JOIN",on_join_trapchan_check); moduleAddMessage(msg,MOD_TAIL); msg = createMessage("SJOIN",on_sjoin_trapchan_check); moduleAddMessage(msg,MOD_TAIL); msg = createMessage("KICK",myKickCheck); moduleAddMessage(msg,MOD_TAIL); cs_joinkillaction = DEFAULT_ACTION; alog("[cs_trapchan] New command: /msg %s TRAPCHAN", s_ChanServ); alog("[cs_trapchan] For information see: /msg %s HELP TRAPCHAN", s_ChanServ); alog("[cs_trapchan] Yayness!(tm) - MODULE LOADED AND ACTIVE"); if (cs_joinkillaction) { m_cs_activatetrapchans(s_ChanServ, "DEFAULT"); } moduleAddAuthor(AUTHOR); moduleAddVersion(VERSION); return MOD_CONT; } int on_sjoin_trapchan_check(char *source, int ac, char **av) { User *u; Channel *c; if ((!cs_joinkillaction) || (!*source) || (ac < 1) || (!av[1])) { return MOD_CONT; } u = finduser(source); if (u && (ac > 0)) { if (is_a_trap_channel(av[1])) { trapchan_takeaction(u,av[1]); } } return MOD_CONT; } int on_join_trapchan_check(char *source, int ac, char **av) { char *s; char *t; User *u; if ((!cs_joinkillaction) || (!*source) || (ac < 1) || (!av[0])) { return MOD_CONT; } u = finduser(source); if (!u || is_oper(u)) { return MOD_CONT; } t = av[0]; while (*(s = t)) { t = s + strcspn(s, ","); if (*t) { *t++ = 0; } if (*s == '0') { continue; } if (is_a_trap_channel(s)) { trapchan_takeaction(u,s); } } return MOD_CONT; } int is_a_trap_channel(char *s) { if (!strchr(s,'#')) { return 0; } #ifdef TRAP_CHAN if (stricmp(s, TRAP_CHAN) == 0) { return 1; } #endif #ifdef TRAP_CHAN2 if (stricmp(s, TRAP_CHAN2) == 0) { return 1; } #endif #ifdef TRAP_CHAN3 if (stricmp(s, TRAP_CHAN3) == 0) { return 1; } #endif #ifdef TRAP_CHAN4 if (stricmp(s, TRAP_CHAN4) == 0) { return 1; } #endif #ifdef TRAP_CHAN5 if (stricmp(s, TRAP_CHAN5) == 0) { return 1; } #endif return 0; } void trapchan_takeaction(User *u, char *chan) { char mask[USERMAX + HOSTMAX + 2]; time_t expires; if ((cs_joinkillaction == 1) || (cs_joinkillaction == 3)) { if (cs_joinkillaction == 1) { if (LOG_ALL) { alog("[cs_trapchan]: KILLING: %s!%s@%s (joined trap chan: %s)", u->nick, u->username, u->host, chan); } kill_user(s_ChanServ, u->nick, TRAP_REASON); } else { alog("[cs_trapchan]: WARNING: %s!%s@%s (joined trap chan: %s)", u->nick, u->username, u->host, chan); wallops(s_ChanServ, "[TRAP-CHANNEL]: %s!%s@%s (joined trap chan: %s)", u->nick, u->username, u->host, chan); } } else if (cs_joinkillaction == 2) { expires = time(NULL) + dotime(TRAP_EXPIRY); strncpy(mask, "*@", 3); /* Use *@" for the akill's, */ strncat(mask, u->host, HOSTMAX); add_akill(NULL, mask, "ChanServ", expires, TRAP_REASON); if (LOG_ALL) { alog("[cs_trapchan]: AKILLING: %s!%s@%s (joined trap chan: %s)", u->nick, u->username, u->host, chan); } if (WallOSAkill) { wallops(s_ChanServ, "[TRAP-CHANNEL]: AKILLED: %s!%s@%s (joined trap chan:%s)", u->nick, u->username, u->host, chan); } check_akill(u->nick, u->username, u->host, NULL, NULL); } return; } int myKickCheck(char *source, int ac, char **av) { if ((!cs_joinkillaction) || (!*source) || (ac < 1) || (readonly) || (!av[0]) || (!av[1])) { return MOD_CONT; } if ((stricmp(av[1],s_ChanServ) !=0) || (stricmp(av[0], TRAP_CHAN) != 0)) { return MOD_CONT; } if (LOG_ALL) { alog("[cs_trapchan]: %s got kicked from %s (Re-Activating TrapChan)", s_ChanServ, av[0]); } m_cs_activatetrapchans(s_ChanServ, "Last action set"); return MOD_STOP; } int m_cs_trapchan(User * u) { char *option = strtok(NULL,""); if (option) { if (stricmp(option,"ON")==0) { if (!(cs_joinkillaction = DEFAULT_ACTION)) { notice(s_ChanServ,u->nick,"Error: Default action is set to 'NONE'. Please"); notice(s_ChanServ,u->nick,"use: /msg %s TRAP_CHAN [KILL|AKILL|GLOBOPS]", s_ChanServ); return MOD_CONT; } m_cs_activatetrapchans(u->nick,"DEFAULT"); notice(s_ChanServ,u->nick,"Trap channels turned \002ON\002."); } else if (stricmp(option,"OFF")==0) { cs_joinkillaction = 0; #ifdef TRAP_CHAN send_cmd(s_ChanServ, "PART %s", TRAP_CHAN); #endif #ifdef TRAP_CHAN2 send_cmd(s_ChanServ, "PART %s", TRAP_CHAN2); #endif #ifdef TRAP_CHAN3 send_cmd(s_ChanServ, "PART %s", TRAP_CHAN3); #endif #ifdef TRAP_CHAN4 send_cmd(s_ChanServ, "PART %s", TRAP_CHAN4); #endif #ifdef TRAP_CHAN5 send_cmd(s_ChanServ, "PART %s", TRAP_CHAN5); #endif notice(s_ChanServ,u->nick,"Trap channels turned \002OFF\002."); } else if (stricmp(option,"KILL")==0) { cs_joinkillaction = 1; m_cs_activatetrapchans(u->nick,"KILL"); notice(s_ChanServ,u->nick,"Trap channels turned \002ON\002."); } else if (stricmp(option,"AKILL")==0) { cs_joinkillaction = 2; m_cs_activatetrapchans(u->nick,"AKILL"); notice(s_ChanServ,u->nick,"Trap channels turned \002ON\002."); } else if (stricmp(option,"GLOBOPS")==0) { cs_joinkillaction = 3; m_cs_activatetrapchans(u->nick,"GLOBOPS"); notice(s_ChanServ,u->nick,"Trap channels turned \002ON\002."); } else if (stricmp(option,"SETTINGS")==0) { if (cs_joinkillaction) { notice(s_ChanServ,u->nick, "The trap channels are currently ON."); } if (cs_joinkillaction == 1) { notice(s_ChanServ,u->nick, "Non-opers who join trap channels will be KILLED."); } else if (cs_joinkillaction == 2) { notice(s_ChanServ,u->nick, "Non-opers who join trap channels will be AKILLED."); } else if (cs_joinkillaction == 3) { notice(s_ChanServ,u->nick, "Non-opers who join trap channels will cause a GLOBOPS to be sent out."); } else { cs_joinkillaction = 0; notice(s_ChanServ,u->nick, "The trap channels are not activated."); } notice(s_ChanServ,u->nick, "The following channels are trap channels:"); #ifdef TRAP_CHAN notice(s_ChanServ,u->nick, "%s", TRAP_CHAN); #endif #ifdef TRAP_CHAN2 notice(s_ChanServ,u->nick, "%s", TRAP_CHAN2); #endif #ifdef TRAP_CHAN3 notice(s_ChanServ,u->nick, "%s", TRAP_CHAN3); #endif #ifdef TRAP_CHAN4 notice(s_ChanServ,u->nick, "%s", TRAP_CHAN4); #endif #ifdef TRAP_CHAN5 notice(s_ChanServ,u->nick, "%s", TRAP_CHAN5); #endif notice(s_ChanServ,u->nick, "End of trap channel settings."); } else { notice(s_ChanServ,u->nick, TRAP_CHAN_SYNTAX); } return MOD_CONT; } notice(s_ChanServ,u->nick, TRAP_CHAN_SYNTAX); return MOD_CONT; } void AnopeFini(void) { #ifdef TRAP_CHAN send_cmd(s_ChanServ, "PART %s", TRAP_CHAN); #endif #ifdef TRAP_CHAN2 send_cmd(s_ChanServ, "PART %s", TRAP_CHAN2); #endif #ifdef TRAP_CHAN3 send_cmd(s_ChanServ, "PART %s", TRAP_CHAN3); #endif #ifdef TRAP_CHAN4 send_cmd(s_ChanServ, "PART %s", TRAP_CHAN4); #endif #ifdef TRAP_CHAN5 send_cmd(s_ChanServ, "PART %s", TRAP_CHAN5); #endif alog("Unloading module cs_joinkill.so"); } void m_cs_activatetrapchans(char *nick, char *action) { #ifdef TRAP_CHAN m_cs_activate_a_trapchan(TRAP_CHAN); #endif #ifdef TRAP_CHAN2 m_cs_activate_a_trapchan(TRAP_CHAN2); #endif #ifdef TRAP_CHAN3 m_cs_activate_a_trapchan(TRAP_CHAN3); #endif #ifdef TRAP_CHAN4 m_cs_activate_a_trapchan(TRAP_CHAN4); #endif #ifdef TRAP_CHAN5 m_cs_activate_a_trapchan(TRAP_CHAN5); #endif alog("[cs_trapchan]: Trap Channels activated by %s with action: %s", nick, action); return; } void m_cs_activate_a_trapchan(char *chan) { if (!chan) { return; } #ifdef ANOPE17x anope_cmd_join(s_ChanServ, chan, time(NULL)); anope_cmd_mode(s_ChanServ, chan, "+o %s", s_ChanServ); anope_cmd_mode(s_ChanServ, chan, TRAP_CHAN_MODES1); anope_cmd_mode(s_ChanServ, chan, TRAP_CHAN_MODES2); anope_cmd_topic(s_ChanServ, chan, s_ChanServ, TRAP_TOPIC, time(NULL)); #else #if defined(IRC_BAHAMUT) send_cmd(s_ChanServ, "SJOIN %lu %s", time(NULL), chan); #elif defined(IRC_HYBRID) send_cmd(NULL, "SJOIN %ld %s + :@%s", time(NULL), chan, s_ChanServ); #else send_cmd(s_ChanServ, "JOIN %s", chan); #endif send_cmd(s_ChanServ, "MODE %s +o %s %s %lu", chan, s_ChanServ, s_ChanServ, time(NULL)); send_cmd(s_ChanServ, "MODE %s %s", chan, TRAP_CHAN_MODES1); send_cmd(s_ChanServ, "MODE %s %s", chan, TRAP_CHAN_MODES2); send_cmd(s_ChanServ, "TOPIC %s :%s", chan, TRAP_TOPIC); #endif if (LOG_ALL) { alog("[cs_trapchan]: Trap Channel %s activated.", chan); } return; } void SGR_Module_Help_CHANSERV_TRAPCHAN(User *u) { if (is_services_admin(u)) { notice(s_ChanServ,u->nick, " TRAPCHAN Configure the 'TRAP' channel."); } return; } int SGR_Module_Help_CHANSERV_TRAPCHAN_FULL(User *u) { if (is_services_admin(u)) { notice(s_NickServ,u->nick, "-------------------------------------------------------------"); notice(s_NickServ,u->nick, TRAP_CHAN_SYNTAX); notice(s_NickServ,u->nick, " "); notice(s_NickServ,u->nick, "This command allows services admins and above to set up the"); notice(s_NickServ,u->nick, "'trap' channel. The trap channel, %s, will cause %s", TRAP_CHAN, s_ChanServ); notice(s_NickServ,u->nick, "to perform the configured action on any non-opered client"); notice(s_NickServ,u->nick, "that joins it."); notice(s_NickServ,u->nick, " "); notice(s_NickServ,u->nick, "If specified with the ON parameter, the trap channel will be"); notice(s_NickServ,u->nick, "activated with the settings specified in the module"); notice(s_NickServ,u->nick, "configuration block. This command is only valid if the"); notice(s_NickServ,u->nick, "default ACTION is set to KILL, AKILL or GLOBOPS."); notice(s_NickServ,u->nick, " "); notice(s_NickServ,u->nick, "If specified with the KILL, AKILL or GLOBOPS parameter, the"); notice(s_NickServ,u->nick, "trap channel will be activated, where the specified command"); notice(s_NickServ,u->nick, "(KILL, AKILL or GLOBOPS) will be used on (or about) any"); notice(s_NickServ,u->nick, "non-opered clients joining %s", TRAP_CHAN); notice(s_NickServ,u->nick, " "); notice(s_NickServ,u->nick, "If given with the SETTINGS parameter, the current trap channel"); notice(s_NickServ,u->nick, "action and status will be reported."); notice(s_NickServ,u->nick, " "); notice(s_NickServ,u->nick, "Finally, if specified with the OFF paramenter, the trap channel"); notice(s_NickServ,u->nick, "will cease to be a 'trap', and client may join it at will without"); notice(s_NickServ,u->nick, "invoking any of the available ACTIONs."); notice(s_NickServ,u->nick, "-------------------------------------------------------------"); } return MOD_CONT; }