Просмотр исходного кода

Merge branch 'ducch-fish-for-chans' into next

* ducch-fish-for-chans:
  * Don't allow setting FiSH key in channel via cmd_setkey
  * Make the size of the key a const size_t
  * Only remove key if it exists
  * Update docs
  * Support FiSH for channel targets in privmsg/notice
  * FiSH key in .chanset instead of .setkey
  * DRY set_fish_key(target, key). empty to remove key.
  * Random FiSH key support in .setkey
Bryan Drewery 14 лет назад
Родитель
Сommit
14a37ee4a3

+ 4 - 3
doc/UPDATES

@@ -16,9 +16,10 @@ next
   * Fix blowfish not working correctly on 64bit
   * Suicide will now remove all bots related to the binary being removed (fixes #435)
   * FiSH message support added.
-  * FiSH support for DH1080 key-exchange. 'keyx' command added to start from bot, and responds to key-exchanges.
-  * Auto FiSH key-exchange when accepting users via callerid (controllable with set 'fish-auto-keyx')
-  * Automatic re-key exchange after every message to avoid replay attacks (controllable with set 'fish-paranoid')
+    * FiSH support for DH1080 key-exchange. 'keyx' command added to start from bot, and responds to key-exchanges.
+    * Auto FiSH key-exchange when accepting users via callerid (controllable with set 'fish-auto-keyx')
+    * Automatic re-key exchange after every message to avoid replay attacks (controllable with set 'fish-paranoid')
+    * Set FiSH key via cmd_setkey and 'chanset fish-key'
   * When 'mdop' protection is on, re-op all previously opped clients automatically.
   * When 'mop' protection is on, deop all previously regular clients automatically.
   * Add './wraith -V' which will display the packconfig that the bot is using.

+ 2 - 1
doc/help.txt

@@ -1747,10 +1747,11 @@ See also: reload, backup
  
 See also: botset
 :leaf:setkey
-### $bsetkey$b <nick|channel> [key]
+### $bsetkey$b <nick> [key|rand]
  
     Sets the FiSH key for the given target.
     Use no key to clear the currently set key.
+    Use 'rand' to generate a random key.
  
 See also: keyx
 ::sha1

+ 1 - 0
src/chan.h

@@ -186,6 +186,7 @@ struct chanset_t {
   interval_t auto_delay;
   int knock_flags;
   int protect_backup;
+  char fish_key[50];
 /* Chanint template 
  *int temp;
  */

+ 46 - 3
src/chanprog.c

@@ -890,17 +890,20 @@ struct chanset_t* find_common_opped_chan(bd::String nick) {
 
 void privmsg(bd::String target, bd::String msg, int idx) {
   struct chanset_t* chan = NULL;
-  if (have_cprivmsg && !strchr(CHANMETA, target[0]))
+  bool talking_to_chan = strchr(CHANMETA, target[0]);
+  if (have_cprivmsg && !talking_to_chan)
     chan = find_common_opped_chan(target);
   bool cleartextPrefix = (msg(0, 3) == "+p ");
 
   // Encrypt with FiSH?
-  if (!strchr(CHANMETA, target[0]) && !cleartextPrefix && FishKeys.contains(target) && FishKeys[target]->sharedKey.length()) {
+  if (!cleartextPrefix && FishKeys.contains(target) && FishKeys[target]->sharedKey.length()) {
     msg = "+OK " + egg_bf_encrypt(msg, FishKeys[target]->sharedKey);
   }
+
   if (cleartextPrefix) {
     msg += static_cast<size_t>(3);
   }
+
   if (chan)
     dprintf(idx, "CPRIVMSG %s %s :%s\n", target.c_str(), chan->name, msg.c_str());
   else
@@ -909,8 +912,19 @@ void privmsg(bd::String target, bd::String msg, int idx) {
 
 void notice(bd::String target, bd::String msg, int idx) {
   struct chanset_t* chan = NULL;
-  if (have_cnotice && !strchr(CHANMETA, target[0]))
+  bool talking_to_chan = strchr(CHANMETA, target[0]);
+  if (have_cnotice && !talking_to_chan)
     chan = find_common_opped_chan(target);
+  bool cleartextPrefix = (msg(0, 3) == "+p ");
+
+  if (!cleartextPrefix && FishKeys.contains(target) && FishKeys[target]->sharedKey.length()) {
+    msg = "+OK " + egg_bf_encrypt(msg, FishKeys[target]->sharedKey);
+  }
+
+  if (cleartextPrefix) {
+    msg += static_cast<size_t>(3);
+  }
+
   if (chan)
     dprintf(idx, "CNOTICE %s %s :%s\n", target.c_str(), chan->name, msg.c_str());
   else
@@ -967,3 +981,32 @@ void keyx(const bd::String &target) {
   fishData->timestamp = now;
   FishKeys[target] = fishData;
 }
+
+void set_fish_key(char *target, char *key)
+{
+  fish_data_t* fishData = FishKeys.contains(target) ? FishKeys[target] : NULL;
+
+  if (!key || !key[0]) { //remove key
+    if (fishData) {
+      FishKeys.remove(target);
+      delete fishData;
+    }
+  } else { //set key
+    fishData = new fish_data_t;
+
+    if (!strcmp(key, "rand")) {
+      // Set a RANDOM key
+      const size_t randomKeyLength = 32;
+      char *rand_key = (char*)my_calloc(1, randomKeyLength+1);
+      make_rand_str(rand_key, randomKeyLength);
+      fishData->sharedKey = rand_key;
+      free(rand_key);
+    } else {
+      fishData->sharedKey = key;
+    }
+
+    // Set the key
+    fishData->timestamp = now;
+    FishKeys[target] = fishData;
+  }
+}

+ 1 - 0
src/chanprog.h

@@ -35,6 +35,7 @@ void privmsg(bd::String target, bd::String msg, int idx);
 void notice(bd::String target, bd::String msg, int idx);
 void check_removed_server(bool = 1);
 void keyx(const bd::String& target);
+void set_fish_key(char *, char *);
 
 extern struct chanset_t		*chanset, *chanset_default;
 extern char			admin[], origbotnick[HANDLEN + 1], origbotname[NICKLEN], jupenick[NICKLEN], botname[NICKLEN], *def_chanset;

+ 10 - 3
src/mod/channels.mod/chanmisc.c

@@ -586,7 +586,15 @@ int channel_modify(char *result, struct chanset_t *chan, int items, char **item,
         return ERROR;
       }
       chan->protect_backup = atoi(item[i]);
-     
+    } else if (!strcmp(item[i], "fish-key")) {
+      i++;
+      if (i >= items) {
+        set_fish_key(chan->dname, "");
+        return ERROR;
+      }
+      set_fish_key(chan->dname, item[i]);
+      strlcpy(chan->fish_key, item[i], sizeof(chan->fish_key));
+    }
 
 /* Chanint template
  *  } else if (!strcmp(item[i], "temp")) {
@@ -598,8 +606,6 @@ int channel_modify(char *result, struct chanset_t *chan, int items, char **item,
  *    }
  *    chan->temp = atoi(item[i]);
  */
-    }
-
 
     else if (!strcmp(item[i], "+enforcebans"))
       chan->status |= CHAN_ENFORCEBANS;
@@ -1030,6 +1036,7 @@ int channel_add(char *result, const char *newname, char *options, bool isdefault
     chan->groups = new bd::Array<bd::String>;
     *(chan->groups) << "main";
     chan->protect_backup = 1;
+    chan->fish_key[0] = 0;
     chan->knock_flags = 0;
     chan->flood_lock_time = 120;
     chan->flood_exempt_mode = 0;

+ 2 - 0
src/mod/channels.mod/cmdschan.c

@@ -1257,6 +1257,8 @@ static void cmd_chaninfo(int idx, char *par)
     SHOW_INT("Protect-backup: ", chan->protect_backup, "Do!", "Don't!");
     SHOW_INT("Voice-non-ident: ", chan->voice_non_ident, "Do!", "Don't!");
 
+    dprintf(idx, "FiSH Key: %s\n", FishKeys.contains(chan->dname) && FishKeys[chan->dname]->sharedKey.length() ? FishKeys[chan->dname]->sharedKey.c_str() : "not set");
+
     dprintf(idx, "Flood settings:   chan ctcp join kick deop nick mjoin\n");
     dprintf(idx, "  number:          %3d  %3d  %3d  %3d  %3d  %3d  %3d\n",
 	    chan->flood_pub_thr, chan->flood_ctcp_thr,

+ 2 - 1
src/mod/channels.mod/userchan.c

@@ -719,7 +719,7 @@ flood-chan %d:%d flood-ctcp %d:%d flood-join %d:%d \
 flood-kick %d:%d flood-deop %d:%d flood-nick %d:%d flood-mjoin %d:%d \
 closed-ban %d closed-invite %d closed-private %d closed-exempt %d ban-time %d \
 exempt-time %d invite-time %d voice-non-ident %d auto-delay %d \
-flood-exempt %d flood-lock-time %d knock %d \
+flood-exempt %d flood-lock-time %d knock %d fish_key { %s } \
 %cmeankicks %cenforcebans %cdynamicbans %cuserbans %cbitch \
 %cprivate %ccycle %cinactive %cdynamicexempts %cuserexempts \
 %cdynamicinvites %cuserinvites %cnodesynch %cclosed %cvoice \
@@ -759,6 +759,7 @@ flood-exempt %d flood-lock-time %d knock %d \
         chan->flood_exempt_mode,
         chan->flood_lock_time,
         chan->knock_flags,
+        chan->fish_key,
  	PLSMNS(channel_meankicks(chan)),
  	PLSMNS(channel_enforcebans(chan)),
 	PLSMNS(channel_dynamicbans(chan)),

+ 14 - 14
src/mod/server.mod/cmdsserv.c

@@ -131,33 +131,33 @@ static void cmd_keyx(int idx, char *par) {
 static void cmd_setkey(int idx, char *par) {
   putlog(LOG_CMDS, "*", "#%s# setkey %s", dcc[idx].nick, par);
 
-  if (!par[0]) {
-    dprintf(idx, "Usage: setkey <nick|channel> [key]\n");
+  const bool target_is_chan = par[0] && strchr(CHANMETA, par[0]);
+
+  if (!par[0] || target_is_chan) {
+    dprintf(idx, "Usage: setkey <nick> [key|rand]\n");
+    if (target_is_chan) {
+      dprintf(idx, "Use 'chanset fish-key' to set a key for a channel.\n");
+    }
     return;
   }
 
   char *target = newsplit(&par);
-  char *key = newsplit(&par);
+  char *newkey = newsplit(&par);
   bool have_key = FishKeys.contains(target);
-  fish_data_t* fishData = NULL;
 
-  if (!key[0]) {
+  if (!newkey[0]) {
     // Clear the key
     if (have_key) {
-      fishData = FishKeys[target];
-      FishKeys.remove(target);
-      delete fishData;
+      set_fish_key(target, "");
       dprintf(idx, "Key cleared for '%s'\n", target);
     } else {
       dprintf(idx, "No key found for '%s'\n", target);
     }
   } else {
-    // Set the key
-    fishData = new fish_data_t;
-    fishData->sharedKey = key;
-    fishData->timestamp = now;
-    FishKeys[target] = fishData;
-    dprintf(idx, "Set key for '%s' to: %s", target, key);
+    // Set a new key
+    set_fish_key(target, newkey);
+    fish_data_t* fishData = FishKeys[target];
+    dprintf(idx, "Set key for '%s' to: %s", target, fishData->sharedKey.c_str());
   }
   return;
 }