コード例 #1
0
/* 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;
}
コード例 #2
0
/*============================================================================
 * 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;
        }
    }
}
コード例 #3
0
/*============================================================================
 * 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;
}
コード例 #4
0
/*============================================================================
 * 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;
}
コード例 #5
0
/*============================================================================
 * 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;
}
コード例 #6
0
ファイル: opcua_thread.c プロジェクト: OPCFoundation/UA-AnsiC
/*============================================================================
 * 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;
}
コード例 #7
0
/*============================================================================
 * 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;
}
コード例 #8
0
/**
* @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;
}
コード例 #9
0
/**
* @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");
}
コード例 #10
0
/*============================================================================
 * 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;
}
コード例 #11
0
/*============================================================================
 * 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;
}
コード例 #12
0
/*============================================================================
 * 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;
}
コード例 #13
0
/*============================================================================
 * 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;
}
コード例 #14
0
/*============================================================================
 * 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;
}
コード例 #15
0
/*============================================================================
 * 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;
}