#include "stdafx.h" #include "SpBase.h" #include "mod_AccessAuth.h" #include "RVCComm.h" #include "comm.h" #include "access_basefun.h" #include "DeviceBaseClass.h" #include #include #include #include "TokenKeeper_client_g.h" using namespace TokenKeeper; #include "PinPad_client_g.h" using namespace PinPad; #ifdef RVC_OS_WIN #include "WMIDeviceQuery.h" #include #endif #define KEY_SIZE 16 #define BUF_SIZE 256 /** TODO(gifur): expand the time to 10s*/ #define DEFUALT_INVOKE_PINPAD_TIMEOUT 3000 typedef struct _REG_TZI_FORMAT { LONG Bias; LONG StandardBias; LONG DaylightBias; SYSTEMTIME StandardDate; SYSTEMTIME DaylightDate; } REG_TZI_FORMAT; void CAccessAuthSession::Handle_Regist(SpOnewayCallContext::Pointer ctx) { m_pEntity->Regist(); } void CAccessAuthSession::Handle_Unregist(SpOnewayCallContext::Pointer ctx) { m_pEntity->Unregist(ctx->Info.nReason, ctx->Info.nWay); } void CAccessAuthSession::Handle_Reregist(SpOnewayCallContext::Pointer ctx) { m_pEntity->Reregist(); } void CAccessAuthSession::Handle_PushTerminalStage(SpOnewayCallContext::Pointer ctx) { m_pEntity->PushTerminalStage(ctx->Info.cNewStage, ctx->Info.dwNewStageTime, ctx->Info.cOldStage, ctx->Info.dwOldStageTime); } void CAccessAuthSession::Handle_InitDev(SpReqAnsContext::Pointer ctx) { m_pEntity->InitDevice(ctx); } void CAccessAuthSession::Handle_SyncTime(SpOnewayCallContext::Pointer ctx) { m_pEntity->SyncTime(); } void CAccessAuthEntity::OnStarted() { //设置时区为北京标准时区 if (!SetLocalTimeZoneByKeyName("China Standard Time", FALSE)) { m_FSM.doWarnMsg(ERR_ACCESSAUTH_SETTIMEZONE,GetOutPutStr("%s%s","设置时区错误","False").c_str()); } m_FSM.Init(this); CSimpleStringA strErrMsg; CSmartPointer spFunction = this->GetFunction(); memset(&m_info,0, sizeof(CSystemStaticInfo)); auto rc = GetFunction()->GetSystemStaticInfo(m_info); if (rc != Error_Succeed) { strErrMsg = "HasPinPad()=>GetSystemStaticInfo() fail"; SetAuthErrMsg((const char*)strErrMsg); m_FSM.doWarnMsg(ERR_ACCESSAUTH_GET_SYSTEM_STATIC_INFO, GetOutPutStr("%s%08X", "获取系统静态信息错误", rc).c_str(), strErrMsg.GetData()); } } void CAccessAuthEntity::OnPreStart(CAutoArray strArgs,CSmartPointer pTransactionContext) { ErrorCodeEnum Error = Error_Succeed; pTransactionContext->SendAnswer(Error) ; } void CAccessAuthEntity::OnPreClose(EntityCloseCauseEnum eCloseCause,CSmartPointer pTransactionContext) { m_FSM.PostExitEvent(); pTransactionContext->SendAnswer(Error_Succeed); } void CAccessAuthEntity::OnSysVarEvent(const char *pszKey, const char *pszValue,const char *pszOldValue,const char *pszEntityName) { } // 开始准入 ErrorCodeEnum CAccessAuthEntity::Regist() { m_FSM.PostEventFIFO(new FSMEvent(CAccessAuthFSM::Event_StartRegist)); return Error_Succeed; } // 重新准入 ErrorCodeEnum CAccessAuthEntity::Reregist() { m_FSM.PostEventFIFO(new FSMEvent(CAccessAuthFSM::Event_StartReregist)); return Error_Succeed; } // 准入退出 ErrorCodeEnum CAccessAuthEntity::Unregist(int nReason, int nWay) { FSMEvent *pEvent = new FSMEvent(CAccessAuthFSM::Event_StartUnregist); pEvent->param1 = nReason; pEvent->param2 = nWay; m_FSM.PostEventFIFO(pEvent); return Error_Succeed; } DWORD CAccessAuthEntity::SyncTime() { return m_FSM.SyncTime(); } ErrorCodeEnum CAccessAuthEntity::PushTerminalStage(char cNewStage, DWORD dwNewStageTime, char cOldStage, DWORD dwOldStageTime) { Dbg("on PushTerminalStage, cNewStage: %c", cNewStage); CAccessAuthFSM::ReportStateEvent *pEvent = new CAccessAuthFSM::ReportStateEvent(cNewStage, dwNewStageTime, cOldStage, dwOldStageTime); m_FSM.PostEventFIFO(pEvent); return Error_Succeed; } // KMC初始化 DWORD CAccessAuthEntity::InitKMC() { return Error_Succeed; } // 获取WK更新请求包 // @nAlgFlag: 1:3des only; 2: sm4 only; 3: both 3des and sm4 ErrorCodeEnum CAccessAuthEntity::GetKmcWKUpdateData(char *pBuf, int &nLen, int nAlgFlag) { return Error_Succeed; } DWORD CAccessAuthEntity::ParseWKUpdateResult(char *pBuf, int nLen, int nAlgFlag) { return Error_Succeed; } CSimpleStringA CAccessAuthEntity::GetKMCLastErrMsg() { return ""; } ErrorCodeEnum CAccessAuthEntity::ReleaseKMC() { return Error_Succeed; } // 加载新WK DWORD CAccessAuthEntity::LoadPinPadWK(bool bSM) { Dbg("load sm key to pinpad..."); CSimpleString strErrMsg; CSmartPointer spFunction = this->GetFunction(); PinPadService_ClientBase* pPinPad = new PinPadService_ClientBase(this); DWORD rc = pPinPad->Connect(); if (rc == Error_Succeed) { PinPadService_LoadKeysSM_Req req = {}; req.smflag = 1; req.initializeflag = true; if (m_bGetKMCKey) { Dbg("使用云接口更新KMC密钥"); req.masterkey = m_TMK.c_str(); req.workingkey1 = m_TPK.c_str(); req.workingkey2 = m_EDK.c_str(); req.reserved3 = m_index.c_str(); } else { strErrMsg = "更新KMC密钥失败"; SetAuthErrMsg((const char*)strErrMsg); spFunction->SetSysVar("AuthErrMsg", (const char*)strErrMsg, false); LogWarn(Severity_Middle, Error_Unexpect, ERR_ACCESSAUTH_GET_KMC_NULL, GetOutPutStr("%s%s", "m_bGetKMCKey", "False").c_str()); rc = ERR_ACCESSAUTH_GET_KMC_NULL; return rc; } if (req.initializeflag) Dbg("initializeflag is true"); else Dbg("initializeflag is false"); Dbg("req.smflag=%d", req.smflag); Dbg("req.masterkey=%s", req.masterkey.GetData()); Dbg("req.workingkey1=%s", req.workingkey1.GetData()); Dbg("req.workingkey2=%s", req.workingkey2.GetData()); Dbg("req.reserved3=%s", req.reserved3.GetData()); PinPadService_LoadKeysSM_Ans ans = {}; rc = pPinPad->LoadKeysSM(req, ans, 30000); if (rc == Error_Succeed) Dbg("load sm key to pinpad succ"); else { strErrMsg = "加载SM密钥到PinPad失败"; SetAuthErrMsg((const char*)strErrMsg); spFunction->SetSysVar("AuthErrMsg", (const char*)strErrMsg, false); LogWarn(Severity_Middle, Error_Unexpect, ERR_ACCESSAUTH_LOAD_KEYS_TO_PINPAD, GetOutPutStr("%s%08x%s%s", "LoadKeysSM", rc, "strErrMsg", strErrMsg.GetData()).c_str()); rc = ERR_ACCESSAUTH_LOAD_KEYS_TO_PINPAD; } pPinPad->GetFunction()->CloseSession(); } else { strErrMsg = "连接PinPad实体失败"; SetAuthErrMsg((const char*)strErrMsg); spFunction->SetSysVar("AuthErrMsg", (const char*)strErrMsg, false); LogWarn(Severity_Middle, Error_Unexpect, ERR_ACCESSAUTH_CONNECT_PINPAD, GetOutPutStr("%s%08x%s%s", "Connect", rc, "strErrMsg", strErrMsg).c_str()); rc = ERR_ACCESSAUTH_CONNECT_PINPAD; //@test 没连接成功调用此接口释放 pPinPad->SafeDelete(); } return rc; } DWORD CAccessAuthEntity::LoadKeysToPinPadNew(string TMK, string TPK, string EDK, string index) { LOG_FUNCTION(); Dbg("load sm key to pinpad..."); PinPadService_ClientBase* pPinPad = new PinPadService_ClientBase(this); DWORD rc = pPinPad->Connect(); if (rc == Error_Succeed) { PinPadService_LoadKeysSM_Req req = {}; req.initializeflag = true; req.smflag = 1; Dbg("使用云接口获取的KMC密钥"); req.masterkey = TMK.c_str(); req.workingkey1 = TPK.c_str(); req.workingkey2 = EDK.c_str(); req.reserved3 = index.c_str(); if (req.initializeflag) Dbg("initializeflag is true"); else Dbg("initializeflag is false"); Dbg("req.smflag=%d", req.smflag); Dbg("req.masterkey=%s", req.masterkey.GetData()); Dbg("req.workingkey1=%s", req.workingkey1.GetData()); Dbg("req.workingkey2=%s", req.workingkey2.GetData()); Dbg("req.reserved3=%s", req.reserved3.GetData()); PinPadService_LoadKeysSM_Ans ans = {}; rc = pPinPad->LoadKeysSM(req, ans, 30000); if (rc == Error_Succeed) Dbg("load sm key to pinpad succ"); else { SetAuthErrMsg("加载SM密钥到PinPad失败"); m_FSM.doWarnMsg(ERR_INITIALIZER_LOAD_KEYS_TO_PINPAD, GetOutPutStr("%s%08x%s%s", "LoadKeys", rc, "strErrMsg", "加载SM密钥到PinPad失败").c_str()); rc = ERR_INITIALIZER_LOAD_KEYS_TO_PINPAD; } pPinPad->GetFunction()->CloseSession(); } else { SetAuthErrMsg("连接PinPad实体失败"); m_FSM.doWarnMsg(ERR_INITIALIZER_CONNECT_PINPAD, GetOutPutStr("%s%08x%s%s", "Connect", rc, "strErrMsg", "连接PinPad实体失败").c_str()); rc = ERR_INITIALIZER_CONNECT_PINPAD; pPinPad->SafeDelete(); } return rc; } // 将16进制字符串转成BYTE数据 bool CAccessAuthEntity::HexStrToByteArray(const char* pHex, BYTE *pBuf, int *pBufLen) { int nHexLen = strlen(pHex); if (nHexLen %2 != 0) { Dbg("error hex string length"); return false; } if (nHexLen /2 > *pBufLen) { Dbg("not enough buf length"); return false; } for(int i=0; i='0' && ch1<='9') b = ch1 - '0'; else if (ch1 >='A' && ch1 <='F') b = ch1 - 'A' + 10; else { Dbg("invalid hex string"); return false; } if (i %2 ==0) { pBuf[i/2] = b; } else { pBuf[i/2] = pBuf[i/2] << 4 | b; } } *pBufLen = nHexLen / 2; return true; } string CAccessAuthEntity::ByteArrayToHexStr(BYTE *pBuf, int nBufLen) { char szBuf[1024]; memset(szBuf, 0, sizeof(szBuf)); for(int i=0; i> 4) & 0x0F; BYTE b2 = pBuf[i] & 0x0F; if (b1 <= 9) szBuf[i*2] = '0' + b1; else szBuf[i*2] = 'A' + b1 - 10; if (b2 <= 9) szBuf[i*2+1] = '0' + b2; else szBuf[i*2+1] = 'A' + b2 - 10; } return szBuf; } // 调用密码键盘加密 DWORD CAccessAuthEntity::EncryptDataWithPinPad(const CBlob &raw, CBlob &enc) { #ifdef IGNORE_PINPAD enc.Alloc(raw.m_iLength); memcpy(enc.m_pData, raw.m_pData, raw.m_iLength); return Error_Succeed; #else CSimpleStringA strErrMsg; CSmartPointer spFunction = this->GetFunction(); PinPadService_EncryptDataSM_Req req = {}; PinPadService_EncryptDataSM_Ans ans = {}; req.data = ByteArrayToHexStr((BYTE*)raw.m_pData, raw.m_iLength).c_str(); Dbg("begin encrpyt data with pinpad"); PinPadService_ClientBase *pPinPad = new PinPadService_ClientBase(this); DWORD rc = pPinPad->Connect(); if (rc == Error_Succeed) { rc = pPinPad->EncryptDataSM(req, ans, 10000); if (rc == Error_Succeed) Dbg("encrypt data with pinpad succ: [%s]", (const char*)ans.ciphertext); else { strErrMsg = "调用PinPad实体中的EncryptData方法加密数据失败"; SetAuthErrMsg((const char *)strErrMsg); m_FSM.doWarnMsg(ERR_ACCESSAUTH_FROM_PINPAD, GetOutPutStr("%s%08x%s%s", "EncryptData", rc, "strErrMsg", strErrMsg).c_str()); rc = ERR_ACCESSAUTH_FROM_PINPAD; } pPinPad->GetFunction()->CloseSession(); } else { strErrMsg = "连接PinPad实体失败"; SetAuthErrMsg((const char *)strErrMsg); m_FSM.doWarnMsg(ERR_ACCESSAUTH_CONNECT_PINPAD, GetOutPutStr("%s%08x%s%s", "Connect", rc, "strErrMsg", strErrMsg).c_str()); rc = ERR_ACCESSAUTH_CONNECT_PINPAD; pPinPad->SafeDelete(); } if (rc != Error_Succeed) return rc; BYTE buf[512]; int nLen = 512; memset(buf, 0, 512); if (!HexStrToByteArray((const char*)ans.ciphertext, buf, &nLen)) { strErrMsg = "加密数据转化十六进制失败"; SetAuthErrMsg((const char *)strErrMsg); m_FSM.doWarnMsg(ERR_ACCESSAUTH_HEX_TO_BYTE, GetOutPutStr("%s%s%s%s", "HexStrToByteArray", "False", "strErrMsg", strErrMsg).c_str()); return ERR_ACCESSAUTH_HEX_TO_BYTE; } enc.Alloc(nLen); memcpy(enc.m_pData, buf, nLen); return Error_Succeed; #endif } // 生成临时SM2密钥对 DWORD CAccessAuthEntity::CreateSM2KeyPair(CBlob &pubKey, CBlob &priKey) { int nPubKeyLen = 256; int nPriKeyLen = 256; pubKey.Alloc(nPubKeyLen); priKey.Alloc(nPriKeyLen); if (!::CreateSM2KeyPair((BYTE*)(pubKey.m_pData), &nPubKeyLen, (BYTE*)(priKey.m_pData), &nPriKeyLen)) { SetAuthErrMsg("创建SM2密钥对失败"); CSmartPointer spFunction = this->GetFunction(); m_FSM.doWarnMsg(ERR_ACCESSAUTH_CREATE_RSA_KEY_PAIR, GetOutPutStr("%s%s","CreateRsaKeyPair","False").c_str(), "创建SM2密钥对失败"); return ERR_ACCESSAUTH_CREATE_RSA_KEY_PAIR; } pubKey.Resize(nPubKeyLen); priKey.Resize(nPriKeyLen); return Error_Succeed; } // 保存到令牌管理实体中 DWORD CAccessAuthEntity::SaveSM2KeyPair(const CBlob &pubKey, const CBlob &priKey) { LOG_FUNCTION(); CSimpleStringA strErrMsg; CSmartPointer spFunction = this->GetFunction(); TokenService_ClientBase *pTokenServiceClient = new TokenService_ClientBase(this); DWORD rc = pTokenServiceClient->Connect(); if (rc != Error_Succeed) { strErrMsg = "连接令牌管理实体失败"; SetAuthErrMsg((const char *)strErrMsg); rc = ERR_ACCESSAUTH_CONNECT_TOKEN_SERVICE; m_FSM.doWarnMsg(rc, GetOutPutStr("%s%08X%s%s", "Connect", rc,"strErrMsg", strErrMsg).c_str()); pTokenServiceClient->SafeDelete(); } else { TokenService_SetKeyPair_Req req; req.pub_key = pubKey; req.pri_key = priKey; TokenService_SetKeyPair_Ans ans; rc = pTokenServiceClient->SetKeyPair(req, ans, DEFUALT_INVOKE_PINPAD_TIMEOUT); pTokenServiceClient->GetFunction()->CloseSession(); if (rc != Error_Succeed) { strErrMsg = "保存密钥对失败"; SetAuthErrMsg((const char *)strErrMsg); rc = ERR_ACCESSAUTH_FROM_TOKEN_SERVICE_SET_KEYS; m_FSM.doWarnMsg(rc, GetOutPutStr("%s%08X%s%s", "SetKeyPair", rc,"strErrMsg", (const char*)strErrMsg).c_str()); } else Dbg("set sm2 key pair succ"); } return rc; } ErrorCodeEnum CAccessAuthEntity::SaveTokenAndSharedSK(const CBlob &token, const CBlob &sharedSK) { LOG_FUNCTION(); CSimpleStringA strErrMsg; CSmartPointer spFunction = this->GetFunction(); TokenService_ClientBase *pTokenServiceClient = new TokenService_ClientBase(this); ErrorCodeEnum rc = pTokenServiceClient->Connect(); if (rc != Error_Succeed) { strErrMsg = "连接令牌管理实体失败"; SetAuthErrMsg((const char *)strErrMsg); m_FSM.doWarnMsg(ERR_ACCESSAUTH_CONNECT_TOKEN_SERVICE, GetOutPutStr("%s%08X%s%s", "Connect", rc,"strErrMsg", (const char*)strErrMsg).c_str()); pTokenServiceClient->SafeDelete(); } else { TokenService_SetToken_Req req = {}; req.token = token; TokenService_SetToken_Ans ans; rc = pTokenServiceClient->SetToken(req, ans, 5000); if (rc == Error_Succeed) Dbg("save token succ, token: [%s]", ByteArrayToHexStr((BYTE*)token.m_pData, token.m_iLength).c_str()); else { strErrMsg = "保存令牌失败"; SetAuthErrMsg((const char *)strErrMsg); m_FSM.doWarnMsg(ERR_ACCESSAUTH_FROM_TOKEN_SERVICE_SET_TOKEN, GetOutPutStr("%s%08X%s%s", "SetToken", rc,"strErrMsg", strErrMsg).c_str()); } TokenService_SetSharedSK_Req req2 = {}; req2.ssk = sharedSK; TokenService_SetSharedSK_Ans ans2 = {}; rc = pTokenServiceClient->SetSharedSK(req2, ans2, 5000); if (rc == Error_Succeed) Dbg("save shared session key succ"); else { strErrMsg = "保存会话密钥失败"; SetAuthErrMsg((const char *)strErrMsg); m_FSM.doWarnMsg(ERR_ACCESSAUTH_FROM_TOKEN_SERVICE_SET_SHAREKEY, GetOutPutStr("%s%08X%s%s", "SetSharedSK", rc,"strErrMsg", (const char*)strErrMsg).c_str()); } pTokenServiceClient->GetFunction()->CloseSession(); } return rc; } bool CAccessAuthEntity::HasPinPad() { CSimpleStringA strErrMsg; CSmartPointer spFunction = this->GetFunction(); //oilyang@20210514 if (!IsMachineTypeConfigurePinPad(m_info.strMachineType)) { Dbg("MachineType[%s], not exist pinpad", m_info.strMachineType); return false; } else if (stricmp(m_info.strMachineType, "RVC.PAD") == 0) // Pad机型 { // 根据PinPad实体状态确定是否连接密码键盘 bool bPinPadExist = false; auto pPinPadClient = new PinPadService_ClientBase(this); if (pPinPadClient->Connect() != Error_Succeed) { Dbg("connect PinPad fail, assume no pinpad"); m_FSM.doWarnMsg(ERR_ACCESSAUTH_CONNECT_PINPAD, GetOutPutStr("%s%s", "连接pinpad错误", "False").c_str()); pPinPadClient->SafeDelete(); } else { PinPadService_GetDevInfo_Req req = {}; PinPadService_GetDevInfo_Ans ans = {}; auto rc = pPinPadClient->GetDevInfo(req, ans, DEFUALT_INVOKE_PINPAD_TIMEOUT); if (rc != Error_Succeed) { strErrMsg = "PinPad::GetDevInfo() fail"; SetAuthErrMsg((const char *)strErrMsg); m_FSM.doWarnMsg(ERR_ACCESSAUTH_FROM_PINPAD, GetOutPutStr("%s%08X", "来自pinpad的错误", rc).c_str(), strErrMsg.GetData()); } else { Dbg("PinPad::GetDevInfo() return state: %d", ans.state); bPinPadExist = ans.state != DEVICE_STATUS_NOT_READY; } pPinPadClient->GetFunction()->CloseSession(); } pPinPadClient = NULL; return bPinPadExist; } else { // 其它VTM机型,全部有内置密码键盘 return true; } } // 1:3des only; 2: sm4 only; 3: both 3des and sm4 // 由当前已初始化的密钥文件决定,兼容旧版本终端 int CAccessAuthEntity::GetPinPadCapability() { int nCapability = 0; if (!IsMachineTypeConfigurePinPad(m_info.strMachineType)) return nCapability; PinPadService_ClientBase *pPinPad = new PinPadService_ClientBase(this); auto rc = pPinPad->Connect(); if (rc == Error_Succeed) { PinPadService_QueryFunc_Req req; PinPadService_QueryFunc_Ans ans; rc = pPinPad->QueryFunc(req,ans, DEFUALT_INVOKE_PINPAD_TIMEOUT); if (rc == Error_Succeed) { nCapability = ans.reserved1; Dbg("QueryFunc from pinpad succ, nCapability[%d]", nCapability); } else { SetAuthErrMsg("从PinPad获取主密钥类型失败"); CSmartPointer spFunction = this->GetFunction(); m_FSM.doWarnMsg(ERR_ACCESSAUTH_FROM_PINPAD, GetOutPutStr("%s%s%s%s", "QueryFunc", "False", "AuthErrMsg", "从PinPad获取主密钥类型失败").c_str()); } pPinPad->GetFunction()->CloseSession(); } else { SetAuthErrMsg("连接PinPad实体失败"); CSmartPointer spFunction = this->GetFunction(); m_FSM.doWarnMsg(ERR_ACCESSAUTH_CONNECT_PINPAD, GetOutPutStr("%s%08X%s%s", "Connect", rc,"AuthErrMsg", "连接PinPad实体失败").c_str()); pPinPad->SafeDelete(); } return nCapability; } void CAccessAuthEntity::printPasswdError(){ string strErrMsg = "密钥集丢失,请重新初始化密钥!"; SetAuthErrMsg(strErrMsg.c_str()); GetFunction()->SetSysVar("AuthErrMsg", strErrMsg.c_str(), true); m_FSM.doWarnMsg( ERROR_ACCESSAUTH_OPENCRYPTCONTEXT, strErrMsg.c_str(),false, strErrMsg); } int Char2Int(char * ch) { int num = 0; for (int i = 0;i < strlen(ch);i++) { num += ((int)(ch[i] - '0')) * pow((float)10, (float)(strlen(ch) - i - 1)); } return num; } bool CAccessAuthEntity::SaveAuthVerAndKey(int nAuthVer, BYTE *pKey) { LOG_FUNCTION(); m_nAuthVersion = nAuthVer; memset(m_AuthSessionKey, 0, 140); if (m_nAuthVersion == 2) { CSimpleString runInfoPath; auto rc = GetFunction()->GetPath("runinfo", runInfoPath); if (rc != Error_Succeed) { Dbg("GetPath runinfo error=%d.", rc); return false; } char privateKey[BUF_SIZE] = { 0 }; runInfoPath += SPLIT_SLASH_STR "runcfg" SPLIT_SLASH_STR "Initializer.ini"; #ifdef RVC_OS_WIN GetPrivateProfileString("TerminalPD", "PrivateKey", "", privateKey, BUF_SIZE, runInfoPath.GetData()); #else Dbg("path ex:%s", runInfoPath.GetData()); char* tmp = inifile_read_str(runInfoPath.GetData(),"TerminalPD", "PrivateKey", ""); strcpy(privateKey, tmp); delete tmp; #endif // RVC_OS_WIN if (strlen(privateKey) <= 0) { printPasswdError(); return false; } Dbg("privateKey=%s,%d", privateKey, strlen(privateKey)); int decodedPrivateKeyLen; char* pDecodedPrivateKey = Hex2Str(privateKey, decodedPrivateKeyLen); Dbg("decodedPrivateKeyLen=%d", decodedPrivateKeyLen); char pDecryptPrivateKey[BUF_SIZE] = { 0 }; int decryprtLen = BUF_SIZE; if (!DecWithSM4_ECB("s5da69gnh4!963@6s5da69gnh4!963@6", (BYTE*)pDecodedPrivateKey, decodedPrivateKeyLen, (BYTE*)pDecryptPrivateKey, &decryprtLen)) { Dbg("DecWithSM4_ECB decrypt privateKey error."); printPasswdError(); delete[] pDecodedPrivateKey; return false; } delete[] pDecodedPrivateKey; //添加调试信息 char * pEncPriKey = Str2Hex((char*)pDecryptPrivateKey, decryprtLen); Dbg("DecWithSM4_ECB succeess.privateKey=%s", pEncPriKey); delete pEncPriKey; char pPlainKey[KEY_SIZE]; int plainKeyLen = KEY_SIZE; char pKeyLen[4] = { 0 }; memcpy(pKeyLen, pKey, 4); int kenLen = Char2Int(pKeyLen); Dbg("kenLen=%d", kenLen); char* pEncodeKey = Str2Hex((char*)pKey,kenLen + 4); Dbg("pEncodeKey=%s", pEncodeKey); delete pEncodeKey; char* key = new char[kenLen + 1]; memset(key, 0, kenLen + 1); memcpy(key, pKey + 4, kenLen); if (!DecWithSM2PriKey((BYTE*)key, kenLen, (BYTE*)pPlainKey, &plainKeyLen, (BYTE*)pDecryptPrivateKey, decryprtLen)) { Dbg("使用私钥解密失败!"); printPasswdError(); return false; } Dbg("使用私钥解密成功"); if (plainKeyLen != KEY_SIZE) { Dbg("私钥解密后的会话密钥长度不等于16!"); } memcpy(m_AuthSessionKey, pPlainKey, KEY_SIZE); } return true; } static BYTE* ConvertHexStrToBytes(const char *pszStr) { if (pszStr == NULL || strlen(pszStr) == 0) return NULL; int nLen = strlen(pszStr) / 2; BYTE *pRet = (BYTE*)malloc(nLen); memset(pRet, 0, nLen); for (int i = 0; i < nLen; i++) { int nTmp(0); if (sscanf(&pszStr[i * 2], "%2X", &nTmp) != 1) { free(pRet); return NULL; } pRet[i] = (BYTE)nTmp; } return pRet; } // 使用准入会话密钥加密 ErrorCodeEnum CAccessAuthEntity::EncryptDataWithSessionKey(const CBlob &raw, CBlob &enc) { LOG_FUNCTION(); assert(m_nAuthVersion ==2); //这里不需要delete,由CBlob析构函数去执行 BYTE* pEncData = new BYTE[1024]; int pEncDataSize = 1024; Dbg("pEncDataSize=%d", pEncDataSize); char* pPlainInfo = Str2Hex((char*)raw.m_pData, raw.m_iLength); Dbg("raw data=%s,raw.m_iLength=%d", pPlainInfo, raw.m_iLength); delete[] pPlainInfo; //char *sessionKey = Str2Hex((char*)m_AuthSessionKey, KEY_SIZE); char sessionKey[KEY_SIZE] = { 0 }; memcpy(sessionKey,m_AuthSessionKey,KEY_SIZE); char* tmpKey = Str2Hex((char*)m_AuthSessionKey, KEY_SIZE); Dbg("sessionKey=%s", tmpKey); delete[] tmpKey; if (!EncWithSM4_ECB((BYTE*)sessionKey, (BYTE*)(raw.m_pData), raw.m_iLength, pEncData, &pEncDataSize)) { Dbg("会话密钥加密准入信息失败!"); return Error_Unexpect; } enc.Attach(pEncData,pEncDataSize); char* tmp = Str2Hex((char*)pEncData, pEncDataSize); Dbg("pEncData=%s,%d", tmp, pEncDataSize); delete[] tmp; tmp = Str2Hex((char*)enc.m_pData, enc.m_iLength); Dbg("EncWithSM4_ECB data=%s,%d", tmp, enc.m_iLength); delete[] tmp; return Error_Succeed; } bool CAccessAuthEntity::GetMD5Hash(const char *pStr, BYTE md5[16]) { return false; } static char* ConvertBytesToHexStr(BYTE *pBuf, int nLen) { char *pRet = (char*)malloc(nLen * 2 + 1); memset(pRet, 0, nLen * 2 + 1); char *p = pRet; for (int i = 0; i < nLen; i++) { BYTE b = pBuf[i]; BYTE l = (b >> 4) & 0x0F; if (l >= 10) *p = l - 10 + 'A'; else *p = l + '0'; p++; BYTE r = b & 0x0F; if (r >= 10) *p = r - 10 + 'A'; else *p = r + '0'; p++; } return pRet; } bool CAccessAuthEntity::GetTerminalFingerPrint(BYTE *pBuf, int &nBufLen) { char szTmp[1024] = {}; string strTmp; int nTmpBufLen = 1024; CSimpleStringA strErrMsg; CSmartPointer spFunction = this->GetFunction(); CSimpleStringA strRet; #ifdef RVC_OS_WIN if (!QueryWMIDevice(Processor, "ProcessorId", szTmp, &nTmpBufLen)) #else CSimpleStringA runInfoPath; auto rc = GetFunction()->GetPath("runinfo", runInfoPath); if (rc != Error_Succeed) { Dbg("GetPath runinfo error=%d.", rc); return false; } runInfoPath += SPLIT_SLASH_STR "runcfg"; if (!get_cpu_id_by_system(strTmp, runInfoPath.GetData())) #endif // RVC_OS_WIN { strErrMsg = CSimpleStringA::Format("查询CPU ID失败,请重启机器并重新初始化"); SetAuthErrMsg((const char *)strErrMsg); m_FSM.doWarnMsg(ERR_ACCESSAUTH_GET_TERMINAL_FINGERPRINT, GetOutPutStr("%s%s", "Processor", "False").c_str()); return false; } #ifdef RVC_OS_WIN strRet = szTmp; nTmpBufLen = 1024; memset(szTmp, 0, sizeof(szTmp)); if (!QueryWMIDevice(BaseBoard, "SerialNumber", szTmp, &nTmpBufLen)) #else Dbg("cpu id: %s", strTmp.c_str()); strRet = strTmp.c_str(); strTmp.clear(); if (!get_board_serial_by_system(strTmp, runInfoPath.GetData())) #endif // RVC_OS_WIN { strErrMsg = CSimpleStringA::Format("查询主板序列号失败, 请重启机器并重新初始化"); SetAuthErrMsg((const char *)strErrMsg); m_FSM.doWarnMsg(ERR_ACCESSAUTH_GET_TERMINAL_FINGERPRINT, GetOutPutStr("%s%s", "BaseBoard", "False").c_str()); return false; } strRet += "|"; #ifdef RVC_OS_WIN strRet += szTmp; nTmpBufLen = 1024; memset(szTmp, 0, sizeof(szTmp)); if (!QueryWMIDevice(DiskDrive, "SerialNumber", szTmp, &nTmpBufLen)) #else Dbg("baseboard sn: %s", strTmp.c_str()); strRet += strTmp.c_str(); vector disk; int errCode = 0; if (!get_disk_serial_by_system(disk, errCode, runInfoPath.GetData())) #endif // RVC_OS_WIN { Dbg("get_disk_serial_by_system errCode:%d", errCode); strErrMsg = CSimpleStringA::Format("查询磁盘序列号失败, 请重启机器并重新初始化"); SetAuthErrMsg((const char*)strErrMsg); m_FSM.doWarnMsg(ERR_INITIALIZER_GET_DISKDRIVE_ID, GetOutPutStr("%s%s", "DiskDrive", "False").c_str()); return false; } strRet += "|"; #ifdef RVC_OS_WIN strRet += szTmp; #else strTmp = ""; vector::iterator it = disk.begin(); while (it != disk.end()) { strTmp += *it; it++; } Dbg("harddisk sn: %s", strTmp.c_str()); strRet += strTmp.c_str(); #endif // RVC_OS_WIN Dbg("device info: [%s]", (const char*)strRet); BYTE sm3[32] = { 0 }; if(!SM3Hash(reinterpret_cast(const_cast(strRet.GetData())),strRet.GetLength(),sm3)) { strErrMsg = "get sm3 hash as fingerprint fail"; SetAuthErrMsg((const char *)strErrMsg); spFunction->SetSysVar("AuthErrMsg", (const char *)strErrMsg, true); m_FSM.doWarnMsg(ERROR_ACCESSAUTH_GETSM3HASH, (const char *)strErrMsg); return false; } if (nBufLen < 32) { //Dbg("buf len is too small"); m_FSM.doWarnMsg(ERROR_ACCESSAUTH_GETSM3HASH, "buf len is too small fail"); return false; } nBufLen = 32; memcpy(pBuf, sm3, nBufLen); char *pszSM3 = ConvertBytesToHexStr(sm3, nBufLen); Dbg("fringerprint: [%s]", pszSM3); free(pszSM3); return true; } // 生成SM2密钥对,并导出公钥 bool CAccessAuthEntity::GetTerminalPublicKey(BYTE *pBuf, int &nBufLen) { CSimpleString runInfoPath; auto rc = GetFunction()->GetPath("runinfo", runInfoPath); if (rc != Error_Succeed) { Dbg("GetPath runinfo error=%d.", rc); return false; } runInfoPath += SPLIT_SLASH_STR "runcfg" SPLIT_SLASH_STR "Initializer.ini"; char publicKey[BUF_SIZE] = { 0 }; #ifdef RVC_OS_WIN GetPrivateProfileString("TerminalPD", "PublicKey", "", publicKey, BUF_SIZE, runInfoPath.GetData()); #else char* tmp = inifile_read_str(runInfoPath.GetData(), "TerminalPD", "PublicKey", ""); strcpy(publicKey, tmp); delete tmp; #endif // RVC_OS_WIN if (strlen(publicKey) <= 0) { Dbg("读取公钥失败,公钥长度小于等于零!"); printPasswdError(); return false; } Dbg("publickey=%s,%d",publicKey,strlen(publicKey)); char* pDecodedPublickey = Hex2Str(publicKey,nBufLen); Dbg("pDecodedPublickey=[%s],len=%d", pDecodedPublickey, nBufLen); memcpy(pBuf, pDecodedPublickey, nBufLen); Dbg("pBuf[0]=%02X,nBufLen=%d", pBuf[0], nBufLen); delete[] pDecodedPublickey; return true; } DWORD CAccessAuthEntity::InitDevice(SpReqAnsContext::Pointer &ctx) { return m_FSM.InitDevice(ctx); } //oilyang@20210510 嵌入"bool CAccessAuthEntity::HasPinPad()"的逻辑 // 返回1:只有PinPadID;2:只有DeviceID;3:两者都有;0:没有;-1表示失败 int CAccessAuthEntity::GetPinPadIDAndDeviceID(CSimpleStringA &strPinPadID, CSimpleStringA &strDeviceID, bool& bHasPinPad) { bHasPinPad = false; CSimpleStringA strErrMsg; CSmartPointer spFunction = this->GetFunction(); //oilyang@20210514 if (!IsMachineTypeConfigurePinPad(m_info.strMachineType)) return 0; int nRet = -1; auto pPinPadClient = new PinPadService_ClientBase(this); bool bPinPadID = false; bool bDeviceID = false; bool bVendor = false; bool bBluetooth = false; CSimpleStringA strVendor; CSimpleStringA strBluetoothID; CSimpleStringA strPID; CSimpleStringA strMID; bHasPinPad = true; auto rc = 0; if ( (rc = pPinPadClient->Connect()) == Error_Succeed) { PinPadService_GetDevInfo_Req req = {}; PinPadService_GetDevInfo_Ans ans = {}; rc = pPinPadClient->GetDevInfo(req, ans, DEFUALT_INVOKE_PINPAD_TIMEOUT); if (rc == Error_Succeed) { if (ans.state == DEVICE_STATUS_NORMAL) { nRet = 0; Dbg("pinpad model: %s", (const char*)ans.model); // CM = V2.0#PM = V1.0#MID = 75500001#PID = 12345678#FWID = V1234567#Vendor = nantian // 密码键盘ID,PID,8到16字节; 设备ID,MID,8到16字节; 固件版本号,FWID,8字节 CSimpleStringA str = ans.model; if (!str.IsNullOrEmpty()) { auto arr = str.Split('#'); if (arr.GetCount() > 0) { for (int i = 0; i < arr.GetCount(); i++) { auto arr2 = arr[i].Split('='); if (arr2.GetCount() != 2) continue; //if (arr2[0] == "PID") if(!strnicmp((LPCTSTR)arr2[0], "PID", strlen("PID"))) { strPID = arr2[1]; if (!strPID.IsNullOrEmpty()) bPinPadID = true; } //else if (arr2[0] == "MID") else if(!strnicmp((LPCTSTR)arr2[0], "MID", strlen("MID"))) { strMID = arr2[1]; if (!strMID.IsNullOrEmpty()) bDeviceID = true; } //else if (arr2[0] == "Vendor") else if(!strnicmp((LPCTSTR)arr2[0], "Vendor", strlen("Vendor"))) { strVendor = arr2[1]; if (!strVendor.IsNullOrEmpty()) bVendor = true; } else if (!strnicmp((LPCTSTR)arr2[0], "FWBID", strlen("FWBID"))) { strBluetoothID = arr2[1]; Dbg("strBluetoothID=%s", strBluetoothID); if (!strBluetoothID.IsNullOrEmpty()) bBluetooth = true; } } } } } else { if (m_info.strMachineType.IsStartWith("RVC.PAD", true)) bHasPinPad = false; Dbg("pinpad not exist, state: %d", ans.state); } } else { if (m_info.strMachineType.IsStartWith("RVC.PAD", true)) bHasPinPad = false; strErrMsg = "调用PinPad实体的GetDevInfo方法失败"; SetAuthErrMsg((const char *)strErrMsg); m_FSM.doWarnMsg(ERR_ACCESSAUTH_FROM_PINPAD, GetOutPutStr("%s%08X%s%s", "GetDevInfo", rc, "strErrMsg", (const char*)strErrMsg ).c_str()); } pPinPadClient->GetFunction()->CloseSession(); } else { if (m_info.strMachineType.IsStartWith("RVC.PAD", true)) bHasPinPad = false; strErrMsg = "连接PinPad实体失败"; SetAuthErrMsg((const char *)strErrMsg); m_FSM.doWarnMsg(ERR_ACCESSAUTH_CONNECT_PINPAD, GetOutPutStr("%s%08X%s%s", "Connect", rc, "strErrMsg", "连接PinPad实体失败").c_str()); pPinPadClient->SafeDelete(); } pPinPadClient = NULL; if (bPinPadID) { if (bVendor) strPinPadID = strVendor + "_" + strPID; else strPinPadID = strPID; nRet += 1; } if (bDeviceID) { if (bVendor) strDeviceID = strVendor + "_" + strMID; else strDeviceID = strMID; if (bBluetooth) strDeviceID = strDeviceID + "_" + strBluetoothID; nRet += 2; } else if (bBluetooth) { strDeviceID = strDeviceID + "_" + strBluetoothID; nRet += 2; } return nRet; } bool CAccessAuthEntity::HasCkCodeFlg() { CSimpleStringA strErrMsg; CSmartPointer spFunction = this->GetFunction(); //oilyang@20210514 if (!IsMachineTypeConfigurePinPad(m_info.strMachineType)) { Dbg("MachineType is [%s], not exist pinpad entity", m_info.strMachineType); return false; } auto pPinPadClient = new PinPadService_ClientBase(this); bool bCheckCode = false; CSimpleStringA strSpeficiCM; if (pPinPadClient->Connect() == Error_Succeed) { PinPadService_GetDevInfo_Req req = {}; PinPadService_GetDevInfo_Ans ans = {}; auto rc = pPinPadClient->GetDevInfo(req, ans, DEFUALT_INVOKE_PINPAD_TIMEOUT); if (rc == Error_Succeed) { if (ans.state == DEVICE_STATUS_NORMAL) { Dbg("pinpad model: %s", (const char*)ans.model); // CM = V2.0#PM = V1.0#MID = 75500001#PID = 12345678#FWID = V1234567#Vendor = nantian // 密码键盘ID,PID,8到16字节; 设备ID,MID,8到16字节; 固件版本号,FWID,8字节 CSimpleStringA str = ans.model; if (!str.IsNullOrEmpty()) { auto arr = str.Split('#'); if (arr.GetCount() > 0) { for (int i = 0; i < arr.GetCount(); i++) { auto arr2 = arr[i].Split('='); if (arr2.GetCount() != 2) continue; if(!strnicmp((LPCTSTR)arr2[0], "CM", strlen("CM"))) { strSpeficiCM = arr2[1]; if (strSpeficiCM.GetLength() > 3 && _strnicmp(strSpeficiCM, "V2.0", strlen("V2.0")) == 0) { //Support checkcode, then operate checkcode routine.. bCheckCode = true; } } } } } } else { Dbg("pinpad not exist, state: %d", ans.state); m_FSM.doWarnMsg(ERR_ACCESSAUTH_FROM_PINPAD, GetOutPutStr("%s%d", "密码键盘异常,请检查。ans.state", ans.state).c_str()); } } else { strErrMsg = "调用PinPad实体(GetDevInfo)失败"; SetAuthErrMsg((const char *)strErrMsg); m_FSM.doWarnMsg(ERR_ACCESSAUTH_FROM_PINPAD, GetOutPutStr("%s%08X", "GetDevInfo", rc).c_str(), strErrMsg.GetData()); } pPinPadClient->GetFunction()->CloseSession(); } else { strErrMsg = "连接PinPad实体失败"; SetAuthErrMsg((const char *)strErrMsg); m_FSM.doWarnMsg(ERR_ACCESSAUTH_CONNECT_PINPAD, GetOutPutStr("%s%s", "连接pinpad错误, strErrMsg", strErrMsg).c_str()); pPinPadClient->SafeDelete(); } pPinPadClient = NULL; return bCheckCode? true:false; } wstring CAccessAuthEntity::ANSIToUnicode(const string& str) { int len = 0; len = str.length(); int unicodeLen = ::MultiByteToWideChar(CP_ACP, 0, str.c_str(), -1, NULL, 0); wchar_t * pUnicode; pUnicode = new wchar_t[unicodeLen+1]; memset(pUnicode,0,(unicodeLen+1)*sizeof(wchar_t)); ::MultiByteToWideChar( CP_ACP, 0, str.c_str(), -1, (LPWSTR)pUnicode, unicodeLen); wstring rt; rt = (wchar_t*)pUnicode; delete pUnicode; return rt; } //China Standard Time BOOL CAccessAuthEntity::SetLocalTimeZoneByKeyName(const TCHAR* szTimeZoneKeyName, BOOL isDaylightSavingTime) { #ifdef RVC_OS_WIN HKEY hKey; LONG ErrorCode; TCHAR szSubKey[256]; TCHAR szStandardName[32]; TCHAR szDaylightName[32]; REG_TZI_FORMAT regTZI; DWORD dwByteLen; // 检测入口参数 if ((szTimeZoneKeyName == NULL) || (strlen(szTimeZoneKeyName) == 0)) { // 时区标识符不能为空 return FALSE; } StringCchCopy(szSubKey, 256, TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones\\")); StringCchCat(szSubKey, 256, szTimeZoneKeyName); ErrorCode = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szSubKey, 0, KEY_QUERY_VALUE, &hKey); if (ErrorCode != ERROR_SUCCESS) { Dbg("RegOpenKeyEx Software\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones\\China Standard Time fail"); return FALSE; } // 标准名 dwByteLen = sizeof(szStandardName); ErrorCode = RegQueryValueEx(hKey, TEXT("Std"), NULL, NULL, reinterpret_cast(&szStandardName), &dwByteLen); if (ErrorCode != ERROR_SUCCESS) { RegCloseKey(hKey); Dbg("RegQueryValueEx Software\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones\\China Standard Time\\Std fail"); return FALSE; } // 夏时制名 dwByteLen = sizeof(szDaylightName); ErrorCode = RegQueryValueEx(hKey, TEXT("Dlt"), NULL, NULL, reinterpret_cast(&szDaylightName), &dwByteLen); if (ErrorCode != ERROR_SUCCESS) { RegCloseKey(hKey); Dbg("RegQueryValueEx Software\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones\\China Standard Time\\Dlt fail"); return FALSE; } // 时区信息 dwByteLen = sizeof(regTZI); ErrorCode = RegQueryValueEx(hKey, TEXT("TZI"), NULL, NULL, reinterpret_cast(®TZI), &dwByteLen); RegCloseKey(hKey); if ((ErrorCode != ERROR_SUCCESS) || (dwByteLen > sizeof(regTZI))) { Dbg("RegQueryValueEx Software\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones\\China Standard Time\\TZI fail"); return FALSE; } // 开启权限 HANDLE hToken; TOKEN_PRIVILEGES tkp; BOOL isOK; if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY, &hToken)) { Dbg("OpenProcessToken Standard Time\\Dlt fail"); return FALSE; } LookupPrivilegeValue(NULL, SE_TIME_ZONE_NAME, &tkp.Privileges[0].Luid); tkp.PrivilegeCount = 1; tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES)NULL, 0); if (GetLastError() != ERROR_SUCCESS) { CloseHandle(hToken); Dbg("AdjustTokenPrivileges fail"); return FALSE; } // 设置新时区 DYNAMIC_TIME_ZONE_INFORMATION tzi; tzi.Bias = regTZI.Bias; tzi.StandardDate = regTZI.StandardDate; tzi.StandardBias = regTZI.StandardBias; tzi.DaylightDate = regTZI.DaylightDate; tzi.DaylightBias = regTZI.DaylightBias; tzi.DynamicDaylightTimeDisabled = !isDaylightSavingTime; wcscpy(tzi.StandardName, ANSIToUnicode(szStandardName).c_str()); wcscpy(tzi.DaylightName, ANSIToUnicode(szDaylightName).c_str()); wcscpy(tzi.TimeZoneKeyName, ANSIToUnicode(szTimeZoneKeyName).c_str()); isOK = SetDynamicTimeZoneInformation(&tzi); // 设置动态时区 if (!isOK) { Dbg("SetDynamicTimeZoneInformation fail"); } // 关闭权限 tkp.Privileges[0].Attributes = 0; AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES)NULL, 0); CloseHandle(hToken); return isOK; #else //temporarily not relased at linux return TRUE; #endif // RVC_OS_WIN } int CAccessAuthEntity::ConvertStr2Byte(string input, BYTE* output, int outputLen) { if (input.size() > outputLen) return 1; for (int i = 0;i < input.size();i++) { output[i] = input[i]; } return 0; } int CAccessAuthEntity::GetOrSetIsFirstSM(int type) { CSmartPointer pConfig; int isFirst = 0; auto rc = GetFunction()->OpenConfig(Config_Run, pConfig); if (rc != Error_Succeed) { Dbg("OpenConfig Config_Run error=%d.", rc); return isFirst; } CSimpleStringA sIsFirst; if (type == 0) { return 0;//oilyang@20211208 这个逻辑没有存在的必要了 rc = pConfig->ReadConfigValue("SM", "IsFirst", sIsFirst); if (rc != Error_Succeed || sIsFirst.IsNullOrEmpty()) { rc = pConfig->WriteConfigValue("SM", "IsFirst", "Yes"); if (rc != Error_Succeed) { Dbg("WriteConfigValue Config_Run SM IsFirst error."); return isFirst; } isFirst = 1; } else if (sIsFirst == "Yes") { isFirst = 1; } else isFirst = 0; return isFirst; } else { rc = pConfig->WriteConfigValue("SM", "IsFirst", "No"); if (rc != Error_Succeed) { Dbg("WriteConfigValue Config_Run SM IsFirst error."); return isFirst; } else { isFirst = 1; } return isFirst; } } bool CAccessAuthEntity::IsMachineTypeConfigurePinPad(CSimpleStringA strMachineType) { // 回单打印机、卡库、简化版 if (strMachineType.IsStartWith("RPM", true) || strMachineType.IsStartWith("RVC.CardStore", true) || strMachineType.IsStartWith("RVC.IL", true)) { return false; } else return true; } SP_BEGIN_ENTITY_MAP() SP_ENTITY(CAccessAuthEntity) SP_END_ENTITY_MAP()