]> jfr.im git - solanum.git/blobdiff - ircd/match.c
Add tests for valid_temp_time
[solanum.git] / ircd / match.c
index a8165ffb22c0b2c08f42202f94be192ca413c942..368ee353834ff48cdd6a98175d26f14b19459dd6 100644 (file)
@@ -22,6 +22,7 @@
 #include "client.h"
 #include "ircd.h"
 #include "match.h"
+#include "s_conf.h"
 #include "s_assert.h"
 
 /*
@@ -104,6 +105,31 @@ int match(const char *mask, const char *name)
        }
 }
 
+/* Reorder runs of [?*] in mask to the form  ``**...??...'' */
+void
+match_arrange_stars(char *mask)
+{
+       char *swap = NULL;
+
+       for (char *p = mask; *p != '\0'; p++)
+       {
+               switch (*p)
+               {
+               case '*':
+                       if (swap == NULL) break;
+                       *swap++ = '*';
+                       *p = '?';
+                       break;
+               case '?':
+                       if (swap == NULL) swap = p;
+                       break;
+               default:
+                       swap = NULL;
+                       break;
+               }
+       }
+}
+
 /** Check a mask against a mask.
  * This test checks using traditional IRC wildcards only: '*' means
  * match zero or more characters of any type; '?' means match exactly
@@ -115,15 +141,23 @@ int match(const char *mask, const char *name)
  * @param[in] name New wildcard-containing mask.
  * @return 1 if \a name is equal to or more specific than \a mask, 0 otherwise.
  */
-int mask_match(const char *mask, const char *name)
+int mask_match(const char *mask_, const char *name)
 {
+       static char mask[BUFSIZE];
        const char *m = mask, *n = name;
        const char *m_tmp = mask, *n_tmp = name;
+       size_t len;
        int star_p;
 
-       s_assert(mask != NULL);
+       s_assert(mask_ != NULL);
        s_assert(name != NULL);
 
+       len = rb_strlcpy(mask, mask_, sizeof mask);
+       s_assert(len < sizeof mask);
+       (void) len; /* for NDEBUG */
+
+       match_arrange_stars(mask);
+
        for (;;)
        {
                switch (*m)
@@ -146,6 +180,7 @@ int mask_match(const char *mask, const char *name)
                                  else if (*m == '?')
                                  {
                                          /* changed for mask_match() */
+                                         while (star_p && *n == '*') n++;
                                          if (*n == '*' || !*n)
                                                  goto backtrack;
                                          n++;
@@ -588,6 +623,7 @@ int ircncmp(const char *s1, const char *s2, int n)
 
 void matchset_for_client(struct Client *who, struct matchset *m)
 {
+       bool hide_ip = IsIPSpoof(who) || (!ConfigChannel.ip_bans_through_vhost && IsDynSpoof(who));
        unsigned hostn = 0;
        unsigned ipn = 0;
 
@@ -595,7 +631,7 @@ void matchset_for_client(struct Client *who, struct matchset *m)
 
        sprintf(m->host[hostn++], "%s!%s@%s", who->name, who->username, who->host);
 
-       if (!IsIPSpoof(who))
+       if (!hide_ip)
        {
                sprintf(m->ip[ipn++], "%s!%s@%s", who->name, who->username, who->sockhost);
        }
@@ -614,12 +650,13 @@ void matchset_for_client(struct Client *who, struct matchset *m)
                        sprintf(m->host[hostn++], "%s!%s@%s", who->name, who->username, who->localClient->mangledhost);
                }
        }
-       if (!IsIPSpoof(who) && GET_SS_FAMILY(&who->localClient->ip) == AF_INET6 &&
+       if (!hide_ip && GET_SS_FAMILY(&who->localClient->ip) == AF_INET6 &&
                        rb_ipv4_from_ipv6((const struct sockaddr_in6 *)&who->localClient->ip, &ip4))
        {
-               int n = sprintf(m->ip[ipn++], "%s!%s@", who->name, who->username);
+               int n = sprintf(m->ip[ipn], "%s!%s@", who->name, who->username);
                rb_inet_ntop_sock((struct sockaddr *)&ip4,
                                m->ip[ipn] + n, sizeof m->ip[ipn] - n);
+               ipn++;
        }
 
        for (int i = hostn; i < ARRAY_SIZE(m->host); i++)