/* HINT: That is a thread entry point and wrapper for the real serverloop. */ OpcUa_Void OpcUa_P_SocketManager_ServerLoopThread(OpcUa_Void* a_pArgument) { OpcUa_StatusCode uStatus = OpcUa_Good; /* only needed for internal reasons */ OpcUa_InternalSocketManager* pInternalSocketManager = (OpcUa_InternalSocketManager*)a_pArgument; OpcUa_Int32 iSocketManagerSlot; OpcUa_Trace(OPCUA_TRACE_LEVEL_INFO, "NetworkThread: Message Loop started...\n"); do { uStatus = OpcUa_P_SocketManager_ServeLoopInternal( pInternalSocketManager, OpcUa_UInt32_Max, OpcUa_False); if(OpcUa_IsEqual(OpcUa_GoodShutdownEvent)) { /* leave this loop if a shutdown was signalled */ break; } } while(OpcUa_IsGood(uStatus)); /* Debug Output */ OpcUa_Trace(OPCUA_TRACE_LEVEL_INFO, "NetworkThread: Message Loop shutting down! (0x%08X)\n", uStatus); if(pInternalSocketManager->Flags.bSpawnThreadOnAccept != 0) { #if OPCUA_USE_SYNCHRONISATION OpcUa_P_Mutex_Lock(pInternalSocketManager->pMutex); #endif /* OPCUA_USE_SYNCHRONISATION */ for(iSocketManagerSlot = 0; iSocketManagerSlot < OPCUA_SOCKET_MAXMANAGERS; iSocketManagerSlot++) { if(pInternalSocketManager->pSocketManagers[iSocketManagerSlot] != OpcUa_Null) { OpcUa_InternalSocketManager *pSpawnedSocketManager = pInternalSocketManager->pSocketManagers[iSocketManagerSlot]; pInternalSocketManager->pSocketManagers[iSocketManagerSlot] = OpcUa_Null; pSpawnedSocketManager->pThreadToJoin = pInternalSocketManager->pThreadToJoin; pInternalSocketManager->pThreadToJoin = pSpawnedSocketManager->pThread; pSpawnedSocketManager->pThread = OpcUa_Null; OpcUa_P_SocketManager_InterruptLoop(pSpawnedSocketManager, OPCUA_SOCKET_SHUTDOWN_EVENT, OpcUa_False); } } #if OPCUA_USE_SYNCHRONISATION OpcUa_P_Mutex_Unlock(pInternalSocketManager->pMutex); #endif /* OPCUA_USE_SYNCHRONISATION */ if(pInternalSocketManager->pThreadToJoin != OpcUa_Null) { OpcUa_P_Thread_Delete(&pInternalSocketManager->pThreadToJoin); } } return; }
/*============================================================================ * OpcUa_ProxyStub_Clear *===========================================================================*/ OpcUa_Void OPCUA_DLLCALL OpcUa_ProxyStub_Clear(OpcUa_Void) { OpcUa_Boolean bSkip = OpcUa_False; if(OpcUa_ProxyStub_g_PlatformLayerCalltable == OpcUa_Null) { /* error */ return; } else { #if OPCUA_USE_SYNCHRONISATION OPCUA_P_MUTEX_LOCK(OpcUa_ProxyStub_g_hGlobalsMutex); #endif /* OPCUA_USE_SYNCHRONISATION */ OpcUa_ProxyStub_g_uNoOfInits--; if(OpcUa_ProxyStub_g_uNoOfInits > 0) { bSkip = OpcUa_True; } #if OPCUA_USE_SYNCHRONISATION OPCUA_P_MUTEX_UNLOCK(OpcUa_ProxyStub_g_hGlobalsMutex); #endif /* OPCUA_USE_SYNCHRONISATION */ if(bSkip == OpcUa_False) { if(OpcUa_ProxyStub_g_pConfigString != OpcUa_Null) { OpcUa_Free(OpcUa_ProxyStub_g_pConfigString); OpcUa_ProxyStub_g_pConfigString = OpcUa_Null; } /* P-Layer resource */ OpcUa_Trace(OPCUA_TRACE_LEVEL_INFO, "OpcUa_ProxyStub_Clear: Network Module...\n"); OPCUA_P_CLEANUPNETWORK(); OPCUA_P_CLEANUPTIMERS(); /* Forces a stop of all timers not yet deleted. Leads to callbacks! */ #if OPCUA_USE_SYNCHRONISATION OPCUA_P_MUTEX_DELETE(&OpcUa_ProxyStub_g_hGlobalsMutex); #endif /* OPCUA_USE_SYNCHRONISATION */ OpcUa_Trace(OPCUA_TRACE_LEVEL_INFO, "OpcUa_ProxyStub_Clear: Network Module done!\n"); #if OPCUA_TRACE_ENABLE /* internal resource */ OpcUa_Trace_Clear(); #endif /* OPCUA_TRACE_ENABLE */ OpcUa_EncodeableTypeTable_Delete(&OpcUa_ProxyStub_g_EncodeableTypes); OpcUa_StringTable_Clear(&OpcUa_ProxyStub_g_NamespaceUris); OpcUa_ProxyStub_g_PlatformLayerCalltable = OpcUa_Null; } } }
/*============================================================================ * verify_callback *===========================================================================*/ static OpcUa_Int OpcUa_P_OpenSSL_CertificateStore_Verify_Callback(int a_ok, X509_STORE_CTX* a_pStore) { OpcUa_P_OpenSSL_CertificateStore_Config* pCertificateStoreCfg; pCertificateStoreCfg = X509_STORE_CTX_get_app_data(a_pStore); if(a_ok == 0) { /* certificate not ok */ char buf[256]; X509* err_cert; int err; int depth; err_cert = X509_STORE_CTX_get_current_cert(a_pStore); err = X509_STORE_CTX_get_error(a_pStore); depth = X509_STORE_CTX_get_error_depth(a_pStore); X509_NAME_oneline(X509_get_subject_name(err_cert), buf, 256); OpcUa_Trace(OPCUA_TRACE_LEVEL_WARNING, "\nverify error:\n\tnum=%d:%s\n\tdepth=%d\n\t%s\n", err, X509_verify_cert_error_string(err), depth, buf); X509_NAME_oneline(X509_get_issuer_name(a_pStore->current_cert), buf, 256); OpcUa_Trace(OPCUA_TRACE_LEVEL_WARNING, "\tissuer=%s\n", buf); switch (err) { case X509_V_ERR_UNABLE_TO_GET_CRL: if (pCertificateStoreCfg->Flags & OPCUA_P_PKI_OPENSSL_SUPPRESS_CRL_NOT_FOUND_ERROR) a_ok = 1; break; case X509_V_ERR_CRL_NOT_YET_VALID: case X509_V_ERR_CRL_HAS_EXPIRED: if (pCertificateStoreCfg->Flags & OPCUA_P_PKI_OPENSSL_SUPPRESS_CRL_VALIDITY_PERIOD_CHECK) a_ok = 1; break; case X509_V_ERR_CERT_NOT_YET_VALID: case X509_V_ERR_CERT_HAS_EXPIRED: if (pCertificateStoreCfg->Flags & OPCUA_P_PKI_OPENSSL_SUPPRESS_CERT_VALIDITY_PERIOD_CHECK) a_ok = 1; break; } } return a_ok; }
/*============================================================================ * OpcUa_TcpSecureChannel_RenewSecurityToken *===========================================================================*/ OpcUa_StatusCode OpcUa_TcpSecureChannel_RenewSecurityToken( OpcUa_SecureChannel* a_pSecureChannel, OpcUa_ChannelSecurityToken* a_pSecurityToken, OpcUa_UInt32 a_tokenLifeTime, OpcUa_ChannelSecurityToken** a_ppSecurityToken) { OpcUa_ChannelSecurityToken* pSecurityToken = OpcUa_Null; OpcUa_InitializeStatus(OpcUa_Module_SecureChannel, "RenewSecurityToken"); /* check parameters */ OpcUa_ReturnErrorIfArgumentNull(a_pSecureChannel); OpcUa_ReturnErrorIfArgumentNull(a_pSecurityToken); OpcUa_ReturnErrorIfArgumentNull(a_ppSecurityToken); OPCUA_SECURECHANNEL_LOCK(a_pSecureChannel); /* initialize outparameters */ *a_ppSecurityToken = OpcUa_Null; /*** create token ***/ pSecurityToken = (OpcUa_ChannelSecurityToken*)OpcUa_Alloc(sizeof(OpcUa_ChannelSecurityToken)); OpcUa_GotoErrorIfAllocFailed(pSecurityToken); OpcUa_ChannelSecurityToken_Initialize(pSecurityToken); pSecurityToken->TokenId = a_pSecureChannel->NextTokenId; pSecurityToken->ChannelId = a_pSecurityToken->ChannelId; pSecurityToken->CreatedAt = OPCUA_P_DATETIME_UTCNOW(); OpcUa_Trace(OPCUA_TRACE_LEVEL_INFO, "OpcUa_TcpSecureChannel_RenewSecurityToken: TOKEN ID is %u-%u\n", pSecurityToken->ChannelId, pSecurityToken->TokenId); OpcUa_TcpSecureChannel_ReviseLifetime(a_tokenLifeTime, &pSecurityToken->RevisedLifetime); /* increment renew counter */ a_pSecureChannel->NextTokenId++; OPCUA_SECURECHANNEL_UNLOCK(a_pSecureChannel); /* assign outparameter */ *a_ppSecurityToken = pSecurityToken; OpcUa_ReturnStatusCode; OpcUa_BeginErrorHandling; OPCUA_SECURECHANNEL_UNLOCK(a_pSecureChannel); if(pSecurityToken != OpcUa_Null) { OpcUa_Free(pSecurityToken); } OpcUa_FinishErrorHandling; }
/*============================================================================ * OpcUa_TcpSecureChannel_ReleaseSecuritySet *===========================================================================*/ OpcUa_StatusCode OpcUa_TcpSecureChannel_ReleaseSecuritySet( OpcUa_SecureChannel* a_pSecureChannel, OpcUa_UInt32 a_uTokenId) { OpcUa_InitializeStatus(OpcUa_Module_SecureChannel, "ReleaseSecuritySet"); OpcUa_ReturnErrorIfArgumentNull(a_pSecureChannel); OpcUa_ReferenceParameter(a_uTokenId); OpcUa_Trace(OPCUA_TRACE_LEVEL_DEBUG, "ReleaseSecurityKeyset: Keyset for token %u released.\n", a_uTokenId); OPCUA_SECURECHANNEL_UNLOCK(a_pSecureChannel); OpcUa_ReturnStatusCode; OpcUa_BeginErrorHandling; OpcUa_FinishErrorHandling; }
/*============================================================================ * Start a created thread. *===========================================================================*/ OpcUa_StatusCode OpcUa_Thread_Start(OpcUa_Thread a_Thread) { OpcUa_StatusCode uStatus = OpcUa_Good; OpcUa_ThreadInternal* pThread = OpcUa_Null; OpcUa_Int32 intThreadId = 0; OpcUa_ReturnErrorIfArgumentNull(a_Thread); pThread = (OpcUa_ThreadInternal*)a_Thread; OPCUA_P_MUTEX_LOCK(pThread->Mutex); if(pThread->IsRunning != OpcUa_False) { OPCUA_P_MUTEX_UNLOCK(pThread->Mutex); return OpcUa_Good; } /* set semaphore to waitable */ uStatus = OPCUA_P_SEMAPHORE_WAIT((pThread->ShutdownEvent)); OpcUa_GotoErrorIfBad(uStatus); pThread->IsRunning = OpcUa_True; intThreadId = OpcUa_P_Thread_Start( pThread->RawThread, InternalThreadMain, (OpcUa_Void*)pThread); if(intThreadId != 0) { pThread->IsRunning = OpcUa_False; OPCUA_P_MUTEX_UNLOCK(pThread->Mutex); uStatus = OpcUa_BadInternalError; OpcUa_Trace(OPCUA_TRACE_LEVEL_ERROR, "OpcUa_Thread_Start: Error during thread creation!\n"); goto Error; } OPCUA_P_MUTEX_UNLOCK(pThread->Mutex); return OpcUa_Good; Error: return uStatus; }
/*============================================================================ * OpcUa_MemoryStream_Flush *===========================================================================*/ static OpcUa_StatusCode OpcUa_MemoryStream_Flush( OpcUa_OutputStream* ostrm, OpcUa_Boolean lastCall) { OpcUa_MemoryStream* handle = OpcUa_Null; OpcUa_InitializeStatus(OpcUa_Module_MemoryStream, "Flush"); OpcUa_ReturnErrorIfArgumentNull(ostrm); OpcUa_ReturnErrorIfInvalidStream(ostrm, Flush); OpcUa_ReferenceParameter(lastCall); handle = (OpcUa_MemoryStream*)ostrm->Handle; if(handle->Closed) { return OpcUa_BadInvalidState; } if(!OpcUa_Buffer_IsEmpty((OpcUa_Buffer *)handle->pBuffer)) { OpcUa_Byte* pData = OpcUa_Null; OpcUa_UInt32 uDataLength = 0; uStatus = OpcUa_Buffer_GetData(handle->pBuffer, &pData, &uDataLength); if (OpcUa_IsBad(uStatus)) { OpcUa_Trace(OPCUA_TRACE_LEVEL_ERROR, "Flush: FAILED with 0x%X\n", uStatus); OpcUa_GotoError; } } OpcUa_ReturnStatusCode; OpcUa_BeginErrorHandling; OpcUa_FinishErrorHandling; }
/** * @brief Builds a connection record for the given parameters and returns it. * * @return: Status Code; */ OpcUa_StatusCode OpcUa_TcpListener_ConnectionManager_AddConnection( OpcUa_TcpListener_ConnectionManager* a_pConnectionManager, OpcUa_TcpListener_Connection* a_pConnection) { OpcUa_StatusCode uStatus = OpcUa_Good; OpcUa_GotoErrorIfArgumentNull(a_pConnection); OpcUa_GotoErrorIfArgumentNull(a_pConnectionManager); OpcUa_GotoErrorIfArgumentNull(a_pConnectionManager->Connections); a_pConnection->ConnectTime = OPCUA_P_DATETIME_UTCNOW(); /* expiration of connection would be DisconnectTime+Lifetime */ OpcUa_List_Enter(a_pConnectionManager->Connections); OpcUa_List_AddElement(a_pConnectionManager->Connections, a_pConnection); OpcUa_Trace(OPCUA_TRACE_LEVEL_DEBUG, "OpcUa_TcpListener_ConnectionManager_AddConnection: Connection added!\n"); OpcUa_List_Leave(a_pConnectionManager->Connections); return OpcUa_Good; Error: return OpcUa_Bad; }
/** * @brief Clean up the given OpcUa_TcpListener_Connection. May be used for static memory. */ OpcUa_Void OpcUa_TcpListener_Connection_Clear(OpcUa_TcpListener_Connection* a_pConnection) { if(a_pConnection == OpcUa_Null) { return; } OpcUa_MemSet(&(a_pConnection->ConnectTime), 0, sizeof(OpcUa_DateTime)); OpcUa_MemSet(&(a_pConnection->DisconnectTime), 0, sizeof(OpcUa_DateTime)); a_pConnection->Socket = OpcUa_Null; /* Socket has to be freed externally. */ a_pConnection->pListenerHandle = OpcUa_Null; a_pConnection->uNoOfRequestsTotal = 0; OpcUa_String_Clear(&a_pConnection->sURL); if(a_pConnection->pInputStream != OpcUa_Null) { OpcUa_TcpStream_Close((OpcUa_Stream*)a_pConnection->pInputStream); OpcUa_TcpStream_Delete((OpcUa_Stream**)&a_pConnection->pInputStream); } while(a_pConnection->pSendQueue != OpcUa_Null) { OpcUa_BufferList* pCurrentBuffer = a_pConnection->pSendQueue; a_pConnection->pSendQueue = pCurrentBuffer->pNext; OpcUa_Buffer_Clear(&pCurrentBuffer->Buffer); OpcUa_Free(pCurrentBuffer); } if(a_pConnection->Mutex) { OPCUA_P_MUTEX_DELETE(&(a_pConnection->Mutex)); } OpcUa_Trace(OPCUA_TRACE_LEVEL_DEBUG, "OpcUa_TcpListener_Connection_Clear: Done!\n"); }
/*============================================================================ * OpcUa_ProxyStub_Initialize *===========================================================================*/ OpcUa_StatusCode OPCUA_DLLCALL OpcUa_ProxyStub_Initialize(OpcUa_Handle a_pPlatformLayerCalltable, OpcUa_ProxyStubConfiguration* a_pProxyStubConfiguration) { OpcUa_Boolean bSkip = OpcUa_False; OpcUa_InitializeStatus(OpcUa_Module_ProxyStub, "Initialize"); OpcUa_ReturnErrorIfArgumentNull(a_pProxyStubConfiguration) OpcUa_ReturnErrorIfArgumentNull(a_pPlatformLayerCalltable); /* set global platform layer handle */ OpcUa_ProxyStub_g_PlatformLayerCalltable = (OpcUa_Port_CallTable *)a_pPlatformLayerCalltable; #if OPCUA_USE_SYNCHRONISATION if(OpcUa_ProxyStub_g_hGlobalsMutex == OpcUa_Null) { uStatus = OPCUA_P_MUTEX_CREATE(&OpcUa_ProxyStub_g_hGlobalsMutex); OpcUa_GotoErrorIfBad(uStatus); } #endif /* OPCUA_USE_SYNCHRONISATION */ #if OPCUA_USE_SYNCHRONISATION OPCUA_P_MUTEX_LOCK(OpcUa_ProxyStub_g_hGlobalsMutex); #endif /* OPCUA_USE_SYNCHRONISATION */ OpcUa_ProxyStub_g_uNoOfInits++; if(OpcUa_ProxyStub_g_uNoOfInits > 1) { bSkip = OpcUa_True; } #if OPCUA_USE_SYNCHRONISATION OPCUA_P_MUTEX_UNLOCK(OpcUa_ProxyStub_g_hGlobalsMutex); #endif /* OPCUA_USE_SYNCHRONISATION */ if(bSkip == OpcUa_False) { /* set global configuration object */ uStatus = OpcUa_ProxyStub_ReInitialize(a_pProxyStubConfiguration); OpcUa_GotoErrorIfBad(uStatus); /* initialize tracer */ #if OPCUA_TRACE_ENABLE uStatus = OpcUa_Trace_Initialize(); OpcUa_GotoErrorIfBad(uStatus); OpcUa_Trace(OPCUA_TRACE_LEVEL_INFO, "OpcUa_ProxyStub_Initialize: Tracer has been initialized!\n"); #endif /* OPCUA_TRACE_ENABLE */ /* initialize networking. */ OpcUa_Trace(OPCUA_TRACE_LEVEL_INFO, "OpcUa_ProxyStub_Initialize: Network Module...\n"); uStatus = OPCUA_P_INITIALIZENETWORK(); OpcUa_GotoErrorIfBad(uStatus); OpcUa_Trace(OPCUA_TRACE_LEVEL_INFO, "OpcUa_ProxyStub_Initialize: Network Module done!\n"); uStatus = OpcUa_EncodeableTypeTable_Create(&OpcUa_ProxyStub_g_EncodeableTypes); OpcUa_GotoErrorIfBad(uStatus); uStatus = OpcUa_EncodeableTypeTable_AddTypes(&OpcUa_ProxyStub_g_EncodeableTypes, OpcUa_KnownEncodeableTypes); OpcUa_GotoErrorIfBad(uStatus); OpcUa_StringTable_Initialize(&OpcUa_ProxyStub_g_NamespaceUris); uStatus = OpcUa_StringTable_AddStringList(&OpcUa_ProxyStub_g_NamespaceUris, OpcUa_ProxyStub_StandardNamespaceUris); OpcUa_GotoErrorIfBad(uStatus); } OpcUa_ReturnStatusCode; OpcUa_BeginErrorHandling; OpcUa_ProxyStub_Clear(); OpcUa_FinishErrorHandling; }
/*============================================================================ * OpcUa_P_OpenSSL_CertificateStore_Open *===========================================================================*/ OpcUa_StatusCode OpcUa_P_OpenSSL_PKI_OpenCertificateStore( OpcUa_PKIProvider* a_pProvider, OpcUa_Void** a_ppCertificateStore) /* type depends on store implementation */ { OpcUa_P_OpenSSL_CertificateStore_Config* pCertificateStoreCfg; X509_STORE* pStore; X509_LOOKUP* pLookup; char CertFile[MAX_PATH]; struct dirent **dirlist = NULL; int numCertificates = 0, i; OpcUa_InitializeStatus(OpcUa_Module_P_OpenSSL, "PKI_OpenCertificateStore"); OpcUa_ReturnErrorIfArgumentNull(a_pProvider); OpcUa_ReturnErrorIfArgumentNull(a_pProvider->Handle); OpcUa_ReturnErrorIfArgumentNull(a_ppCertificateStore); *a_ppCertificateStore = OpcUa_Null; pCertificateStoreCfg = (OpcUa_P_OpenSSL_CertificateStore_Config*)a_pProvider->Handle; if(!(*a_ppCertificateStore = pStore = X509_STORE_new())) { OpcUa_GotoErrorWithStatus(OpcUa_Bad); } X509_STORE_set_verify_cb_func(pStore, OpcUa_P_OpenSSL_CertificateStore_Verify_Callback); if(pCertificateStoreCfg->Flags & OPCUA_P_PKI_OPENSSL_USE_DEFAULT_CERT_CRL_LOOKUP_METHOD) { if(X509_STORE_set_default_paths(pStore) != 1) { OpcUa_Trace(OPCUA_TRACE_LEVEL_WARNING, "error at X509_STORE_set_default_paths!\n"); OpcUa_GotoErrorWithStatus(OpcUa_Bad); } } if(!(pCertificateStoreCfg->Flags & OPCUA_P_PKI_OPENSSL_DONT_ADD_TRUST_LIST_TO_ROOT_CERTIFICATES)) { if(pCertificateStoreCfg->CertificateTrustListLocation == OpcUa_Null || pCertificateStoreCfg->CertificateTrustListLocation[0] == '\0') { OpcUa_GotoErrorWithStatus(OpcUa_Bad); } /* how to search for certificate & CRLs */ if(!(pLookup = X509_STORE_add_lookup(pStore, X509_LOOKUP_file()))) { OpcUa_GotoErrorWithStatus(OpcUa_Bad); } /* how to search for certificate & CRLs */ numCertificates = scandir(pCertificateStoreCfg->CertificateTrustListLocation, &dirlist, certificate_filter_der, alphasort); for (i=0; i<numCertificates; i++) { uStatus = OpcUa_P_OpenSSL_BuildFullPath(pCertificateStoreCfg->CertificateTrustListLocation, dirlist[i]->d_name, MAX_PATH, CertFile); OpcUa_GotoErrorIfBad(uStatus); /* add CACertificate lookup */ if(X509_LOOKUP_load_file(pLookup, CertFile, X509_FILETYPE_ASN1) != 1) /*DER encoded*/ { OpcUa_Trace(OPCUA_TRACE_LEVEL_WARNING, "error at X509_LOOKUP_load_file: skipping %s\n", CertFile); } } for (i=0; i<numCertificates; i++) { free(dirlist[i]); } free(dirlist); dirlist = NULL; } if(pCertificateStoreCfg->Flags & OPCUA_P_PKI_OPENSSL_ADD_UNTRUSTED_LIST_TO_ROOT_CERTIFICATES) { if(pCertificateStoreCfg->CertificateUntrustedListLocation == OpcUa_Null || pCertificateStoreCfg->CertificateUntrustedListLocation[0] == '\0') { OpcUa_GotoErrorWithStatus(OpcUa_Bad); } if(pCertificateStoreCfg->Flags & OPCUA_P_PKI_OPENSSL_UNTRUSTED_LIST_IS_INDEX) { /* how to search for certificate */ if(!(pLookup = X509_STORE_add_lookup(pStore, X509_LOOKUP_hash_dir()))) { OpcUa_GotoErrorWithStatus(OpcUa_Bad); } /* add hash lookup */ if(X509_LOOKUP_add_dir(pLookup, pCertificateStoreCfg->CertificateUntrustedListLocation, X509_FILETYPE_ASN1) != 1) /*DER encoded*/ { OpcUa_Trace(OPCUA_TRACE_LEVEL_WARNING, "error at X509_LOOKUP_add_dir!\n"); OpcUa_GotoErrorWithStatus(OpcUa_Bad); } } else { /* how to search for certificate & CRLs */ if(!(pLookup = X509_STORE_add_lookup(pStore, X509_LOOKUP_file()))) { OpcUa_GotoErrorWithStatus(OpcUa_Bad); } numCertificates = scandir(pCertificateStoreCfg->CertificateUntrustedListLocation, &dirlist, certificate_filter_der, alphasort); for (i=0; i<numCertificates; i++) { uStatus = OpcUa_P_OpenSSL_BuildFullPath(pCertificateStoreCfg->CertificateUntrustedListLocation, dirlist[i]->d_name, MAX_PATH, CertFile); OpcUa_GotoErrorIfBad(uStatus); /* add CACertificate lookup */ if(X509_LOOKUP_load_file(pLookup, CertFile, X509_FILETYPE_ASN1) != 1) /*DER encoded*/ { OpcUa_Trace(OPCUA_TRACE_LEVEL_WARNING, "error at X509_LOOKUP_load_file: skipping %s\n", CertFile); } } for (i=0; i<numCertificates; i++) { free(dirlist[i]); } free(dirlist); dirlist = NULL; } } if(pCertificateStoreCfg->Flags & OPCUA_P_PKI_OPENSSL_CHECK_REVOCATION_ALL) { if(pCertificateStoreCfg->CertificateRevocationListLocation == OpcUa_Null || pCertificateStoreCfg->CertificateRevocationListLocation[0] == '\0') { OpcUa_GotoErrorWithStatus(OpcUa_Bad); } if(pCertificateStoreCfg->Flags & OPCUA_P_PKI_OPENSSL_REVOCATION_LIST_IS_INDEX) { /* how to search for certificate & CRLs */ if(!(pLookup = X509_STORE_add_lookup(pStore, X509_LOOKUP_hash_dir()))) { OpcUa_GotoErrorWithStatus(OpcUa_Bad); } /* add CRL lookup */ if(X509_LOOKUP_add_dir(pLookup, pCertificateStoreCfg->CertificateRevocationListLocation, X509_FILETYPE_PEM) != 1) /*PEM encoded*/ { OpcUa_Trace(OPCUA_TRACE_LEVEL_WARNING, "error at X509_LOOKUP_add_dir!\n"); OpcUa_GotoErrorWithStatus(OpcUa_Bad); } } else if(pCertificateStoreCfg->Flags & OPCUA_P_PKI_OPENSSL_REVOCATION_LIST_IS_CONCATENATED_PEM_FILE) { /* how to search for certificate & CRLs */ if(!(pLookup = X509_STORE_add_lookup(pStore, X509_LOOKUP_file()))) { OpcUa_GotoErrorWithStatus(OpcUa_Bad); } /* add CRL lookup */ if(X509_load_crl_file(pLookup, pCertificateStoreCfg->CertificateRevocationListLocation, X509_FILETYPE_PEM) != 1) /*PEM encoded*/ { OpcUa_Trace(OPCUA_TRACE_LEVEL_WARNING, "error at X509_load_crl_file!\n"); } } else { /* how to search for certificate & CRLs */ if(!(pLookup = X509_STORE_add_lookup(pStore, X509_LOOKUP_file()))) { OpcUa_GotoErrorWithStatus(OpcUa_Bad); } numCertificates = scandir(pCertificateStoreCfg->CertificateRevocationListLocation, &dirlist, certificate_filter_crl, alphasort); for (i=0; i<numCertificates; i++) { uStatus = OpcUa_P_OpenSSL_BuildFullPath(pCertificateStoreCfg->CertificateRevocationListLocation, dirlist[i]->d_name, MAX_PATH, CertFile); OpcUa_GotoErrorIfBad(uStatus); if(X509_load_crl_file(pLookup, CertFile, X509_FILETYPE_PEM) != 1) /*PEM encoded*/ { OpcUa_Trace(OPCUA_TRACE_LEVEL_WARNING, "error at X509_load_crl_file: skipping %s\n", CertFile); } } for (i=0; i<numCertificates; i++) { free(dirlist[i]); } free(dirlist); dirlist = NULL; } if((pCertificateStoreCfg->Flags & OPCUA_P_PKI_OPENSSL_CHECK_REVOCATION_ALL) == OPCUA_P_PKI_OPENSSL_CHECK_REVOCATION_ALL) { /* set the flags of the store so that CRLs are consulted */ if(X509_STORE_set_flags(pStore, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL) != 1) { OpcUa_GotoErrorWithStatus(OpcUa_Bad); } } else if(pCertificateStoreCfg->Flags & OPCUA_P_PKI_OPENSSL_CHECK_REVOCATION_ONLY_LEAF) { /* set the flags of the store so that CRLs are consulted */ if(X509_STORE_set_flags(pStore, X509_V_FLAG_CRL_CHECK) != 1) { OpcUa_GotoErrorWithStatus(OpcUa_Bad); } } } if(pCertificateStoreCfg->Flags & OPCUA_P_PKI_OPENSSL_CHECK_SELF_SIGNED_SIGNATURE) { /* set the flags of the store so that CRLs are consulted */ if(X509_STORE_set_flags(pStore, X509_V_FLAG_CHECK_SS_SIGNATURE) != 1) { OpcUa_GotoErrorWithStatus(OpcUa_Bad); } } if(pCertificateStoreCfg->Flags & OPCUA_P_PKI_OPENSSL_ALLOW_PROXY_CERTIFICATES) { /* set the flags of the store so that CRLs are consulted */ if(X509_STORE_set_flags(pStore, X509_V_FLAG_ALLOW_PROXY_CERTS) != 1) { OpcUa_GotoErrorWithStatus(OpcUa_Bad); } } OpcUa_ReturnStatusCode; OpcUa_BeginErrorHandling; if(dirlist != NULL) { for (i=0; i<numCertificates; i++) { free(dirlist[i]); } free(dirlist); } if(*a_ppCertificateStore != OpcUa_Null) { X509_STORE_free((X509_STORE*)*a_ppCertificateStore); *a_ppCertificateStore = OpcUa_Null; } OpcUa_FinishErrorHandling; }
/*============================================================================ * Delete SocketManager Type (closes all sockets) *===========================================================================*/ OpcUa_Void OPCUA_DLLCALL OpcUa_P_SocketManager_Delete(OpcUa_SocketManager* a_pSocketManager) { OpcUa_InternalSocketManager* pInternalSocketManager = OpcUa_Null; OpcUa_UInt32 uintIndex = 0; #if !OPCUA_MULTITHREADED if(a_pSocketManager == OpcUa_Null && OpcUa_Socket_g_SocketManager != OpcUa_Null) { a_pSocketManager = &OpcUa_Socket_g_SocketManager; } #endif if(a_pSocketManager == OpcUa_Null || *a_pSocketManager == OpcUa_Null) { OpcUa_Trace(OPCUA_TRACE_LEVEL_ERROR, "OpcUa_SocketManager_Delete: Invalid Socket Manager!\n"); return; } pInternalSocketManager = (OpcUa_InternalSocketManager*)*a_pSocketManager; /* send shutdown event to serveloop */ OpcUa_P_SocketManager_InterruptLoop(pInternalSocketManager, OPCUA_SOCKET_SHUTDOWN_EVENT, OpcUa_False); #if OPCUA_MULTITHREADED if(pInternalSocketManager->pThread != OpcUa_Null) { OpcUa_P_Thread_Delete(&(pInternalSocketManager->pThread)); } else { OpcUa_Trace(OPCUA_TRACE_LEVEL_ERROR, "OpcUa_SocketManager_Delete: Invalid Thread Handle!\n"); return; } #endif /* OPCUA_MULTITHREADED */ #if OPCUA_USE_SYNCHRONISATION OpcUa_P_Mutex_Lock(pInternalSocketManager->pMutex); #endif /* OPCUA_USE_SYNCHRONISATION */ /* handle the socket list content (close, cleanup, etc.) */ if(pInternalSocketManager->pSockets != OpcUa_Null) { for(uintIndex = 0; uintIndex < pInternalSocketManager->uintMaxSockets; uintIndex++) { OpcUa_Socket pSocketTemp = &(pInternalSocketManager->pSockets[uintIndex]); if( (pInternalSocketManager->pSockets[uintIndex].bSocketIsInUse != OpcUa_False) && (pInternalSocketManager->pSockets[uintIndex].bInvalidSocket == OpcUa_False)) { OpcUa_Socket_HandleEvent(pSocketTemp, OPCUA_SOCKET_CLOSE_EVENT); OpcUa_P_RawSocket_Close(pInternalSocketManager->pSockets[uintIndex].rawSocket); } OpcUa_Socket_Clear(pSocketTemp); } OpcUa_P_Memory_Free(pInternalSocketManager->pSockets); } /* if(pInternalSocketManager->pSockets != OpcUa_Null) */ OpcUa_P_RawSocket_Close(pInternalSocketManager->pCookie); #if OPCUA_USE_SYNCHRONISATION OpcUa_P_Mutex_Unlock(pInternalSocketManager->pMutex); OpcUa_P_Mutex_Delete(&pInternalSocketManager->pMutex); #endif /* OPCUA_USE_SYNCHRONISATION */ #if OPCUA_MULTITHREADED if(pInternalSocketManager->pStartupSemaphore != OpcUa_Null) { OpcUa_P_Semaphore_Delete(&pInternalSocketManager->pStartupSemaphore); } if(pInternalSocketManager->pSocketManagers != OpcUa_Null) { OpcUa_P_Memory_Free(pInternalSocketManager->pSocketManagers); } #endif OpcUa_P_Memory_Free(*a_pSocketManager); *a_pSocketManager = OpcUa_Null; return; }
/*============================================================================ * OpcUa_TcpSecureChannel_GetCurrentSecuritySet *===========================================================================*/ OpcUa_StatusCode OpcUa_TcpSecureChannel_GetCurrentSecuritySet( OpcUa_SecureChannel* a_pSecureChannel, OpcUa_UInt32* a_puTokenId, OpcUa_SecurityKeyset** a_ppReceivingKeyset, OpcUa_SecurityKeyset** a_ppSendingKeyset, OpcUa_CryptoProvider** a_ppCryptoProvider) { OpcUa_InitializeStatus(OpcUa_Module_SecureChannel, "GetCurrentSecuritySet"); OpcUa_ReturnErrorIfArgumentNull(a_pSecureChannel); OPCUA_SECURECHANNEL_LOCK(a_pSecureChannel); if(a_pSecureChannel->bCurrentTokenActive != OpcUa_False) { OpcUa_Trace(OPCUA_TRACE_LEVEL_DEBUG, "GetCurrentSecuritySet: Current Keysets requested. Returned token id is %u\n", a_pSecureChannel->CurrentChannelSecurityToken.TokenId); if(a_puTokenId != OpcUa_Null) { *a_puTokenId = a_pSecureChannel->CurrentChannelSecurityToken.TokenId; } if(a_ppReceivingKeyset != OpcUa_Null) { *a_ppReceivingKeyset = a_pSecureChannel->pCurrentReceivingKeyset; } if(a_ppSendingKeyset != OpcUa_Null) { *a_ppSendingKeyset = a_pSecureChannel->pCurrentSendingKeyset; } if(a_ppCryptoProvider != OpcUa_Null) { *a_ppCryptoProvider = a_pSecureChannel->pCurrentCryptoProvider; } } else { OpcUa_Trace(OPCUA_TRACE_LEVEL_DEBUG, "GetCurrentSecuritySet: Current Keysets requested. Inactive. Returned token id is %u\n", a_pSecureChannel->PreviousChannelSecurityToken.TokenId); if(a_puTokenId != OpcUa_Null) { *a_puTokenId = a_pSecureChannel->PreviousChannelSecurityToken.TokenId; } if(a_ppReceivingKeyset != OpcUa_Null) { *a_ppReceivingKeyset = a_pSecureChannel->pPreviousReceivingKeyset; } if(a_ppSendingKeyset != OpcUa_Null) { *a_ppSendingKeyset = a_pSecureChannel->pPreviousSendingKeyset; } if(a_ppCryptoProvider != OpcUa_Null) { *a_ppCryptoProvider = a_pSecureChannel->pPreviousCryptoProvider; } } OpcUa_ReturnStatusCode; OpcUa_BeginErrorHandling; OpcUa_FinishErrorHandling; }
/*============================================================================ * OpcUa_SecureChannel_Renew *===========================================================================*/ OpcUa_StatusCode OpcUa_TcpSecureChannel_Renew( OpcUa_SecureChannel* a_pSecureChannel, OpcUa_Handle a_hTransportConnection, OpcUa_ChannelSecurityToken a_ChannelSecurityToken, OpcUa_MessageSecurityMode a_eMessageSecurityMode, OpcUa_ByteString* a_pbsClientCertificate, OpcUa_ByteString* a_pbsServerCertificate, OpcUa_SecurityKeyset* a_pNewReceivingKeyset, OpcUa_SecurityKeyset* a_pNewSendingKeyset, OpcUa_CryptoProvider* a_pNewCryptoProvider) { OpcUa_InitializeStatus(OpcUa_Module_SecureChannel, "Renew"); OpcUa_ReturnErrorIfArgumentNull(a_pSecureChannel); OpcUa_ReturnErrorIfArgumentNull(a_hTransportConnection); OpcUa_ReturnErrorIfArgumentNull(a_pNewCryptoProvider); OPCUA_SECURECHANNEL_LOCK(a_pSecureChannel); OpcUa_Trace(OPCUA_TRACE_LEVEL_INFO, "OpcUa_TcpSecureChannel_Renew: New token id for channel %u is %u\n", a_pSecureChannel->SecureChannelId, a_ChannelSecurityToken.TokenId); if(a_pSecureChannel->TransportConnection != a_hTransportConnection) { OpcUa_GotoErrorWithStatus(OpcUa_BadSecureChannelIdInvalid); } if(a_pSecureChannel->SecureChannelId != a_ChannelSecurityToken.ChannelId) { OpcUa_GotoErrorWithStatus(OpcUa_BadSecureChannelIdInvalid); } /*** TCP SECURECHANNEL ***/ /* Previous objects will be overwritten by current objects */ a_pSecureChannel->bCurrentTokenActive = OpcUa_False; /* set channelSecurityToken members */ a_pSecureChannel->PreviousChannelSecurityToken.ChannelId = a_pSecureChannel->CurrentChannelSecurityToken.ChannelId; a_pSecureChannel->PreviousChannelSecurityToken.TokenId = a_pSecureChannel->CurrentChannelSecurityToken.TokenId; a_pSecureChannel->PreviousChannelSecurityToken.CreatedAt = a_pSecureChannel->CurrentChannelSecurityToken.CreatedAt; a_pSecureChannel->PreviousChannelSecurityToken.RevisedLifetime = a_pSecureChannel->CurrentChannelSecurityToken.RevisedLifetime; /* set current channelSecurityToken */ a_pSecureChannel->CurrentChannelSecurityToken.ChannelId = a_ChannelSecurityToken.ChannelId; a_pSecureChannel->CurrentChannelSecurityToken.TokenId = a_ChannelSecurityToken.TokenId; a_pSecureChannel->CurrentChannelSecurityToken.CreatedAt = a_ChannelSecurityToken.CreatedAt; a_pSecureChannel->CurrentChannelSecurityToken.RevisedLifetime = a_ChannelSecurityToken.RevisedLifetime; /*** SECURECHANNEL ***/ a_pSecureChannel->State = OpcUa_SecureChannelState_Opened; a_pSecureChannel->MessageSecurityMode = a_eMessageSecurityMode; a_pSecureChannel->uExpirationCounter = (OpcUa_UInt32)(a_pSecureChannel->CurrentChannelSecurityToken.RevisedLifetime/OPCUA_SECURELISTENER_WATCHDOG_INTERVAL); a_pSecureChannel->uOverlapCounter = (OpcUa_UInt32)((a_pSecureChannel->CurrentChannelSecurityToken.RevisedLifetime>>2)/OPCUA_SECURELISTENER_WATCHDOG_INTERVAL); /* free old certificate and add new one */ OpcUa_ByteString_Clear(&a_pSecureChannel->ClientCertificate); /* copy client certificate!!! */ if(a_pbsClientCertificate != OpcUa_Null && a_pbsClientCertificate->Length > 0) { a_pSecureChannel->ClientCertificate.Data = (OpcUa_Byte*)OpcUa_Alloc(a_pbsClientCertificate->Length); OpcUa_GotoErrorIfAllocFailed(a_pSecureChannel->ClientCertificate.Data); a_pSecureChannel->ClientCertificate.Length = a_pbsClientCertificate->Length; OpcUa_MemCpy( a_pSecureChannel->ClientCertificate.Data, a_pSecureChannel->ClientCertificate.Length, a_pbsClientCertificate->Data, a_pbsClientCertificate->Length); } /* free old certificate and add new one */ OpcUa_ByteString_Clear(&a_pSecureChannel->ServerCertificate); if(a_pbsServerCertificate != OpcUa_Null && a_pbsServerCertificate->Length > 0) { a_pSecureChannel->ServerCertificate.Data = (OpcUa_Byte*)OpcUa_Alloc(a_pbsServerCertificate->Length); OpcUa_GotoErrorIfAllocFailed(a_pSecureChannel->ServerCertificate.Data); a_pSecureChannel->ServerCertificate.Length = a_pbsServerCertificate->Length; OpcUa_MemCpy( a_pSecureChannel->ServerCertificate.Data, a_pSecureChannel->ServerCertificate.Length, a_pbsServerCertificate->Data, a_pbsServerCertificate->Length); } /* delete previous keysets */ OpcUa_SecurityKeyset_Clear(a_pSecureChannel->pPreviousReceivingKeyset); OpcUa_SecurityKeyset_Clear(a_pSecureChannel->pPreviousSendingKeyset); OpcUa_Free(a_pSecureChannel->pPreviousReceivingKeyset); OpcUa_Free(a_pSecureChannel->pPreviousSendingKeyset); a_pSecureChannel->pPreviousReceivingKeyset = OpcUa_Null; a_pSecureChannel->pPreviousSendingKeyset = OpcUa_Null; /* assign current to previous */ a_pSecureChannel->pPreviousReceivingKeyset = a_pSecureChannel->pCurrentReceivingKeyset; a_pSecureChannel->pPreviousSendingKeyset = a_pSecureChannel->pCurrentSendingKeyset; /* delete previous cryptoprovider */ if( a_pSecureChannel->pPreviousCryptoProvider != OpcUa_Null && a_pSecureChannel->pPreviousCryptoProvider != a_pSecureChannel->pCurrentCryptoProvider) { OPCUA_P_CRYPTOFACTORY_DELETECRYPTOPROVIDER(a_pSecureChannel->pPreviousCryptoProvider); OpcUa_Free(a_pSecureChannel->pPreviousCryptoProvider); a_pSecureChannel->pPreviousCryptoProvider = OpcUa_Null; } else { a_pSecureChannel->pPreviousCryptoProvider = OpcUa_Null; } /* make current cryptoprovider previous */ a_pSecureChannel->pPreviousCryptoProvider = a_pSecureChannel->pCurrentCryptoProvider; a_pSecureChannel->pCurrentCryptoProvider = a_pNewCryptoProvider; a_pSecureChannel->pCurrentReceivingKeyset = a_pNewReceivingKeyset; a_pSecureChannel->pCurrentSendingKeyset = a_pNewSendingKeyset; OPCUA_SECURECHANNEL_UNLOCK(a_pSecureChannel); OpcUa_ReturnStatusCode; OpcUa_BeginErrorHandling; OpcUa_SecurityKeyset_Clear(a_pNewReceivingKeyset); OpcUa_SecurityKeyset_Clear(a_pNewSendingKeyset); OpcUa_Free(a_pNewReceivingKeyset); OpcUa_Free(a_pNewSendingKeyset); OPCUA_SECURECHANNEL_UNLOCK(a_pSecureChannel); OpcUa_FinishErrorHandling; }
/*============================================================================ * OpcUa_TcpSecureChannel_GetSecuritySet *===========================================================================*/ OpcUa_StatusCode OpcUa_TcpSecureChannel_GetSecuritySet( OpcUa_SecureChannel* a_pSecureChannel, OpcUa_UInt32 a_uTokenId, OpcUa_SecurityKeyset** a_ppReceivingKeyset, OpcUa_SecurityKeyset** a_ppSendingKeyset, OpcUa_CryptoProvider** a_ppCryptoProvider) { OpcUa_InitializeStatus(OpcUa_Module_SecureChannel, "GetSecuritySet"); OpcUa_ReturnErrorIfArgumentNull(a_pSecureChannel); OpcUa_Trace(OPCUA_TRACE_LEVEL_DEBUG, "GetSecurityKeyset: Keysets for token id %u requested.\n", a_uTokenId); OPCUA_SECURECHANNEL_LOCK(a_pSecureChannel); if(a_pSecureChannel->CurrentChannelSecurityToken.TokenId == a_uTokenId) { /* immediately activate the new keyset */ a_pSecureChannel->bCurrentTokenActive = OpcUa_True; if(a_ppReceivingKeyset != OpcUa_Null) { *a_ppReceivingKeyset = a_pSecureChannel->pCurrentReceivingKeyset; } if(a_ppSendingKeyset != OpcUa_Null) { *a_ppSendingKeyset = a_pSecureChannel->pCurrentSendingKeyset; } if(a_ppCryptoProvider != OpcUa_Null) { *a_ppCryptoProvider = a_pSecureChannel->pCurrentCryptoProvider; } } else if(a_pSecureChannel->PreviousChannelSecurityToken.TokenId == a_uTokenId) { if(a_ppReceivingKeyset != OpcUa_Null) { *a_ppReceivingKeyset = a_pSecureChannel->pPreviousReceivingKeyset; } if(a_ppSendingKeyset != OpcUa_Null) { *a_ppSendingKeyset = a_pSecureChannel->pPreviousSendingKeyset; } if(a_ppCryptoProvider != OpcUa_Null) { *a_ppCryptoProvider = a_pSecureChannel->pPreviousCryptoProvider; } } else { uStatus = OpcUa_BadSecureChannelTokenUnknown; OpcUa_Trace(OPCUA_TRACE_LEVEL_ERROR, "GetSecurityKeyset: Token id %u at secure channel %u invalid!\n", a_uTokenId, a_pSecureChannel->SecureChannelId); OPCUA_SECURECHANNEL_UNLOCK(a_pSecureChannel); } OpcUa_ReturnStatusCode; OpcUa_BeginErrorHandling; OpcUa_FinishErrorHandling; }