From 1f7f045d15e29e9d7476dce03fa4620aa41eb36a Mon Sep 17 00:00:00 2001 From: lotodore Date: Sun, 11 Oct 2009 09:20:17 +0000 Subject: [PATCH] Starting gsasl integration to perform challenge response authentication. Note that gsasl 1.3 is required (previous versions are not supported). Authentication is currently broken. --- pokerth_game.pro | 34 +++++++-------- pokerth_server.pro | 25 +++++------ src/core/openssl_wrapper.h | 2 +- src/db/common/serverdbgeneric.cpp | 6 +-- src/db/serverdbcallback.h | 6 +-- src/db/serverdbgeneric.h | 6 +-- src/db/serverdbinterface.h | 8 ++-- src/net/common/clientstate.cpp | 5 ++- src/net/common/servergame.cpp | 4 +- src/net/common/servergamestate.cpp | 5 --- src/net/common/serverlobbythread.cpp | 63 +++++++++++++++++++--------- src/net/common/sessiondata.cpp | 17 +------- src/net/servergame.h | 6 +-- src/net/serverlobbythread.h | 9 +++- src/net/sessiondata.h | 4 -- src/net/socket_msg.h | 2 + src/playerdata.cpp | 16 ++++++- src/playerdata.h | 5 +++ 18 files changed, 123 insertions(+), 100 deletions(-) diff --git a/pokerth_game.pro b/pokerth_game.pro index 79214010..6cb7bc6a 100644 --- a/pokerth_game.pro +++ b/pokerth_game.pro @@ -295,36 +295,34 @@ win32 { INCLUDEPATH += ../SDL/include/SDL \ ../SDL_mixer/include \ ../GnuTLS/include \ + ../gsasl/include \ ../curl/include \ ../zlib LIBPATH += ../boost/stage/lib \ - ../GnuTLS/lib \ - ../curl/lib \ - ../zlib + ../GnuTLS/lib \ + ../gsasl/lib \ + ../curl/lib \ + ../SDL/lib \ + ../SDL_mixer/lib \ + ../zlib LIBS += -lpokerth_lib \ -lpokerth_db \ -lpokerth_protocol - win32-msvc2005 { - LIBPATH += Release/lib \ - ../SDL/VisualC/SDL/Release \ - ../SDL/VisualC/SDLmain/Release \ - ../SDL_mixer/VisualC/Release - - # LIBPATH += Debug/lib ../SDL/VisualC/SDL/Debug ../SDL/VisualC/SDLmain/Debug ../SDL_mixer/VisualC/Debug - LIBS += -llibgnutls-openssl \ - -llibgcrypt - LIBS += -llibcurl + debug:LIBPATH += Debug/lib + release:LIBPATH += Release/lib + win32-msvc2008 { + LIBS += -llibgnutls-openssl-26 \ + -llibgcrypt-11 \ + -llibgsasl-7 \ + -llibcurl } win32-g++ { - debug:LIBPATH += Debug/lib - release:LIBPATH += Release/lib - LIBPATH += ../SDL/lib \ - ../SDL_mixer/lib LIBS += -lgnutls-openssl \ -lgnutls \ -lgcrypt \ -ltasn1 \ - -lgpg-error + -lgpg-error \ + -lgsasl LIBS += -lcurl LIBS += -lz LIBS += -llibboost_thread-mgw44-mt diff --git a/pokerth_server.pro b/pokerth_server.pro index cebc5d2b..04d62afe 100644 --- a/pokerth_server.pro +++ b/pokerth_server.pro @@ -115,29 +115,26 @@ win32 { DEFINES += CURL_STATICLIB DEFINES += _WIN32_WINNT=0x0501 DEPENDPATH += src/net/win32/ src/core/win32 - INCLUDEPATH += ../boost/ ../GnuTLS/include + INCLUDEPATH += ../boost/ ../GnuTLS/include ../gsasl/include SOURCES += src/core/win32/convhelper.cpp - LIBPATH += ../boost/stage/lib ../GnuTLS/lib ../curl/lib ../zlib + LIBPATH += ../boost/stage/lib ../GnuTLS/lib ../gsasl/lib ../curl/lib ../zlib LIBS += -lpokerth_lib -lpokerth_db -lpokerth_protocol - win32-msvc2005 { - LIBPATH += Release/lib - #LIBPATH += Debug/lib - LIBS += -llibgnutls-openssl -llibgcrypt - LIBS += -llibcurl + debug:LIBPATH += Debug/lib + release:LIBPATH += Release/lib + + win32-msvc2008 { + LIBS += -llibgnutls-openssl-26 \ + -llibgcrypt-11 \ + -llibgsasl-7 \ + -llibcurl } win32-g++ { - debug { - LIBPATH += Debug/lib - } - release { - LIBPATH += Release/lib - } - LIBS += -lgnutls-openssl -lgnutls -lgcrypt -ltasn1 -lgpg-error + LIBS += -lgnutls-openssl -lgnutls -lgcrypt -ltasn1 -lgpg-error -lgsasl LIBS += -lcurl LIBS += -lz LIBS += -llibboost_thread-mgw44-mt diff --git a/src/core/openssl_wrapper.h b/src/core/openssl_wrapper.h index b1aefac5..7a58124e 100644 --- a/src/core/openssl_wrapper.h +++ b/src/core/openssl_wrapper.h @@ -46,7 +46,7 @@ // "2. Can I use OpenSSL with GPL software?" // http://www.openssl.org/support/faq.html#LEGAL2 // -#if defined (_WIN32) || defined(__APPLE__) || defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__NetBSD__) +#if defined(__APPLE__) || defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__NetBSD__) #define HAVE_OPENSSL #endif diff --git a/src/db/common/serverdbgeneric.cpp b/src/db/common/serverdbgeneric.cpp index 713436ad..fc6d7717 100644 --- a/src/db/common/serverdbgeneric.cpp +++ b/src/db/common/serverdbgeneric.cpp @@ -55,7 +55,7 @@ ServerDBGeneric::AsyncPlayerLogin(unsigned requestId, const string &/*playerName } void -ServerDBGeneric::PlayerLogout(db_id /*playerId*/) +ServerDBGeneric::PlayerLogout(DB_id /*playerId*/) { } @@ -66,11 +66,11 @@ ServerDBGeneric::AsyncCreateGame(unsigned requestId, const string &/*gameName*/) } void -ServerDBGeneric::SetGamePlayerPlace(db_id /*gameId*/, db_id /*playerId*/, unsigned /*place*/) +ServerDBGeneric::SetGamePlayerPlace(DB_id /*gameId*/, DB_id /*playerId*/, unsigned /*place*/) { } void -ServerDBGeneric::EndGame(db_id /*gameId*/) +ServerDBGeneric::EndGame(DB_id /*gameId*/) { } diff --git a/src/db/serverdbcallback.h b/src/db/serverdbcallback.h index 4f312576..8fe06351 100644 --- a/src/db/serverdbcallback.h +++ b/src/db/serverdbcallback.h @@ -23,7 +23,7 @@ #include -typedef unsigned db_id; +typedef unsigned DB_id; #define DB_ID_INVALID 0 // Callback operations are posted using the io service, @@ -38,10 +38,10 @@ public: virtual void QueryError(const std::string &error) = 0; - virtual void PlayerLoginSuccess(unsigned requestId, db_id playerId) = 0; + virtual void PlayerLoginSuccess(unsigned requestId, DB_id playerId) = 0; virtual void PlayerLoginFailed(unsigned requestId) = 0; - virtual void CreateGameSuccess(unsigned requestId, db_id gameId) = 0; + virtual void CreateGameSuccess(unsigned requestId, DB_id gameId) = 0; virtual void CreateGameFailed(unsigned requestId) = 0; }; diff --git a/src/db/serverdbgeneric.h b/src/db/serverdbgeneric.h index 2fb20186..0ffd337b 100644 --- a/src/db/serverdbgeneric.h +++ b/src/db/serverdbgeneric.h @@ -39,11 +39,11 @@ public: virtual void Stop(); virtual void AsyncPlayerLogin(unsigned requestId, const std::string &playerName, const std::string &secretString); - virtual void PlayerLogout(db_id playerId); + virtual void PlayerLogout(DB_id playerId); virtual void AsyncCreateGame(unsigned requestId, const std::string &gameName); - virtual void SetGamePlayerPlace(db_id gameId, db_id playerId, unsigned place); - virtual void EndGame(db_id gameId); + virtual void SetGamePlayerPlace(DB_id gameId, DB_id playerId, unsigned place); + virtual void EndGame(DB_id gameId); private: boost::shared_ptr m_ioService; diff --git a/src/db/serverdbinterface.h b/src/db/serverdbinterface.h index 5ad1dd83..35e6348d 100644 --- a/src/db/serverdbinterface.h +++ b/src/db/serverdbinterface.h @@ -25,7 +25,7 @@ #include #include -typedef std::list db_list; +typedef std::list db_list; class ServerDBInterface { @@ -39,11 +39,11 @@ public: virtual void Stop() = 0; virtual void AsyncPlayerLogin(unsigned requestId, const std::string &playerName, const std::string &secretString) = 0; - virtual void PlayerLogout(db_id playerId) = 0; + virtual void PlayerLogout(DB_id playerId) = 0; virtual void AsyncCreateGame(unsigned requestId, const std::string &gameName) = 0; - virtual void SetGamePlayerPlace(db_id gameId, db_id playerId, unsigned place) = 0; - virtual void EndGame(db_id gameId) = 0; + virtual void SetGamePlayerPlace(DB_id gameId, DB_id playerId, unsigned place) = 0; + virtual void EndGame(DB_id gameId) = 0; }; #endif diff --git a/src/net/common/clientstate.cpp b/src/net/common/clientstate.cpp index c5b7b7f6..9c1fd6f8 100644 --- a/src/net/common/clientstate.cpp +++ b/src/net/common/clientstate.cpp @@ -676,12 +676,13 @@ ClientStateStartSession::Enter(boost::shared_ptr client) netInit->requestedVersion.minor = NET_VERSION_MINOR; netInit->login.present = login_PR_authenticatedLogin; AuthenticatedLogin_t *authLogin = &netInit->login.choice.authenticatedLogin; - OCTET_STRING_fromBuf(&authLogin->playerName, + // TODO +/* OCTET_STRING_fromBuf(&authLogin->playerName, context.GetPlayerName().c_str(), context.GetPlayerName().length()); OCTET_STRING_fromBuf(&authLogin->password, context.GetPassword().c_str(), - context.GetPassword().length()); + context.GetPassword().length());*/ //context.GetPassword(); string avatarFile = client->GetQtToolsInterface().stringFromUtf8(context.GetAvatarFile()); if (!avatarFile.empty()) diff --git a/src/net/common/servergame.cpp b/src/net/common/servergame.cpp index 281a6774..287c0204 100644 --- a/src/net/common/servergame.cpp +++ b/src/net/common/servergame.cpp @@ -87,14 +87,14 @@ ServerGame::GetName() const return m_name; } -db_id +DB_id ServerGame::GetDBId() const { return m_dbId; } void -ServerGame::SetDBId(db_id newId) +ServerGame::SetDBId(DB_id newId) { m_dbId = newId; } diff --git a/src/net/common/servergamestate.cpp b/src/net/common/servergamestate.cpp index 17541b7b..d9450a32 100644 --- a/src/net/common/servergamestate.cpp +++ b/src/net/common/servergamestate.cpp @@ -326,11 +326,6 @@ ServerGameStateInit::HandleNewSession(boost::shared_ptr server, Sess { server->MoveSessionToLobby(session, NTF_NET_REMOVED_GAME_FULL); } - // Check whether the client supports the current game. - else if ((size_t)server->GetGameData().maxNumberOfPlayers > session.sessionData->GetMaxNumPlayers()) - { - server->MoveSessionToLobby(session, NTF_NET_REMOVED_GAME_FULL); - } else { if (session.playerData->GetUniqueId() == server->GetAdminPlayerId()) diff --git a/src/net/common/serverlobbythread.cpp b/src/net/common/serverlobbythread.cpp index cdd70527..9b8abb29 100644 --- a/src/net/common/serverlobbythread.cpp +++ b/src/net/common/serverlobbythread.cpp @@ -44,6 +44,7 @@ #include #include #include +#include #define SERVER_MAX_NUM_SESSIONS 512 // Maximum number of idle users in lobby. @@ -110,7 +111,7 @@ public: // TODO } - virtual void PlayerLoginSuccess(unsigned requestId, db_id dbPlayerId) + virtual void PlayerLoginSuccess(unsigned requestId, DB_id dbPlayerId) { m_server.AuthenticationSuccess(requestId, dbPlayerId); } @@ -120,7 +121,7 @@ public: m_server.AuthenticationFailure(requestId); } - virtual void CreateGameSuccess(unsigned requestId, db_id gameId) + virtual void CreateGameSuccess(unsigned requestId, DB_id gameId) { m_server.SetGameDBId((u_int32_t)requestId, gameId); } @@ -136,7 +137,7 @@ private: ServerLobbyThread::ServerLobbyThread(GuiInterface &gui, ServerIrcBotCallback &ircBotCb, ConfigFile *playerConfig, AvatarManager &avatarManager, boost::shared_ptr ioService) -: m_ioService(ioService), m_gui(gui), m_ircBotCb(ircBotCb), m_avatarManager(avatarManager), +: m_ioService(ioService), m_authContext(NULL), m_gui(gui), m_ircBotCb(ircBotCb), m_avatarManager(avatarManager), m_playerConfig(playerConfig), m_curGameId(0), m_curUniquePlayerId(0), m_curSessionId(INVALID_SESSION + 1), m_statDataChanged(false), m_removeGameTimer(*ioService), m_removePlayerTimer(*ioService), m_sessionTimeoutTimer(*ioService), m_avatarCleanupTimer(*ioService), @@ -608,13 +609,16 @@ ServerLobbyThread::GetNextGameId() void ServerLobbyThread::Main() { - InitChatCleaner(); - // Start database engine. - m_database->Start(); - // Register all timers. - RegisterTimers(); try { + InitAuthContext(); + + InitChatCleaner(); + // Start database engine. + m_database->Start(); + // Register all timers. + RegisterTimers(); + boost::asio::io_service::work ioWork(*m_ioService); m_ioService->run(); // Will only be aborted asynchronously. @@ -630,6 +634,8 @@ ServerLobbyThread::Main() CancelTimers(); // Stop database engine. m_database->Stop(); + + ClearAuthContext(); } void @@ -684,6 +690,30 @@ ServerLobbyThread::CancelTimers() m_avatarLockTimer.cancel(); } +void +ServerLobbyThread::InitAuthContext() +{ + int res = gsasl_init(&m_authContext); + if (res != GSASL_OK) + throw ServerException(__FILE__, __LINE__, ERR_NET_GSASL_INIT_FAILED, 0); + + if (!gsasl_server_support_p(m_authContext, "SCRAM-SHA-1")) + { + gsasl_done(m_authContext); + throw ServerException(__FILE__, __LINE__, ERR_NET_GSASL_NO_SCRAM, 0); + } +} + +void +ServerLobbyThread::ClearAuthContext() +{ + if (m_authContext) + { + gsasl_done(m_authContext); + m_authContext = NULL; + } +} + void ServerLobbyThread::InitChatCleaner() { @@ -876,25 +906,20 @@ ServerLobbyThread::HandleNetPacketInit(SessionWrapper session, const InitMessage SessionError(session, ERR_NET_VERSION_NOT_SUPPORTED); return; } - session.sessionData->SetMaxNumPlayers(MAX_NUMBER_OF_PLAYERS); string playerName; - string password; + string authData; MD5Buf avatarMD5; bool guestUser = false; if (initMessage.login.present == login_PR_anonymousLogin) { - const AnonymousLogin_t *anonLogin = &initMessage.login.choice.anonymousLogin; - playerName = string((const char *)anonLogin->playerName.buf, anonLogin->playerName.size); - if (anonLogin->avatar) - memcpy(avatarMD5.data, anonLogin->avatar->buf, MD5_DATA_SIZE); + playerName = "guest001"; // TODO guestUser = true; } else if (initMessage.login.present == login_PR_authenticatedLogin) { const AuthenticatedLogin_t *authLogin = &initMessage.login.choice.authenticatedLogin; - playerName = string((const char *)authLogin->playerName.buf, authLogin->playerName.size); - password = string((const char *)authLogin->password.buf, authLogin->password.size); + authData = string((const char *)authLogin->clientUserData.buf, authLogin->clientUserData.size); if (authLogin->avatar) memcpy(avatarMD5.data, authLogin->avatar->buf, MD5_DATA_SIZE); } @@ -947,7 +972,7 @@ ServerLobbyThread::HandleNetPacketInit(SessionWrapper session, const InitMessage if (guestUser) InitAfterLogin(session); else - AuthenticatePlayer(session, password); + AuthenticatePlayer(session, authData); } void @@ -1273,7 +1298,7 @@ ServerLobbyThread::AuthenticatePlayer(SessionWrapper session, const std::string } void -ServerLobbyThread::AuthenticationSuccess(unsigned playerId, db_id dbPlayerId) +ServerLobbyThread::AuthenticationSuccess(unsigned playerId, DB_id dbPlayerId) { InitAfterLogin(m_sessionManager.GetSessionByUniquePlayerId(playerId, true)); } @@ -1774,7 +1799,7 @@ ServerLobbyThread::GetCallback() } void -ServerLobbyThread::SetGameDBId(u_int32_t gameId, db_id gameDBId) +ServerLobbyThread::SetGameDBId(u_int32_t gameId, DB_id gameDBId) { boost::shared_ptr game = InternalGetGameFromId(gameId); if (game) diff --git a/src/net/common/sessiondata.cpp b/src/net/common/sessiondata.cpp index 7320fe69..fb931756 100644 --- a/src/net/common/sessiondata.cpp +++ b/src/net/common/sessiondata.cpp @@ -21,8 +21,7 @@ SessionData::SessionData(boost::shared_ptr sock, SessionId id, SessionDataCallback &cb) : m_socket(sock), m_id(id), m_gameId(0), m_state(SessionData::Init), m_readyFlag(false), - m_wantsLobbyMsg(true), m_activityTimeoutNoticeSent(false), m_callback(cb), - m_maxNumPlayers(0) + m_wantsLobbyMsg(true), m_activityTimeoutNoticeSent(false), m_callback(cb) { } @@ -171,17 +170,3 @@ SessionData::GetAutoDisconnectTimerElapsedSec() const boost::mutex::scoped_lock lock(m_dataMutex); return m_autoDisconnectTimer.elapsed().total_seconds(); } - -unsigned -SessionData::GetMaxNumPlayers() const -{ - boost::mutex::scoped_lock lock(m_dataMutex); - return m_maxNumPlayers; -} - -void -SessionData::SetMaxNumPlayers(unsigned numPlayers) -{ - boost::mutex::scoped_lock lock(m_dataMutex); - m_maxNumPlayers = numPlayers; -} diff --git a/src/net/servergame.h b/src/net/servergame.h index 9d1afe89..1ac1f46d 100644 --- a/src/net/servergame.h +++ b/src/net/servergame.h @@ -51,8 +51,8 @@ public: u_int32_t GetId() const; const std::string &GetName() const; - db_id GetDBId() const; - void SetDBId(db_id newId); + DB_id GetDBId() const; + void SetDBId(DB_id newId); void AddSession(SessionWrapper session); void RemovePlayer(unsigned playerId, unsigned errorCode); @@ -155,7 +155,7 @@ private: ServerGameState *m_curState; const u_int32_t m_id; - db_id m_dbId; + DB_id m_dbId; const std::string m_name; const std::string m_password; ConfigFile *m_playerConfig; diff --git a/src/net/serverlobbythread.h b/src/net/serverlobbythread.h index 88136c86..dd1616bd 100644 --- a/src/net/serverlobbythread.h +++ b/src/net/serverlobbythread.h @@ -48,6 +48,7 @@ class ChatCleanerManager; class ServerDBInterface; struct GameData; class Game; +struct Gsasl; class ServerLobbyThread : public Thread, public boost::enable_shared_from_this { @@ -93,7 +94,7 @@ public: u_int32_t GetNextGameId(); ServerCallback &GetCallback(); - void SetGameDBId(u_int32_t gameId, db_id gameDBId); + void SetGameDBId(u_int32_t gameId, DB_id gameDBId); AvatarManager &GetAvatarManager(); @@ -120,6 +121,8 @@ protected: virtual void Main(); void RegisterTimers(); void CancelTimers(); + void InitAuthContext(); + void ClearAuthContext(); void InitChatCleaner(); void HandleRead(const boost::system::error_code &ec, SessionId sessionId, size_t bytesRead); @@ -137,7 +140,7 @@ protected: void InitAfterLogin(SessionWrapper session); void EstablishSession(SessionWrapper session); void AuthenticatePlayer(SessionWrapper session, const std::string &password); - void AuthenticationSuccess(unsigned playerId, db_id dbPlayerId); + void AuthenticationSuccess(unsigned playerId, DB_id dbPlayerId); void AuthenticationFailure(unsigned playerId); void RequestPlayerAvatar(SessionWrapper session); void TimerRemoveGame(const boost::system::error_code &ec); @@ -195,6 +198,8 @@ private: SessionManager m_sessionManager; SessionManager m_gameSessionManager; + Gsasl *m_authContext; + TimerClientAddressMap m_timerAvatarClientAddressMap; mutable boost::mutex m_timerAvatarClientAddressMapMutex; diff --git a/src/net/sessiondata.h b/src/net/sessiondata.h index 141a6aef..27d795f7 100644 --- a/src/net/sessiondata.h +++ b/src/net/sessiondata.h @@ -72,9 +72,6 @@ public: void MarkActivityNotice(); unsigned GetAutoDisconnectTimerElapsedSec() const; - unsigned GetMaxNumPlayers() const; - void SetMaxNumPlayers(unsigned numPlayers); - private: boost::shared_ptr m_socket; const SessionId m_id; @@ -88,7 +85,6 @@ private: bool m_activityTimeoutNoticeSent; boost::timers::portable::microsec_timer m_autoDisconnectTimer; SessionDataCallback &m_callback; - unsigned m_maxNumPlayers; mutable boost::mutex m_dataMutex; }; diff --git a/src/net/socket_msg.h b/src/net/socket_msg.h index 50a2866f..ab6b05c4 100644 --- a/src/net/socket_msg.h +++ b/src/net/socket_msg.h @@ -84,6 +84,8 @@ #define ERR_NET_INTERNAL_GAME_ERROR 130 #define ERR_NET_DEALER_NOT_FOUND 131 #define ERR_NET_AVATAR_UPLOAD_BLOCKED 132 +#define ERR_NET_GSASL_INIT_FAILED 133 +#define ERR_NET_GSASL_NO_SCRAM 134 #define ERR_IRC_INTERNAL 151 #define ERR_IRC_CONNECT_FAILED 152 diff --git a/src/playerdata.cpp b/src/playerdata.cpp index 8ab1dda8..9577e55e 100644 --- a/src/playerdata.cpp +++ b/src/playerdata.cpp @@ -45,12 +45,26 @@ PlayerData::GetName() const } void -PlayerData::SetName(const std::string &name) +PlayerData::SetName(const string &name) { boost::mutex::scoped_lock lock(m_dataMutex); m_name = name; } +string +PlayerData::GetPassword() const +{ + boost::mutex::scoped_lock lock(m_dataMutex); + return m_password; +} + +void +PlayerData::SetPassword(const string &password) +{ + boost::mutex::scoped_lock lock(m_dataMutex); + m_password = password; +} + string PlayerData::GetAvatarFile() const { diff --git a/src/playerdata.h b/src/playerdata.h index 43b67733..25d19fc8 100644 --- a/src/playerdata.h +++ b/src/playerdata.h @@ -28,6 +28,7 @@ #include #include #include +#include class SessionData; @@ -78,6 +79,8 @@ public: std::string GetName() const; void SetName(const std::string &name); + std::string GetPassword() const; + void SetPassword(const std::string &password); std::string GetAvatarFile() const; void SetAvatarFile(const std::string &avatarFile); MD5Buf GetAvatarMD5() const; @@ -98,8 +101,10 @@ public: private: const unsigned m_uniqueId; + DB_id m_dbId; int m_number; std::string m_name; + std::string m_password; std::string m_avatarFile; MD5Buf m_avatarMD5; PlayerType m_type;