added possibility to recover connections using Login on Connect
[ircu2.10.12-pk.git] / ircd / s_auth.c
index 71c86385db89e66b589a99c4abae9ecc37da5a65..112fdc8cf87946de03e7f64cbc02b1fb7ed72ee0 100644 (file)
@@ -84,6 +84,7 @@ enum AuthRequestFlag {
     AR_NEEDS_USER,      /**< user must send USER command */
     AR_NEEDS_NICK,      /**< user must send NICK command */
     AR_LAST_SCAN = AR_NEEDS_NICK, /**< maximum flag to scan through */
+    AR_ZOMBIE_RECOVER,  /**< nick of user is already taken by a zombie - try to recover */
     AR_IAUTH_PENDING,   /**< iauth request sent, waiting for response */
     AR_IAUTH_HURRY,     /**< we told iauth to hurry up */
     AR_IAUTH_USERNAME,  /**< iauth sent a username (preferred or forced) */
@@ -109,6 +110,7 @@ struct AuthRequest {
   unsigned int        cookie;     /**< cookie the user must PONG */
   unsigned short      port;       /**< client's remote port number */
   unsigned int        numeric;    /**< unregistered client numeric */
+  struct Client*      recover_client; /**< zombie client to be recovered later */
   char                loc_user[ACCOUNTLEN];
   char                loc_pass[PASSWDLEN];
 };
@@ -134,6 +136,7 @@ static struct {
   MSG("NOTICE AUTH :*** Checking login\r\n"),
   MSG("NOTICE AUTH :*** Login rejected\r\n"),
   MSG("NOTICE AUTH :*** Login accepted\r\n"),
+  MSG("NOTICE AUTH :*** Nickname in Use by Zombie - try to recover\r\n"),
 #undef MSG
 };
 
@@ -150,7 +153,8 @@ typedef enum {
   REPORT_INVAL_DNS,
   REPORT_DO_LOC,
   REPORT_FAIL_LOC,
-  REPORT_DONE_LOC
+  REPORT_DONE_LOC,
+  REPORT_ZOMBIE_RECOVER
 } ReportType;
 
 /** Sends response \a r (from #ReportType) to client \a c. */
@@ -557,10 +561,27 @@ static int check_auth_finished(struct AuthRequest *auth)
 
   if (IsUserPort(auth->client))
   {
+    if(FlagHas(&auth->flags, AR_ZOMBIE_RECOVER)) {
+      /* check if able to recover connection */
+      if(!IsAccount(auth->client) || ircd_strcmp(cli_user(auth->client)->account, cli_user(auth->recover_client)->account)) {
+        send_reply(auth->client, ERR_RECOVERDENIED, cli_name(auth->recover_client), "auth missmatch");
+        
+        /* reset nickname */
+        FlagSet(&auth->flags, AR_NEEDS_NICK);
+        send_reply(auth->client, ERR_NICKNAMEINUSE, cli_name(auth->recover_client));
+        hRemClient(auth->client);
+        (cli_name(auth->client))[0] = '\0';
+        return 0;
+      }
+    }
     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);
+    if (res == 0 && FlagHas(&auth->flags, AR_ZOMBIE_RECOVER)) {
+      unzombie_client(&me, &me, auth->client, auth->recover_client);
+      auth->client = auth->recover_client;
+    }
   }
   else
     res = 0;
@@ -1404,6 +1425,17 @@ int auth_set_user(struct AuthRequest *auth, const char *username, const char *ho
   return check_auth_finished(auth);
 }
 
+/** Set Zombie Client that should be recovered later
+ */
+int auth_set_recover_client(struct AuthRequest *auth, struct Client *zombie)
+{
+  assert(auth != NULL);
+  FlagSet(&auth->flags, AR_ZOMBIE_RECOVER);
+  auth->recover_client = zombie;
+  
+  sendheader(auth->client, REPORT_ZOMBIE_RECOVER);
+}
+
 /** Handle authorization-related aspects of initial nickname selection.
  * This is called after verifying that the nickname is available.
  * @param[in] auth Authorization request for client.
@@ -1414,6 +1446,7 @@ int auth_set_nick(struct AuthRequest *auth, const char *nickname)
 {
   assert(auth != NULL);
   FlagClr(&auth->flags, AR_NEEDS_NICK);
+
   /*
    * If the client hasn't gotten a cookie-ping yet,
    * choose a cookie and send it. -record!jegelhof@cloud9.net