Index: ircd/m_join.c =================================================================== --- ircd/m_join.c (revision 1907) +++ ircd/m_join.c (working copy) @@ -254,6 +254,7 @@ } joinbuf_join(&join, chptr, flags); + cli_last_join_time(sptr) = CurrentTime; if (flags & CHFL_CHANOP) { struct ModeBuf mbuf; /* Always let the server op him: this is needed on a net with older servers Index: ircd/channel.c =================================================================== --- ircd/channel.c (revision 1907) +++ ircd/channel.c (working copy) @@ -3594,6 +3594,69 @@ return 0; } +/* check_spambot_warning() + * + * inputs - Client to check, channel name or NULL if this is a part. + * output - NONE + * side effects - Updates the client's oper_warn_count_down, warns the + * IRC operators if necessary, and updates + * join_leave_countdown as needed. + */ +void +check_spambot_warning(struct Client *source_p, const char *name) +{ + time_t t_delta; + int decrement_count; + + if (source_p->join_leave_count >= SPAM_NUM) + { + if (source_p->oper_warn_count_down > 0) + source_p->oper_warn_count_down--; + else + source_p->oper_warn_count_down = 0; + if (source_p->oper_warn_count_down == 0) + { + /* Its already known as a possible spambot */ + if (name != NULL) + sendto_opmask_butone(0, SNO_OLDSNO, + "User %s (%s@%s) trying to join %s is a possible spambot", + cli_name(source_p), cli_username(source_p), + cli_sockhost(source_p), name); + else + sendto_opmask_butone(0, SNO_OLDSNO, + "User %s (%s@%s) is a possible spambot", + cli_name(source_p), cli_username(source_p), + cli_sockhost(source_p)); + + cli_oper_warn_count_down(source_p) = OPER_SPAM_COUNTDOWN; + } + } + else + { + if ((t_delta = (CurrentTime - source_p->last_leave_time)) > + JOIN_LEAVE_COUNT_EXPIRE_TIME) + { + decrement_count = (t_delta / JOIN_LEAVE_COUNT_EXPIRE_TIME); + if (decrement_count > source_p->join_leave_count) + source_p->join_leave_count = 0; + else + source_p->join_leave_count -= decrement_count; + } + else + { + if ((CurrentTime - (source_p->last_join_time)) < SPAM_TIME) + { + /* oh, its a possible spambot */ + source_p->join_leave_count++; + } + } + if (name != NULL) + cli_last_join_time(source_p) = CurrentTime; + else + cli_last_leave_time(source_p) = CurrentTime; + } +} + /* Returns TRUE (1) if client is invited, FALSE (0) if not */ int IsInvited(struct Client* cptr, const void* chptr) { Index: ircd/m_part.c =================================================================== --- ircd/m_part.c (revision 1907) +++ ircd/m_part.c (working copy) @@ -150,6 +150,8 @@ if (IsDelayedJoin(member)) flags |= CHFL_DELAYED; + if (!IsOper(sptr)) + check_spambot_warning(sptr, NULL); joinbuf_join(&parts, chptr, flags); /* part client from channel */ } Index: include/channel.h =================================================================== --- include/channel.h (revision 1907) +++ include/channel.h (working copy) @@ -449,4 +449,40 @@ extern int apply_ban(struct Ban **banlist, struct Ban *newban, int free); extern void free_ban(struct Ban *ban); +/* ANTISPAM join/part bot code. + * + * You might want to make these tweakable with an oper command + * Or move them into config.h + * + * - Dianora + */ +/* Minimum length of time on a channel that a client has to be on + * before its not considered a possible spam bot. + */ +#define MIN_JOIN_LEAVE_TIME 60 +/* So opers don't get overly spammed about spambots, only warn + * every OPER_SPAM_COUNTDOWN times. You could remove this code. + */ +#define OPER_SPAM_COUNTDOWN 5 +/* After a client leaves, we zero the counters after this length + * of time. i.e. if a client is well behaved, we simply zero. + */ +#define JOIN_LEAVE_COUNT_EXPIRE_TIME 120 + +/* These are leftovers from hybrids /quote set, for now I have + * left them in. You can remove as you wish. + */ +#define MIN_SPAM_NUM 5 +#define MIN_SPAM_TIME 60 +/* This is a leftover from hybrids /quote set system. + */ +#define MAX_JOIN_LEAVE_COUNT 25 + +/* You will really want to tweak these, but these aren't bad if + * they have to be statically defined. + */ +#define SPAM_TIME MIN_JOIN_LEAVE_TIME +#define SPAM_NUM MIN_SPAM_NUM + +extern void check_spambot_warning(struct Client *source_p, const char *name); #endif /* INCLUDED_channel_h */ Index: include/client.h =================================================================== --- include/client.h (revision 1907) +++ include/client.h (working copy) @@ -258,6 +258,16 @@ char cli_name[HOSTLEN + 1]; /**< Unique name of the client, nick or host */ char cli_username[USERLEN + 1]; /**< Username determined by ident lookup */ char cli_info[REALLEN + 1]; /**< Free form additional client information */ + + /* Anti flooding part, all because of lamers... */ + time_t last_join_time; /* when this client last + joined a channel */ + time_t last_leave_time; /* when this client last + * left a channel */ + int join_leave_count; /* count of JOIN/LEAVE in less than + MIN_JOIN_LEAVE_TIME seconds */ + int oper_warn_count_down; /* warn opers of this possible + spambot every time this gets to 0 */ }; /** Magic constant to identify valid Client structures. */ @@ -736,5 +746,13 @@ extern void client_set_privs(struct Client *client, struct ConfItem *oper); extern int client_report_privs(struct Client* to, struct Client* client); +/* ANTISPAM bot patch + * - Dianora + */ +#define cli_last_join_time(cli) ((cli)->last_join_time) +#define cli_last_leave_time(cli) ((cli)->last_leave_time) +#define cli_join_leave_count(cli) ((cli)->join_leave_count) +#define cli_oper_warn_count_down(cli) ((cli)->oper_warn_count_down) + #endif /* INCLUDED_client_h */