]> jfr.im git - irc/evilnet/x3.git/commitdiff
DEFCON System for X3, idea from Anope.. mostly new code however one or 2 functions...
authorsirvulcan <redacted>
Mon, 31 Jul 2006 02:04:55 +0000 (02:04 +0000)
committersirvulcan <redacted>
Mon, 31 Jul 2006 02:04:55 +0000 (02:04 +0000)
ChangeLog
docs/DEFCON [new file with mode: 0644]
src/chanserv.c
src/mod-memoserv.c
src/nickserv.c
src/opserv.c
src/opserv.h
src/opserv.help
src/proto-p10.c
x3.conf.example

index 991a79a307730a419649812fa040d0fadb7f4c51..38ff49b38d13dc3e9fa517e3a49356d5dab72f3d 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,29 @@
 /***********************************************************************
  X3 ChangeLog
 
+2006-07-31  Neil Spierling  <sirvulcan@gmail.com>
+
+       * x3.conf.example: Added new Defcon system settings
+
+       * doc/DEFCON: Anope's Defcon doc adapted for X3.
+
+       * src/chanserv.c: Block mode changes and channel registrations if
+       required.
+
+       * src/mod-memoserv.c: Block new memos if required.
+
+       * src/nickserv.c: Block nick registrations if required.
+
+       * src/opserv.c: Added in defcon system, uses some of the anope code.
+       Most tho is from scratch.
+
+       * src/opserv.h: Defcon declerations.
+
+       * src/opserv.help: Added DEFCON entry.
+
+       * src/proto-p10.c: If required gline new clients, also if required
+       kill new clients.
+
 2006-07-29  Alex Schumann  <rubin@afternet.org>
 
        * configure.in, Makefile.in, src/Makefile.in, tools/tre_install.sh,
diff --git a/docs/DEFCON b/docs/DEFCON
new file mode 100644 (file)
index 0000000..dfe55b9
--- /dev/null
@@ -0,0 +1,124 @@
+X3 DefCon 
+------------
+
+1) Introduction
+2) Installation
+3) Configuration
+4) Usage
+5) Usage Example
+
+1) Introduction
+
+    X3 supports a unique protection mechanism based on the military "Defense
+    Readiness Condition" (DefCon) system. It is based on 5 levels of defense
+    readiness defined as:
+
+    DEFCON5 Normal peacetime readiness
+    DEFCON4 Increased intelligence and security readiness
+    DEFCON3 Increase in force readiness
+    DEFCON2 Further increase in force readiness
+    DEFCON1 Maximum force readiness.
+
+    These are configurable levels that mandates what actions X3 should
+    take in case of emergency and change in readiness status.
+
+    It is used to prevent abuse to both Services, and the ircd on which they 
+    are running. Also to protect the users, primarily in the event of Clones
+    and/or FloodBOT attacks. 
+
+2) Installation
+
+    The DefCon system is part of O3,
+
+    The DefCon system has to be configured on your x3.conf file to
+    be enabled.
+
+    Make sure you restart X3 after changing the DefCon configuration
+    directives.
+
+3) Configuration
+
+    Pre-defined DefCon actions:
+
+    No new channel registrations                       1 
+    No New Nick Registrations                          2 
+    No channel Mode changes                            4 
+    Force Chan Mode                                    8 
+    Use Reduced Session Limit                         16 
+    KILL any new clients trying to connect            32 
+    Services will ignore everyone but opers           64 
+    Services will silently ignore everyone but opers 128 
+    GLINE all new clients trying to connect          256 
+    No new memos sent to block MemoServ attacks      512
+
+    These are the values used to determine each defcon setting, are set via: 
+
+    "DefCon1 "XX";
+    "DefCon2 "XX";
+    "DefCon3 "XX";
+    "DefCon4 "XX";
+
+    To set the desired value, you simply add the value of the numbers together 
+    and place that as your DefCon# setting. For instance:
+
+    Say you wish to set: 
+
+    No Channel Registrations, No Nickname Registrations and Services Ignoring 
+    everyone except for Operators. You would do this by: 
+
+    1 + 2 + 128 (Each value listed above is added together) 
+    Giving: 131 
+
+    You would then place this as which ever Defcon setting you want: 
+    
+    "DefCon1" "131";
+
+    The recommended default values are safe to use on any network.
+
+4) Usage
+
+    X3 starts up in DEFCON5 (normal readiness) by default, this is configurable.
+    To change the Defcon level in action use:
+    
+    /msg O3 DEFCON 1|2|3|4|5
+
+5) Usage Example
+
+    Place the network on DEFCON3:
+
+    /msg O3 DEFCON 3
+
+    <O3> DefCon is at level 3 and enforcing:
+    <O3> No Channel Registrations
+    <O3> No Nickname/Account Registrations
+    <O3> No ChanServ SET MODE Changes
+    <O3> Forcing Channel Mode(s): +r
+    <O3> Forcing Reduced Session: 2
+    <O3> Allowing Services Communication With Opers Only AND Silently Ignoring Regular Users
+    <Global> Network DefCon level has changed to level 3
+    <Global> SiRVulcaN is changing the DefCon level to 3
+
+    Note that the last message is sent to Opers only.
+
+    Restore normal readiness:
+
+    /msg O3 DEFCON 5
+
+    <O3> DefCon is at level 5 and allowing everything
+    <Global> Network DefCon level has changed to level 5
+    <Global> SiRVulcaN is changing the DefCon level to 5
+
+    Note that the last message is sent to Opers only.
+
+    Listing The Currently Set DefCon Settings:
+
+    /msg O3 DEFCON
+
+    <O3> DefCon is at level 3 and enforcing:
+    <O3> No Channel Registrations
+    <O3> No Nickname/Account Registrations
+    <O3> No ChanServ SET MODE Changes
+    <O3> Forcing Channel Mode(s): +r
+    <O3> Forcing Reduced Session: 2
+    <O3> Allowing Services Communication With Opers Only AND Silently Ignoring Regular Users
+
index 29748f3e2dbc8eb3de280278eaa4f41590f817b1..6ff9d5fd2ec334c9381374175c7d591174ac4c8e 100644 (file)
@@ -513,6 +513,8 @@ static const struct message_entry msgtab[] = {
 /* Other things */
     { "CSMSG_EVENT_SEARCH_RESULTS", "$bChannel Events for %s$b" },
     { "CSMSG_LAST_INVALID", "Invalid argument.  must be 1-200" },
+    { "CSMSG_DEFCON_NO_NEW_CHANNELS", "You cannot register new channels at this time, please try again soon." },
+    { "CSMSG_DEFCON_NO_MODE_CHANGE", "You cannot change the MODE at this time, please try again soon." },
     { NULL, NULL }
 };
 
@@ -1963,6 +1965,10 @@ static CHANSERV_FUNC(cmd_register)
     struct do_not_register *dnr;
     unsigned int n;
 
+    if (checkDefCon(DEFCON_NO_NEW_CHANNELS) && !IsOper(user)) {
+        reply("CSMSG_DEFCON_NO_NEW_CHANNELS");
+        return 0;
+    }
 
     if(channel)
     {
@@ -4447,6 +4453,11 @@ static CHANSERV_FUNC(cmd_mode)
     
     if(argc < 2)
     {
+        if (checkDefCon(DEFCON_NO_MODE_CHANGE) && !IsOper(user)) {
+            reply("CSMSG_DEFCON_NO_MODE_CHANGE");
+            return 0;
+        }
+
         change = &channel->channel_info->modes;
        if(change->modes_set || change->modes_clear) {
             modcmd_chanmode_announce(change);
@@ -5750,6 +5761,11 @@ static MODCMD_FUNC(chan_opt_modes)
 
     if(argc > 1)
     {
+        if (checkDefCon(DEFCON_NO_MODE_CHANGE) && !IsOper(user)) {
+            reply("CSMSG_DEFCON_NO_MODE_CHANGE");
+            return 0;
+        }
+
         if(!check_user_level(channel, user, lvlEnfModes, 1, 0))
         {
             reply("CSMSG_NO_ACCESS");
index 8de5874e8880bcd83ba63dfcb109198ad5025717..4c9011f4a38f2e3024c5af7d9d4ae3e8ae931d9b 100644 (file)
@@ -42,6 +42,7 @@
 #include "conf.h"
 #include "modcmd.h"
 #include "nickserv.h"
+#include "opserv.h"
 #include "saxdb.h"
 #include "timeq.h"
 
@@ -108,6 +109,8 @@ static const struct message_entry msgtab[] = {
     { "MSMSG_LIST_END",        "--------------End of Memos--------------" },
     { "MSMSG_BAR",             "----------------------------------------"},
 
+    { "MSMSG_DEFCON_NO_NEW_MEMOS", "You cannot send new memos at this time, please try again soon." },
+
     { NULL, NULL }
 };
 
@@ -401,6 +404,11 @@ static MODCMD_FUNC(cmd_send)
 
     MEMOSERV_MIN_PARAMS(3);
 
+    if (checkDefCon(DEFCON_NO_NEW_MEMOS) && !IsOper(user)) {
+        reply("MSMSG_DEFCON_NO_NEW_MEMOS");
+        return 0;
+    }
+
     if (!(hi = modcmd_get_handle_info(user, argv[1])))
         return 0;
 
index eb077f590e61a8ae494f44c64869cd5059922681..19bb174f3424ccf661e4fcf05234d6b1a345831d 100644 (file)
@@ -367,6 +367,7 @@ static const struct message_entry msgtab[] = {
     { "NSMSG_NOT_VALID_FAKEHOST_REGEX", "$b%s$b is not allowed by the admin, consult the valid vhost regex pattern in the config file under nickserv/valid_fakehost_regex." },
     { "CHECKPASS_YES", "Yes." },
     { "CHECKPASS_NO", "No." },
+    { "NSMSG_DEFCON_NO_NEW_NICKS", "You cannot register new %s at this time, please try again soon" },
     { NULL, NULL }
 };
 
@@ -1279,6 +1280,11 @@ static NICKSERV_FUNC(cmd_register)
     char syncpass[MD5_CRYPT_LENGTH];
     int no_auth, weblink;
 
+    if (checkDefCon(DEFCON_NO_NEW_NICKS) && !IsOper(user)) {
+        reply("NSMSG_DEFCON_NO_NEW_NICKS", nickserv_conf.disable_nicks ? "accounts" : "nicknames");
+        return 0;
+    }
+
     if (!IsOper(user) && !dict_size(nickserv_handle_dict)) {
        /* Require the first handle registered to belong to someone +o. */
        reply("NSMSG_REQUIRE_OPER");
index 6ef304045e0ff1e6392081cc79e8b8114971a644..77c945d8eaebba2cc7aa66ec00f5d1cb00bfb36b 100644 (file)
 #define KEY_OFFLINE "offline"
 #define KEY_ROUTINGPLAN "routingplan"
 #define KEY_ROUTINGPLAN_OPTIONS "routingplan_options"
+#define KEY_DEFCON1 "DefCon1"
+#define KEY_DEFCON2 "DefCon2"
+#define KEY_DEFCON3 "DefCon3"
+#define KEY_DEFCON4 "DefCon4"
+#define KEY_DEFCON_LEVEL "DefConLevel"
+#define KEY_DEFCON_CHANMODES "DefConChanModes"
+#define KEY_DEFCON_SESSION_LIMIT "DefConSessionLimit"
+#define KEY_DEFCON_TIMEOUT "DefConTimeOut"
+#define KEY_DEFCON_GLOBAL_TARGET "DefConGlobalTarget"
+#define KEY_DEFCON_GLOBAL "GlobalOnDefcon"
+#define KEY_DEFCON_GLOBAL_MORE "GlobalOnDefconMore"
+#define KEY_DEFCON_MESSAGE "DefconMessage"
+#define KEY_DEFCON_OFF_MESSAGE "DefConOffMessage"
+#define KEY_DEFCON_GLINE_DURATION "DefConGlineExpire"
+#define KEY_DEFCON_GLINE_REASON "DefConGlineReason"
 
 /* Routing karma values: */
 /* What value we start out with when new servers are added: */
@@ -362,11 +377,40 @@ static const struct message_entry msgtab[] = {
     { "OSMSG_INVALID_REGEX", "Invalid regex: %s: %s (%d)" },
     { "OSMSG_TRACK_DISABLED", "Tracking is not currently compiled into X3" },
     { "OSMSG_MAXUSERS_RESET", "Max clients has been reset to $b%d$b" },
+
+    { "OSMSG_DEFCON_INVALID", "DefCon level %d is invalid, please choose a value between 1 and 5" },
+    { "OSMSG_DEFCON_ALLOWING_ALL", "DefCon is at level 5 and allowing everything" },
+    { "OSMSG_DEFCON_DISALLOWING", "DefCon is at level %d and enforcing:" },
+    { "OSMSG_DEFCON_NO_NEW_CHANNELS", "No Channel Registrations" },
+    { "OSMSG_DEFCON_NO_NEW_NICKS", "No Nickname/Account Registrations" },
+    { "OSMSG_DEFCON_NO_MODE_CHANGE", "No Channel Mode Changes" },
+    { "OSMSG_DEFCON_NO_NEW_CLIENTS", "No New Clients" },
+    { "OSMSG_DEFCON_FORCE_CHANMODES", "Forcing Channel Mode(s): %s" },
+    { "OSMSG_DEFCON_REDUCE_SESSION", "Forcing Reduced Session: %d" },
+    { "OSMSG_DEFCON_OPER_ONLY", "Allowing Services Communication With Opers Only" },
+    { "OSMSG_DEFCON_SILENT_OPER_ONLY", "Allowing Services Communication With Opers Only AND Silently Ignoring Regular Users" },
+    { "OSMSG_DEFCON_GLINE_NEW_CLIENTS", "Glining New Clients" },
+    { "OSMSG_DEFCON_NO_NEW_MEMOS", "Disallowing New Memos" },
+
     { NULL, NULL }
 };
 
 #define OPSERV_SYNTAX() svccmd_send_help_brief(user, opserv, cmd)
 
+int DefConLevel = 5;
+int DefCon[6];
+int DefConTimeOut;
+int GlobalOnDefcon = 0;
+int GlobalOnDefconMore = 0;
+int DefConGlineExpire;
+int DefConModesSet = 0;
+int DefConGlobalTarget = 3;
+unsigned int DefConSessionLimit;
+char *DefConChanModes;
+char *DefConGlineReason;
+char *DefConMessage;
+char *DefConOffMessage;
+
 extern void add_track_user(struct userNode *user);
 typedef int (*discrim_search_func)(struct userNode *match, void *extra);
 
@@ -524,6 +568,177 @@ opserv_free_user_alert(void *data)
 #define opserv_alert(format...) do { if (opserv_conf.alert_channel) send_channel_notice(opserv_conf.alert_channel , opserv , ## format); } while (0)
 
 
+char *defconReverseModes(const char *modes)
+{
+    char *newmodes = NULL;
+    unsigned int i = 0;
+    if (!modes) {
+        return NULL;
+    }
+    if (!(newmodes = malloc(sizeof(char) * strlen(modes) + 1))) {
+        return NULL;
+    }
+    for (i = 0; i < strlen(modes); i++) {
+        if (modes[i] == '+')
+            newmodes[i] = '-';
+        else if (modes[i] == '-')
+            newmodes[i] = '+';
+        else
+            newmodes[i] = modes[i];
+    }
+    newmodes[i] = '\0';
+    return newmodes;
+}
+
+int checkDefCon(int level)
+{
+    return DefCon[DefConLevel] & level;
+}
+
+void showDefConSettings(struct userNode *user, struct svccmd *cmd)
+{
+    if (DefConLevel == 5) {
+        reply("OSMSG_DEFCON_ALLOWING_ALL");
+        return;
+    } else
+        reply("OSMSG_DEFCON_DISALLOWING", DefConLevel);
+
+    if (checkDefCon(DEFCON_NO_NEW_CHANNELS))
+        reply("OSMSG_DEFCON_NO_NEW_CHANNELS");
+
+    if (checkDefCon(DEFCON_NO_NEW_NICKS))
+        reply("OSMSG_DEFCON_NO_NEW_NICKS");
+
+    if (checkDefCon(DEFCON_NO_MODE_CHANGE))
+        reply("OSMSG_DEFCON_NO_MODE_CHANGE");
+
+    if (checkDefCon(DEFCON_FORCE_CHAN_MODES) && (DefConChanModes))
+        reply("OSMSG_DEFCON_FORCE_CHANMODES", DefConChanModes);
+
+    if (checkDefCon(DEFCON_REDUCE_SESSION))
+        reply("OSMSG_DEFCON_REDUCE_SESSION", DefConSessionLimit);
+
+    if (checkDefCon(DEFCON_NO_NEW_CLIENTS))
+        reply("OSMSG_DEFCON_NO_NEW_CLIENTS");
+
+    if (checkDefCon(DEFCON_OPER_ONLY))
+        reply("OSMSG_DEFCON_OPER_ONLY");
+
+    if (checkDefCon(DEFCON_SILENT_OPER_ONLY))
+        reply("OSMSG_DEFCON_SILENT_OPER_ONLY");
+
+    if (checkDefCon(DEFCON_GLINE_NEW_CLIENTS))
+        reply("OSMSG_DEFCON_GLINE_NEW_CLIENTS");
+
+    if (checkDefCon(DEFCON_NO_NEW_MEMOS))
+        reply("OSMSG_DEFCON_NO_NEW_MEMOS");
+
+    return;
+}
+
+void do_mass_mode(char *modes)
+{
+    dict_iterator_t it;
+
+    if (!modes)
+        return;
+
+    for (it = dict_first(channels); it; it = iter_next(it)) {
+        struct chanNode *chan = iter_data(it);
+
+        irc_mode(opserv, chan, modes);
+    }
+
+}
+
+void DefConProcess(struct userNode *user)
+{
+    char *newmodes;
+    long targets;
+
+    if (DefConGlobalTarget == 1)
+        targets = MESSAGE_RECIPIENT_LUSERS;
+    else if (DefConGlobalTarget == 2)
+        targets = MESSAGE_RECIPIENT_CHANNELS;
+    else
+        targets = MESSAGE_RECIPIENT_ALL;
+
+    if (GlobalOnDefcon) {
+        char *globalmsg;
+        globalmsg = alloca(44);
+        sprintf(globalmsg, "Network DefCon level has changed to level %d", DefConLevel);
+        global_message(targets, globalmsg);
+    }
+
+    if (GlobalOnDefconMore)
+        global_message(targets, DefConMessage);
+
+    if ((DefConLevel == 5) && !GlobalOnDefconMore && !GlobalOnDefcon)
+        global_message(targets, DefConOffMessage);
+
+    char *opermsg;
+    if (user) {
+        opermsg = alloca(strlen(user->nick) + 35);
+        sprintf(opermsg, "%s is changing the DefCon level to %d", user->nick, DefConLevel);
+    } else {
+        opermsg = alloca(49);
+        sprintf(opermsg, "The DefCon has changed back to level %d (timeout)", DefConLevel);
+    }
+    global_message(MESSAGE_RECIPIENT_OPERS, opermsg);
+
+    if (checkDefCon(DEFCON_FORCE_CHAN_MODES)) {
+        if (DefConChanModes && !DefConModesSet) {
+            if (DefConChanModes[0] == '+' || DefConChanModes[0] == '-') {
+                do_mass_mode(DefConChanModes);
+                DefConModesSet = 1;
+            }
+        }
+    } else {
+        if (DefConChanModes && (DefConModesSet != 0)) {
+            if (DefConChanModes[0] == '+' || DefConChanModes[0] == '-') {
+                if ((newmodes = defconReverseModes(DefConChanModes))) {
+                    do_mass_mode(newmodes);
+                    free(newmodes);
+                }
+                DefConModesSet = 0;
+            }
+        }
+    }
+
+    return;
+}
+
+void
+defcon_timeout(UNUSED_ARG(void *data))
+{
+    DefConLevel = 5;
+    DefConProcess(NULL);
+}
+
+static MODCMD_FUNC(cmd_defcon)
+{
+    if ((argc < 2) || (atoi(argv[1]) == DefConLevel)) {
+        showDefConSettings(user, cmd);
+        return 1;
+    }
+
+    if ((atoi(argv[1]) < 1) || (atoi(argv[1]) > 5)) {
+        reply("OSMSG_DEFCON_INVALID", atoi(argv[1]));
+        return 0;
+    }
+
+    DefConLevel = atoi(argv[1]);
+    showDefConSettings(user, cmd);
+
+    if (DefConTimeOut > 0) {
+        timeq_del(0, defcon_timeout, NULL, TIMEQ_IGNORE_DATA & TIMEQ_IGNORE_WHEN);
+        timeq_add(now + DefConTimeOut, defcon_timeout, NULL);
+    }
+
+    DefConProcess(user);
+    return 1;
+}
+
 /* A lot of these commands are very similar to what ChanServ can do,
  * but OpServ can do them even on channels that aren't registered.
  */
@@ -2172,12 +2387,21 @@ opserv_new_user_check(struct userNode *user)
         }
     }
 
+    if (checkDefCon(DEFCON_NO_NEW_CLIENTS)) {
+        irc_kill(opserv, user, DefConGlineReason);
+        return 0;
+    }
+
     /* Only warn or G-line if there's an untrusted max and their IP is sane. */
     if (opserv_conf.untrusted_max
         && irc_in_addr_is_valid(user->ip)
         && !irc_in_addr_is_loopback(user->ip)) {
         struct trusted_host *th = dict_find(opserv_trusted_hosts, addr, NULL);
         unsigned int limit = th ? th->limit : opserv_conf.untrusted_max;
+
+        if (checkDefCon(DEFCON_REDUCE_SESSION) && !th)
+            limit = DefConSessionLimit;
+
         if (!limit) {
             /* 0 means unlimited hosts */
         } else if (ohi->clients.used == limit) {
@@ -5989,6 +6213,51 @@ opserv_conf_read(void)
     policer_params_set(pp, "drain-rate", "3");
     if ((child = database_get_data(conf_node, KEY_NEW_USER_POLICER, RECDB_OBJECT)))
         dict_foreach(child, set_policer_param, pp);
+
+    /* Defcon configuration */
+    DefCon[0] = 0;
+    str = database_get_data(conf_node, KEY_DEFCON1, RECDB_QSTRING);
+    DefCon[1] = str ? atoi(str) : 415;
+    str = database_get_data(conf_node, KEY_DEFCON2, RECDB_QSTRING);
+    DefCon[2] = str ? atoi(str) : 159;
+    str = database_get_data(conf_node, KEY_DEFCON3, RECDB_QSTRING);
+    DefCon[3] = str ? atoi(str) : 31;
+    str = database_get_data(conf_node, KEY_DEFCON4, RECDB_QSTRING);
+    DefCon[4] = str? atoi(str) : 23;
+    DefCon[5] = 0;
+
+    str = database_get_data(conf_node, KEY_DEFCON_LEVEL, RECDB_QSTRING);
+    DefConLevel = str ? atoi(str) : 5;
+
+    str = database_get_data(conf_node, KEY_DEFCON_CHANMODES, RECDB_QSTRING);
+    DefConChanModes = str ? strdup(str) : "+r";
+
+    str = database_get_data(conf_node, KEY_DEFCON_SESSION_LIMIT, RECDB_QSTRING);
+    DefConSessionLimit = str ? atoi(str) : 2;
+
+    str = database_get_data(conf_node, KEY_DEFCON_TIMEOUT, RECDB_QSTRING);
+    DefConTimeOut = str ? ParseInterval(str) : 900;
+
+    str = database_get_data(conf_node, KEY_DEFCON_GLINE_DURATION, RECDB_QSTRING);
+    DefConGlineExpire = str ? ParseInterval(str) : 300;
+
+    str = database_get_data(conf_node, KEY_DEFCON_GLOBAL_TARGET, RECDB_QSTRING);
+    DefConGlobalTarget = str ? atoi(str) : 3;
+
+    str = database_get_data(conf_node, KEY_DEFCON_GLOBAL, RECDB_QSTRING);
+    GlobalOnDefcon = str ? atoi(str) : 0;
+
+    str = database_get_data(conf_node, KEY_DEFCON_GLOBAL_MORE, RECDB_QSTRING);
+    GlobalOnDefconMore = str ? atoi(str) : 0;
+
+    str = database_get_data(conf_node, KEY_DEFCON_MESSAGE, RECDB_QSTRING);
+    DefConMessage = str ? strdup(str) : "Put your message to send your users here. Dont forget to uncomment GlobalOnDefconMore";
+
+    str = database_get_data(conf_node, KEY_DEFCON_OFF_MESSAGE, RECDB_QSTRING);
+    DefConOffMessage = str? strdup(str) : "Services are now back to normal, sorry for any inconvenience";
+
+    str = database_get_data(conf_node, KEY_DEFCON_GLINE_REASON, RECDB_QSTRING);
+    DefConGlineReason = str ? strdup(str) : "This network is currently not accepting connections, please try again later";
 }
 
 /* lame way to export opserv_conf value to nickserv.c ... */
@@ -6097,6 +6366,7 @@ init_opserv(const char *nick)
     opserv_define_func("DELTRUST", cmd_deltrust, 800, 0, 2);
     opserv_define_func("DEOP", cmd_deop, 100, 2, 2);
     opserv_define_func("DEOPALL", cmd_deopall, 400, 2, 0);
+    opserv_define_func("DEFCON", cmd_defcon, 900, 0, 0);
     opserv_define_func("DEHOP", cmd_dehop, 100, 2, 2);
     opserv_define_func("DEHOPALL", cmd_dehopall, 400, 2, 0);
     opserv_define_func("DEVOICEALL", cmd_devoiceall, 300, 2, 0);
index 08fcac49a5df8f3603cd00ee2f6524c456ec3ee5..d78db9c539d2a5c3190aa90b5c870dd13e89b568 100644 (file)
 #ifndef _opserv_h
 #define _opserv_h
 
+#define DEFCON_NO_NEW_CHANNELS          1       /* No New Channel Registrations */
+#define DEFCON_NO_NEW_NICKS             2       /* No New Nick Registrations */
+#define DEFCON_NO_MODE_CHANGE           4       /* No SET MODE changes */
+#define DEFCON_FORCE_CHAN_MODES         8       /* Force Chan Mode */
+#define DEFCON_REDUCE_SESSION           16      /* Reduce Session Limit */
+#define DEFCON_NO_NEW_CLIENTS           32      /* Kill any NEW clients */
+#define DEFCON_OPER_ONLY                64      /* Restrict services to oper's only */
+#define DEFCON_SILENT_OPER_ONLY         128     /* Silently ignore non-opers */
+#define DEFCON_GLINE_NEW_CLIENTS        256     /* Gline any new clients */
+#define DEFCON_NO_NEW_MEMOS             512     /* No New Memos Sent */
+
+extern int DefCon[6];
+extern int checkDefCon(int level);
+extern void DefConProcess(struct userNode *user);
+extern void defcon_timeout(UNUSED_ARG(void *data));
 void init_opserv(const char *nick);
 unsigned int gag_create(const char *mask, const char *owner, const char *reason, time_t expires);
 int opserv_bad_channel(const char *name);
index 8d69a89d1ece1e6d2d6b36ecdf66f0bfe59dddda..f48491d88ac7bbd9c238b230778f87ca1afb2d82 100644 (file)
             "  $bJUPE$b         Create dummy server.",
             "  $bUNJUPE$b       Remove a dummy server.",
             "  $b$b",
+            "  $bDEFCON$b       Manipulate the DefCon system.",
             "  $bREFRESHG$b     Refresh the Glines.",
             "  $bREFRESHS$b     Refresh the Shuns.",
             "  $bSETTIME$b      Synchronize time across the network.",
        "$uSee Also:$u refreshg, gline, ungline"
         );
 
+"DEFCON" ("/msg $O DEFCON [1|2|3|4|5]",
+        "The defcon system can be used to implement a pre-defined set of restrictions to services useful during an attempted attack on the network. Not specifying a level will cause $O to display the currently set defcon level and options if the level is below 5",
+        "Access level: $b${level/defcon}$b",
+        );
+
 "REFRESHG" ("/msg $O REFRESHG [server]",
         "Re-issues all GLINES in $b$O's$b database. Usually used for newly joining or desynched servers.  If a server mask is specified, the GLINES are only sent to server(s) with matching names.",
         "Access level: $b${level/refreshg}$b",
index e3fa69ed470fea1ab41d8471366b0afaae778a07..775679879ca79c7b98c1ba25e47f94c23ed39c8b 100644 (file)
@@ -20,6 +20,7 @@
 
 #include "nickserv.h"
 #include "chanserv.h"
+#include "helpfile.h"
 #include "hosthiding.h"
 #include "proto-common.c"
 #include "opserv.h"
  */
 #define PREHISTORY 780000000
 
+#define MODELEN                 40 + KEYLEN
+
 static struct server *servers_num[64*64];
 static privmsg_func_t *privmsg_funcs;
 static unsigned int num_privmsg_funcs;
@@ -316,6 +319,11 @@ static int extended_accounts;
 static struct userNode *AddUser(struct server* uplink, const char *nick, const char *ident, const char *hostname, const char *modes, const char *numeric, const char *userinfo, time_t timestamp, const char *realip);
 
 extern int off_channel;
+extern int DefConLevel;
+extern int DefConGlineExpire;
+extern int DefConTimeOut;
+extern char *DefConChanModes;
+extern char *DefConGlineReason;
 
 static int parse_oplevel(char *str);
 
@@ -675,6 +683,18 @@ void
 irc_eob_ack(void)
 {
     putsock("%s " P10_EOB_ACK, self->numeric);
+
+    char *nick;
+    const char *str;
+    str = conf_get_data("services/opserv/nick", RECDB_QSTRING);
+    nick = strdup(str);
+
+    if (nick && (DefConLevel < 5)) {
+        DefConProcess(GetUserH(nick));
+
+        if (DefConTimeOut > 0)
+            timeq_add(now + DefConTimeOut, defcon_timeout, NULL);
+    }
 }
 
 void
@@ -1288,6 +1308,7 @@ static CMD_FUNC(cmd_nick)
         NickChange(user, argv[1], 1);
     } else {
         struct server *serv;
+        struct userNode *nuser;
         char modes[MAXLEN];
         /* new nick */
         if (argc < 9)
@@ -1297,7 +1318,18 @@ static CMD_FUNC(cmd_nick)
             unsplit_string(argv+6, argc-9, modes);
         else
             strcpy(modes, "+");
-        AddUser(serv, argv[1], argv[4], argv[5], modes, argv[argc-2], argv[argc-1], atoi(argv[3]), argv[argc-3]);
+        nuser = AddUser(serv, argv[1], argv[4], argv[5], modes, argv[argc-2], argv[argc-1], atoi(argv[3]), argv[argc-3]);
+        if (checkDefCon(DEFCON_GLINE_NEW_CLIENTS) && !IsOper(nuser)) {
+            char target[IRC_NTOP_MAX_SIZE + 3] = { '*', '@', '\0' };
+            const char *str;
+            
+            str = conf_get_data("services/opserv/nick", RECDB_QSTRING);
+            if (str) {
+                strcpy(target + 2, nuser->hostname);
+                gline_add(str, target, DefConGlineExpire, DefConGlineReason, now, 1, 0);
+            }
+            return 0;
+        }
     }
     return 1;
 }
@@ -1531,6 +1563,22 @@ static CMD_FUNC(cmd_mode)
         cn->timestamp = atoi(argv[argc-1]);
     }
 
+    if (checkDefCon(DEFCON_NO_MODE_CHANGE) && !IsOper(un)) {
+        const char *str;
+        str = conf_get_data("services/opserv/nick", RECDB_QSTRING);
+        if (str) {
+            char modes[MODELEN];
+            struct userNode *opserv = GetUserH(str);
+            send_message_type(4, un, opserv, "Channel modes cannot be changed due to DefCon level %d in effect, please try again soon", DefConLevel);
+            irc_make_chanmode(cn, modes);
+            irc_mode(opserv, cn, modes);
+            irc_mode(opserv, cn, DefConChanModes);
+        }
+        return 1;
+    }
+
+
     return mod_chanmode(un, cn, argv+2, argc-2, MCP_ALLOW_OVB|MCP_FROM_SERVER|(un ? MC_NOTIFY : 0));
 }
 
@@ -1807,6 +1855,18 @@ static CMD_FUNC(cmd_privmsg)
     pd.user = GetUserH(origin);
     if (!pd.user || (IsGagged(pd.user) && !IsOper(pd.user)))
         return 1;
+
+    if (checkDefCon(DEFCON_OPER_ONLY) && !IsOper(pd.user)) {
+        const char *str;
+        str = conf_get_data("services/opserv/nick", RECDB_QSTRING);
+        if (str)
+            send_message_type(4, pd.user, GetUserH(str), "Services are currently not available, please try again soon");
+        return 1;
+    }
+
+    if (checkDefCon(DEFCON_SILENT_OPER_ONLY) && !IsOper(pd.user))
+        return 1; /* Silently Ignore */
+
     pd.is_notice = 0;
     pd.text = argv[2];
     parse_foreach(argv[1], privmsg_chan_helper, NULL, privmsg_user_helper, privmsg_invalid, &pd);
index a938c8d0e3b9ea4570d68da9c9f2de11ccfb8079..77a3c9de3a11c2d0ae4835811a40a6c80e9883cd 100644 (file)
         // how long to keep an illegal channel locked down (seconds)?
         "purge_lock_delay" "60";
 
+        // ------------------------------------------------------------------
+        // Defcon Settings
+        //
+        // No new channel registrations                       1 
+        // No New Nick Registrations                          2 
+        // No Channel Mode changes                            4 
+        // Force Chan Mode                                    8 
+        // Use Reduced Session Limit                         16 
+        // KILL any new clients trying to connect            32 
+        // Services will ignore everyone but opers           64 
+        // Services will silently ignore everyone but opers 128 
+        // GLINE all new clients trying to connect          256 
+        // No new memos sent to block MemoServ attacks      512
+        // 
+        // These are the values are added together to determine each defcon setting: 
+        "DefCon1" "415"; 
+        "DefCon2" "159";
+        "DefCon3" "31";
+        "DefCon4" "23";
+
+        // Default defcon level, 5 is running all normally
+        "DefConLevel" "5";
+
+        // If defcon is limiting sessions then how many sessions should O3 allow?
+        "DefConSessionLimit" "2";
+
+        // Length of the gline set on newly connecting clients, if defcon is glining
+        // newly connecting clients
+        "DefConGlineExpire" "5m";
+
+        // Mode to set on all channels if defcon is forcing channel modes on all channels
+        "DefConChanModes" "+r";
+
+        // If not set to 0, defcon will set back to level 5 after this time
+        "DefConTimeOut" "15m";
+
+        // Where will the user global notices go to?
+        // 1 - Users Only
+        // 2 - Channels Only
+        // 3 - Both Users and Channels
+        "DefConGlobalTarget" "3";
+
+        // Set to 1 to send a notice to all users when defcon levels are changed
+        "GlobalOnDefcon" "0";
+
+        // If set to 1 along with the notice that the levels are changing an extra
+        // notice will be sent
+        "GlobalOnDefconMore" "0";
+
+        // GlobalOnDefconMore notice.
+        "DefconMessage" "Put your message to send your users here. Dont forget to uncomment GlobalOnDefconMore";
+
+        // This notice will be used if GlobalOnDefcon and GlobalOnDefconMore are off
+        "DefConOffMessage" "Services are now back to normal, sorry for any inconvenience";
+
+        // Reason placed in defcon Glines.
+        "DefConGlineReason" "This network is currently not accepting connections, please try again later";
+
+        // ------------------------------------------------------------------
+
         // The join-flood policer code goes off all the time when a server
         // goes down (and everyone reconnects) so i don't reccomend using it.
         // Automatically moderate join flooded channels?