Esempio n. 1
0
/* Create a signed nonce */
static UA_StatusCode
nonceAndSignCreateSessionResponse(UA_Server *server, UA_SecureChannel *channel,
                                  UA_Session *session,
                                  const UA_CreateSessionRequest *request,
                                  UA_CreateSessionResponse *response) {
    if(channel->securityMode != UA_MESSAGESECURITYMODE_SIGN &&
       channel->securityMode != UA_MESSAGESECURITYMODE_SIGNANDENCRYPT)
        return UA_STATUSCODE_GOOD;

    const UA_SecurityPolicy *const securityPolicy = channel->securityPolicy;
    UA_SignatureData *signatureData = &response->serverSignature;

    /* Generate Nonce
     * FIXME: remove magic number??? */
    UA_StatusCode retval = UA_SecureChannel_generateNonce(channel, 32, &response->serverNonce);
    retval |= UA_ByteString_copy(&response->serverNonce, &session->serverNonce);
    if(retval != UA_STATUSCODE_GOOD) {
        UA_SessionManager_removeSession(&server->sessionManager, &session->authenticationToken);
        return retval;
    }

    size_t signatureSize = securityPolicy->asymmetricModule.cryptoModule.
        getLocalSignatureSize(securityPolicy, channel->channelContext);

    retval |= UA_ByteString_allocBuffer(&signatureData->signature, signatureSize);
    if(retval != UA_STATUSCODE_GOOD) {
        UA_SessionManager_removeSession(&server->sessionManager, &session->authenticationToken);
        return retval;
    }

    UA_ByteString dataToSign;
    retval |= UA_ByteString_allocBuffer(&dataToSign,
                                        request->clientCertificate.length +
                                        request->clientNonce.length);
    if(retval != UA_STATUSCODE_GOOD) {
        UA_SignatureData_deleteMembers(signatureData);
        UA_SessionManager_removeSession(&server->sessionManager, &session->authenticationToken);
        return retval;
    }

    memcpy(dataToSign.data, request->clientCertificate.data, request->clientCertificate.length);
    memcpy(dataToSign.data + request->clientCertificate.length,
           request->clientNonce.data, request->clientNonce.length);

    retval |= UA_String_copy(&securityPolicy->asymmetricModule.cryptoModule.
                             signatureAlgorithmUri, &signatureData->algorithm);
    retval |= securityPolicy->asymmetricModule.cryptoModule.
        sign(securityPolicy, channel->channelContext, &dataToSign, &signatureData->signature);

    UA_ByteString_deleteMembers(&dataToSign);
    if(retval != UA_STATUSCODE_GOOD) {
        UA_SignatureData_deleteMembers(signatureData);
        UA_SessionManager_removeSession(&server->sessionManager, &session->authenticationToken);
    }
    return retval;
}
Esempio n. 2
0
END_TEST

START_TEST(encodeShallYieldDecode) {
    /* floating point types may change the representaton due to several possible NaN values. */
    if(_i != UA_TYPES_FLOAT || _i != UA_TYPES_DOUBLE ||
       _i != UA_TYPES_CREATESESSIONREQUEST || _i != UA_TYPES_CREATESESSIONRESPONSE ||
       _i != UA_TYPES_VARIABLEATTRIBUTES || _i != UA_TYPES_READREQUEST ||
       _i != UA_TYPES_MONITORINGPARAMETERS || _i != UA_TYPES_MONITOREDITEMCREATERESULT ||
       _i != UA_TYPES_CREATESUBSCRIPTIONREQUEST || _i != UA_TYPES_CREATESUBSCRIPTIONRESPONSE)
        return;

    // given
    UA_ByteString msg1, msg2;
    void *obj1 = UA_new(&UA_TYPES[_i]);
    UA_StatusCode retval = UA_ByteString_allocBuffer(&msg1, 65000); // fixed buf size
    ck_assert_int_eq(retval, UA_STATUSCODE_GOOD);
    UA_Byte *pos = msg1.data;
    const UA_Byte *end = &msg1.data[msg1.length];
    retval = UA_encodeBinary(obj1, &UA_TYPES[_i],
                             &pos, &end, NULL, NULL);
    if(retval != UA_STATUSCODE_GOOD) {
        UA_delete(obj1, &UA_TYPES[_i]);
        UA_ByteString_deleteMembers(&msg1);
        return;
    }

    // when
    void *obj2 = UA_new(&UA_TYPES[_i]);
    size_t offset = 0;
    retval = UA_decodeBinary(&msg1, &offset, obj2, &UA_TYPES[_i], 0, NULL); 
    ck_assert_msg(retval == UA_STATUSCODE_GOOD, "could not decode idx=%d,nodeid=%i",
                  _i, UA_TYPES[_i].typeId.identifier.numeric);
    ck_assert(!memcmp(obj1, obj2, UA_TYPES[_i].memSize)); // bit identical decoding
    retval = UA_ByteString_allocBuffer(&msg2, 65000);
    ck_assert_int_eq(retval, UA_STATUSCODE_GOOD);
    pos = msg2.data;
    end = &msg2.data[msg2.length];
    retval = UA_encodeBinary(obj2, &UA_TYPES[_i], &pos, &end, NULL, NULL);
    ck_assert_int_eq(retval, UA_STATUSCODE_GOOD);

    // then
    msg1.length = offset;
    msg2.length = offset;
    ck_assert_msg(UA_ByteString_equal(&msg1, &msg2) == true, "messages differ idx=%d,nodeid=%i", _i,
                  UA_TYPES[_i].typeId.identifier.numeric);

    // finally
    UA_delete(obj1, &UA_TYPES[_i]);
    UA_delete(obj2, &UA_TYPES[_i]);
    UA_ByteString_deleteMembers(&msg1);
    UA_ByteString_deleteMembers(&msg2);
}
Esempio n. 3
0
END_TEST

START_TEST(calcSizeBinaryShallBeCorrect) {
    /* Empty variants (with no type defined) cannot be encoded. This is intentional. Discovery configuration is just a base class and void * */
    if(_i == UA_TYPES_VARIANT ||
       _i == UA_TYPES_VARIABLEATTRIBUTES ||
       _i == UA_TYPES_VARIABLETYPEATTRIBUTES ||
       _i == UA_TYPES_FILTEROPERAND ||
       _i == UA_TYPES_MONITORINGFILTER ||
       _i == UA_TYPES_DISCOVERYCONFIGURATION ||
       _i == UA_TYPES_UNION ||
       _i == UA_TYPES_HISTORYREADDETAILS ||
       _i == UA_TYPES_NOTIFICATIONDATA ||
       _i == UA_TYPES_MONITORINGFILTERRESULT)
        return;
    void *obj = UA_new(&UA_TYPES[_i]);
    size_t predicted_size = UA_calcSizeBinary(obj, &UA_TYPES[_i]);
    ck_assert_int_ne(predicted_size, 0);
    UA_ByteString msg;
    UA_StatusCode retval = UA_ByteString_allocBuffer(&msg, predicted_size);
    ck_assert_int_eq(retval, UA_STATUSCODE_GOOD);
    UA_Byte *pos = msg.data;
    const UA_Byte *end = &msg.data[msg.length];
    retval = UA_encodeBinary(obj, &UA_TYPES[_i], &pos, &end, NULL, NULL);
    if(retval)
        printf("%i\n",_i);
    ck_assert_int_eq(retval, UA_STATUSCODE_GOOD);
    ck_assert_int_eq((uintptr_t)(pos - msg.data), predicted_size);
    UA_delete(obj, &UA_TYPES[_i]);
    UA_ByteString_deleteMembers(&msg);
}
Esempio n. 4
0
END_TEST

START_TEST(decodeComplexTypeFromRandomBufferShallSurvive) {
    // given
    UA_ByteString msg1;
    UA_Int32 retval = UA_STATUSCODE_GOOD;
    UA_Int32 buflen = 256;
    retval = UA_ByteString_allocBuffer(&msg1, buflen); // fixed size
#ifdef _WIN32
    srand(42);
#else
    srandom(42);
#endif
    // when
    for(int n = 0;n < RANDOM_TESTS;n++) {
        for(UA_Int32 i = 0;i < buflen;i++) {
#ifdef _WIN32
            UA_UInt32 rnd;
            rnd = rand();
            msg1.data[i] = rnd;
#else
            msg1.data[i] = (UA_Byte)random();  // when
#endif
        }
        size_t pos = 0;
        void *obj1 = UA_new(&UA_TYPES[_i]);
        retval |= UA_decodeBinary(&msg1, &pos, obj1, &UA_TYPES[_i], 0, NULL);
        UA_delete(obj1, &UA_TYPES[_i]);
    }

    // finally
    UA_ByteString_deleteMembers(&msg1);
}
Esempio n. 5
0
static UA_StatusCode
ClientNetworkLayerGetBuffer(UA_Connection *connection, size_t length, UA_ByteString *buf) {
    if(length > connection->remoteConf.recvBufferSize)
        return UA_STATUSCODE_BADCOMMUNICATIONERROR;
    if(connection->state == UA_CONNECTION_CLOSED)
        return UA_STATUSCODE_BADCONNECTIONCLOSED;
    return UA_ByteString_allocBuffer(buf, connection->remoteConf.recvBufferSize);
}
Esempio n. 6
0
static void
checkSignature(const UA_Server *server,
               const UA_SecureChannel *channel,
               UA_Session *session,
               const UA_ActivateSessionRequest *request,
               UA_ActivateSessionResponse *response) {
    if(channel->securityMode == UA_MESSAGESECURITYMODE_SIGN ||
       channel->securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT) {
        const UA_SecurityPolicy *const securityPolicy = channel->securityPolicy;
        const UA_ByteString *const localCertificate = &securityPolicy->localCertificate;

        UA_ByteString dataToVerify;
        UA_StatusCode retval = UA_ByteString_allocBuffer(&dataToVerify,
                                                         localCertificate->length + session->serverNonce.length);
        if(retval != UA_STATUSCODE_GOOD) {
            response->responseHeader.serviceResult = retval;
            UA_LOG_DEBUG_SESSION(server->config.logger, session,
                                 "Failed to allocate buffer for signature verification! %#10x", retval);
            return;
        }

        memcpy(dataToVerify.data, localCertificate->data, localCertificate->length);
        memcpy(dataToVerify.data + localCertificate->length,
               session->serverNonce.data, session->serverNonce.length);

        retval = securityPolicy->asymmetricModule.cryptoModule.
            verify(securityPolicy, channel->channelContext, &dataToVerify,
                   &request->clientSignature.signature);
        if(retval != UA_STATUSCODE_GOOD) {
            response->responseHeader.serviceResult = retval;
            UA_LOG_DEBUG_SESSION(server->config.logger, session,
                                 "Failed to verify the client signature! %#10x", retval);
            UA_ByteString_deleteMembers(&dataToVerify);
            return;
        }

        retval  = UA_SecureChannel_generateNonce(channel, 32, &response->serverNonce);
        retval |= UA_ByteString_copy(&response->serverNonce, &session->serverNonce);
        if(retval != UA_STATUSCODE_GOOD) {
            response->responseHeader.serviceResult = retval;
            UA_LOG_DEBUG_SESSION(server->config.logger, session,
                                 "Failed to generate a new nonce! %#10x", retval);
            UA_ByteString_deleteMembers(&dataToVerify);
            return;
        }

        UA_ByteString_deleteMembers(&dataToVerify);
    }
}
Esempio n. 7
0
static UA_StatusCode
requestSession(UA_Client *client, UA_UInt32 *requestId) {
    UA_CreateSessionRequest request;
    UA_CreateSessionRequest_init(&request);

    UA_StatusCode retval = UA_STATUSCODE_GOOD;
    if(client->channel.securityMode == UA_MESSAGESECURITYMODE_SIGN ||
       client->channel.securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT) {
        if(client->channel.localNonce.length != UA_SESSION_LOCALNONCELENGTH) {
           UA_ByteString_deleteMembers(&client->channel.localNonce);
            retval = UA_ByteString_allocBuffer(&client->channel.localNonce,
                                               UA_SESSION_LOCALNONCELENGTH);
            if(retval != UA_STATUSCODE_GOOD)
                return retval;
        }

        retval = client->channel.securityPolicy->symmetricModule.
                 generateNonce(client->channel.securityPolicy, &client->channel.localNonce);
        if(retval != UA_STATUSCODE_GOOD)
            return retval;
    }

    request.requestHeader.requestHandle = ++client->requestHandle;
    request.requestHeader.timestamp = UA_DateTime_now();
    request.requestHeader.timeoutHint = 10000;
    UA_ByteString_copy(&client->channel.localNonce, &request.clientNonce);
    request.requestedSessionTimeout = client->config.requestedSessionTimeout;
    request.maxResponseMessageSize = UA_INT32_MAX;
    UA_String_copy(&client->config.endpoint.endpointUrl, &request.endpointUrl);

    UA_ApplicationDescription_copy(&client->config.clientDescription,
                                   &request.clientDescription);

    retval = UA_Client_sendAsyncRequest (
            client, &request, &UA_TYPES[UA_TYPES_CREATESESSIONREQUEST],
            (UA_ClientAsyncServiceCallback) responseSessionCallback,
            &UA_TYPES[UA_TYPES_CREATESESSIONRESPONSE], NULL, requestId);
    UA_CreateSessionRequest_deleteMembers(&request);
    client->connectStatus = retval;
    return client->connectStatus;
}
Esempio n. 8
0
END_TEST

#define RANDOM_TESTS 1000

START_TEST(decodeScalarBasicTypeFromRandomBufferShallSucceed) {
    // given
    void *obj1 = NULL;
    UA_ByteString msg1;
    UA_Int32 retval = UA_STATUSCODE_GOOD;
    UA_Int32 buflen = 256;
    retval = UA_ByteString_allocBuffer(&msg1, buflen); // fixed size
#ifdef _WIN32
    srand(42);
#else
    srandom(42);
#endif
    for(int n = 0;n < RANDOM_TESTS;n++) {
        for(UA_Int32 i = 0;i < buflen;i++) {
#ifdef _WIN32
            UA_UInt32 rnd;
            rnd = rand();
            msg1.data[i] = rnd;
#else
            msg1.data[i] = (UA_Byte)random();  // when
#endif
        }
        size_t pos = 0;
        obj1 = UA_new(&UA_TYPES[_i]);
        retval |= UA_decodeBinary(&msg1, &pos, obj1, &UA_TYPES[_i], 0, NULL);
        //then
        ck_assert_msg(retval == UA_STATUSCODE_GOOD, "Decoding %d from random buffer", UA_TYPES[_i].typeId.identifier.numeric);
        // finally
        UA_delete(obj1, &UA_TYPES[_i]);
    }
    UA_ByteString_deleteMembers(&msg1);
}
Esempio n. 9
0
END_TEST

START_TEST(decodeShallFailWithTruncatedBufferButSurvive) {
    //Skip test for void*
    if (_i == UA_TYPES_DISCOVERYCONFIGURATION ||
            _i == UA_TYPES_FILTEROPERAND ||
            _i == UA_TYPES_MONITORINGFILTER ||
            _i == UA_TYPES_UNION ||
            _i == UA_TYPES_HISTORYREADDETAILS ||
            _i == UA_TYPES_NOTIFICATIONDATA ||
            _i == UA_TYPES_MONITORINGFILTERRESULT)
        return;
    // given
    UA_ByteString msg1;
    void *obj1 = UA_new(&UA_TYPES[_i]);
    UA_StatusCode retval = UA_ByteString_allocBuffer(&msg1, 65000); // fixed buf size
    UA_Byte *pos = msg1.data;
    const UA_Byte *end = &msg1.data[msg1.length];
    retval |= UA_encodeBinary(obj1, &UA_TYPES[_i], &pos, &end, NULL, NULL);
    UA_delete(obj1, &UA_TYPES[_i]);
    if(retval != UA_STATUSCODE_GOOD) {
        UA_ByteString_deleteMembers(&msg1);
        return; // e.g. variants cannot be encoded after an init without failing (no datatype set)
    }

    size_t half = (uintptr_t)(pos - msg1.data) / 2;
    msg1.length = half;

    // when
    void *obj2 = UA_new(&UA_TYPES[_i]);
    size_t offset = 0;
    retval = UA_decodeBinary(&msg1, &offset, obj2, &UA_TYPES[_i], 0, NULL);
    ck_assert_int_ne(retval, UA_STATUSCODE_GOOD);
    UA_delete(obj2, &UA_TYPES[_i]);
    UA_ByteString_deleteMembers(&msg1);
}
Esempio n. 10
0
static UA_StatusCode
ServerNetworkLayerGetSendBuffer(UA_Connection *connection, size_t length, UA_ByteString *buf) {
    if(length > connection->remoteConf.recvBufferSize)
        return UA_STATUSCODE_BADCOMMUNICATIONERROR;
    return UA_ByteString_allocBuffer(buf, length);
}
static UA_StatusCode
subscriberListen(UA_PubSubChannel *psc) {
    UA_ByteString buffer;
    UA_StatusCode retval = UA_ByteString_allocBuffer(&buffer, 512);
    if(retval != UA_STATUSCODE_GOOD) {
        UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
                     "Message buffer allocation failed!");
        return retval;
    }

    /* Receive the message. Blocks for 100ms */
    retval = psc->receive(psc, &buffer, NULL, 100);
    if(retval != UA_STATUSCODE_GOOD || buffer.length == 0) {
        /* Workaround!! Reset buffer length. Receive can set the length to zero.
         * Then the buffer is not deleted because no memory allocation is
         * assumed.
         * TODO: Return an error code in 'receive' instead of setting the buf
         * length to zero. */
        buffer.length = 512;
        UA_ByteString_clear(&buffer);
        return UA_STATUSCODE_GOOD;
    }

    /* Decode the message */
    UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND,
                "Message length: %lu", (unsigned long) buffer.length);
    UA_NetworkMessage networkMessage;
    memset(&networkMessage, 0, sizeof(UA_NetworkMessage));
    size_t currentPosition = 0;
    UA_NetworkMessage_decodeBinary(&buffer, &currentPosition, &networkMessage);
    UA_ByteString_clear(&buffer);

    /* Is this the correct message type? */
    if(networkMessage.networkMessageType != UA_NETWORKMESSAGE_DATASET)
        goto cleanup;

    /* At least one DataSetMessage in the NetworkMessage? */
    if(networkMessage.payloadHeaderEnabled &&
       networkMessage.payloadHeader.dataSetPayloadHeader.count < 1)
        goto cleanup;

    /* Is this a KeyFrame-DataSetMessage? */
    for(size_t j = 0; j < networkMessage.payloadHeader.dataSetPayloadHeader.count; j++) {
        UA_DataSetMessage *dsm = &networkMessage.payload.dataSetPayload.dataSetMessages[j];
        if(dsm->header.dataSetMessageType != UA_DATASETMESSAGE_DATAKEYFRAME)
            continue;

        /* Loop over the fields and print well-known content types */
        for(int i = 0; i < dsm->data.keyFrameData.fieldCount; i++) {
            const UA_DataType *currentType = dsm->data.keyFrameData.dataSetFields[i].value.type;
            if(currentType == &UA_TYPES[UA_TYPES_BYTE]) {
                UA_Byte value = *(UA_Byte *)dsm->data.keyFrameData.dataSetFields[i].value.data;
                UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND,
                            "Message content: [Byte] \tReceived data: %i", value);
            } else if (currentType == &UA_TYPES[UA_TYPES_DATETIME]) {
                UA_DateTime value = *(UA_DateTime *)dsm->data.keyFrameData.dataSetFields[i].value.data;
                UA_DateTimeStruct receivedTime = UA_DateTime_toStruct(value);
                UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND,
                            "Message content: [DateTime] \t"
                            "Received date: %02i-%02i-%02i Received time: %02i:%02i:%02i",
                            receivedTime.year, receivedTime.month, receivedTime.day,
                            receivedTime.hour, receivedTime.min, receivedTime.sec);
            }
        }
    }

    cleanup:
    UA_NetworkMessage_clear(&networkMessage);
    return retval;
}
Esempio n. 12
0
int main(int argc, char** argv) {
    signal(SIGINT, stopHandler); /* catches ctrl-c */

    UA_ServerConfig config = UA_ServerConfig_standard;
    UA_ServerNetworkLayer nl = UA_ServerNetworkLayerTCP(UA_ConnectionConfig_standard, 16664, logger);
    config.logger = Logger_Stdout;
    config.networkLayers = &nl;
    config.networkLayersSize = 1;
    UA_Server *server = UA_Server_new(config);

    /* add a variable node to the address space */
    UA_VariableAttributes attr;
    UA_VariableAttributes_init(&attr);
    UA_Int32 myInteger = 42;
    UA_Variant_setScalar(&attr.value, &myInteger, &UA_TYPES[UA_TYPES_INT32]);
    attr.description = UA_LOCALIZEDTEXT("en_US","the answer");
    attr.displayName = UA_LOCALIZEDTEXT("en_US","the answer");
    UA_NodeId myIntegerNodeId = UA_NODEID_STRING(1, "the.answer");
    UA_QualifiedName myIntegerName = UA_QUALIFIEDNAME(1, "the answer");
    UA_NodeId parentNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER);
    UA_NodeId parentReferenceNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES);
    UA_Server_addVariableNode(server, myIntegerNodeId, parentNodeId,
                              parentReferenceNodeId, myIntegerName,
                              UA_NODEID_NULL, attr, NULL, NULL);

    UA_ReadRequest request;
    UA_ReadRequest_init(&request);
    UA_ReadValueId rvi;
    rvi.nodeId = myIntegerNodeId;
    rvi.attributeId = UA_ATTRIBUTEID_VALUE;
    rvi.indexRange = UA_STRING_NULL;
    rvi.dataEncoding = UA_QUALIFIEDNAME(0, "DefaultBinary");
    request.timestampsToReturn = UA_TIMESTAMPSTORETURN_NEITHER;
    request.nodesToReadSize = 1;
    request.nodesToRead = &rvi;

    UA_StatusCode retval = UA_STATUSCODE_GOOD;
    UA_ByteString request_msg;
    retval |= UA_ByteString_allocBuffer(&request_msg, 1000);
    UA_ByteString response_msg;
    retval |= UA_ByteString_allocBuffer(&response_msg, 1000);
    size_t offset = 0;
    retval |= UA_encodeBinary(&request, &UA_TYPES[UA_TYPES_READREQUEST], &request_msg, &offset);
    
    clock_t begin, end;
    begin = clock();

    UA_ReadRequest rq;
    UA_ReadResponse rr;

    for(int i = 0; i < 900000; i++) {
        offset = 0;
        retval |= UA_decodeBinary(&request_msg, &offset, &rq, &UA_TYPES[UA_TYPES_READREQUEST]);

        UA_ReadResponse_init(&rr);
        Service_Read(server, &adminSession, &rq, &rr);

        offset = 0;
        retval |= UA_encodeBinary(&rr, &UA_TYPES[UA_TYPES_READRESPONSE], &response_msg, &offset);

        UA_ReadRequest_deleteMembers(&rq);
        UA_ReadResponse_deleteMembers(&rr);
    }

    end = clock();
    double time_spent = (double)(end - begin) / CLOCKS_PER_SEC;
    printf("duration was %f s\n", time_spent);
    printf("retval is %i\n", retval);

    UA_ByteString_deleteMembers(&request_msg);
    UA_ByteString_deleteMembers(&response_msg);

    retval |= UA_Server_run(server, &running);
    UA_Server_delete(server);
    nl.deleteMembers(&nl);

    return (int)retval;
}
Esempio n. 13
0
/**
 * Initialize a client instance which is used for calling the registerServer service.
 * If the given endpoint has securityMode NONE, a client with default configuration
 * is returned.
 * If it is using SignAndEncrypt, the client certificates must be provided as a
 * command line argument and then the client is initialized using these certificates.
 * @param endpointRegister The remote endpoint where this server should register
 * @param argc from the main method
 * @param argv from the main method
 * @return NULL or the initialized non-connected client
 */
static
UA_Client *getRegisterClient(UA_EndpointDescription *endpointRegister, int argc, char **argv) {
    if (endpointRegister->securityMode == UA_MESSAGESECURITYMODE_NONE) {
        UA_LOG_INFO(logger, UA_LOGCATEGORY_SERVER, "Using LDS endpoint with security None");
        return UA_Client_new(UA_ClientConfig_default);
    }
#ifdef UA_ENABLE_ENCRYPTION
    if (endpointRegister->securityMode == UA_MESSAGESECURITYMODE_SIGN) {
        UA_LOG_INFO(logger, UA_LOGCATEGORY_SERVER, "LDS endpoint which only supports Sign is currently not supported");
        return NULL;
    }

    UA_Client *clientRegister;
    UA_LOG_INFO(logger, UA_LOGCATEGORY_SERVER, "Using LDS endpoint with security SignAndEncrypt");

    UA_ByteString certificate = UA_BYTESTRING_NULL;
    UA_ByteString privateKey = UA_BYTESTRING_NULL;
    UA_ByteString *trustList = NULL;
    size_t trustListSize = 0;
    UA_ByteString *revocationList = NULL;
    size_t revocationListSize = 0;


    if (argc < 3) {
        UA_LOG_FATAL(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND,
                     "The Certificate and key is missing."
                         "The required arguments are "
                         "<client-certificate.der> <client-private-key.der> "
                         "[<trustlist1.crl>, ...]");
        return NULL;
    }
    certificate = loadFile(argv[1]);
    privateKey = loadFile(argv[2]);

    /* Load the trustList. Load revocationList is not supported now */
    if (argc > 3) {
        trustListSize = (size_t) argc - 3;
        UA_StatusCode retval = UA_ByteString_allocBuffer(trustList, trustListSize);
        if (retval != UA_STATUSCODE_GOOD) {
            UA_ByteString_deleteMembers(&certificate);
            UA_ByteString_deleteMembers(&privateKey);
            return NULL;
        }

        for (size_t trustListCount = 0; trustListCount < trustListSize; trustListCount++) {
            trustList[trustListCount] = loadFile(argv[trustListCount + 3]);
        }
    }


    /* Secure client initialization */
    clientRegister = UA_Client_secure_new(UA_ClientConfig_default,
                                          certificate, privateKey,
                                          &endpointRegister->serverCertificate,
                                          trustList, trustListSize,
                                          revocationList, revocationListSize,
                                          UA_SecurityPolicy_Basic128Rsa15);
    UA_ByteString_deleteMembers(&certificate);
    UA_ByteString_deleteMembers(&privateKey);
    for (size_t deleteCount = 0; deleteCount < trustListSize; deleteCount++) {
        UA_ByteString_deleteMembers(&trustList[deleteCount]);
    }

    return clientRegister;
#else
	return NULL;
#endif
}
/* When a change is detected, encoding contains the heap-allocated binary
 * encoded value. The default for changed is false. */
static UA_StatusCode
detectValueChangeWithFilter(UA_Server *server, UA_MonitoredItem *mon, UA_DataValue *value,
                            UA_ByteString *encoding, UA_Boolean *changed) {
    if(UA_DataType_isNumeric(value->value.type) &&
       (mon->filter.dataChangeFilter.trigger == UA_DATACHANGETRIGGER_STATUSVALUE ||
        mon->filter.dataChangeFilter.trigger == UA_DATACHANGETRIGGER_STATUSVALUETIMESTAMP)) {
        if(mon->filter.dataChangeFilter.deadbandType == UA_DEADBANDTYPE_ABSOLUTE) {
            if(!updateNeededForFilteredValue(&value->value, &mon->lastValue,
                                             mon->filter.dataChangeFilter.deadbandValue))
                return UA_STATUSCODE_GOOD;
        }
#ifdef UA_ENABLE_DA
        else if(mon->filter.dataChangeFilter.deadbandType == UA_DEADBANDTYPE_PERCENT) {
            UA_QualifiedName qn = UA_QUALIFIEDNAME(0, "EURange");
            UA_BrowsePathResult bpr = UA_Server_browseSimplifiedBrowsePath(server, mon->monitoredNodeId, 1, &qn);
            if(bpr.statusCode != UA_STATUSCODE_GOOD || bpr.targetsSize < 1) { //if branch is not entried, property has been found
                  UA_BrowsePathResult_deleteMembers(&bpr);
                  return UA_STATUSCODE_GOOD;
            }
            const UA_VariableNode* node =
                (const UA_VariableNode*) UA_Nodestore_getNode(server->nsCtx, &bpr.targets->targetId.nodeId);
            UA_Range* euRange = (UA_Range*) node->value.data.value.value.data;
            if(!updateNeededForFilteredPercentValue(&value->value, &mon->lastValue,
                                                    mon->filter.dataChangeFilter.deadbandValue, euRange)) {
                if(!updateNeededForStatusCode(value, mon)) //when same value, but different status code is written
                  return UA_STATUSCODE_GOOD;
            }
        }
#endif
    }

    /* Stack-allocate some memory for the value encoding. We might heap-allocate
     * more memory if needed. This is just enough for scalars and small
     * structures. */
    UA_STACKARRAY(UA_Byte, stackValueEncoding, UA_VALUENCODING_MAXSTACK);
    UA_ByteString valueEncoding;
    valueEncoding.data = stackValueEncoding;
    valueEncoding.length = UA_VALUENCODING_MAXSTACK;

    /* Encode the value */
    UA_Byte *bufPos = valueEncoding.data;
    const UA_Byte *bufEnd = &valueEncoding.data[valueEncoding.length];
    UA_StatusCode retval = UA_encodeBinary(value, &UA_TYPES[UA_TYPES_DATAVALUE],
                                           &bufPos, &bufEnd, NULL, NULL);
    if(retval == UA_STATUSCODE_BADENCODINGERROR) {
        size_t binsize = UA_calcSizeBinary(value, &UA_TYPES[UA_TYPES_DATAVALUE]);
        if(binsize == 0)
            return UA_STATUSCODE_BADENCODINGERROR;

        if(binsize > UA_VALUENCODING_MAXSTACK) {
            retval = UA_ByteString_allocBuffer(&valueEncoding, binsize);
            if(retval == UA_STATUSCODE_GOOD) {
                bufPos = valueEncoding.data;
                bufEnd = &valueEncoding.data[valueEncoding.length];
                retval = UA_encodeBinary(value, &UA_TYPES[UA_TYPES_DATAVALUE],
                                         &bufPos, &bufEnd, NULL, NULL);
            }
        }
    }
    if(retval != UA_STATUSCODE_GOOD) {
        if(valueEncoding.data != stackValueEncoding)
            UA_ByteString_deleteMembers(&valueEncoding);
        return retval;
    }

    /* Has the value changed? */
    valueEncoding.length = (uintptr_t)bufPos - (uintptr_t)valueEncoding.data;
    *changed = (!mon->lastSampledValue.data ||
                !UA_String_equal(&valueEncoding, &mon->lastSampledValue));

    /* No change */
    if(!(*changed)) {
        if(valueEncoding.data != stackValueEncoding)
            UA_ByteString_deleteMembers(&valueEncoding);
        return UA_STATUSCODE_GOOD;
    }

    /* Change detected. Copy encoding on the heap if necessary. */
    if(valueEncoding.data == stackValueEncoding)
        return UA_ByteString_copy(&valueEncoding, encoding);

    *encoding = valueEncoding;
    return UA_STATUSCODE_GOOD;
}