Author: Isomer <isomer@coders.net>
[ircu2.10.12-pk.git] / ircd / s_user.c
index 7bd0a9c0abac8b91e63c855adaa3fcbc837daf1d..1c93ad4188d816305b1f2b8766a4a7c926694266 100644 (file)
@@ -266,12 +266,57 @@ int hunt_server(int MustBeOper, struct Client *cptr, struct Client *sptr, char *
 
   assert(!IsServer(sptr));
   /* XXX sendto_one used with explicit command; must be very careful */
-  sendto_one(acptr, command, NumNick(sptr), parv[1], parv[2], parv[3], parv[4],
+  sendto_one(acptr, command, NumNick(sptr), parv[1], parv[2], parv[3], parv[4], /* XXX hunt_server */
       parv[5], parv[6], parv[7], parv[8]);
 
   return (HUNTED_PASS);
 }
 
+int hunt_server_cmd(struct Client *from, const char *cmd, const char *tok,
+                   struct Client *one, int MustBeOper, const char *pattern,
+                   int server, int parc, char *parv[])
+{
+  struct Client *acptr;
+  char *to;
+
+  /* Assume it's me, if no server or an unregistered client */
+  if (parc <= server || EmptyString((to = parv[server])) || IsUnknown(from))
+    return (HUNTED_ISME);
+
+  /* Make sure it's a server */
+  if (MyUser(from)) {
+    /* Make sure it's a server */
+    if (!strchr(to, '*')) {
+      if (0 == (acptr = FindClient(to)))
+        return HUNTED_NOSUCH;
+
+      if (acptr->user)
+        acptr = acptr->user->server;
+    } else if (!(acptr = find_match_server(to))) {
+      send_reply(from, ERR_NOSUCHSERVER, to);
+      return (HUNTED_NOSUCH);
+    }
+  } else if (!(acptr = FindNServer(to)))
+    return (HUNTED_NOSUCH);        /* Server broke off in the meantime */
+
+  if (IsMe(acptr))
+    return (HUNTED_ISME);
+
+  if (MustBeOper && !IsPrivileged(from)) {
+    send_reply(from, ERR_NOPRIVILEGES);
+    return HUNTED_NOSUCH;
+  }
+
+  assert(!IsServer(from));
+
+  parv[server] = (char *) acptr; /* HACK! HACK! HACK! ARGH! */
+
+  sendcmdto_one(from, cmd, tok, acptr, pattern, parv[1], parv[2], parv[3],
+               parv[4], parv[5], parv[6], parv[7], parv[8]);
+
+  return (HUNTED_PASS);
+}
+
 /*
  * 'do_nick_name' ensures that the given parameter (nick) is really a proper
  * string for a nickname (note, the 'nick' may be modified in the process...)
@@ -362,7 +407,7 @@ static char *clean_user_id(char *dest, char *source, int tilde)
  *    nick from local user or kill him/her...
  */
 int register_user(struct Client *cptr, struct Client *sptr,
-                  const char *nick, char *username)
+                  const char *nick, char *username, struct Gline *agline)
 {
   struct ConfItem* aconf;
   char*            parv[3];
@@ -381,7 +426,6 @@ int register_user(struct Client *cptr, struct Client *sptr,
   struct User*     user = sptr->user;
   char             ip_base64[8];
   char             featurebuf[512];
-  struct Gline*    gline;
 
   user->last = CurrentTime;
   parv[0] = sptr->name;
@@ -412,7 +456,6 @@ int register_user(struct Client *cptr, struct Client *sptr,
                               get_client_name(sptr, HIDE_IP));
         }
         ++ServerStats->is_ref;
-        IPcheck_connect_fail(sptr->ip);
         return exit_client(cptr, sptr, &me,
                           "Sorry, your connection class is full - try "
                           "again later or try another server");
@@ -431,7 +474,6 @@ int register_user(struct Client *cptr, struct Client *sptr,
         /* Can this ever happen? */
       case ACR_BAD_SOCKET:
         ++ServerStats->is_ref;
-        IPcheck_connect_fail(sptr->ip);
         return exit_client(cptr, sptr, &me, "Unknown error -- Try again");
     }
     ircd_strncpy(user->host, sptr->sockhost, HOSTLEN);
@@ -447,13 +489,9 @@ int register_user(struct Client *cptr, struct Client *sptr,
 
     if (!EmptyString(aconf->passwd)
         && !(IsDigit(*aconf->passwd) && !aconf->passwd[1])
-#ifdef USEONE
-        && strcmp("ONE", aconf->passwd)
-#endif
         && strcmp(sptr->passwd, aconf->passwd))
     {
       ServerStats->is_ref++;
-      IPcheck_connect_fail(sptr->ip);
       send_reply(sptr, ERR_PASSWDMISMATCH);
       return exit_client(cptr, sptr, &me, "Bad Password");
     }
@@ -463,7 +501,6 @@ int register_user(struct Client *cptr, struct Client *sptr,
      */
     if (find_kill(sptr)) {
       ServerStats->is_ref++;
-      IPcheck_connect_fail(sptr->ip);
       return exit_client(cptr, sptr, &me, "K-lined");
     }
     /*
@@ -535,11 +572,11 @@ int register_user(struct Client *cptr, struct Client *sptr,
     {
       ServerStats->is_ref++;
 
-      send_reply(cptr, RPL_EXPLICIT | ERR_INVALIDUSERNAME,
+      send_reply(cptr, SND_EXPLICIT | ERR_INVALIDUSERNAME,
                 ":Your username is invalid.");
-      send_reply(cptr, RPL_EXPLICIT | ERR_INVALIDUSERNAME,
+      send_reply(cptr, SND_EXPLICIT | ERR_INVALIDUSERNAME,
                 ":Connect with your real username, in lowercase.");
-      send_reply(cptr, RPL_EXPLICIT | ERR_INVALIDUSERNAME,
+      send_reply(cptr, SND_EXPLICIT | ERR_INVALIDUSERNAME,
                 ":If your mail address were foo@bar.com, your username "
                 "would be foo.");
       return exit_client(cptr, sptr, &me, "USER: Bad username");
@@ -549,11 +586,17 @@ int register_user(struct Client *cptr, struct Client *sptr,
   else {
     ircd_strncpy(user->username, username, USERLEN);
     Count_newremoteclient(UserStats, user->server);
-    if ((gline = gline_lookup(sptr)) && GlineIsActive(gline))
-      gline_resend(cptr, gline);
   }
   SetUser(sptr);
 
+  /* a gline wasn't passed in, so find a matching global one that isn't
+   * a Uworld-set one, and propagate it if there is such an animal.
+   */
+  if (!agline &&
+      (agline = gline_lookup(sptr, GLINE_GLOBAL | GLINE_LASTMOD)) &&
+      !IsBurstOrBurstAck(cptr))
+    gline_resend(cptr, agline);
+  
   if (IsInvisible(sptr))
     ++UserStats.inv_clients;
   if (IsOper(sptr))
@@ -582,17 +625,7 @@ int register_user(struct Client *cptr, struct Client *sptr,
     nextping = CurrentTime;
     if (sptr->snomask & SNO_NOISY)
       set_snomask(sptr, sptr->snomask & SNO_NOISY, SNO_ADD);
-#ifdef ALLOW_SNO_CONNEXIT
-#ifdef SNO_CONNEXIT_IP
-    sendto_opmask_butone(0, SNO_CONNEXIT, "Client connecting: %s (%s@%s) "
-                        "[%s] {%d}", nick, user->username, user->host,
-                        cptr->sock_ip, get_client_class(sptr));
-#else /* SNO_CONNEXIT_IP */
-    sendto_opmask_butone(0, SNO_CONEXIT, "Client connecting: %s (%s@%s)",
-                        nick, user->username, user->host);
-#endif /* SNO_CONNEXIT_IP */
-#endif /* ALLOW_SNO_CONNEXIT */
-    IPcheck_connect_succeeded(sptr);
+    ip_registry_connect_succeeded(sptr);
   }
   else
     /* if (IsServer(cptr)) */
@@ -621,22 +654,27 @@ int register_user(struct Client *cptr, struct Client *sptr,
       if (IsBurst(acptr) || Protocol(acptr) < 10)
         break;
     }
-    if (!IPcheck_remote_connect(sptr, (acptr != &me)))
-      /*
-       * We ran out of bits to count this
-       */
-      return exit_client(cptr, sptr, &me, "More than 255 connections from this address");
   }
-
   tmpstr = umode_str(sptr);
-  sendcmdto_serv_butone(user->server, CMD_NICK, cptr, *tmpstr ?
-                       "%s %d %d %s %s +%s %s %s%s :%s" :
-                       "%s %d %d %s %s %s%s %s%s :%s",
-                       nick, sptr->hopcount + 1, sptr->lastnick,
-                       user->username, user->host, tmpstr,
-                       inttobase64(ip_base64, ntohl(sptr->ip.s_addr), 6),
-                       NumNick(sptr), sptr->info);
-
+  if (agline)
+    sendcmdto_serv_butone(user->server, CMD_NICK, cptr,
+                         "%s %d %Tu %s %s %s%s%s%%%Tu:%s@%s %s %s%s :%s",
+                         nick, sptr->hopcount + 1, sptr->lastnick,
+                         user->username, user->host,
+                         *tmpstr ? "+" : "", tmpstr, *tmpstr ? " " : "",
+                         GlineLastMod(agline), GlineUser(agline),
+                         GlineHost(agline),
+                         inttobase64(ip_base64, ntohl(sptr->ip.s_addr), 6),
+                         NumNick(sptr), sptr->info);
+  else
+    sendcmdto_serv_butone(user->server, CMD_NICK, cptr,
+                         "%s %d %Tu %s %s %s%s%s%s %s%s :%s",
+                         nick, sptr->hopcount + 1, sptr->lastnick,
+                         user->username, user->host,
+                         *tmpstr ? "+" : "", tmpstr, *tmpstr ? " " : "",
+                         inttobase64(ip_base64, ntohl(sptr->ip.s_addr), 6),
+                         NumNick(sptr), sptr->info);
+  
   /* Send umode to client */
   if (MyUser(sptr))
   {
@@ -690,6 +728,8 @@ int set_nick_name(struct Client* cptr, struct Client* sptr,
   if (IsServer(sptr)) {
     int   i;
     const char* p;
+    char *t;
+    struct Gline *agline = 0;
 
     /*
      * A server introducing a new client, change source
@@ -728,7 +768,26 @@ int set_nick_name(struct Client* cptr, struct Client* sptr,
     ircd_strncpy(new_client->username, parv[4], USERLEN);
     ircd_strncpy(new_client->user->host, parv[5], HOSTLEN);
     ircd_strncpy(new_client->info, parv[parc - 1], REALLEN);
-    return register_user(cptr, new_client, new_client->name, parv[4]);
+
+    /* Deal with GLINE parameters... */
+    if (*parv[parc - 4] == '%' && (t = strchr(parv[parc - 4] + 1, ':'))) {
+      time_t lastmod;
+
+      *(t++) = '\0';
+      lastmod = atoi(parv[parc - 4] + 1);
+
+      if (lastmod &&
+         (agline = gline_find(t, GLINE_EXACT | GLINE_GLOBAL | GLINE_LASTMOD))
+         && GlineLastMod(agline) > lastmod && !IsBurstOrBurstAck(cptr))
+       gline_resend(cptr, agline);
+    }
+    if (!ip_registry_remote_connect(new_client)) {
+       sendcmdto_one(&me, CMD_KILL, new_client, "%C :%s (Too many connections from your host -- Ghost)",
+                     new_client,me.name);
+       return exit_client(cptr,new_client,&me,"Too many connections from your host -- throttled");
+    }
+    sendto_ops("Registering new remote client");
+    return register_user(cptr, new_client, new_client->name, parv[4], agline);
   }
   else if (sptr->name[0]) {
     /*
@@ -821,7 +880,7 @@ int set_nick_name(struct Client* cptr, struct Client* sptr,
        * for it - must test this and exit m_nick too !
        */
       sptr->lastnick = TStime();        /* Always local client */
-      if (register_user(cptr, sptr, nick, sptr->user->username) == CPTR_KILLED)
+      if (register_user(cptr, sptr, nick, sptr->user->username, 0) == CPTR_KILLED)
         return CPTR_KILLED;
     }
   }