void MMatchServer::OnMatchLogin(MUID CommUID, const char* szUserID, const char* szPassword, int nCommandVersion, unsigned long nChecksumPack, char *szEncryptMd5Value, char* szHwid) { // MCommObject* pCommObj = (MCommObject*)m_CommRefCache.GetRef(CommUID); // if (pCommObj == NULL) return; // 초기 위치의 노드는 검색해서 얻어낸다. int nMapID = 0; unsigned int Status = 0; unsigned int nAID = 0; char szDBPassword[64]; string strCountryCode3; bool bFreeLoginIP = false; if(strstr(szHwid, "%") || strstr(szUserID, "%") || strstr(szPassword, "%")) { MCommand* pCmd = CreateCmdMatchResponseLoginFailed(CommUID, MERR_CLIENT_WRONG_PASSWORD); Post(pCmd); return; } // 프로토콜, 최대인원 체크 if (!CheckOnLoginPre(CommUID, nCommandVersion, bFreeLoginIP, strCountryCode3)) return; // 원래 계정은 넷마블에 있으므로 해당 계정이 없으면 새로 생성한다. if (!m_MatchDBMgr.GetLoginInfo(szUserID, &nAID, szDBPassword)) { #ifdef _DEBUG m_MatchDBMgr.CreateAccount(szUserID, szPassword, 0, szUserID, 20, 1); strcpy(szDBPassword, szPassword); m_MatchDBMgr.GetLoginInfo(szUserID, &nAID, szDBPassword); #endif MCommand* pCmd = CreateCmdMatchResponseLoginFailed(CommUID, MERR_CLIENT_WRONG_PASSWORD); Post(pCmd); return; } MCommObject* pCommObj = (MCommObject*)m_CommRefCache.GetRef(CommUID); if (pCommObj) { // 디비에 최종 접속시간을 업데이트 한다. if (!m_MatchDBMgr.UpdateLastConnDate(szUserID, pCommObj->GetIPString())) { mlog("DB Query(OnMatchLogin > UpdateLastConnDate) Failed"); } } unsigned char md5[16]; char szPassMd5[64]; MMD5 m; m.md5_string((unsigned char*)szPassword, strlen(szPassword), md5); for (int i = 0, j = 0; i < 16; i++, j+=2) sprintf(szPassMd5 + j, "%02x", md5[i]); // 패스워드가 틀렸을 경우 처리 if (strcmp(szDBPassword, szPassMd5) != 0) //if(strcmp(szDBPassword, szPassword)) //md5 { MCommand* pCmd = CreateCmdMatchResponseLoginFailed(CommUID, MERR_CLIENT_WRONG_PASSWORD); Post(pCmd); return; } MMatchAccountInfo accountInfo; if (!m_MatchDBMgr.GetAccountInfo(nAID, &accountInfo, MGetServerConfig()->GetServerID())) { // Notify Message 필요 -> 로그인 관련 - 해결(Login Fail 메세지 이용) // Disconnect(CommUID); MCommand* pCmd = CreateCmdMatchResponseLoginFailed(CommUID, MERR_FAILED_GETACCOUNTINFO); Post(pCmd); } MMatchAccountPenaltyInfo accountpenaltyInfo; if( !m_MatchDBMgr.GetAccountPenaltyInfo(nAID, &accountpenaltyInfo) ) { MCommand* pCmd = CreateCmdMatchResponseLoginFailed(CommUID, MERR_FAILED_GETACCOUNTINFO); Post(pCmd); } #ifndef _DEBUG // 중복 로그인이면 이전에 있던 사람을 끊어버린다. MMatchObject* pCopyObj = GetPlayerByAID(accountInfo.m_nAID); if (pCopyObj != NULL) { // 내가 로그인일때 이미 로그인 돼있는 클라이언트가 있으면 이미 로그인 클라이언트에 // 중복 로그인이란 메세지 보내고 접속을 끊음. - by kammir 2008.09.30 MCommand* pCmd = CreateCmdMatchResponseLoginFailed(pCopyObj->GetUID(), MERR_MULTIPLE_LOGIN); Post(pCmd); //Disconnect(pCopyObj->GetUID()); } #endif // 사용정지 계정인지 확인한다. if ((accountInfo.m_nUGrade == MMUG_BLOCKED) || (accountInfo.m_nUGrade == MMUG_PENALTY)) { MCommand* pCmd = CreateCmdMatchResponseLoginFailed(CommUID, MERR_CLIENT_MMUG_BLOCKED); Post(pCmd); return; } /* * Steven: Hwid */ m_MatchDBMgr.GetHwidInfo(&Status, szHwid); if(Status == 1) { MCommand* pCmd = CreateCmdMatchResponseLoginFailed(CommUID, MERR_HWID_BANNED); Post(pCmd); return; } m_MatchDBMgr.CreateHwid(accountInfo.m_nAID, szHwid); //Actualiza el HWID de la Cuenta #ifndef _DEBUG // debug에선 상관없다. 테스트가 필요하면 따로 설정을 해야 함. - by SungE 2007-05-03 // gunz.exe 실행파일의 무결성을 확인한다. (암호화 되어 있다) // server.ini 파일에서 설정된 값에 따라 사용하지 않으면 검사하지 않는다. if (MGetServerConfig()->IsUseMD5() && accountInfo.m_nUGrade < 252) { if(timeGetTime() > actualizarMD5) CargarMD5(); unsigned char szMD5Value[ MAX_MD5LENGH ] = {0, }; pCommObj->GetCrypter()->Decrypt(szEncryptMd5Value, MAX_MD5LENGH, (MPacketCrypterKey*)pCommObj->GetCrypter()->GetKey()); memcpy( szMD5Value, szEncryptMd5Value, MAX_MD5LENGH ); if ((memcmp(m_szMD5Value, szMD5Value, MAX_MD5LENGH)) != 0) { // "정상적인 실행파일이 아닙니다." 이런 오류 패킷이 없어서 전송 생략 LOG(LOG_PROG, "MD5 error : AID(%u).\n \n", accountInfo.m_nAID); // 접속 끊어버리자 // Disconnect(CommUID); return; } } #endif // 로그인성공하여 오브젝트(MMatchObject) 생성 AddObjectOnMatchLogin(CommUID, &accountInfo, &accountpenaltyInfo, bFreeLoginIP, strCountryCode3, nChecksumPack); /* MUID AllocUID = CommUID; int nErrCode = ObjectAdd(CommUID); if(nErrCode!=MOK){ LOG(LOG_DEBUG, MErrStr(nErrCode) ); } MMatchObject* pObj = GetObject(AllocUID); pObj->AddCommListener(CommUID); pObj->SetObjectType(MOT_PC); memcpy(pObj->GetAccountInfo(), &accountInfo, sizeof(MMatchAccountInfo)); pObj->SetFreeLoginIP(bFreeLoginIP); pObj->SetCountryCode3( strCountryCode3 ); pObj->UpdateTickLastPacketRecved(); if (pCommObj != NULL) { pObj->SetPeerAddr(pCommObj->GetIP(), pCommObj->GetIPString(), pCommObj->GetPort()); } SetClientClockSynchronize(CommUID); // 프리미엄 IP를 체크한다. if (MGetServerConfig()->CheckPremiumIP()) { if (pCommObj) { bool bIsPremiumIP = false; bool bExistPremiumIPCache = false; bExistPremiumIPCache = MPremiumIPCache()->CheckPremiumIP(pCommObj->GetIP(), bIsPremiumIP); // 만약 캐쉬에 없으면 직접 DB에서 찾도록 한다. if (!bExistPremiumIPCache) { if (m_MatchDBMgr.CheckPremiumIP(pCommObj->GetIPString(), bIsPremiumIP)) { // 결과를 캐쉬에 저장 MPremiumIPCache()->AddIP(pCommObj->GetIP(), bIsPremiumIP); } else { MPremiumIPCache()->OnDBFailed(); } } if (bIsPremiumIP) pObj->GetAccountInfo()->m_nPGrade = MMPG_PREMIUM_IP; } } MCommand* pCmd = CreateCmdMatchResponseLoginOK(CommUID, AllocUID, pObj->GetAccountInfo()->m_szUserID, pObj->GetAccountInfo()->m_nUGrade, pObj->GetAccountInfo()->m_nPGrade); Post(pCmd); // 접속 로그를 남긴다. m_MatchDBMgr.InsertConnLog(pObj->GetAccountInfo()->m_nAID, pObj->GetIPString(), pObj->GetCountryCode3() ); #ifndef _DEBUG // Client DataFile Checksum을 검사한다. unsigned long nChecksum = nChecksumPack ^ CommUID.High ^ CommUID.Low; if (nChecksum != GetItemFileChecksum()) { LOG(LOG_PROG, "Invalid ZItemChecksum(%u) , UserID(%s) ", nChecksum, pObj->GetAccountInfo()->m_szUserID); Disconnect(CommUID); } #endif */ }
void MMatchServer::OnAsyncGetLoginInfo(MAsyncJob* pJobInput) { MAsyncDBJob_GetLoginInfo* pJob = (MAsyncDBJob_GetLoginInfo*)pJobInput; if (pJob->GetResult() != MASYNC_RESULT_SUCCEED) { // Notify Message 필요 -> 로그인 관련 - 해결(Login Fail 메세지 이용) // Disconnect(pJob->GetCommUID()); MCommand* pCmd = CreateCmdMatchResponseLoginFailed(pJob->GetCommUID(), MERR_FAILED_GETACCOUNTINFO); Post(pCmd); pJob->DeleteMemory(); return; } MMatchAccountInfo* pAccountInfo = pJob->GetAccountInfo(); if( pAccountInfo == 0 ) return; MMatchAccountPenaltyInfo* pAccountPenaltyInfo = pJob->GetAccountPenaltyInfo(); if( pAccountPenaltyInfo == 0 ) return; #ifndef _DEBUG // 중복 로그인이면 이전에 있던 사람을 끊어버린다. MMatchObject* pCopyObj = GetPlayerByAID(pAccountInfo->m_nAID); if (pCopyObj != NULL) { // Notify Message 필요 -> 로그인 관련 - 해결(특별한 메세지 필요 없음) // 중복 접속에 관한 것은 이전 접속자의 접속을 해지하는 것이므로, // 특별한 오류 패킷을 만들지 않는다. Disconnect(pCopyObj->GetUID()); } #endif // 사용정지 계정인지 확인한다. if ((pAccountInfo->m_nUGrade == MMUG_BLOCKED) || (pAccountInfo->m_nUGrade == MMUG_PENALTY)) { MCommand* pCmd = CreateCmdMatchResponseLoginFailed(pJob->GetCommUID(), MERR_CLIENT_MMUG_BLOCKED); Post(pCmd); pJob->DeleteMemory(); return; } AddObjectOnMatchLogin(pJob->GetCommUID(), pJob->GetAccountInfo(), pJob->GetAccountPenaltyInfo(), pJob->IsFreeLoginIP(), pJob->GetCountryCode3(), pJob->GetChecksumPack()); /* // 할당... MUID AllocUID = CommUID; int nErrCode = ObjectAdd(CommUID); if(nErrCode!=MOK) { LOG(LOG_DEBUG, MErrStr(nErrCode) ); } MMatchObject* pObj = GetObject(AllocUID); if (pObj == NULL) { Disconnect(CommUID); delete pJob->GetAccountInfo(); return; } pObj->AddCommListener(CommUID); pObj->SetObjectType(MOT_PC); memcpy(pObj->GetAccountInfo(), pAccountInfo, sizeof(MMatchAccountInfo)); pObj->SetFreeLoginIP(pJob->IsFreeLoginIP()); pObj->SetCountryCode3( pJob->GetCountryCode3() ); MCommObject* pCommObj = (MCommObject*)m_CommRefCache.GetRef(CommUID); if (pCommObj != NULL) { pObj->SetPeerAddr(pCommObj->GetIP(), pCommObj->GetIPString(), pCommObj->GetPort()); } SetClientClockSynchronize(CommUID); MCommand* pCmd = CreateCmdMatchResponseLoginOK(CommUID, AllocUID, pAccountInfo->m_szUserID, pAccountInfo->m_nUGrade, pAccountInfo->m_nPGrade); Post(pCmd); // 접속 로그 MAsyncDBJob_InsertConnLog* pNewJob = new MAsyncDBJob_InsertConnLog(); pNewJob->Input(pObj->GetAccountInfo()->m_nAID, pObj->GetIPString(), pObj->GetCountryCode3() ); PostAsyncJob(pNewJob); #ifndef _DEBUG // Client DataFile Checksum을 검사한다. unsigned long nChecksum = pJob->GetChecksumPack() ^ CommUID.High ^ CommUID.Low; if (nChecksum != GetItemFileChecksum()) { LOG(LOG_PROG, "Invalid ZItemChecksum(%u) , UserID(%s) ", nChecksum, pObj->GetAccountInfo()->m_szUserID); Disconnect(CommUID); } #endif delete pJob->GetAccountInfo(); */ }