diff --git a/irc/client_lookup_set.go b/irc/client_lookup_set.go index ef767b6d..ea9c88b7 100644 --- a/irc/client_lookup_set.go +++ b/irc/client_lookup_set.go @@ -116,6 +116,8 @@ func (clients *ClientManager) SetNick(client *Client, session *Session, newNick useAccountName = alwaysOn || config.Accounts.NickReservation.ForceNickEqualsAccount } + nickIsReserved := false + if useAccountName { if registered && newNick != accountName { return "", errNickAccountMismatch, false @@ -167,7 +169,9 @@ func (clients *ClientManager) SetNick(client *Client, session *Session, newNick reservedAccount, method := client.server.accounts.EnforcementStatus(newCfNick, newSkeleton) if method == NickEnforcementStrict && reservedAccount != "" && reservedAccount != account { - return "", errNicknameReserved, false + // see #2135: we want to enter the critical section, see if the nick is actually in use, + // and return errNicknameInUse in that case + nickIsReserved = true } } @@ -219,6 +223,9 @@ func (clients *ClientManager) SetNick(client *Client, session *Session, newNick if skeletonHolder != nil && skeletonHolder != client { return "", errNicknameInUse, false } + if nickIsReserved { + return "", errNicknameReserved, false + } if dryRun { return "", nil, false diff --git a/irc/nickname.go b/irc/nickname.go index b180c005..b2a8cbe1 100644 --- a/irc/nickname.go +++ b/irc/nickname.go @@ -43,6 +43,8 @@ func performNickChange(server *Server, client *Client, target *Client, session * } } else if err == errNicknameReserved { if !isSanick { + // see #1594 for context: ERR_NICKNAMEINUSE can confuse clients if the nickname is not + // literally in use: if !client.registered { rb.Add(nil, server.name, ERR_NICKNAMEINUSE, details.nick, utils.SafeErrorParam(nickname), client.t("Nickname is reserved by a different account")) }