diff --git a/pokerth_lib.pro b/pokerth_lib.pro index 1341264e..ce9604bd 100644 --- a/pokerth_lib.pro +++ b/pokerth_lib.pro @@ -242,4 +242,5 @@ mac{ INCLUDEPATH += /Developer/SDKs/MacOSX10.5.sdk/usr/include/ INCLUDEPATH += /Library/Frameworks/SDL.framework/Headers INCLUDEPATH += /Library/Frameworks/SDL_mixer.framework/Headers + INCLUDEPATH += /opt/local/include } diff --git a/src/net/clientstate.h b/src/net/clientstate.h index 74d3da6b..faa67f94 100644 --- a/src/net/clientstate.h +++ b/src/net/clientstate.h @@ -266,6 +266,42 @@ protected: virtual void InternalHandlePacket(boost::shared_ptr client, boost::shared_ptr tmpPacket) = 0; }; +// State: Wait for Authentication Challenge. +class ClientStateWaitAuthChallenge : public AbstractClientStateReceiving +{ +public: + // Access the state singleton. + static ClientStateWaitAuthChallenge &Instance(); + virtual ~ClientStateWaitAuthChallenge(); + + virtual void Enter(boost::shared_ptr client); + virtual void Exit(boost::shared_ptr client); + +protected: + // Protected constructor - this is a singleton. + ClientStateWaitAuthChallenge(); + + virtual void InternalHandlePacket(boost::shared_ptr client, boost::shared_ptr tmpPacket); +}; + +// State: Wait for Authentication Verification. +class ClientStateWaitAuthVerify : public AbstractClientStateReceiving +{ +public: + // Access the state singleton. + static ClientStateWaitAuthVerify &Instance(); + virtual ~ClientStateWaitAuthVerify(); + + virtual void Enter(boost::shared_ptr client); + virtual void Exit(boost::shared_ptr client); + +protected: + // Protected constructor - this is a singleton. + ClientStateWaitAuthVerify(); + + virtual void InternalHandlePacket(boost::shared_ptr client, boost::shared_ptr tmpPacket); +}; + // State: Wait for Session ACK. class ClientStateWaitSession : public AbstractClientStateReceiving { diff --git a/src/net/clientthread.h b/src/net/clientthread.h index 904d32ed..7a4a61a5 100644 --- a/src/net/clientthread.h +++ b/src/net/clientthread.h @@ -267,6 +267,8 @@ friend class ClientStateWaitChooseServer; friend class ClientStateStartConnect; friend class ClientStateConnecting; friend class ClientStateStartSession; +friend class ClientStateWaitAuthChallenge; +friend class ClientStateWaitAuthVerify; friend class ClientStateWaitSession; friend class ClientStateWaitJoin; friend class ClientStateWaitGame; diff --git a/src/net/common/clientstate.cpp b/src/net/common/clientstate.cpp index b0b7fc6b..a61aaa41 100644 --- a/src/net/common/clientstate.cpp +++ b/src/net/common/clientstate.cpp @@ -676,10 +676,11 @@ 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; - // TODO + // Send authentication user data for challenge/response in init. boost::shared_ptr tmpSession = context.GetSessionData(); tmpSession->CreateClientAuthSession(client->GetAuthContext(), context.GetPlayerName(), context.GetPassword()); - tmpSession->AuthStep(1, ""); + if (!tmpSession->AuthStep(1, "")) + throw ClientException(__FILE__, __LINE__, ERR_NET_INVALID_PASSWORD, 0); string outUserData(tmpSession->AuthGetNextOutMsg()); OCTET_STRING_fromBuf(&authLogin->clientUserData, outUserData.c_str(), @@ -700,7 +701,7 @@ ClientStateStartSession::Enter(boost::shared_ptr client) } client->GetSender().Send(context.GetSessionData(), init); - client->SetState(ClientStateWaitSession::Instance()); + client->SetState(ClientStateWaitAuthChallenge::Instance()); } void @@ -1008,6 +1009,118 @@ AbstractClientStateReceiving::HandlePacket(boost::shared_ptr clien //----------------------------------------------------------------------------- +ClientStateWaitAuthChallenge & +ClientStateWaitAuthChallenge::Instance() +{ + static ClientStateWaitAuthChallenge state; + return state; +} + +ClientStateWaitAuthChallenge::ClientStateWaitAuthChallenge() +{ +} + +ClientStateWaitAuthChallenge::~ClientStateWaitAuthChallenge() +{ +} + +void +ClientStateWaitAuthChallenge::Enter(boost::shared_ptr client) +{ + // Now we finally start receiving data. + client->StartAsyncRead(); +} + +void +ClientStateWaitAuthChallenge::Exit(boost::shared_ptr /*client*/) +{ +} + +void +ClientStateWaitAuthChallenge::InternalHandlePacket(boost::shared_ptr client, boost::shared_ptr tmpPacket) +{ + if (tmpPacket->GetMsg()->present == PokerTHMessage_PR_authMessage) + { + // Check subtype. + AuthMessage_t *netAuth = &tmpPacket->GetMsg()->choice.authMessage; + if (netAuth->present == AuthMessage_PR_authServerChallenge) + { + AuthServerChallenge_t *netChallenge = &netAuth->choice.authServerChallenge; + string challengeStr((const char *)netChallenge->serverChallenge.buf, netChallenge->serverChallenge.size); + boost::shared_ptr tmpSession = client->GetContext().GetSessionData(); + if (!tmpSession->AuthStep(2, challengeStr.c_str())) + throw ClientException(__FILE__, __LINE__, ERR_NET_INVALID_PASSWORD, 0); + string outUserData(tmpSession->AuthGetNextOutMsg()); + + + boost::shared_ptr packet(new NetPacket(NetPacket::Alloc)); + packet->GetMsg()->present = PokerTHMessage_PR_authMessage; + AuthMessage_t *outAuth = &packet->GetMsg()->choice.authMessage; + outAuth->present = AuthMessage_PR_authClientResponse; + AuthClientResponse_t *outResponse = &outAuth->choice.authClientResponse; + + OCTET_STRING_fromBuf(&outResponse->clientResponse, + outUserData.c_str(), + outUserData.length()); + client->GetSender().Send(tmpSession, packet); + client->SetState(ClientStateWaitAuthVerify::Instance()); + } + else + throw ClientException(__FILE__, __LINE__, ERR_NET_INVALID_PASSWORD, 0); + } +} + +//----------------------------------------------------------------------------- + +ClientStateWaitAuthVerify & +ClientStateWaitAuthVerify::Instance() +{ + static ClientStateWaitAuthVerify state; + return state; +} + +ClientStateWaitAuthVerify::ClientStateWaitAuthVerify() +{ +} + +ClientStateWaitAuthVerify::~ClientStateWaitAuthVerify() +{ +} + +void +ClientStateWaitAuthVerify::Enter(boost::shared_ptr /*client*/) +{ +} + +void +ClientStateWaitAuthVerify::Exit(boost::shared_ptr /*client*/) +{ +} + +void +ClientStateWaitAuthVerify::InternalHandlePacket(boost::shared_ptr client, boost::shared_ptr tmpPacket) +{ + if (tmpPacket->GetMsg()->present == PokerTHMessage_PR_authMessage) + { + // Check subtype. + AuthMessage_t *netAuth = &tmpPacket->GetMsg()->choice.authMessage; + if (netAuth->present == AuthMessage_PR_authServerVerification) + { + AuthServerVerification_t *netVerification = &netAuth->choice.authServerVerification; + string verificationStr((const char *)netVerification->serverVerification.buf, netVerification->serverVerification.size); + boost::shared_ptr tmpSession = client->GetContext().GetSessionData(); + if (!tmpSession->AuthStep(3, verificationStr.c_str())) + throw ClientException(__FILE__, __LINE__, ERR_NET_INVALID_PASSWORD, 0); + + client->SetState(ClientStateWaitSession::Instance()); + } + else + throw ClientException(__FILE__, __LINE__, ERR_NET_INVALID_PASSWORD, 0); + } +} + +//----------------------------------------------------------------------------- + ClientStateWaitSession & ClientStateWaitSession::Instance() { @@ -1024,10 +1137,8 @@ ClientStateWaitSession::~ClientStateWaitSession() } void -ClientStateWaitSession::Enter(boost::shared_ptr client) +ClientStateWaitSession::Enter(boost::shared_ptr /*client*/) { - // Now we finally start receiving data. - client->StartAsyncRead(); } void