]> jfr.im git - irc/evilnet/x3.git/blobdiff - src/opserv.c
This should fix the nickserv module complaining about not enough parameters when...
[irc/evilnet/x3.git] / src / opserv.c
index 88fb61d6c7154b8796bb61e1f23c7c310591d68c..71fa774f5f47d2707807fa7ebd457bb25b9af735 100644 (file)
@@ -369,6 +369,7 @@ typedef struct opservDiscrim {
     unsigned int match_opers : 1, option_log : 1;
     unsigned int chan_req_modes : 2, chan_no_modes : 2;
     int authed : 2, info_space : 2;
+    unsigned int intra_scmp : 2, intra_dcmp : 2;
     time_t min_ts, max_ts;
     unsigned int use_regex : 1;
 } *discrim_t;
@@ -389,6 +390,7 @@ static int ungag_helper_func(struct userNode *match, void *extra);
 typedef enum {
     REACT_NOTICE,
     REACT_KILL,
+    REACT_SILENT,
     REACT_GLINE,
     REACT_SHUN
 } opserv_alert_reaction;
@@ -864,7 +866,7 @@ static MODCMD_FUNC(cmd_restart)
 }
 
 static struct gline *
-opserv_block(struct userNode *target, char *src_handle, char *reason, unsigned long duration)
+opserv_block(struct userNode *target, char *src_handle, char *reason, unsigned long duration, int silent)
 {
     char *mask;
     mask = alloca(MAXLEN);
@@ -874,7 +876,7 @@ opserv_block(struct userNode *target, char *src_handle, char *reason, unsigned l
         snprintf(reason, MAXLEN, "G-line requested by %s.", src_handle);
     }
     if (!duration) duration = opserv_conf.block_gline_duration;
-    return gline_add(src_handle, mask, duration, reason, now, 1);
+    return gline_add(src_handle, mask, duration, reason, now, 1, silent ? 1 : 0);
 }
 
 static MODCMD_FUNC(cmd_block)
@@ -893,7 +895,7 @@ static MODCMD_FUNC(cmd_block)
         return 0;
     }
     reason = (argc > 2) ? unsplit_string(argv+2, argc-2, NULL) : NULL;
-    gline = opserv_block(target, user->handle_info->handle, reason, 0);
+    gline = opserv_block(target, user->handle_info->handle, reason, 0, 0);
     reply("OSMSG_GLINE_ISSUED", gline->target);
     return 1;
 }
@@ -918,7 +920,7 @@ static MODCMD_FUNC(cmd_gline)
         reply("MSG_INVALID_DURATION", argv[2]);
         return 0;
     }
-    gline = gline_add(user->handle_info->handle, argv[1], duration, reason, now, 1);
+    gline = gline_add(user->handle_info->handle, argv[1], duration, reason, now, 1, 0);
     reply("OSMSG_GLINE_ISSUED", gline->target);
     return 1;
 }
@@ -1801,6 +1803,7 @@ static MODCMD_FUNC(cmd_stats_alerts) {
         switch (alert->reaction) {
         case REACT_NOTICE: reaction = "notice"; break;
         case REACT_KILL: reaction = "kill"; break;
+        case REACT_SILENT: reaction = "silent"; break;
         case REACT_GLINE: reaction = "gline"; break;
         case REACT_SHUN: reaction = "shun"; break;
         default: reaction = "<unknown>"; break;
@@ -2062,7 +2065,7 @@ opserv_new_user_check(struct userNode *user)
         } else if (ohi->clients.used > limit) {
             char target[18];
             sprintf(target, "*@%s", inet_ntoa(user->ip));
-            gline_add(opserv->nick, target, opserv_conf.clone_gline_duration, "AUTO Excessive connections from a single host.", now, 1);
+            gline_add(opserv->nick, target, opserv_conf.clone_gline_duration, "Excessive connections from a single host.", now, 1, 1);
         }
     }
 
@@ -2755,6 +2758,8 @@ foreach_matching_user(const char *hostmask, discrim_search_func func, void *extr
     discrim->max_channels = INT_MAX;
     discrim->authed = -1;
     discrim->info_space = -1;
+    discrim->intra_scmp = 0;
+    discrim->intra_dcmp = 0;
     discrim->use_regex = 0;
     dupmask = strdup(hostmask);
     if (split_ircmask(dupmask, &discrim->mask_nick, &discrim->mask_ident, &discrim->mask_host)) {
@@ -2920,6 +2925,8 @@ add_user_alert(const char *key, void *data, UNUSED_ARG(void *extra))
         reaction = REACT_NOTICE;
     else if (!irccasecmp(react, "kill"))
         reaction = REACT_KILL;
+    else if (!irccasecmp(react, "silent"))
+        reaction = REACT_SILENT;
     else if (!irccasecmp(react, "gline"))
         reaction = REACT_GLINE;
     else if (!irccasecmp(react, "shun"))
@@ -3110,6 +3117,7 @@ opserv_saxdb_write(struct saxdb_context *ctx)
             switch (alert->reaction) {
             case REACT_NOTICE: reaction = "notice"; break;
             case REACT_KILL: reaction = "kill"; break;
+            case REACT_SILENT: reaction = "silent"; break;
             case REACT_GLINE: reaction = "gline"; break;
             case REACT_SHUN: reaction = "shun"; break;
             default:
@@ -3226,6 +3234,8 @@ opserv_discrim_create(struct userNode *user, struct userNode *bot, unsigned int
     discrim->max_channels = INT_MAX;
     discrim->authed = -1;
     discrim->info_space = -1;
+    discrim->intra_dcmp = 0;
+    discrim->intra_scmp = 0;
 
     for (i=0; i<argc; i++) {
         if (irccasecmp(argv[i], "log") == 0) {
@@ -3237,6 +3247,18 @@ opserv_discrim_create(struct userNode *user, struct userNode *bot, unsigned int
             send_message(user, bot, "MSG_MISSING_PARAMS", argv[i]);
             goto fail;
         }
+        if (argv[i+1][0] == '&') {
+            /* Looking for intra-userNode matches */
+            char *tmp = &(argv[i+1][1]);
+            if (strcasecmp(tmp, argv[i]) != 0) { /* Don't allow "nick &nick" etc */
+                if (!strcasecmp(tmp, "nick"))
+                    discrim->intra_dcmp = 1;
+                else if (!strcasecmp(tmp, "ident"))
+                    discrim->intra_dcmp = 2;
+                else if (!strcasecmp(tmp, "info"))
+                    discrim->intra_dcmp = 3;
+            }
+        }
         if (irccasecmp(argv[i], "mask") == 0) {
             if (!is_ircmask(argv[++i])) {
                 send_message(user, bot, "OSMSG_INVALID_IRCMASK", argv[i]);
@@ -3250,13 +3272,25 @@ opserv_discrim_create(struct userNode *user, struct userNode *bot, unsigned int
                 goto fail;
             }
         } else if (irccasecmp(argv[i], "nick") == 0) {
-            discrim->mask_nick = argv[++i];
+            i++;
+            if (discrim->intra_dcmp > 0)
+                discrim->intra_scmp = 1;
+           else
+                discrim->mask_nick = argv[i];
         } else if (irccasecmp(argv[i], "ident") == 0) {
-            discrim->mask_ident = argv[++i];
+            i++;
+            if (discrim->intra_dcmp > 0)
+                discrim->intra_scmp = 2;
+           else
+                discrim->mask_ident = argv[i];
         } else if (irccasecmp(argv[i], "host") == 0) {
             discrim->mask_host = argv[++i];
         } else if (irccasecmp(argv[i], "info") == 0) {
-            discrim->mask_info = argv[++i];
+            i++;
+            if (discrim->intra_dcmp > 0)
+                discrim->intra_scmp = 3;
+           else
+                discrim->mask_info = argv[i];
         } else if (irccasecmp(argv[i], "server") == 0) {
             discrim->server = argv[++i];
         } else if (irccasecmp(argv[i], "ip") == 0) {
@@ -3502,6 +3536,7 @@ static int
 discrim_match(discrim_t discrim, struct userNode *user)
 {
     unsigned int access;
+    char *scmp=NULL, *dcmp=NULL;
 
     if ((user->timestamp < discrim->min_ts)
         || (user->timestamp > discrim->max_ts)
@@ -3536,6 +3571,31 @@ discrim_match(discrim_t discrim, struct userNode *user)
         }
     }
 
+    if ((discrim->intra_scmp > 0 && discrim->intra_dcmp > 0)) {
+       switch(discrim->intra_scmp) {
+            case 1: scmp=user->nick; break;
+            case 2: scmp=user->ident; break;
+            case 3: 
+                scmp=user->info; 
+                if (discrim->info_space == 1) scmp++;
+                break;
+        }
+        switch(discrim->intra_dcmp) {
+            case 1: dcmp=user->nick; break;
+            case 2: dcmp=user->ident; break;
+            case 3: /* When checking INFO, and info_space is enabled
+                     * ignore the first character in a search 
+                     * XXX: Should we ignore ALL leading whitespace?
+                     *      Also, what about ignoring ~ in ident?
+                     */
+                dcmp=user->info; 
+                if (discrim->info_space == 1) dcmp++;
+                break;
+        }
+        if (irccasecmp(scmp,dcmp))
+            return 0;
+    }
+
     if (discrim->channel && !GetUserMode(discrim->channel, user)) return 0;
     access = user->handle_info ? user->handle_info->opserv_level : 0;
     if ((access < discrim->min_level)
@@ -3654,7 +3714,7 @@ trace_gline_func(struct userNode *match, void *extra)
     struct discrim_and_source *das = extra;
 
     if (is_oper_victim(das->source, match, das->discrim->match_opers)) {
-        opserv_block(match, das->source->handle_info->handle, das->discrim->reason, das->discrim->duration);
+        opserv_block(match, das->source->handle_info->handle, das->discrim->reason, das->discrim->duration, 0);
     }
 
     return 0;
@@ -4283,8 +4343,11 @@ alert_check_user(const char *key, void *data, void *extra)
     case REACT_KILL:
         DelUser(user, opserv, 1, alert->discrim->reason);
         return 1;
+    case REACT_SILENT:
+        opserv_block(user, alert->owner, alert->discrim->reason, alert->discrim->duration, 1);
+        return 1;
     case REACT_GLINE:
-        opserv_block(user, alert->owner, alert->discrim->reason, alert->discrim->duration);
+        opserv_block(user, alert->owner, alert->discrim->reason, alert->discrim->duration, 0);
         return 1;
     case REACT_SHUN:
         opserv_shun(user, alert->owner, alert->discrim->reason, alert->discrim->duration);
@@ -4452,6 +4515,8 @@ static MODCMD_FUNC(cmd_addalert)
         reaction = REACT_NOTICE;
     else if (!irccasecmp(argv[2], "kill"))
         reaction = REACT_KILL;
+    else if (!irccasecmp(argv[2], "silent"))
+        reaction = REACT_SILENT;
     else if (!irccasecmp(argv[2], "gline"))
         reaction = REACT_GLINE;
     else if (!irccasecmp(argv[2], "shun"))
@@ -4649,6 +4714,7 @@ init_opserv(const char *nick)
     opserv_define_func("ACCESS", cmd_access, 0, 0, 0);
     opserv_define_func("ADDALERT", cmd_addalert, 800, 0, 4);
     opserv_define_func("ADDALERT NOTICE", NULL, 0, 0, 0);
+    opserv_define_func("ADDALERT SILENT", NULL, 900, 0, 0);
     opserv_define_func("ADDALERT GLINE", NULL, 900, 0, 0);
     opserv_define_func("ADDALERT SHUN", NULL, 900, 0, 0);
     opserv_define_func("ADDALERT KILL", NULL, 900, 0, 0);