bool TSessionRedisStore::store(TSession &session) { QByteArray data; QDataStream ds(&data, QIODevice::WriteOnly); ds << *static_cast<const QVariantMap *>(&session); data = qCompress(data, 1).toBase64(); #ifndef TF_NO_DEBUG { QByteArray badummy; QDataStream dsdmy(&badummy, QIODevice::ReadWrite); dsdmy << *static_cast<const QVariantMap *>(&session); TSession dummy; dsdmy.device()->seek(0); dsdmy >> *static_cast<QVariantMap *>(&dummy); if (dsdmy.status() != QDataStream::Ok) { tSystemError("Failed to store a session into the cookie store. Must set objects that can be serialized."); } } #endif TRedis redis; tSystemDebug("TSessionRedisStore::store id:%s", session.id().data()); return redis.setEx('_' + session.id(), data, lifeTimeSecs()); }
TSession TSessionCookieStore::find(const QByteArray &id, const QDateTime &) { TSession session; if (id.isEmpty()) return session; QList<QByteArray> balst = id.split('_'); if (balst.count() == 2 && !balst.value(0).isEmpty() && !balst.value(1).isEmpty()) { QByteArray ba = QByteArray::fromHex(balst.value(0)); QByteArray digest = QCryptographicHash::hash(ba + Tf::app()->appSettings().value("Session.Secret").toByteArray(), QCryptographicHash::Sha1); if (digest != QByteArray::fromHex(balst.value(1))) { tSystemWarn("Recieved a tampered cookie or that of other web application."); //throw SecurityException("Tampered with cookie", __FILE__, __LINE__); return session; } QDataStream ds(&ba, QIODevice::ReadOnly); ds >> *static_cast<QVariantHash *>(&session); if (ds.status() != QDataStream::Ok) { tSystemError("Unable to load a session from the cookie store."); session.clear(); } }
bool TSessionSqlObjectStore::store(TSession &session) { TSqlORMapper<TSessionObject> mapper; TCriteria cri(TSessionObject::Id, TSql::Equal, session.id()); TSessionObject so = mapper.findFirst(cri); #ifndef TF_NO_DEBUG { QByteArray badummy; QDataStream dsdmy(&badummy, QIODevice::ReadWrite); dsdmy << *static_cast<const QVariantMap *>(&session); TSession dummy; dsdmy.device()->seek(0); dsdmy >> *static_cast<QVariantMap *>(&dummy); if (dsdmy.status() != QDataStream::Ok) { tSystemError("Failed to store a session into the cookie store. Must set objects that can be serialized."); } } #endif QDataStream ds(&so.data, QIODevice::WriteOnly); ds << *static_cast<const QVariantMap *>(&session); if (ds.status() != QDataStream::Ok) { tSystemError("Failed to store session. Must set objects that can be serialized."); return false; } if (so.isNull()) { so.id = session.id(); return so.create(); } return so.update(); }
//-------------------------------------------------------------------------------------------- TSession* TManagerSession::NewSession(TIP_Port& ip_port, INetTransport* pTransport) { mLastID_Session++;// нет проверки на совпадение, unsigned int 4 млрд - слишком много TSession* pSession = new TSession(mTimeLiveSession); pSession->SetTransport(pTransport); pSession->SetInfo(ip_port); pSession->SetID(mLastID_Session); mNavigateSession->Add(pSession); return pSession; }
//-------------------------------------------------------------------------------------------- unsigned int TSessionManager::GetSessionID( unsigned int ip, unsigned short port ) { unsigned int id = INVALID_HANDLE_SESSION; if( mNavigateSession == nullptr ) return id; TIP_Port ip_port( ip, port ); TSession* pSession = mNavigateSession->FindSessionByIP( ip_port ); if( pSession ) id = pSession->GetID(); return id; }
//-------------------------------------------------------------------------------------------- void TSessionManager::DisconnectHandler( TDisconnectTransportEvent* pEvent ) { if( mNavigateSession == nullptr ) return; TSession* pSession = mNavigateSession->FindSessionByIP( pEvent->ip_port ); if( pSession ) { unsigned int id = pSession->GetID(); mCallBackDiconnect.Notify( id ); mNavigateSession->Delete( pSession ); } }
//-------------------------------------------------------------------------------------------- TSession* TSessionManager::NewSession( TIP_Port& ip_port, INetTransport* pTransport, bool connectTo_elseFrom ) { auto state = connectTo_elseFrom ? TSession::StateWaitConnectTo : TSession::StateWaitLogin; mLastID_Session++;// нет проверки на совпадение, unsigned int 4 млрд - слишком много TSession* pSession = new TSession( state, mTimeLiveSession ); pSession->SetTransport( pTransport ); pSession->SetInfo( ip_port ); pSession->SetID( mLastID_Session ); mNavigateSession->Add( pSession ); return pSession; }
//------------------------------------------------------------------------- bool TSessionManager::GetInfo( unsigned int ID_Session, TIP_Port& ip_port_out ) { bool res = false; if( mNavigateSession == nullptr ) return false; //=================================================================== TSession* pSession = mNavigateSession->FindSessionByID( ID_Session ); if( pSession ) { res = true; pSession->GetInfo( ip_port_out ); } return res; }
//-------------------------------------------------------------------------------------------- void TManagerSession::Recv( INetTransport::TDescRecv* pDescRecv, INetTransport* pTransport) { lockAccessSession(); if(mNavigateSession==NULL) { unlockAccessSession(); return; } //=================================================================== // данные, пришедшие от сессии содержат заголовок, учесть при формировании TSession::THeader* pHeader = (TSession::THeader*)pDescRecv->data; // определить новая сессия или нет TSession* pSession = mNavigateSession->FindSessionByIP(pDescRecv->ip_port); if(pSession==NULL) { // новую сессию создавать, только если получен RSA ключ if(pHeader->type!=TSession::eKeyRSA) { unlockAccessSession(); return; } pSession = NewSession(pDescRecv->ip_port, pTransport); } else pSession->Recv();// уведомить сессию о приеме unsigned int id = pSession->GetID(); //----------------------------------------------- TDescRecvSession descRecvSession; *((INetTransport::TDescRecv*)&descRecvSession) = *pDescRecv; descRecvSession.id_session = id; // данные, пришедшие от сессии содержат заголовок, учесть при формировании descRecvSession.use_crypt = pHeader->use_crypt; switch(pHeader->type) { case TSession::eEcho: break; case TSession::ePacket: RecvPacket(descRecvSession, pSession); break; case TSession::eKeyRSA: RecvKeyRSA(descRecvSession, pSession); break; case TSession::eKeyAES: RecvKeyAES(descRecvSession); break; default: FixHack("Undefined type packet"); } unlockAccessSession(); }
bool TSessionSqlObjectStore::store(TSession &session) { TSqlORMapper<TSessionObject> mapper; TCriteria cri(TSessionObject::Id, TSql::Equal, session.id()); TSessionObject so = mapper.findFirst(cri); QDataStream ds(&so.data, QIODevice::WriteOnly); ds << *static_cast<const QVariantHash *>(&session); if (so.isEmpty()) { so.id = session.id(); return so.create(); } return so.update(); }
//-------------------------------------------------------------------------------------------- unsigned int TManagerSession::GetSessionID(unsigned int ip, unsigned short port) { unsigned int id = INVALID_HANDLE_SESSION; lockAccessSession(); if(mNavigateSession==NULL) { unlockAccessSession(); return id; } //=================================================================== TSession* pSession = mNavigateSession->FindSessionByIP(TIP_Port(ip,port)); if(pSession) id = pSession->GetID(); unlockAccessSession(); return id; }
/*! \~english Sets CSRF protection informaion into \a session. Internal use. \~japanese CSRF対策の情報をセッションに設定する (内部使用) */ void TActionController::setCsrfProtectionInto(TSession &session) { if (Tf::app()->appSettings().value(STORE_TYPE).toString().toLower() == QLatin1String("cookie")) { QString key = Tf::app()->appSettings().value(CSRF_PROTECTION_KEY).toString(); session.insert(key, TSessionManager::instance().generateId()); // it's just a random value } }
//------------------------------------------------------------------------- void TSessionManager::Accept( unsigned int sessionID, std::string& password ) { if( mNavigateSession == nullptr ) { BL_FIX_BUG(); return; } TSession* pSession = mNavigateSession->FindSessionByID( sessionID ); if( pSession == nullptr ) { BL_FIX_BUG(); return; } pSession->SetPassword( password ); pSession->SetState( TSession::StateWaitConfirmation ); pSession->SendKeyAES(); }
//-------------------------------------------------------------------------------------------- void TSessionManager::RecvHandler( TRecvTransportEvent* pEvent ) { if( mNavigateSession == nullptr ) return; //=================================================================== // данные, пришедшие от сессии содержат заголовок, учесть при формировании auto pHeader = (TSession::THeader*)pEvent->data.GetPtr(); // определить новая сессия или нет TSession* pSession = mNavigateSession->FindSessionByIP( pEvent->ip_port ); if( pSession == nullptr ) return; TDescRecvSession descRecvSession; descRecvSession.c = pEvent->data;// данные пакета descRecvSession.data = descRecvSession.c.GetPtr(); descRecvSession.dataSize = descRecvSession.c.GetSize(); descRecvSession.ip_port = pEvent->ip_port; descRecvSession.type = pEvent->typeRecv; descRecvSession.sessionID = pSession->GetID(); // данные, пришедшие от сессии содержат заголовок, учесть при формировании switch( pHeader->type ) { case TSession::eEcho: break; case TSession::eData: RecvData( descRecvSession, pSession ); break; case TSession::eLogin: RecvLogin( descRecvSession, pSession ); break; case TSession::eKeyAES: RecvKeyAES( descRecvSession, pSession ); break; case TSession::eIDconfirmation: RecvIDconfirmation( descRecvSession, pSession ); break; default: { BL_FIX_BUG(); FixHack( "Undefined type packet" ); } } }
//------------------------------------------------------------------------- bool TManagerSession::GetInfo(unsigned int ID_Session, TIP_Port& ip_port_out) { bool res = false; lockAccessSession(); if(mNavigateSession==NULL) { unlockAccessSession(); return false; } //=================================================================== TSession* pSession = mNavigateSession->FindSessionByID(ID_Session); if(pSession) { res = true; pSession->GetInfo(ip_port_out); } unlockAccessSession(); return res; }
//-------------------------------------------------------------------------------------------- void TManagerSession::Disconnect(TIP_Port* ip_port) { lockAccessSession(); if(mNavigateSession==NULL) { unlockAccessSession(); return; } //=================================================================== mMngCtxCrypto.Close(*ip_port); TSession* pSession = mNavigateSession->FindSessionByIP(*ip_port); if(pSession) { unsigned int id = pSession->GetID(); mCallBackDiconnect.Notify(id); mNavigateSession->Delete(pSession); } unlockAccessSession(); }
//------------------------------------------------------------------------- bool TManagerSession::GetRSAPublicKey(unsigned int id_session, TContainer& cRSA) { bool res = false; TIP_Port ip_port; lockAccessSession(); if(mNavigateSession==NULL) { unlockAccessSession(); return res; } //=================================================================== TSession* pSession = mNavigateSession->FindSessionByID(id_session); if(pSession) { pSession->GetInfo(ip_port); res = mMngCtxCrypto.GetRSAkeyByIP(ip_port, cRSA); } unlockAccessSession(); return res; }
bool TSessionCookieStore::store(TSession &session) { if (session.isEmpty()) return true; QByteArray ba; QDataStream ds(&ba, QIODevice::WriteOnly); ds << *static_cast<const QVariantHash *>(&session); QByteArray digest = QCryptographicHash::hash(ba + Tf::app()->appSettings().value("Session.Secret").toByteArray(), QCryptographicHash::Sha1); session.sessionId = ba.toHex() + "_" + digest.toHex(); return true; }
//-------------------------------------------------------------------------------------------- void TManagerSession::CloseSession(unsigned int ID_Session) { if(ID_Session==INVALID_HANDLE_SESSION) return; lockAccessSession(); if(mNavigateSession==NULL) { unlockAccessSession(); return; } //=================================================================== TSession* pSession = mNavigateSession->FindSessionByID(ID_Session); if(pSession) { TIP_Port ip_port; pSession->GetInfo(ip_port); mMngCtxCrypto.Close(ip_port); mNavigateSession->Delete(pSession); } unlockAccessSession(); }
bool TSessionManager::store(TSession &session) { T_TRACEFUNC(""); if (session.id().isEmpty()) { tSystemError("Internal Error [%s:%d]", __FILE__, __LINE__); return false; } bool res = false; TSessionStore *store = TSessionStoreFactory::create(storeType()); if (store) { res = store->store(session); delete store; } return res; }
bool TSessionFileStore::store(TSession &session) { QDir dir(sessionDirPath()); if (!dir.exists()) { dir.mkpath("."); } bool res = false; QFile file(sessionDirPath() + session.id()); if (!file.exists()) { if (file.open(QIODevice::WriteOnly)) { QDataStream ds(&file); ds << *static_cast<const QVariantHash *>(&session); res = (ds.status() == QDataStream::Ok); } } return res; }
//-------------------------------------------------------------------------------------------- void TSessionManager::ConnectAsync( TIP_Port& ip_port, std::string& login, std::string& password, unsigned char subNet, ConnectResultCallback onResult ) { BL_ASSERT( flgNeedAnswerFromUp == false ); mConnectResult = onResult; BeginWaitConnectUp(); lockConnectUp(); INetTransport* pTransport = mMngTransport->FindBySubNet( subNet ); if( pTransport == nullptr ) { unlockConnectUp(); return mConnectResult( INVALID_HANDLE_SESSION ); } if( mNavigateSession == nullptr ) { unlockConnectUp(); return mConnectResult( INVALID_HANDLE_SESSION ); } //=================================================================== // соединиться с сервером (верхнее соединение) if( pTransport->Connect( ip_port.ip, ip_port.port ) == false ) { unlockConnectUp(); return mConnectResult( INVALID_HANDLE_SESSION );// нет такого прослушивающего порта }// connect to event mIP_PortUp = ip_port; // запомнить параметры верхнего соединения TSession* pSession = mNavigateSession->FindSessionByIP( mIP_PortUp ); if( pSession == nullptr ) pSession = NewSession( mIP_PortUp, pTransport, true/*connect to*/ ); else { unlockConnectUp(); GetLogger( STR_NAME_MMO_ENGINE )-> WriteF_time( "TSessionManager::Send(%s) sending to IP with exist session.\n", ip_port.ToString() ); BL_FIX_BUG(); return mConnectResult( INVALID_HANDLE_SESSION ); } mSessionID_UP = pSession->GetID(); pSession->SetLogin( login ); pSession->SetPassword( password ); pSession->SetState( TSession::StateWaitKeyAES ); pSession->SendLogin(); unlockConnectUp(); // waiting recv... }
//-------------------------------------------------------------------------------------------- unsigned int TManagerSession::Send(unsigned int ip, unsigned short port, TBreakPacket bp, unsigned char subNet, bool check) { lockConnectUp(); INetTransport* pTransport = mMngTransport->FindBySubNet(subNet); if(pTransport==NULL) { unlockConnectUp(); return INVALID_HANDLE_SESSION; } lockAccessSession(); if(mNavigateSession==NULL) { unlockAccessSession(); unlockConnectUp(); return INVALID_HANDLE_SESSION; } //=================================================================== // соединиться с сервером if(pTransport->Connect(ip, port)==false) { unlockAccessSession(); unlockConnectUp(); //BL_FIX_BUG(); return INVALID_HANDLE_SESSION;// нет такого прослушивающего порта } mIP_PortUp.Set(ip,port); // запомнить параметры верхнего соединения TSession* pSession = mNavigateSession->FindSessionByIP(mIP_PortUp); if(pSession==NULL) pSession = NewSession(mIP_PortUp, pTransport); else { unlockAccessSession(); unlockConnectUp(); GetLogger(STR_NAME_MMO_ENGINE)-> WriteF_time("TManagerSession::Send(0x%X,%u) sending to IP with exist session.\n", ip, port); BL_FIX_BUG(); return INVALID_HANDLE_SESSION; } unsigned int id_session = pSession->GetID(); // отсылка запроса на AES ключ SendKeyRSA_Up(pSession); unlockAccessSession(); //=================================================================== // ждем ответа bool res = WaitAnswerFromUp(); CleanFlagsForWaitUp(); if(res==false) { unlockConnectUp(); GetLogger(STR_NAME_MMO_ENGINE)-> WriteF_time("Wait Answer From Up don't recv answer.\n"); return INVALID_HANDLE_SESSION; } //=================================================================== lockAccessSession(); if(mNavigateSession==NULL) { // произошел разрыв соединения unlockAccessSession(); unlockConnectUp(); return INVALID_HANDLE_SESSION; } // возможно сессия была удалена, пока ждали ответа pSession = mNavigateSession->FindSessionByID(id_session); if(pSession) Send(pSession, bp, check); else id_session = INVALID_HANDLE_SESSION; unlockConnectUp(); unlockAccessSession(); return id_session; }