#include "SpSecureClient.h" #include "sp_cfg.h" #include "sp_env.h" #include "spShareMemoryBase.h" #include "toolkit.h" #include "dbgutil.h" #ifdef RVC_OS_WIN #include "IHttpFunc.h" #include "sp_checkEntity.h" #include "SpEntity.h" #endif #include #include "TokenKeeper_client_g.h" using namespace TokenKeeper; #define TAG RVCCOMM_TAG("SecureClient") CEntityBase* SpSecureClient::m_pEntity = NULL; void getHttpToken(std::string &channelId, std::string &token, std::string &terminalNo, std::string &reserve1) { CSimpleString t_channelId, t_token; CSystemStaticInfo info; if (SpSecureClient::m_pEntity == NULL || SpSecureClient::m_pEntity->GetFunction()->GetToken(t_channelId, t_token) != ErrorCodeEnum::Error_Succeed || SpSecureClient::m_pEntity->GetFunction()->GetSystemStaticInfo(info) != ErrorCodeEnum::Error_Succeed) return; if(t_channelId.GetLength() != 0 && t_token.GetLength() != 0 && info.strTerminalID.GetLength() != 0) { channelId = t_channelId.GetData(); token = t_token.GetData(); terminalNo = info.strTerminalID.GetData(); } } enum CommEventEnum { //连接主用地址 事件 1 0xNNN08001 连接配置文件定义的主用地址,需要记录地址信息。如果为短连接,记录首次连接事件。 CE_ConnectMasterServer = 0x00008001, //连接备用地址 事件 1 0xNNN08002 如果没有定义备用地址,就不会有这条信息 CE_ConnectSlaveServer = 0x00008002, //主动断开连接 事件 1 0xNNN08011 如果为短连接,无需记录此事件 CE_ActiveClose = 0x00008011, //读取配置失败 错误 3 0xNNN08021 不能读到需要配置项,代码或配置有误,可以切换备份区域,或需要人干预 CE_ReadCfgFail = 0x00008021, //连接地址无效 错误 2 0xNNN88031 对端不存在,配置错误,或当前服务器故障 CE_InvalidAddr = 0x00088031, //对端拒绝连接 错误 2 0xNNN88032 对端存在,但可能故障,导致服务器拒绝建立连接 CE_PeerReject = 0x00088032, //连接超时 错误 2 0xNNN88033 等待连接超时 CE_ConnectTimeout = 0x00088033, //容量拒绝 错误 2 0xNNN88034 由于达到后台的最大容量,连接拒绝,需要重试 CE_ReachMaxNum = 0x00088034, //服务暂停 错误 2 0xNNN88035 后台暂停服务,实体可以切换主备服务或抛出连接失败,切换备份区域 CE_OutOfService = 0x00088035, //失去连接 错误 2 0xNNN88036 由于对端或网络原因连接断开 CE_LostConnection = 0x00088036, //无效请求包 错误 3 0xNNN88041 实体或后台代码错误,需要进行人工修复。在描述中应该说明错误的原因。 CE_InvalidReqPack = 0x00088041, //鉴权不可识别 错误 3 0xNNN88051 由于服务准入服务证书不符,不能解开请求包,错误需要干预,不能自动修复。 CE_AuthFailed = 0x00088051, //鉴权信息不匹配 错误 2 0xNNN88052 请求时鉴权信息不匹配,需要重新进行准入。 CE_HashMismatch = 0x00088052, //当前区域连接失败 事件 2 0xNNN880F1 由于多次尝试失败,或发生不可尝试错误,实体放弃了当前区域连接尝试,用于驱动状态切换。记录区域代码。 CE_CurRegionDisabled = 0x000880F1, }; void* SpSecureClient::logProducer(NULL); void SpSecureClient::DbgWithLink_DualActive(const char* formatStr, ...) { if (formatStr == nullptr) return; va_list arg; va_start(arg, formatStr); //不这么写?貌似到DbgWithLink内后,arg会被析构? int n = _vscprintf(formatStr, arg) + 1; std::vector buf(n + 1, '\0'); vsnprintf(&buf[0], n, formatStr, arg); DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__).withLogProducer(logProducer).withExtendLog(false)(&buf[0]); if(EntityResource::getSaveFile()) m_log.LOGERROR(&buf[0]); va_end(arg); } // 不应该直接delete,而用DecRef() SpSecureClient::~SpSecureClient() { //this would lost the process at UOS plat. //#ifndef _WIN32 // if (logProducer != NULL) { // destroy_log_producer_storage(logProducer); // logProducer = NULL; // } //#endif } SpSecureClient::SpSecureClient(CEntityBase *pEntityBase) : m_bClosed(true) { m_pEntity = pEntityBase; if(logProducer == NULL) { logProducer = create_log_producer_storage("DualActive", "0", "", "", ""); } } std::pair FromAddressToIP(std::string host) { struct hostent* ht = NULL; ht = gethostbyname(host.c_str()); if (ht) { for (int i = 0; ; i++) { if (ht->h_addr_list[i] != NULL) return std::make_pair(true, inet_ntoa(*((struct in_addr*)ht->h_addr_list[i]))); else break; } for (int j = 0; ; j++) { if (ht->h_aliases[j] != NULL) return std::make_pair(true, ht->h_aliases[j]); else break; } } return std::make_pair(false, ""); } bool SpSecureClient::Connect(const char *pServerAddr, int nPort, int nOption) // wait until all authentication operation has been finished { TOOLKIT_ASSERT(m_pEntity != NULL); auto ipRet = FromAddressToIP(pServerAddr); std::string dstIp = ipRet.first ? ipRet.second : pServerAddr; bool result = false; if (GetFunction()->Connect(dstIp.c_str(), nPort, nOption)) { m_bClosed = false; result = true; } else { DbgWithLink_DualActive("connect to %s:%d, option=%d, result:%s", dstIp.c_str(), nPort, nOption, result ? "SUCCESS" : "FAIL"); result = false; } return result; } // 使用配置项连接, 连接参数从实体配置文件中读取 [Main]/Server和[Main]/Server_Backup项 // @option:1、重新鉴权新建会话密钥;2、通过握手使用缓存会话密钥; // 3、不使用会话密钥,即非安全通道; 4、不协商,直接使用共享会话密钥 bool SpSecureClient::ConnectFromConfig(int nOption) { DbgWithLink_DualActive("ConnectFromConfig has been deprecated."); return false; if (IsConnectionOK()) return true; const char* pEntityName = m_pEntity->GetEntityName(); ENTITY_CONNECT_INFO connectInfo; if (!readConnectInfoFromConfig(pEntityName, &connectInfo)) { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("Read %s Info Failed", pEntityName); return false; } // 判断当前是否已经准入,已准入时强制使用加密通道 int nActOption = nOption; CSimpleStringA strVal; const ErrorCodeEnum result = m_pEntity->GetFunction()->GetSysVar("EntryPermit", strVal); if (Error_Succeed == result) { if (strVal == "L" && stricmp(pEntityName, "AccessAuthorization") != 0 && stricmp(pEntityName, "Initializer") != 0) nActOption = 2; // 优先使用缓存密钥 } if (1 == connectInfo.m_DualActive) return Connect_Dual(&connectInfo, nOption); else return Connect_Single(&connectInfo, nOption); } bool SpSecureClient::readConnectInfoFromConfig(const char *pEntityName, ENTITY_CONNECT_INFO *connectInfo) { if (NULL == pEntityName || NULL == connectInfo) return false; connectControl *entityConnect = connectControl::getInstance(); bool readSuccess = entityConnect->getEntityInfo(pEntityName, connectInfo); auto pFunc = m_pEntity->GetFunction(); CSmartPointer spConfig; if (Error_Succeed != pFunc->OpenConfig(Config_CenterSetting, spConfig)) { //DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("open center setting config fail"); return false; } CSimpleStringA str; int readEach = 0; if (Error_Succeed == spConfig->ReadConfigValue("SpBase", "ReadEach", str) && !str.IsNullOrEmpty()) readEach = atoi(str); if (0 == readEach && readSuccess) return true;//不是每次都读取新的Entity的IP和Port,只在实体启动时读取一次 int dualActive = -1; if (Error_Succeed == spConfig->ReadConfigValue("SpBase", "DualActive", str) && !str.IsNullOrEmpty()) dualActive = atoi(str); if (Error_Succeed != pFunc->OpenConfig(Config_Software, spConfig)) { //DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("open entity config fail"); return false; } if (Error_Succeed != spConfig->ReadConfigValue("Main", "Server", str) || str.IsNullOrEmpty()) { //DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("read Main::Server config fail"); return false; } CSimpleStringA strServer1; int nServer1Port; if (Error_Succeed != ParseIPAddress(str, strServer1, nServer1Port)) { //DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("parse ip addr fail: %s", (const char*)str); return false; } CSimpleStringA strServer2; int nServer2Port = 0; if (Error_Succeed == spConfig->ReadConfigValue("Main", "Server_Backup", str) && !str.IsNullOrEmpty()) ParseIPAddress(str, strServer2, nServer2Port); if (readSuccess) connectInfo->setParam(pEntityName, strServer1.GetData(), nServer1Port, strServer2.GetData(), nServer2Port, dualActive, connectInfo->m_currentLink); else { connectInfo->clear(); connectInfo->setParam(pEntityName, strServer1.GetData(), nServer1Port, strServer2.GetData(), nServer2Port, dualActive); } entityConnect->setEntityInfo(connectInfo); return true; } void SpSecureClient::connectClose(const char *pEntityName) { if (NULL == pEntityName) return; ENTITY_CONNECT_INFO connectInfo; if (!findConnectInfo(pEntityName, &connectInfo)) { DbgWithLink_DualActive("can not find %s in connection list.", pEntityName); return; } connectInfo.m_currentLink = -1; } bool SpSecureClient::findConnectInfo(const char *pEntityName, ENTITY_CONNECT_INFO *connectInfo) { if (NULL == pEntityName || NULL == connectInfo) return false; connectControl *entityConnect = connectControl::getInstance(); if (entityConnect->getEntityInfo(pEntityName, connectInfo)) return true; return false; } bool SpSecureClient::readConnectInfoFromCentralSetting(const char *pEntityName, ENTITY_CONNECT_INFO *connectInfo) { if (NULL == pEntityName || NULL == connectInfo) return false; connectControl *entityConnect = connectControl::getInstance(); bool readSuccess = entityConnect->getEntityInfo(pEntityName, connectInfo); //获得集中配置信息 auto pFunc = m_pEntity->GetFunction(); CSmartPointer spConfig; if (Error_Succeed != pFunc->OpenConfig(Config_CenterSetting, spConfig)) { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("open center setting config fail"); return false; } CSimpleStringA str; int readEach = 1; if (Error_Succeed == spConfig->ReadConfigValue("SpBase", "ReadEach", str) && !str.IsNullOrEmpty()) readEach = atoi(str); if (0 == readEach && readSuccess) return true;//不是每次都读取新的Entity的IP和Port,只在实体启动时读取一次 ErrorCodeEnum configRc = Error_Bug; if (Error_Succeed != (configRc = spConfig->ReadConfigValue(pEntityName, "Server", str)) || str.IsNullOrEmpty()) { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("read Main::Server config fail, %d, %s", configRc, pEntityName); return false; } CSimpleStringA strServer1; int nServer1Port; if (Error_Succeed != (configRc = ParseIPAddress(str, strServer1, nServer1Port))) { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("parse ip addr fail: %s, %d", (const char*)str, configRc); return false; } CSimpleStringA strServer2 = ""; int nServer2Port = 0; if (Error_Succeed == spConfig->ReadConfigValue(pEntityName, "Server_Backup", str) && !str.IsNullOrEmpty()) ParseIPAddress(str, strServer2, nServer2Port); int dualActive = -1; if (Error_Succeed == spConfig->ReadConfigValue("SpBase", "DualActive", str) && !str.IsNullOrEmpty()) dualActive = atoi(str); if (readSuccess) connectInfo->setParam(pEntityName, strServer1.GetData(), nServer1Port, strServer2.GetData(), nServer2Port, dualActive, connectInfo->m_currentLink); else { //DbgWithLink_DualActive("call clear"); connectInfo->clear(); connectInfo->setParam(pEntityName, strServer1.GetData(), nServer1Port, strServer2.GetData(), nServer2Port, dualActive); } entityConnect->setEntityInfo(connectInfo); return true; } bool SpSecureClient::setConnectInfo(const ENTITY_CONNECT_INFO *connectInfo) { if (NULL == connectInfo) return false; connectControl *entityConnect = connectControl::getInstance(); entityConnect->setLastLink(connectInfo->m_currentLink); return entityConnect->setEntityInfo(connectInfo); } // 使用集中配置项连接 bool SpSecureClient::ConnectFromCentralSetting() { #ifdef RVC_OS_WIN SetthreadGroup(GetCurrentThreadId(), m_pEntity->GetEntityName()); #endif // RVC_OS_WIN if (IsConnectionOK()) return true; const char* pEntityName = m_pEntity->GetEntityName(); ENTITY_CONNECT_INFO connectInfo; if (!readConnectInfoFromCentralSetting(pEntityName, &connectInfo)) { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("Read %s Info Failed", pEntityName); DbgWithLink_DualActive("Read %s Info Failed", pEntityName); return false; } // 判断当前是否已经准入,已经准入则强制使用安全连接 int nOption = 3; CSimpleStringA strVal; if (Error_Succeed == m_pEntity->GetFunction()->GetSysVar("EntryPermit", strVal)) { if (strVal == "L" && stricmp(pEntityName, "AccessAuthorization") != 0 && stricmp(pEntityName, "Initializer") != 0) nOption = 2; // 优先使用缓存密钥 } if (1 == connectInfo.m_DualActive) return Connect_Dual(&connectInfo, nOption); else return Connect_Single(&connectInfo, nOption); } int SpSecureClient::getCurrentLink() { if (!IsConnectionOK()) return -1; const char* pEntityName = m_pEntity->GetEntityName(); ENTITY_CONNECT_INFO connectInfo; if (!readConnectInfoFromCentralSetting(pEntityName, &connectInfo)) { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("Read %s Info Failed", pEntityName); return -1; } return connectInfo.m_currentLink; } bool SpSecureClient::Connect_Single(ENTITY_CONNECT_INFO *connectInfo, int option) { if (NULL == connectInfo || 0 == strlen(connectInfo->m_EntityName)) return false; //DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("mod %s using option %d", connectInfo->m_EntityName, option); DbgWithLink_DualActive("mod %s using option %d", connectInfo->m_EntityName, option); if (Connect(connectInfo->m_ServerIP, connectInfo->m_ServerPort, option)) connectInfo->m_currentLink = 0; else if (0 != strlen(connectInfo->m_Server_BackupIP) && strcmp(connectInfo->m_ServerIP, connectInfo->m_Server_BackupIP) && Connect(connectInfo->m_Server_BackupIP, connectInfo->m_Server_BackupPort, option)) connectInfo->m_currentLink = 1; else connectInfo->m_currentLink = -1; setConnectInfo(connectInfo); DbgWithLink_DualActive("Single Connection: EntityName:%s, server:%s %d, serverBackup:%s %d, DualOpen: %d, currentLink:%d", connectInfo->m_EntityName, connectInfo->m_ServerIP, connectInfo->m_ServerPort, connectInfo->m_Server_BackupIP, connectInfo->m_Server_BackupPort, connectInfo->m_DualActive, connectInfo->m_currentLink); return -1 != connectInfo->m_currentLink; } bool SpSecureClient::Connect_Dual(ENTITY_CONNECT_INFO *connectInfo, int option) { if (NULL == connectInfo || 0 == strlen(connectInfo->m_EntityName)) return false; connectControl *entityConnect = connectControl::getInstance(); bool quickConnect = false; const int priorLink = entityConnect->getPriorLink(connectInfo->m_lastLink); if (-1 != priorLink) { /* 根据上次双活成功时的server进行连接 */ if (0 == priorLink && 0 != strlen(connectInfo->m_ServerIP)) { connectInfo->m_currentLink = (Connect(connectInfo->m_ServerIP, connectInfo->m_ServerPort, option) ? 0 : -1); } else if (1 == priorLink && 0 != strlen(connectInfo->m_Server_BackupIP)) { connectInfo->m_currentLink = (Connect(connectInfo->m_Server_BackupIP, connectInfo->m_Server_BackupPort, option) ? 1 : -1); } quickConnect = (-1 == connectInfo->m_currentLink ? false : true); } if (!IsConnectionOK()) { /* 根据终端号进行连接 */ //获取终端号,判断优先连接的IP和端口 auto pFunc = m_pEntity->GetFunction(); CSmartPointer spConfig; auto rc = pFunc->OpenConfig(Config_Root, spConfig); if (rc != Error_Succeed) { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("read root.ini Fail: %s", SpStrError(rc)); return false; } CSimpleStringA strValue; spConfig->ReadConfigValue("Terminal", "TerminalNo", strValue); bool isMainServer = true; if (strValue.GetLength() > 0) { char str[20] = ""; sprintf(str, "%s", (const char*)strValue); const int f = (str[strlen(str) - 1] - '0'); isMainServer = (0 == (f % 2)); DbgWithLink_DualActive("TerminalNo: %s, lastByte: %d, MainServer:%d", str, f, isMainServer); } DbgWithLink_DualActive("mod %s using option %d", connectInfo->m_EntityName, option); if (0 == strlen(connectInfo->m_Server_BackupIP) && 0 == strlen(connectInfo->m_ServerIP)) { connectInfo->m_currentLink = -1; } else if (0 == strlen(connectInfo->m_Server_BackupIP)) {//serverBackup Ip and port error, link to server connectInfo->m_currentLink = (Connect(connectInfo->m_ServerIP, connectInfo->m_ServerPort, option) ? 0 : -1);//Link to first one DbgWithLink_DualActive("%s serverBackup param error", connectInfo->m_EntityName); } else { if (isMainServer) {//link to first server if (Connect(connectInfo->m_ServerIP, connectInfo->m_ServerPort, option)) connectInfo->m_currentLink = 0; else if ( strcmp(connectInfo->m_ServerIP, connectInfo->m_Server_BackupIP) && Connect(connectInfo->m_Server_BackupIP, connectInfo->m_Server_BackupPort, option) ) { connectInfo->m_currentLink = 1; } else { connectInfo->m_currentLink = -1; } } else {//link to second server DbgWithLink_DualActive("BackUp"); if (Connect(connectInfo->m_Server_BackupIP, connectInfo->m_Server_BackupPort, option)) connectInfo->m_currentLink = 1; else if (strcmp(connectInfo->m_ServerIP, connectInfo->m_Server_BackupIP) && Connect(connectInfo->m_ServerIP, connectInfo->m_ServerPort, option)) connectInfo->m_currentLink = 0; else connectInfo->m_currentLink = -1; } } } /* 连接结束 */ char msg[1024]; sprintf(msg, "%sDual Connection: EntityName:%s, server:%s %d, serverBackup:%s %d, DualOpen: %d, currentLink:%d, curEntityNum:%d", (quickConnect ? "quick " : ""), connectInfo->m_EntityName, connectInfo->m_ServerIP, connectInfo->m_ServerPort, connectInfo->m_Server_BackupIP, connectInfo->m_Server_BackupPort, connectInfo->m_DualActive, connectInfo->m_currentLink, entityConnect->getEntityNum()); DbgWithLink_DualActive(msg); setConnectInfo(connectInfo); return (-1 != connectInfo->m_currentLink); } bool SpSecureClient::IsConnectionOK() { return GetFunction()->IsConnectionOK(); } bool SpSecureClient::IsSecureConn() { return GetFunction()->IsSecureConnection(); } void SpSecureClient::Close() { if (!m_bClosed) { m_bClosed = true; GetFunction()->Close(); //clear the connect Info connectClose(m_pEntity->GetEntityName()); DbgWithLink_DualActive("%s closed", m_pEntity->GetEntityName()); } } string SpSecureClient::SendPackage(const CSmartPointer& pSendPkg) { return GetFunction()->SendPackage(pSendPkg); } CSmartPointer SpSecureClient::ReceivePackage(int nWaitSecond) { return GetFunction()->ReceivePackage(nWaitSecond); } CSmartPointer SpSecureClient::CreateNewPackage(const char *pServiceCode) { return GetFunction()->CreateNewPackage(pServiceCode); } CSmartPointer SpSecureClient::CreateReplyPackage(const CSmartPointer& pRecvPkg) { return GetFunction()->CreateReplyPackage(pRecvPkg); } void SpSecureClient::OnErrorMsg(DWORD dwSysCode, DWORD dwUserCode, const CSimpleStringA &pErrMsg) { // 切换到实体线程执行 DbgWithLink(LOG_LEVEL_ERROR, LOG_TYPE_SYSTEM).setAPI(__FUNCTION__)("SpSecureClient error: %s", (const char*)pErrMsg); } void SpSecureClient::OnDisconnect() { DbgWithLink_DualActive("Entity %s OnDisconnect", m_pEntity->GetEntityName()); } void SpSecureClient::OnReConnect() { if (!IsConnectionOK()) {//可能OnDisconnect被重载,已重新连接 DbgWithLink_DualActive("Entity %s disconnect, try to reconnect", m_pEntity->GetEntityName()); ConnectFromCentralSetting(); } } struct OnPackageTask : public ITaskSp { OnPackageTask(SpSecureClient *pClient, IPackage* pkg) :m_pSecureClient(pClient), m_pPackage(pkg) {} SpSecureClient *m_pSecureClient; IPackage * m_pPackage; virtual void Process() { TOOLKIT_ASSERT(m_pPackage != NULL); CSmartPointer ptr; ptr.Attach(m_pPackage); m_pSecureClient->OnPkgAnswer(ptr); m_pSecureClient->DecRefCount(); } }; struct OnDisconnectTask : public ITaskSp { OnDisconnectTask(SpSecureClient *pClient) :m_pSecureClient(pClient) {} SpSecureClient *m_pSecureClient; virtual void Process() { m_pSecureClient->Close(); m_pSecureClient->OnDisconnect(); m_pSecureClient->DecRefCount(); m_pSecureClient->OnReConnect(); } }; struct OnErrorTask : public ITaskSp { OnErrorTask(SpSecureClient *pClient, DWORD dwSysCode, DWORD dwUserCode, const char *pMsg) :m_pSecureClient(pClient), m_dwSysCode(dwSysCode), m_dwUserCode(dwUserCode), m_strErrMsg(pMsg) {} SpSecureClient *m_pSecureClient; DWORD m_dwSysCode; DWORD m_dwUserCode; CSimpleStringA m_strErrMsg; virtual void Process() { m_pSecureClient->OnErrorMsg(m_dwSysCode, m_dwUserCode, m_strErrMsg); m_pSecureClient->DecRefCount(); } }; void SpSecureClient::OnReceivePackage(CSmartPointer &pRecvPkg) { // 切换到实体线程执行 OnPackageTask *pTask = new OnPackageTask(this, pRecvPkg.Detach()); IncRefCount(); m_pEntity->GetFunction()->PostEntityTaskFIFO(pTask); } void SpSecureClient::OnClose() { // 切换到实体线程执行 OnDisconnectTask *pTask = new OnDisconnectTask(this); IncRefCount(); m_pEntity->GetFunction()->PostEntityTaskFIFO(pTask); } void SpSecureClient::OnError(DWORD dwSysCode, DWORD dwUserCode, const char *pErrMsg) { // 切换到实体线程执行 OnErrorTask *pTask = new OnErrorTask(this, dwSysCode, dwUserCode, pErrMsg); IncRefCount(); m_pEntity->GetFunction()->PostEntityTaskFIFO(pTask); } void SpSecureClient::OnAuthPass() { } bool SpSecureClient::OnAuthRequest(CConnAuthReq *pReq) { ErrorCodeEnum Error = Error_Unexpect; // prepare verify info CSystemStaticInfo si; m_pEntity->GetFunction()->GetSystemStaticInfo(si); CVerifyInfo info; memset(&info, 0, sizeof(info)); strncpy(info.m_arrTerminalNo, (LPCSTR)si.strTerminalID, sizeof(info.m_arrTerminalNo)-1); strcpy(info.m_arrServiceType, "CMBRVC"); { #ifdef RVC_OS_WIN hostent *ent = _gethostbyname(NULL); if (ent && ent->h_addr_list[0] != NULL) { int i = 0; for (; ent->h_addr_list[i] != NULL; ++i) { struct in_addr* in = (struct in_addr*)ent->h_addr_list[i]; if (in->S_un.S_un_b.s_b1 == 99 || in->S_un.S_un_b.s_b1 == 10) break; } if (ent->h_addr_list[i] == NULL) i = 0; auto in = (struct in_addr*)ent->h_addr_list[i]; info.m_arrIP[0] = in->S_un.S_un_b.s_b1; info.m_arrIP[1] = in->S_un.S_un_b.s_b2; info.m_arrIP[2] = in->S_un.S_un_b.s_b3; info.m_arrIP[3] = in->S_un.S_un_b.s_b4; } #else char buf[512]; toolkit_interface_address_t* addr; int count, i, aim = -1, backup = -1, third = -1; toolkit_interface_addresses(&addr, &count); i = count; WLog_DBG(TAG, "Number of interfaces: %d", count); while (i--) { toolkit_interface_address_t interface = addr[i]; WLog_DBG(TAG, "Name: %s", interface.name); WLog_DBG(TAG, "Internal? %s", interface.is_internal ? "Yes" : "No"); if (interface.address.address4.sin_family == AF_INET) { third = i; toolkit_ip4_name(&interface.address.address4, buf, sizeof(buf)); WLog_DBG(TAG, "IPv4 address: %s", buf); CSimpleStringA s(buf); if (s.IsStartWith("99.") || s.IsStartWith("10.")) { aim = i; break; } if (!interface.is_internal && backup != -1) { backup = i; } } else if (interface.address.address4.sin_family == AF_INET6) { toolkit_ip6_name(&interface.address.address6, buf, sizeof(buf)); WLog_DBG(TAG, "IPv6 address: %s", buf); } } if (aim == -1 && backup != -1) { aim = backup; } if (aim == -1 && third != -1) aim = third; memset(info.m_arrIP, 0, sizeof(info.m_arrIP)); if (aim != -1) { char ipStr[32]; int b1, b2, b3, b4; b1 = b2 = b3 = b4 = 0; toolkit_ip4_name(&addr[aim].address.address4, ipStr, sizeof(ipStr)); WLog_DBG(TAG, "specified local ip: %s", ipStr); sscanf(ipStr, "%d.%d.%d.%d", &b1, &b2, &b3, &b4); info.m_arrIP[0] = (BYTE)b1; info.m_arrIP[1] = (BYTE)b2; info.m_arrIP[2] = (BYTE)b3; info.m_arrIP[3] = (BYTE)b4; } toolkit_free_interface_addresses(addr, count); #endif } if (pReq != NULL) { // call token service to encrypt verify info int nDestLen = sizeof(pReq->m_arrVerifyInfo); TokenService_ClientBase *client = new TokenService_ClientBase(m_pEntity); Error = client->Connect(); if (Error == Error_Succeed) { TokenService_EncryptWithPubKey_Req Req; TokenService_EncryptWithPubKey_Ans Ans; Req.raw_data.m_pData = (char*)&info; Req.raw_data.m_iLength = sizeof(info); //28 Error = client->EncryptWithPubKey(Req, Ans, -1); if (Error != Error_Succeed) { LOG_TRACE("EncryptWithPriKey for VerifyInfo failed! Error = %s", SpStrError(Error)); } else { memcpy_s(pReq->m_arrVerifyInfo, sizeof(pReq->m_arrVerifyInfo), Ans.enc_data.m_pData, Ans.enc_data.m_iLength); // get token TokenService_GetToken_Req Req1; TokenService_GetToken_Ans Ans1; Error = client-> GetToken(Req1, Ans1, -1); if (Error != Error_Succeed) { LOG_TRACE("GetToken for VerifyInfo failed! Error = %s", SpStrError(Error)); } else { memcpy_s(pReq->m_arrVerifyToken, sizeof(pReq->m_arrVerifyToken), Ans1.token.m_pData, Ans1.token.m_iLength); } } client->GetFunction()->CloseSession(); } else { LOG_TRACE("connect to tokenservice failed! Error = %s", SpStrError(Error)); client->SafeDelete(); } } return Error == Error_Succeed; } bool SpSecureClient::OnAuthRequestSM(CConnAuthSMReq* pReq) { ErrorCodeEnum Error = Error_Unexpect; CSystemStaticInfo si; m_pEntity->GetFunction()->GetSystemStaticInfo(si); CVerifyInfo info; memset(&info, 0, sizeof(info)); strncpy(info.m_arrTerminalNo, (LPCSTR)si.strTerminalID, sizeof(info.m_arrTerminalNo) - 1); strcpy(info.m_arrServiceType, "CMBRVC"); { #ifdef RVC_OS_LINUX char buf[512]; toolkit_interface_address_t* addr; int count, i, aim = -1, backup = -1, third=-1; toolkit_interface_addresses(&addr, &count); i = count; WLog_DBG(TAG, "Number of interfaces: %d", count); while (i--) { toolkit_interface_address_t interface = addr[i]; WLog_DBG(TAG, "Name: %s", interface.name); WLog_DBG(TAG, "Internal? %s", interface.is_internal ? "Yes" : "No"); if (interface.address.address4.sin_family == AF_INET) { third = i; toolkit_ip4_name(&interface.address.address4, buf, sizeof(buf)); WLog_DBG(TAG, "IPv4 address: %s", buf); CSimpleStringA s(buf); if (s.IsStartWith("99.") || s.IsStartWith("10.")) { aim = i; break; } if (!interface.is_internal && backup != -1) { backup = i; } } else if (interface.address.address4.sin_family == AF_INET6) { toolkit_ip6_name(&interface.address.address6, buf, sizeof(buf)); WLog_DBG(TAG, "IPv6 address: %s", buf); } } if (aim == -1 && backup != -1) { aim = backup; } if (aim == -1 && third != -1) aim = third; memset(info.m_arrIP, 0, sizeof(info.m_arrIP)); if (aim != -1) { char ipStr[32]; int b1, b2, b3, b4; b1 = b2 = b3 = b4 = 0; toolkit_ip4_name(&addr[aim].address.address4, ipStr, sizeof(ipStr)); WLog_DBG(TAG, "specified local ip: %s", ipStr); sscanf(ipStr, "%d.%d.%d.%d", &b1, &b2, &b3, &b4); info.m_arrIP[0] = (BYTE)b1; info.m_arrIP[1] = (BYTE)b2; info.m_arrIP[2] = (BYTE)b3; info.m_arrIP[3] = (BYTE)b4; } toolkit_free_interface_addresses(addr, count); #else hostent* ent = _gethostbyname(NULL); WLog_DBG(TAG, "_gethostbyname finished "); if (ent && ent->h_addr_list[0] != NULL) { int i = 0; WLog_DBG(TAG, "office hostname: %s", ent->h_name); for (; ent->h_addr_list[i] != NULL; ++i) { struct in_addr* in = (struct in_addr*)ent->h_addr_list[i]; if (in->S_un.S_un_b.s_b1 == 99 || in->S_un.S_un_b.s_b1 == 10) break; } if (ent->h_addr_list[i] == NULL) i = 0; auto in = (struct in_addr*)ent->h_addr_list[i]; info.m_arrIP[0] = in->S_un.S_un_b.s_b1; info.m_arrIP[1] = in->S_un.S_un_b.s_b2; info.m_arrIP[2] = in->S_un.S_un_b.s_b3; info.m_arrIP[3] = in->S_un.S_un_b.s_b4; } #endif //RVC_OS_LINUX } if(pReq != NULL) { // call token service to encrypt verify info int nDestLen = sizeof(pReq->m_arrVerifyInfo); TokenService_ClientBase* client = new TokenService_ClientBase(m_pEntity); Error = client->Connect(); if (Error == Error_Succeed) { TokenService_EncryptWithPubKey_Req Req; TokenService_EncryptWithPubKey_Ans Ans; Req.raw_data.m_pData = (char*)&info; Req.raw_data.m_iLength = sizeof(info); //28 Error = client->EncryptWithPubKey(Req, Ans, -1); if (Error != Error_Succeed) { LOG_TRACE("EncryptWithPriKey for VerifyInfo failed! Error = %s", SpStrError(Error)); } else { memcpy_s(pReq->m_arrVerifyInfo, sizeof(pReq->m_arrVerifyInfo), Ans.enc_data.m_pData, Ans.enc_data.m_iLength); // get token TokenService_GetToken_Req Req1; TokenService_GetToken_Ans Ans1; Error = client->GetToken(Req1, Ans1, -1); if (Error != Error_Succeed) { LOG_TRACE("GetToken for VerifyInfo failed! Error = %s", SpStrError(Error)); } else { memcpy_s(pReq->m_arrVerifyToken, sizeof(pReq->m_arrVerifyToken), Ans1.token.m_pData, Ans1.token.m_iLength); } } client->GetFunction()->CloseSession(); } else { LOG_TRACE("connect to tokenservice failed! Error = %s", SpStrError(Error)); client->SafeDelete(); } } return Error == Error_Succeed; } bool SpSecureClient::OnSessionKeyRet(CConnAuthRet *pRet, BYTE *pBuf, int *pBufLen) { memset(pBuf, 0, *pBufLen); TokenService_ClientBase *client = new TokenService_ClientBase(m_pEntity); ErrorCodeEnum Error = client->Connect(); if (Error == Error_Succeed) { TokenService_DecryptWithPriKey_Req Req; TokenService_DecryptWithPriKey_Ans Ans; Req.enc_data.m_pData = (char*)&pRet->m_arrEncSessionKey[0]; Req.enc_data.m_iLength = sizeof(pRet->m_arrEncSessionKey); Error = client->DecryptWithPriKey(Req, Ans, -1); if (Error == Error_Succeed) { memcpy_s(pBuf, *pBufLen, Ans.raw_data.m_pData, Ans.raw_data.m_iLength); *pBufLen = Ans.raw_data.m_iLength; } else { *pBufLen = 0; LOG_TRACE("OnSessionKey decrypt session key failed! Error = %s", SpStrError(Error)); } client->GetFunction()->CloseSession(); } else { LOG_TRACE("connect to tokenservice failed! Error = %s", SpStrError(Error)); client->SafeDelete(); } return Error == Error_Succeed; } bool SpSecureClient::OnSessionKeySMRet(CConnAuthSMRet* pRet, BYTE* pBuf, int* pBufLen) { memset(pBuf, 0, *pBufLen); TokenService_ClientBase* client = new TokenService_ClientBase(m_pEntity); ErrorCodeEnum Error = client->Connect(); if (Error == Error_Succeed) { TokenService_DecryptWithPriKey_Req Req; TokenService_DecryptWithPriKey_Ans Ans; Req.enc_data.m_pData = (char*)&pRet->m_arrEncSessionKey[0]; Req.enc_data.m_iLength = sizeof(pRet->m_arrEncSessionKey); Error = client->DecryptWithPriKey(Req, Ans, -1); if (Error == Error_Succeed) { memcpy_s(pBuf, *pBufLen, Ans.raw_data.m_pData, Ans.raw_data.m_iLength); *pBufLen = Ans.raw_data.m_iLength; } else { *pBufLen = 0; LOG_TRACE("OnSessionKey decrypt session key failed! Error = %s", SpStrError(Error)); } client->GetFunction()->CloseSession(); } else { LOG_TRACE("connect to tokenservice failed! Error = %s", SpStrError(Error)); client->SafeDelete(); } return Error == Error_Succeed; } bool SpSecureClient::OnGetSharedSK(char *pTerminalNo, int *pTerminalNoLen, BYTE *pBuf, int *pBufLen) { #ifdef _MSC_VER ErrorCodeEnum Error = Error_Unexpect; CSystemStaticInfo si; { m_pEntity->GetFunction()->GetSystemStaticInfo(si); } TOOLKIT_ASSERT(si.strTerminalID.GetLength() <= *pTerminalNoLen); strcpy(pTerminalNo, (LPCSTR)si.strTerminalID); *pTerminalNoLen = strlen(pTerminalNo); { TokenService_ClientBase *client = new TokenService_ClientBase(m_pEntity); Error = client->Connect(); if (Error == Error_Succeed) { TokenService_GetSharedSK_Req Req; TokenService_GetSharedSK_Ans Ans; Error = client->GetSharedSK(Req, Ans, 10000); if (Error == Error_Succeed) { memcpy_s(pBuf, *pBufLen, Ans.ssk.m_pData, Ans.ssk.m_iLength); *pBufLen = Ans.ssk.m_iLength; } else { *pBufLen = 0; LOG_TRACE("OnSessionKey decrypt session key failed! Error = %s", SpStrError(Error)); } client->GetFunction()->CloseSession(); } else { LOG_TRACE("connect to tokenservice failed! Error = %s", SpStrError(Error)); client->SafeDelete(); } } return Error == Error_Succeed; #else return false; #endif //_MSC_VER } ErrorCodeEnum SpSecureClient::ParseIPAddress(const char *str, CSimpleStringA &ip, int &port) { ErrorCodeEnum Error = Error_Unexpect; if (str) { char tmp1[32] = {}; char tmp2[16] = {}; sscanf(str, "%s %s", tmp1, tmp2); if (tmp1[0] != 0 && tmp2[0] != 0) { ip = tmp1; port = atoi(tmp2); Error = Error_Succeed; } else return Error; } return Error; } DWORD SpSecureClient::GetEntityUserCode(DWORD code) { TOOLKIT_ASSERT(m_pEntity != NULL); auto pEnv = sp_get_env(); TOOLKIT_ASSERT(pEnv != NULL); auto pCfg = pEnv->cfg; TOOLKIT_ASSERT(pCfg != NULL); auto pEntity = sp_cfg_get_entity_by_name(pCfg, m_pEntity->GetEntityName()); TOOLKIT_ASSERT(pEntity != NULL); DWORD dwDevelopID = pEntity->devel_id; return (dwDevelopID << 20 | code); }