/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * Copyright 2019 (c) fortiss (Author: Stefan Profanter) */ #include "custom_memory_manager.h" #include #include #include #include #include "ua_server_internal.h" #include "testing_networklayers.h" #define RECEIVE_BUFFER_SIZE 65535 #define SERVER_PORT 4840 volatile bool running = true; static void *serverLoop(void *server_ptr) { UA_Server *server = (UA_Server*) server_ptr; while (running) { UA_Server_run_iterate(server, false); } return NULL; } /* ** Main entry point. The fuzzer invokes this function with each ** fuzzed input. */ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { // Allow the fuzzer to at least create all the necessary structs before limiting memory. // Otherwise fuzzing is useless UA_memoryManager_setLimit((unsigned long long) -1); /* less debug output */ UA_ServerConfig initialConfig; memset(&initialConfig, 0, sizeof(UA_ServerConfig)); UA_StatusCode retval = UA_ServerConfig_setMinimal(&initialConfig, SERVER_PORT, NULL); initialConfig.allowEmptyVariables = UA_RULEHANDLING_ACCEPT; if(retval != UA_STATUSCODE_GOOD) { UA_ServerConfig_clean(&initialConfig); UA_LOG_FATAL(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "Could not generate the server config"); return EXIT_FAILURE; } UA_Server *server = UA_Server_newWithConfig(&initialConfig); if(!server) { UA_LOG_FATAL(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "Could not create server instance using UA_Server_new"); return EXIT_FAILURE; } UA_ServerConfig *config = UA_Server_getConfig(server); // Enable the mDNS announce and response functionality config->mdnsEnabled = true; config->mdnsConfig.mdnsServerName = UA_String_fromChars("Sample Multicast Server"); retval = UA_Server_run_startup(server); if(retval != UA_STATUSCODE_GOOD) { UA_LOG_FATAL(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "Could not run UA_Server_run_startup. %s", UA_StatusCode_name(retval)); UA_Server_delete(server); return EXIT_FAILURE; } if (!UA_memoryManager_setLimitFromLast4Bytes(data, size)) { UA_Server_run_shutdown(server); UA_Server_delete(server); return EXIT_SUCCESS; } size -= 4; // Iterate once to initialize the TCP connection. Otherwise the connect below may come before the server is up. UA_Server_run_iterate(server, true); pthread_t serverThread; int rc = pthread_create(&serverThread, NULL, serverLoop, (void *)server); if (rc){ UA_LOG_FATAL(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "return code from pthread_create() is %d", rc); UA_Server_run_shutdown(server); UA_Server_delete(server); return -1; } int retCode = EXIT_SUCCESS; int sockfd = 0; { // create a client and write to localhost TCP server if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { UA_LOG_FATAL(UA_Log_Stdout, UA_LOGCATEGORY_CLIENT, "Could not create socket"); retCode = EXIT_FAILURE; } else { struct sockaddr_in serv_addr; serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons(SERVER_PORT); serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); int status = connect(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)); if (status >= 0) { if (write(sockfd, data, size) != size) { UA_LOG_FATAL(UA_Log_Stdout, UA_LOGCATEGORY_CLIENT, "Did not write %lu bytes", (long unsigned)size); retCode = EXIT_FAILURE; } } else { UA_LOG_FATAL(UA_Log_Stdout, UA_LOGCATEGORY_CLIENT, "Could not connect to server: %s", strerror(errno)); retCode = EXIT_FAILURE; } } } running = false; void *status; pthread_join(serverThread, &status); // Process any remaining data. Just repeat a few times to empty all the buffered bytes for (size_t i=0; i<5; i++) { UA_Server_run_iterate(server, false); } close(sockfd); UA_Server_run_shutdown(server); UA_Server_delete(server); return retCode; }