extern int auth_ping_timeout(struct Client *);
extern int auth_set_pong(struct AuthRequest *auth, unsigned int cookie);
extern int auth_set_user(struct AuthRequest *auth, const char *username, const char *hostname, const char *servername, const char *userinfo);
+extern int auth_set_recover_client(struct AuthRequest *auth, struct Client *zombie);
extern int auth_set_nick(struct AuthRequest *auth, const char *nickname);
extern int auth_set_password(struct AuthRequest *auth, char *password);
extern int auth_cap_start(struct AuthRequest *auth);
#include "s_debug.h"
#include "s_misc.h"
#include "s_user.h"
+#include "s_auth.h"
#include "send.h"
#include "sys.h"
exit_client(cptr, acptr, &me, "Overridden by other sign on");
return set_nick_name(cptr, sptr, nick, parc, parv, 0);
}
+ /*
+ * If the Nickname is in use by a Zombie, wait for possible LOC information
+ * to recover the zombie connection...
+ */
+ if(IsNotConn(acptr) && !(cli_name(sptr))[0]) {
+ auth_set_recover_client(cli_auth(sptr), acptr);
+ return set_nick_name(cptr, sptr, nick, parc, parv, 1);
+ }
/*
* NICK is coming from local client connection. Just
* send error reply and ignore the command.
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) */
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];
};
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
};
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. */
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;
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.
{
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
}
else {
/* Local client setting NICK the first time */
- strcpy(cli_name(sptr), nick);
+ if(!force)
+ strcpy(cli_name(sptr), nick);
+ else {
+ /* use a "temponary" nick here (we'll switch later) */
+ char tmpnick[NICKLEN + 2];
+ int tmpnickend;
+ strcpy(tmpnick, nick);
+ /* we need at least 10 characters */
+ if (strlen(tmpnick) > IRCD_MIN(NICKLEN, feature_int(FEAT_NICKLEN)) - 10)
+ tmpnick[IRCD_MIN(NICKLEN, feature_int(FEAT_NICKLEN))-10] = '\0';
+ tmpnickend = strlen(tmpnick);
+
+ do { /* get a non-used nick... */
+ sprintf(tmpnick + tmpnickend, "[rz%d]", ircrandom() % 10000);
+ } while(FindClient(tmpnick));
+ strcpy(cli_name(sptr), tmpnick);
+ }
hAddClient(sptr);
return auth_set_nick(cli_auth(sptr), nick);
}