IOT-2258: Allow secure and nonsecure endpoints with OCCreateResource.
authorTodd Malsbary <todd.malsbary@intel.com>
Wed, 17 May 2017 18:56:13 +0000 (11:56 -0700)
committerDan Mihai <Daniel.Mihai@microsoft.com>
Sat, 20 May 2017 00:56:13 +0000 (00:56 +0000)
Added new property flag OC_NONSECURE.  To specify both secure and
nonsecure endpoints use OC_SECURE | OC_NONSECURE.  The behavior when
neither flag is specified is OC_NONSECURE, the same as before this
change.

Bug: https://jira.iotivity.org/browse/IOT-2258
Change-Id: I12ffdff70a83455eff46d4464e234963063c4f35
Signed-off-by: Todd Malsbary <todd.malsbary@intel.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/19995
Tested-by: jenkins-iotivity <jenkins@iotivity.org>
Reviewed-by: Dan Mihai <Daniel.Mihai@microsoft.com>
resource/csdk/include/octypes.h
resource/csdk/resource-directory/src/rd_client.c
resource/csdk/security/src/doxmresource.c
resource/csdk/stack/src/ocpayload.c
resource/csdk/stack/src/ocstack.c
resource/csdk/stack/test/stacktests.cpp

index 2106098..9c24106 100644 (file)
@@ -984,7 +984,7 @@ typedef enum
  */
 typedef enum
 {
-    /** When none of the bits are set, the resource is non-discoverable &
+    /** When none of the bits are set, the resource is non-secure, non-discoverable &
      *  non-observable by the client.*/
     OC_RES_PROP_NONE = (0),
 
@@ -1004,6 +1004,9 @@ typedef enum
      *  processing its requests from clients.*/
     OC_SLOW          = (1 << 3),
 
+    /** When this bit is set, the resource supports access via non-secure endpoints. */
+    OC_NONSECURE     = (1 << 6),
+
 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
     /** When this bit is set, the resource is a secure resource.*/
     OC_SECURE        = (1 << 4),
@@ -1031,6 +1034,8 @@ typedef enum
 #endif
 } OCResourceProperty;
 
+#define OC_MASK_RESOURCE_SECURE    (OC_NONSECURE | OC_SECURE)
+
 /**
  * Transport Protocol IDs.
  */
index 144272a..d550ef2 100644 (file)
@@ -250,7 +250,8 @@ static OCRepPayload *RDPublishPayloadCreate(const unsigned char *id,
             }
 
             OCResourceProperty p = OCGetResourceProperties(handle);
-            bool isSecure = (p & OC_SECURE);
+            bool includeSecure = (p & OC_SECURE);
+            bool includeNonsecure = (p & OC_NONSECURE);
             p &= (OC_DISCOVERABLE | OC_OBSERVABLE);
             OCRepPayload *policy = OCRepPayloadCreate();
             if (!policy)
@@ -278,7 +279,8 @@ static OCRepPayload *RDPublishPayloadCreate(const unsigned char *id,
                 uint32_t k = 0;
                 for (size_t i = 0; i < nCaEps; i++)
                 {
-                    if (isSecure == (bool)(caEps[i].flags & OC_FLAG_SECURE))
+                    bool isSecure = (caEps[i].flags & OC_FLAG_SECURE);
+                    if ((isSecure && includeSecure) || (!isSecure && includeNonsecure))
                     {
                         char *epStr = OCCreateEndpointStringFromCA(&caEps[i]);
                         if (!epStr)
index c804022..b2a2445 100644 (file)
@@ -1766,7 +1766,7 @@ OCStackResult CreateDoxmResource()
                                          OIC_RSRC_DOXM_URI,
                                          DoxmEntityHandler,
                                          NULL,
-                                         OC_SECURE |
+                                         OC_SECURE | OC_NONSECURE |
                                          OC_DISCOVERABLE);
 
     if (OC_STACK_OK != ret)
index eaf5973..86d650b 100644 (file)
@@ -1818,7 +1818,8 @@ static OCResourcePayload* OCCopyResource(const OCResource* res, uint16_t secureP
         return NULL;
     }
 
-    bool isSecure = res->resourceProperties & OC_FLAG_SECURE;
+    bool includeSecure = res->resourceProperties & OC_SECURE;
+    bool includeNonsecure = res->resourceProperties & OC_NONSECURE;
     OCEndpointPayload *selfEp = NULL;
     if (networkInfo && infoSize && devAddr)
     {
@@ -1842,8 +1843,9 @@ static OCResourcePayload* OCCopyResource(const OCResource* res, uint16_t secureP
                         return NULL;
                     }
 
+                    bool isSecure = (info->flags & OC_FLAG_SECURE);
                     if (((res->endpointType) & matchedTps) &&
-                            (isSecure == (bool)(info->flags & OC_FLAG_SECURE)))
+                            ((isSecure && includeSecure) || (!isSecure && includeNonsecure)))
                     {
                         // create payload
                         OCEndpointPayload* tmpNode = (OCEndpointPayload*)
index 29248dd..5ee4991 100644 (file)
@@ -4087,7 +4087,7 @@ OCStackResult OCCreateResourceWithEp(OCResourceHandle *handle,
 #endif
     // Make sure resourceProperties bitmask has allowed properties specified
     if (resourceProperties
-            > (OC_ACTIVE | OC_DISCOVERABLE | OC_OBSERVABLE | OC_SLOW | OC_SECURE |
+            > (OC_ACTIVE | OC_DISCOVERABLE | OC_OBSERVABLE | OC_SLOW | OC_NONSECURE | OC_SECURE |
                OC_EXPLICIT_DISCOVERABLE
 #ifdef MQ_PUBLISHER
                | OC_MQ_PUBLISHER
@@ -4165,6 +4165,12 @@ OCStackResult OCCreateResourceWithEp(OCResourceHandle *handle,
         goto exit;
     }
 
+    // Set resource to nonsecure if caller did not specify
+    if ((resourceProperties & OC_MASK_RESOURCE_SECURE) == 0)
+    {
+        resourceProperties |= OC_NONSECURE;
+    }
+
     // Set properties.  Set OC_ACTIVE
     pointer->resourceProperties = (OCResourceProperty) (resourceProperties
             | OC_ACTIVE);
index 4bee8ef..33faf9e 100644 (file)
@@ -1331,6 +1331,7 @@ TEST(StackResource, GetResourceProperties)
     OIC_LOG(INFO, TAG, "Starting GetResourceProperties test");
     InitStack(OC_SERVER);
 
+    uint8_t props = OC_DISCOVERABLE|OC_OBSERVABLE;
     OCResourceHandle handle;
     EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle,
                                             "core.led",
@@ -1338,13 +1339,9 @@ TEST(StackResource, GetResourceProperties)
                                             "/a/led",
                                             0,
                                             NULL,
-                                            OC_DISCOVERABLE|OC_OBSERVABLE));
+                                            props));
 
-#ifdef MQ_PUBLISHER
-    EXPECT_EQ(OC_ACTIVE|OC_DISCOVERABLE|OC_OBSERVABLE|OC_MQ_PUBLISHER, OCGetResourceProperties(handle));
-#else
-    EXPECT_EQ(OC_ACTIVE|OC_DISCOVERABLE|OC_OBSERVABLE, OCGetResourceProperties(handle));
-#endif
+    EXPECT_EQ(props, OCGetResourceProperties(handle) & props);
     EXPECT_EQ(OC_STACK_OK, OCDeleteResource(handle));
 
     EXPECT_EQ(OC_STACK_OK, OCStop());
@@ -1365,12 +1362,9 @@ TEST(StackResource, SetResourceProperties)
                                             NULL,
                                             0));
 
-    EXPECT_EQ(OC_STACK_OK, OCSetResourceProperties(handle, OC_DISCOVERABLE|OC_OBSERVABLE));
-#ifdef MQ_PUBLISHER
-    EXPECT_EQ(OC_ACTIVE|OC_DISCOVERABLE|OC_OBSERVABLE|OC_MQ_PUBLISHER, OCGetResourceProperties(handle));
-#else
-    EXPECT_EQ(OC_ACTIVE|OC_DISCOVERABLE|OC_OBSERVABLE, OCGetResourceProperties(handle));
-#endif
+    uint8_t props = OC_DISCOVERABLE|OC_OBSERVABLE;
+    EXPECT_EQ(OC_STACK_OK, OCSetResourceProperties(handle, props));
+    EXPECT_EQ(props, OCGetResourceProperties(handle) & props);
 
     EXPECT_EQ(OC_STACK_OK, OCDeleteResource(handle));
 
@@ -1383,6 +1377,7 @@ TEST(StackResource, ClearResourceProperties)
     OIC_LOG(INFO, TAG, "Starting ClearResourceProperties test");
     InitStack(OC_SERVER);
 
+    uint8_t props = OC_DISCOVERABLE|OC_OBSERVABLE;
     OCResourceHandle handle;
     EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle,
                                             "core.led",
@@ -1390,14 +1385,10 @@ TEST(StackResource, ClearResourceProperties)
                                             "/a/led",
                                             0,
                                             NULL,
-                                            OC_DISCOVERABLE|OC_OBSERVABLE));
+                                            props));
 
-    EXPECT_EQ(OC_STACK_OK, OCClearResourceProperties(handle, OC_DISCOVERABLE|OC_OBSERVABLE));
-#ifdef MQ_PUBLISHER
-    EXPECT_EQ(OC_ACTIVE|OC_MQ_PUBLISHER, OCGetResourceProperties(handle));
-#else
-    EXPECT_EQ(OC_ACTIVE, OCGetResourceProperties(handle));
-#endif
+    EXPECT_EQ(OC_STACK_OK, OCClearResourceProperties(handle, props));
+    EXPECT_EQ(0, OCGetResourceProperties(handle) & props);
 
     EXPECT_EQ(OC_STACK_OK, OCDeleteResource(handle));
 
@@ -2817,6 +2808,111 @@ TEST_F(OCDiscoverTests, DISABLED_DiscoverResourceWithInvalidQueries)
     EXPECT_EQ(OC_STACK_OK, discoverUnicastRTEmptyCB.Wait(10));
 }
 
+class OCEndpointTests : public testing::Test
+{
+    protected:
+        virtual void SetUp()
+        {
+            OCPersistentStorage ps = { fopen, fread, fwrite, fclose, unlink };
+            EXPECT_EQ(OC_STACK_OK, OCRegisterPersistentStorageHandler(&ps));
+            EXPECT_EQ(OC_STACK_OK, OCInit(NULL, 0, OC_CLIENT_SERVER));
+        }
+
+        virtual void TearDown()
+        {
+            OCStop();
+        }
+};
+
+static OCStackApplicationResult SecureAndNonsecureEndpoints(void *ctx, OCDoHandle handle,
+    OCClientResponse *response)
+{
+    OC_UNUSED(ctx);
+    OC_UNUSED(handle);
+    EXPECT_EQ(OC_STACK_OK, response->result);
+    EXPECT_TRUE(NULL != response->payload);
+    if (NULL != response->payload)
+    {
+        EXPECT_EQ(PAYLOAD_TYPE_DISCOVERY, response->payload->type);
+        OCDiscoveryPayload *payload = (OCDiscoveryPayload *)response->payload;
+        EXPECT_TRUE(NULL != payload->sid);
+        for (OCResourcePayload *resource = payload->resources; resource; resource = resource->next)
+        {
+            if (!strcmp("/a/default", resource->uri))
+            {
+                for (OCEndpointPayload *ep = resource->eps; ep; ep = ep->next)
+                {
+                    EXPECT_EQ(0, OC_FLAG_SECURE & ep->family);
+                }
+            }
+            else if (!strcmp("/a/secure", resource->uri))
+            {
+                for (OCEndpointPayload *ep = resource->eps; ep; ep = ep->next)
+                {
+#ifdef __WITH_DTLS__
+                    EXPECT_EQ(OC_FLAG_SECURE, OC_FLAG_SECURE & ep->family);
+#else
+                    EXPECT_EQ(0, OC_FLAG_SECURE & ep->family);
+#endif
+                }
+            }
+            else if (!strcmp("/a/nonsecure", resource->uri))
+            {
+                for (OCEndpointPayload *ep = resource->eps; ep; ep = ep->next)
+                {
+                    EXPECT_EQ(0, OC_FLAG_SECURE & ep->family);
+                }
+            }
+            else if (!strcmp("/a/both", resource->uri))
+            {
+                bool hasSecure = false;
+                bool hasNonsecure = false;
+                for (OCEndpointPayload *ep = resource->eps; ep; ep = ep->next)
+                {
+                    if (OC_FLAG_SECURE & ep->family)
+                    {
+                        hasSecure = true;
+                    }
+                    else
+                    {
+                        hasNonsecure = true;
+                    }
+                }
+#ifdef __WITH_DTLS__
+                EXPECT_TRUE(hasSecure);
+#else
+                EXPECT_FALSE(hasSecure);
+#endif
+                EXPECT_TRUE(hasNonsecure);
+            }
+        }
+    }
+    return OC_STACK_DELETE_TRANSACTION;
+}
+
+// Disabled until unit tests can run with SECURED=1 builds
+TEST_F(OCEndpointTests, DISABLED_SecureAndNonsecureEndpoints)
+{
+    itst::DeadmanTimer killSwitch(LONG_TEST_TIMEOUT);
+
+    OCResourceHandle handle;
+    handle = OCGetResourceHandleAtUri(OC_RSRVD_WELL_KNOWN_URI);
+    EXPECT_EQ(OC_STACK_OK, OCSetResourceProperties(handle, OC_DISCOVERABLE | OC_OBSERVABLE));
+    EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle, "core.light", "oic.if.baseline", "/a/default",
+            entityHandler, NULL, OC_DISCOVERABLE));
+    EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle, "core.light", "oic.if.baseline", "/a/secure",
+            entityHandler, NULL, OC_DISCOVERABLE | OC_SECURE));
+    EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle, "core.light", "oic.if.baseline", "/a/nonsecure",
+            entityHandler, NULL, OC_DISCOVERABLE | OC_NONSECURE));
+    EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle, "core.light", "oic.if.baseline", "/a/both",
+            entityHandler, NULL, OC_DISCOVERABLE | OC_SECURE | OC_NONSECURE));
+
+    itst::Callback secureAndNonSecureEndpointsCB(&SecureAndNonsecureEndpoints);
+    EXPECT_EQ(OC_STACK_OK, OCDoResource(NULL, OC_REST_DISCOVER, "/oic/res", NULL,
+            0, CT_DEFAULT, OC_HIGH_QOS, secureAndNonSecureEndpointsCB, NULL, 0));
+    EXPECT_EQ(OC_STACK_OK, secureAndNonSecureEndpointsCB.Wait(100));
+}
+
 #ifdef IP_ADAPTER
 TEST(StackZoneId, getZoneId)
 {