diff --git a/pokerth_game.pro b/pokerth_game.pro index 6cb7bc6a..b90c18cf 100644 --- a/pokerth_game.pro +++ b/pokerth_game.pro @@ -463,12 +463,13 @@ mac { LIBS += /usr/local/lib/libboost_regex.a LIBS += /usr/local/lib/libboost_system.a LIBS += /usr/local/lib/libboost_iostreams.a + LIBS += /usr/local/lib/libgsasl.a # libraries installed on every mac LIBS += -lcrypto \ -lssl \ -lz \ - -lcurl \ + -lcurl \ -framework \ Carbon diff --git a/pokerth_server.pro b/pokerth_server.pro index 04d62afe..f7aae64e 100644 --- a/pokerth_server.pro +++ b/pokerth_server.pro @@ -280,6 +280,8 @@ mac { LIBS += /usr/local/lib/libboost_system.a LIBS += /usr/local/lib/libboost_iostreams.a LIBS += /usr/local/lib/libboost_program_options.a + LIBS += /usr/local/lib/libgsasl.a + # libraries installed on every mac LIBS += -lcrypto -lssl -lz -lcurl -liconv # set the application icon diff --git a/src/net/common/clientstate.cpp b/src/net/common/clientstate.cpp index 9947429e..b0b7fc6b 100644 --- a/src/net/common/clientstate.cpp +++ b/src/net/common/clientstate.cpp @@ -679,8 +679,8 @@ ClientStateStartSession::Enter(boost::shared_ptr client) // TODO boost::shared_ptr tmpSession = context.GetSessionData(); tmpSession->CreateClientAuthSession(client->GetAuthContext(), context.GetPlayerName(), context.GetPassword()); - string outUserData; - tmpSession->AuthStep(1, "", outUserData); + tmpSession->AuthStep(1, ""); + string outUserData(tmpSession->AuthGetNextOutMsg()); OCTET_STRING_fromBuf(&authLogin->clientUserData, outUserData.c_str(), outUserData.length()); diff --git a/src/net/common/serverlobbythread.cpp b/src/net/common/serverlobbythread.cpp index 1692338f..acb658a7 100644 --- a/src/net/common/serverlobbythread.cpp +++ b/src/net/common/serverlobbythread.cpp @@ -829,6 +829,14 @@ ServerLobbyThread::HandlePacket(SessionWrapper session, boost::shared_ptrGetMsg()->present == PokerTHMessage_PR_initMessage) HandleNetPacketInit(session, packet->GetMsg()->choice.initMessage); + else if (packet->GetMsg()->present == PokerTHMessage_PR_authMessage) + { + AuthMessage_t *authMsg = &packet->GetMsg()->choice.authMessage; + if (authMsg->present == AuthMessage_PR_authClientResponse) + HandleNetPacketAuthClientResponse(session, authMsg->choice.authClientResponse); + else + SessionError(session, ERR_SOCK_INVALID_STATE); + } else if (packet->GetMsg()->present == PokerTHMessage_PR_avatarReplyMessage) { AvatarReplyMessage_t *avatarReply = &packet->GetMsg()->choice.avatarReplyMessage; @@ -898,15 +906,14 @@ ServerLobbyThread::HandleNetPacketInit(SessionWrapper session, const InitMessage LOG_VERBOSE("Received init for session #" << session.sessionData->GetId() << "."); // Check the protocol version. - if (initMessage.requestedVersion.major != NET_VERSION_MAJOR) + if (initMessage.requestedVersion.major != NET_VERSION_MAJOR + || session.playerData) // Has this session already sent an init? { SessionError(session, ERR_NET_VERSION_NOT_SUPPORTED); return; } string playerName; - string inAuthData; - string outRequestData; MD5Buf avatarMD5; bool guestUser = false; if (initMessage.login.present == login_PR_anonymousLogin) @@ -917,12 +924,12 @@ ServerLobbyThread::HandleNetPacketInit(SessionWrapper session, const InitMessage else if (initMessage.login.present == login_PR_authenticatedLogin) { const AuthenticatedLogin_t *authLogin = &initMessage.login.choice.authenticatedLogin; - inAuthData = string((const char *)authLogin->clientUserData.buf, authLogin->clientUserData.size); + string inAuthData((const char *)authLogin->clientUserData.buf, authLogin->clientUserData.size); if (authLogin->avatar) memcpy(avatarMD5.data, authLogin->avatar->buf, MD5_DATA_SIZE); session.sessionData->CreateServerAuthSession(m_authContext); - session.sessionData->AuthStep(1, inAuthData, outRequestData); - playerName = session.sessionData->AuthGetUser(); + if (session.sessionData->AuthStep(1, inAuthData)) + playerName = session.sessionData->AuthGetUser(); } else SessionError(session, ERR_NET_INVALID_PASSWORD); @@ -973,13 +980,42 @@ ServerLobbyThread::HandleNetPacketInit(SessionWrapper session, const InitMessage if (guestUser) InitAfterLogin(session); else - AuthenticatePlayer(session, inAuthData); + AuthenticatePlayer(session); +} + +void +ServerLobbyThread::HandleNetPacketAuthClientResponse(SessionWrapper session, const AuthClientResponse_t &clientResponse) +{ + if (session.sessionData && session.playerData && session.sessionData->AuthGetCurStepNum() == 1) + { + string authData((const char *)clientResponse.clientResponse.buf, clientResponse.clientResponse.size); + if (session.sessionData->AuthStep(2, authData)) + { + string outVerification(session.sessionData->AuthGetNextOutMsg()); + + boost::shared_ptr packet(new NetPacket(NetPacket::Alloc)); + packet->GetMsg()->present = PokerTHMessage_PR_authMessage; + AuthMessage_t *netAuth = &packet->GetMsg()->choice.authMessage; + netAuth->present = AuthMessage_PR_authServerVerification; + AuthServerVerification_t *verification = &netAuth->choice.authServerVerification; + OCTET_STRING_fromBuf( + &verification->serverVerification, + (char *)outVerification.c_str(), + outVerification.size()); + GetSender().Send(session.sessionData, packet); + // The last message is only for server verification. + // We are done now, the user has logged in. + InitAfterLogin(session); + } + else + SessionError(session, ERR_NET_INVALID_PASSWORD); + } } void ServerLobbyThread::HandleNetPacketAvatarHeader(SessionWrapper session, unsigned /*requestId*/, const AvatarHeader_t &avatarHeader) { - if (session.playerData.get()) + if (session.playerData) { if (avatarHeader.avatarSize >= MIN_AVATAR_FILE_SIZE && avatarHeader.avatarSize <= MAX_AVATAR_FILE_SIZE) { @@ -1226,6 +1262,28 @@ ServerLobbyThread::HandleNetPacketChatRequest(SessionWrapper session, const Chat } } +void +ServerLobbyThread::AuthChallenge(SessionWrapper session, const string &secret) +{ + if (session.sessionData && session.playerData && session.sessionData->AuthGetCurStepNum() == 1) + { + session.playerData->SetPassword(secret); // For later encryption of data. + session.sessionData->AuthSetPassword(secret); // For this auth session. + string outChallenge(session.sessionData->AuthGetNextOutMsg()); + + boost::shared_ptr packet(new NetPacket(NetPacket::Alloc)); + packet->GetMsg()->present = PokerTHMessage_PR_authMessage; + AuthMessage_t *netAuth = &packet->GetMsg()->choice.authMessage; + netAuth->present = AuthMessage_PR_authServerChallenge; + AuthServerChallenge_t *challenge = &netAuth->choice.authServerChallenge; + OCTET_STRING_fromBuf( + &challenge->serverChallenge, + (char *)outChallenge.c_str(), + outChallenge.size()); + GetSender().Send(session.sessionData, packet); + } +} + void ServerLobbyThread::InitAfterLogin(SessionWrapper session) { @@ -1292,10 +1350,10 @@ ServerLobbyThread::EstablishSession(SessionWrapper session) } void -ServerLobbyThread::AuthenticatePlayer(SessionWrapper session, const std::string &password) +ServerLobbyThread::AuthenticatePlayer(SessionWrapper session) { - assert(session.playerData); - m_database->AsyncPlayerLogin(session.playerData->GetUniqueId(), session.playerData->GetName()); + if(session.playerData) + m_database->AsyncPlayerLogin(session.playerData->GetUniqueId(), session.playerData->GetName()); } void diff --git a/src/net/common/sessiondata.cpp b/src/net/common/sessiondata.cpp index a059958c..d7d4e079 100644 --- a/src/net/common/sessiondata.cpp +++ b/src/net/common/sessiondata.cpp @@ -104,7 +104,7 @@ SessionData::CreateClientAuthSession(Gsasl *context, const string &userName, con } bool -SessionData::AuthStep(int stepNum, const std::string &inData, std::string &outData) +SessionData::AuthStep(int stepNum, const std::string &inData) { bool retVal = false; boost::mutex::scoped_lock lock(m_dataMutex); @@ -116,12 +116,12 @@ SessionData::AuthStep(int stepNum, const std::string &inData, std::string &outDa int errorCode = gsasl_step(m_authSession, inData.c_str(), inData.length(), &tmpOut, &tmpOutSize); if (errorCode == GSASL_NEEDS_MORE) { - outData = string(tmpOut, tmpOutSize); + m_nextGsaslMsg = string(tmpOut, tmpOutSize); retVal = true; } else if (errorCode == GSASL_OK && stepNum != 1) { - outData = string(tmpOut, tmpOutSize); + m_nextGsaslMsg = string(tmpOut, tmpOutSize); retVal = true; InternalClearAuthSession(); } @@ -131,7 +131,7 @@ SessionData::AuthStep(int stepNum, const std::string &inData, std::string &outDa } string -SessionData::AuthGetUser() +SessionData::AuthGetUser() const { string retStr; if (m_authSession) @@ -139,6 +139,25 @@ SessionData::AuthGetUser() return retStr; } +void +SessionData::AuthSetPassword(const std::string &password) +{ + if (m_authSession) + gsasl_property_set(m_authSession, GSASL_PASSWORD, password.c_str()); +} + +string +SessionData::AuthGetNextOutMsg() const +{ + return m_nextGsaslMsg; +} + +int +SessionData::AuthGetCurStepNum() const +{ + return m_curAuthStep; +} + void SessionData::InternalClearAuthSession() { diff --git a/src/net/serverlobbythread.h b/src/net/serverlobbythread.h index 49f61da5..652f5195 100644 --- a/src/net/serverlobbythread.h +++ b/src/net/serverlobbythread.h @@ -128,6 +128,7 @@ protected: void HandleRead(const boost::system::error_code &ec, SessionId sessionId, size_t bytesRead); void HandlePacket(SessionWrapper session, boost::shared_ptr packet); void HandleNetPacketInit(SessionWrapper session, const InitMessage_t &initMessage); + void HandleNetPacketAuthClientResponse(SessionWrapper session, const AuthClientResponse_t &clientResponse); void HandleNetPacketAvatarHeader(SessionWrapper session, unsigned requestId, const AvatarHeader_t &avatarHeader); void HandleNetPacketUnknownAvatar(SessionWrapper session, unsigned requestId, const UnknownAvatar_t &unknownAvatar); void HandleNetPacketAvatarFile(SessionWrapper session, unsigned requestId, const AvatarData_t &avatarData); @@ -137,9 +138,10 @@ protected: void HandleNetPacketCreateGame(SessionWrapper session, const std::string &password, const JoinNewGame_t &newGame); void HandleNetPacketJoinGame(SessionWrapper session, const std::string &password, const JoinExistingGame_t &joinGame); void HandleNetPacketChatRequest(SessionWrapper session, const ChatRequestMessage_t &chatRequest); + void AuthChallenge(SessionWrapper session, const std::string &secret); void InitAfterLogin(SessionWrapper session); void EstablishSession(SessionWrapper session); - void AuthenticatePlayer(SessionWrapper session, const std::string &password); + void AuthenticatePlayer(SessionWrapper session); void UserValid(unsigned playerId, DB_id dbPlayerId, const std::string &dbSecret); void UserInvalid(unsigned playerId); void RequestPlayerAvatar(SessionWrapper session); diff --git a/src/net/sessiondata.h b/src/net/sessiondata.h index 7ce2f15b..71e55492 100644 --- a/src/net/sessiondata.h +++ b/src/net/sessiondata.h @@ -59,8 +59,11 @@ public: bool CreateServerAuthSession(Gsasl *context); bool CreateClientAuthSession(Gsasl *context, const std::string &userName, const std::string &password); - bool AuthStep(int stepNum, const std::string &inData, std::string &outData); - std::string AuthGetUser(); + bool AuthStep(int stepNum, const std::string &inData); + std::string AuthGetUser() const; + void AuthSetPassword(const std::string &password); + std::string AuthGetNextOutMsg() const; + int AuthGetCurStepNum() const; void SetReadyFlag(); void ResetReadyFlag(); @@ -98,6 +101,7 @@ private: SessionDataCallback &m_callback; Gsasl_session *m_authSession; int m_curAuthStep; + std::string m_nextGsaslMsg; mutable boost::mutex m_dataMutex; };