Browse Source

manually trigger failure modes for additional unit tests

Julius Pfrommer 6 years ago
parent
commit
68b567f82a
4 changed files with 41 additions and 5 deletions
  1. 10 3
      CMakeLists.txt
  2. 3 0
      include/ua_config.h.in
  3. 22 2
      src/ua_securechannel.c
  4. 6 0
      src/ua_securechannel.h

+ 10 - 3
CMakeLists.txt

@@ -102,19 +102,26 @@ mark_as_advanced(UA_ENABLE_VALGRIND_UNIT_TESTS)
 option(UA_ENABLE_NONSTANDARD_UDP "Enable udp extension (non-standard)" OFF)
 mark_as_advanced(UA_ENABLE_NONSTANDARD_UDP)
 
+option(UA_ENABLE_UNIT_TEST_FAILURE_HOOKS
+       "Add hooks to force failure modes for additional unit tests. Not for production use!" OFF)
+mark_as_advanced(UA_ENABLE_UNIT_TEST_FAILURE_HOOKS)
+
+# Build options for debugging
+option(UA_DEBUG_DUMP_PKGS "Dump every package received by the server as hexdump format" OFF)
+mark_as_advanced(UA_DEBUG_DUMP_PKGS)
+
 # Build Targets
 option(UA_BUILD_EXAMPLES "Build example servers and clients" OFF)
 option(UA_BUILD_UNIT_TESTS "Build the unit tests" OFF)
 option(UA_BUILD_FUZZING "Build the fuzzing executables" OFF)
 mark_as_advanced(UA_BUILD_FUZZING)
-if (UA_BUILD_FUZZING)
+if(UA_BUILD_FUZZING)
     # oss-fuzz already defines this by default
     add_definitions(-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
 endif()
+
 option(UA_BUILD_OSS_FUZZ "Special build switch used in oss-fuzz" OFF)
 mark_as_advanced(UA_BUILD_OSS_FUZZ)
-option(UA_DEBUG_DUMP_PKGS "Dump every package received by the server as hexdump format" OFF)
-mark_as_advanced(UA_DEBUG_DUMP_PKGS)
 
 # Advanced Build Targets
 option(UA_BUILD_SELFSIGNED_CERTIFICATE "Generate self-signed certificate" OFF)

+ 3 - 0
include/ua_config.h.in

@@ -38,6 +38,9 @@ extern "C" {
 #cmakedefine UA_ENABLE_DISCOVERY
 #cmakedefine UA_ENABLE_DISCOVERY_MULTICAST
 #cmakedefine UA_ENABLE_DISCOVERY_SEMAPHORE
+#cmakedefine UA_ENABLE_UNIT_TEST_FAILURE_HOOKS
+
+/* Options for Debugging */
 #cmakedefine UA_DEBUG_DUMP_PKGS
 
 /**

+ 22 - 2
src/ua_securechannel.c

@@ -25,6 +25,12 @@
 const UA_ByteString
     UA_SECURITY_POLICY_NONE_URI = {47, (UA_Byte *) "http://opcfoundation.org/UA/SecurityPolicy#None"};
 
+#ifdef UA_ENABLE_UNIT_TEST_FAILURE_HOOKS
+UA_THREAD_LOCAL UA_StatusCode decrypt_verifySignatureFailure;
+UA_THREAD_LOCAL UA_StatusCode sendAsym_sendFailure;
+UA_THREAD_LOCAL UA_StatusCode processSym_seqNumberFailure;
+#endif
+
 /* Callback data for sending responses in multiple chunks */
 typedef struct {
     UA_SecureChannel *channel;
@@ -405,7 +411,11 @@ UA_SecureChannel_sendAsymmetricOPNMessage(UA_SecureChannel *channel, UA_UInt32 r
 
     /* Send the message, the buffer is freed in the network layer */
     buf.length = respHeader.messageHeader.messageSize;
-    return connection->send(connection, &buf);
+    retval = connection->send(connection, &buf);
+#ifdef UA_ENABLE_UNIT_TEST_FAILURE_HOOKS
+    retval |= sendAsym_sendFailure
+#endif
+    return retval;
 }
 
 /**************************/
@@ -772,7 +782,11 @@ decryptChunk(UA_SecureChannel *channel, const UA_SecurityPolicyCryptoModule *cry
         /* Verify the signature */
         const UA_ByteString chunkDataToVerify = {chunkSizeAfterDecryption - sigsize, chunk->data};
         const UA_ByteString signature = {sigsize, chunk->data + chunkSizeAfterDecryption - sigsize};
-        retval = cryptoModule->verify(securityPolicy, channel->channelContext, &chunkDataToVerify, &signature);
+        retval = cryptoModule->verify(securityPolicy, channel->channelContext,
+                                      &chunkDataToVerify, &signature);
+#ifdef UA_ENABLE_UNIT_TEST_FAILURE_HOOKS
+        retval |= decrypt_verifySignatureFailure;
+#endif
         if(retval != UA_STATUSCODE_GOOD)
             return retval;
     }
@@ -806,6 +820,12 @@ processSequenceNumberAsym(UA_SecureChannel *const channel, UA_UInt32 sequenceNum
 // TODO: We somehow need to make sure that a sequence number is never reused for the same tokenId
 static UA_StatusCode
 processSequenceNumberSym(UA_SecureChannel *const channel, UA_UInt32 sequenceNumber) {
+    /* Failure mode hook for unit tests */
+#ifdef UA_ENABLE_UNIT_TEST_FAILURE_HOOKS
+    if(processSym_seqNumberFailure != UA_STATUSCODE_GOOD)
+        return processSym_seqNumberFailure;
+#endif
+
     /* Does the sequence number match? */
     if(sequenceNumber != channel->receiveSequenceNumber + 1) {
         if(channel->receiveSequenceNumber + 1 > 4294966271 && sequenceNumber < 1024) // FIXME: Remove magic numbers :(

+ 6 - 0
src/ua_securechannel.h

@@ -19,6 +19,12 @@ extern "C" {
 
 #define UA_SECURE_CONVERSATION_MESSAGE_HEADER_LENGTH 12
 
+#ifdef UA_ENABLE_UNIT_TEST_FAILURE_HOOKS
+extern UA_THREAD_LOCAL UA_StatusCode decrypt_verifySignatureFailure;
+extern UA_THREAD_LOCAL UA_StatusCode sendAsym_sendFailure;
+extern UA_THREAD_LOCAL UA_StatusCode processSym_seqNumberFailure;
+#endif
+
 struct UA_Session;
 typedef struct UA_Session UA_Session;