X-Git-Url: http://git.pk910.de/?a=blobdiff_plain;f=src%2Fmod-watchdog.c;h=0edf09dfb5cec806111b9e91cf6809ab70f38d03;hb=95ca19dd93fa5ef8d8756d0ef0ec1c39fe398650;hp=e62bcd003156df78c685472dabfcb3eadaeb59c8;hpb=bff6cf147150876f31e25b51c8659324bbc0a1d2;p=srvx.git diff --git a/src/mod-watchdog.c b/src/mod-watchdog.c index e62bcd0..0edf09d 100644 --- a/src/mod-watchdog.c +++ b/src/mod-watchdog.c @@ -43,11 +43,13 @@ #define KEY_BADWORD_MASK "mask" #define KEY_BADWORD_TRIGGERED "count" #define KEY_BADWORD_ACTION "action" +#define KEY_BADWOR_ALERT "alert" #define KEY_CHANNELS "channel" #define KEY_BADWORDID "badwordid" static const struct message_entry msgtab[] = { { "WDMSG_REGISTER_SUCCESS", "$b%s$b is now registered with %s." }, + { "WDMSG_UNREG_SUCCESS", "$b%s$b is now unregistered." }, { "WDMSG_NOT_REGISTERED", "$b%s$b is not registered with %s." }, { "WDMSG_ALREADY_ADDED", "$b%s$b is already added. (ID: %s)" }, { "WDMSG_BADWORD_ADDED", "added '$b%s$b' to the badword list with ID %s." }, @@ -59,6 +61,7 @@ static const struct message_entry msgtab[] = { { "WDMSG_BADWORD_SET", "Settings for BadWord entry $b%s$b" }, { "WDMSG_BADWORD_SET_MASK", "$bMASK$b: %s" }, { "WDMSG_BADWORD_SET_ACTION", "$bACTION$b: %s" }, + { "WDMSG_BADWORD_SET_ALERT", "$bALERT$b: %d" }, { NULL, NULL } }; @@ -67,6 +70,7 @@ struct badword { char *badword_mask; unsigned int triggered : 29; unsigned int action : 3; + unsigned int alert; }; struct watchdog_channel { @@ -80,12 +84,18 @@ struct watchdog_channel { #define BADACTION_KILL 2 #define BADACTION_GLINE 3 +#define WDMSG_BADWORD_ALERT "%s used badword '%s' in channel: %s." +#define WDMSG_REGISTER_SUCCESS "$b%s$b is now registered with %s by %s." +#define WDMSG_UNREG_SUCCESS "$b%s$b is now unregistered by %s." + static struct { const char *nick; const char *modes; const char *punishment_reason; unsigned long ban_duration; unsigned long gline_duration; + struct chanNode *alert_channel; + struct chanNode *oper_channel; } watchdog_conf; const char *watchdog_module_deps[] = { NULL }; @@ -98,8 +108,10 @@ static struct log_type *MS_LOG; static unsigned int last_badword_id = 0; static struct watchdog_channel *add_channel(const char *name); -static struct badword *add_badword(const char *badword_mask, unsigned int triggered, unsigned int action, const char *id); +static struct badword *add_badword(const char *badword_mask, unsigned int triggered, unsigned int action, unsigned int alert, const char *id); #define watchdog_notice(target, format...) send_message(target , watchdog , ## format) +#define watchdog_debug(format...) do { if(watchdog_conf.alert_channel) send_channel_message(watchdog_conf.alert_channel , watchdog , ## format); } while(0) +#define watchdog_oper_message(format...) do { if(watchdog_conf.oper_channel) send_channel_message(watchdog_conf.oper_channel , watchdog , ## format); } while(0) static MODCMD_FUNC(cmd_addbad) { @@ -113,7 +125,7 @@ static MODCMD_FUNC(cmd_addbad) } } - struct badword *new_badword = add_badword(mask, 0, BADACTION_KICK, NULL); + struct badword *new_badword = add_badword(mask, 0, BADACTION_KICK, 0, NULL); for (it = dict_first(shitlist); it; it = iter_next(it)) { struct badword *badword = iter_data(it); if(match_ircglob(badword->badword_mask, new_badword->badword_mask) && badword != new_badword) { @@ -175,6 +187,17 @@ static MODCMD_FUNC(cmd_setbad) } else { reply("WDMSG_BADWORD_SET_INVALID", setting); } + } + else if(!strcmp("ALERT",setting)) { + if (!strcmp("0",value)) { + badword->alert = 0; + reply("WDMSG_BADWORD_SET_DONE"); + } else if (!strcmp("1",value)) { + badword->alert = 1; + reply("WDMSG_BADWORD_SET_DONE"); + } else { + reply("WDMSG_BADWORD_SET_INVALID", setting); + } } else { reply("WDMSG_BADWORD_SETTING_INVALID", setting); } @@ -198,6 +221,7 @@ static MODCMD_FUNC(cmd_setbad) default: reply("WDMSG_BADWORD_SET_ACTION", "*undef*"); } + reply("WDMSG_BADWORD_SET_ALERT", badword->alert); } } else { reply("WDMSG_BADWORD_NOT_FOUND", argv[1]); @@ -226,7 +250,7 @@ static MODCMD_FUNC(cmd_listbad) count++; } tbl.length = count+1; - tbl.width = 4; + tbl.width = 5; tbl.flags = 0; tbl.flags = TABLE_NO_FREE; tbl.contents = malloc(tbl.length * sizeof(tbl.contents[0])); @@ -235,6 +259,7 @@ static MODCMD_FUNC(cmd_listbad) tbl.contents[0][1] = "Badword"; tbl.contents[0][2] = "Action"; tbl.contents[0][3] = "(Triggered)"; + tbl.contents[0][4] = "Alert"; if(!count) { table_send(cmd->parent->bot, user->nick, 0, NULL, tbl); @@ -271,6 +296,7 @@ static MODCMD_FUNC(cmd_listbad) tbl.contents[ii][2] = "*undef*"; } tbl.contents[ii][3] = strtab(bw->triggered); + tbl.contents[ii][4] = strtab(bw->alert); } table_send(cmd->parent->bot, user->nick, 0, NULL, tbl); for(ii = 1; ii < tbl.length; ++ii) @@ -285,20 +311,42 @@ static MODCMD_FUNC(cmd_listbad) static MODCMD_FUNC(cmd_register) { dict_iterator_t it; + struct modeNode *mn; - if((argc < 2) || !IsChannelName(argv[1])) + if(channel) { - reply("MSG_NOT_CHANNEL_NAME"); - return 0; - } - if(opserv_bad_channel(argv[1])) - { - reply("CSMSG_ILLEGAL_CHANNEL", argv[1]); - return 0; + if(channel->bad_channel) + { + reply("CSMSG_ILLEGAL_CHANNEL", channel->name); + return 0; + } + + if(!IsHelping(user) + && (!(mn = GetUserMode(channel, user)) || !(mn->modes & MODE_CHANOP))) + { + reply("CSMSG_MUST_BE_OPPED", channel->name); + return 0; + } + } + else + { - channel = AddChannel(argv[1], now, NULL, NULL); + if((argc < 2) || !IsChannelName(argv[1])) + { + reply("MSG_NOT_CHANNEL_NAME"); + return 0; + } + + if(opserv_bad_channel(argv[1])) + { + reply("CSMSG_ILLEGAL_CHANNEL", argv[1]); + return 0; + } + + channel = AddChannel(argv[1], now, NULL, NULL); + } for (it = dict_first(chanlist); it; it = iter_next(it)) { struct watchdog_channel *chan = iter_data(it); @@ -310,6 +358,7 @@ static MODCMD_FUNC(cmd_register) add_channel(channel->name); reply("WDMSG_REGISTER_SUCCESS", channel->name, watchdog->nick); + watchdog_oper_message(WDMSG_REGISTER_SUCCESS, channel->name, watchdog->nick, user->handle_info->handle); return 1; } @@ -326,9 +375,12 @@ static MODCMD_FUNC(cmd_unregister) if(chan && chan->channel == channel) { //found, unregister it! - DelChannelUser(watchdog, channel, "unregistered.", 0); + char reason[MAXLEN]; + sprintf(reason, "Unregistered by %s.", user->handle_info->handle); + DelChannelUser(watchdog, channel, reason, 0); dict_remove(chanlist, channel->name); reply("CSMSG_UNREG_SUCCESS", channel->name); + watchdog_oper_message(WDMSG_UNREG_SUCCESS, channel->name, user->handle_info->handle); return 1; } else { reply("WDMSG_NOT_REGISTERED", channel->name, watchdog->nick); @@ -343,36 +395,43 @@ watchdog_detected_badword(struct userNode *user, struct chanNode *chan, struct b char *hostmask; char *reason = watchdog_conf.punishment_reason; char mask[IRC_NTOP_MAX_SIZE+3] = { '*', '@', '\0' }; - switch(badword->action) { - case BADACTION_BAN: - hostmask = generate_hostmask(user, GENMASK_STRICT_HOST | GENMASK_ANY_IDENT); - sanitize_ircmask(hostmask); - if(chan->channel_info) { - //registered channel - add_channel_ban(chan->channel_info, hostmask, watchdog->nick, now, now, now + watchdog_conf.ban_duration, reason); - } - struct mod_chanmode change; - mod_chanmode_init(&change); - change.argc = 1; - change.args[0].mode = MODE_BAN; - change.args[0].u.hostmask = hostmask; - mod_chanmode_announce(watchdog, chan, &change); - free(hostmask); - - case BADACTION_KICK: - KickChannelUser(user, chan, watchdog, reason); - break; - case BADACTION_KILL: - DelUser(user, watchdog, 1, reason); - break; - case BADACTION_GLINE: - irc_ntop(mask + 2, sizeof(mask) - 2, &user->ip); - gline_add(watchdog->nick, mask, watchdog_conf.gline_duration, reason, now, now, 0, 1); - break; - default: - //error? - break; - } + if(!IsOper(user)) { + if(badword->alert == 1) { + log_module(MS_LOG, LOG_WARNING, "%s used badword '%s' in channel: %s", user->nick, badword->badword_mask, chan->name); + watchdog_debug(WDMSG_BADWORD_ALERT, user->nick, badword->badword_mask, chan->name); + } + switch(badword->action) { + case BADACTION_BAN: + hostmask = generate_hostmask(user, GENMASK_STRICT_HOST | GENMASK_ANY_IDENT); + sanitize_ircmask(hostmask); + if(chan->channel_info) { + //registered channel + add_channel_ban(chan->channel_info, hostmask, watchdog->nick, now, now, now + watchdog_conf.ban_duration, reason); + } + struct mod_chanmode change; + mod_chanmode_init(&change); + change.argc = 1; + change.args[0].mode = MODE_BAN; + change.args[0].u.hostmask = hostmask; + mod_chanmode_announce(watchdog, chan, &change); + free(hostmask); + + case BADACTION_KICK: + if(GetUserMode(chan, user)) + KickChannelUser(user, chan, watchdog, reason); + break; + case BADACTION_KILL: + DelUser(user, watchdog, 1, reason); + break; + case BADACTION_GLINE: + irc_ntop(mask + 2, sizeof(mask) - 2, &user->ip); + gline_add(watchdog->nick, mask, watchdog_conf.gline_duration, reason, now, now, 0, 1); + break; + default: + //error? + break; + } + } } static void @@ -380,7 +439,7 @@ watchdog_channel_message(struct userNode *user, struct chanNode *chan, const cha { dict_iterator_t it; - if(!watchdog) + if(!watchdog || !dict_find(chanlist, chan->name, NULL)) return; for (it = dict_first(shitlist); it; it = iter_next(it)) { @@ -392,7 +451,7 @@ watchdog_channel_message(struct userNode *user, struct chanNode *chan, const cha } static struct badword* -add_badword(const char *badword_mask, unsigned int triggered, unsigned int action, const char *id) +add_badword(const char *badword_mask, unsigned int triggered, unsigned int action, unsigned int alert, const char *id) { struct badword *badword; @@ -408,6 +467,7 @@ add_badword(const char *badword_mask, unsigned int triggered, unsigned int actio badword->badword_mask = strdup(badword_mask); badword->triggered = triggered; badword->action = action; + badword->alert = alert; dict_insert(shitlist, badword->id, badword); return badword; } @@ -482,7 +542,26 @@ watchdog_conf_read(void) str = database_get_data(conf_node, "punishment_reason", RECDB_QSTRING); watchdog_conf.punishment_reason = (str ? str : "Your message contained a forbidden word."); + + str = database_get_data(conf_node, "alert_chan", RECDB_QSTRING); + if(str) + { + watchdog_conf.alert_channel = AddChannel(str, now, "+tinms", NULL); + } + else + { + watchdog_conf.alert_channel = NULL; + } + str = database_get_data(conf_node, "oper_channel", RECDB_QSTRING); + if(str) + { + watchdog_conf.oper_channel = AddChannel(str, now, "+tinms", NULL); + } + else + { + watchdog_conf.oper_channel = NULL; + } } static int @@ -490,7 +569,7 @@ watchdog_saxdb_read_shitlist(const char *name, void *data, UNUSED_ARG(void *extr { struct record_data *rd = data; char *badword; - char *triggered, *action; + char *triggered, *action, *alert; if (rd->type == RECDB_OBJECT) { dict_t obj = GET_RECORD_OBJECT(rd); @@ -498,8 +577,9 @@ watchdog_saxdb_read_shitlist(const char *name, void *data, UNUSED_ARG(void *extr badword = database_get_data(obj, KEY_BADWORD_MASK, RECDB_QSTRING); triggered = database_get_data(obj, KEY_BADWORD_TRIGGERED, RECDB_QSTRING); action = database_get_data(obj, KEY_BADWORD_ACTION, RECDB_QSTRING); + alert = database_get_data(obj, KEY_BADWOR_ALERT, RECDB_QSTRING); - add_badword(badword, strtoul(triggered, NULL, 0), strtoul(action, NULL, 0), name); + add_badword(badword, strtoul(triggered, NULL, 0), strtoul(action, NULL, 0), strtoul(alert, NULL, 0), name); } return 0; } @@ -546,13 +626,16 @@ watchdog_saxdb_write(struct saxdb_context *ctx) saxdb_start_record(ctx, KEY_BADWORDS, 1); for (it = dict_first(shitlist); it; it = iter_next(it)) { struct badword *badword = iter_data(it); - saxdb_start_record(ctx, iter_key(it), 0); - - saxdb_write_string(ctx, KEY_BADWORD_MASK, badword->badword_mask); - saxdb_write_int(ctx, KEY_BADWORD_TRIGGERED, badword->triggered); - saxdb_write_int(ctx, KEY_BADWORD_ACTION, badword->action); - - saxdb_end_record(ctx); + if(badword && badword->badword_mask) { + saxdb_start_record(ctx, iter_key(it), 0); + + saxdb_write_string(ctx, KEY_BADWORD_MASK, badword->badword_mask); + saxdb_write_int(ctx, KEY_BADWORD_TRIGGERED, badword->triggered); + saxdb_write_int(ctx, KEY_BADWORD_ACTION, badword->action); + saxdb_write_int(ctx, KEY_BADWOR_ALERT, badword->alert); + + saxdb_end_record(ctx); + } } saxdb_end_record(ctx); } @@ -561,9 +644,11 @@ watchdog_saxdb_write(struct saxdb_context *ctx) saxdb_start_record(ctx, KEY_CHANNELS, 1); for (it = dict_first(chanlist); it; it = iter_next(it)) { struct watchdog_channel *wc = iter_data(it); - saxdb_start_record(ctx, wc->channel->name, 0); - //anything else? - saxdb_end_record(ctx); + if(wc && wc->channel && wc->channel->name) { + saxdb_start_record(ctx, wc->channel->name, 0); + //anything else? + saxdb_end_record(ctx); + } } saxdb_end_record(ctx); } @@ -610,7 +695,7 @@ watchdog_init(void) modcmd_register(watchdog_module, "delbad", cmd_delbad, 2, MODCMD_REQUIRE_AUTHED, "flags", "+oper", NULL); modcmd_register(watchdog_module, "setbad", cmd_setbad, 2, MODCMD_REQUIRE_AUTHED, "flags", "+oper", NULL); modcmd_register(watchdog_module, "listbad", cmd_listbad, 1, MODCMD_REQUIRE_AUTHED, "flags", "+oper", NULL); - modcmd_register(watchdog_module, "register", cmd_register, 2, MODCMD_REQUIRE_AUTHED, "flags", "+helping", NULL); + modcmd_register(watchdog_module, "register", cmd_register, 1, MODCMD_REQUIRE_AUTHED, "flags", "+acceptchan,+helping", NULL); modcmd_register(watchdog_module, "unregister", cmd_unregister, 1, MODCMD_REQUIRE_AUTHED | MODCMD_REQUIRE_CHANNEL, "flags", "+helping", NULL); message_register_table(msgtab);