#include "stdafx.h" #include "AccessAuthFSM.h" #include "mod_AccessAuth.h" #include "Event.h" #include "access_basefun.h" #include #include #include "fileutil.h" #include "iniutil.h" #include "CommEntityUtil.hpp" #include "SpUtility.h" #include "comm.h" #include "PinPad_client_g.h" #include using namespace PinPad; #ifdef RVC_OS_WIN #include #include " #include "MyBase64.h" #include #include #include #include #include #include "WMIDeviceQuery.h" #include #include #include "DeviceBaseClass.h" #pragma comment(lib, "IPHLPAPI.lib") #define ALLOW_MULTI_NETWORKD_CARDS #endif // RVC_OS_WIN int HexBuf2StrBuf(PBYTE hexBuf, char** strBuf, DWORD len) { char* tmpStr = *strBuf; int count = 0; for (int i = 0; i < len; ++i) { sprintf(tmpStr + count, "%0.2X", hexBuf[i]); count += 2; } return 0; } int StrBuf2HexBuf(LPCTSTR strBuf, PBYTE* hexBuf) { int len = strlen(strBuf); if (len == 0 || len % 2 != 0) return 0; BYTE* buf = new BYTE[len / 2]; if (buf == NULL) return 0; int j = 0; for (int i = 0; i < len;) { int tmpVal; sscanf(strBuf + i, "%2X", &tmpVal); buf[j] = tmpVal; i += 2; j++; } *hexBuf = buf; return j; } CAccessAuthFSM::CAccessAuthFSM() :m_finishAccess(0), m_nAccessFailedCount(0) , m_accessAuthHost(true), m_initDeviceHost(true) , m_torelateDiffSyncTimeSecs(180) { } CAccessAuthFSM::~CAccessAuthFSM() { m_iState = FSM_STATE_EXIT; // 屏蔽退出ASSERT错误 } void CAccessAuthFSM::OnStateTrans(int iSrcState, int iDstState) { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("trans from %s to %s", GetStateName(iSrcState), GetStateName(iDstState)); } ErrorCodeEnum CAccessAuthFSM::OnInit() { LOG_FUNCTION(); AddStateHooker(this); m_finishAccess = 0; DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("Complied at: %s %s", __DATE__, __TIME__); //设置初始锁定状态,0 CSmartPointer spFunction = m_pEntity->GetFunction(); spFunction->SetSysVar("LockState", "0", true); ErrorCodeEnum Error = LoadCenterConfig(); if (Error != Error_Succeed) { LOG_TRACE("load CenterSetting.ini failed!"); } GetDiffSyncTimeFromCenterSettings(); return Error_Succeed; } ErrorCodeEnum CAccessAuthFSM::OnExit() { RemoveStateHooker(this); return Error_Succeed; } void CAccessAuthFSM::HttpsLogCallBack(const char* logtxt) { DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM).setAPI("HttpsLogCallBack")("%s", logtxt); } struct TimeSynTask : ITaskSp { CAccessAuthFSM* m_fsm; TimeSynTask(CAccessAuthFSM* fsm) :m_fsm(fsm) {} void Process() { if (m_fsm->GetmAccessAuthHost().IsNullOrEmpty()) { LogWarn(Severity_Middle, Error_Unexpect, AccessAuthorization_UserErrorCode_AccessAuth_NULL, "准入Url为空"); FSMEvent* pEvent = new FSMEvent(CAccessAuthFSM::Event_ReqTokenCancel); pEvent->param1 = AccessAuthorization_UserErrorCode_AccessAuth_NULL; m_fsm->PostEventFIFO(pEvent); CSimpleStringA strMsg(true); strMsg = CSimpleStringA::Format("准入服务地址为空,请下载集中配置或重启应用"); m_fsm->doWarnMsg(AccessAuthorization_UserErrorCode_AccessAuth_NULL, strMsg.GetData(), true); return; } CSystemStaticInfo si; m_fsm->GetEntityBase()->GetFunction()->GetSystemStaticInfo(si); CSessionkeySynReq timeSyncReq; CSessionkeySynAns timeSyncAns; timeSyncReq.terminalNo = si.strTerminalID.GetData(); timeSyncReq.curTime = CSmallDateTime::GetNow().GetTime64(); HttpClientResponseResult result; HttpClientRequestConfig config(HttpRequestMethod::POST, m_fsm->GetmAccessAuthHost().GetData(), &SpGetToken); config.SetChildUri("/api/v3/sessionkey"); SP::Module::Restful::FulfillRequestJsonBody(&config, timeSyncReq); RestfulClient client = RestfulClient::getInstance(); PROCESS_LINK_CONTEXT("LR0402502SessionKey"); if (m_fsm->containsChinese(m_fsm->GetmAccessAuthHost().GetData())) { result.statusCode = 6; m_fsm->AuthLogWarn(result, m_fsm->GetmAccessAuthHost().GetData(), "获取会话密钥"); DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("TimeSynTask Connect Failed."); FSMEvent* pEvent = new FSMEvent(CAccessAuthFSM::Event_ReqTokenCancel); pEvent->param1 = AccessAuthorization_UserErrorCode_ACS_FAIL; m_fsm->PostEventFIFO(pEvent); return; } std::string test; test = config.GetRequestUri(); config.PreDo(); client.Do(&config, &result, &nextLink); if (result.ResponseOK()) { SP::Module::Restful::CommResponseJson responseStatus; SP::Module::Restful::GetStatusFromDebranchResponse(result.content, responseStatus); if (!responseStatus.IsOperatedOK()) { m_fsm->AuthLogWarn(result, config.GetRequestUri(), "获取会话密钥"); return; } SP::Module::Restful::ExtractDataFromDebranchResponse(result.content, timeSyncAns); auto printFunc = [&timeSyncAns]() { DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("timeDiff: %d", timeSyncAns.timeDiff); DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("authVersion: %d", timeSyncAns.authVersion); DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("sessionKey: %s", timeSyncAns.sessionKey.c_str()); DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("reserved: %s", timeSyncAns.reserved.c_str()); }; printFunc(); int decodedSessionKeyLen = 0; char* decodedSessionKey = Hex2Str(timeSyncAns.sessionKey.c_str(), decodedSessionKeyLen); DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("decodedSessionKey=%s,%d", decodedSessionKey, decodedSessionKeyLen); DWORD rc = Error_InvalidState; rc = m_fsm->HandleTimeSyn(timeSyncAns.timeDiff, (BYTE*)decodedSessionKey); delete decodedSessionKey; if (rc == Error_Succeed) { auto pEvent = new FSMEvent(CAccessAuthFSM::Event_EndSyncTime); m_fsm->PostEventFIFO(pEvent); } else { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("TimeSynTask HandleTimeSyn error = %08X", rc); } } else { std::string errDetail(result.WhatError()); if (errDetail.find("Error resolving address") != std::string::npos) { std::string tmpDetail = SP::Module::Net::GetWWWInfoThroughDig(config.GetBaseUri()); if (!tmpDetail.empty()) { SP::Utility::replaceInPlace(tmpDetail, "\n", "$$"); const int len = tmpDetail.length(); int pos = 0, times = 0; const int each_size = 450; std::vector contents; while (pos < len) { const std::string elem = tmpDetail.substr(pos, (len - pos) > each_size ? each_size : std::string::npos); pos = (++times) * each_size; contents.push_back(elem); LogWarn(Severity_Low, Error_Debug, ERROR_ACCESSAUTH_ACS_DIGINFO, CSimpleStringA::Format("[%d]%s", times, elem.c_str())); } } else { LogWarn(Severity_Low, Error_Debug, ERROR_ACCESSAUTH_ACS_DIGINFO, errDetail.c_str()); } } m_fsm->AuthLogWarn(result, config.GetRequestUri(), "获取会话密钥"); DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("TimeSynTask Connect Failed."); FSMEvent* pEvent = new FSMEvent(CAccessAuthFSM::Event_ReqTokenCancel); pEvent->param1 = AccessAuthorization_UserErrorCode_ACS_FAIL; m_fsm->PostEventFIFO(pEvent); } } }; struct UpdateWKTask : ITaskSp { CAccessAuthFSM* m_fsm; CAccessAuthEntity* m_entity; UpdateWKTask(CAccessAuthFSM* fsm, CAccessAuthEntity* entity) :m_fsm(fsm), m_entity(entity) {} void Process() { if (m_fsm->GetmAccessAuthHost().IsNullOrEmpty()) { LogWarn(Severity_Middle, Error_Unexpect, AccessAuthorization_UserErrorCode_AccessAuth_NULL, "准入Url为空"); return; } CSystemStaticInfo si; m_fsm->GetEntityBase()->GetFunction()->GetSystemStaticInfo(si); if (m_fsm->containsChinese(m_fsm->GetmAccessAuthHost().GetData())) { m_fsm->doWarnMsg(ERROR_ACCESSAUTH_CONNECT_ACS, GetOutPutStr("%s", "连接总行ACS准入服务失败(UpdateWKTask).").c_str(), true); DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setResultCode("RTA5212").setLogCode(AccessAuthService_LogCode_UpdateWK) ("UpdateWKTask Connect Failed."); FSMEvent* pEvent = new FSMEvent(CAccessAuthFSM::Event_ReqTokenCancel); m_fsm->PostEventFIFO(pEvent); return; } CAccessAuthUpdateWKReq updateWKReq; CAccessAuthUpdateWKAns updateWKAns; updateWKReq.terminalNo = si.strTerminalID.GetData(); auto tmkpair = m_entity->GenerateTmkToKMC();//first是加密的,seconde是没加密的 updateWKReq.encRandom = tmkpair.first; PinPadService_ClientBase* pPinPad = new PinPadService_ClientBase(this->m_entity); auto errRc = pPinPad->Connect(); if (errRc == Error_Succeed) { PinPadService_GetCheckCode_Req req = {}; PinPadService_GetCheckCode_Ans ans = {}; req.mSN.Init(1); req.wSN.Init(1); req.mSN[0] = 1; req.wSN[0] = 0; errRc = (*pPinPad)(EntityResource::getLink().upgradeLink())->GetCheckCode(req, ans, 10000); if (errRc == Error_Succeed) { updateWKReq.tpkKeyCheck = ans.checkcode[0].GetData(); updateWKReq.keyIndex = ans.index[0].GetData(); } else { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setLogCode(AccessAuthService_LogCode_UpdateWK)("Get keyChek && keyIndex failed."); return; } pPinPad->GetFunction()->CloseSession(); } else { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setLogCode(AccessAuthService_LogCode_UpdateWK)("connect to pinpad failed.error code:%d", errRc); return; } HttpClientResponseResult result; HttpClientRequestConfig config(HttpRequestMethod::POST, m_fsm->GetmAccessAuthHost().GetData(), &SpGetToken); config.SetChildUri("/api/v5/wkupdate"); SP::Module::Restful::FulfillRequestJsonBody(&config, updateWKReq); std::string test; test = config.GetRequestUri(); DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("请求地址:%s.", test.c_str()); RestfulClient client = RestfulClient::getInstance(); PROCESS_LINK_CONTEXT("LR0402502wkUpdate"); config.PreDo(); DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("to Post with new restful...."); client.Do(&config, &result, &nextLink); if (result.ResponseOK()) { DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("UpdateWKTask Connect With Restful Success."); SP::Module::Restful::CommResponseJson responseStatus; SP::Module::Restful::GetStatusFromDebranchResponse(result.content, responseStatus); if (!responseStatus.IsOperatedOK()) { m_fsm->doWarnMsg(ERR_ACCESSAUTH_UPDATE_WK, GetOutPutStr("%s%s%s%s", "UpdateWKTask", responseStatus.errorCode.c_str(), "message", responseStatus.errorMsg.c_str()).c_str(), true); DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setLogCode(AccessAuthService_LogCode_UpdateWK)("UpdateWK service failed."); return; } SP::Module::Restful::ExtractDataFromDebranchResponse(result.content, updateWKAns); DWORD rc = m_entity->LoadKeysToPinPadACS(tmkpair.second, updateWKAns.tpk, updateWKAns.edk, updateWKAns.keyIndex, updateWKAns.tpkKeyCheck, updateWKAns.edkKeyCheck); if (rc == Error_Succeed) { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setLogCode(AccessAuthService_LogCode_UpdateWK)("UpdateWK suc."); return; } else { DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM).setLogCode(AccessAuthService_LogCode_UpdateWK) ("UpdateWKTask 密钥加载失败,请检查密码键盘连接。 error = %08X", rc); } } else { m_fsm->doWarnMsg(ERROR_ACCESSAUTH_CONNECT_ACS, GetOutPutStr("%s%s", "连接总行ACS准入服务失败(UpdateWKTask).", result.WhatError().c_str()).c_str(), true); DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setResultCode("RTA5212").setLogCode(AccessAuthService_LogCode_UpdateWK) ("UpdateWKTask Connect Failed."); } UpdateWKRetError: FSMEvent* pEvent = new FSMEvent(CAccessAuthFSM::Event_ReqTokenCancel); m_fsm->PostEventFIFO(pEvent); } }; struct GetTokenTask : ITaskSp { CAccessAuthFSM* m_fsm; CAccessAuthEntity* m_entity; GetTokenTask(CAccessAuthFSM* fsm, CAccessAuthEntity* entity) :m_fsm(fsm), m_entity(entity) {} void Process() { if (m_fsm->GetmAccessAuthHost().IsNullOrEmpty()) { LogWarn(Severity_Middle, Error_Unexpect, AccessAuthorization_UserErrorCode_AccessAuth_NULL, "准入Url为空"); FSMEvent* pEvent = new FSMEvent(CAccessAuthFSM::Event_ReqTokenCancel); pEvent->param1 = AccessAuthorization_UserErrorCode_AccessAuth_NULL; m_fsm->PostEventFIFO(pEvent); CSimpleStringA strMsg(true); strMsg = CSimpleStringA::Format("准入服务地址为空,请下载集中配置或尝试重启应用"); m_fsm->doWarnMsg(AccessAuthorization_UserErrorCode_AccessAuth_NULL, strMsg.GetData(), true); return; } ///**TODO(Gifur@3/11/2022): 诗友确定是否还需要连分行!!!!! */ CAccessAuthGetTokenReq getTokenReq; if (m_fsm->GetTokenReq(&getTokenReq) != Error_Succeed) { FSMEvent* pEvent = new FSMEvent(CAccessAuthFSM::Event_ReqTokenFail); m_fsm->PostEventFIFO(pEvent); return; } DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("encTerminalInfo: %s", getTokenReq.encTerminalInfo.c_str()); DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("sessionTempPubKey:%s", getTokenReq.sessionTempPubKey.c_str()); DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("terminalNo: %s", getTokenReq.terminalNo.c_str()); DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("terminalVersion: %s", getTokenReq.terminalVersion.c_str()); CAccessAuthGetTokenAns getTokenAns; HttpClientResponseResult result; HttpClientRequestConfig config(HttpRequestMethod::POST, m_fsm->GetmAccessAuthHost().GetData(), &SpGetToken); config.SetChildUri("/api/v4/access"); if (m_fsm->containsChinese(m_fsm->GetmAccessAuthHost().GetData())) { result.statusCode = 6; m_fsm->AuthLogWarn(result, m_fsm->GetmAccessAuthHost().GetData(), "获取准入token"); DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("GetTokenTask Connect Failed."); FSMEvent* pEvent = new FSMEvent(CAccessAuthFSM::Event_ReqTokenFail); m_fsm->PostEventFIFO(pEvent); return; } SP::Module::Restful::FulfillRequestJsonBody(&config, getTokenReq); RestfulClient client = RestfulClient::getInstance(); PROCESS_LINK_CONTEXT("LR0402502Access"); config.PreDo(); client.Do(&config, &result, &nextLink); if (result.ResponseOK()) { SP::Module::Restful::CommResponseJson responseStatus; SP::Module::Restful::GetStatusFromDebranchResponse(result.content, responseStatus); if (!responseStatus.IsOperatedOK()) { m_fsm->AuthLogWarn(result, config.GetRequestUri(), "获取准入token"); return; } SP::Module::Restful::ExtractDataFromDebranchResponse(result.content, getTokenAns); if (getTokenAns.flag != false/*&& flag?*/) //判断是否需要告警,通过标志位,标志位待确定 { CSimpleStringA tmsg = CSimpleStringA::Format("{\"errcode\": \"%s\", \"message\": %s}", responseStatus.errorCode.c_str(), getTokenAns.warnMessage.c_str()); m_entity->SetAuthErrMsg(tmsg.GetData()); m_fsm->GetEntityBase()->GetFunction()->SetSysVar("AuthErrMsg", tmsg.GetData()); } else { m_entity->SetAuthErrMsg(""); m_fsm->GetEntityBase()->GetFunction()->SetSysVar("AuthErrMsg", ""); } DWORD rc = m_fsm->HandleGetToken((BYTE*)getTokenAns.sharedKey.enToken.c_str(), (BYTE*)getTokenAns.sharedKey.sharedSK.c_str(), (BYTE*)getTokenAns.accessToken.enToken.c_str(), (BYTE*)getTokenAns.accessToken.retHash.c_str()); if (rc == Error_Succeed) { FSMEvent* pEvent = new FSMEvent(CAccessAuthFSM::Event_ReqTokenSucc); m_fsm->PostEventFIFO(pEvent); return; } else { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("GetTokenTask HandleGetToken error = %08X", rc); } } else { std::string errDetail(result.WhatError()); if (errDetail.find("Error resolving address") != std::string::npos) { std::string tmpDetail = SP::Module::Net::GetWWWInfoThroughDig(config.GetBaseUri()); if (!tmpDetail.empty()) { SP::Utility::replaceInPlace(tmpDetail, "\n", "$$"); const int len = tmpDetail.length(); int pos = 0, times = 0; const int each_size = 450; std::vector contents; while (pos < len) { const std::string elem = tmpDetail.substr(pos, (len - pos) > each_size ? each_size : std::string::npos); pos = (++times) * each_size; contents.push_back(elem); LogWarn(Severity_Low, Error_Debug, ERROR_ACCESSAUTH_ACS_DIGINFO, CSimpleStringA::Format("[%d]%s", times, elem.c_str())); } } else { LogWarn(Severity_Low, Error_Debug, ERROR_ACCESSAUTH_ACS_DIGINFO, errDetail.c_str()); } } m_fsm->AuthLogWarn(result, config.GetRequestUri(), "获取准入token"); DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("GetTokenTask Connect Failed. [%s]", result.WhatError().c_str()); } FSMEvent* pEvent = new FSMEvent(CAccessAuthFSM::Event_ReqTokenFail); m_fsm->PostEventFIFO(pEvent); } }; #ifdef RVC_OS_LINUX bool isChineseChar(const char* p) { if (*p >= 0x80) { // ASCII字符的最高位是0,非ASCII字符的最高位是1 char firstByte = *p; if ((firstByte & 0xE0) == 0xE0) { // 3字节的UTF-8字符 return (*++p >= 0x80) && (*++p >= 0x80) && // 第二、三个字节都是10xxxxxx ((firstByte & 0xFE) != 0xFE) && // 排除0xFE00~0xFEFF的特殊区域 ((*(unsigned char*)p - 0x80) <= 0xBF); } else if ((firstByte & 0xC0) == 0xC0) { // 2字节的UTF-8字符 return (*++p >= 0x80) && // 第二个字节是10xxxxxx ((firstByte & 0xFE) != 0xFE); } } return false; } bool CAccessAuthFSM::containsChinese(const std::string& str) { for (size_t i = 0; i < str.size(); i++) { if (isChineseChar(str.c_str() + i)) { return true; } } return false; } #else bool CAccessAuthFSM::containsChinese(const std::string& str) { int len = MultiByteToWideChar(CP_ACP, 0, str.c_str(), -1, NULL, 0); wchar_t* wideStr = new wchar_t[len]; MultiByteToWideChar(CP_ACP, 0, str.c_str(), -1, wideStr, len); for (int i = 0; i < len; i++) { if (wideStr[i] >= 0x4E00 && wideStr[i] <= 0x9FFF) { delete[] wideStr; return true; } } delete[] wideStr; return false; } #endif // RVC_OS_WIN void CAccessAuthFSM::doWarnMsg(int errReason, std::string errMsg, bool bNeedEvent, string varMsg) { #ifdef RVC_OS_WIN auto fullErrMsg = varMsg.length() > 0 ? varMsg : errMsg; #else const std::string errMsgStr = SP::Utility::GBK2UTF8(errMsg); const std::string varMsgStr = SP::Utility::GBK2UTF8(varMsg); auto fullErrMsg = varMsgStr.length() > 0 ? varMsgStr : errMsgStr; #endif // RVC_OS_WIN if (bNeedEvent) { auto pEntity = (CAccessAuthEntity*)m_pEntity; pEntity->SetAuthErrMsg(fullErrMsg.c_str()); const ErrorCodeEnum ec = m_pEntity->GetFunction()->SetSysVar("AuthErrMsg", fullErrMsg.c_str()); if (ec != Error_Succeed) { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("Update SysVar failed: 0x%X", ec); } if (errReason == ERR_ACCESSAUTH_SERVICE_FAILED) { pEntity->SetAuthErrMsg(errMsg.c_str()); m_pEntity->GetFunction()->SetSysVar("AuthErrMsg", errMsg.c_str()); LogEvent(Severity_Middle, ERR_ACCESSAUTH_SERVICE_FAILED, errMsg.c_str()); } else { LogEvent(Severity_Middle, checkErrType(errReason), errMsg.c_str()); } } LogWarn(Severity_Middle, Error_Unexpect, errReason, errMsg.c_str()); } void CAccessAuthFSM::s1_on_entry() { CSimpleStringA strEntryStatus = GetEntryPermitSysVar(); if (strEntryStatus.Compare("L") == 0) { PostEventFIFO(new FSMEvent(Event_AccessAuthSucc)); } else { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("EntryStatus: %s", strEntryStatus.GetData()); SetEntryPermitSysVar("I"); } GetEntityBase()->GetFunction()->SetSysVar("AccessHavePath", "Y");//oiltmp to delete } void CAccessAuthFSM::s1_on_exit() { } unsigned int CAccessAuthFSM::s1_on_event(FSMEvent* pEvent) { DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("s1_on_event: %d", pEvent->iEvt); return 0; } void CAccessAuthFSM::s2_on_entry() { LOG_FUNCTION(); m_finishAccess = 0; SetEntryPermitSysVar("C"); DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("开始第%d次准入", m_nAccessFailedCount); CSmartPointer timeSynTask = new TimeSynTask(this); GetEntityBase()->GetFunction()->PostThreadPoolTask(timeSynTask.GetRawPointer()); } void CAccessAuthFSM::s2_on_exit() { } unsigned int CAccessAuthFSM::s2_on_event(FSMEvent* pEvent) { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("s2 receives event id: %d", pEvent->iEvt); if (pEvent->iEvt == Event_EndSyncTime) { pEvent->SetHandled(); CSmartPointer getTokenTask = new GetTokenTask(this, (CAccessAuthEntity*)m_pEntity); GetEntityBase()->GetFunction()->PostThreadPoolTask(getTokenTask.GetRawPointer()); return 0; } else if (pEvent->iEvt == Event_ReqTokenCancel) { //这里貌似会触发健康发起重试 auto pEntity = (CAccessAuthEntity*)m_pEntity; if (pEvent->param1 == AccessAuthorization_UserErrorCode_AccessAuth_NULL) { CSimpleStringA strMsg = CSimpleStringA::Format("准入Url为空"); pEntity->SetAuthErrMsg(strMsg); } else if (pEvent->param1 == AccessAuthorization_UserErrorCode_ACS_FAIL) { pEntity->SetAuthErrMsg("访问总行ACS失败"); } else { CSimpleStringA strErrMsg = CSimpleStringA::Format("准入超时(%d)", m_finishAccess); pEntity->GetFunction()->ShowFatalError(strErrMsg); } SetEntryPermitSysVar("A"); m_nAccessFailedCount++; pEvent->SetHandled(); } else if (pEvent->iEvt == Event_ReqTokenFail) { //而这里不会触发健康发起重试 SetEntryPermitSysVar("F"); pEvent->SetHandled(); auto pEntity = (CAccessAuthEntity*)m_pEntity; CSimpleStringA strErrMsg = CSimpleStringA::Format("%s", (const char*)pEntity->GetAuthErrMsg()); // 发送准入失败事件,暂时不发送事件进去关门界面,原因关门界面显示中文乱码 doWarnMsg(EVENT_ACCESSAUTH_FAILED, strErrMsg.GetData(), true); DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setResultCode("RTA520B")("准入失败"); pEntity->GetFunction()->ShowFatalError(strErrMsg); m_nAccessFailedCount = 0; } else if (pEvent->iEvt == Event_ReqTokenSucc) { SetEntryPermitSysVar("L"); LogEvent(Severity_Middle, EVENT_ACCESSAUTH_SUCCEED, "终端准入成功"); m_pEntity->GetFunction()->ShowStartupInfo("准入成功"); m_nAccessFailedCount = 0; pEvent->SetHandled(); PostEventFIFO(new FSMEvent(Event_AccessAuthSucc)); } return 0; } void CAccessAuthFSM::s3_on_entry() { LOG_FUNCTION(); CSystemStaticInfo si; DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_USER).setLogCode(AccessAuthService_LogCode_Regist)("终端准入成功"); m_pEntity->GetFunction()->GetSystemStaticInfo(si); if (si.InstallVersion.ToString().IsNullOrEmpty()) { LogWarn(Severity_Low, Error_Debug, AccessAuthorization_UserErrorCode_Start, "终端准入成功"); } else { LogWarn(Severity_Low, Error_Debug, AccessAuthorization_UserErrorCode_Start, CSimpleStringA::Format("终端准入成功,版本: %s", si.InstallVersion.ToString().GetData())); } } unsigned int CAccessAuthFSM::s3_on_event(FSMEvent* event) { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("s3 receives event id: %d", event->iEvt); return 0; } CSimpleStringA CAccessAuthFSM::GetEntryPermitSysVar() { CSimpleStringA strValue(true); CSmartPointer spFunction = m_pEntity->GetFunction(); spFunction->GetSysVar("EntryPermit", strValue); return strValue; } ErrorCodeEnum CAccessAuthFSM::SetEntryPermitSysVar(const CSimpleStringA& newVal) { CSmartPointer spFunction = m_pEntity->GetFunction(); DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("Set EntryPermit with %s", newVal.GetData()); return spFunction->SetSysVar("EntryPermit", (const char*)newVal); } ErrorCodeEnum CAccessAuthFSM::LoadCenterConfig() { CSmartPointer spFunction = m_pEntity->GetFunction(); CSmartPointer spConfig; ErrorCodeEnum Error = spFunction->OpenConfig(Config_CenterSetting, spConfig); if (Error_Succeed == Error) { spConfig->ReadConfigValue("AccessAuthorization", "HostUrl", m_accessAuthHost); spConfig->ReadConfigValue("AccessAuthorization", "HostInitDeviceUrl", m_initDeviceHost); } return Error; } bool CAccessAuthFSM::DecryptWithSessionKey(BYTE* encText, int encTextLen, BYTE* decTest, int& decTestLen) { BYTE key[16] = { 0 }; memcpy(key, ((CAccessAuthEntity*)m_pEntity)->m_AuthSessionKey, 16); char* keyTmp = Str2Hex((char*)key, 16); delete keyTmp; if (!DecWithSM4_ECB(key, encText, encTextLen, decTest, &decTestLen)) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("DecryptWithSessionKey ECB error."); return false; } keyTmp = Str2Hex((char*)decTest, decTestLen); delete keyTmp; return true; } DWORD CAccessAuthFSM::HandleTimeSyn(long nTimeDiff, BYTE* nSessionKey) { // 比较终端和服务器时间, 时差小于3分钟(默认,可通过集中配置配置)不纠正 const long dwTimeDiff = nTimeDiff > 0 ? nTimeDiff : 0 - nTimeDiff; const long torelateTime = m_torelateDiffSyncTimeSecs > 0 ? m_torelateDiffSyncTimeSecs : 0 - m_torelateDiffSyncTimeSecs; if (torelateTime < dwTimeDiff) { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI("HandleTimeSyn")("time diff is too large (%ds), sync time now", nTimeDiff); CSmallDateTime dtServerTime((DWORD)(CSmallDateTime::GetNow()) + nTimeDiff); SYSTEMTIME stServerTime = dtServerTime.ToSystemTime(); CSmallDateTime dtLocalTime((DWORD)(CSmallDateTime::GetNow())); #ifdef RVC_OS_WIN if (SetLocalTime(&stServerTime)) { #else if (set_system_time_by_sec(nTimeDiff)) { #endif // RVC_OS_WIN DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("sync time with server succeed, before local time:[%s], server time: [%s]", dtLocalTime.ToTimeString().GetData(), dtServerTime.ToTimeString().GetData()); LogWarn(Severity_Low, Error_Debug, AccessAuthorization_UserErrorCode_Sync_Time_Succ, CSimpleStringA::Format("%ld",nTimeDiff)); } else { LogWarn(Severity_Middle, Error_Unexpect, AccessAuthorization_UserErrorCode_Sync_Time_Failed, CSimpleStringA::Format("sync time failed: local time:[%s], server time: [%s],diff[%ld],threshold:[%d](GLE=%u)", dtLocalTime.ToTimeString().GetData(), dtServerTime.ToTimeString().GetData(), nTimeDiff, m_torelateDiffSyncTimeSecs, GetLastError())); return ERR_ACCESSAUTH_SET_LOCALE_TIME; } } else { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI("HandleTimeSyn") ("time diff is acceptable (%lds), threshold(%d),", nTimeDiff, m_torelateDiffSyncTimeSecs); } //会话密钥缓存 if (((CAccessAuthEntity*)m_pEntity)->SaveAuthKey(nSessionKey)) return Error_Succeed; return Error_Unexpect; } DWORD CAccessAuthFSM::HandleGetToken(BYTE* enToken1, BYTE* sharedKey, BYTE* enToken2, BYTE* retHash) { DWORD rc = Error_Succeed; auto pEntity = (CAccessAuthEntity*)m_pEntity; DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM).setAPI("HandleGetToken")("retHash=%s", (char*)retHash); char* enToken1_acs, * sharedKey_acs, * enToken2_acs, * hash_acs; int enToken1_acs_len = 0, sharedKey_acs_len = 0, enToken2_acs_len = 0, hash_acs_len = 0; enToken1_acs = Hex2Str((char*)enToken1, enToken1_acs_len); sharedKey_acs = Hex2Str((char*)sharedKey, sharedKey_acs_len); enToken2_acs = Hex2Str((char*)enToken2, enToken2_acs_len); hash_acs = Hex2Str((char*)retHash, hash_acs_len); DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM).setAPI("HandleGetToken")("enToken1_acs_len=%d", enToken1_acs_len); DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM).setAPI("HandleGetToken")("sharedKey_acs_len=%d", sharedKey_acs_len); DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM).setAPI("HandleGetToken")("enToken2_acs_len=%d", enToken2_acs_len); DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM).setAPI("HandleGetToken")("hash_acs_len=%d", hash_acs_len); memset(enToken1, 0, strlen((char*)enToken1)); memset(sharedKey, 0, strlen((char*)sharedKey)); memset(enToken2, 0, strlen((char*)enToken2)); memset(retHash, 0, strlen((char*)retHash)); memcpy(enToken1, enToken1_acs, enToken1_acs_len); memcpy(sharedKey, sharedKey_acs, sharedKey_acs_len); memcpy(enToken2, enToken2_acs, enToken2_acs_len); memcpy(retHash, hash_acs, hash_acs_len); delete enToken1_acs; delete sharedKey_acs; delete enToken2_acs; delete hash_acs; BYTE enToken[512 + 16] = { 0 }; memcpy(enToken, enToken1, 256); memcpy(enToken + 256, enToken2, 256); memcpy(enToken + 512, sharedKey, 16); BYTE sm3[32] = { 0 }; if (!SM3Hash(enToken, 512 + 16, sm3)) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("SM3 Hash error at Token Ret."); } if (memcmp(sm3, retHash, 32) != 0) { rc = Error_Bug; pEntity->SetAuthErrMsg("返回令牌校验不通过"); pEntity->GetFunction()->SetSysVar("AuthErrMsg", "返回令牌校验不通过"); char* sm3Ret = Str2Hex((char*)sm3, 32); delete sm3Ret; doWarnMsg(ERR_ACCESSAUTH_TOKEN_HASH, "返回令牌校验不通过", true); DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)(GetOutPutStr("%s%s", "Hash", "返回令牌校验不通过").c_str()); } else { CBlob token; token.Alloc(512); memcpy(token.m_pData, enToken, 512); CBlob sharedSK; sharedSK.Alloc(16); memcpy(sharedSK.m_pData, sharedKey, 16); rc = pEntity->SaveTokenAndSharedSK(token, sharedSK); if (rc != Error_Succeed) { pEntity->SetAuthErrMsg("保存令牌失败"); pEntity->GetFunction()->SetSysVar("AuthErrMsg", "保存令牌失败"); doWarnMsg(ERR_ACCESSAUTH_SAVE_TOKEN, "保存令牌失败", true); DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setResultCode("RTA5208")(GetOutPutStr("%s%08X", "SaveTokenAndSharedSK", rc).c_str()); } } return rc; } DWORD CAccessAuthFSM::GetEncTerminalInfoWithKey(CBlob& encInfo, BYTE* key) { LOG_FUNCTION(); ErrorCodeEnum rc = Error_Succeed; CSimpleStringA ip, mac, pinpadModel, cpuId, mainBoardId, hardDiskId, osType, osVersion; std::map termInfo; auto pEntity = ((CAccessAuthEntity*)m_pEntity); bool bPinPadOnline = false; pEntity->GetPinPadModel(pinpadModel, bPinPadOnline); GetIPandMac(ip, mac); osVersion = GetOsVersion(); while (1) { if (pEntity->GetTermSysInfo() == -1) return false; else if (pEntity->GetTermSysInfo() == 1) break; else if (pEntity->GetTermSysInfo() == 0) Sleep(1000);//oiltmp@20220917 之前的逻辑是不跳出去,现在要加么?暂时不加,连调用系统接口都有问题,让其他逻辑处理 } #ifdef RVC_OS_WIN termInfo["osType"] = "Windows"; #else termInfo["osType"] = "UOS"; #endif // RVC_OS_WIN termInfo["osVersion"] = osVersion.GetData(); termInfo["ip"] = ip.GetData(); termInfo["mac"] = mac.GetData(); termInfo["cpuId"] = pEntity->m_cpuId.GetData(); termInfo["mainBoardId"] = pEntity->m_mainBoardId.GetData(); termInfo["hardDiskId"] = pEntity->m_hardDiskId.GetData(); termInfo["pinpadModel"] = pinpadModel.GetData(); std::pair strResult; strResult = generateJsonStr(termInfo); char* pBuf = new char[2048]; int len = 0; #ifdef RVC_OS_WIN string tmpStr = strResult.second; SP::Module::Util::ConvertGBKToUtf8(tmpStr); strcpy(pBuf, tmpStr.c_str()); //GBK转UTF8 len = tmpStr.size(); #else strcpy(pBuf, strResult.second.c_str()); len = strResult.second.size(); #endif // RVC_OS_WIN DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("HardWareInfo: %s", pBuf); DbgWithLink(LOG_LEVEL_DEBUG, LOG_TYPE_SYSTEM)("HardWareInfo size: %d", len); CBlob raw; raw.Refer(pBuf, len); rc = pEntity->EncryptDataWithKey(raw, encInfo, key); if (rc != Error_Succeed) { doWarnMsg(ERR_ACCESSAUTH_ENCRYPT_KEY, GetOutPutStr("%s%08X", "CryptEncrypt", rc).c_str()); DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)(GetOutPutStr("%s%08X", "CryptEncrypt", rc).c_str()); return ERR_ACCESSAUTH_ENCRYPT_KEY; } return Error_Succeed; } //密钥加密并转成可见字符 DWORD CAccessAuthFSM::GetTmk(string& tmk) { BYTE tmp[140]; CBlob pubKey; CBlob priKey; DWORD rc = ((CAccessAuthEntity*)m_pEntity)->CreateSM2KeyPair(pubKey, priKey); if (rc != Error_Succeed) return rc; rc = ((CAccessAuthEntity*)m_pEntity)->SaveSM2KeyPair(pubKey, priKey); if (rc != Error_Succeed) return rc; memset(tmp, 0, sizeof(tmp)); if (pubKey.m_iLength > 70) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("临时公钥长度(%d)大于70。。。", pubKey.m_iLength); return Error_TooSmallBuffer; } memcpy_s(tmp, sizeof(tmp) - 70, pubKey.m_pData, pubKey.m_iLength); if (priKey.m_iLength > 70) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("临时私钥长度(%d)大于70。。。", priKey.m_iLength); return Error_TooSmallBuffer; } memcpy_s(&tmp[70], sizeof(tmp) - 70, priKey.m_pData, priKey.m_iLength); char* pRet = new char[512]; HexBuf2StrBuf(tmp, &pRet, 140); DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("data=%s,%d", pRet, strlen(pRet)); tmk.assign(pRet); delete[] pRet; return Error_Succeed; } DWORD CAccessAuthFSM::GetTokenReq(CAccessAuthGetTokenReq* getTokenReq) { DWORD rc; auto pEntity = (CAccessAuthEntity*)m_pEntity; CSystemStaticInfo si; pEntity->GetFunction()->GetSystemStaticInfo(si); getTokenReq->terminalVersion = si.InstallVersion.ToString(); getTokenReq->terminalNo = si.strTerminalID.GetData(); CBlob encInfo; // 使用会话密钥加密 char sessionKey[KEY_SIZE] = { 0 }; memcpy(sessionKey, pEntity->m_AuthSessionKey, KEY_SIZE); if ((rc = GetEncTerminalInfoWithKey(encInfo, (BYTE*)sessionKey)) != Error_Succeed) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("GetEncTerminalInfo failed:%d", rc); return rc; } char* pTmp = Str2Hex((char*)encInfo.m_pData, encInfo.m_iLength); getTokenReq->encTerminalInfo = pTmp; delete pTmp; string tmpStr = ""; if ((rc = GetTmk(tmpStr)) != Error_Succeed) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM)("GetTmk failed:%d", rc); return rc; } getTokenReq->sessionTempPubKey = tmpStr; return rc; } void CAccessAuthFSM::UpdateWK() { LOG_FUNCTION(); auto pEntity = ((CAccessAuthEntity*)m_pEntity); CSimpleStringA strPinPadModel = ""; bool bPinPadOnline = false; pEntity->GetPinPadModel(strPinPadModel, bPinPadOnline); if (bPinPadOnline) { CSmartPointer updateWKTask = new UpdateWKTask(this, pEntity); GetEntityBase()->GetFunction()->PostThreadPoolTask(updateWKTask.GetRawPointer()); } } DWORD CAccessAuthFSM::InitDevice(SpReqAnsContext::Pointer& ctx) { return Error_Succeed; } void CAccessAuthFSM::GetDiffSyncTimeFromCenterSettings() { CSmartPointer spConfig; GetEntityBase()->GetFunction()->OpenConfig(Config_CenterSetting, spConfig); int nValue(0); spConfig->ReadConfigValueInt(GetEntityBase()->GetEntityName(), "SyncTimeThreshold", nValue); if (nValue != 0) { m_torelateDiffSyncTimeSecs = nValue; DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_BUSINESS_SYSTEM)("Fetch SyncTimeThreshold from CS returns: %d", m_torelateDiffSyncTimeSecs); } } template void CAccessAuthFSM::AuthLogWarn(const T& ret, const string& url, const string& method, bool bNeedEvent) { CSimpleStringA msg; if (!ret.ResponseOK()) { int acsErrCode = ERROR_ACCESSAUTH_CONNECT_ACS_x; if (ret.statusCode == 6) { acsErrCode = ERROR_ACCESSAUTH_CONNECT_ACS_6; msg = CSimpleStringA::Format("%s失败:域名解析失败,请尝试重启应用", method.c_str()); } else if (ret.statusCode == 28) { acsErrCode = ERROR_ACCESSAUTH_CONNECT_ACS_28; msg = CSimpleStringA::Format("%s失败:连接总行服务超时,请尝试重启应用", method.c_str()); } else { msg = CSimpleStringA::Format("%s失败,请尝试重启应用", method.c_str()); } doWarnMsg(acsErrCode, msg.GetData(), bNeedEvent); DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_USER).setLogCode(AccessAuthService_LogCode_Regist)(msg.GetData()); } else { SP::Module::Restful::CommResponseJson responseStatus; SP::Module::Restful::GetStatusFromDebranchResponse(ret.content, responseStatus); msg = CSimpleStringA::Format("{\"errcode\": \"%s\", \"message\": %s}", responseStatus.errorCode.c_str(), responseStatus.errorMsg.c_str()); doWarnMsg(ERR_ACCESSAUTH_SERVICE_FAILED, msg.GetData(), bNeedEvent); DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_USER).setResultCode("RTA520A").setLogCode(AccessAuthService_LogCode_Regist) (msg.GetData()); } } void CAccessAuthFSM::GetNetMsg(SpReqAnsContext::Pointer& ctx) { CSimpleStringA tmp; ctx->Ans.netStatus = 1; //成功 ctx->Answer(Error_Succeed); } CSimpleStringA CAccessAuthFSM::GetOsVersion() { std::map errInfo; CSimpleStringA errMsg; errInfo["errcode"] = "RTA5219"; errInfo["msg"] = "调用系统api获取操作系统版本失败"; #if defined(RVC_OS_WIN) CSimpleStringA runInfoPath; ErrorCodeEnum eErr = GetEntityBase()->GetFunction()->GetPath("runinfo", runInfoPath); if (eErr != Error_Succeed) { DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("GetPath runinfo error=%s.", SpStrError(eErr)); errInfo["getLastErr"] = to_string(GetLastError()); errMsg = generateJsonStr(errInfo).second.c_str(); return errMsg; } runInfoPath += "\\runcfg\\osverion"; ifstream is; is.open(runInfoPath.GetData(), ios::binary); if (!is.is_open()) { DWORD dwErr = GetLastError(); DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("open runcfg\\osverion file failed. [%d]", dwErr); errInfo["getLastErr"] = to_string(dwErr); errMsg = generateJsonStr(errInfo).second.c_str(); return errMsg; } string line; while (!is.eof()) { getline(is, line); int start = line.find("版本"); if (start != string::npos) //return CSimpleStringA(line.substr(start + 5, line.length() - start - 7).c_str()); return CSimpleStringA(line.c_str()); else continue; } errInfo["getLastErr"] = to_string(GetLastError()); errMsg = generateJsonStr(errInfo).second.c_str(); return errMsg; #else std::map osInfo; const char filePath[] = "/etc/os-version"; char tmp[33]; memset(tmp, 0, 33); inifile_read_str_s("Version", "SystemName", "unknown", tmp, 32, filePath); osInfo["SystemName"] = tmp; memset(tmp, 0, 33); inifile_read_str_s("Version", "ProductType", "unknown", tmp, 32, filePath); osInfo["ProductType"] = tmp; memset(tmp, 0, 33); inifile_read_str_s("Version", "MajorVersion", "unknown", tmp, 32, filePath); osInfo["MajorVersion"] = tmp; memset(tmp, 0, 33); inifile_read_str_s("Version", "MinorVersion", "unknown", tmp, 32, filePath); osInfo["MinorVersion"] = tmp; memset(tmp, 0, 33); inifile_read_str_s("Version", "OsBuild", "unknown", tmp, 32, filePath); osInfo["OsBuild"] = tmp; return generateJsonStr(osInfo).second.c_str(); #endif } void CAccessAuthFSM::GetIPandMac(CSimpleStringA& ip, CSimpleStringA& mac) { CAutoArray netList; ErrorCodeEnum rc = SP::Module::Net::GetINETMacAddresses(netList); std::map errInfo; if (rc != Error_Succeed) { DbgWithLink(LOG_LEVEL_WARN, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("Get sys netinfo failed!. rc=%d.", rc); errInfo["errcode"] = "RTA5216"; errInfo["msg"] = "调用系统api获取ip失败"; errInfo["getLastErr"] = to_string(GetLastError()); ip = generateJsonStr(errInfo).second.c_str(); errInfo["errcode"] = "RTA5217"; errInfo["msg"] = "调用系统api获取mac地址失败"; errInfo["getLastErr"] = to_string(GetLastError()); mac = generateJsonStr(errInfo).second.c_str(); auto pEntity = (CAccessAuthEntity*)m_pEntity; pEntity->SetAuthErrMsg("获取本地ip和mac失败"); return; } CSimpleStringA csMac(""), csIP(""), csDNS(""); for (int i = 0; i < netList.GetCount(); i++) { if (!csMac.IsNullOrEmpty()) { csMac += ";"; } csMac += netList[i].mac.c_str(); } mac = csMac; for (int i = 0; i < netList.GetCount(); i++) { if (!csIP.IsNullOrEmpty()) { csIP += ";"; } csIP += netList[i].ip.c_str(); } ip = csIP; return; }