/*============================================================================ * Clear and free the mutex. *===========================================================================*/ OpcUa_Void OPCUA_DLLCALL OpcUa_P_Mutex_DeleteImp(OpcUa_Mutex* phMutex, char* file, int line) { OpcUa_Int32 nMutexId; CRITICAL_SECTION *pCS = NULL; OpcUa_P_InternalMutex* pInternalMutex = OpcUa_Null; if(phMutex == OpcUa_Null || *phMutex == OpcUa_Null) { printf("Invalid Argument Error in: OpcUa_P_Mutex_Delete!\n"); return; } pInternalMutex = (OpcUa_P_InternalMutex*)*phMutex; pCS = (CRITICAL_SECTION*)pInternalMutex->pSystemMutex; if(pInternalMutex->nLockCount != 0) { printf("Error in OpcUa_P_Mutex_Delete. LockCount != 0.\n"); } nMutexId = pInternalMutex->nMutexId; OpcUa_P_Memory_Free(pInternalMutex); DeleteCriticalSection(pCS); OpcUa_P_Memory_Free(pCS); *phMutex = OpcUa_Null; /* printf("Deleted Mutex%d, File: %s, Line: %d\n", nMutexId, file, line); */ return; }
/*============================================================================ * Delete Raw Thread *===========================================================================*/ OpcUa_Void OPCUA_DLLCALL OpcUa_P_Thread_Delete(OpcUa_RawThread* pRawThread) { OpcUa_P_ThreadArg* pThreadArgs = OpcUa_Null; if(pRawThread == OpcUa_Null || *pRawThread == OpcUa_Null) { return; } else { pThreadArgs = *pRawThread; if(INVALID_HANDLE_VALUE != pThreadArgs->hThread) { WaitForSingleObject(pThreadArgs->hThread, INFINITE); CloseHandle(pThreadArgs->hThread); } pThreadArgs->hThread = INVALID_HANDLE_VALUE; pThreadArgs->pfnInternalThreadMain = OpcUa_Null; pThreadArgs->ThreadArgs = OpcUa_Null; } OpcUa_P_Memory_Free(pThreadArgs); *pRawThread = OpcUa_Null; return; }
/*============================================================================ * Create a UDP sender socket *===========================================================================*/ OpcUa_StatusCode OPCUA_DLLCALL OpcUa_P_SocketUdp_CreateSender( OpcUa_StringA a_LocalIpAddress, OpcUa_StringA a_RemoteIpAddress, OpcUa_Int16 a_RemotePort, OpcUa_Byte a_TimeToLive, OpcUa_Socket* a_pSocket) { OpcUa_InternalUdpSocket* pInternalSocket = OpcUa_Null; OpcUa_InitializeStatus(OpcUa_Module_Socket, "CreateUdpSender"); OpcUa_ReturnErrorIfArgumentNull(a_pSocket); *a_pSocket = OpcUa_Null; OpcUa_GotoErrorIfArgumentNull(a_RemoteIpAddress); if(a_RemotePort == 0) { OpcUa_GotoErrorWithStatus(OpcUa_BadInvalidArgument); } pInternalSocket = (OpcUa_InternalUdpSocket*)OpcUa_P_Memory_Alloc(sizeof(OpcUa_InternalUdpSocket)); OpcUa_GotoErrorIfAllocFailed(pInternalSocket); pInternalSocket->pSocketServiceTable = &OpcUa_UdpSocketServiceTable; if(strchr(a_RemoteIpAddress, ':')) { uStatus = OpcUa_P_RawSocket_CreateUdpV6(&pInternalSocket->rawSocket, OpcUa_True, a_LocalIpAddress, a_RemoteIpAddress, a_RemotePort, a_TimeToLive); OpcUa_GotoErrorIfBad(uStatus); } else { uStatus = OpcUa_P_RawSocket_CreateUdp(&pInternalSocket->rawSocket, OpcUa_True, a_LocalIpAddress, a_RemoteIpAddress, a_RemotePort, a_TimeToLive); OpcUa_GotoErrorIfBad(uStatus); } *a_pSocket = pInternalSocket; OpcUa_ReturnStatusCode; OpcUa_BeginErrorHandling; if(pInternalSocket != OpcUa_Null) { OpcUa_P_Memory_Free(pInternalSocket); } OpcUa_FinishErrorHandling; }
/*============================================================================ * Clear and free the mutex. *===========================================================================*/ OpcUa_Void OPCUA_DLLCALL OpcUa_P_Mutex_Delete(OpcUa_Mutex* phMutex) { if( phMutex == OpcUa_Null || *phMutex == OpcUa_Null) { return; } else { OpcUa_P_Mutex_Clear(*phMutex); OpcUa_P_Memory_Free(*phMutex); *phMutex = OpcUa_Null; } }
/*============================================================================ * Close UDP Socket. *===========================================================================*/ static OpcUa_StatusCode OpcUa_P_SocketService_UdpClose(OpcUa_Socket a_pSocket) { OpcUa_InternalUdpSocket* pInternalSocket = (OpcUa_InternalUdpSocket*)a_pSocket; OpcUa_InitializeStatus(OpcUa_Module_Socket, "UdpClose"); OpcUa_GotoErrorIfArgumentNull(a_pSocket); OpcUa_P_RawSocket_Close(pInternalSocket->rawSocket); OpcUa_P_Memory_Free(pInternalSocket); OpcUa_ReturnStatusCode; OpcUa_BeginErrorHandling; OpcUa_FinishErrorHandling; }
/*============================================================================ * Allocate the mutex. *===========================================================================*/ OpcUa_StatusCode OPCUA_DLLCALL OpcUa_P_Mutex_CreateImp(OpcUa_Mutex* a_phMutex) { OpcUa_StatusCode uStatus = OpcUa_Good; LPCRITICAL_SECTION lpCriticalSection = NULL; #if OPCUA_MUTEX_USE_SPINCOUNT BOOL bRet; LONG hr; #endif if(a_phMutex == OpcUa_Null) { return OpcUa_BadInvalidArgument; } if(*a_phMutex != OpcUa_Null) { *a_phMutex = OpcUa_Null; } lpCriticalSection = OpcUa_P_Memory_Alloc(sizeof(CRITICAL_SECTION)); if(lpCriticalSection == NULL) { return OpcUa_BadOutOfMemory; } #if OPCUA_MUTEX_USE_SPINCOUNT bRet = InitializeCriticalSectionAndSpinCount( lpCriticalSection, 0x00000400) ; if (bRet == 0) { hr = GetLastError(); OpcUa_P_Memory_Free(lpCriticalSection); return OpcUa_Bad; } #else InitializeCriticalSection(lpCriticalSection); #endif *a_phMutex = (OpcUa_Mutex)lpCriticalSection; return uStatus; }
/*============================================================================ * Clear and free the mutex. *===========================================================================*/ OpcUa_Void OPCUA_DLLCALL OpcUa_P_Mutex_DeleteImp(OpcUa_Mutex* a_phMutex) { LPCRITICAL_SECTION lpCriticalSection = NULL; if(a_phMutex == OpcUa_Null || *a_phMutex == OpcUa_Null) { return; } lpCriticalSection = (LPCRITICAL_SECTION)*a_phMutex; DeleteCriticalSection(lpCriticalSection); OpcUa_P_Memory_Free(lpCriticalSection); *a_phMutex = OpcUa_Null; return; }
/*============================================================================ * OpcUa_P_OpenSSL_RSA_LoadPrivateKeyFromFile *===========================================================================*/ OpcUa_StatusCode OpcUa_P_OpenSSL_RSA_LoadPrivateKeyFromFile( OpcUa_StringA a_privateKeyFile, OpcUa_P_FileFormat a_fileFormat, OpcUa_StringA a_password, /* optional: just needed encrypted PEM */ OpcUa_ByteString* a_pPrivateKey) { BIO* pPrivateKeyFile = OpcUa_Null; RSA* pRsaPrivateKey = OpcUa_Null; EVP_PKEY* pEvpKey = OpcUa_Null; unsigned char* pData; OpcUa_InitializeStatus(OpcUa_Module_P_OpenSSL, "RSA_LoadPrivateKeyFromFile"); /* check parameters */ OpcUa_ReturnErrorIfArgumentNull(a_privateKeyFile); OpcUa_ReturnErrorIfArgumentNull(a_pPrivateKey); if(a_fileFormat == OpcUa_Crypto_Encoding_Invalid) { return OpcUa_BadInvalidArgument; } OpcUa_ReferenceParameter(a_password); /* open file */ pPrivateKeyFile = BIO_new_file((const char*)a_privateKeyFile, "rb"); OpcUa_ReturnErrorIfArgumentNull(pPrivateKeyFile); /* read and convert file */ switch(a_fileFormat) { case OpcUa_Crypto_Encoding_PEM: { /* read from file */ pEvpKey = PEM_read_bio_PrivateKey( pPrivateKeyFile, /* file */ NULL, /* key struct */ 0, /* password callback */ a_password); /* default passphrase or arbitrary handle */ OpcUa_GotoErrorIfNull(pEvpKey, OpcUa_Bad); break; } case OpcUa_Crypto_Encoding_PKCS12: { int iResult = 0; /* read from file. */ PKCS12* pPkcs12 = d2i_PKCS12_bio(pPrivateKeyFile, NULL); if (pPkcs12 == 0) { OpcUa_GotoErrorWithStatus(OpcUa_BadEncodingError); } /* parse the certificate. */ iResult = PKCS12_parse(pPkcs12, a_password, &pEvpKey, NULL, NULL); if (iResult == 0) { OpcUa_GotoErrorWithStatus(OpcUa_BadEncodingError); } /* free certificate. */ PKCS12_free(pPkcs12); pPkcs12 = NULL; break; } case OpcUa_Crypto_Encoding_DER: default: { uStatus = OpcUa_BadNotSupported; OpcUa_GotoError; } } /* convert to intermediary openssl struct */ pRsaPrivateKey = EVP_PKEY_get1_RSA(pEvpKey); EVP_PKEY_free(pEvpKey); OpcUa_GotoErrorIfNull(pRsaPrivateKey, OpcUa_Bad); /* get required length */ a_pPrivateKey->Length = i2d_RSAPrivateKey(pRsaPrivateKey, OpcUa_Null); OpcUa_GotoErrorIfTrue((a_pPrivateKey->Length <= 0), OpcUa_Bad); /* allocate target buffer */ a_pPrivateKey->Data = (OpcUa_Byte*)OpcUa_P_Memory_Alloc(a_pPrivateKey->Length); OpcUa_GotoErrorIfAllocFailed(a_pPrivateKey->Data); /* do real conversion */ pData = a_pPrivateKey->Data; a_pPrivateKey->Length = i2d_RSAPrivateKey(pRsaPrivateKey, &pData); OpcUa_GotoErrorIfTrue((a_pPrivateKey->Length <= 0), OpcUa_Bad); RSA_free(pRsaPrivateKey); BIO_free(pPrivateKeyFile); OpcUa_ReturnStatusCode; OpcUa_BeginErrorHandling; if(pEvpKey) { EVP_PKEY_free(pEvpKey); } if(a_pPrivateKey != OpcUa_Null) { if(a_pPrivateKey->Data != OpcUa_Null) { OpcUa_P_Memory_Free(a_pPrivateKey->Data); a_pPrivateKey->Data = OpcUa_Null; a_pPrivateKey->Length = -1; } } if(pPrivateKeyFile != NULL) { BIO_free(pPrivateKeyFile); } if(pRsaPrivateKey != NULL) { RSA_free(pRsaPrivateKey); } OpcUa_FinishErrorHandling; }
/* ToDo: Create Access to OpenSSL certificate store => Only API to In-Memory-Store is available for version 0.9.8x => Wait until Directory- and/or File-Store is available */ OpcUa_StatusCode OpcUa_P_OpenSSL_PKI_LoadCertificate( OpcUa_PKIProvider* a_pProvider, OpcUa_Void* a_pLoadHandle, OpcUa_Void* a_pCertificateStore, OpcUa_ByteString* a_pCertificate) { OpcUa_Byte* buf = OpcUa_Null; OpcUa_Byte* p = OpcUa_Null; FILE* pCertificateFile = OpcUa_Null; X509* pTmpCert = OpcUa_Null; OpcUa_InitializeStatus(OpcUa_Module_P_OpenSSL, "PKI_LoadCertificate"); OpcUa_ReturnErrorIfArgumentNull(a_pProvider); OpcUa_ReturnErrorIfArgumentNull(a_pProvider->Handle); OpcUa_ReturnErrorIfArgumentNull(a_pLoadHandle); OpcUa_ReturnErrorIfArgumentNull(a_pCertificateStore); OpcUa_ReturnErrorIfArgumentNull(a_pCertificate); /* read DER certificates */ pCertificateFile = fopen((const char*)a_pLoadHandle, "r"); /* check for valid file handle */ OpcUa_GotoErrorIfTrue((pCertificateFile == OpcUa_Null), OpcUa_BadInvalidArgument); if(!(pTmpCert = d2i_X509_fp(pCertificateFile, (X509**)OpcUa_Null))) { uStatus = OpcUa_Bad; OpcUa_GotoErrorIfBad(uStatus); } a_pCertificate->Length = i2d_X509(pTmpCert, NULL); buf = (OpcUa_Byte*)OpcUa_P_Memory_Alloc(a_pCertificate->Length); OpcUa_GotoErrorIfAllocFailed(buf); p = buf; for (;;) { i2d_X509(pTmpCert, &p); X509_free(pTmpCert); if(!(pTmpCert = d2i_X509_fp(pCertificateFile, (X509**)OpcUa_Null))) { break; } p = OpcUa_P_Memory_ReAlloc(buf, a_pCertificate->Length + i2d_X509(pTmpCert, NULL)); OpcUa_GotoErrorIfAllocFailed(p); buf = p; p = buf + a_pCertificate->Length; a_pCertificate->Length += i2d_X509(pTmpCert, NULL); } if(fclose(pCertificateFile) != 0) { pCertificateFile = OpcUa_Null; uStatus = OpcUa_Bad; OpcUa_GotoErrorIfBad(uStatus); } a_pCertificate->Data = buf; OpcUa_ReturnStatusCode; OpcUa_BeginErrorHandling; if(pCertificateFile != OpcUa_Null) { fclose(pCertificateFile); } if(pTmpCert != OpcUa_Null) { X509_free(pTmpCert); } if(buf != OpcUa_Null) { OpcUa_P_Memory_Free(buf); } OpcUa_FinishErrorHandling; }
/** @brief Extracts data from a certificate store object. @param pCertificate [in] The certificate to examine. @param pIssuer [out, optional] The issuer name of the certificate. @param pSubject [out, optional] The subject name of the certificate. @param pSubjectUri [out, optional] The subject's URI of the certificate. @param pSubjectIP [out, optional] The subject's IP of the certificate. @param pSubjectDNS [out, optional] The subject's DNS name of the certificate. @param pCertThumbprint [out, optional] The thumbprint of the certificate. @param pSubjectHash [out, optional] The hash code of the certificate. @param pCertRawLength [out, optional] The length of the DER encoded data. can be smaller than the total length of pCertificate in case of chain certificate or garbage follow. */ OpcUa_StatusCode OpcUa_P_OpenSSL_PKI_ExtractCertificateData( OpcUa_ByteString* a_pCertificate, OpcUa_ByteString* a_pIssuer, OpcUa_ByteString* a_pSubject, OpcUa_ByteString* a_pSubjectUri, OpcUa_ByteString* a_pSubjectIP, OpcUa_ByteString* a_pSubjectDNS, OpcUa_ByteString* a_pCertThumbprint, OpcUa_UInt32* a_pSubjectHash, OpcUa_UInt32* a_pCertRawLength) { X509* pX509Cert = OpcUa_Null; char* pName = OpcUa_Null; GENERAL_NAMES* pNames = OpcUa_Null; const unsigned char* p; OpcUa_InitializeStatus(OpcUa_Module_P_OpenSSL, "PKI_ExtractCertificateData"); OpcUa_ReturnErrorIfArgumentNull(a_pCertificate); if(a_pIssuer != OpcUa_Null) { a_pIssuer->Data = OpcUa_Null; a_pIssuer->Length = 0; } if(a_pSubject != OpcUa_Null) { a_pSubject->Data = OpcUa_Null; a_pSubject->Length = 0; } if(a_pSubjectUri != OpcUa_Null) { a_pSubjectUri->Data = OpcUa_Null; a_pSubjectUri->Length = 0; } if(a_pSubjectIP != OpcUa_Null) { a_pSubjectIP->Data = OpcUa_Null; a_pSubjectIP->Length = 0; } if(a_pSubjectDNS != OpcUa_Null) { a_pSubjectDNS->Data = OpcUa_Null; a_pSubjectDNS->Length = 0; } if(a_pCertThumbprint != OpcUa_Null) { a_pCertThumbprint->Data = OpcUa_Null; a_pCertThumbprint->Length = 0; } if(a_pSubjectHash != OpcUa_Null) { *a_pSubjectHash = 0; } if(a_pCertRawLength != OpcUa_Null) { *a_pCertRawLength = 0; } /* convert openssl X509 certificate to DER encoded bytestring certificate */ p = a_pCertificate->Data; if(!(pX509Cert = d2i_X509((X509**)OpcUa_Null, &p, a_pCertificate->Length))) { uStatus = OpcUa_Bad; OpcUa_GotoErrorIfBad(uStatus); } if(a_pIssuer != OpcUa_Null) { pName = X509_NAME_oneline(X509_get_issuer_name(pX509Cert), NULL, 0); OpcUa_GotoErrorIfAllocFailed(pName); a_pIssuer->Length = strlen(pName)+1; a_pIssuer->Data = (OpcUa_Byte*)OpcUa_P_Memory_Alloc(a_pIssuer->Length*sizeof(OpcUa_Byte)); OpcUa_GotoErrorIfAllocFailed(a_pIssuer->Data); uStatus = OpcUa_P_Memory_MemCpy(a_pIssuer->Data, a_pIssuer->Length, pName, a_pIssuer->Length); OpcUa_GotoErrorIfBad(uStatus); OPENSSL_free(pName); pName = OpcUa_Null; } if(a_pSubject != OpcUa_Null) { pName = X509_NAME_oneline(X509_get_subject_name(pX509Cert), NULL, 0); OpcUa_GotoErrorIfAllocFailed(pName); a_pSubject->Length = strlen(pName)+1; a_pSubject->Data = (OpcUa_Byte*)OpcUa_P_Memory_Alloc(a_pSubject->Length*sizeof(OpcUa_Byte)); OpcUa_GotoErrorIfAllocFailed(a_pSubject->Data); uStatus = OpcUa_P_Memory_MemCpy(a_pSubject->Data, a_pSubject->Length, pName, a_pSubject->Length); OpcUa_GotoErrorIfBad(uStatus); OPENSSL_free(pName); pName = OpcUa_Null; } if(a_pSubjectUri != OpcUa_Null || a_pSubjectIP != OpcUa_Null || a_pSubjectDNS != OpcUa_Null) { pNames = X509_get_ext_d2i(pX509Cert, NID_subject_alt_name, OpcUa_Null, OpcUa_Null); if (pNames != OpcUa_Null) { int num; for (num = 0; num < sk_GENERAL_NAME_num(pNames); num++) { GENERAL_NAME *value = sk_GENERAL_NAME_value(pNames, num); switch (value->type) { case GEN_URI: if (a_pSubjectUri != OpcUa_Null && a_pSubjectUri->Data == OpcUa_Null) { a_pSubjectUri->Length = value->d.ia5->length+1; a_pSubjectUri->Data = (OpcUa_Byte*)OpcUa_P_Memory_Alloc(a_pSubjectUri->Length*sizeof(OpcUa_Byte)); OpcUa_GotoErrorIfAllocFailed(a_pSubjectUri->Data); uStatus = OpcUa_P_Memory_MemCpy(a_pSubjectUri->Data, a_pSubjectUri->Length, value->d.ia5->data, a_pSubjectUri->Length); OpcUa_GotoErrorIfBad(uStatus); } break; case GEN_IPADD: if (a_pSubjectIP != OpcUa_Null && a_pSubjectIP->Data == OpcUa_Null) { a_pSubjectIP->Length = value->d.ip->length; a_pSubjectIP->Data = (OpcUa_Byte*)OpcUa_P_Memory_Alloc(a_pSubjectIP->Length*sizeof(OpcUa_Byte)); OpcUa_GotoErrorIfAllocFailed(a_pSubjectIP->Data); uStatus = OpcUa_P_Memory_MemCpy(a_pSubjectIP->Data, a_pSubjectIP->Length, value->d.ip->data, a_pSubjectIP->Length); OpcUa_GotoErrorIfBad(uStatus); } break; case GEN_DNS: if (a_pSubjectDNS != OpcUa_Null && a_pSubjectDNS->Data == OpcUa_Null) { a_pSubjectDNS->Length = value->d.ia5->length+1; a_pSubjectDNS->Data = (OpcUa_Byte*)OpcUa_P_Memory_Alloc(a_pSubjectDNS->Length*sizeof(OpcUa_Byte)); OpcUa_GotoErrorIfAllocFailed(a_pSubjectDNS->Data); uStatus = OpcUa_P_Memory_MemCpy(a_pSubjectDNS->Data, a_pSubjectDNS->Length, value->d.ia5->data, a_pSubjectDNS->Length); OpcUa_GotoErrorIfBad(uStatus); } break; } } sk_GENERAL_NAME_pop_free(pNames, GENERAL_NAME_free); pNames = OpcUa_Null; } } if(a_pCertThumbprint != OpcUa_Null) { /* update pX509Cert->sha1_hash */ X509_check_purpose(pX509Cert, -1, 0); a_pCertThumbprint->Length = sizeof(pX509Cert->sha1_hash); a_pCertThumbprint->Data = (OpcUa_Byte*)OpcUa_P_Memory_Alloc(a_pCertThumbprint->Length*sizeof(OpcUa_Byte)); OpcUa_GotoErrorIfAllocFailed(a_pCertThumbprint->Data); uStatus = OpcUa_P_Memory_MemCpy(a_pCertThumbprint->Data, a_pCertThumbprint->Length, pX509Cert->sha1_hash, a_pCertThumbprint->Length); OpcUa_GotoErrorIfBad(uStatus); } if(a_pSubjectHash != OpcUa_Null) { *a_pSubjectHash = X509_NAME_hash(X509_get_subject_name(pX509Cert)); } if(a_pCertRawLength != OpcUa_Null) { *a_pCertRawLength = (OpcUa_UInt32)(p - a_pCertificate->Data); } X509_free(pX509Cert); OpcUa_ReturnStatusCode; OpcUa_BeginErrorHandling; if(a_pIssuer != OpcUa_Null && a_pIssuer->Data != OpcUa_Null) { OpcUa_P_Memory_Free(a_pIssuer->Data); a_pIssuer->Data = OpcUa_Null; a_pIssuer->Length = 0; } if(a_pSubject != OpcUa_Null && a_pSubject->Data != OpcUa_Null) { OpcUa_P_Memory_Free(a_pSubject->Data); a_pSubject->Data = OpcUa_Null; a_pSubject->Length = 0; } if(a_pSubjectUri != OpcUa_Null && a_pSubjectUri->Data != OpcUa_Null) { OpcUa_P_Memory_Free(a_pSubjectUri->Data); a_pSubjectUri->Data = OpcUa_Null; a_pSubjectUri->Length = 0; } if(a_pSubjectIP != OpcUa_Null && a_pSubjectIP->Data != OpcUa_Null) { OpcUa_P_Memory_Free(a_pSubjectIP->Data); a_pSubjectIP->Data = OpcUa_Null; a_pSubjectIP->Length = 0; } if(a_pSubjectDNS != OpcUa_Null && a_pSubjectDNS->Data != OpcUa_Null) { OpcUa_P_Memory_Free(a_pSubjectDNS->Data); a_pSubjectDNS->Data = OpcUa_Null; a_pSubjectDNS->Length = 0; } if(a_pCertThumbprint != OpcUa_Null && a_pCertThumbprint->Data != OpcUa_Null) { OpcUa_P_Memory_Free(a_pCertThumbprint->Data); a_pCertThumbprint->Data = OpcUa_Null; a_pCertThumbprint->Length = 0; } if (pName != OpcUa_Null) { OPENSSL_free(pName); } if (pNames != OpcUa_Null) { sk_GENERAL_NAME_pop_free(pNames, GENERAL_NAME_free); } if(pX509Cert != OpcUa_Null) { X509_free(pX509Cert); } OpcUa_FinishErrorHandling; }
/*============================================================================ * Create a server socket *===========================================================================*/ OpcUa_StatusCode OPCUA_DLLCALL OpcUa_P_SocketManager_CreateServer( OpcUa_SocketManager a_pSocketManager, OpcUa_StringA a_sAddress, OpcUa_Boolean a_bListenOnAllInterfaces, OpcUa_Socket_EventCallback a_pfnSocketCallBack, OpcUa_Void* a_pCallbackData, OpcUa_Socket* a_pSocket) { OpcUa_InternalSocketManager* pInternalSocketManager = OpcUa_Null; OpcUa_UInt16 uPort = 0; OpcUa_StringA sRemoteAdress = OpcUa_Null; OpcUa_InitializeStatus(OpcUa_Module_Socket, "CreateServer"); #if !OPCUA_MULTITHREADED if(a_pSocketManager == OpcUa_Null) { a_pSocketManager = OpcUa_Socket_g_SocketManager; } #endif OpcUa_ReturnErrorIfArgumentNull(a_pSocketManager); OpcUa_ReturnErrorIfArgumentNull(a_pSocket); pInternalSocketManager = (OpcUa_InternalSocketManager*)a_pSocketManager; /* parse address */ uStatus = OpcUa_P_ParseUrl( a_sAddress, &sRemoteAdress, &uPort); OpcUa_ReturnErrorIfBad(uStatus); if(a_bListenOnAllInterfaces) { if(sRemoteAdress != OpcUa_Null) { OpcUa_P_Memory_Free(sRemoteAdress); sRemoteAdress = OpcUa_Null; } } uStatus = OpcUa_SocketManager_InternalCreateServer( pInternalSocketManager, sRemoteAdress, uPort, a_pfnSocketCallBack, a_pCallbackData, a_pSocket); OpcUa_GotoErrorIfBad(uStatus); OpcUa_P_SocketManager_InterruptLoop(pInternalSocketManager, OPCUA_SOCKET_RENEWLOOP_EVENT, OpcUa_False); if(sRemoteAdress != OpcUa_Null) { OpcUa_P_Memory_Free(sRemoteAdress); } OpcUa_ReturnStatusCode; OpcUa_BeginErrorHandling; if(sRemoteAdress != OpcUa_Null) { OpcUa_P_Memory_Free(sRemoteAdress); } OpcUa_FinishErrorHandling; }
/*============================================================================ * Create a client socket *===========================================================================*/ OpcUa_StatusCode OPCUA_DLLCALL OpcUa_P_SocketManager_CreateClient( OpcUa_SocketManager a_hSocketManager, OpcUa_StringA a_sRemoteAddress, OpcUa_UInt16 a_uLocalPort, OpcUa_Socket_EventCallback a_pfnSocketCallBack, OpcUa_Void* a_pCallbackData, OpcUa_Socket* a_pSocket) { OpcUa_InternalSocket* pNewClientSocket = OpcUa_Null; OpcUa_InternalSocketManager* pInternalSocketManager = OpcUa_Null; OpcUa_UInt16 uPort = 0; OpcUa_StringA sRemoteAdress = OpcUa_Null; OpcUa_InitializeStatus(OpcUa_Module_Socket, "CreateClient"); #if !OPCUA_MULTITHREADED if(a_hSocketManager == OpcUa_Null) { a_hSocketManager = OpcUa_Socket_g_SocketManager; } #endif OpcUa_ReturnErrorIfArgumentNull(a_hSocketManager); OpcUa_ReturnErrorIfArgumentNull(a_pSocket); OpcUa_ReturnErrorIfArgumentNull(a_sRemoteAddress); /* parse address */ uStatus = OpcUa_P_ParseUrl( a_sRemoteAddress, &sRemoteAdress, &uPort); OpcUa_ReturnErrorIfBad(uStatus); pInternalSocketManager = (OpcUa_InternalSocketManager*)a_hSocketManager; pNewClientSocket = (OpcUa_InternalSocket*)OpcUa_SocketManager_FindFreeSocket( (OpcUa_SocketManager)pInternalSocketManager, OpcUa_False); if (pNewClientSocket == OpcUa_Null) { OpcUa_P_Memory_Free(sRemoteAdress); uStatus = OpcUa_BadMaxConnectionsReached; /* no socket left in the list. */ goto Error; } /* Create client socket. */ pNewClientSocket->rawSocket = OpcUa_P_Socket_CreateClient( a_uLocalPort, uPort, sRemoteAdress, &uStatus); OpcUa_P_Memory_Free(sRemoteAdress); OpcUa_GotoErrorIfTrue( pNewClientSocket->rawSocket == (OpcUa_RawSocket)OPCUA_P_SOCKET_INVALID, OpcUa_BadCommunicationError); pNewClientSocket->pfnEventCallback = a_pfnSocketCallBack; pNewClientSocket->pvUserData = a_pCallbackData; pNewClientSocket->Flags.bOwnThread = OpcUa_False; pNewClientSocket->Flags.EventMask = OPCUA_SOCKET_READ_EVENT | OPCUA_SOCKET_EXCEPT_EVENT | OPCUA_SOCKET_CONNECT_EVENT | OPCUA_SOCKET_TIMEOUT_EVENT; OPCUA_SOCKET_SETVALID(pNewClientSocket); /* return the new client socket */ *a_pSocket = pNewClientSocket; /* break loop to add new socket into eventing */ uStatus = OpcUa_P_SocketManager_InterruptLoop( a_hSocketManager, OPCUA_SOCKET_RENEWLOOP_EVENT, OpcUa_False); OpcUa_GotoErrorIfBad(uStatus); OpcUa_ReturnStatusCode; OpcUa_BeginErrorHandling; if(pNewClientSocket != OpcUa_Null) { if(pNewClientSocket->rawSocket != (OpcUa_RawSocket)OPCUA_P_SOCKET_INVALID) { OpcUa_P_RawSocket_Close(pNewClientSocket->rawSocket); pNewClientSocket->rawSocket = (OpcUa_RawSocket)OPCUA_P_SOCKET_INVALID; } OPCUA_SOCKET_INVALIDATE(pNewClientSocket); } 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; }
/*============================================================================ * Create a new socket manager or initialize the global one (OpcUa_Null first). *===========================================================================*/ OpcUa_StatusCode OPCUA_DLLCALL OpcUa_P_SocketManager_Create(OpcUa_SocketManager* a_pSocketManager, OpcUa_UInt32 a_nSockets, OpcUa_UInt32 a_nFlags) { OpcUa_InternalSocketManager* pInternalSocketManager = OpcUa_Null; OpcUa_InitializeStatus(OpcUa_Module_Socket, "SocketManager_Create"); if(a_nFlags & 0xFFFFFFF8) { return OpcUa_BadInvalidArgument; } if(a_nSockets > OPCUA_P_SOCKETMANAGER_NUMBEROFSOCKETS) { return OpcUa_BadInvalidArgument; } /* set number of socket to maximum */ if(a_nSockets == 0) { a_nSockets = OPCUA_P_SOCKETMANAGER_NUMBEROFSOCKETS; } a_nSockets += 1; /* add signal socket to requested sockets */ #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) { return OpcUa_BadInvalidArgument; } *a_pSocketManager = OpcUa_SocketManager_Alloc(); OpcUa_GotoErrorIfAllocFailed(*a_pSocketManager); pInternalSocketManager = (OpcUa_InternalSocketManager*)*a_pSocketManager; OpcUa_SocketManager_Initialize(pInternalSocketManager); #if OPCUA_USE_SYNCHRONISATION uStatus = OpcUa_P_Mutex_Create(&pInternalSocketManager->pMutex); OpcUa_GotoErrorIfBad(uStatus); #endif /* OPCUA_USE_SYNCHRONISATION */ /* preallocate socket structures for all possible sockets (maxsockets) */ uStatus = OpcUa_SocketManager_CreateSockets((OpcUa_SocketManager)pInternalSocketManager, a_nSockets); OpcUa_GotoErrorIfBad(uStatus); pInternalSocketManager->uintLastExternalEvent = OPCUA_SOCKET_NO_EVENT; /* set the behaviour flags */ if((a_nFlags & OPCUA_SOCKET_SPAWN_THREAD_ON_ACCEPT) != OPCUA_SOCKET_NO_FLAG) { pInternalSocketManager->Flags.bSpawnThreadOnAccept = OpcUa_True; } if((a_nFlags & OPCUA_SOCKET_REJECT_ON_NO_THREAD) != OPCUA_SOCKET_NO_FLAG) { pInternalSocketManager->Flags.bRejectOnThreadFail = OpcUa_True; } if((a_nFlags & OPCUA_SOCKET_DONT_CLOSE_ON_EXCEPT) != OPCUA_SOCKET_NO_FLAG) { pInternalSocketManager->Flags.bDontCloseOnExcept = OpcUa_True; } uStatus = OpcUa_P_SocketManager_NewSignalSocket(pInternalSocketManager); OpcUa_GotoErrorIfBad(uStatus); #if OPCUA_MULTITHREADED if (pInternalSocketManager->Flags.bSpawnThreadOnAccept) { /* create a semaphore with no free resources for which a host can wait to be signalled. */ uStatus = OpcUa_P_Semaphore_Create(&pInternalSocketManager->pStartupSemaphore, 0, 1); OpcUa_GotoErrorIfBad(uStatus); pInternalSocketManager->pSocketManagers = OpcUa_P_Memory_Alloc(sizeof(OpcUa_InternalSocketManager*) * OPCUA_SOCKET_MAXMANAGERS); OpcUa_GotoErrorIfAllocFailed(pInternalSocketManager->pSocketManagers); OpcUa_MemSet(pInternalSocketManager->pSocketManagers, 0, sizeof(OpcUa_InternalSocketManager*) * OPCUA_SOCKET_MAXMANAGERS); } /* if multithreaded, create and start the server thread if the list is not the global list. */ uStatus = OpcUa_P_Thread_Create(&pInternalSocketManager->pThread); /* make raw thread */ OpcUa_GotoErrorIfBad(uStatus); uStatus = OpcUa_P_Thread_Start( pInternalSocketManager->pThread, OpcUa_P_SocketManager_ServerLoopThread, (OpcUa_Void*)pInternalSocketManager); OpcUa_GotoErrorIfBad(uStatus); #endif /* OPCUA_MULTITHREADED */ OpcUa_ReturnStatusCode; OpcUa_BeginErrorHandling; if(pInternalSocketManager != OpcUa_Null) { #if OPCUA_MULTITHREADED if(pInternalSocketManager->pThread != OpcUa_Null) { OpcUa_P_Thread_Delete(&pInternalSocketManager->pThread); } if(pInternalSocketManager->pSocketManagers != OpcUa_Null) { OpcUa_P_Memory_Free(pInternalSocketManager->pSocketManagers); } if(pInternalSocketManager->pStartupSemaphore != OpcUa_Null) { OpcUa_P_Semaphore_Delete(&pInternalSocketManager->pStartupSemaphore); } #endif /* OPCUA_MULTITHREADED */ if(pInternalSocketManager->pCookie != (OpcUa_RawSocket)OPCUA_P_SOCKET_INVALID) { OpcUa_P_RawSocket_Close(pInternalSocketManager->pCookie); } if(pInternalSocketManager->pSockets != OpcUa_Null) { if(pInternalSocketManager->pSockets[0].rawSocket != (OpcUa_RawSocket)OPCUA_P_SOCKET_INVALID) { OpcUa_P_RawSocket_Close(pInternalSocketManager->pSockets[0].rawSocket); } OpcUa_P_Memory_Free(pInternalSocketManager->pSockets); } #if OPCUA_USE_SYNCHRONISATION if(pInternalSocketManager->pMutex != OpcUa_Null) { OpcUa_P_Mutex_Delete(&pInternalSocketManager->pMutex); } #endif /* OPCUA_USE_SYNCHRONISATION */ OpcUa_P_Memory_Free(pInternalSocketManager); } *a_pSocketManager = OpcUa_Null; OpcUa_FinishErrorHandling; }
/*============================================================================ * OpcUa_P_OpenSSL_Random_Key_PSHA256_Derive *===========================================================================*/ OpcUa_StatusCode OpcUa_P_OpenSSL_Random_Key_PSHA256_Derive( OpcUa_CryptoProvider* a_pProvider, OpcUa_ByteString a_secret, /* clientnonce | servernonce, servernonce | clientnonce */ OpcUa_ByteString a_seed, OpcUa_Int32 a_keyLen, /* output len */ OpcUa_Key* a_pKey) { OpcUa_P_OpenSSL_PSHA256_Ctx*pCtx = OpcUa_Null; OpcUa_Byte* pBuffer = OpcUa_Null; OpcUa_Int bufferlength; OpcUa_Int i; OpcUa_Int iterations; OpcUa_CryptoProviderConfig* pConfig = OpcUa_Null; OpcUa_Int32 keyLen = 0; OpcUa_InitializeStatus(OpcUa_Module_P_OpenSSL, "Random_Key_PSHA256_Derive"); OpcUa_ReferenceParameter(a_pProvider); OpcUa_ReturnErrorIfArgumentNull(a_pProvider); OpcUa_ReturnErrorIfArgumentNull(a_secret.Data); OpcUa_ReturnErrorIfArgumentNull(a_seed.Data); OpcUa_ReturnErrorIfArgumentNull(a_pKey); keyLen = a_keyLen; if(keyLen < 0) { if(a_pProvider->Handle != OpcUa_Null) { /* get default configuration */ pConfig = (OpcUa_CryptoProviderConfig*)a_pProvider->Handle; keyLen = pConfig->SymmetricKeyLength; } else { uStatus = OpcUa_BadInvalidArgument; OpcUa_GotoErrorIfBad(uStatus); } } else if(keyLen > MAX_DERIVED_OUTPUT_LEN) { uStatus = OpcUa_BadInvalidArgument; OpcUa_GotoErrorIfBad(uStatus); } if(a_pKey->Key.Data == OpcUa_Null) { a_pKey->Key.Length = keyLen; OpcUa_ReturnStatusCode; } a_pKey->Type = OpcUa_Crypto_KeyType_Random; /** start creating key **/ pCtx = (OpcUa_P_OpenSSL_PSHA256_Ctx*)OpcUa_Null; iterations = keyLen/32 + (keyLen%32?1:0); bufferlength = iterations*32; pBuffer = (OpcUa_Byte *)OpcUa_P_Memory_Alloc(bufferlength * sizeof(OpcUa_Byte)); pCtx = OpcUa_P_OpenSSL_PSHA256_Context_Create(a_secret.Data, a_secret.Length, a_seed.Data, a_seed.Length); for(i=0; i<iterations; i++) { /* SHA256 produces 32 Bytes of output for every iteration */ uStatus = OpcUa_P_OpenSSL_PSHA256_Hash_Generate(pCtx, pBuffer + (i*32)); OpcUa_GotoErrorIfBad(uStatus); } OpcUa_P_Memory_MemCpy(a_pKey->Key.Data, a_pKey->Key.Length, pBuffer, keyLen); if(pCtx != OpcUa_Null) { OpcUa_P_Memory_Free(pCtx); pCtx = OpcUa_Null; } if(pBuffer != OpcUa_Null) { OpcUa_P_Memory_Free(pBuffer); pBuffer = OpcUa_Null; } OpcUa_ReturnStatusCode; OpcUa_BeginErrorHandling; if(pCtx != OpcUa_Null) { OpcUa_P_Memory_Free(pCtx); pCtx = OpcUa_Null; } if(pBuffer != OpcUa_Null) { OpcUa_P_Memory_Free(pBuffer); pBuffer = OpcUa_Null; } OpcUa_FinishErrorHandling; }
/*============================================================================ * OpcUa_P_ParseUrl *===========================================================================*/ OpcUa_StatusCode OpcUa_P_ParseUrl( OpcUa_StringA a_psUrl, OpcUa_StringA* a_psIpAddress, OpcUa_UInt16* a_puPort) { OpcUa_StringA sHostName = OpcUa_Null; OpcUa_UInt32 uHostNameLength = 0; OpcUa_CharA* sPort = OpcUa_Null; OpcUa_CharA* pcCursor; OpcUa_Int nIndex1 = 0; OpcUa_Int nIpStart; struct addrinfo* pAddrInfo = OpcUa_Null; OpcUa_InitializeStatus(OpcUa_Module_Utilities, "P_ParseUrl"); OpcUa_ReturnErrorIfArgumentNull(a_psUrl); OpcUa_ReturnErrorIfArgumentNull(a_psIpAddress); OpcUa_ReturnErrorIfArgumentNull(a_puPort); *a_psIpAddress = OpcUa_Null; /* check for // (end of protocol header) */ pcCursor = strstr(a_psUrl, "//"); if(pcCursor != OpcUa_Null) { /* begin of host address */ pcCursor += 2; nIndex1 = (OpcUa_Int)(pcCursor - a_psUrl); } /* skip protocol prefix and store beginning of ip adress */ nIpStart = nIndex1; /* skip host address (IPv6 address can contain colons!) */ while(a_psUrl[nIndex1] != '/' && a_psUrl[nIndex1] != 0) { if(a_psUrl[nIndex1] == ':') { sPort = &a_psUrl[nIndex1 + 1]; uHostNameLength = nIndex1 - nIpStart; } /* handle "opc.tcp://[::1]:4880/" */ if(a_psUrl[nIndex1] == ']' && sPort != OpcUa_Null && a_psUrl[nIpStart] == '[') { nIpStart++; uHostNameLength = nIndex1 - nIpStart; sPort = OpcUa_Null; if(a_psUrl[nIndex1 + 1] == ':') { sPort = &a_psUrl[nIndex1 + 2]; } break; } nIndex1++; } if(uHostNameLength == 0) { uHostNameLength = nIndex1 - nIpStart; } /* scan port */ if(sPort != OpcUa_Null) { /* convert port */ *a_puPort = (OpcUa_UInt16)OpcUa_P_CharAToInt(sPort); } else { /* return default port */ *a_puPort = OPCUA_TCP_DEFAULT_PORT; } sHostName = (OpcUa_StringA)OpcUa_P_Memory_Alloc(uHostNameLength + 1); if(sHostName == NULL) { OpcUa_GotoErrorWithStatus(OpcUa_BadOutOfMemory); } memcpy(sHostName, &a_psUrl[nIpStart], uHostNameLength); sHostName[uHostNameLength] = '\0'; if(getaddrinfo(sHostName, NULL, NULL, &pAddrInfo)) { /* hostname could not be resolved */ pAddrInfo = NULL; OpcUa_GotoErrorWithStatus(OpcUa_BadHostUnknown); } if(pAddrInfo->ai_family == AF_INET) { struct sockaddr_in* pAddr = (struct sockaddr_in*)pAddrInfo->ai_addr; OpcUa_P_Memory_Free(sHostName); sHostName = OpcUa_P_Memory_Alloc(INET_ADDRSTRLEN); OpcUa_GotoErrorIfAllocFailed(sHostName); if(inet_ntop(AF_INET, (void*)&pAddr->sin_addr, sHostName, INET_ADDRSTRLEN) == NULL) { OpcUa_GotoErrorWithStatus(OpcUa_BadInternalError); } } else if(pAddrInfo->ai_family == AF_INET6) { struct sockaddr_in6* pAddr = (struct sockaddr_in6*)pAddrInfo->ai_addr; OpcUa_P_Memory_Free(sHostName); sHostName = OpcUa_P_Memory_Alloc(INET6_ADDRSTRLEN); OpcUa_GotoErrorIfAllocFailed(sHostName); if(inet_ntop(AF_INET6, (void*)&pAddr->sin6_addr, sHostName, INET6_ADDRSTRLEN) == NULL) { OpcUa_GotoErrorWithStatus(OpcUa_BadInternalError); } if(pAddr->sin6_scope_id) { char *pScopeAddress = OpcUa_P_Memory_Alloc(strlen(sHostName) + 12); OpcUa_GotoErrorIfAllocFailed(pScopeAddress); sprintf(pScopeAddress, "%s%%%u", sHostName, pAddr->sin6_scope_id); OpcUa_P_Memory_Free(sHostName); sHostName = pScopeAddress; } } else { OpcUa_GotoErrorWithStatus(OpcUa_BadInternalError); } *a_psIpAddress = sHostName; freeaddrinfo(pAddrInfo); OpcUa_ReturnStatusCode; OpcUa_BeginErrorHandling; if(sHostName != OpcUa_Null) { OpcUa_P_Memory_Free(sHostName); } if(pAddrInfo != NULL) { freeaddrinfo(pAddrInfo); } OpcUa_FinishErrorHandling; }
/*============================================================================ * OpcUa_P_OpenSSL_X509_LoadFromFile *===========================================================================*/ OpcUa_StatusCode OpcUa_P_OpenSSL_X509_LoadFromFile( OpcUa_StringA a_fileName, OpcUa_P_FileFormat a_fileFormat, OpcUa_StringA a_sPassword, /* optional: just for OpcUa_PKCS12 */ OpcUa_ByteString* a_pCertificate) { BIO* pCertFile = OpcUa_Null; X509* pCertX509 = OpcUa_Null; PKCS12* pPKCS12Cert = OpcUa_Null; OpcUa_InitializeStatus(OpcUa_Module_P_OpenSSL, "X509_LoadFromFile"); /* check filename */ if(OpcUa_P_String_strlen(a_fileName) < 1) { uStatus = OpcUa_BadInvalidArgument; OpcUa_GotoErrorIfBad(uStatus); } /* import certificate from file by the given encoding type */ pCertFile = BIO_new_file((const char*)a_fileName, "r"); OpcUa_ReturnErrorIfArgumentNull(pCertFile); switch(a_fileFormat) { case OpcUa_Crypto_Encoding_DER: { pCertX509 = d2i_X509_bio(pCertFile, /* sourcefile */ (X509**)NULL); /* target (if preallocated) */ break; } case OpcUa_Crypto_Encoding_PEM: { pCertX509 = PEM_read_bio_X509( pCertFile, /* sourcefile */ (X509**)OpcUa_Null, /* target (if preallocated) */ OpcUa_Null, /* password callback function */ OpcUa_Null); /* passphrase or callback data */ break; } case OpcUa_Crypto_Encoding_PKCS12: { d2i_PKCS12_bio(pCertFile, &pPKCS12Cert); PKCS12_parse(pPKCS12Cert, a_sPassword, OpcUa_Null, &pCertX509, OpcUa_Null); if(pPKCS12Cert != OpcUa_Null) { PKCS12_free(pPKCS12Cert); /*OPENSSL_free(pPKCS12Cert);*/ } break; } default: { BIO_free(pCertFile); return OpcUa_BadNotSupported; } } BIO_free(pCertFile); pCertFile = OpcUa_Null; if(pCertX509 == OpcUa_Null) { /* error in OpenSSL - maybe certificate file was corrupt */ return OpcUa_Bad; } /* prepare container */ memset(a_pCertificate, 0, sizeof(OpcUa_ByteString)); /* get required length for conversion target buffer */ a_pCertificate->Length = i2d_X509( pCertX509, NULL); if(a_pCertificate->Length <= 0) { /* conversion to DER not possible */ uStatus = OpcUa_Bad; } /* allocate conversion target buffer */ a_pCertificate->Data = (OpcUa_Byte*)OpcUa_P_Memory_Alloc(a_pCertificate->Length); OpcUa_GotoErrorIfAllocFailed(a_pCertificate->Data); /* convert into DER */ a_pCertificate->Length = i2d_X509( pCertX509, &(a_pCertificate->Data)); if(a_pCertificate->Length <= 0) { /* conversion to DER not possible */ uStatus = OpcUa_Bad; } else { /* correct pointer incrementation by i2d_X509() */ a_pCertificate->Data -= a_pCertificate->Length; } X509_free(pCertX509); OpcUa_ReturnStatusCode; OpcUa_BeginErrorHandling; if(pCertX509 != OpcUa_Null) { X509_free(pCertX509); } if(pPKCS12Cert != OpcUa_Null) { OPENSSL_free(pPKCS12Cert); } if(a_pCertificate->Data != OpcUa_Null) { OpcUa_P_Memory_Free(a_pCertificate->Data); a_pCertificate->Data = OpcUa_Null; } if(pCertFile != OpcUa_Null) { BIO_free(pCertFile); } OpcUa_FinishErrorHandling; }