implement IAUTH client code to query a separate server before allowing
[ircu2.10.12-pk.git] / ircd / s_user.c
index 990d4ff7646edd1c3aca97c2f1f8f1fc21be85aa..2aefc68517d0aa7fd112a98ffe30df147434e5b6 100644 (file)
@@ -32,6 +32,7 @@
 #include "hash.h"
 #include "ircd.h"
 #include "ircd_alloc.h"
+#include "ircd_auth.h"
 #include "ircd_chattr.h"
 #include "ircd_features.h"
 #include "ircd_log.h"
@@ -348,7 +349,7 @@ int register_user(struct Client *cptr, struct Client *sptr,
                   const char *nick, char *username)
 {
   struct ConfItem* aconf;
-  char*            parv[3];
+  char*            parv[4];
   char*            tmpstr;
   char*            tmpstr2;
   char             c = 0;    /* not alphanum */
@@ -362,7 +363,7 @@ int register_user(struct Client *cptr, struct Client *sptr,
   short            badid = 0;
   short            digitgroups = 0;
   struct User*     user = cli_user(sptr);
-  struct Flags flag;
+  int              killreason;
   char             ip_base64[8];
 
   user->last = CurrentTime;
@@ -375,6 +376,12 @@ int register_user(struct Client *cptr, struct Client *sptr,
     static time_t last_too_many2;
 
     assert(cptr == sptr);
+    if (!IsIAuthed(sptr)) {
+      if (iauth_active)
+        return iauth_start_client(iauth_active, sptr);
+      else
+        SetIAuthed(sptr);
+    }
     switch (conf_check_client(sptr))
     {
       case ACR_OK:
@@ -433,7 +440,6 @@ int register_user(struct Client *cptr, struct Client *sptr,
         && strcmp(cli_passwd(sptr), aconf->passwd))
     {
       ServerStats->is_ref++;
-      IPcheck_connect_fail(cli_ip(sptr));
       send_reply(sptr, ERR_PASSWDMISMATCH);
       return exit_client(cptr, sptr, &me, "Bad Password");
     }
@@ -441,10 +447,11 @@ int register_user(struct Client *cptr, struct Client *sptr,
     /*
      * following block for the benefit of time-dependent K:-lines
      */
-    if (find_kill(sptr)) {
+    killreason = find_kill(sptr);
+    if (killreason) {
       ServerStats->is_ref++;
-      IPcheck_connect_fail(cli_ip(sptr));
-      return exit_client(cptr, sptr, &me, "K-lined");
+      return exit_client(cptr, sptr, &me,
+                         (killreason == -1 ? "K-lined" : "G-lined"));
     }
     /*
      * Check for mixed case usernames, meaning probably hacked.  Jon2 3-94
@@ -540,9 +547,10 @@ int register_user(struct Client *cptr, struct Client *sptr,
   if (MyConnect(sptr)) {
     cli_handler(sptr) = CLIENT_HANDLER;
     release_dns_reply(sptr);
-
+    SetLocalNumNick(sptr);
     send_reply(sptr,
                RPL_WELCOME,
+               feature_str(FEAT_NETWORK),
                feature_str(FEAT_PROVIDER) ? " via " : "",
                feature_str(FEAT_PROVIDER) ? feature_str(FEAT_PROVIDER) : "",
                nick);
@@ -551,7 +559,8 @@ int register_user(struct Client *cptr, struct Client *sptr,
      */
     send_reply(sptr, RPL_YOURHOST, cli_name(&me), version);
     send_reply(sptr, RPL_CREATED, creation);
-    send_reply(sptr, RPL_MYINFO, cli_name(&me), version);
+    send_reply(sptr, RPL_MYINFO, cli_name(&me), infousermodes, infochanmodes,
+               infochanmodeswithparams, version);
     send_supported(sptr);
     m_lusers(sptr, sptr, 1, parv);
     update_load();
@@ -561,11 +570,21 @@ int register_user(struct Client *cptr, struct Client *sptr,
       set_snomask(sptr, cli_snomask(sptr) & SNO_NOISY, SNO_ADD);
     if (feature_bool(FEAT_CONNEXIT_NOTICES))
       sendto_opmask_butone(0, SNO_CONNEXIT,
-                           "Client connecting: %s (%s@%s) [%s] {%d}",
+                           "Client connecting: %s (%s@%s) [%s] {%d} [%s] <%s%s>",
                            cli_name(sptr), user->username, user->host,
-                           cli_sock_ip(sptr), get_client_class(sptr));
+                           cli_sock_ip(sptr), get_client_class(sptr),
+                           cli_info(sptr), NumNick(cptr) /* two %s's */);
 
     IPcheck_connect_succeeded(sptr);
+    /*
+     * Set user's initial modes
+     */
+    parv[0] = (char*)nick;
+    parv[1] = (char*)nick;
+    parv[2] = (char*)client_get_default_umode(sptr);
+    parv[3] = NULL; /* needed in case of +s */
+    set_user_mode(sptr, sptr, 3, parv);
+    ClearHiddenHost(sptr); /* just in case somebody stuck +x in there */
   }
   else
     /* if (IsServer(cptr)) */
@@ -614,13 +633,9 @@ int register_user(struct Client *cptr, struct Client *sptr,
                        inttobase64(ip_base64, ntohl(cli_ip(sptr).s_addr), 6),
                        NumNick(sptr), cli_info(sptr));
   
-  /* Send umode to client */
-  if (MyUser(sptr))
-  {
-    send_umode(cptr, sptr, &flag, ALL_UMODES);
-    if (cli_snomask(sptr) != SNO_DEFAULT && HasFlag(sptr, FLAG_SERVNOTICE))
-      send_reply(sptr, RPL_SNOMASK, cli_snomask(sptr), cli_snomask(sptr));
-  }
+  /* Send server notice mask to client */
+  if (MyUser(sptr) && (cli_snomask(sptr) != SNO_DEFAULT) && HasFlag(sptr, FLAG_SERVNOTICE))
+    send_reply(sptr, RPL_SNOMASK, cli_snomask(sptr), cli_snomask(sptr));
 
   return 0;
 }
@@ -702,8 +717,17 @@ int set_nick_name(struct Client* cptr, struct Client* sptr,
     ircd_strncpy(cli_user(new_client)->host, parv[5], HOSTLEN);
     ircd_strncpy(cli_user(new_client)->realhost, parv[5], HOSTLEN);
     ircd_strncpy(cli_info(new_client), parv[parc - 1], REALLEN);
-    if (account)
-      ircd_strncpy(cli_user(new_client)->account, account, ACCOUNTLEN);
+    if (account) {
+      int len = ACCOUNTLEN;
+      if ((p = strchr(account, ':'))) {
+       len = (p++) - account;
+       cli_user(new_client)->acc_create = atoi(p);
+       Debug((DEBUG_DEBUG, "Received timestamped account in user mode; "
+              "account \"%s\", timestamp %Tu", account,
+              cli_user(new_client)->acc_create));
+      }
+      ircd_strncpy(cli_user(new_client)->account, account, len);
+    }
     if (HasHiddenHost(new_client))
       ircd_snprintf(0, cli_user(new_client)->host, HOSTLEN, "%s.%s",
         account, feature_str(FEAT_HIDDEN_HOST));
@@ -787,7 +811,6 @@ int set_nick_name(struct Client* cptr, struct Client* sptr,
       cli_user(sptr) = make_user(sptr);
       cli_user(sptr)->server = &me;
     }
-    SetLocalNumNick(sptr);
     hAddClient(sptr);
 
     /*
@@ -839,8 +862,6 @@ add_target(struct Client *sptr, void *target)
 
   targets = cli_targets(sptr);
 
-  if (IsChannelName(cli_name(sptr)) && IsInvited(sptr, target))
-    return;
   /* 
    * Already in table?
    */
@@ -875,6 +896,10 @@ int check_target_limit(struct Client *sptr, void *target, const char *name,
   assert(cli_local(sptr));
   targets = cli_targets(sptr);
 
+  /* If user is invited to channel, give him/her a free target */
+  if (IsChannelName(name) && IsInvited(sptr, target))
+    return 0;
+
   /*
    * Same target as last time?
    */
@@ -1057,6 +1082,11 @@ hide_hostmask(struct Client *cptr, unsigned int flag)
       flag == FLAG_HIDDENHOST)
     return 0;
 
+/* Invalidate all bans against the user so we check them again */
+      for (chan = (cli_user(cptr))->channel; chan;
+           chan = chan->next_channel)
+        ClearBanValid(chan);
+
   SetFlag(cptr, flag);
   if (!HasFlag(cptr, FLAG_HIDDENHOST) || !HasFlag(cptr, FLAG_ACCOUNT))
     return 0;
@@ -1075,14 +1105,22 @@ hide_hostmask(struct Client *cptr, unsigned int flag)
    */
   for (chan = cli_user(cptr)->channel; chan; chan = chan->next_channel)
   {
-    sendcmdto_channel_butserv_butone(cptr, CMD_JOIN, chan->channel, cptr,
-                                     "%H", chan->channel);
+    if (IsZombie(chan))
+      continue;
+    /* For a user with no modes in a join-delayed channel, do not show
+     * the rejoin. */
+    if (!IsChanOp(chan) && !HasVoice(chan)
+        && (chan->channel->mode.mode & MODE_DELJOINS))
+      SetDelayedJoin(chan);
+    else
+      sendcmdto_channel_butserv_butone(cptr, CMD_JOIN, chan->channel, cptr, 0,
+                                         "%H", chan->channel);
     if (IsChanOp(chan) && HasVoice(chan))
-      sendcmdto_channel_butserv_butone(&me, CMD_MODE, chan->channel, cptr,
+      sendcmdto_channel_butserv_butone(&me, CMD_MODE, chan->channel, cptr, 0,
                                        "%H +ov %C %C", chan->channel, cptr,
                                        cptr);
     else if (IsChanOp(chan) || HasVoice(chan))
-      sendcmdto_channel_butserv_butone(&me, CMD_MODE, chan->channel, cptr,
+      sendcmdto_channel_butserv_butone(&me, CMD_MODE, chan->channel, cptr, 0,
         "%H +%c %C", chan->channel, IsChanOp(chan) ? 'o' : 'v', cptr);
   }
   return 0;
@@ -1248,6 +1286,7 @@ int set_user_mode(struct Client *cptr, struct Client *sptr, int parc, char *parv
          do_host_hiding = 1;
        break;
       default:
+        send_reply(sptr, ERR_UMODEUNKNOWNFLAG, *m);
         break;
       }
     }
@@ -1286,9 +1325,9 @@ int set_user_mode(struct Client *cptr, struct Client *sptr, int parc, char *parv
   }
   if (MyConnect(sptr))
   {
-    if (FlagHas(&setflags, FLAG_OPER) || FlagHas(&setflags, FLAG_LOCOP) &&
-       !IsAnOper(sptr))
-      det_confs_butmask(sptr, CONF_CLIENT & ~CONF_OPS);
+    if ((FlagHas(&setflags, FLAG_OPER) || FlagHas(&setflags, FLAG_LOCOP)) &&
+        !IsAnOper(sptr))
+      det_confs_butmask(sptr, CONF_CLIENT & ~CONF_OPERATOR);
 
     if (SendServNotice(sptr))
     {
@@ -1339,7 +1378,7 @@ char *umode_str(struct Client *cptr)
   /* Maximum string size: "owidgrx\0" */
   char *m = umodeBuf;
   int i;
-  struct Flags c_flags;
+  struct Flags c_flags = cli_flags(cptr);
 
   if (HasPriv(cptr, PRIV_PROPAGATE))
     FlagSet(&c_flags, FLAG_OPER);
@@ -1360,6 +1399,18 @@ char *umode_str(struct Client *cptr)
     *m++ = ' ';
     while ((*m++ = *t++))
       ; /* Empty loop */
+
+    if (cli_user(cptr)->acc_create) {
+      char nbuf[20];
+      Debug((DEBUG_DEBUG, "Sending timestamped account in user mode for "
+            "account \"%s\"; timestamp %Tu", cli_user(cptr)->account,
+            cli_user(cptr)->acc_create));
+      ircd_snprintf(0, t = nbuf, sizeof(nbuf), ":%Tu",
+                   cli_user(cptr)->acc_create);
+      m--; /* back up over previous nul-termination */
+      while ((*m++ = *t++))
+       ; /* Empty loop */
+    }
   }
 
   *m = '\0';