Created
May 23, 2014 00:04
-
-
Save H7-25/9e86009530952f11ee0e to your computer and use it in GitHub Desktop.
anope 1.8 ctcp version
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "module.h" | |
#define AUTHOR "SGR" | |
#define VERSION "2.98" | |
#define MODNAME "ircd_ctcpversion" | |
/* ----------------------------------------------------------- | |
* Name : ircd_ctcpserv | |
* Author: SGR <[email protected]> | |
* Date : 17/11/2003 | |
* ----------------------------------------------------------- | |
* Functions: my_privmsgA, my_nickA, ctcp_check, | |
* timeout_version_user, CheckOffDefList, | |
* CheckCustomDefList | |
* Limitations: Anope1.5.6-r30 and later only. | |
* Tested: Ultimate(2.8.x), Unreal(3.2), Viagra, Ultimate(3.x) | |
* ----------------------------------------------------------- | |
* This version has been tested on Ultimate, Viagra and | |
* Unreal. | |
* | |
* This modules has 15 configurable options | |
* | |
* Please read the comments by each one. | |
* | |
* Some future version should have JOIN "/msg CTCPServ VALID" | |
* option - that would allow clients to report that they are | |
* real if they match a 'defintion' - thus preventing 'action'. | |
* | |
* Version Changes: | |
* | |
* 1: Core, many segfaults, in-code only def checking. | |
* 2: Core, All segfaults cleared. | |
* 3: Reading from files, kill or akill option added. | |
* 4: Bugs from above code ignored, alog and globops added | |
* 5: Reading from def files added, structure not used due | |
* to possible memory limits. | |
* 6: Help and in-IRC SET command added. All reported bugs | |
* cleared. Sorted some memory allocation issues that | |
* caused random segfaults and tested all detection | |
* and action systems. | |
* 7: Fixed some typos in the messages responses from the | |
* SET command, added Version change log. | |
* 8: Fixed a problem in it not detecting any dodgy clients | |
* as I had ignored CTCP protocall. | |
* 9: Removed unnecessary Akill checking. Fixed "less than | |
* 1 char from def" bug. | |
* 10: have done full scale testing. thanks VERY much to the | |
* staff of irc.weaklinks.net (a great network i must say) | |
* I hope the 500+ akills on bottler clients we set in | |
* one hour help keep your servers a little less laggy ;) | |
* 11: Fixed some screw-ups due to Ultimates protocall | |
* implementation, updated logging system | |
* 12: Sorted out an issue where /Nick'ing users were sometimes | |
* ignored and no user struct created for them. | |
* 13: Added optional 'Check ID'd and Opered users' setting. | |
* 14: Added Optional NOTICE parameter. | |
* Thanks especially to Rob - for discovering the | |
* ultimate client connect annouce is 'wank' :) | |
* 15: Resoved 'on nick change, invalid argc' error. | |
* 16: Found and fixed an error where def files were not | |
* closed, ultimatly causing a user to hit the file | |
* descriptor limit for a process. | |
* 17: Added option for default check and logging settings | |
* at the bottom of configuration block, and updated | |
* on load log-chan info to boot. | |
* 18: Fixed practically unnoticable memory leak reported | |
* by Certus :) | |
* 19: Added "rejoin on kill" system. | |
* 20: Added QUIT message to rejoin on kill system, should | |
* prevent crap IRCd's getting stuck in a loop attempting | |
* to kill CTCPServ on re-introduction. | |
* 21: Added an option to kill if clients don't reply. | |
* 22: Added Anope-1.7.x SVN (revision 370+) support. | |
* | |
* Thanks to dengel, Rob and Certus for all there support. | |
* Thanks to "raw" (mario@*.ipt.aol.com) and 'Larry' for | |
* there excellent help in providing bug reports and | |
* backtraces. | |
* ----------------------------------------------------------- | |
*/ | |
/* ---------------------------------------------------------------------- */ | |
/* START OF CONFIGURATION BLOCK - please read the comments :) */ | |
/* ---------------------------------------------------------------------- */ | |
/* If you are using Anope-1.7.x or later, leave this alone. | |
* Otherwise change it to '#undef ANOPE17x' (no quotes). | |
* | |
* THIS IS IMPORTANT | |
* | |
*/ | |
#undef ANOPE17x | |
/* NONE OF THE BELOW MESSAGES SHOULD BE LONGER THAN 450 characters - | |
* including spaces. */ | |
/* The below is noticed to users before they are KILLED or AKILLED. | |
* comment out or modify as necessary. Not all 6 need be used. */ | |
#define cNOTICE1 "Abilita il CTCP Version reply per connetterti a questo Network." | |
#define cNOTICE2 "Supporto http://support.simosnap.org" | |
/* #define cNOTICE6 "bleh blah bleh blah" */ | |
/* The below is noticed to users when ACTION is set to NOTICE. | |
* comment out or modify as necessary. Not all 10 need be used. */ | |
#define ccNOTICE1 "Abilita il CTCP Version reply per connetterti a questo Network." | |
#define ccNOTICE2 "Supporto http://support.simosnap.org" | |
//#define ccNOTICE3 " " | |
//#define ccNOTICE4 " " | |
//#define ccNOTICE5 " " | |
//#define ccNOTICE6 " " | |
//#define ccNOTICE7 " " | |
//#define ccNOTICE8 " " | |
//#define ccNOTICE9 " " | |
//#define ccNOTICE10 " " | |
/**************************************** | |
FOR THE BELOW SETTINGS **ONLY** | |
* CHANGE WHAT IS **INSIDE** THE | |
* "Speach marks". | |
****************************************/ | |
/* If this is defined, TIME_TO_WAIT_BEFORE_CTCP will NOT be used and | |
* clients will be versioned instantly on connecting. */ | |
#undef CTCP_INSTANTLY | |
/* ACTION_NO_REPLY_USERS -- If this is defined, CTCPServ will take | |
* action on clients that DO NOT reply to the CTCP request within | |
* NO_REPLY_TIMEOUT. This setting is not recommended :). | |
* | |
* The action performed will the the same as the one set for | |
* users who reply with a matched defintion. | |
*/ | |
#define ACTION_NO_REPLY_USERS | |
#define NO_REPLY_TIMEOUT "4s" | |
/* Time to wait before CTCPing users who have joined the network - MANDATORY | |
* Note that an integer followed by a letter == the time. | |
* e.g: 3s = 3 seconds; 3m = 3 mins; 3h = 3 hours; 3d = 3 days. | |
* set to a sensible time, e.g 3s to 30s [NOT less than 1s] */ | |
#define TIME_TO_WAIT_BEFORE_CTCP "5s" | |
/* The reason with which clients are killed - MANDATORY */ | |
#define KILL_REASON "Kline ID 301 - Info http://support.simosnap.org ."; | |
/* The reason with which clients are Akilled - MANDATORY */ | |
#define AKILL_REASON "Kline ID 301 - Info http://support.simosnap.org ."; | |
/* The below setting determins what action should be taken on the clients whose | |
* replies match a definition. There are currenly 5 settings: | |
* 0: Kill matches | |
* 1: AKILL matches | |
* 2: Globops (Send a message to all global IRCops) | |
* 3: Send to LogChan Only. | |
* 4: Notice the user. | |
* | |
* This setting is MANDATORY */ | |
#define DEFAULT_ACTION 1 | |
/* This is used if KillClonesAkillExpire is not set in the services.conf | |
* or if DONT_USE_KILL_CLONES_TIME is defined below. Please note this is | |
* subject to ExpireTimeout. | |
* | |
* This value _CANNOT_ be larger than 2147483647 (about 68 years) | |
* This value _MUST_ larger than 60 - MANDATORY | |
* | |
* NB: its recommended this is not set more than a few days as when a | |
* large botnet joins the network, the AKILL list can fill up quickly. | |
* My personal recommendation is about 3 hours. | |
* | |
*/ | |
#define AKILL_TIME_IN_SECONDS 3600 /* 1 minuto */ | |
/* Set to 1 to force the above time to be used. | |
* (and NOT the KillClonesAkillExpire from the services.conf file) | |
*/ | |
#define DONT_USE_KILL_CLONES_TIME 1 | |
/* On load status - should I automatically start checking clients? | |
* SET CHECK [ALL | ON | OFF ] | |
* 2 1 0 | |
* Diff between ON and ALL - when ON only clients who don't ID to | |
* NickServ or /Oper up in TIME_TO_WAIT_BEFORE_CTCP will be checked | |
* | |
* This setting MUST be 0, 1 or 2 | |
*/ | |
#define DEFAULT_MODE 1 | |
/* on load logging status | |
* SET LOGGING [OFF|BASIC|USEFUL|VERBOSE|FULL]" | |
* 0 1 2 3 4 | |
* 0 - Off | |
* 1 - Every Action | |
* 2 - Every Match + Every Action + Every FAIL | |
* 3 - Every New User Versioned + Every Match + Every Action | |
* 4 - Detected User + Every New User Versioned + Every Match + Every Action | |
* | |
* This setting MUST be 0, 1, 2, 3 or 4 | |
*/ | |
#define DEFAULT_LOG_LEVEL 1 | |
/* ---------------------------------------------------------------------- */ | |
/* DO NOT EDIT BELOW THIS LINE UNLESS YOU KNOW WHAT YOU ARE DOING */ | |
/* ---------------------------------------------------------------------- */ | |
/* Set these to be the Nick, Host and Realname of the CTCPServ Psudo | |
* client, as per your whims. */ | |
/* Nickname - NICKLEN character MAXIMUM - (see your IRCd's protocall response for this) */ | |
char *s_CTCPServ = "CTCPServ"; | |
/* HostMask: 64 character MAXIMUM */ | |
char *s_CTCPServHOST = "services.simosnap.com"; | |
/* Realname 30 character MAXIMUM */ | |
char *s_CTCPServREALNAME = "CTCP Responce Checker"; | |
int timeout_kill_user(int argc, char **argv); | |
int my_privmsgA(char *source, int ac, char **av); | |
int my_nickA(char *source, int ac, char **av); | |
int ctcp_check(User * u, char *buf); | |
int timeout_version_user(int argc, char **argv); | |
int CheckOffDefList(char *to_be_matched_off); | |
int kill_due_to_version(User *u); | |
int is_ctcpexempt(User *u); | |
int CheckCustomDefList(char *to_be_matched); | |
int my_ctcpserv_killrejoin(char *source, int ac, char **av); | |
int cTAKEACTION = DEFAULT_ACTION; | |
int cAKILLTIMEINSECONDS = AKILL_TIME_IN_SECONDS; | |
int cDONTUSEKILLCONESTIME = DONT_USE_KILL_CLONES_TIME; | |
int cDEFAULTMODE = DEFAULT_MODE; | |
int cDEFAULTLOGLEVEL = DEFAULT_LOG_LEVEL; | |
char *cAKILLREASON = AKILL_REASON; | |
char *cKILLREASON = KILL_REASON; | |
int CTCPid = 0; | |
int donotchecktrue = 0; | |
int CTCPServLOGLEV = 0; | |
int KillClonesAkillExpires = 0; | |
char *CTCPExempts = NULL; | |
char **CTCPExemptsList; | |
int CTCPExemptsNum = 0; | |
#ifdef ANOPE17x | |
#define NEWNICK(a,b,c,d,e,f) anope_cmd_bot_nick(a,b,c,d,ircd->botserv_bot_mode) | |
#define wallops anope_cmd_global | |
#endif | |
#ifdef ACTION_NO_REPLY_USERS | |
typedef struct CTCPU_ CTCPU; | |
struct CTCPU_ | |
{ | |
CTCPU *next; | |
CTCPU *prev; | |
char *nick; | |
char *uid; | |
time_t time; | |
}; | |
#define HASH_SIZE 8192 | |
CTCPU *ctcpuhash[HASH_SIZE]; | |
unsigned int ctcpunum = 0; | |
static void add_entry(CTCPU *fc); | |
static int del_entry(CTCPU *fc); | |
static CTCPU *create_entry(char *nick, char *uid); | |
static CTCPU *find_ctcpu_entry(char *nick); | |
#endif | |
int AnopeInit(int argc, char **argv) | |
{ | |
Message *msg = NULL; | |
int status, i; | |
char *s; | |
Directive directive = {"CTCPExempts", {{PARAM_STRING, PARAM_RELOAD, &CTCPExempts}}}; | |
msg = createMessage("PRIVMSG", my_privmsgA); | |
status = moduleAddMessage(msg, MOD_HEAD); | |
msg = createMessage("NOTICE", my_privmsgA); | |
status = moduleAddMessage(msg, MOD_HEAD); | |
#if defined(IRC_ULTIMATE3) | |
msg = createMessage("CLIENT", my_nickA); | |
alog("[ircd_ctcpserv] Created message for CLIENT command."); | |
#else | |
msg = createMessage("UID", my_nickA); | |
alog("[ircd_ctcpserv] Created message for UID command."); | |
#endif | |
status = moduleAddMessage(msg, MOD_TAIL); | |
msg = createMessage("KILL", my_ctcpserv_killrejoin); | |
status = moduleAddMessage(msg, MOD_HEAD); | |
if (status == MOD_ERR_OK) { | |
kill_user(NULL, s_CTCPServ, "This nick is now being used by Services"); // Lets just make sure. | |
NEWNICK(s_CTCPServ, s_CTCPServ, s_CTCPServHOST, s_CTCPServREALNAME, "+Iko", 1); | |
} | |
moduleAddAuthor(AUTHOR); | |
moduleAddVersion(VERSION); | |
donotchecktrue = cDEFAULTMODE; | |
CTCPServLOGLEV = cDEFAULTLOGLEVEL; | |
// caricamento delle exempts | |
moduleGetConfigDirective(&directive); | |
if (!(*(char **) (&directive)->params[0].ptr)) { | |
alog("[%s] ERROR: Missing configuration option '%s' - Please read %s.c before compiling", MODNAME, (&directive)->name, MODNAME); | |
} | |
if (CTCPExemptsNum) { | |
for (i = 0; i < CTCPExemptsNum; i++) { | |
free(CTCPExemptsList[i]); | |
} | |
} | |
if (CTCPExempts) { | |
CTCPExemptsNum = 0; | |
s = strtok(CTCPExempts, " "); | |
do { | |
if (s) { | |
CTCPExemptsNum++; | |
CTCPExemptsList = realloc(CTCPExemptsList, sizeof(char *) * CTCPExemptsNum); | |
CTCPExemptsList[CTCPExemptsNum - 1] = sstrdup(s); | |
} | |
} while ((s = strtok(NULL, " "))); | |
} | |
alog("[ircd_ctcpserv] This module has loaded and is now active."); | |
alog("[ircd_ctcpserv] For information see /msg %s HELP", s_CTCPServ); | |
if (!cDEFAULTMODE) { | |
alog("[ircd_ctcpserv] %s Protection DISABLED. To activate protection now, use: /msg %s SET CHECK ON", s_CTCPServ, s_CTCPServ); | |
} | |
if (cDEFAULTMODE) { | |
if (cDEFAULTMODE > 1) { | |
alog("[ircd_ctcpserv] %s - Protection activated for ALL clients.", s_CTCPServ); | |
} | |
if (cDEFAULTMODE == 1) { | |
alog("[ircd_ctcpserv] %s - Protection activated.", s_CTCPServ); | |
} | |
} | |
if (!cDEFAULTLOGLEVEL) { | |
alog("[ircd_ctcpserv] %s - Logging set to OFF. Use: /msg %s SET LOGGING ON - to enable.", s_CTCPServ, s_CTCPServ); | |
} | |
if (cDEFAULTLOGLEVEL == 1) { | |
alog("[ircd_ctcpserv] %s - Logging set to BASIC.", s_CTCPServ); | |
} | |
if (cDEFAULTLOGLEVEL == 2) { | |
alog("[ircd_ctcpserv] %s - Logging set to USEFUL.", s_CTCPServ); | |
} | |
if (cDEFAULTLOGLEVEL == 3) { | |
alog("[ircd_ctcpserv] %s - Logging set to VERBOSE.", s_CTCPServ); | |
} | |
if (cDEFAULTLOGLEVEL == 4) { | |
alog("[ircd_ctcpserv] %s - Logging set to FULL.", s_CTCPServ); | |
} | |
return MOD_CONT; | |
} | |
void AnopeFini(void) | |
{ | |
int i; | |
if (CTCPExempts) free(CTCPExempts); | |
if (CTCPExemptsNum) { | |
for (i = 0; i < CTCPExemptsNum; i++) { | |
free(CTCPExemptsList[i]); | |
} | |
} | |
alog("[%s] Module Unloaded Successfully!", MODNAME); | |
send_cmd(s_CTCPServ, "QUIT :Module Unloaded!"); | |
} | |
int my_privmsgA(char *source, int ac, char **msg) | |
{ | |
/* an uglier version of Rob's CatServ module code ---- aggiunto TS6 da Simos*/ | |
User *u; | |
Uid *ud = NULL; | |
char *s; | |
/* First, some basic checks */ | |
if (ac != 2) { /* bleh */ | |
return MOD_CONT; | |
} | |
if (ircd->ts6) | |
u = find_byuid(source); // If this is a ts6 ircd, find the user by uid | |
if (!u && !(u = finduser(source))) { // If user isn't found and we cant find them by nick, return | |
return MOD_CONT; | |
} | |
if (*msg[0] == '#') { | |
return MOD_CONT; | |
} | |
/* Channel message */ | |
s = strchr(msg[0], '@'); | |
if (s) { | |
*s++ = 0; | |
if (stricmp(s, ServerName) != 0) { | |
return MOD_CONT; | |
} | |
} | |
/*aggiunto*/ | |
if (ircd->ts6) | |
ud = find_uid(s_CTCPServ); // Find CTCPServ UID | |
if ((stricmp(msg[0], s_CTCPServ)) == 0 || (ud && strcmp(msg[0], ud->uid) == 0)) { /* its for US! */ | |
ctcp_check(u, msg[1]); | |
return MOD_STOP; | |
} else { /* ok it isnt us, let the old code have it */ | |
return MOD_CONT; | |
} | |
} | |
/*****************************************************************************/ | |
int ctcp_check(User * u, char *buf) | |
{ | |
char *isversion = strtok(buf, " "); | |
char *s; | |
char *t; | |
if (!isversion) { | |
return MOD_STOP; | |
} | |
if (stricmp(isversion, "\1PING") == 0) { | |
if (!(s = strtok(NULL, ""))) { | |
s = "\1"; | |
} | |
notice(s_CTCPServ, u->nick, "\1PING %s", s); | |
return MOD_STOP; | |
} | |
if (skeleton) { | |
notice_lang(s_CTCPServ, u, SERVICE_OFFLINE, s_CTCPServ); | |
return MOD_STOP; | |
} | |
if (CTCPServLOGLEV > 3) { | |
alog("[ircd_ctcpversion] - Got a message - starts: %s", isversion); | |
} | |
if (stricmp(isversion, "\1VERSION") == 0) { | |
#ifdef ACTION_NO_REPLY_USERS | |
CTCPU *moo; | |
#endif | |
if (CTCPServLOGLEV > 3) { | |
alog("[ircd_ctcpversion] - Its a VERSION!"); | |
} | |
#ifdef ACTION_NO_REPLY_USERS | |
if ((moo = find_ctcpu_entry(u->nick))) { | |
del_entry(moo); | |
} | |
#endif | |
if (donotchecktrue) { | |
if (!(s = strtok(NULL, ""))) { | |
s = "\1"; | |
} | |
if (CTCPServLOGLEV > 3) { | |
alog("[ircd_ctcpversion] - Checking | %s | against def lists.", s); | |
} | |
if (CheckCustomDefList(s) == 1) { | |
kill_due_to_version(u); | |
return MOD_STOP; | |
} | |
if (CheckOffDefList(s) == 1) { | |
kill_due_to_version(u); | |
return MOD_STOP; | |
} | |
} | |
} | |
if (stricmp(isversion, "HELP") == 0) { | |
s = strtok(NULL, " "); | |
if (!s) { | |
notice(s_CTCPServ, u->nick, "-----------------------------------------------------------------------"); | |
notice(s_CTCPServ, u->nick, "%s checks users CTCP versions as they join the network.", s_CTCPServ); | |
notice(s_CTCPServ, u->nick, "This is done so we can quickly remove mass-spam or clone bots."); | |
notice(s_CTCPServ, u->nick, "If you match a forbidden client you may be forcefully removed"); | |
notice(s_CTCPServ, u->nick, "from the network. For more information join the official help"); | |
notice(s_CTCPServ, u->nick, "room."); | |
if (is_oper(u)) { | |
notice(s_CTCPServ, u->nick, " "); | |
notice(s_CTCPServ, u->nick, "The module version is %s", VERSION); | |
notice(s_CTCPServ, u->nick, " "); | |
notice(s_CTCPServ, u->nick, "New defintions should be added to custom.dat"); | |
notice(s_CTCPServ, u->nick, "Please remember to NOT modify the official.dat file - "); | |
notice(s_CTCPServ, u->nick, "and to only add your own 'definitions' to the custom.dat"); | |
notice(s_CTCPServ, u->nick, "file; offical.dat may get updated, check the anope forums."); | |
notice(s_CTCPServ, u->nick, "This file [custom.dat] can be updated \"on the fly\" so no"); | |
notice(s_CTCPServ, u->nick, "'reshashing' is needed. Please ensure there are NO blank lines."); | |
notice(s_CTCPServ, u->nick, "in this file."); | |
notice(s_CTCPServ, u->nick, " "); | |
notice(s_CTCPServ, u->nick, "For help on setting %s options see /msg %s HELP SET", s_CTCPServ, | |
s_CTCPServ); | |
} | |
notice(s_CTCPServ, u->nick, "-----------------------------------------------------------------------"); | |
return MOD_CONT; | |
} | |
if (is_services_admin(u)) { | |
if (stricmp(s, "NOTICES") == 0) { | |
notice(s_CTCPServ, u->nick, "-----------------------------------------------------------------------"); | |
notice(s_CTCPServ, u->nick, "These notices will be noticed to uses when NOTIFY is set as the"); | |
notice(s_CTCPServ, u->nick, "%s action when checking is on.", s_CTCPServ); | |
notice(s_CTCPServ, u->nick, "-----------------------------------------------------------------------"); | |
#ifdef ccNOTICE1 | |
notice(s_CTCPServ, u->nick, ccNOTICE1); | |
#endif | |
#ifdef ccNOTICE2 | |
notice(s_CTCPServ, u->nick, ccNOTICE2); | |
#endif | |
#ifdef ccNOTICE3 | |
notice(s_CTCPServ, u->nick, ccNOTICE3); | |
#endif | |
#ifdef ccNOTICE4 | |
notice(s_CTCPServ, u->nick, ccNOTICE4); | |
#endif | |
#ifdef ccNOTICE5 | |
notice(s_CTCPServ, u->nick, ccNOTICE5); | |
#endif | |
#ifdef ccNOTICE6 | |
notice(s_CTCPServ, u->nick, ccNOTICE6); | |
#endif | |
#ifdef ccNOTICE7 | |
notice(s_CTCPServ, u->nick, ccNOTICE7); | |
#endif | |
#ifdef ccNOTICE8 | |
notice(s_CTCPServ, u->nick, ccNOTICE8); | |
#endif | |
#ifdef ccNOTICE9 | |
notice(s_CTCPServ, u->nick, ccNOTICE9); | |
#endif | |
#ifdef ccNOTICE10 | |
notice(s_CTCPServ, u->nick, ccNOTICE10); | |
#endif | |
notice(s_CTCPServ, u->nick, "-----------------------------------------------------------------------"); | |
return MOD_CONT; | |
} | |
if (stricmp(s, "SET") == 0) { | |
notice(s_CTCPServ, u->nick, "-----------------------------------------------------------------------"); | |
notice(s_CTCPServ, u->nick, "Syntax: SET ACTION [KILL|AKILL|GLOBOPS|ALOG|NOTICE]"); | |
notice(s_CTCPServ, u->nick, "Syntax: SET CHECK [ALL|ON|OFF]"); | |
notice(s_CTCPServ, u->nick, "Syntax: SET LOGGING [OFF|BASIC|USEFUL|VERBOSE|FULL]"); | |
notice(s_CTCPServ, u->nick, " "); | |
notice(s_CTCPServ, u->nick, "SET ACTION: Set the action that is peformed on detected clients, ALOG"); | |
notice(s_CTCPServ, u->nick, " will force a LogChan message. NOTICE will cause the notices"); | |
notice(s_CTCPServ, u->nick, " listed in /msg %s HELP NOTICES be broadcast to detected", s_CTCPServ); | |
notice(s_CTCPServ, u->nick, " users. The rest should be self-explainatory. "); | |
notice(s_CTCPServ, u->nick, " "); | |
notice(s_CTCPServ, u->nick, "SET CHECK: Set if the CTCP VERSION on connect is actually used. This"); | |
notice(s_CTCPServ, u->nick, " command is designed to stop the checks for a short time"); | |
notice(s_CTCPServ, u->nick, " without a SRA having to unload the module. ALL means that"); | |
notice(s_CTCPServ, u->nick, " ALL clients will be checked, ON means only non-ID'd and"); | |
notice(s_CTCPServ, u->nick, " non-opered client will be checked (after timeout) and OFF"); | |
notice(s_CTCPServ, u->nick, " means no clients will be checked at all."); | |
notice(s_CTCPServ, u->nick, " "); | |
notice(s_CTCPServ, u->nick, "SET LOGGING: This command sets how verbose %s's logging is. When set to", s_CTCPServ); | |
notice(s_CTCPServ, u->nick, " OFF, there is no logging what-so-ever. When set to BASIC, logs"); | |
notice(s_CTCPServ, u->nick, " of clients who ilicit ACTION are made to the logchan."); | |
notice(s_CTCPServ, u->nick, " When set to USEFUL, CTCPServ will send logchan messages of"); | |
notice(s_CTCPServ, u->nick, " the definition matched and the action ensuing it. VERBOSE"); | |
notice(s_CTCPServ, u->nick, " puts all relevant info into the logchan, and finally FULL"); notice(s_CTCPServ, u->nick, " is used for debugging purposes. "); | |
notice(s_CTCPServ, u->nick, " "); | |
notice(s_CTCPServ, u->nick, "NOTE: If this module is unloaded these settings are lost."); | |
notice(s_CTCPServ, u->nick, "-----------------------------------------------------------------------"); | |
return MOD_CONT; | |
} | |
} | |
return MOD_CONT; | |
} | |
if (stricmp(isversion, "SET") == 0) { | |
if (!is_services_admin(u)) { | |
return MOD_CONT; | |
} | |
s = strtok(NULL, " "); | |
t = strtok(NULL, " "); | |
if (!s || !t) { | |
notice(s_CTCPServ, u->nick, "See \2/msg %s HELP SET\2 for more information.", s_CTCPServ); | |
return MOD_CONT; | |
} | |
if (stricmp(s, "ACTION") == 0) { | |
if (stricmp(t, "KILL") == 0) { | |
cTAKEACTION = 0; | |
notice(s_CTCPServ, u->nick, "Action sucessfully set to KILL"); | |
wallops(s_CTCPServ, "%s set %s action to KILL", u->nick, s_CTCPServ); | |
return MOD_CONT; | |
} | |
if (stricmp(t, "AKILL") == 0) { | |
cTAKEACTION = 1; | |
notice(s_CTCPServ, u->nick, "Action sucessfully set to AKILL"); | |
wallops(s_CTCPServ, "%s set %s action to AKILL", u->nick, s_CTCPServ); | |
return MOD_CONT; | |
} | |
if (stricmp(t, "GLOBOPS") == 0) { | |
cTAKEACTION = 2; | |
notice(s_CTCPServ, u->nick, "Action sucessfully set to GLOBOPS"); | |
wallops(s_CTCPServ, "%s set %s action to GLOBOPS", u->nick, s_CTCPServ); | |
return MOD_CONT; | |
} | |
if (stricmp(t, "ALOG") == 0) { | |
cTAKEACTION = 3; | |
notice(s_CTCPServ, u->nick, "Action sucessfully set to ALOG"); | |
wallops(s_CTCPServ, "%s set %s action to ALOG", u->nick, s_CTCPServ); | |
return MOD_CONT; | |
} | |
if (stricmp(t, "NOTICE") == 0) { | |
cTAKEACTION = 4; | |
notice(s_CTCPServ, u->nick, "Action sucessfully set to NOTICE"); | |
wallops(s_CTCPServ, "%s set %s action to NOTICE", u->nick, s_CTCPServ); | |
return MOD_CONT; | |
} | |
else { | |
notice(s_CTCPServ, u->nick, "See \2/msg %s HELP SET\2 for more information.", s_CTCPServ); | |
} | |
return MOD_CONT; | |
} | |
/* ------------ | |
* Checking INT's | |
* ------------ | |
* OFF = 0 | |
* ON = 1 | |
* ALL = 2 | |
* */ | |
if (stricmp(s, "CHECK") == 0) { | |
if (stricmp(t, "OFF") == 0) { | |
donotchecktrue = 0; | |
notice(s_CTCPServ, u->nick, "You sucessfully disabled CTCP VERSION checking."); | |
wallops(s_CTCPServ, "%s set %s on connect CTCP VERSION checking OFF.", u->nick, s_CTCPServ); | |
return MOD_CONT; | |
} | |
if (stricmp(t, "ON") == 0) { | |
donotchecktrue = 1; | |
notice(s_CTCPServ, u->nick, "You sucessfully enabled CTCP VERSION checking."); | |
wallops(s_CTCPServ, "%s set %s on connect CTCP VERSION checking ON.", u->nick, s_CTCPServ); | |
return MOD_CONT; | |
} | |
if (stricmp(t, "ALL") == 0) { | |
donotchecktrue = 2; | |
notice(s_CTCPServ, u->nick, "You sucessfully enabled CTCP VERSION checking [ALL clients]."); | |
wallops(s_CTCPServ, "%s set %s on connect CTCP VERSION checking ON [ALL clients].", u->nick, s_CTCPServ); | |
return MOD_CONT; | |
} | |
else { | |
notice(s_CTCPServ, u->nick, "See \2/msg %s HELP SET\2 for more information.", s_CTCPServ); | |
} | |
return MOD_CONT; | |
} | |
/* ---------- | |
* Logging INT's | |
*----------- | |
* 0 Off | |
* 1 Every Action | |
* 2 Every Match + Every Action + Every FAIL | |
* 3 Every New User Versioned + Every Match + Every Action | |
* 4 Detected User + Every New User Versioned + Every Match + Every Action | |
*/ | |
if (stricmp(s, "LOGGING") == 0) { | |
if (stricmp(t, "OFF") == 0) { | |
CTCPServLOGLEV = 0; | |
notice(s_CTCPServ, u->nick, "You sucessfully set %s logging to OFF.", s_CTCPServ); | |
wallops(s_CTCPServ, "%s set sucessfully set %s logging to OFF.", u->nick, s_CTCPServ); | |
return MOD_CONT; | |
} | |
if (stricmp(t, "BASIC") == 0) { | |
CTCPServLOGLEV = 1; | |
notice(s_CTCPServ, u->nick, "You sucessfully set %s logging to BASIC.", s_CTCPServ); | |
wallops(s_CTCPServ, "%s set sucessfully set %s logging to BASIC.", u->nick, s_CTCPServ); | |
return MOD_CONT; | |
} | |
if (stricmp(t, "USEFUL") == 0) { | |
CTCPServLOGLEV = 2; | |
notice(s_CTCPServ, u->nick, "You sucessfully set %s logging to USEFUL.", s_CTCPServ); | |
wallops(s_CTCPServ, "%s set sucessfully set %s logging to USEFUL.", u->nick, s_CTCPServ); | |
return MOD_CONT; | |
} | |
if (stricmp(t, "VERBOSE") == 0) { | |
CTCPServLOGLEV = 3; | |
notice(s_CTCPServ, u->nick, "You sucessfully set %s logging to VERBOSE.", s_CTCPServ); | |
wallops(s_CTCPServ, "%s set sucessfully set %s logging to VERBOSE.", u->nick, s_CTCPServ); | |
return MOD_CONT; | |
} | |
if (stricmp(t, "FULL") == 0) { | |
CTCPServLOGLEV = 4; | |
notice(s_CTCPServ, u->nick, "You sucessfully set %s logging to FULL.", s_CTCPServ); | |
wallops(s_CTCPServ, "%s set sucessfully set %s logging to FULL.", u->nick, s_CTCPServ); | |
return MOD_CONT; | |
} | |
} | |
} | |
return MOD_CONT; | |
} | |
int my_nickA(char *source, int ac, char **av) | |
{ | |
#ifndef CTCP_INSTANTLY | |
char CTCPidx[16]; | |
#endif | |
char *argv[1]; | |
if (ac < 2) { | |
if (CTCPServLOGLEV > 2) { | |
alog("CTCPServ [ircd_ctcpversion] ERROR - NICK/CLIENT/UID MSG LACKS NECESSARY ARGUMENTS"); | |
} | |
return MOD_CONT; | |
} | |
if (CTCPServLOGLEV > 3) { | |
alog("[ircd_ctcpversion] - Found a new user :D"); | |
} | |
#ifndef IRC_ULTIMATE3 | |
if (*source) { | |
// commentato per testare su inspircd2.x | |
// return MOD_CONT; | |
} | |
#endif | |
if (CTCPServLOGLEV > 3) { | |
alog("[ircd_ctcpversion] - av0 %s av1 %s av2 %s", av[0], av[1], av[2] ); | |
} | |
argv[0] = sstrdup(av[0]); | |
#ifndef CTCP_INSTANTLY | |
CTCPid = CTCPid + 1; | |
snprintf(CTCPidx, sizeof(CTCPidx), "CTCP-%d", CTCPid); | |
if (moduleAddCallback(CTCPidx, time(NULL)+dotime(TIME_TO_WAIT_BEFORE_CTCP), timeout_version_user,1,argv) != MOD_ERR_OK) { | |
alog("CTCPServ [ircd_ctcpversion] --------- ERROR REPORT -------"); | |
alog("CTCPServ [ircd_ctcpversion] moduleAddCallback Failed. (Timeout setting for function"); | |
alog("CTCPServ [ircd_ctcpversion] int timeout_version_user; args: %s)", av[0]); | |
alog("CTCPServ [ircd_ctcpversion] MOD_ERR_OK not returned. Please report this to the module developer"); | |
alog("CTCPServ [ircd_ctcpversion] ------- ERROR REPORT END------"); | |
free(argv[0]); | |
return MOD_CONT; | |
} | |
if (CTCPid > 2147483600) { | |
CTCPid = 1; | |
} | |
#else | |
timeout_version_user(1, argv); | |
#endif | |
free(argv[0]); | |
return MOD_CONT; | |
} | |
int timeout_version_user(int argc, char **argv) | |
{ | |
User *u2; | |
char *peep = argv[0]; | |
if (!argc) { | |
return MOD_STOP; | |
} | |
if (ircd->ts6) | |
u2 = find_byuid(peep); // If this is a ts6 ircd, find the user by uid | |
if (!u2) | |
u2 = finduser(peep); | |
if (u2) { | |
if (donotchecktrue < 2 ) { | |
if (is_oper(u2)) { | |
if (CTCPServLOGLEV > 3) { | |
alog("[ircd_ctcpversion] %s - Not being checked (is an Oper)", u2->nick); | |
} | |
return MOD_CONT; | |
} | |
if (nick_identified(u2)) { | |
if (CTCPServLOGLEV > 3) { | |
alog("[ircd_ctcpversion] %s - Not being checked (is NickServ Identifed)", u2->nick); | |
} | |
return MOD_CONT; | |
} | |
/* if (is_svsagent(u2)) { | |
if (CTCPServLOGLEV > 3) { | |
alog("[ircd_ctcpversion] %s - Not being checked (is a Services Agent)", u2->nick); | |
} | |
return MOD_CONT; | |
} | |
*/ | |
if (is_ctcpexempt(u2)) { | |
if (CTCPServLOGLEV > 3) { | |
alog("[ircd_ctcpversion] %s - Not being checked (is in exempts list)", u2->nick); | |
} | |
return MOD_CONT; | |
} | |
} | |
if (donotchecktrue) { | |
#ifdef ACTION_NO_REPLY_USERS | |
char CTCPidx[16]; | |
char *argG[2]; | |
#endif | |
if (CTCPServLOGLEV > 2) { | |
alog("[ircd_ctcpversion] Version Checking %s", u2->nick); | |
} | |
anope_cmd_privmsg(s_CTCPServ, u2->nick, "%cVERSION%c", 1, 1); | |
// lnx85: sostituisco il send_cmd con anope_cmd_privmsg (su 1.8.7 pare che send_cmd non faccia nulla) | |
// send_cmd(s_CTCPServ, "PRIVMSG %s :\1VERSION\1", u2->nick); | |
#ifdef ACTION_NO_REPLY_USERS | |
create_entry(u2->nick, ircd->ts6 ? u2->uid : NULL); | |
CTCPid = CTCPid + 1; | |
snprintf(CTCPidx, sizeof(CTCPidx), "NICK-%d", CTCPid); | |
if (CTCPid > 2147483600) { | |
CTCPid = 1; | |
} | |
argG[0] = sstrdup(u2->nick); | |
if (ircd->ts6) | |
argG[1] = sstrdup(u2->uid); | |
moduleAddCallback(CTCPidx, time(NULL)+dotime(NO_REPLY_TIMEOUT), timeout_kill_user,ircd->ts6 ? 2 : 1,argG); | |
#endif | |
} | |
} | |
else { | |
if (CTCPServLOGLEV > 1) { | |
alog("[ircd_ctcpversion] ERROR - could not find %s [Perhaps they Quit]", peep); | |
} | |
} | |
return MOD_CONT; | |
} | |
int timeout_kill_user(int argc, char **argv) | |
{ | |
CTCPU *moo; | |
User *u; | |
if ((moo = find_ctcpu_entry(argv[0]))) { | |
if (ircd->ts6) | |
u = find_byuid(moo->uid); // If this is a ts6 ircd, find the user by uid | |
if (!u) | |
u = finduser(moo->nick); | |
if (u) { | |
kill_due_to_version(u); | |
} | |
del_entry(moo); | |
} | |
return MOD_CONT; | |
} | |
/*-----------------------------------------------*/ | |
int CheckOffDefList(char *to_be_matched) | |
{ | |
FILE *OffDef; | |
char definition_string[128]; | |
int len = 0; | |
// Open the file (r == in read only mode) | |
OffDef = fopen("official.dat","r"); | |
// if the file is there, loop until there is no | |
// more data to be read from the file | |
if (OffDef) { | |
while (fgets(definition_string, 127, OffDef) != NULL) { | |
len = strlen(definition_string); | |
// replace the \n and CTCP (\1) character with \0 | |
definition_string[len-1]='\0'; | |
//definition_string[len-2]='\0'; | |
// check if the given users version string has | |
// the def string as a part of if - if so | |
// return 1 - for action, else, carry on | |
if (stristr(to_be_matched, definition_string)) { | |
if (CTCPServLOGLEV > 1) { | |
alog("VERSION MATCH: %s +[MATCHED WITH]+ %s", to_be_matched, definition_string); | |
} | |
fclose(OffDef); | |
return 1; | |
break; | |
} | |
} | |
} | |
else { | |
alog("CRITICAL ERROR: Unable to open official.dat"); | |
return 0; | |
} | |
if (CTCPServLOGLEV > 3) { | |
alog("[ircd_ctcpversion] - Check against official.dat done."); | |
} | |
fclose(OffDef); | |
return 0; | |
} | |
int CheckCustomDefList(char *to_be_matched) | |
{ | |
FILE *CustomDef; | |
char definition_string[128]; | |
int len = 0; | |
/* Check empty version response */ | |
while (isspace(*to_be_matched)) to_be_matched++; | |
if (strlen(to_be_matched) < 2) { | |
alog("[ircd_ctcpversion] - Empty version response."); | |
return 1; | |
} | |
/* Open the file (r == in read only mode) */ | |
CustomDef = fopen("custom.dat","r"); | |
/* if the file is there, loop until there is no | |
* more data to be read from the file */ | |
if (CustomDef) { | |
while (fgets(definition_string, 127, CustomDef) != NULL) { | |
len = strlen(definition_string); | |
/* replace the \n character with \0 */ | |
definition_string[len-1]='\0'; | |
//definition_string[len-2]='\0'; | |
/* check if the given users version string has | |
* the def string as a part of if - if so | |
* return 1 - for action, else, carry on */ | |
if (stristr(to_be_matched, definition_string)) { | |
if (CTCPServLOGLEV > 1) { | |
alog("VERSION MATCH: %s +[MATCHED WITH]+ %s", to_be_matched, definition_string); | |
} | |
fclose(CustomDef); | |
return 1; | |
break; | |
} | |
} | |
} | |
else { | |
alog("CRITICAL ERROR: Unable to open custom.dat"); | |
return 0; | |
} | |
if (CTCPServLOGLEV > 3) { | |
alog("[ircd_ctcpversion] - Check against custom.dat done."); | |
} | |
fclose(CustomDef); | |
return 0; | |
} | |
int kill_due_to_version(User *u) | |
{ | |
char akillmask[BUFSIZE]; | |
if (cTAKEACTION == 4) { | |
#ifdef ccNOTICE1 | |
notice(s_CTCPServ, u->nick, ccNOTICE1); | |
#endif | |
#ifdef ccNOTICE2 | |
notice(s_CTCPServ, u->nick, ccNOTICE2); | |
#endif | |
#ifdef ccNOTICE3 | |
notice(s_CTCPServ, u->nick, ccNOTICE3); | |
#endif | |
#ifdef ccNOTICE4 | |
notice(s_CTCPServ, u->nick, ccNOTICE4); | |
#endif | |
#ifdef ccNOTICE5 | |
notice(s_CTCPServ, u->nick, ccNOTICE5); | |
#endif | |
#ifdef ccNOTICE6 | |
notice(s_CTCPServ, u->nick, ccNOTICE6); | |
#endif | |
#ifdef ccNOTICE7 | |
notice(s_CTCPServ, u->nick, ccNOTICE7); | |
#endif | |
#ifdef ccNOTICE8 | |
notice(s_CTCPServ, u->nick, ccNOTICE8); | |
#endif | |
#ifdef ccNOTICE9 | |
notice(s_CTCPServ, u->nick, ccNOTICE9); | |
#endif | |
#ifdef ccNOTICE10 | |
notice(s_CTCPServ, u->nick, ccNOTICE10); | |
#endif | |
return MOD_STOP; | |
} | |
if (cTAKEACTION == 3) { | |
alog("WARNING: %s (%s) has a forbidden string in their CTCP VERSION reply", u->nick, u->host); | |
return MOD_STOP; | |
} | |
if (cTAKEACTION == 2) { | |
wallops(s_CTCPServ, "WARNING: %s (%s) has a forbidden string in their CTCP VERSION reply", u->nick, u->host); | |
return MOD_STOP; | |
} | |
#ifdef cNOTICE1 | |
notice(s_CTCPServ, u->nick, "%s", cNOTICE1); | |
#endif | |
#ifdef cNOTICE2 | |
notice(s_CTCPServ, u->nick, "%s", cNOTICE2); | |
#endif | |
#ifdef cNOTICE3 | |
notice(s_CTCPServ, u->nick, "%s", cNOTICE3); | |
#endif | |
#ifdef cNOTICE4 | |
notice(s_CTCPServ, u->nick, "%s", cNOTICE4); | |
#endif | |
#ifdef cNOTICE5 | |
notice(s_CTCPServ, u->nick, "%s", cNOTICE5); | |
#endif | |
#ifdef cNOTICE6 | |
notice(s_CTCPServ, u->nick, "%s", cNOTICE6); | |
#endif | |
if (cTAKEACTION == 1) { | |
if (cAKILLTIMEINSECONDS < 60) { | |
/* 15 mins */ | |
cAKILLTIMEINSECONDS = 90; | |
} | |
sprintf(akillmask, "*@%s", u->host); | |
if ((cDONTUSEKILLCONESTIME == 1) || (!(KillClonesAkillExpires))) { | |
add_akill(NULL, akillmask, s_CTCPServ, time(NULL) + cAKILLTIMEINSECONDS, cAKILLREASON); | |
if (CTCPServLOGLEV > 0) { | |
alog("AKILLING: %s -- *@%s [forbidden string in reply]", u->nick, u->host); | |
} | |
} | |
else { | |
add_akill(NULL, akillmask, s_CTCPServ, time(NULL) + KillClonesAkillExpires, cAKILLREASON); | |
if (CTCPServLOGLEV > 0) { | |
alog("AKILLING: %s -- *@%s [forbidden string in reply]", u->nick, u->host); | |
} | |
} | |
if (!AkillOnAdd) { | |
kill_user(s_CTCPServ, u->nick, cKILLREASON); | |
return MOD_STOP; | |
} | |
} | |
else { | |
if (CTCPServLOGLEV > 0) { | |
alog("KILLING: %s (%s) [forbidden string in reply]", u->nick, u->host); | |
} | |
kill_user(s_CTCPServ, u->nick, cKILLREASON); | |
return MOD_STOP; | |
} | |
return MOD_STOP; | |
} | |
int my_ctcpserv_killrejoin(char *source, int ac, char **av) | |
{ | |
if (ac != 2) { | |
return MOD_STOP; | |
} | |
if (stricmp(av[0], s_CTCPServ) == 0) { | |
if (CTCPServLOGLEV > 1) { | |
alog("[ircd_ctcpversion] %s got KILLED, rejoining.", s_CTCPServ); | |
} | |
send_cmd(s_CTCPServ, "QUIT :Rejoin on kill loop protection."); | |
NEWNICK(s_CTCPServ, s_CTCPServ, s_CTCPServHOST, s_CTCPServREALNAME, "+ioS", 1); | |
return MOD_STOP; | |
} | |
return MOD_CONT; | |
} | |
#ifdef ACTION_NO_REPLY_USERS | |
static int del_entry(CTCPU *fc) | |
{ | |
if (fc->next) { | |
fc->next->prev = fc->prev; | |
} | |
if (fc->prev) { | |
fc->prev->next = fc->next; | |
} | |
else { | |
ctcpuhash[tolower(*fc->nick)] = fc->next; | |
} | |
ctcpunum--; | |
if (fc->nick) { | |
free(fc->nick); | |
} | |
if (fc->uid) { | |
free(fc->uid); | |
} | |
free(fc); | |
return 1; | |
} | |
CTCPU *find_ctcpu_entry(char *nick) | |
{ | |
CTCPU *fc; | |
if (!nick || !*nick || !ctcpunum) { | |
return NULL; | |
} | |
for (fc = ctcpuhash[tolower(*nick)]; fc; fc = fc->next) { | |
if (!stricmp(nick, fc->nick) || !stricmp(nick, fc->uid)) { | |
return fc; | |
} | |
} | |
return NULL; | |
} | |
static CTCPU *create_entry(char *nick, char *uid) | |
{ | |
CTCPU *fc; | |
fc = scalloc(sizeof(CTCPU), 1); | |
if (fc == NULL) { | |
alog("[ircd_ctcpversion] WARNING: COULD NOT ADD CHANNEL FREEZE RECORD! [Out of memory?]"); | |
return NULL; | |
} | |
fc->nick = sstrdup(nick); | |
fc->uid = sstrdup(uid); | |
fc->time = time(NULL); | |
add_entry(fc); | |
ctcpunum++; | |
return fc; | |
} | |
int is_ctcpexempt(User *u) | |
{ | |
int i, ret = 0; | |
char *buf, *buf2 = NULL; | |
buf = scalloc(strlen(u->username) + strlen(u->host) + 2, 1); | |
sprintf(buf, "%s@%s", u->username, u->host); | |
if (ircd->vhost) { | |
if (u->vhost) { | |
buf2 = scalloc(strlen(u->username) + strlen(u->vhost) + 2, 1); | |
sprintf(buf2, "%s@%s", u->username, u->vhost); | |
} | |
} | |
for (i = 0; i < CTCPExemptsNum; i++) { | |
if (strchr(CTCPExemptsList[i], '@') != NULL) { | |
if (match_wild_nocase(CTCPExemptsList[i], buf) || (ircd->vhost ? match_wild_nocase(CTCPExemptsList[i], buf2) : 0)) { | |
ret = 1; | |
} | |
} else { | |
if (match_wild_nocase(CTCPExemptsList[i], u->realname)) { | |
ret = 1; | |
} | |
} | |
} | |
free(buf); | |
if (ircd->vhost) { | |
free(buf2); | |
} | |
return ret; | |
} | |
static void add_entry(CTCPU *fc) | |
{ | |
CTCPU *next, *prev; | |
for (prev = NULL, next = ctcpuhash[tolower(*fc->nick)]; | |
next != NULL && stricmp(next->nick, fc->nick) < 0; | |
prev = next, next = next->next); | |
fc->prev = prev; | |
fc->next = next; | |
if (!prev) { | |
ctcpuhash[tolower(*fc->nick)] = fc; | |
} | |
else { | |
prev->next = fc; | |
} | |
if (next) { | |
next->prev = fc; | |
} | |
return; | |
} | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment