void WardenBase::RequestModule() { sLog->outDebug(LOG_FILTER_UNITS, "Request module"); // Create packet structure WardenModuleUse Request; Request.Command = WARDEN_SMSG_MODULE_USE; memcpy(Request.Module_Id, Module->ID, 16); memcpy(Request.Module_Key, Module->Key, 16); Request.Size = Module->CompressedSize; // Encrypt with warden RC4 key. EncryptData((uint8*)&Request, sizeof(WardenModuleUse)); WorldPacket pkt(SMSG_WARDEN_DATA, sizeof(WardenModuleUse)); pkt.append((uint8*)&Request, sizeof(WardenModuleUse)); Client->SendPacket(&pkt); }
void WardenWin::InitializeModule() { sLog->outDebug(LOG_FILTER_WARDEN, "Initialize module"); // Create packet structure WardenInitModuleRequest Request; Request.Command1 = WARDEN_SMSG_MODULE_INITIALIZE; Request.Size1 = 20; Request.Unk1 = 1; Request.Unk2 = 0; Request.Type = 1; Request.String_library1 = 0; Request.Function1[0] = 0x00024F80; // 0x00400000 + 0x00024F80 SFileOpenFile Request.Function1[1] = 0x000218C0; // 0x00400000 + 0x000218C0 SFileGetFileSize Request.Function1[2] = 0x00022530; // 0x00400000 + 0x00022530 SFileReadFile Request.Function1[3] = 0x00022910; // 0x00400000 + 0x00022910 SFileCloseFile Request.CheckSumm1 = BuildChecksum(&Request.Unk1, 20); Request.Command2 = WARDEN_SMSG_MODULE_INITIALIZE; Request.Size2 = 8; Request.Unk3 = 4; Request.Unk4 = 0; Request.String_library2 = 0; Request.Function2 = 0x00419D40; // 0x00400000 + 0x00419D40 FrameScript::GetText Request.Function2_set = 1; Request.CheckSumm2 = BuildChecksum(&Request.Unk2, 8); Request.Command3 = WARDEN_SMSG_MODULE_INITIALIZE; Request.Size3 = 8; Request.Unk5 = 1; Request.Unk6 = 1; Request.String_library3 = 0; Request.Function3 = 0x0046AE20; // 0x00400000 + 0x0046AE20 PerformanceCounter Request.Function3_set = 1; Request.CheckSumm3 = BuildChecksum(&Request.Unk5, 8); // Encrypt with warden RC4 key. EncryptData((uint8*)&Request, sizeof(WardenInitModuleRequest)); WorldPacket pkt(SMSG_WARDEN_DATA, sizeof(WardenInitModuleRequest)); pkt.append((uint8*)&Request, sizeof(WardenInitModuleRequest)); _session->SendPacket(&pkt); }
void Warden::RequestModule() { sLog->outDebug(LOG_FILTER_WARDEN, "Request module"); // Create packet structure WardenModuleUse request; request.Command = WARDEN_SMSG_MODULE_USE; memcpy(request.ModuleId, _module->Id, 16); memcpy(request.ModuleKey, _module->Key, 16); request.Size = _module->CompressedSize; // Encrypt with warden RC4 key. EncryptData((uint8*)&request, sizeof(WardenModuleUse)); WorldPacket pkt(SMSG_WARDEN_DATA, sizeof(WardenModuleUse)); pkt.append((uint8*)&request, sizeof(WardenModuleUse)); _session->SendPacket(&pkt); }
// 发送重新处理循环码的数据 bool PasServer::SendCrcData(socket_t *sock, const char* data, int len) { // 处理循环码 char *buf = new char[len + 1]; memset(buf, 0, len + 1); memcpy(buf, data, len); // 处理加密数据 EncryptData((unsigned char*) buf, len, true); // 计算循环码处理,这里需要先加密后处理循环码校验 ResetCrcCode(buf, len); // 添加5B的处理 bool bSend = Send5BCodeData(sock, buf, len); delete[] buf; return bSend; }
void WardenMac::RequestData() { sLog.outDebug("Request data"); ByteBuffer buff; buff << uint8(WARDEN_SMSG_CHEAT_CHECKS_REQUEST); std::string str = "Test string!"; buff << uint8(str.size()); buff.append(str.c_str(), str.size()); buff.hexlike(); // Encrypt with warden RC4 key. EncryptData(const_cast<uint8*>(buff.contents()), buff.size()); WorldPacket pkt(SMSG_WARDEN_DATA, buff.size()); pkt.append(buff); Client->SendPacket(&pkt); m_WardenDataSent = true; }
void WardenMac::RequestData() { sLog->outDebug(LOG_FILTER_WARDEN, "Request data"); ByteBuffer buff; buff << uint8(WARDEN_SMSG_CHEAT_CHECKS_REQUEST); std::string str = "Test string!"; buff << uint8(str.size()); buff.append(str.c_str(), str.size()); buff.hexlike(); // Encrypt with warden RC4 key. EncryptData(buff.contents(), buff.size()); WorldPacket pkt(SMSG_WARDEN_DATA, buff.size()); pkt.append(buff); _session->SendPacket(&pkt); _dataSent = true; }
bool SavedataParam::Save(SceUtilitySavedataParam* param, int saveId) { if (!param) { return false; } std::string dirPath = GetSaveFilePath(param, saveId); if (!pspFileSystem.GetFileInfo(dirPath).exists) pspFileSystem.MkDir(dirPath); u8* cryptedData = 0; int cryptedSize = 0; u8 cryptedHash[0x10]; memset(cryptedHash,0,0x10); // Encrypt save. if(param->dataBuf != 0 && g_Config.bEncryptSave) { cryptedSize = param->dataSize; if(cryptedSize == 0 || (SceSize)cryptedSize > param->dataBufSize) cryptedSize = param->dataBufSize; // fallback, should never use this u8* data_ = (u8*)Memory::GetPointer(param->dataBuf); int aligned_len = align16(cryptedSize); cryptedData = new u8[aligned_len + 0x10]; memcpy(cryptedData, data_, cryptedSize); int decryptMode = 1; if(param->key[0] != 0) { decryptMode = (GetSDKMainVersion(sceKernelGetCompiledSdkVersion()) >= 4 ? 5 : 3); } if(EncryptData(decryptMode, cryptedData, &cryptedSize, &aligned_len, cryptedHash, ((param->key[0] != 0)?param->key:0)) == 0) { } else { ERROR_LOG(HLE,"Save encryption failed. This save won't work on real PSP"); delete[] cryptedData; cryptedData = 0; } } // SAVE PARAM.SFO ParamSFOData sfoFile; std::string sfopath = dirPath+"/"+sfoName; PSPFileInfo sfoInfo = pspFileSystem.GetFileInfo(sfopath); if(sfoInfo.exists) // Read old sfo if exist { u8 *sfoData = new u8[(size_t)sfoInfo.size]; size_t sfoSize = (size_t)sfoInfo.size; if(ReadPSPFile(sfopath,&sfoData,sfoSize, NULL)) { sfoFile.ReadSFO(sfoData,sfoSize); delete[] sfoData; } } // Update values sfoFile.SetValue("TITLE",param->sfoParam.title,128); sfoFile.SetValue("SAVEDATA_TITLE",param->sfoParam.savedataTitle,128); sfoFile.SetValue("SAVEDATA_DETAIL",param->sfoParam.detail,1024); sfoFile.SetValue("PARENTAL_LEVEL",param->sfoParam.parentalLevel,4); sfoFile.SetValue("CATEGORY","MS",4); sfoFile.SetValue("SAVEDATA_DIRECTORY",GetSaveDir(param,saveId),64); // For each file, 13 bytes for filename, 16 bytes for file hash (0 in PPSSPP), 3 byte for padding const int FILE_LIST_ITEM_SIZE = 13 + 16 + 3; const int FILE_LIST_COUNT_MAX = 99; const int FILE_LIST_TOTAL_SIZE = FILE_LIST_ITEM_SIZE * FILE_LIST_COUNT_MAX; u32 tmpDataSize = 0; u8* tmpDataOrig = sfoFile.GetValueData("SAVEDATA_FILE_LIST", &tmpDataSize); u8* tmpData = new u8[FILE_LIST_TOTAL_SIZE]; if (tmpDataOrig != NULL) memcpy(tmpData, tmpDataOrig, tmpDataSize > FILE_LIST_TOTAL_SIZE ? FILE_LIST_TOTAL_SIZE : tmpDataSize); else memset(tmpData, 0, FILE_LIST_TOTAL_SIZE); if (param->dataBuf != 0) { char *fName = (char*)tmpData; for(int i = 0; i < FILE_LIST_COUNT_MAX; i++) { if(fName[0] == 0) break; // End of list if(strncmp(fName,GetFileName(param).c_str(),20) == 0) break; fName += FILE_LIST_ITEM_SIZE; } if (fName + 13 <= (char*)tmpData + FILE_LIST_TOTAL_SIZE) snprintf(fName, 13, "%s",GetFileName(param).c_str()); if (fName + 13 + 16 <= (char*)tmpData + FILE_LIST_TOTAL_SIZE) memcpy(fName+13, cryptedHash, 16); } sfoFile.SetValue("SAVEDATA_FILE_LIST", tmpData, FILE_LIST_TOTAL_SIZE, FILE_LIST_TOTAL_SIZE); delete[] tmpData; // Init param with 0. This will be used to detect crypted save or not on loading tmpData = new u8[128]; memset(tmpData, 0, 128); sfoFile.SetValue("SAVEDATA_PARAMS", tmpData, 128, 128); delete[] tmpData; u8 *sfoData; size_t sfoSize; sfoFile.WriteSFO(&sfoData,&sfoSize); // Calc SFO hash for PSP. if(cryptedData != 0) { int offset = sfoFile.GetDataOffset(sfoData,"SAVEDATA_PARAMS"); if(offset >= 0) UpdateHash(sfoData, sfoSize, offset, (param->key[0]?3:1)); } WritePSPFile(sfopath, sfoData, (SceSize)sfoSize); delete[] sfoData; if(param->dataBuf != 0) // Can launch save without save data in mode 13 { std::string filePath = dirPath+"/"+GetFileName(param); u8* data_ = 0; SceSize saveSize = 0; if(cryptedData == 0) // Save decrypted data { saveSize = param->dataSize; if(saveSize == 0 || saveSize > param->dataBufSize) saveSize = param->dataBufSize; // fallback, should never use this data_ = (u8*)Memory::GetPointer(param->dataBuf); } else { data_ = cryptedData; saveSize = cryptedSize; } INFO_LOG(HLE,"Saving file with size %u in %s",saveSize,filePath.c_str()); // copy back save name in request strncpy(param->saveName,GetSaveDirName(param, saveId).c_str(),20); if (!WritePSPFile(filePath, data_, saveSize)) { ERROR_LOG(HLE,"Error writing file %s",filePath.c_str()); if(cryptedData != 0) { delete[] cryptedData; } return false; } delete[] cryptedData; } // SAVE ICON0 if (param->icon0FileData.buf) { u8* data_ = (u8*)Memory::GetPointer(param->icon0FileData.buf); std::string icon0path = dirPath+"/"+icon0Name; WritePSPFile(icon0path, data_, param->icon0FileData.bufSize); } // SAVE ICON1 if (param->icon1FileData.buf) { u8* data_ = (u8*)Memory::GetPointer(param->icon1FileData.buf); std::string icon1path = dirPath+"/"+icon1Name; WritePSPFile(icon1path, data_, param->icon1FileData.bufSize); } // SAVE PIC1 if (param->pic1FileData.buf) { u8* data_ = (u8*)Memory::GetPointer(param->pic1FileData.buf); std::string pic1path = dirPath+"/"+pic1Name; WritePSPFile(pic1path, data_, param->pic1FileData.bufSize); } // Save SND if (param->snd0FileData.buf) { u8* data_ = (u8*)Memory::GetPointer(param->snd0FileData.buf); std::string snd0path = dirPath+"/"+snd0Name; WritePSPFile(snd0path, data_, param->snd0FileData.bufSize); } // Save Encryption Data { EncryptFileInfo encryptInfo; SceSize dataSize = sizeof(encryptInfo); // version + key + sdkVersion memset(&encryptInfo,0,dataSize); encryptInfo.fileVersion = 1; encryptInfo.sdkVersion = sceKernelGetCompiledSdkVersion(); if(param->size > 1500) memcpy(encryptInfo.key,param->key,16); std::string encryptInfoPath = dirPath+"/"+"ENCRYPT_INFO.BIN"; WritePSPFile(encryptInfoPath, (u8*)&encryptInfo, dataSize); } return true; }
void WardenWin::RequestData() { DEBUG_LOG("WARDEN: Request data"); if (MemCheck.empty()) MemCheck.assign(WardenDataStorage.MemCheckIds.begin(), WardenDataStorage.MemCheckIds.end()); ServerTicks = WorldTimer::getMSTime(); uint32 maxid = WardenDataStorage.InternalDataID; uint32 id; uint8 type; WardenData *wd; SendDataId.clear(); // always! this is SpeedHack on WEH SendDataId.push_back(385); for (int i = 0; i < 3; ++i) // for now include 3 MEM_CHECK's { if (MemCheck.empty()) break; id = MemCheck.back(); SendDataId.push_back(id); MemCheck.pop_back(); } ByteBuffer buff; buff << uint8(WARDEN_SMSG_CHEAT_CHECKS_REQUEST); int maxSize = 8 - MemCheck.size(); for (int i = 0; i < maxSize; ++i) // for now include 5 random checks { id = irand(1, maxid - 1); wd = WardenDataStorage.GetWardenDataById(id); SendDataId.push_back(id); switch (wd->Type) { case MPQ_CHECK: case LUA_STR_CHECK: case DRIVER_CHECK: buff << uint8(wd->str.size()); buff.append(wd->str.c_str(), wd->str.size()); break; default: break; } } uint8 xorByte = InputKey[0]; buff << uint8(0x00); buff << uint8(TIMING_CHECK ^ xorByte); // check TIMING_CHECK uint8 index = 1; for (std::vector<uint32>::iterator itr = SendDataId.begin(); itr != SendDataId.end(); ++itr) { wd = WardenDataStorage.GetWardenDataById(*itr); type = wd->Type; buff << uint8(type ^ xorByte); switch (type) { case MEM_CHECK: { buff << uint8(0x00); buff << uint32(wd->Address); buff << uint8(wd->Length); break; } case PAGE_CHECK_A: case PAGE_CHECK_B: { buff.append(wd->i.AsByteArray(0, false), wd->i.GetNumBytes()); buff << uint32(wd->Address); buff << uint8(wd->Length); break; } case MPQ_CHECK: case LUA_STR_CHECK: { buff << uint8(index++); break; } case DRIVER_CHECK: { buff.append(wd->i.AsByteArray(0, false), wd->i.GetNumBytes()); buff << uint8(index++); break; } case MODULE_CHECK: { uint32 seed = static_cast<uint32>(rand32()); buff << uint32(seed); HMACSHA1 hmac(4, (uint8*)&seed); hmac.UpdateData(wd->str); hmac.Finalize(); buff.append(hmac.GetDigest(), hmac.GetLength()); break; } /*case PROC_CHECK: { buff.append(wd->i.AsByteArray(0, false), wd->i.GetNumBytes()); buff << uint8(index++); buff << uint8(index++); buff << uint32(wd->Address); buff << uint8(wd->Length); break; }*/ default: break; // should never happens } } buff << uint8(xorByte); buff.hexlike(); // Encrypt with warden RC4 key. EncryptData(const_cast<uint8*>(buff.contents()), buff.size()); WorldPacket pkt(SMSG_WARDEN_DATA, buff.size()); pkt.append(buff); Client->SendPacket(&pkt); m_WardenDataSent = true; std::stringstream stream; stream << "Sent check id's: "; for (std::vector<uint32>::iterator itr = SendDataId.begin(); itr != SendDataId.end(); ++itr) stream << *itr << " "; DEBUG_LOG("WARDEN: %s",stream.str().c_str()); }
void WardenWin::RequestData() { sLog->outStaticDebug("Request data"); if(MemCheck.empty()) MemCheck.assign(WardenDataStorage.MemCheckIds.begin(), WardenDataStorage.MemCheckIds.end()); ServerTicks = getMSTime(); uint32 maxid = WardenDataStorage.InternalDataID; uint32 id; uint8 type; WardenData *wd; SendDataId.clear(); uint8 memcheckAdded = 0; for(uint32 i = 1; i <= maxid; ++i) { if(MemCheck.empty()) break; if(memcheckAdded >= 3) // for now include 3 MEM_CHECK's break; id = MemCheck.back(); if(std::find(SendDataId.begin(), SendDataId.end(), id) != SendDataId.end()) continue; memcheckAdded++; SendDataId.push_back(id); MemCheck.pop_back(); } ByteBuffer buff; buff << uint8(WARDEN_SMSG_CHEAT_CHECKS_REQUEST); uint8 cheatCheckAdded = 0; for(uint32 i = 1; i <= maxid; ++i) // for now include 5 random checks { if(cheatCheckAdded >= 5) break; id = urand(1, maxid - 1); if(std::find(SendDataId.begin(), SendDataId.end(), id) != SendDataId.end()) continue; cheatCheckAdded++; wd = WardenDataStorage.GetWardenDataById(id); SendDataId.push_back(id); switch(wd->Type) { case MPQ_CHECK: case LUA_STR_CHECK: case DRIVER_CHECK: buff << uint8(wd->str.size()); buff.append(wd->str.c_str(), wd->str.size()); break; default: break; } } uint8 xorByte = InputKey[0]; buff << uint8(0x00); buff << uint8(TIMING_CHECK ^ xorByte); // check TIMING_CHECK uint8 index = 1; for(std::vector<uint32>::iterator itr = SendDataId.begin(); itr != SendDataId.end(); ++itr) { wd = WardenDataStorage.GetWardenDataById(*itr); type = wd->Type; buff << uint8(type ^ xorByte); switch(type) { case MEM_CHECK: { buff << uint8(0x00); buff << uint32(wd->Address); buff << uint8(wd->Length); break; } case PAGE_CHECK_A: case PAGE_CHECK_B: { buff.append(wd->i.AsByteArray(0, false), wd->i.GetNumBytes()); buff << uint32(wd->Address); buff << uint8(wd->Length); break; } case MPQ_CHECK: case LUA_STR_CHECK: { buff << uint8(index++); break; } case DRIVER_CHECK: { buff.append(wd->i.AsByteArray(0, false), wd->i.GetNumBytes()); buff << uint8(index++); break; } case MODULE_CHECK: { uint32 seed = static_cast<uint32>(rand32()); buff << uint32(seed); HmacHash hmac(4, (uint8*)&seed); hmac.UpdateData(wd->str); hmac.Finalize(); buff.append(hmac.GetDigest(), hmac.GetLength()); break; } default: break; // should never happens } } buff << uint8(xorByte); buff.hexlike(); // Encrypt with warden RC4 key. EncryptData(const_cast<uint8*>(buff.contents()), buff.size()); WorldPacket pkt(SMSG_WARDEN_DATA, buff.size()); pkt.append(buff); Client->SendPacket(&pkt); m_WardenDataSent = true; std::stringstream stream; stream << "Sent check id's: "; for(std::vector<uint32>::iterator itr = SendDataId.begin(); itr != SendDataId.end(); ++itr) stream << *itr << " "; sLog->outStaticDebug(stream.str().c_str()); }
void AppleCSPSession::WrapKey( CSSM_CC_HANDLE CCHandle, const Context &Context, const AccessCredentials &AccessCred, const CssmKey &UnwrappedKey, const CssmData *DescriptiveData, CssmKey &WrappedKey, CSSM_PRIVILEGE Privilege) { CssmKey::Header &wrappedHdr = WrappedKey.header(); bool isNullWrap = false; CssmKey *wrappingKey = NULL; CSSM_KEYBLOB_FORMAT wrapFormat; switch(UnwrappedKey.keyClass()) { case CSSM_KEYCLASS_PUBLIC_KEY: case CSSM_KEYCLASS_PRIVATE_KEY: case CSSM_KEYCLASS_SESSION_KEY: break; default: CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS); } /* wrapping key only required for non-NULL wrap */ wrappingKey = Context.get<CssmKey>(CSSM_ATTRIBUTE_KEY); if(wrappingKey == NULL) { if((Context.algorithm() == CSSM_ALGID_NONE) && (Context.type() == CSSM_ALGCLASS_SYMMETRIC)) { // NULL wrap, OK isNullWrap = true; } else { errorLog0("WrapKey: missing wrapping key\n"); CssmError::throwMe(CSSMERR_CSP_MISSING_ATTR_KEY); } } /* * Validate misc. params as best we can */ if(isNullWrap) { wrapFormat = CSSM_KEYBLOB_WRAPPED_FORMAT_NONE; } else { /* * Can only wrap session and private keys. */ #if !ALLOW_PUB_KEY_WRAP if(UnwrappedKey.keyClass() == CSSM_KEYCLASS_PUBLIC_KEY) { CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS); } #endif /* ALLOW_PUB_KEY_WRAP */ cspValidateIntendedKeyUsage(&wrappingKey->KeyHeader, CSSM_KEYUSE_WRAP); cspVerifyKeyTimes(wrappingKey->KeyHeader); /* * make sure wrapping key type matches context */ CSSM_CONTEXT_TYPE wrapType; switch(wrappingKey->KeyHeader.KeyClass) { case CSSM_KEYCLASS_PUBLIC_KEY: case CSSM_KEYCLASS_PRIVATE_KEY: wrapType = CSSM_ALGCLASS_ASYMMETRIC; break; case CSSM_KEYCLASS_SESSION_KEY: wrapType = CSSM_ALGCLASS_SYMMETRIC; break; default: errorLog0("WrapKey: bad class of wrappingKey\n"); CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_KEY); } if(wrapType != Context.type()) { errorLog0("WrapKey: mismatch wrappingKey/contextType\n"); CssmError::throwMe(CSSMERR_CSP_INVALID_CONTEXT); } if(Context.algorithm() == CSSM_ALGID_NONE) { errorLog0("WrapKey: null wrap alg, non-null key\n"); CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM); } /* * Get optional wrap format, set default per incoming keys * Note: no such atrribute ==> 0 ==> FORMAT_NONE, which we * take to mean "use the default". */ wrapFormat = Context.getInt(CSSM_ATTRIBUTE_WRAPPED_KEY_FORMAT); if(wrapFormat == CSSM_KEYBLOB_WRAPPED_FORMAT_NONE) { /* figure out a default based on unwrapped key */ switch(UnwrappedKey.keyClass()) { case CSSM_KEYCLASS_SESSION_KEY: wrapFormat = CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS7; break; case CSSM_KEYCLASS_PUBLIC_KEY: wrapFormat = CSSM_KEYBLOB_WRAPPED_FORMAT_APPLE_CUSTOM; break; case CSSM_KEYCLASS_PRIVATE_KEY: switch(UnwrappedKey.algorithm()) { case CSSM_ALGID_FEE: wrapFormat = CSSM_KEYBLOB_WRAPPED_FORMAT_APPLE_CUSTOM; break; default: wrapFormat = CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS8; break; } break; default: /* NOT REACHED - checked above */ break; } } /* no format present or FORMAT_NONE */ } /* make sure we have a valid format here */ switch(wrapFormat) { case CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS7: if(UnwrappedKey.keyClass() != CSSM_KEYCLASS_SESSION_KEY) { /* this wrapping style only for symmetric keys */ CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS); } break; case CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS8: case CSSM_KEYBLOB_WRAPPED_FORMAT_OPENSSL: if(UnwrappedKey.keyClass() != CSSM_KEYCLASS_PRIVATE_KEY) { /* these wrapping styles only for private keys */ CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS); } break; case CSSM_KEYBLOB_WRAPPED_FORMAT_APPLE_CUSTOM: /* no restrictions (well AES can't be the wrap alg but that will * be caught later */ break; case CSSM_KEYBLOB_WRAPPED_FORMAT_OPENSSH1: /* RSA private key, reference format, only */ if(UnwrappedKey.keyClass() != CSSM_KEYCLASS_PRIVATE_KEY) { CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS); } if(UnwrappedKey.algorithm() != CSSM_ALGID_RSA) { CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM); } if(UnwrappedKey.blobType() != CSSM_KEYBLOB_REFERENCE) { CssmError::throwMe(CSSMERR_CSP_KEY_BLOB_TYPE_INCORRECT); } break; case CSSM_KEYBLOB_WRAPPED_FORMAT_NONE: if(isNullWrap) { /* only time this is OK */ break; } /* else fall thru */ default: dprintf1("KeyWrap: invalid wrapFormat (%d)\n", (int)wrapFormat); CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_WRAPPED_KEY_FORMAT); } /* get the blob to be wrappped */ CssmData rawBlob; bool allocdRawBlob = false; CSSM_KEYBLOB_FORMAT rawFormat; /* * Outgoing same as incoming unless a partial key is completed during * generateKeyBlob() */ const CssmKey::Header &unwrappedHdr = UnwrappedKey.header(); CSSM_KEYATTR_FLAGS unwrappedKeyAttrFlags = unwrappedHdr.KeyAttr; switch(UnwrappedKey.blobType()) { case CSSM_KEYBLOB_RAW: /* * Trivial case - we already have the blob. * This op - wrapping a raw key - is not supported for the * CSSM_KEYBLOB_WRAPPED_FORMAT_OPENSSH1 format since that doesn't * operate on a key blob. */ rawBlob = CssmData::overlay(UnwrappedKey.KeyData); rawFormat = UnwrappedKey.blobFormat(); break; case CSSM_KEYBLOB_REFERENCE: /* get binary key, then get blob from it */ { BinaryKey &binKey = lookupRefKey(UnwrappedKey); /* * Subsequent tests for extractability: don't trust the * caller's header; use the one in the BinaryKey. */ CSSM_KEYATTR_FLAGS keyAttr = binKey.mKeyHeader.KeyAttr; if(!(keyAttr & CSSM_KEYATTR_EXTRACTABLE)) { /* this key not extractable in any form */ CssmError::throwMe(CSSMERR_CSP_INVALID_KEYATTR_MASK); } /* * CSSM_KEYBLOB_WRAPPED_FORMAT_OPENSSH1: we're ready to roll; * all we need is the reference key. */ if(wrapFormat == CSSM_KEYBLOB_WRAPPED_FORMAT_OPENSSH1) { break; } /* * Null wrap - prevent caller from obtaining * clear bits if CSSM_KEYATTR_SENSITIVE */ if(isNullWrap && (keyAttr & CSSM_KEYATTR_SENSITIVE)) { CssmError::throwMe(CSSMERR_CSP_INVALID_KEYATTR_MASK); } /* * Special case for PKCS8 and openssl: need to get blob of a specific * algorithm-dependent format. Caller can override our * preference with a * CSSM_ATTRIBUTE_{PRIVATE,PUBLIC,SESSION}_KEY_FORMAT * context attribute. */ rawFormat = requestedKeyFormat(Context, UnwrappedKey); if(rawFormat == CSSM_KEYBLOB_RAW_FORMAT_NONE) { CSSM_ALGORITHMS keyAlg = binKey.mKeyHeader.AlgorithmId; switch(wrapFormat) { case CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS8: rawFormat = pkcs8RawKeyFormat(keyAlg); break; case CSSM_KEYBLOB_WRAPPED_FORMAT_OPENSSL: rawFormat = opensslRawKeyFormat(keyAlg); break; default: /* punt and take default for key type */ break; } } /* * DescriptiveData for encoding, currently only used for * SSH1 keys. */ if((DescriptiveData != NULL) && (DescriptiveData->Length != 0)) { binKey.descData(*DescriptiveData); } /* optional parameter-bearing key */ CssmKey *paramKey = Context.get<CssmKey>(CSSM_ATTRIBUTE_PARAM_KEY); binKey.generateKeyBlob(privAllocator, rawBlob, rawFormat, *this, paramKey, unwrappedKeyAttrFlags); } allocdRawBlob = true; // remember - we need to free break; default: errorLog0("WrapKey: bad unwrappedKey BlobType\n"); CssmError::throwMe(CSSMERR_CSP_INVALID_KEY); } /* * Prepare outgoing header. */ setKeyHeader(wrappedHdr, plugin.myGuid(), unwrappedHdr.algorithm(), // same as incoming unwrappedHdr.keyClass(), // same as incoming unwrappedKeyAttrFlags, unwrappedHdr.KeyUsage); wrappedHdr.LogicalKeySizeInBits = unwrappedHdr.LogicalKeySizeInBits; wrappedHdr.WrapAlgorithmId = Context.algorithm(); // true for null // and non-Null wrappedHdr.StartDate = unwrappedHdr.StartDate; wrappedHdr.EndDate = unwrappedHdr.EndDate; wrappedHdr.Format = wrapFormat; if(isNullWrap) { wrappedHdr.BlobType = CSSM_KEYBLOB_RAW; } else { wrappedHdr.BlobType = CSSM_KEYBLOB_WRAPPED; } /* * special cases - break out here for Apple Custom and OpenSSHv1 */ if(!isNullWrap) { switch(wrapFormat) { case CSSM_KEYBLOB_WRAPPED_FORMAT_APPLE_CUSTOM: try { WrapKeyCms(CCHandle, Context, AccessCred, UnwrappedKey, rawBlob, allocdRawBlob, DescriptiveData, WrappedKey, Privilege); } catch(...) { if(allocdRawBlob) { freeCssmData(rawBlob, privAllocator); } throw; } if(allocdRawBlob) { freeCssmData(rawBlob, privAllocator); } return; case CSSM_KEYBLOB_WRAPPED_FORMAT_OPENSSH1: { /* * 1. We don't have to worry about allocdRawBlob since this * operation only works on reference keys and we did not * obtain the raw blob from the BinaryKey. * 2. This is a redundant lookupRefKey, I know, but since * that returns a reference, it would just be too messy to have * the previous call be in the same scope as this. */ BinaryKey &binKey = lookupRefKey(UnwrappedKey); WrapKeyOpenSSH1(CCHandle, Context, AccessCred, binKey, rawBlob, allocdRawBlob, DescriptiveData, WrappedKey, Privilege); return; } default: /* proceed to encrypt blob */ break; } } /* !isNullWrap */ /* * Generate wrapped blob. Careful, we need to conditionally free * rawBlob on error. */ CssmData encryptedBlob; CssmData remData; WrappedKey.KeyData.Data = NULL; // ignore possible incoming KeyData WrappedKey.KeyData.Length = 0; try { if(isNullWrap) { /* copy raw blob to caller's wrappedKey */ copyCssmData(rawBlob, CssmData::overlay(WrappedKey.KeyData), normAllocator); wrappedHdr.Format = rawFormat; } else { /* encrypt rawBlob using caller's context, then encode to * WrappedKey.KeyData */ CSSM_SIZE bytesEncrypted; EncryptData(CCHandle, Context, &rawBlob, // ClearBufs[] 1, // ClearBufCount &encryptedBlob, // CipherBufs[], 1, // CipherBufCount, bytesEncrypted, remData, Privilege); // I'm not 100% sure about this.... assert(remData.Length == 0); encryptedBlob.Length = bytesEncrypted; WrappedKey.KeyData = encryptedBlob; wrappedHdr.BlobType = CSSM_KEYBLOB_WRAPPED; // OK to be zero or not present wrappedHdr.WrapMode = Context.getInt( CSSM_ATTRIBUTE_MODE); } } catch (...) { errorLog0("WrapKey: EncryptData() threw exception\n"); if(allocdRawBlob) { freeCssmData(rawBlob, privAllocator); } freeCssmData(remData,normAllocator); throw; } if(allocdRawBlob) { freeCssmData(rawBlob, privAllocator); } freeCssmData(remData, normAllocator); }
//src_data为转码前的数据,发送给mas和pas的。 void PasServer::HandleOnePacket(socket_t *sock, const char *data, int len) { if (data == NULL || len < (int) sizeof(Header) + (int) sizeof(Footer)) return; Header *header = (Header *) data; unsigned int access_code = ntouv32(header->access_code); string str_access_code = uitodecstr(access_code); // 针对接入码进行统计处理 _datastat.AddFlux(access_code, len); unsigned int msg_len = ntouv32(header->msg_len); if (msg_len != (unsigned int) len) { OUT_ERROR( NULL, 0, NULL, "PasServer::HandleOnePacket packet len error"); return; } // 是否需要加密处理 if (EncryptData((unsigned char *) data, len, false)) { // 将加密标志清空 header->encrypt_flag = 0; } unsigned short msg_type = ntouv16(header->msg_type); string mac_id = _proto_parse.GetMacId(data, len); const char *ip = sock->_szIp; unsigned int port = sock->_port; OUT_RECV3( ip, port, str_access_code.c_str(), "fd %d, %s", sock->_fd, _proto_parse.Decoder(data,len).c_str() ); // OUT_HEX( ip, port, str_access_code.c_str(), data, len ) ; // 处理车号对应的接入码的关系 if (!mac_id.empty()) { // 记录车号对应的接入码的关系 _corp_info_handler.update_car_info(mac_id, access_code); } if (msg_type == UP_CONNECT_REQ) { User user = _online_user.GetUserByUserId("U_" + str_access_code); UpConnectReq *out_login = (UpConnectReq *) data; OUT_RECV(ip, port, str_access_code.c_str(), "fd %d, UP_CONNECT_REQ,down-link listen port:%d", sock->_fd, ntouv16(out_login->down_link_port)); //判定是不是同一个socket发上来的UP_CONNECT_REQ。 if (!user._user_id.empty()) { //说明在线列表中已有次用户, if (user._fd == sock) { OUT_WARNING( ip, port, str_access_code.c_str(), "fd %d, sock already in user queue" , sock->_fd ); return; } else { OUT_WARNING(ip, port, str_access_code.c_str(), "fd %d, one user already login", sock->_fd); CloseSocket(sock); return; } } char szuser[128] = { 0 }; char szpwd[128] = { 0 }; sprintf(szuser, "%u", ntouv32(out_login->user_id)); strncpy(szpwd, (const char*) out_login->password, sizeof(out_login->password)); unsigned int flag = 0; unsigned char ret = _login_check->CheckUser(access_code, szuser, szpwd, ip, flag); UpConnectRsp resp; resp.header.access_code = ntouv32(access_code); resp.header.msg_len = ntouv32(sizeof(UpConnectRsp)); resp.header.msg_type = ntouv16(UP_CONNECT_RSP); resp.header.msg_seq = ntouv32(_proto_parse.get_next_seq()); resp.verify_code = ntouv32(_verify_code); resp.result = ret; switch (ret) { case 0: OUT_INFO(ip, port, str_access_code.c_str(), "login check success,access_code:%d up-link ON_LINE", access_code); break; case 1: OUT_WARNING(ip, port, str_access_code.c_str(), "login check fail,ip is invalid"); break; case 2: OUT_WARNING(ip, port, str_access_code.c_str(), "login check fail,%d accesscode is invalid,close it", access_code); break; case 3: OUT_WARNING(ip, port, str_access_code.c_str(), "login check fail,user_name:%s is invalid,close it", szuser); break; case 4: OUT_WARNING(ip, port, str_access_code.c_str(), "login check fail,user_password:%s is invalid,close it", szpwd); break; default: OUT_WARNING(ip, port, str_access_code.c_str(), "login check fail,other error,close it"); break; } // 对于登陆的连接的响应处理 if (SendCrcData(sock, (const char*) &resp, sizeof(resp))) OUT_SEND(ip,port,str_access_code.c_str(),"UP_CONNECT_RSP"); else OUT_ERROR(ip,port,str_access_code.c_str(),"UP_CONNECT_RSP"); // 如果用户认证不通过则直接关闭连接处理 if (ret != 0) { OUT_WARNING( ip, port, str_access_code.c_str(), "result %d, close socket user fd %d", ret , sock->_fd ); CloseSocket(sock); return; } //睡眠一毫秒等待数据发送出去。 user._access_code = access_code; user._user_name = szuser; user._user_id = "U_" + str_access_code; //表明是上行链路 user._login_time = time(0); user._msg_seq = flag; // 处理地市级跨域数据的处理 user._socket_type = User::TcpClient; user._fd = sock; user._ip = ip; user._port = port; user._last_active_time = time(0); unsigned short down_link_port = ntouv16( out_login->down_link_port ); char szdownip[64] = { 0 }; strncpy(szdownip, (char*) out_login->down_link_ip, sizeof(out_login->down_link_ip)); OUT_CONN( ip, port, str_access_code.c_str() , "fd %d, down connection down ip %s , down port %d", sock->_fd, szdownip, down_link_port ); if (ret == 0) { user._user_state = User::ON_LINE; User down_user = _online_user.GetUserByUserId( "D_" + str_access_code); if (!down_user._user_id.empty()) { // 修正从链接切换地址的BUG if (down_user._fd != NULL) { // 如果已建立连接则关闭 CloseSocket(down_user._fd); } } if (down_link_port > 0 && check_addr(szdownip)) { //说明下行链路还没有建立起来。 down_user._user_id = "D_" + str_access_code; down_user._access_code = access_code; down_user._user_name = szuser; down_user._login_time = time(0); down_user._socket_type = User::TcpConnClient; down_user._fd = NULL; down_user._user_state = User::OFF_LINE; down_user._ip = szdownip; down_user._port = down_link_port; down_user._last_active_time = time(0); down_user._msg_seq = flag; //下行链路只重连3次。重连三次连不上时就将这个user erase掉。 down_user._connect_info.keep_alive = ReConnTimes; down_user._connect_info.last_reconnect_time = 0; down_user._connect_info.timeval = 10; down_user._connect_info.reconnect_times = 3; if (!_online_user.AddUser(down_user._user_id, down_user)) { // 如果已存在则直接替换原来的会话 _online_user.SetUser(down_user._user_id, down_user); } } // 只登陆成功才添加到用户队列中 _online_user.AddUser(user._user_id, user); } else user._user_state = User::OFF_LINE; user._last_active_time = time(0); _online_user.SetUser(user._user_id, user); return; } User user = _online_user.GetUserBySocket(sock); if (user._user_id.empty()) { OUT_ERROR(ip, port, str_access_code.c_str(), "fd %d, msg type %04x, user havn't login,close it", sock->_fd, msg_type); CloseSocket(sock); return; } //未登录成功数据上来做单独处理,处理策略 if (msg_type == UP_DISCONNECT_REQ) { OUT_RECV(ip, port, user._user_id.c_str(), "UP_DISCONNECT_REQ"); // 发送从链路注销请求 DownDisconnectReq req; req.header.msg_type = ntouv16(DOWN_DISCONNECT_REQ); req.header.msg_len = ntouv32(sizeof(DownDisconnectReq)); req.header.msg_seq = ntouv32(_proto_parse.get_next_seq()); req.header.access_code = header->access_code; req.verify_code = ntouv32(_verify_code); char buf[200]; sprintf(buf, "D_%u", user._access_code); // 取从链路fd User sub_user = _online_user.GetUserByUserId(buf); if (!sub_user._user_id.empty()) { if (SendCrcData(sub_user._fd, (const char*) &req, sizeof(req))) { OUT_SEND(sub_user._ip.c_str(), sub_user._port, user._user_id.c_str(), "DOWN_DISCONNECT_REQ"); } else OUT_ERROR(sub_user._ip.c_str(),sub_user._port,user._user_id.c_str(),"DOWN_DISCONNECT_REQ"); } UpDisconnectRsp resp; resp.header.msg_seq = ntouv32(_proto_parse.get_next_seq()); resp.header.access_code = header->access_code; if (SendCrcData(sock, (const char*) &resp, sizeof(resp))) OUT_SEND(ip, port, user._user_id.c_str(), "UP_DISCONNECT_RSP"); else OUT_ERROR(ip,port,user._user_id.c_str(),"UP_DISCONNECT_RSP"); } else if (msg_type == UP_LINKTEST_REQ) { OUT_RECV(ip, port, user._user_id.c_str(), "UP_LINKTEST_REQ"); UpLinkTestRsp resp; resp.header.access_code = header->access_code; resp.header.msg_seq = ntouv32(_proto_parse.get_next_seq()); if (SendCrcData(sock, (const char*) &resp, sizeof(resp))) OUT_SEND(ip, port, user._user_id.c_str(), "UP_LINKTEST_RSP"); else OUT_ERROR(ip,port,user._user_id.c_str(),"UP_LINKTEST_RSP"); } else if (msg_type == UP_CLOSELINK_INFORM) { // 不需要处理,由定时处理流程解决 OUT_RECV(ip, port, user._user_id.c_str(), "fd %d, UP_CLOSELINK_INFORM", sock->_fd); char buf[200] = { 0 }; sprintf(buf, "U_%u", user._access_code); // 取主链路fd User main_user = _online_user.GetUserByUserId(buf); if (!main_user._user_id.empty()) { { DownDisconnectInform req; req.header.access_code = ntouv32(user._access_code); req.header.msg_len = ntouv32(sizeof(DownDisconnectInform)); req.header.msg_type = ntouv16(DOWN_DISCONNECT_INFORM); req.header.msg_seq = ntouv32(_proto_parse.get_next_seq()); if (SendCrcData(main_user._fd, (const char*) &req, sizeof(req))) OUT_SEND(ip, port, user._user_id.c_str(), "fd %d, DOWN_DISCONNECT_INFORM", sock->_fd); else OUT_ERROR(ip, port, user._user_id.c_str(), "fd %d, DOWN_DISCONNECT_INFORM", sock->_fd); } { DownCloselinkInform req; req.header.access_code = ntouv32(user._access_code); req.header.msg_len = ntouv32(sizeof(DownCloselinkInform)); req.header.msg_type = ntouv16(DOWN_CLOSELINK_INFORM); req.header.msg_seq = ntouv32(_proto_parse.get_next_seq()); if (SendCrcData(main_user._fd, (const char*) &req, sizeof(req))) OUT_SEND(ip, port, user._user_id.c_str(), "fd %d, DOWN_CLOSELINK_INFORM", sock->_fd); else OUT_ERROR(ip, port, user._user_id.c_str(), "fd %d, DOWN_CLOSELINK_INFORM", sock->_fd); } main_user._last_active_time = time(0); _online_user.SetUser(main_user._user_id, main_user); user._user_state = User::OFF_LINE; } } else if (msg_type == UP_DISCONNECT_INFORM) { // 不需要处理,由定时处理流程解决 OUT_RECV(ip, port, user._user_id.c_str(), "fd %d, UP_DISCONNECT_INFORM", sock->_fd); } else if (msg_type == UP_CLOSELINK_INFORM) { // 不需要处理,由定时处理流程解决 OUT_RECV(ip, port, user._user_id.c_str(), "fd %d, UP_CLOSELINK_INFORM", sock->_fd); // 取主链路fd { DownDisconnectInform req; req.header.msg_len = ntouv32( sizeof(req) ); req.header.msg_type = ntouv16( DOWN_DISCONNECT_INFORM ); req.header.access_code = ntouv32(user._access_code); req.header.msg_seq = ntouv32(_proto_parse.get_next_seq()); if (SendCrcData(sock, (const char*) &req, sizeof(req))) OUT_SEND(ip, port, user._user_id.c_str(), "fd %d, DOWN_DISCONNECT_INFORM", sock->_fd); else OUT_ERROR(ip, port, user._user_id.c_str(), "fd %d, DOWN_DISCONNECT_INFORM", sock->_fd); } { DownCloselinkInform req; req.header.msg_len = ntouv32( sizeof(req) ); req.header.msg_type = ntouv16( DOWN_CLOSELINK_INFORM ); req.header.access_code = ntouv32(user._access_code); req.header.msg_seq = ntouv32(_proto_parse.get_next_seq()); if (SendCrcData(sock, (const char*) &req, sizeof(req))) OUT_SEND(ip, port, user._user_id.c_str(), "fd %d, DOWN_CLOSELINK_INFORM", sock->_fd); else OUT_ERROR(ip, port, user._user_id.c_str(), "fd %d, DOWN_CLOSELINK_INFORM", sock->_fd); } } else if (msg_type == UP_DISCONNECT_INFORM) { // 不需要处理,由定时处理流程解决 OUT_RECV(ip, port, user._user_id.c_str(), "fd %d, UP_DISCONNECT_INFORM", sock->_fd); } else if (msg_type == DOWN_CONNECT_RSP) { DownConnectRsp *_down_resp = (DownConnectRsp*) data; if (_down_resp->result == 0) { OUT_RECV(ip, port, user._user_id.c_str(), "fd %d, DOWN_CONNECT_RSP,Down-Link ON_LINE", sock->_fd); user._connect_info.reconnect_times = 3; user._user_state = User::ON_LINE; } else { OUT_RECV(ip, port, user._user_id.c_str(), "fd %d, DOWN_CONNECT_RSP,connect fail,result=%d", sock->_fd, _down_resp->result); } } else if (msg_type == DOWN_LINKTEST_RSP) { // 这里处理有些运营商回复下行链路心跳时使用上行来回应 OUT_RECV(ip, port, user._user_id.c_str(), get_type(msg_type)); /** if ( user._user_id.at(0) == 'U' ) { User down = _online_user.GetUserByUserId("D_" + str_access_code); if ( ! down._user_id.empty() ) { down._last_active_time = time(0) ; _online_user.SetUser( down._user_id, down ) ; } }*/ } else if (msg_type == DOWN_DISCONNECT_RSP) { OUT_RECV(ip, port, user._user_id.c_str(), get_type(msg_type)); // user._user_state = User::OFF_LINE; if (user._user_state == User::ON_LINE && user._fd != NULL) { CloseSocket(user._fd); } } else if (msg_type == DOWN_DISCONNECT_INFORM) { //不管它,由定时线程来完成。 OUT_RECV(ip, port, user._user_id.c_str(), get_type(msg_type)); } else if (msg_type == DOWN_DISCONNECT_RSP) { OUT_RECV(ip, port, user._user_id.c_str(), get_type(msg_type)); user._user_state = User::OFF_LINE; } else { if (msg_type == UP_EXG_MSG) { ExgMsgHeader *msg_header = (ExgMsgHeader*) (data + sizeof(Header)); if (msg_header->vehicle_no[0] == (char) 0) { OUT_ERROR(ip, port, user._user_id.c_str(), "vehicle is null"); return; } unsigned short data_type = ntouv16( msg_header->data_type ); switch (data_type) { case UP_EXG_MSG_REAL_LOCATION: { OUT_RECV3(ip, port, user._user_id.c_str(), "UP_EXG_MSG_REAL_LOCATION:%s", msg_header->vehicle_no); CorpInfoHandle::_CorpInfo info = _corp_info_handler.update_corp_map(access_code, 1, _max_send_num); if (info.send_num < 1) { Header * pHeader = (Header *) (data); //给运营商回复DOWN_TOTAL_RECV_BACK_MSG DownTotalRecvBackMsg resp; resp.header.access_code = pHeader->access_code; resp.DynamicInfoTotal = ntouv32(_max_send_num); resp.start_time = ntouv64(info.send_time); resp.end_time = ntouv64(time(0)); resp.header.msg_seq = ntouv32(_proto_parse.get_next_seq()); char buf[200] = { 0 }; sprintf(buf, "D_%u", user._access_code); User sub_user = _online_user.GetUserByUserId(buf); socket_t *isock = sock; if (!(sub_user._user_id.empty() || sub_user._user_state != User::ON_LINE)) isock = sub_user._fd; if (SendCrcData(isock, (const char*) &resp, sizeof(resp))) { OUT_SEND( ip, port, user._user_id.c_str(), "DOWN_TOTAL_RECV_BACK_MSG" ); } else { OUT_ERROR( ip, port, user._user_id.c_str(), "DOWN_TOTAL_RECV_BACK_MSG" ); } } } break; case UP_EXG_MSG_HISTORY_LOCATION: { OUT_RECV3(ip, port, user._user_id.c_str(), "UP_EXG_MSG_HISTORY_LOCATION:%s", msg_header->vehicle_no); UpExgMsgHistoryLocation * pReq = (UpExgMsgHistoryLocation *) (data); unsigned int num = pReq->gnss_cnt; CorpInfoHandle::_CorpInfo info = _corp_info_handler.update_corp_map(access_code, num, _max_send_num); if (info.send_num < num) { //给运营商回复DOWN_TOTAL_RECV_BACK_MSG DownTotalRecvBackMsg resp; resp.header.access_code = pReq->header.header.access_code; resp.DynamicInfoTotal = ntouv32(_max_send_num); resp.start_time = ntouv64(info.send_time); resp.end_time = ntouv64(time(0)); resp.header.msg_seq = ntouv32(_proto_parse.get_next_seq()); char buf[200]; sprintf(buf, "D_%u", user._access_code); User sub_user = _online_user.GetUserByUserId(buf); socket_t *isock = sock; if (!(sub_user._user_id.empty() || sub_user._user_state != User::ON_LINE)) isock = sub_user._fd; if (SendCrcData(isock, (const char*) &resp, sizeof(resp))) { OUT_SEND( ip, port, user._user_id.c_str(), "DOWN_TOTAL_RECV_BACK_MSG" ); } else { OUT_ERROR( ip, port, user._user_id.c_str(), "DOWN_TOTAL_RECV_BACK_MSG" ); } } } break; case UP_EXG_MSG_APPLY_HISGNSSDATA_REQ: // 补报数据请求 { if (len < (int) sizeof(UpExgApplyHisGnssDataReq)) { OUT_ERROR( ip, port, user._user_id.c_str(), "UP_EXG_MSG_APPLY_HISGNSSDATA_REQ data length errro, len %d" , len ); return; } UpExgApplyHisGnssDataReq *req = (UpExgApplyHisGnssDataReq *) data; DownExgMsgApplyHisgnssdataAck resp; resp.header.msg_len = ntouv32( sizeof(DownExgMsgApplyHisgnssdataAck) ); resp.header.access_code = req->header.access_code; resp.header.msg_type = ntouv16( DOWN_EXG_MSG ); memcpy(resp.exg_msg_header.vehicle_no, req->exg_msg_header.vehicle_no, sizeof(resp.exg_msg_header.vehicle_no)); resp.exg_msg_header.vehicle_color = req->exg_msg_header.vehicle_color; resp.exg_msg_header.data_type = ntouv16( DOWN_EXG_MSG_APPLY_HISGNSSDATA_ACK ); resp.exg_msg_header.data_length = ntouv32( sizeof(char) ); resp.result = 0x00; // 补报数据自动应答 SendCrcData(sock, (const char *) &resp, sizeof(resp)); // 设置用户为在线处理开始补报数据 _filecache.Online(user._access_code); } break; default: OUT_RECV(ip, port, user._user_id.c_str(), get_type(data_type)); break; } } else if (msg_type == UP_PLATFORM_MSG) { } else if (msg_type == UP_CTRL_MSG) { } else if (msg_type == UP_BASE_MSG) { } else if (msg_type == UP_WARN_MSG) { } else { OUT_ERROR(ip, port, user._user_id.c_str(), "msg_type=%04x,received an invalid message,len %d", msg_type, len); OUT_HEX( ip, port, user._user_id.c_str(), data, len ); } _pEnv->GetMasServer()->HandleMasUpData((const char *) data, len); } user._last_active_time = time(0); _online_user.SetUser(user._user_id, user); }
STDMETHODIMP_(UInt32) CDecoder::Filter(Byte *data, UInt32 size) { _hmac.Update(data, size); EncryptData(data, size); return size; }
UPK_STATUS NitroPlus:: Pack( PCWSTR InputPath, PCWSTR OutputFile /* = NULL */, PLARGE_INTEGER PackedFiles /* = NULL */, ULONG Flags /* = 0 */ ) { UNREFERENCED_PARAMETER(OutputFile); UNREFERENCED_PARAMETER(Flags); ULONG PathLength, Length, Hash, Offset; ULONG Size, CompressedSize, FileBufferSize, CompresseBufferSize; WCHAR FilePath[MAX_NTPATH]; PVOID NpaEntryBase, FileBuffer, CompresseBuffer; PBYTE NpaEntryBuffer; PWSTR FileName; NTSTATUS Status; LARGE_INTEGER FileCount, PackedFileCount; NITRO_PLUS_ENTRY *BaseEntry, *Entry; NITRO_PLUS_NPA_HEADER Header; NITRO_PLUS_NPA_ETNRY *Info; NtFileDisk File; if (PackedFiles == NULL) PackedFiles = &PackedFileCount; PackedFiles->QuadPart = 0; if (!EnumDirectoryFiles( (PVOID *)&BaseEntry, L"*.*", sizeof(*BaseEntry), InputPath, &FileCount, (EnumDirectoryFilesCallBackRoutine)QueryFileList, 0, EDF_SUBDIR) ) { return STATUS_UNSUCCESSFUL; } FileBufferSize = 0; CompresseBufferSize = 0; FileBuffer = NULL; CompresseBuffer = NULL; *(PULONG)&Header.Signature = NPA_HEADER_MAGIC; Header.Version = NPA_GCLX_VERSION; Header.EntryCount = FileCount.LowPart; Header.FileCount = FileCount.LowPart; Header.DirectoryCount = 0; Header.IsCompressed = TRUE; Header.IsEncrypted = TRUE; RtlRandom(&Header.Hash[0]); RtlRandom(&Header.Hash[1]); PathLength = StrLengthW(InputPath); if (OutputFile != NULL) { Status = m_File.Create(OutputFile); } else { FileName = FilePath + PathLength; CopyMemory(FilePath, InputPath, PathLength * sizeof(*FilePath)); if (FileName[-1] == '\\') --FileName; *(PULONG64)FileName = TAG4W('.npa'); FileName[4] = 0; Status = m_File.Create(FilePath); } if (!NT_SUCCESS(Status)) goto RETURN_POINT; PathLength += InputPath[PathLength - 1] != '\\'; NpaEntryBase = AllocateMemory(sizeof(*BaseEntry) * FileCount.LowPart); if (NpaEntryBase == NULL) { Status = STATUS_INSUFFICIENT_RESOURCES; goto RETURN_POINT; } NpaEntryBuffer = (PBYTE)NpaEntryBase; Entry = BaseEntry; for (ULONG Index = 0, Count = FileCount.LowPart; Count; ++Index, --Count) { Length = StrLengthW(Entry->FileName) - PathLength; Length = WideCharToMultiByte( CP_SHIFTJIS, 0, Entry->FileName + PathLength, Length, (PSTR)NpaEntryBuffer + 4, INT_MAX, NULL, NULL ); // Nt_UnicodeToAnsi((PSTR)NpaEntryBuffer + 4, INT_MAX, Entry->FileName + PathLength, Length, &Length); *(PULONG)NpaEntryBuffer = Length; NpaEntryBuffer += 4; Entry->DecryptLength = Length; Entry->Seed = HashBuffer(NpaEntryBuffer, Length); EncryptName(NpaEntryBuffer, Length, Index, &Header); NpaEntryBuffer += Length; NpaEntryBuffer += sizeof(*Info); ++Entry; } Header.EntrySize = PtrOffset(NpaEntryBuffer, NpaEntryBase); Hash = Header.Hash[0] * Header.Hash[1]; NpaEntryBuffer = (PBYTE)NpaEntryBase; Entry = BaseEntry; Offset = 0; m_File.Seek(Header.EntrySize + sizeof(Header), FILE_BEGIN); for (ULONG Index = 0, Count = FileCount.LowPart; Count; ++Index, --Count) { Status = File.Open(Entry->FileName); if (!NT_SUCCESS(Status)) break; Size = File.GetSize32(); if (FileBufferSize < Size) { FileBufferSize = Size; FileBuffer = ReAllocateMemory(FileBuffer, FileBufferSize); if (FileBuffer == NULL) { Status = STATUS_INSUFFICIENT_RESOURCES; break; } } Status = File.Read(FileBuffer, Size); if (!NT_SUCCESS(Status)) break; CompressedSize = Size * 4; if (CompresseBufferSize < CompressedSize) { CompresseBufferSize = CompressedSize; CompresseBuffer = ReAllocateMemory(CompresseBuffer, CompresseBufferSize); if (CompresseBuffer == NULL) { Status = STATUS_INSUFFICIENT_RESOURCES; break; } } CompressedSize = CompresseBufferSize; Status = compress2(CompresseBuffer, &CompressedSize, FileBuffer, Size, Z_BEST_COMPRESSION); if (Status != Z_OK) { Status = STATUS_UNSUCCESSFUL; break; } EncryptData( CompresseBuffer, MY_MIN(CompressedSize, Entry->DecryptLength + 0x1000), (Hash + Entry->Seed) * Size ); NpaEntryBuffer += *(PULONG)NpaEntryBuffer + 4; Info = (NITRO_PLUS_NPA_ETNRY *)NpaEntryBuffer; NpaEntryBuffer += sizeof(*Info); Info->FileType = NP_FILE_TYPE_FILE; Info->CompressedSize = CompressedSize; Info->Offset = Offset; Info->OriginalSize = Size; Info->DirectoryIndex = 0; Status = m_File.Write(CompresseBuffer, CompressedSize); if (!NT_SUCCESS(Status)) break; Offset += CompressedSize; ++Entry; } if (!NT_SUCCESS(Status)) goto RETURN_POINT; m_File.Seek(0, FILE_BEGIN); Status = m_File.Write(&Header, sizeof(Header)); if (!NT_SUCCESS(Status)) goto RETURN_POINT; Status = m_File.Write(NpaEntryBase, Header.EntrySize); if (!NT_SUCCESS(Status)) goto RETURN_POINT; PackedFiles->QuadPart = FileCount.QuadPart; RETURN_POINT: FreeMemory(FileBuffer); EnumDirectoryFilesFree(BaseEntry); return Status; }
void WardenWin::RequestData() { sLog->outWarden("Request data"); // If all checks were done, fill the todo list again if (_memChecksTodo.empty()) _memChecksTodo.assign(sWardenCheckMgr->MemChecksIdPool.begin(), sWardenCheckMgr->MemChecksIdPool.end()); if (_otherChecksTodo.empty()) _otherChecksTodo.assign(sWardenCheckMgr->OtherChecksIdPool.begin(), sWardenCheckMgr->OtherChecksIdPool.end()); _serverTicks = getMSTime(); uint32 id; uint8 type; WardenCheck* wd; _currentChecks.clear(); // Build check request (3 mem checks + 7 other checks) for (int i = 0; i < 3; ++i) { // If todo list is done break loop (will be filled on next Update() run) if (_memChecksTodo.empty()) break; // Get check id from the end and remove it from todo id = _memChecksTodo.back(); _memChecksTodo.pop_back(); // Add the id to the list sent in this cycle _currentChecks.push_back(id); } ByteBuffer buff; buff << uint8(WARDEN_SMSG_CHEAT_CHECKS_REQUEST); for (int i = 0; i < 7; ++i) { // If todo list is done break loop (will be filled on next Update() run) if (_otherChecksTodo.empty()) break; // Get check id from the end and remove it from todo id = _otherChecksTodo.back(); _otherChecksTodo.pop_back(); // Add the id to the list sent in this cycle _currentChecks.push_back(id); wd = sWardenCheckMgr->GetWardenDataById(id); // Skip if checks aren't in the stores anymore (e.g. by database edit & reload during runtime) if (!wd) continue; switch (wd->Type) { case MPQ_CHECK: case LUA_STR_CHECK: case DRIVER_CHECK: buff << uint8(wd->Str.size()); buff.append(wd->Str.c_str(), wd->Str.size()); break; default: break; } } uint8 xorByte = _inputKey[0]; buff << uint8(0x00); buff << uint8(TIMING_CHECK ^ xorByte); // check TIMING_CHECK uint8 index = 1; for (std::list<uint32>::iterator itr = _currentChecks.begin(); itr != _currentChecks.end(); ++itr) { // Skip if checks aren't in the stores anymore (e.g. by database edit & reload during runtime) wd = sWardenCheckMgr->GetWardenDataById(*itr); if (!wd) continue; type = wd->Type; buff << uint8(type ^ xorByte); switch (type) { case MEM_CHECK: { buff << uint8(0x00); buff << uint32(wd->Address); buff << uint8(wd->Length); break; } case PAGE_CHECK_A: case PAGE_CHECK_B: { buff.append(wd->Data.AsByteArray(0, false), wd->Data.GetNumBytes()); buff << uint32(wd->Address); buff << uint8(wd->Length); break; } case MPQ_CHECK: case LUA_STR_CHECK: { buff << uint8(index++); break; } case DRIVER_CHECK: { buff.append(wd->Data.AsByteArray(0, false), wd->Data.GetNumBytes()); buff << uint8(index++); break; } case MODULE_CHECK: { uint32 seed = static_cast<uint32>(rand32()); buff << uint32(seed); HmacHash hmac(4, (uint8*)&seed); hmac.UpdateData(wd->Str); hmac.Finalize(); buff.append(hmac.GetDigest(), hmac.GetLength()); break; } /*case PROC_CHECK: { buff.append(wd->i.AsByteArray(0, false), wd->i.GetNumBytes()); buff << uint8(index++); buff << uint8(index++); buff << uint32(wd->Address); buff << uint8(wd->Length); break; }*/ default: break; // Should never happen } } buff << uint8(xorByte); buff.hexlike(); // Encrypt with warden RC4 key. EncryptData(const_cast<uint8*>(buff.contents()), buff.size()); WorldPacket pkt(SMSG_WARDEN_DATA, buff.size()); pkt.append(buff); _session->SendPacket(&pkt); // DEBUG CODE: Save time the request was sent for later comparison _requestSent = time(NULL); _dataSent = true; std::stringstream stream; stream << "Sent check id's: "; for (std::list<uint32>::iterator itr = _currentChecks.begin(); itr != _currentChecks.end(); ++itr) stream << *itr << " "; sLog->outWarden(stream.str().c_str()); }
void WardenWin::RequestData() { sLog->outDebug(LOG_FILTER_WARDEN, "Request data"); // If all checks were done, fill the todo list again if (_memChecksTodo.empty()) _memChecksTodo.assign(sWardenCheckMgr->MemChecksIdPool.begin(), sWardenCheckMgr->MemChecksIdPool.end()); if (_otherChecksTodo.empty()) _otherChecksTodo.assign(sWardenCheckMgr->OtherChecksIdPool.begin(), sWardenCheckMgr->OtherChecksIdPool.end()); _serverTicks = getMSTime(); uint16 id; uint8 type; WardenCheck* wd; _currentChecks.clear(); // Build check request for (uint32 i = 0; i < sWorld->getIntConfig(CONFIG_WARDEN_NUM_MEM_CHECKS); ++i) { // If todo list is done break loop (will be filled on next Update() run) if (_memChecksTodo.empty()) break; // Get check id from the end and remove it from todo id = _memChecksTodo.back(); _memChecksTodo.pop_back(); // Add the id to the list sent in this cycle _currentChecks.push_back(id); } ByteBuffer buff; buff << uint8(WARDEN_SMSG_CHEAT_CHECKS_REQUEST); ACE_READ_GUARD(ACE_RW_Mutex, g, sWardenCheckMgr->_checkStoreLock); for (uint32 i = 0; i < sWorld->getIntConfig(CONFIG_WARDEN_NUM_OTHER_CHECKS); ++i) { // If todo list is done break loop (will be filled on next Update() run) if (_otherChecksTodo.empty()) break; // Get check id from the end and remove it from todo id = _otherChecksTodo.back(); _otherChecksTodo.pop_back(); // Add the id to the list sent in this cycle _currentChecks.push_back(id); wd = sWardenCheckMgr->GetWardenDataById(id); switch (wd->Type) { case MPQ_CHECK: case LUA_STR_CHECK: case DRIVER_CHECK: buff << uint8(wd->Str.size()); buff.append(wd->Str.c_str(), wd->Str.size()); break; default: break; } } uint8 xorByte = _inputKey[0]; // Add TIMING_CHECK buff << uint8(0x00); buff << uint8(TIMING_CHECK ^ xorByte); uint8 index = 1; for (std::list<uint16>::iterator itr = _currentChecks.begin(); itr != _currentChecks.end(); ++itr) { wd = sWardenCheckMgr->GetWardenDataById(*itr); type = wd->Type; buff << uint8(type ^ xorByte); switch (type) { case MEM_CHECK: { buff << uint8(0x00); buff << uint32(wd->Address); buff << uint8(wd->Length); break; } case PAGE_CHECK_A: case PAGE_CHECK_B: { buff.append(wd->Data.AsByteArray(0, false), wd->Data.GetNumBytes()); buff << uint32(wd->Address); buff << uint8(wd->Length); break; } case MPQ_CHECK: case LUA_STR_CHECK: { buff << uint8(index++); break; } case DRIVER_CHECK: { buff.append(wd->Data.AsByteArray(0, false), wd->Data.GetNumBytes()); buff << uint8(index++); break; } case MODULE_CHECK: { uint32 seed = static_cast<uint32>(rand32()); buff << uint32(seed); HmacHash hmac(4, (uint8*)&seed); hmac.UpdateData(wd->Str); hmac.Finalize(); buff.append(hmac.GetDigest(), hmac.GetLength()); break; } /*case PROC_CHECK: { buff.append(wd->i.AsByteArray(0, false), wd->i.GetNumBytes()); buff << uint8(index++); buff << uint8(index++); buff << uint32(wd->Address); buff << uint8(wd->Length); break; }*/ default: break; // Should never happen } } buff << uint8(xorByte); buff.hexlike(); // Encrypt with warden RC4 key EncryptData(buff.contents(), buff.size()); WorldPacket pkt(SMSG_WARDEN_DATA, buff.size()); pkt.append(buff); _session->SendPacket(&pkt); _dataSent = true; std::stringstream stream; stream << "Sent check id's: "; for (std::list<uint16>::iterator itr = _currentChecks.begin(); itr != _currentChecks.end(); ++itr) stream << *itr << " "; sLog->outDebug(LOG_FILTER_WARDEN, "%s", stream.str().c_str()); }
void WardenWin::RequestData() { sLog.outDebug("Request data"); if (MemCheck.empty()) MemCheck.assign(WardenDataStorage.MemCheckIds.begin(), WardenDataStorage.MemCheckIds.end()); ServerTicks = getMSTime(); uint32 id; uint8 type; WardenData* wd; SendDataId.clear(); for (uint32 i = 0; i < sWorld.getConfig(CONFIG_WARDEN_NUM_CHECKS); ++i) // for now include 3 MEM_CHECK's { if (MemCheck.empty()) break; id = MemCheck.back(); SendDataId.push_back(id); MemCheck.pop_back(); } ByteBuffer buff; buff << uint8(WARDEN_SMSG_CHEAT_CHECKS_REQUEST); // This doesn't apply for 2.4.3 //for (int i = 0; i < 5; ++i) // for now include 5 random checks //{ // id = irand(1, maxid - 1); // wd = WardenDataStorage.GetWardenDataById(id); // SendDataId.push_back(id); // switch (wd->Type) // { // case MPQ_CHECK: // case LUA_STR_CHECK: // case DRIVER_CHECK: // buff << uint8(wd->str.size()); // buff.append(wd->str.c_str(), wd->str.size()); // break; // default: // break; // } //} uint8 xorByte = InputKey[0]; buff << uint8(0x00); buff << uint8(TIMING_CHECK ^ xorByte); // check TIMING_CHECK uint8 index = 1; for (std::vector<uint32>::iterator itr = SendDataId.begin(); itr != SendDataId.end(); ++itr) { wd = WardenDataStorage.GetWardenDataById(*itr); type = wd->Type; buff << uint8(type ^ xorByte); switch (type) { case MEM_CHECK: { buff << uint8(0x00); buff << uint32(wd->Address); buff << uint8(wd->Length); break; } case PAGE_CHECK_A: case PAGE_CHECK_B: { buff.append(wd->i.AsByteArray(0), wd->i.GetNumBytes()); buff << uint32(wd->Address); buff << uint8(wd->Length); break; } case MPQ_CHECK: case LUA_STR_CHECK: { buff << uint8(index++); break; } case DRIVER_CHECK: { buff.append(wd->i.AsByteArray(0), wd->i.GetNumBytes()); buff << uint8(index++); break; } case MODULE_CHECK: { uint32 seed = rand32(); buff << uint32(seed); HmacHash hmac(4, (uint8*)&seed); hmac.UpdateData(wd->str); hmac.Finalize(); buff.append(hmac.GetDigest(), hmac.GetLength()); break; } /*case PROC_CHECK: { buff.append(wd->i.AsByteArray(0, false), wd->i.GetNumBytes()); buff << uint8(index++); buff << uint8(index++); buff << uint32(wd->Address); buff << uint8(wd->Length); break; }*/ default: break; // should never happens } } buff << uint8(xorByte); buff.hexlike(); // Encrypt with warden RC4 key. EncryptData(const_cast<uint8*>(buff.contents()), buff.size()); WorldPacket pkt(SMSG_WARDEN_DATA, buff.size()); pkt.append(buff); Client->SendPacket(&pkt); m_WardenDataSent = true; std::stringstream stream; stream << "Sent check id's: "; for (std::vector<uint32>::iterator itr = SendDataId.begin(); itr != SendDataId.end(); ++itr) stream << *itr << " "; sLog.outDebug("%s", stream.str().c_str()); }
// 处理809协议的数据 void CPccServer::HandleOutData( socket_t *sock, const char *data, int len ) { // 处理809 if (data == NULL || len < (int)sizeof(Header)) { OUT_HEX( sock->_szIp, sock->_port, "PccServer" , (const char *)data, len ) ; return; } Header *header = (Header *) data; unsigned int access_code = ntouv32(header->access_code); string str_access_code = uitodecstr(access_code); unsigned short msg_type = ntouv16(header->msg_type); const char *ip = sock->_szIp ; unsigned int port = sock->_port ; // 处理加解密数据 EncryptData( (unsigned char*) data , len , false ) ; OUT_RECV( ip, port, str_access_code.c_str(), "%s,from pccserver", _proto_parse.Decoder(data,len).c_str() ) ; OUT_HEX( ip, port, str_access_code.c_str(), data, len ) ; if (msg_type == DOWN_CONNECT_REQ){ // 连接请求 User user = _online_user.GetUserByUserId(str_access_code); if ( user._fd != NULL && user._fd != sock ) { CloseSocket(user._fd) ; } DownConnectReq* req = (DownConnectReq*) data; user._fd = sock; user._ip = ip ; user._port = port ; user._login_time = time(0); user._msg_seq = 0; user._user_id = str_access_code ; user._access_code = access_code ; user._user_state = User::ON_LINE; //一定要设置这个,因为在下行链路还没有建立起来的时候,第一次登录的时候上的那个是不能执行的。 user._last_active_time = time(0); // 添加用户 if ( ! _online_user.AddUser( str_access_code, user ) ){ _online_user.SetUser( str_access_code, user ) ; } DownConnectRsp resp; resp.header.msg_seq = ntouv16(_proto_parse.get_next_seq()); resp.header.access_code = req->header.access_code; resp.result = 0; if ( SendCrcData( sock,(const char *)&resp,sizeof(resp) ) ) { OUT_INFO(ip,port,str_access_code.c_str(),"DOWN_CONNECT_REQ: send DOWN_CONNECT_RSP downlink is online"); } else { OUT_ERROR(ip,port,str_access_code.c_str(),"DOWN_CONNECT_REQ: send DOWN_CONNECT_RSP downlink is online failed"); } // 更新连接状态 _pEnv->GetPasClient()->UpdateSlaveConn( access_code , CONN_CONNECT ) ; return; } User user = _online_user.GetUserBySocket( sock ); if (user._user_id.empty()){ OUT_ERROR(ip,port,str_access_code.c_str(),"msg type %04x, user havn't login,close it %d", msg_type, sock->_fd ); CloseSocket( sock ); return; } // 如果为心跳 if (msg_type == DOWN_LINKTEST_REQ){ OUT_RECV(ip,port,user._user_id.c_str(),"DOWN_LINKTEST_REQ"); DownLinkTestRsp resp; resp.header.access_code = header->access_code; resp.header.msg_seq = ntouv32(_proto_parse.get_next_seq()); if ( SendCrcData( sock, (const char*) &resp, sizeof(resp) ) ) OUT_SEND(ip,port,user._user_id.c_str(),"DOWN_LINKTEST_RSP"); else OUT_ERROR(ip,port,user._user_id.c_str(),"DOWN_LINKTEST_RSP") ; } else if (msg_type == DOWN_DISCONNECT_REQ ) { // 从链路注销请求 OUT_RECV(ip,port,user._user_id.c_str(),get_type(msg_type)); DownDisconnectRsp resp ; resp.header.msg_len = ntouv32( sizeof(resp) ) ; resp.header.msg_type = ntouv16( DOWN_DISCONNECT_RSP ) ; resp.header.access_code = header->access_code ; resp.header.msg_seq = ntouv32( _proto_parse.get_next_seq() ) ; if ( SendCrcData( sock, (const char*) &resp, sizeof(resp) ) ) OUT_SEND(ip,port,user._user_id.c_str(),"DOWN_DISCONNECT_RSP"); else OUT_ERROR(ip,port,user._user_id.c_str(),"DOWN_DISCONNECT_RSP") ; // 这里由主链路来主动关闭连接,置离线状态由线程自动回收链路 // user._user_state = User::OFF_LINE ; } else if (msg_type == DOWN_DISCONNECT_INFORM){ // 主链路消息 //不管它,由定时线程来完成。 OUT_RECV(ip,port,user._user_id.c_str(),get_type(msg_type)); } else if (msg_type == DOWN_CLOSELINK_INFORM ){ // 来自主链路 } else{ // 直接到CLIENT处理 _pEnv->GetPasClient()->HandlePasDownData( access_code, data, len ) ; } user._last_active_time = time(0); _online_user.SetUser(user._user_id,user); }