]> jfr.im git - irc/DALnet/bahamut.git/commitdiff
Improve user host-masking support for WHO & RWHO
authorRyan Smith <redacted>
Thu, 5 Mar 2020 05:42:56 +0000 (00:42 -0500)
committerRyan Smith <redacted>
Thu, 5 Mar 2020 05:42:56 +0000 (00:42 -0500)
include/struct.h
src/m_rwho.c
src/m_who.c

index 8342367b926c6874c76c38c751a80bb4726ebe8d..7bf74d9cc45bdb7792658ee255c5c30ea2a46b19 100644 (file)
@@ -1535,6 +1535,7 @@ typedef struct SearchOptions
     unsigned search_chan:1;
     unsigned ip_show:1;
     unsigned realhost_show:1;
+    unsigned maskhost_show:1;
     unsigned client_type_plus:1;
 } SOpts;
 
index 64c79a0457f8f5afc6a4da5f4371dedd0b6bdc31..63b357877c805581fbaa0208d168a92da9ea7640 100644 (file)
@@ -81,12 +81,20 @@ extern Link *find_channel_link(Link *, aChannel *);
 #define RWO_MATCHES 0x2000
 #define RWO_CHANNEL 0x4000
 #define RWO_PROB    0x8000
+#define RWO_MASKED_HOST   0x10000
+#define RWO_UNMASKED_HOST   0x20000
 
 /* miscellaneous flags */
 #define RWC_SHOWIP  0x0001  /* WHO compatibility */
 #define RWC_CHANNEL 0x0002  /* WHO compatibility */
 #define RWC_TIME    0x0004  /* show timing stats */
 
+#ifdef USER_HOSTMASKING
+#define RWHO_HOST(cptr) IsUmodeH(cptr)?cptr->user->mhost:cptr->user->host
+#else
+#define RWHO_HOST(cptr) cptr->user->host
+#endif
+
 static const char *rwho_help[] = {
     "RWHO <[+|-]matchflags>[/<outputflags>[:<cookie>]] <args>",
     "Match flags are specified like channel modes,",
@@ -123,7 +131,13 @@ static const char *rwho_help[] = {
     "  :<cookie>     - supplied cookie (useful for scripts)",
     "  n             - user's nick",
     "  u             - user's username",
+#ifdef USER_HOSTMASKING
+    "  h             - user's current host",
+    "  H             - user's masked host",
+    "  R             - user's real/unmasked host",
+#else
     "  h             - user's host",
+#endif
     "  i             - user's IP",
     "  s             - user's server",
     "  f             - standard WHO flags (GH*%@+)",
@@ -188,7 +202,7 @@ static struct {
 #endif
 } rwho_opts;
 
-static char rwhobuf[1024];
+static char rwhobuf[2048];
 static char scratch[1024];
 
 
@@ -766,6 +780,10 @@ static int rwho_parseopts(aClient *sptr, int parc, char *parv[])
             case 'n': rwho_opts.rplfields |= RWO_NICK; sfl++; break;
             case 'u': rwho_opts.rplfields |= RWO_USER; sfl++; break;
             case 'h': rwho_opts.rplfields |= RWO_HOST; sfl++; break;
+#ifdef USER_HOSTMASKING
+            case 'H': rwho_opts.rplfields |= RWO_MASKED_HOST; sfl++; break;
+            case 'R': rwho_opts.rplfields |= RWO_UNMASKED_HOST; sfl++; break;
+#endif
             case 'i': rwho_opts.rplfields |= RWO_IP; sfl++; break;
             case 's': rwho_opts.rplfields |= RWO_SERVER; sfl++; break;
             case 'f': rwho_opts.rplfields |= RWO_FLAGS; sfl++; break;
@@ -972,11 +990,11 @@ static int rwho_match(aClient *cptr, int *failcode, aClient **failclient)
     }
 
     if ((rwho_opts.check[0] & RWM_HOST) &&
-        rwho_opts.host_func[0](rwho_opts.host_pat[0], cptr->user->host))
+        rwho_opts.host_func[0](rwho_opts.host_pat[0], cptr->user->host) && rwho_opts.host_func[0](rwho_opts.host_pat[0], cptr->user->mhost))
         return 0;
 
     if ((rwho_opts.check[1] & RWM_HOST) &&
-        !rwho_opts.host_func[1](rwho_opts.host_pat[1], cptr->user->host))
+        !rwho_opts.host_func[1](rwho_opts.host_pat[1], cptr->user->host) && !rwho_opts.host_func[1](rwho_opts.host_pat[1], cptr->user->mhost))
         return 0;
 
 #ifdef RWHO_PROBABILITY
@@ -1124,7 +1142,7 @@ static void rwho_reply(aClient *cptr, aClient *ac, char *buf, chanMember *cm)
         if (rwho_opts.misc & RWC_SHOWIP)
             src = ac->hostip;
         else
-            src = ac->user->host;
+            src = RWHO_HOST(ac);
 
         ircsprintf(buf, getreply(RPL_WHOREPLY), me.name, cptr->name,
                    rwho_opts.chptr ? rwho_opts.chptr->chname : chname,
@@ -1150,12 +1168,29 @@ static void rwho_reply(aClient *cptr, aClient *ac, char *buf, chanMember *cm)
     }
 
     if (rwho_opts.rplfields & RWO_HOST)
+    {
+        src = RWHO_HOST(ac);
+        *dst++ = ' ';
+        while (*src)
+            *dst++ = *src++;
+    }
+
+#ifdef USER_HOSTMASKING
+    if (rwho_opts.rplfields & RWO_MASKED_HOST)
+    {
+        src = ac->user->mhost;
+        *dst++ = ' ';
+        while (*src)
+            *dst++ = *src++;
+    }
+    if (rwho_opts.rplfields & RWO_UNMASKED_HOST)
     {
         src = ac->user->host;
         *dst++ = ' ';
         while (*src)
             *dst++ = *src++;
     }
+#endif
 
     if (rwho_opts.rplfields & RWO_IP)
     {
index 75f0d7a3918878a04c40ece031b2d6d728e62e3e..bcb5d825579c3a111187b986cb59776492fbd6b4 100644 (file)
@@ -45,7 +45,11 @@ int build_searchopts(aClient *sptr, int parc, char *parv[])
 {
   static char *who_oper_help[] =
   {
-      "/WHO [+|-][acghilmnstuCM] [args]",
+#ifdef USER_HOSTMASKING
+      "/WHO [+|-][acghilmnstuCHIMR] [args]",
+#else
+      "/WHO [+|-][acghilmnstuCIM] [args]",
+#endif
       "Flags are specified like channel modes,",
       "The flags cghimnsu all have arguments",
       "Flags are set to a positive check by +, a negative check by -",
@@ -74,6 +78,7 @@ int build_searchopts(aClient *sptr, int parc, char *parv[])
       "Flag M: check for user in channels I am a member of",
       "Flag I: always show IPs instead of hosts",
 #ifdef USER_HOSTMASKING
+      "Flag H: show the masked host even if the user's host is not masked (umode -H)",
       "Flag R: show the real host even if the user's host is masked (umode +H)",
 #endif
       NULL
@@ -350,6 +355,14 @@ int build_searchopts(aClient *sptr, int parc, char *parv[])
           wsopts.ip_show = change;
           break; 
 #ifdef USER_HOSTMASKING
+      case 'H':
+          if(!IsAnOper(sptr))
+          {
+              sendto_one(sptr, getreply(ERR_NOPRIVILEGES), me.name, parv[0]);
+              return 0;
+          }
+          wsopts.maskhost_show = change;
+          break;
       case 'R':
           if(!IsAnOper(sptr))
           {
@@ -615,10 +628,27 @@ int chk_who(aClient *ac, aClient *sptr, int showall)
           (!wsopts.user_plus && !uchkfn(wsopts.user, ac->user->username)))
            return 0;
 
-    if(wsopts.nick!=NULL)
-       if((wsopts.nick_plus && nchkfn(wsopts.nick, ac->name)) ||
-          (!wsopts.nick_plus && !nchkfn(wsopts.nick, ac->name)))
-           return 0;
+    if(wsopts.host!=NULL)
+    {
+#ifdef USER_HOSTMASKING
+        if(IsAnOper(sptr))
+        {
+           if((wsopts.host_plus && hchkfn(wsopts.host, ac->user->host) && hchkfn(wsopts.host, ac->user->mhost)) ||
+              (!wsopts.host_plus && (!hchkfn(wsopts.host, ac->user->host) || !hchkfn(wsopts.host, ac->user->mhost))))
+               return 0;
+        }
+        else
+        {
+           if((wsopts.host_plus && hchkfn(wsopts.host, IsUmodeH(ac)?ac->user->mhost:ac->user->host)) ||
+              (!wsopts.host_plus && !hchkfn(wsopts.host, IsUmodeH(ac)?ac->user->mhost:ac->user->host)))
+               return 0;
+        }
+#else
+        if((wsopts.host_plus && hchkfn(wsopts.host, ac->user->host)) ||
+           (!wsopts.host_plus && !hchkfn(wsopts.host, ac->user->host)))
+            return 0;
+#endif
+    }
     
     if(wsopts.host!=NULL)
        if((wsopts.host_plus && hchkfn(wsopts.host, ac->user->host)) ||
@@ -642,7 +672,7 @@ int chk_who(aClient *ac, aClient *sptr, int showall)
     /*
      * For the below options, a value of two means '+', 
      * a value of 1 means '-', and a value of 0 means
-     * not speficied. 
+     * not specified.
      */
 
     if(wsopts.ts_value == 2 && /* +t */
@@ -697,7 +727,7 @@ inline char *first_visible_channel(aClient *cptr, aClient *sptr)
 #define WHO_HOPCOUNT(s, a) ( ( (IsULine((a)) || IsUmodeI((a))) && !IsAnOper((s)) ) ? 0 : a->hopcount)
 #define WHO_SERVER(s ,a) ((IsUmodeI((a)) && !IsAnOper((s))) ? HIDDEN_SERVER_NAME : a->user->server)
 #ifdef USER_HOSTMASKING
-#define WHO_HOST(s, a) ((wsopts.ip_show) ? (a)->hostip : (IsUmodeH((a)) && !wsopts.realhost_show) ? (a)->user->mhost : (a)->user->host)
+#define WHO_HOST(s, a) ((wsopts.ip_show) ? (a)->hostip : ((IsUmodeH((a)) && !wsopts.realhost_show) || wsopts.maskhost_show) ? (a)->user->mhost : (a)->user->host)
 #else
 #define WHO_HOST(s, a) ((wsopts.ip_show) ? (a)->hostip : (a)->user->host)
 #endif