Make IPv4-only sockaddr_from_irc() work properly.
[ircu2.10.12-pk.git] / ircd / s_auth.c
index 33e2242db5e6350ec5f68ce1fc6b70de68637d2f..d3e816b772567052d9e9dcfa9b4b78040c08a2e6 100644 (file)
@@ -200,7 +200,9 @@ struct IAuth {
 #define i_debug(iauth) ((iauth)->i_debug)
 
 /** Active instance of IAuth. */
-struct IAuth *iauth;
+static struct IAuth *iauth;
+/** Freelist of AuthRequest structures. */
+static struct AuthRequest *auth_freelist;
 
 static void iauth_sock_callback(struct Event *ev);
 static void iauth_stderr_callback(struct Event *ev);
@@ -425,13 +427,17 @@ static int check_auth_finished(struct AuthRequest *auth)
   else
     FlagSet(&auth->flags, AR_IAUTH_HURRY);
 
-  destroy_auth_request(auth);
-  if (!IsUserPort(auth->client))
-    return 0;
-  memset(cli_passwd(auth->client), 0, sizeof(cli_passwd(auth->client)));
-  res = auth_set_username(auth);
-  if (res == 0)
+  if (IsUserPort(auth->client))
+  {
+    memset(cli_passwd(auth->client), 0, sizeof(cli_passwd(auth->client)));
+    res = auth_set_username(auth);
+    if (res == 0)
       res = register_user(auth->client, auth->client);
+  }
+  else
+    res = 0;
+  if (res == 0)
+    destroy_auth_request(auth);
   return res;
 }
 
@@ -719,7 +725,10 @@ void destroy_auth_request(struct AuthRequest* auth)
 
   if (t_active(&auth->timeout))
     timer_del(&auth->timeout);
+
   cli_auth(auth->client) = NULL;
+  auth->next = auth_freelist;
+  auth_freelist = auth;
 }
 
 /** Handle a 'ping' (authorization) timeout for a client.
@@ -733,6 +742,11 @@ int auth_ping_timeout(struct Client *cptr)
 
   auth = cli_auth(cptr);
 
+  /* Check whether the auth request is gone (more likely, it never
+   * existed, as in an outbound server connection). */
+  if (!auth)
+      return exit_client_msg(cptr, cptr, &me, "Registration Timeout");
+
   /* Check for a user-controlled timeout. */
   for (flag = 0; flag <= AR_LAST_SCAN; ++flag) {
     if (FlagHas(&auth->flags, flag)) {
@@ -957,8 +971,13 @@ void start_auth(struct Client* client)
   socket_events(&(cli_socket(client)), SOCK_ACTION_SET | SOCK_EVENT_READABLE);
 
   /* Allocate the AuthRequest. */
-  auth = MyCalloc(1, sizeof(*auth));
+  auth = auth_freelist;
+  if (auth)
+      auth_freelist = auth->next;
+  else
+      auth = MyMalloc(sizeof(*auth));
   assert(0 != auth);
+  memset(auth, 0, sizeof(*auth));
   auth->client = client;
   cli_auth(client) = auth;
   s_fd(&auth->socket) = -1;
@@ -1024,10 +1043,14 @@ int auth_set_pong(struct AuthRequest *auth, unsigned int cookie)
 /** Record a user's claimed username and userinfo.
  * @param[in] auth Authorization request for client.
  * @param[in] username Client's asserted username.
+ * @param[in] hostname Third argument of USER command (client's
+ *   hostname, per RFC 1459).
+ * @param[in] servername Fourth argument of USER command (server's
+ *   name, per RFC 1459).
  * @param[in] userinfo Client's asserted self-description.
  * @return Zero if client should be kept, CPTR_KILLED if rejected.
  */
-int auth_set_user(struct AuthRequest *auth, const char *username, const char *userinfo)
+int auth_set_user(struct AuthRequest *auth, const char *username, const char *hostname, const char *servername, const char *userinfo)
 {
   struct Client *cptr;
 
@@ -1040,7 +1063,7 @@ int auth_set_user(struct AuthRequest *auth, const char *username, const char *us
   ircd_strncpy(cli_user(cptr)->username, username, USERLEN);
   ircd_strncpy(cli_user(cptr)->host, cli_sockhost(cptr), HOSTLEN);
   if (IAuthHas(iauth, IAUTH_UNDERNET))
-    sendto_iauth(cptr, "U %s :%s", username, userinfo);
+    sendto_iauth(cptr, "U %s %s %s :%s", username, hostname, servername, userinfo);
   else if (IAuthHas(iauth, IAUTH_ADDLINFO))
     sendto_iauth(cptr, "U %s", username);
   return check_auth_finished(auth);
@@ -1394,6 +1417,7 @@ static int sendto_iauth(struct Client *cptr, const char *format, ...)
   /* Tack it onto the iauth sendq and try to write it. */
   ++iauth->i_sendM;
   msgq_add(i_sendQ(iauth), mb, 0);
+  msgq_clean(mb);
   iauth_write(iauth);
   return 1;
 }