void LoginHandler::handleIdentMessage(const QString &message) { const QRegularExpression re("\\IDENT \"([^\"]+)\"\\s*(?:;(.+))?\\z"); auto m = re.match(message); if(!m.hasMatch()) { send("ERROR SYNTAX"); _client->disconnectError("login error"); return; } QString username = m.captured(1); QString password; if(m.lastCapturedIndex() == 2) password = m.captured(2); if(!validateUsername(username)) { send("ERROR BADNAME"); _client->disconnectError("login error"); return; } if(_server->identityManager()) { _state = WAIT_FOR_IDENTITYMANAGER_REPLY; IdentityResult *result = _server->identityManager()->checkLogin(username, password); connect(result, &IdentityResult::resultAvailable, [this, username, password](IdentityResult *result) { QString error; Q_ASSERT(result->status() != IdentityResult::INPROGRESS); switch(result->status()) { case IdentityResult::INPROGRESS: /* can't happen */ break; case IdentityResult::NOTFOUND: if(!_server->identityManager()->isAuthorizedOnly()) { guestLogin(username); break; } // fall through to badpass if guest logins are disabled case IdentityResult::BADPASS: if(password.isEmpty()) { // No password: tell client that guest login is not possible (for this username) _state = WAIT_FOR_IDENT; send("NEEDPASS"); return; } error = "BADPASS"; break; case IdentityResult::BANNED: error = "BANNED"; break; case IdentityResult::OK: { // Yay, username and password were valid! QString okstr = "IDENTIFIED USER "; if(result->flags().isEmpty()) okstr += "-"; else okstr += result->flags().join(","); if(validateUsername(result->canonicalName())) { _client->setUsername(result->canonicalName()); } else { logger::warning() << "Identity manager gave us an invalid username:"******"MOD")); _hostPrivilege = result->flags().contains("HOST"); _state = WAIT_FOR_LOGIN; send(okstr); announceServerInfo(); } break; } if(!error.isEmpty()) { send("ERROR " + error); _client->disconnectError("login error"); } }); } else { if(!password.isNull()) { // if we have no identity manager, we can't accept passwords send("ERROR NOIDENT"); _client->disconnectError("login error"); return; } guestLogin(username); } }
void LoginHandler::handleIdentMessage(const protocol::ServerCommand &cmd) { QString username, password; if(cmd.args.size()!=1 && cmd.args.size()!=2) { sendError("syntax", "Expected username and (optional) password"); return; } username = cmd.args[0].toString(); if(cmd.args.size()>1) password = cmd.args[1].toString(); if(!validateUsername(username)) { sendError("badUsername", "Invalid username"); return; } if(m_server->identityManager()) { m_state = WAIT_FOR_IDENTITYMANAGER_REPLY; IdentityResult *result = m_server->identityManager()->checkLogin(username, password); connect(result, &IdentityResult::resultAvailable, [this, username, password](IdentityResult *result) { QString errorcode, errorstr; Q_ASSERT(result->status() != IdentityResult::INPROGRESS); switch(result->status()) { case IdentityResult::INPROGRESS: /* can't happen */ break; case IdentityResult::NOTFOUND: if(!m_server->identityManager()->isAuthorizedOnly()) { guestLogin(username); break; } // fall through to badpass if guest logins are disabled case IdentityResult::BADPASS: if(password.isEmpty()) { // No password: tell client that guest login is not possible (for this username) m_state = WAIT_FOR_IDENT; protocol::ServerReply identReply; identReply.type = protocol::ServerReply::RESULT; identReply.message = "Password needed"; identReply.reply["state"] = "needPassword"; send(identReply); return; } errorcode = "badPassword"; errorstr = "Incorrect password"; break; case IdentityResult::BANNED: errorcode = "banned"; errorstr = "This username is banned"; break; case IdentityResult::OK: { // Yay, username and password were valid! if(validateUsername(result->canonicalName())) { m_client->setUsername(result->canonicalName()); } else { logger::warning() << "Identity manager gave us an invalid username:"******"Authenticated login OK!"; identReply.reply["state"] = "identOk"; identReply.reply["flags"] = QJsonArray::fromStringList(result->flags()); identReply.reply["ident"] = m_client->username(); identReply.reply["guest"] = false; m_client->setAuthenticated(true); m_client->setModerator(result->flags().contains("MOD")); m_hostPrivilege = result->flags().contains("HOST"); m_state = WAIT_FOR_LOGIN; send(identReply); announceServerInfo(); } break; } if(!errorcode.isEmpty()) { sendError(errorcode, errorstr); } }); } else { if(!password.isNull()) { // if we have no identity manager, we can't accept passwords sendError("noIdent", "This is a guest-only server"); return; } guestLogin(username); } }