UA_Int32 UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(UA_AsymmetricAlgorithmSecurityHeader* p) { UA_Int32 retval = UA_SUCCESS; retval |= UA_ByteString_deleteMembers(&(p->securityPolicyUri)); retval |= UA_ByteString_deleteMembers(&(p->senderCertificate)); retval |= UA_ByteString_deleteMembers(&(p->receiverCertificateThumbprint)); return retval; }
/** Accesses only the sockfd in the handle. Can be run from parallel threads. */ static UA_StatusCode sendUDP(UA_Connection *connection, UA_ByteString *buf) { UDPConnection *udpc = (UDPConnection*)connection; ServerNetworkLayerUDP *layer = (ServerNetworkLayerUDP*)connection->handle; size_t nWritten = 0; struct sockaddr_in *sin = NULL; if (udpc->from.sa_family == AF_INET) { #if ((__GNUC__ == 4 && __GNUC_MINOR__ >= 6) || __GNUC__ > 4 || defined(__clang__)) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wcast-align" #endif sin = (struct sockaddr_in *) &udpc->from; #if ((__GNUC__ == 4 && __GNUC_MINOR__ >= 6) || __GNUC__ > 4 || defined(__clang__)) #pragma GCC diagnostic pop #endif } else { UA_ByteString_deleteMembers(buf); return UA_STATUSCODE_BADINTERNALERROR; } while (nWritten < (size_t)buf->length) { UA_Int32 n = sendto(layer->serversockfd, buf->data, buf->length, 0, (struct sockaddr*)sin, sizeof(struct sockaddr_in)); if(n == -1L) { UA_LOG_WARNING(layer->layer.logger, UA_LOGCATEGORY_COMMUNICATION, "UDP send error %i", errno); UA_ByteString_deleteMembers(buf); return UA_STATUSCODE_BADINTERNALERROR; } nWritten += n; } UA_ByteString_deleteMembers(buf); return UA_STATUSCODE_GOOD; }
static UA_StatusCode socket_write(UA_Connection *connection, UA_ByteString *buf) { size_t nWritten = 0; while(buf->length > 0 && nWritten < (size_t)buf->length) { UA_Int32 n = 0; do { #ifdef _WIN32 n = send((SOCKET)connection->sockfd, (const char*)buf->data, (size_t)buf->length, 0); const int last_error = WSAGetLastError(); if(n < 0 && last_error != WSAEINTR && last_error != WSAEWOULDBLOCK) { connection->close(connection); socket_close(connection); UA_ByteString_deleteMembers(buf); return UA_STATUSCODE_BADCONNECTIONCLOSED; } #else n = send(connection->sockfd, (const char*)buf->data, (size_t)buf->length, MSG_NOSIGNAL); if(n == -1L && errno != EINTR && errno != EAGAIN) { connection->close(connection); socket_close(connection); UA_ByteString_deleteMembers(buf); return UA_STATUSCODE_BADCONNECTIONCLOSED; } #endif } while (n == -1L); nWritten += n; } UA_ByteString_deleteMembers(buf); return UA_STATUSCODE_GOOD; }
void UA_SecureChannel_deleteMembers(UA_SecureChannel *channel) { UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(&channel->serverAsymAlgSettings); UA_ByteString_deleteMembers(&channel->serverNonce); UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(&channel->clientAsymAlgSettings); UA_ByteString_deleteMembers(&channel->clientNonce); UA_ChannelSecurityToken_deleteMembers(&channel->securityToken); }
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); }
int main(int argc, char* argv[]) { signal(SIGINT, stopHandler); signal(SIGTERM, stopHandler); if(argc < 3) { UA_LOG_FATAL(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "Missing arguments. Arguments are " "<server-certificate.der> <private-key.der> " "[<trustlist1.crl>, ...]"); return 1; } /* Load certificate and private key */ UA_ByteString certificate = loadFile(argv[1]); UA_ByteString privateKey = loadFile(argv[2]); /* Load the trustlist */ size_t trustListSize = 0; if(argc > 3) trustListSize = (size_t)argc-3; UA_STACKARRAY(UA_ByteString, trustList, trustListSize); for(size_t i = 0; i < trustListSize; i++) trustList[i] = loadFile(argv[i+3]); /* Loading of a revocation list currently unsupported */ UA_ByteString *revocationList = NULL; size_t revocationListSize = 0; UA_ServerConfig *config = UA_ServerConfig_new_basic128rsa15(4840, &certificate, &privateKey, trustList, trustListSize, revocationList, revocationListSize); UA_ByteString_deleteMembers(&certificate); UA_ByteString_deleteMembers(&privateKey); for(size_t i = 0; i < trustListSize; i++) UA_ByteString_deleteMembers(&trustList[i]); if(!config) { UA_LOG_FATAL(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "Could not create the server config"); return 1; } UA_Server *server = UA_Server_new(config); UA_StatusCode retval = UA_Server_run(server, &running); UA_Server_delete(server); UA_ServerConfig_delete(config); return (int)retval; }
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); } }
static UA_StatusCode socket_recv(UA_Connection *connection, UA_ByteString *response, UA_UInt32 timeout) { response->data = malloc(connection->localConf.recvBufferSize); if(!response->data) { response->length = 0; return UA_STATUSCODE_BADOUTOFMEMORY; /* not enough memory retry */ } if(timeout > 0) { /* currently, only the client uses timeouts */ #ifndef _WIN32 int timeout_usec = timeout * 1000; struct timeval tmptv = {timeout_usec / 1000000, timeout_usec % 1000000}; int ret = setsockopt(connection->sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char *)&tmptv, sizeof(struct timeval)); #else DWORD timeout_dw = timeout; int ret = setsockopt(connection->sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout_dw, sizeof(DWORD)); #endif if(0 != ret) { UA_ByteString_deleteMembers(response); socket_close(connection); return UA_STATUSCODE_BADCONNECTIONCLOSED; } } int ret = recv(connection->sockfd, (char*)response->data, connection->localConf.recvBufferSize, 0); if(ret == 0) { /* server has closed the connection */ UA_ByteString_deleteMembers(response); socket_close(connection); return UA_STATUSCODE_BADCONNECTIONCLOSED; } else if(ret < 0) { UA_ByteString_deleteMembers(response); #ifdef _WIN32 const int last_error = WSAGetLastError(); #define TEST_RETRY (last_error == WSAEINTR || last_error == WSAEWOULDBLOCK) #else #define TEST_RETRY (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) #endif if (TEST_RETRY) return UA_STATUSCODE_GOOD; /* retry */ else { socket_close(connection); return UA_STATUSCODE_BADCONNECTIONCLOSED; } } response->length = ret; return UA_STATUSCODE_GOOD; }
/* loadFile parses the certificate file. * * @param path specifies the file name given in argv[] * @return Returns the file content after parsing */ static UA_ByteString loadFile(const char *const path) { UA_ByteString fileContents = UA_BYTESTRING_NULL; if (path == NULL) return fileContents; /* Open the file */ FILE *fp = fopen(path, "rb"); if (!fp) { errno = 0; /* We read errno also from the tcp layer */ return fileContents; } /* Get the file length, allocate the data and read */ fseek(fp, 0, SEEK_END); fileContents.length = (size_t) ftell(fp); fileContents.data = (UA_Byte *) UA_malloc(fileContents.length * sizeof(UA_Byte)); if (fileContents.data) { fseek(fp, 0, SEEK_SET); size_t read = fread(fileContents.data, sizeof(UA_Byte), fileContents.length, fp); if (read != fileContents.length) UA_ByteString_deleteMembers(&fileContents); } else { fileContents.length = 0; } fclose(fp); return fileContents; }
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); }
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); }
static UA_Int32 sendHello(UA_Int32 sock, UA_String *endpointURL) { UA_TcpMessageHeader messageHeader; messageHeader.messageTypeAndFinal = UA_MESSAGETYPEANDFINAL_HELF; UA_TcpHelloMessage hello; UA_String_copy(endpointURL, &hello.endpointUrl); hello.maxChunkCount = 1; hello.maxMessageSize = 16777216; hello.protocolVersion = 0; hello.receiveBufferSize = 65536; hello.sendBufferSize = 65536; messageHeader.messageSize = UA_TcpHelloMessage_calcSizeBinary((UA_TcpHelloMessage const*) &hello) + UA_TcpMessageHeader_calcSizeBinary((UA_TcpMessageHeader const*) &messageHeader); UA_ByteString message; UA_ByteString_newMembers(&message, messageHeader.messageSize); size_t offset = 0; UA_TcpMessageHeader_encodeBinary((UA_TcpMessageHeader const*) &messageHeader, &message, &offset); UA_TcpHelloMessage_encodeBinary((UA_TcpHelloMessage const*) &hello, &message, &offset); UA_Int32 sendret = send(sock, message.data, offset, 0); UA_ByteString_deleteMembers(&message); free(hello.endpointUrl.data); if (sendret < 0) return 1; return 0; }
static void processJob(UA_Server *server, UA_Job *job) { UA_ASSERT_RCU_UNLOCKED(); UA_RCU_LOCK(); switch(job->type) { case UA_JOBTYPE_NOTHING: break; case UA_JOBTYPE_DETACHCONNECTION: UA_Connection_detachSecureChannel(job->job.closeConnection); break; case UA_JOBTYPE_BINARYMESSAGE_NETWORKLAYER: UA_Server_processBinaryMessage(server, job->job.binaryMessage.connection, &job->job.binaryMessage.message); UA_Connection *connection = job->job.binaryMessage.connection; connection->releaseRecvBuffer(connection, &job->job.binaryMessage.message); break; case UA_JOBTYPE_BINARYMESSAGE_ALLOCATED: UA_Server_processBinaryMessage(server, job->job.binaryMessage.connection, &job->job.binaryMessage.message); UA_ByteString_deleteMembers(&job->job.binaryMessage.message); break; case UA_JOBTYPE_METHODCALL: case UA_JOBTYPE_METHODCALL_DELAYED: job->job.methodCall.method(server, job->job.methodCall.data); break; default: UA_LOG_WARNING(server->config.logger, UA_LOGCATEGORY_SERVER, "Trying to execute a job of unknown type"); break; } UA_RCU_UNLOCK(); }
static UA_StatusCode socket_write(UA_Connection *connection, UA_ByteString *buf, size_t buflen) { size_t nWritten = 0; while (nWritten < buflen) { UA_Int32 n = 0; do { #ifdef _WIN32 n = send((SOCKET)connection->sockfd, (const char*)buf->data, buflen, 0); if(n < 0 && WSAGetLastError() != WSAEINTR && WSAGetLastError() != WSAEWOULDBLOCK){ connection->close(connection); socket_close(connection); return UA_STATUSCODE_BADCONNECTIONCLOSED; } #else n = send(connection->sockfd, (const char*)buf->data, buflen, MSG_NOSIGNAL); if(n == -1L && errno != EINTR && errno != EAGAIN){ socket_close(connection); return UA_STATUSCODE_BADCONNECTIONCLOSED; } #endif } while (n == -1L); nWritten += n; } #ifdef UA_MULTITHREADING UA_ByteString_deleteMembers(buf); #endif return UA_STATUSCODE_GOOD; }
void print_time() { UA_DateTime now = UA_DateTime_now(); UA_ByteString str; UA_DateTime_toString(now, &str); printf("\"%.*s\"}", str.length, str.data); UA_ByteString_deleteMembers(&str); }
static size_t browseWithMaxResults(UA_Server *server, UA_NodeId nodeId, UA_UInt32 maxResults) { UA_BrowseDescription bd; UA_BrowseDescription_init(&bd); bd.nodeId = nodeId; bd.resultMask = UA_BROWSERESULTMASK_ALL; bd.browseDirection = UA_BROWSEDIRECTION_FORWARD; UA_BrowseResult br = UA_Server_browse(server, maxResults, &bd); ck_assert_int_eq(br.statusCode, UA_STATUSCODE_GOOD); ck_assert(br.referencesSize > 0); size_t total = br.referencesSize; UA_ByteString cp = br.continuationPoint; br.continuationPoint = UA_BYTESTRING_NULL; UA_BrowseResult_deleteMembers(&br); while(cp.length > 0) { br = UA_Server_browseNext(server, false, &cp); ck_assert(br.referencesSize > 0); UA_ByteString_deleteMembers(&cp); cp = br.continuationPoint; br.continuationPoint = UA_BYTESTRING_NULL; total += br.referencesSize; UA_BrowseResult_deleteMembers(&br); } return total; }
static void print_time(void) { UA_DateTime now = UA_DateTime_now(); UA_ByteString str; UA_DateTime_toString(now, &str); printf("%.27s", str.data); //a bit hacky way not to display nanoseconds UA_ByteString_deleteMembers(&str); }
/* 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; }
/* run only when the server is stopped */ static void ServerNetworkLayerTCP_deleteMembers(UA_ServerNetworkLayer *nl) { ServerNetworkLayerTCP *layer = nl->handle; #ifndef UA_MULTITHREADING UA_ByteString_deleteMembers(&layer->buffer); #endif for(size_t i = 0; i < layer->mappingsSize; i++) free(layer->mappings[i].connection); free(layer->mappings); free(layer); }
void UA_Log_Stdout(UA_LogLevel level, UA_LogCategory category, const char *msg, ...) { UA_String t = UA_DateTime_toString(UA_DateTime_now()); printf("[%.23s] %s/%s\t", t.data, LogLevelNames[level], LogCategoryNames[category]); UA_ByteString_deleteMembers(&t); va_list ap; va_start(ap, msg); vprintf(msg, ap); va_end(ap); printf("\n"); }
static UA_Int32 sendCreateSession(UA_Int32 sock, UA_UInt32 channelId, UA_UInt32 tokenId, UA_UInt32 sequenceNumber, UA_UInt32 requestId, UA_String *endpointUrl) { UA_ByteString message; UA_ByteString_newMembers(&message, 65536); UA_UInt32 tmpChannelId = channelId; size_t offset = 0; UA_TcpMessageHeader msghdr; msghdr.messageTypeAndFinal = UA_MESSAGETYPEANDFINAL_MSGF; UA_NodeId type; type.identifier.numeric = 461; type.identifierType = UA_NODEIDTYPE_NUMERIC; type.namespaceIndex = 0; UA_CreateSessionRequest rq; UA_CreateSessionRequest_init(&rq); rq.requestHeader.requestHandle = 1; rq.requestHeader.timestamp = UA_DateTime_now(); rq.requestHeader.timeoutHint = 10000; rq.requestHeader.authenticationToken.identifier.numeric = 10; rq.requestHeader.authenticationToken.identifierType = UA_NODEIDTYPE_NUMERIC; rq.requestHeader.authenticationToken.namespaceIndex = 10; UA_String_copy(endpointUrl, &rq.endpointUrl); UA_String_copycstring("mysession", &rq.sessionName); UA_String_copycstring("abcd", &rq.clientCertificate); UA_ByteString_newMembers(&rq.clientNonce, 1); rq.clientNonce.data[0] = 0; rq.requestedSessionTimeout = 1200000; rq.maxResponseMessageSize = UA_INT32_MAX; msghdr.messageSize = 16 + UA_TcpMessageHeader_calcSizeBinary(&msghdr) + UA_NodeId_calcSizeBinary(&type) + UA_CreateSessionRequest_calcSizeBinary(&rq); UA_TcpMessageHeader_encodeBinary(&msghdr, &message, &offset); UA_UInt32_encodeBinary(&tmpChannelId, &message, &offset); UA_UInt32_encodeBinary(&tokenId, &message, &offset); UA_UInt32_encodeBinary(&sequenceNumber, &message, &offset); UA_UInt32_encodeBinary(&requestId, &message, &offset); UA_NodeId_encodeBinary(&type, &message, &offset); UA_CreateSessionRequest_encodeBinary(&rq, &message, &offset); UA_Int32 sendret = send(sock, message.data, offset, 0); UA_ByteString_deleteMembers(&message); UA_CreateSessionRequest_deleteMembers(&rq); if (sendret < 0) { printf("send opensecurechannel failed"); return 1; } return 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); }
END_TEST START_TEST(encodeShallYieldDecode) { // given UA_ByteString msg1, msg2; UA_UInt32 pos = 0; void *obj1 = UA_TYPES[_i].new(); UA_ByteString_newMembers(&msg1, UA_TYPES[_i].encodings[UA_ENCODING_BINARY].calcSize(obj1)); UA_StatusCode retval = UA_TYPES[_i].encodings[UA_ENCODING_BINARY].encode(obj1, &msg1, &pos); if(retval != UA_STATUSCODE_GOOD) { // this happens, e.g. when we encode a variant (with UA_TYPES[UA_INVALIDTYPE] in the vtable) UA_TYPES[_i].delete(obj1); UA_ByteString_deleteMembers(&msg1); return; }
static UA_Int32 closeSession(ConnectionInfo *connectionInfo) { size_t offset = 0; UA_ByteString message; UA_ByteString_newMembers(&message, 65536); UA_CloseSessionRequest rq; UA_CloseSessionRequest_init(&rq); rq.requestHeader.requestHandle = 1; rq.requestHeader.timestamp = UA_DateTime_now(); rq.requestHeader.timeoutHint = 10000; rq.requestHeader.authenticationToken.identifier.numeric = 10; rq.requestHeader.authenticationToken.identifierType = UA_NODEIDTYPE_NUMERIC; rq.requestHeader.authenticationToken.namespaceIndex = 10; rq.deleteSubscriptions = UA_TRUE; UA_TcpMessageHeader msghdr; msghdr.messageTypeAndFinal = UA_MESSAGETYPEANDFINAL_MSGF; UA_NodeId type; type.identifier.numeric = 473; type.identifierType = UA_NODEIDTYPE_NUMERIC; type.namespaceIndex = 0; msghdr.messageSize = 16 + UA_TcpMessageHeader_calcSizeBinary(&msghdr) + UA_NodeId_calcSizeBinary(&type) + UA_CloseSessionRequest_calcSizeBinary(&rq); UA_TcpMessageHeader_encodeBinary(&msghdr, &message, &offset); UA_UInt32_encodeBinary(&connectionInfo->channelId, &message, &offset); UA_UInt32_encodeBinary(&connectionInfo->tokenId, &message, &offset); UA_UInt32_encodeBinary(&connectionInfo->sequenceHdr.sequenceNumber, &message, &offset); UA_UInt32_encodeBinary(&connectionInfo->sequenceHdr.requestId, &message, &offset); UA_NodeId_encodeBinary(&type, &message, &offset); UA_CloseSessionRequest_encodeBinary(&rq, &message, &offset); UA_Int32 sendret = send(connectionInfo->socket, message.data, offset, 0); UA_ByteString_deleteMembers(&message); UA_CloseSessionRequest_deleteMembers(&rq); if(sendret < 0) { printf("send closesessionrequest failed"); return 1; } return 0; }
/** * Called in processCompleteChunk for every complete chunk which is received by the server. * * It will first try to decode the message to get the name of the called service. * When we have a name the message is dumped as binary to that file. * If the file already exists a new file will be created with a counter at the end. */ void UA_debug_dumpCompleteChunk(UA_Server *const server, UA_Connection *const connection, UA_ByteString *messageBuffer) { struct UA_dump_filename dump_filename; dump_filename.messageType = NULL; dump_filename.serviceName[0] = 0; if(!connection->channel) { UA_debug_dump_setName_withoutChannel(server, connection, messageBuffer, &dump_filename); } else { UA_SecureChannel dummy = *connection->channel; TAILQ_INIT(&dummy.messages); UA_ByteString messageBufferCopy; UA_ByteString_copy(messageBuffer, &messageBufferCopy); UA_SecureChannel_decryptAddChunk(&dummy, &messageBufferCopy, UA_TRUE); UA_SecureChannel_processCompleteMessages(&dummy, &dump_filename, UA_debug_dump_setName_withChannel); UA_SecureChannel_deleteMessages(&dummy); UA_ByteString_deleteMembers(&messageBufferCopy); } char fileName[250]; snprintf(fileName, 255, "%s/%05d_%s%s", UA_CORPUS_OUTPUT_DIR, ++UA_dump_chunkCount, dump_filename.messageType ? dump_filename.messageType : "", dump_filename.serviceName); char dumpOutputFile[255]; snprintf(dumpOutputFile, 255, "%s.bin", fileName); // check if file exists and if yes create a counting filename to avoid overwriting unsigned cnt = 1; while ( access( dumpOutputFile, F_OK ) != -1 ) { snprintf(dumpOutputFile, 255, "%s_%d.bin", fileName, cnt); cnt++; } UA_LOG_INFO(&server->config.logger, UA_LOGCATEGORY_SERVER, "Dumping package %s", dumpOutputFile); FILE *write_ptr = fopen(dumpOutputFile, "ab"); fwrite(messageBuffer->data, messageBuffer->length, 1, write_ptr); // write 10 bytes from our buffer // add the available memory size. See the UA_DUMP_RAM_SIZE define for more info. uint32_t ramSize = UA_DUMP_RAM_SIZE; fwrite(&ramSize, sizeof(ramSize), 1, write_ptr); fclose(write_ptr); }
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; }
int main(int argc, char** argv) { signal(SIGINT, stopHandler); /* catches ctrl-c */ #ifdef UA_MULTITHREADING pthread_rwlock_init(&writeLock, 0); #endif UA_Server *server = UA_Server_new(UA_ServerConfig_standard); logger = Logger_Stdout_new(); UA_Server_setLogger(server, logger); UA_ByteString certificate = loadCertificate(); UA_Server_setServerCertificate(server, certificate); UA_ByteString_deleteMembers(&certificate); UA_Server_addNetworkLayer(server, ServerNetworkLayerTCP_new(UA_ConnectionConfig_standard, 16664)); // add node with the datetime data source UA_DataSource dateDataSource = (UA_DataSource) {.handle = NULL, .read = readTimeData, .release = releaseTimeData, .write = NULL}; const UA_QualifiedName dateName = UA_QUALIFIEDNAME(1, "current time"); UA_Server_addDataSourceVariableNode(server, dateDataSource, dateName, UA_NODEID_NULL, UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES)); //cpu temperature monitoring for linux machines if((temperatureFile = fopen("/sys/class/thermal/thermal_zone0/temp", "r"))){ // add node with the data source UA_DataSource temperatureDataSource = (UA_DataSource) {.handle = NULL, .read = readTemperature, .release = releaseTemperature, .write = NULL}; const UA_QualifiedName tempName = UA_QUALIFIEDNAME(1, "cpu temperature"); UA_Server_addDataSourceVariableNode(server, temperatureDataSource, tempName, UA_NODEID_NULL, UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER), UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES)); }
static UA_ByteString loadCertificate(void) { UA_ByteString certificate = UA_STRING_NULL; FILE *fp = NULL; if(!(fp=fopen("server_cert.der", "rb"))) { errno = 0; // we read errno also from the tcp layer... return certificate; } fseek(fp, 0, SEEK_END); certificate.length = (size_t)ftell(fp); certificate.data = malloc(certificate.length*sizeof(UA_Byte)); if(!certificate.data){ fclose(fp); return certificate; } fseek(fp, 0, SEEK_SET); if(fread(certificate.data, sizeof(UA_Byte), certificate.length, fp) < (size_t)certificate.length) UA_ByteString_deleteMembers(&certificate); // error reading the cert fclose(fp); return certificate; }
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); }
static UA_Int32 closeSecureChannel(ConnectionInfo *connectionInfo) { size_t offset = 0; UA_ByteString message; UA_ByteString_newMembers(&message, 65536); UA_CloseSecureChannelRequest rq; UA_CloseSecureChannelRequest_init(&rq); rq.requestHeader.requestHandle = 1; rq.requestHeader.timestamp = UA_DateTime_now(); rq.requestHeader.timeoutHint = 10000; rq.requestHeader.authenticationToken.identifier.numeric = 10; rq.requestHeader.authenticationToken.identifierType = UA_NODEIDTYPE_NUMERIC; rq.requestHeader.authenticationToken.namespaceIndex = 10; UA_TcpMessageHeader msghdr; msghdr.messageTypeAndFinal = UA_MESSAGETYPEANDFINAL_CLOF; msghdr.messageSize = 4 + UA_TcpMessageHeader_calcSizeBinary(&msghdr) + UA_CloseSecureChannelRequest_calcSizeBinary(&rq); UA_TcpMessageHeader_encodeBinary(&msghdr, &message, &offset); UA_UInt32_encodeBinary(&connectionInfo->channelId, &message, &offset); UA_CloseSecureChannelRequest_encodeBinary(&rq, &message, &offset); UA_Int32 sendret = send(connectionInfo->socket, message.data, offset, 0); UA_ByteString_deleteMembers(&message); UA_CloseSecureChannelRequest_deleteMembers(&rq); if(sendret < 0) { printf("send CloseSecureChannelRequest failed"); return 1; } return 0; }