Add more G-line length tests. Resolves SF#2985922.
[ircu2.10.12-pk.git] / ircd / gline.c
index 5ae577e785423b82785191bf4f5fc4d0f001cbea..9c3d2970e24df6a078e4c976cb94c64a2b7d8d36 100644 (file)
@@ -24,6 +24,7 @@
 #include "config.h"
 
 #include "gline.h"
+#include "channel.h"
 #include "client.h"
 #include "ircd.h"
 #include "ircd_alloc.h"
@@ -44,7 +45,6 @@
 #include "msg.h"
 #include "numnicks.h"
 #include "numeric.h"
-#include "whocmds.h"
 
 /* #include <assert.h> -- Now using assert in ircd_log.h */
 #include <string.h>
@@ -77,18 +77,22 @@ struct Gline* BadChanGlineList = 0;
  * @param[in] gl Name of a struct Gline pointer variable that will be made to point to the G-lines in sequence.
  * @param[in] next Name of a scratch struct Gline pointer variable.
  */
+/* There is some subtlety here with the boolean operators:
+ * (x || 1) is used to continue in a logical-and series even when !x.
+ * (x && 0) is used to continue in a logical-or series even when x.
+ */
 #define gliter(list, gl, next)                         \
   /* Iterate through the G-lines in the list */                \
   for ((gl) = (list); (gl); (gl) = (next))             \
     /* Figure out the next pointer in list... */       \
     if ((((next) = (gl)->gl_next) || 1) &&             \
        /* Then see if it's expired */                  \
-       (gl)->gl_lifetime <= CurrentTime)               \
+       (gl)->gl_lifetime <= TStime())                  \
       /* Record has expired, so free the G-line */     \
       gline_free((gl));                                        \
     /* See if we need to expire the G-line */          \
-    else if (((gl)->gl_expire > CurrentTime ||         \
-             ((gl)->gl_flags &= ~GLINE_ACTIVE) ||      \
+    else if ((((gl)->gl_expire > TStime()) ||          \
+             (((gl)->gl_flags &= ~GLINE_ACTIVE) && 0) ||       \
              ((gl)->gl_state = GLOCAL_GLOBAL)) && 0)   \
       ; /* empty statement */                          \
     else
@@ -137,37 +141,9 @@ static struct Gline *
 make_gline(char *user, char *host, char *reason, time_t expire, time_t lastmod,
           time_t lifetime, unsigned int flags)
 {
-  struct Gline *gline, *after = 0;
-
-  /* Disable checking for overlapping G-lines.  The problem is that we
-   * may have a wide-mask, long lifetime G-line that we've
-   * deactivated--maybe it was a mistake?--and someone comes along and
-   * wants to set a narrower overlapping G-line with a shorter
-   * lifetime.  If we were to leave this logic enabled, there would be
-   * no way to set that narrower G-line.
-   */
-/*   if (!(flags & GLINE_BADCHAN)) { /\* search for overlapping glines first *\/ */
-
-/*     for (gline = GlobalGlineList; gline; gline = sgline) { */
-/*       sgline = gline->gl_next; */
-
-/*       if (gline->gl_expire <= CurrentTime) */
-/*     gline_free(gline); */
-/*       else if (((gline->gl_flags & GLINE_LOCAL) != (flags & GLINE_LOCAL)) || */
-/*                (gline->gl_host && !host) || (!gline->gl_host && host)) */
-/*     continue; */
-/*       else if (!mmatch(gline->gl_user, user) /\* gline contains new mask *\/ */
-/*            && (gline->gl_host == NULL || !mmatch(gline->gl_host, host))) { */
-/*     if (expire <= gline->gl_expire) /\* will expire before wider gline *\/ */
-/*       return 0; */
-/*     else */
-/*       after = gline; /\* stick new gline after this one *\/ */
-/*       } else if (!mmatch(user, gline->gl_user) /\* new mask contains gline *\/ */
-/*              && (gline->gl_host==NULL || !mmatch(host, gline->gl_host))  */
-/*              && gline->gl_expire <= expire) /\* old expires before new *\/ */
-/*     gline_free(gline); /\* save some memory *\/ */
-/*     } */
-/*   } */
+  struct Gline *gline;
+
+  assert(0 != expire);
 
   gline = (struct Gline *)MyMalloc(sizeof(struct Gline)); /* alloc memory */
   assert(0 != gline);
@@ -181,7 +157,7 @@ make_gline(char *user, char *host, char *reason, time_t expire, time_t lastmod,
 
   if (flags & GLINE_BADCHAN) { /* set a BADCHAN gline */
     DupString(gline->gl_user, user); /* first, remember channel */
-    gline->gl_host = 0;
+    gline->gl_host = NULL;
 
     gline->gl_next = BadChanGlineList; /* then link it into list */
     gline->gl_prev_p = &BadChanGlineList;
@@ -198,19 +174,11 @@ make_gline(char *user, char *host, char *reason, time_t expire, time_t lastmod,
     if (*user != '$' && ipmask_parse(host, &gline->gl_addr, &gline->gl_bits))
       gline->gl_flags |= GLINE_IPMASK;
 
-    if (after) {
-      gline->gl_next = after->gl_next;
-      gline->gl_prev_p = &after->gl_next;
-      if (after->gl_next)
-       after->gl_next->gl_prev_p = &gline->gl_next;
-      after->gl_next = gline;
-    } else {
-      gline->gl_next = GlobalGlineList; /* then link it into list */
-      gline->gl_prev_p = &GlobalGlineList;
-      if (GlobalGlineList)
-       GlobalGlineList->gl_prev_p = &gline->gl_next;
-      GlobalGlineList = gline;
-    }
+    gline->gl_next = GlobalGlineList; /* then link it into list */
+    gline->gl_prev_p = &GlobalGlineList;
+    if (GlobalGlineList)
+      GlobalGlineList->gl_prev_p = &gline->gl_next;
+    GlobalGlineList = gline;
   }
 
   return gline;
@@ -362,7 +330,7 @@ gline_checkmask(char *mask)
  * @param[in] gline G-line to forward.
  * @return Zero.
  */
-int
+static int
 gline_propagate(struct Client *cptr, struct Client *sptr, struct Gline *gline)
 {
   if (GlineIsLocal(gline))
@@ -374,12 +342,74 @@ gline_propagate(struct Client *cptr, struct Client *sptr, struct Gline *gline)
                        GlineIsRemActive(gline) ? '+' : '-', gline->gl_user,
                        gline->gl_host ? "@" : "",
                        gline->gl_host ? gline->gl_host : "",
-                       gline->gl_expire - CurrentTime, gline->gl_lastmod,
-                       gline->gl_lifetime - CurrentTime, gline->gl_reason);
+                       gline->gl_expire - TStime(), gline->gl_lastmod,
+                       gline->gl_lifetime, gline->gl_reason);
 
   return 0;
 }
 
+/** Count number of users who match \a mask.
+ * @param[in] mask user\@host or user\@ip mask to check.
+ * @param[in] flags Bitmask possibly containing the value GLINE_LOCAL, to limit searches to this server.
+ * @return Count of matching users.
+ */
+static int
+count_users(char *mask, int flags)
+{
+  struct irc_in_addr ipmask;
+  struct Client *acptr;
+  int count = 0;
+  int ipmask_valid;
+  char namebuf[USERLEN + HOSTLEN + 2];
+  char ipbuf[USERLEN + SOCKIPLEN + 2];
+  unsigned char ipmask_len;
+
+  ipmask_valid = ipmask_parse(mask, &ipmask, &ipmask_len);
+  for (acptr = GlobalClientList; acptr; acptr = cli_next(acptr)) {
+    if (!IsUser(acptr))
+      continue;
+    if ((flags & GLINE_LOCAL) && !MyConnect(acptr))
+      continue;
+
+    ircd_snprintf(0, namebuf, sizeof(namebuf), "%s@%s",
+                 cli_user(acptr)->username, cli_user(acptr)->realhost);
+    ircd_snprintf(0, ipbuf, sizeof(ipbuf), "%s@%s", cli_user(acptr)->username,
+                 ircd_ntoa(&cli_ip(acptr)));
+
+    if (!match(mask, namebuf)
+        || !match(mask, ipbuf)
+        || (ipmask_valid && ipmask_check(&cli_ip(acptr), &ipmask, ipmask_len)))
+      count++;
+  }
+
+  return count;
+}
+
+/** Count number of users with a realname matching \a mask.
+ * @param[in] mask Wildcard mask to match against realnames.
+ * @return Count of matching users.
+ */
+static int
+count_realnames(const char *mask)
+{
+  struct Client *acptr;
+  int minlen;
+  int count;
+  char cmask[BUFSIZE];
+
+  count = 0;
+  matchcomp(cmask, &minlen, NULL, mask);
+  for (acptr = GlobalClientList; acptr; acptr = cli_next(acptr)) {
+    if (!IsUser(acptr))
+      continue;
+    if (strlen(cli_info(acptr)) < minlen)
+      continue;
+    if (!matchexec(cli_info(acptr), cmask, minlen))
+      count++;
+  }
+  return count;
+}
+
 /** Create a new G-line and add it to global lists.
  * \a userhost may be in one of four forms:
  * \li A channel name, to add a BadChan.
@@ -391,7 +421,7 @@ gline_propagate(struct Client *cptr, struct Client *sptr, struct Gline *gline)
  * @param[in] sptr Client that originated the G-line.
  * @param[in] userhost Text mask for the G-line.
  * @param[in] reason Reason for G-line.
- * @param[in] expire Duration of G-line in seconds.
+ * @param[in] expire Expiration time of G-line.
  * @param[in] lastmod Last modification time of G-line.
  * @param[in] lifetime Lifetime of G-line.
  * @param[in] flags Bitwise combination of GLINE_* flags.
@@ -409,6 +439,8 @@ gline_add(struct Client *cptr, struct Client *sptr, char *userhost,
 
   assert(0 != userhost);
   assert(0 != reason);
+  assert(((flags & (GLINE_GLOBAL | GLINE_LOCAL)) == GLINE_GLOBAL) ||
+         ((flags & (GLINE_GLOBAL | GLINE_LOCAL)) == GLINE_LOCAL));
 
   Debug((DEBUG_DEBUG, "gline_add(\"%s\", \"%s\", \"%s\", \"%s\", %Tu, %Tu "
         "%Tu, 0x%04x)", cli_name(cptr), cli_name(sptr), userhost, reason,
@@ -417,27 +449,38 @@ gline_add(struct Client *cptr, struct Client *sptr, char *userhost,
   if (*userhost == '#' || *userhost == '&') {
     if ((flags & GLINE_LOCAL) && !HasPriv(sptr, PRIV_LOCAL_BADCHAN))
       return send_reply(sptr, ERR_NOPRIVILEGES);
+    /* Allow maximum channel name length, plus margin for wildcards. */
+    if (strlen(userhost+1) >= CHANNELLEN + 6)
+      return send_reply(sptr, ERR_LONGMASK);
 
     flags |= GLINE_BADCHAN;
     user = userhost;
-    host = 0;
+    host = NULL;
   } else if (*userhost == '$') {
     switch (userhost[1]) {
-      case 'R': flags |= GLINE_REALNAME; break;
+      case 'R':
+        /* Allow REALLEN for the real name, plus margin for wildcards. */
+        if (strlen(userhost+2) >= REALLEN + 6)
+          return send_reply(sptr, ERR_LONGMASK);
+        flags |= GLINE_REALNAME;
+        break;
       default:
         /* uh, what to do here? */
         /* The answer, my dear Watson, is we throw a protocol_violation()
            -- hikari */
         if (IsServer(cptr))
           return protocol_violation(sptr,"%s has been smoking the sweet leaf and sent me a whacky gline",cli_name(sptr));
-        else {
-         sendto_opmask_butone(NULL, SNO_GLINE, "%s has been smoking the sweet leaf and sent me a whacky gline", cli_name(sptr));
-         return 0;
-        }
-        break;
+        sendto_opmask_butone(NULL, SNO_GLINE, "%s has been smoking the sweet leaf and sent me a whacky gline", cli_name(sptr));
+        return 0;
+    }
+    user = userhost;
+    host = NULL;
+    if (MyUser(sptr) || (IsUser(sptr) && flags & GLINE_LOCAL)) {
+      tmp = count_realnames(userhost + 2);
+      if ((tmp >= feature_int(FEAT_GLINEMAXUSERCOUNT))
+         && !(flags & GLINE_OPERFORCE))
+       return send_reply(sptr, ERR_TOOMANYUSERS, tmp);
     }
-     user = userhost;
-     host = 0;
   } else {
     canon_userhost(userhost, &user, &host, "*");
     if (sizeof(uhmask) <
@@ -454,7 +497,7 @@ gline_add(struct Client *cptr, struct Client *sptr, char *userhost,
        break;
       }
 
-      if ((tmp = count_users(uhmask)) >=
+      if ((tmp = count_users(uhmask, flags)) >=
          feature_int(FEAT_GLINEMAXUSERCOUNT) && !(flags & GLINE_OPERFORCE))
        return send_reply(sptr, ERR_TOOMANYUSERS, tmp);
     }
@@ -464,31 +507,34 @@ gline_add(struct Client *cptr, struct Client *sptr, char *userhost,
    * You cannot set a negative (or zero) expire time, nor can you set an
    * expiration time for greater than GLINE_MAX_EXPIRE.
    */
-  if (!(flags & GLINE_FORCE) && (expire <= 0 || expire > GLINE_MAX_EXPIRE)) {
+  if (!(flags & GLINE_FORCE) &&
+      (expire <= TStime() || expire > TStime() + GLINE_MAX_EXPIRE)) {
     if (!IsServer(sptr) && MyConnect(sptr))
       send_reply(sptr, ERR_BADEXPIRE, expire);
     return 0;
+  } else if (expire <= TStime()) {
+    /* This expired G-line was forced to be added, so mark it inactive. */
+    flags &= ~GLINE_ACTIVE;
   }
 
-  expire += CurrentTime; /* convert from lifetime to timestamp */
-
   if (!lifetime) /* no lifetime set, use expiration time */
     lifetime = expire;
-  else /* convert lifetime into timestamp */
-    lifetime += CurrentTime;
+
+  /* lifetime is already an absolute timestamp */
 
   /* Inform ops... */
   sendto_opmask_butone(0, ircd_strncmp(reason, "AUTO", 4) ? SNO_GLINE :
-                       SNO_AUTO, "%s adding %s %s for %s%s%s, expiring at "
+                       SNO_AUTO, "%s adding %s%s %s for %s%s%s, expiring at "
                        "%Tu: %s",
                        (feature_bool(FEAT_HIS_SNOTICES) || IsServer(sptr)) ?
                          cli_name(sptr) :
                          cli_name((cli_user(sptr))->server),
+                       (flags & GLINE_ACTIVE) ? "" : "deactivated ",
                       (flags & GLINE_LOCAL) ? "local" : "global",
                       (flags & GLINE_BADCHAN) ? "BADCHAN" : "GLINE", user,
                       (flags & (GLINE_BADCHAN|GLINE_REALNAME)) ? "" : "@",
                       (flags & (GLINE_BADCHAN|GLINE_REALNAME)) ? "" : host,
-                      expire + TSoffset, reason);
+                      expire, reason);
 
   /* and log it */
   log_write(LS_GLINE, L_INFO, LOG_NOSNOTICE,
@@ -497,7 +543,7 @@ gline_add(struct Client *cptr, struct Client *sptr, char *userhost,
            flags & GLINE_BADCHAN ? "BADCHAN" : "GLINE", user,
            flags & (GLINE_BADCHAN|GLINE_REALNAME) ? "" : "@",
            flags & (GLINE_BADCHAN|GLINE_REALNAME) ? "" : host,
-           expire + TSoffset, reason);
+           expire, reason);
 
   /* make the gline */
   agline = make_gline(user, host, reason, expire, lastmod, lifetime, flags);
@@ -506,8 +552,6 @@ gline_add(struct Client *cptr, struct Client *sptr, char *userhost,
    * never be NULL...
    */
   assert(agline);
-/*   if (!agline) /\* if it overlapped, silently return *\/ */
-/*     return 0; */
 
   gline_propagate(cptr, sptr, agline);
 
@@ -557,14 +601,14 @@ gline_activate(struct Client *cptr, struct Client *sptr, struct Gline *gline,
                        GlineIsBadChan(gline) ? "BADCHAN" : "GLINE",
                        gline->gl_user, gline->gl_host ? "@" : "",
                        gline->gl_host ? gline->gl_host : "",
-                       gline->gl_expire + TSoffset, gline->gl_reason);
-  
+                       gline->gl_expire, gline->gl_reason);
+
   log_write(LS_GLINE, L_INFO, LOG_NOSNOTICE,
            "%#C activating global %s for %s%s%s, expiring at %Tu: %s", sptr,
            GlineIsBadChan(gline) ? "BADCHAN" : "GLINE", gline->gl_user,
            gline->gl_host ? "@" : "",
            gline->gl_host ? gline->gl_host : "",
-           gline->gl_expire + TSoffset, gline->gl_reason);
+           gline->gl_expire, gline->gl_reason);
 
   if (!(flags & GLINE_LOCAL)) /* don't propagate local changes */
     gline_propagate(cptr, sptr, gline);
@@ -625,14 +669,14 @@ gline_deactivate(struct Client *cptr, struct Client *sptr, struct Gline *gline,
                       msg, GlineIsBadChan(gline) ? "BADCHAN" : "GLINE",
                       gline->gl_user, gline->gl_host ? "@" : "",
                        gline->gl_host ? gline->gl_host : "",
-                      gline->gl_expire + TSoffset, gline->gl_reason);
+                      gline->gl_expire, gline->gl_reason);
 
   log_write(LS_GLINE, L_INFO, LOG_NOSNOTICE,
            "%#C %s %s for %s%s%s, expiring at %Tu: %s", sptr, msg,
            GlineIsBadChan(gline) ? "BADCHAN" : "GLINE", gline->gl_user,
            gline->gl_host ? "@" : "",
            gline->gl_host ? gline->gl_host : "",
-           gline->gl_expire + TSoffset, gline->gl_reason);
+           gline->gl_expire, gline->gl_reason);
 
   if (!(flags & GLINE_LOCAL)) /* don't propagate local changes */
     gline_propagate(cptr, sptr, gline);
@@ -650,7 +694,7 @@ gline_deactivate(struct Client *cptr, struct Client *sptr, struct Gline *gline,
  * @param[in] gline G-line being modified.
  * @param[in] action Resultant status of the G-line.
  * @param[in] reason Reason for G-line.
- * @param[in] expire Duration of G-line in seconds.
+ * @param[in] expire Expiration time of G-line.
  * @param[in] lastmod Last modification time of G-line.
  * @param[in] lifetime Lifetime of G-line.
  * @param[in] flags Bitwise combination of GLINE_* flags.
@@ -662,7 +706,7 @@ gline_modify(struct Client *cptr, struct Client *sptr, struct Gline *gline,
             time_t lastmod, time_t lifetime, unsigned int flags)
 {
   char buf[BUFSIZE], *op = "";
-  int pos = 0;
+  int pos = 0, non_auto = 0;
 
   assert(gline);
   assert(!GlineIsLocal(gline));
@@ -691,14 +735,12 @@ gline_modify(struct Client *cptr, struct Client *sptr, struct Gline *gline,
   /* All right, we know that there's a change of some sort.  What is it? */
   /* first, check out the expiration time... */
   if ((flags & GLINE_EXPIRE) && expire) {
-    if (!(flags & GLINE_FORCE) && (expire <= 0 || expire > GLINE_MAX_EXPIRE)) {
+    if (!(flags & GLINE_FORCE) &&
+       (expire <= TStime() || expire > TStime() + GLINE_MAX_EXPIRE)) {
       if (!IsServer(sptr) && MyConnect(sptr)) /* bad expiration time */
        send_reply(sptr, ERR_BADEXPIRE, expire);
       return 0;
     }
-
-    /* convert to a timestamp... */
-    expire += CurrentTime;
   } else
     flags &= ~GLINE_EXPIRE;
 
@@ -709,9 +751,7 @@ gline_modify(struct Client *cptr, struct Client *sptr, struct Gline *gline,
   }
 
   /* Next, check out lifetime--this one's a bit trickier... */
-  if ((flags & GLINE_LIFETIME) && lifetime)
-    lifetime += CurrentTime; /* convert to a timestamp */
-  else
+  if (!(flags & GLINE_LIFETIME) || !lifetime)
     lifetime = gline->gl_lifetime; /* use G-line lifetime */
 
   lifetime = IRCD_MAX(lifetime, expire); /* set lifetime to the max */
@@ -737,7 +777,7 @@ gline_modify(struct Client *cptr, struct Client *sptr, struct Gline *gline,
       (action == GLINE_LOCAL_DEACTIVATE &&
        (gline->gl_state == GLOCAL_DEACTIVATED)) ||
       /* can't activate an expired G-line */
-      IRCD_MAX(gline->gl_expire, expire) <= CurrentTime)
+      IRCD_MAX(gline->gl_expire, expire) <= TStime())
     action = GLINE_MODIFY; /* no activity state modifications */
 
   Debug((DEBUG_DEBUG,  "About to perform changes; flags 0x%04x, action %s",
@@ -810,6 +850,7 @@ gline_modify(struct Client *cptr, struct Client *sptr, struct Gline *gline,
 
   /* Now, handle reason changes... */
   if (flags & GLINE_REASON) {
+    non_auto = non_auto || ircd_strncmp(gline->gl_reason, "AUTO", 4);
     MyFree(gline->gl_reason); /* release old reason */
     DupString(gline->gl_reason, reason); /* store new reason */
     if (pos < BUFSIZE)
@@ -819,7 +860,9 @@ gline_modify(struct Client *cptr, struct Client *sptr, struct Gline *gline,
   }
 
   /* All right, inform ops... */
-  sendto_opmask_butone(0, SNO_GLINE, "%s modifying global %s for %s%s%s:%s",
+  non_auto = non_auto || ircd_strncmp(gline->gl_reason, "AUTO", 4);
+  sendto_opmask_butone(0, non_auto ? SNO_GLINE : SNO_AUTO,
+                      "%s modifying global %s for %s%s%s:%s",
                       (feature_bool(FEAT_HIS_SNOTICES) || IsServer(sptr)) ?
                       cli_name(sptr) : cli_name((cli_user(sptr))->server),
                       GlineIsBadChan(gline) ? "BADCHAN" : "GLINE",
@@ -842,8 +885,8 @@ gline_modify(struct Client *cptr, struct Client *sptr, struct Gline *gline,
                          flags & GLINE_OPERFORCE ? "!" : "", op,
                          gline->gl_user, gline->gl_host ? "@" : "",
                          gline->gl_host ? gline->gl_host : "",
-                         gline->gl_expire - CurrentTime, gline->gl_lastmod,
-                         gline->gl_lifetime - CurrentTime, gline->gl_reason);
+                         gline->gl_expire - TStime(), gline->gl_lastmod,
+                         gline->gl_lifetime, gline->gl_reason);
 
   /* OK, let's do the G-line... */
   return do_gline(cptr, sptr, gline);
@@ -902,8 +945,7 @@ gline_find(char *userhost, unsigned int flags)
 
   if (flags & (GLINE_BADCHAN | GLINE_ANY)) {
     gliter(BadChanGlineList, gline, sgline) {
-      if ((flags & GLINE_GLOBAL && gline->gl_flags & GLINE_LOCAL) ||
-         (flags & GLINE_LOCAL && gline->gl_flags & GLINE_GLOBAL) ||
+        if ((flags & (GlineIsLocal(gline) ? GLINE_GLOBAL : GLINE_LOCAL)) ||
          (flags & GLINE_LASTMOD && !gline->gl_lastmod))
        continue;
       else if ((flags & GLINE_EXACT ? ircd_strcmp(gline->gl_user, userhost) :
@@ -920,8 +962,7 @@ gline_find(char *userhost, unsigned int flags)
   canon_userhost(t_uh, &user, &host, "*");
 
   gliter(GlobalGlineList, gline, sgline) {
-    if ((flags & GLINE_GLOBAL && gline->gl_flags & GLINE_LOCAL) ||
-       (flags & GLINE_LOCAL && gline->gl_flags & GLINE_GLOBAL) ||
+    if ((flags & (GlineIsLocal(gline) ? GLINE_GLOBAL : GLINE_LOCAL)) ||
        (flags & GLINE_LASTMOD && !gline->gl_lastmod))
       continue;
     else if (flags & GLINE_EXACT) {
@@ -1020,16 +1061,16 @@ gline_burst(struct Client *cptr)
                    GlineIsRemActive(gline) ? '+' : '-', gline->gl_user,
                     gline->gl_host ? "@" : "",
                     gline->gl_host ? gline->gl_host : "",
-                   gline->gl_expire - CurrentTime, gline->gl_lastmod,
-                    gline->gl_lifetime - CurrentTime, gline->gl_reason);
+                   gline->gl_expire - TStime(), gline->gl_lastmod,
+                    gline->gl_lifetime, gline->gl_reason);
   }
 
   gliter(BadChanGlineList, gline, sgline) {
     if (!GlineIsLocal(gline) && gline->gl_lastmod)
       sendcmdto_one(&me, CMD_GLINE, cptr, "* %c%s %Tu %Tu %Tu :%s",
                    GlineIsRemActive(gline) ? '+' : '-', gline->gl_user,
-                   gline->gl_expire - CurrentTime, gline->gl_lastmod,
-                   gline->gl_lifetime - CurrentTime, gline->gl_reason);
+                   gline->gl_expire - TStime(), gline->gl_lastmod,
+                   gline->gl_lifetime, gline->gl_reason);
   }
 }
 
@@ -1048,8 +1089,8 @@ gline_resend(struct Client *cptr, struct Gline *gline)
                GlineIsRemActive(gline) ? '+' : '-', gline->gl_user,
                gline->gl_host ? "@" : "",
                 gline->gl_host ? gline->gl_host : "",
-               gline->gl_expire - CurrentTime, gline->gl_lastmod,
-               gline->gl_lifetime - CurrentTime, gline->gl_reason);
+               gline->gl_expire - TStime(), gline->gl_lastmod,
+               gline->gl_lifetime, gline->gl_reason);
 
   return 0;
 }
@@ -1075,8 +1116,8 @@ gline_list(struct Client *sptr, char *userhost)
     send_reply(sptr, RPL_GLIST, gline->gl_user,
                gline->gl_host ? "@" : "",
                gline->gl_host ? gline->gl_host : "",
-              gline->gl_expire + TSoffset, gline->gl_lastmod,
-              gline->gl_lifetime + TSoffset,
+              gline->gl_expire, gline->gl_lastmod,
+              gline->gl_lifetime,
               GlineIsLocal(gline) ? cli_name(&me) : "*",
               gline->gl_state == GLOCAL_ACTIVATED ? ">" :
               (gline->gl_state == GLOCAL_DEACTIVATED ? "<" : ""),
@@ -1086,8 +1127,8 @@ gline_list(struct Client *sptr, char *userhost)
       send_reply(sptr, RPL_GLIST, gline->gl_user,
                 gline->gl_host ? "@" : "",
                 gline->gl_host ? gline->gl_host : "",
-                gline->gl_expire + TSoffset, gline->gl_lastmod,
-                gline->gl_lifetime + TSoffset,
+                gline->gl_expire, gline->gl_lastmod,
+                gline->gl_lifetime,
                 GlineIsLocal(gline) ? cli_name(&me) : "*",
                 gline->gl_state == GLOCAL_ACTIVATED ? ">" :
                 (gline->gl_state == GLOCAL_DEACTIVATED ? "<" : ""),
@@ -1096,8 +1137,8 @@ gline_list(struct Client *sptr, char *userhost)
 
     gliter(BadChanGlineList, gline, sgline) {
       send_reply(sptr, RPL_GLIST, gline->gl_user, "", "",
-                gline->gl_expire + TSoffset, gline->gl_lastmod,
-                gline->gl_lifetime + TSoffset,
+                gline->gl_expire, gline->gl_lastmod,
+                gline->gl_lifetime,
                 GlineIsLocal(gline) ? cli_name(&me) : "*",
                 gline->gl_state == GLOCAL_ACTIVATED ? ">" :
                 (gline->gl_state == GLOCAL_DEACTIVATED ? "<" : ""),
@@ -1125,8 +1166,8 @@ gline_stats(struct Client *sptr, const struct StatDesc *sd,
     send_reply(sptr, RPL_STATSGLINE, 'G', gline->gl_user,
               gline->gl_host ? "@" : "",
               gline->gl_host ? gline->gl_host : "",
-              gline->gl_expire + TSoffset, gline->gl_lastmod,
-              gline->gl_lifetime + TSoffset,
+              gline->gl_expire, gline->gl_lastmod,
+              gline->gl_lifetime,
               gline->gl_state == GLOCAL_ACTIVATED ? ">" :
               (gline->gl_state == GLOCAL_DEACTIVATED ? "<" : ""),
               GlineIsRemActive(gline) ? '+' : '-',