Manufacturer certificate based ownership transfer support.
authorChul Lee <chuls.lee@samsung.com>
Mon, 14 Nov 2016 04:49:36 +0000 (13:49 +0900)
committerRandeep Singh <randeep.s@samsung.com>
Fri, 18 Nov 2016 06:21:47 +0000 (06:21 +0000)
1. Add manufacturer certificate OxM callbacks
   : resource/csdk/security/provisioning/src/oxmmanufacturercert.c
   : resource/csdk/security/provisioning/include/oxm/oxmmanufacturercert.h

2. Apply the manufacturer cert based OxM on the client & server.
   : resource/csdk/security/provisioning/src/ownershiptransfermanager.c
   : resource/csdk/security/src/doxmresource.c

3. Add manufacturer certificate supported sample server
   : resource/csdk/security/provisioning/sample/sampleserver_mfg.cpp

4. Add API to set the allowed/not-allowed OxM which is OCSetOxmAllowStatus()
   : resource/csdk/security/provisioning/src/ocprovisioningmanager.c
   : resource/csdk/security/provisioning/include/ocprovisioningmanager.h

5. Add OCStackResult code to handle not allowed OxM exception.
   : resource/csdk/stack/include/octypes.h
   : resource/src/OCException.cpp
   : resource/include/StringConstants.h
   : resource/unittests/OCExceptionTest.cpp

6. Update the SConscript according to above modifications.
   : resource/csdk/security/provisioning/SConscript
   : resource/csdk/security/provisioning/sample/SConscript

Change-Id: Ibb4b4eec33a1e39234f808e32cc3b96aff4879ad
Signed-off-by: Chul Lee <chuls.lee@samsung.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/14275
Tested-by: jenkins-iotivity <jenkins-iotivity@opendaylight.org>
Reviewed-by: Randeep Singh <randeep.s@samsung.com>
17 files changed:
resource/csdk/octbstack_product_secured.def
resource/csdk/security/provisioning/SConscript
resource/csdk/security/provisioning/include/internal/ownershiptransfermanager.h
resource/csdk/security/provisioning/include/ocprovisioningmanager.h
resource/csdk/security/provisioning/include/oxm/oxmmanufacturercert.h [new file with mode: 0644]
resource/csdk/security/provisioning/sample/SConscript
resource/csdk/security/provisioning/sample/provisioningclient.c
resource/csdk/security/provisioning/sample/sampleserver_mfg.cpp [new file with mode: 0644]
resource/csdk/security/provisioning/src/ocprovisioningmanager.c
resource/csdk/security/provisioning/src/ownershiptransfermanager.c
resource/csdk/security/provisioning/src/oxmmanufacturercert.c [new file with mode: 0644]
resource/csdk/security/provisioning/unittest/otmunittest.cpp
resource/csdk/security/src/doxmresource.c
resource/csdk/stack/include/octypes.h
resource/include/StringConstants.h
resource/src/OCException.cpp
resource/unittests/OCExceptionTest.cpp

index f923cd5..a9525d2 100644 (file)
@@ -32,6 +32,7 @@ OCRemoveDeviceWithUuid
 OCResetDevice
 OCSetOwnerTransferCallbackData
 OCUnlinkDevices
+OCSetOxmAllowStatus
 
 SetGeneratePinCB
 SetInputPinCB
index 0c0ce1b..5956bb0 100644 (file)
@@ -104,6 +104,7 @@ provisioning_src = [
        'src/ocprovisioningmanager.c',
        'src/oxmjustworks.c',
        'src/oxmrandompin.c',
+       'src/oxmmanufacturercert.c',
        'src/provisioningdatabasemanager.c' ]
 
 if provisioning_env.get('MULTIPLE_OWNER') == '1':
index f302bd6..2df0540 100644 (file)
@@ -47,6 +47,17 @@ typedef struct OTMContext OTMContext_t;
 OCStackResult OTMDoOwnershipTransfer(void* ctx,\r
                                      OCProvisionDev_t* selectedDeviceList, OCProvisionResultCB resultCB);\r
 \r
+/**\r
+ * API to set a allow status of OxM\r
+ *\r
+ * @param[in] oxm Owership transfer method (ref. OicSecOxm_t)\r
+ * @param[in] allowStatus allow status (true = allow, false = not allow)\r
+ *\r
+ * @return OC_STACK_OK in case of success and other value otherwise.\r
+ */\r
+OCStackResult OTMSetOxmAllowStatus(const OicSecOxm_t oxm, const bool allowStatus);\r
+\r
+\r
 /*\r
  *Callback for load secret for temporal secure session\r
  *\r
index 0c43003..7cf06a1 100644 (file)
@@ -81,6 +81,16 @@ OCStackResult OCDoOwnershipTransfer(void* ctx,
                                     OCProvisionDev_t *targetDevices,\r
                                     OCProvisionResultCB resultCallback);\r
 \r
+/**\r
+ * API to set a allow status of OxM\r
+ *\r
+ * @param[in] oxm Owership transfer method (ref. OicSecOxm_t)\r
+ * @param[in] allowStatus allow status (true = allow, false = not allow)\r
+ *\r
+ * @return OC_STACK_OK in case of success and other value otherwise.\r
+ */\r
+OCStackResult OCSetOxmAllowStatus(const OicSecOxm_t oxm, const bool allowStatus);\r
+\r
 #ifdef _ENABLE_MULTIPLE_OWNER_\r
 /**\r
  * API to perfrom multiple ownership transfer for MOT enabled device.\r
diff --git a/resource/csdk/security/provisioning/include/oxm/oxmmanufacturercert.h b/resource/csdk/security/provisioning/include/oxm/oxmmanufacturercert.h
new file mode 100644 (file)
index 0000000..0a9bca7
--- /dev/null
@@ -0,0 +1,81 @@
+//******************************************************************
+//
+// Copyright 2016 Samsung Electronics All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#ifndef _OXM_MANUFACTURER_CERTIFICATE_H_
+#define _OXM_MANUFACTURER_CERTIFICATE_H_
+
+#include "ocstack.h"
+#include "securevirtualresourcetypes.h"
+#include "ownershiptransfermanager.h"
+#include "pmtypes.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+/**
+ * Callback implementation to prepare manufacturer certificate based OT.
+ *
+ * @param otmCtx Context of OTM, It includes current device information.
+ *
+ * @return ::OC_STACK_SUCCESS in case of success and other value otherwise.
+ */
+OCStackResult PrepareMCertificateCallback(OTMContext_t *otmCtx);
+
+/**
+ * Callback implementation to establish a secure channel with RSA cipher suite.
+ *
+ * @param otmCtx Context of OTM, It includes current device information.
+ *
+ * @return ::OC_STACK_SUCCESS in case of success and other value otherwise.
+ */
+OCStackResult CreateSecureSessionMCertificateCallback(OTMContext_t *otmCtx);
+
+/**
+ * Generate payload for select OxM request.
+ *
+ * @param otmCtx Context of OTM, It includes current device information.
+ * @param cborPayload is the DOXM CBOR payload including the selected OxM.
+ * @note Returned memory should be deallocated by caller.
+ * @param cborSize is the size of the cborPayload.
+ *
+ * @return ::OC_STACK_SUCCESS in case of success and other value otherwise.
+ */
+OCStackResult CreateMCertificateBasedSelectOxmPayload(OTMContext_t *otmCtx, uint8_t **cborPayload,
+                                             size_t *cborSize);
+
+/**
+ * Generate payload for owner transfer request.
+ *
+ * @param otmCtx Context of OTM, It includes current device information.
+ * @param cborPaylaod is the DOXM CBOR payload including the owner information.
+ * @note Returned memory should be deallocated by caller.
+ * @param cborSize is the size of the cborPayload.
+ *
+ * @return ::OC_STACK_SUCCESS in case of success and other value otherwise.
+ */
+OCStackResult CreateMCertificateBasedOwnerTransferPayload(OTMContext_t *otmCtx, uint8_t **cborPayload,
+                                                 size_t *cborSize);
+
+#ifdef __cplusplus
+}
+#endif
+#endif //_OXM_MANUFACTURER_CERTIFICATE_H_
+
index 99814dd..1ec4546 100644 (file)
@@ -103,6 +103,7 @@ if target_os in ['linux', 'tizen']:
 provisioningclient = provisioning_env.Program('provisioningclient', 'provisioningclient.c')
 sampleserver_justworks = provisioning_env.Program('sampleserver_justworks', 'sampleserver_justworks.cpp')
 sampleserver_randompin = provisioning_env.Program('sampleserver_randompin', 'sampleserver_randompin.cpp')
+sampleserver_mfg = provisioning_env.Program('sampleserver_mfg', 'sampleserver_mfg.cpp')
 
 if provisioning_env.get('MULTIPLE_OWNER') == '1':
        subownerclient = provisioning_env.Program('subownerclient', 'subownerclient.c')
@@ -127,6 +128,8 @@ justworksdat = provisioning_env.Install(sec_provisioning_build_dir,
                                     sec_provisioning_src_dir + 'oic_svr_db_server_justworks.dat')
 randompindat = provisioning_env.Install(sec_provisioning_build_dir,
                                     sec_provisioning_src_dir+ 'oic_svr_db_server_randompin.dat')
+mfgdat = provisioning_env.Install(sec_provisioning_build_dir,
+                                    sec_provisioning_src_dir+ 'oic_svr_db_server_mfg.dat')
 randompin_with_emptyuuid_dat = provisioning_env.Install(sec_provisioning_build_dir,
                                     sec_provisioning_src_dir+ 'oic_svr_db_randompin_with_empty_deviceid.dat')
 
@@ -145,16 +148,16 @@ if provisioning_env.get('WITH_TCP') == True:
 if provisioning_env.get('MULTIPLE_OWNER') == '1':
        Alias("samples", [
                                        provisioningclient, subownerclient,
-                                       sampleserver_justworks, sampleserver_randompin,
+                                       sampleserver_justworks, sampleserver_randompin, sampleserver_mfg,
                                        clientdat, subownerclientdat,
-                                       justworksdat, randompindat, randompin_with_emptyuuid_dat
+                                       justworksdat, randompindat, mfgdat, randompin_with_emptyuuid_dat
                                ])
 else:
        Alias("samples", [
                                        provisioningclient,
-                                       sampleserver_justworks, sampleserver_randompin,
+                                       sampleserver_justworks, sampleserver_randompin, sampleserver_mfg,
                                        clientdat,
-                                       justworksdat, randompindat, randompin_with_emptyuuid_dat
+                                       justworksdat, randompindat, mfgdat, randompin_with_emptyuuid_dat
                                ])
 
 provisioning_env.AppendTarget('samples')
index 1ae6c1d..e1f4e4b 100644 (file)
@@ -2099,6 +2099,12 @@ int main()
         goto PMCLT_ERROR;
     }
 
+    // Client can choose a allowed/not-allowed OxM method.
+    if(OC_STACK_OK != OCSetOxmAllowStatus(OIC_DECENTRALIZED_PUBLIC_KEY, false))
+    {
+        OIC_LOG(WARNING, TAG, "Failed to disable OIC_DECENTRALIZED_PUBLIC_KEY OxM");
+    }
+
 #ifdef _ENABLE_MULTIPLE_OWNER_
     SetPreconfigPin("12341234", 8);
 #endif //_ENABLE_MULTIPLE_OWNER_
diff --git a/resource/csdk/security/provisioning/sample/sampleserver_mfg.cpp b/resource/csdk/security/provisioning/sample/sampleserver_mfg.cpp
new file mode 100644 (file)
index 0000000..c347a42
--- /dev/null
@@ -0,0 +1,480 @@
+/******************************************************************
+*
+* Copyright 2016 Samsung Electronics All Rights Reserved.
+*
+*
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*
+******************************************************************/
+///////////////////////////////////////////////////////////////////////
+//NOTE :  This sample server is generated based on ocserverbasicops.cpp
+///////////////////////////////////////////////////////////////////////
+#include "iotivity_config.h"
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_PTHREAD_H
+#include <pthread.h>
+#endif
+#include <signal.h>
+#include "ocstack.h"
+#include "ocpayload.h"
+
+#ifdef HAVE_WINDOWS_H
+#include <windows.h>
+/** @todo stop-gap for naming issue. Windows.h does not like us to use ERROR */
+#ifdef ERROR
+#undef ERROR
+#endif //ERROR
+#endif //HAVE_WINDOWS_H
+#include "platform_features.h"
+#include "logger.h"
+
+
+#define TAG "SAMPLE_MANUFACTURER_CERT"
+
+int gQuitFlag = 0;
+
+/* Structure to represent a LED resource */
+typedef struct LEDRESOURCE{
+    OCResourceHandle handle;
+    bool state;
+    int power;
+} LEDResource;
+
+static LEDResource LED;
+// This variable determines instance number of the LED resource.
+// Used by POST method to create a new instance of LED resource.
+static int gCurrLedInstance = 0;
+#define SAMPLE_MAX_NUM_POST_INSTANCE  2
+static LEDResource gLedInstance[SAMPLE_MAX_NUM_POST_INSTANCE];
+
+char *gResourceUri= (char *)"/a/led";
+
+//Secure Virtual Resource database for Iotivity Server
+//It contains Server's Identity and the manufacturer certificate
+static char CRED_FILE[] = "oic_svr_db_server_mfg.dat";
+
+/* Function that creates a new LED resource by calling the
+ * OCCreateResource() method.
+ */
+int createLEDResource (char *uri, LEDResource *ledResource, bool resourceState, int resourcePower);
+
+/* This method converts the payload to JSON format */
+OCRepPayload* constructResponse (OCEntityHandlerRequest *ehRequest);
+
+/* Following methods process the PUT, GET, POST
+ * requests
+ */
+OCEntityHandlerResult ProcessGetRequest (OCEntityHandlerRequest *ehRequest,
+                                         OCRepPayload **payload);
+OCEntityHandlerResult ProcessPutRequest (OCEntityHandlerRequest *ehRequest,
+                                         OCRepPayload **payload);
+OCEntityHandlerResult ProcessPostRequest (OCEntityHandlerRequest *ehRequest,
+                                        OCEntityHandlerResponse *response,
+                                        OCRepPayload **payload);
+
+/* Entity Handler callback functions */
+OCEntityHandlerResult
+OCEntityHandlerCb (OCEntityHandlerFlag flag,
+        OCEntityHandlerRequest *entityHandlerRequest,
+        void* callbackParam);
+
+const char *getResult(OCStackResult result) {
+    switch (result) {
+    case OC_STACK_OK:
+        return "OC_STACK_OK";
+    case OC_STACK_RESOURCE_CREATED:
+        return "OC_STACK_RESOURCE_CREATED";
+    case OC_STACK_RESOURCE_DELETED:
+        return "OC_STACK_RESOURCE_DELETED";
+    case OC_STACK_INVALID_URI:
+        return "OC_STACK_INVALID_URI";
+    case OC_STACK_INVALID_QUERY:
+        return "OC_STACK_INVALID_QUERY";
+    case OC_STACK_INVALID_IP:
+        return "OC_STACK_INVALID_IP";
+    case OC_STACK_INVALID_PORT:
+        return "OC_STACK_INVALID_PORT";
+    case OC_STACK_INVALID_CALLBACK:
+        return "OC_STACK_INVALID_CALLBACK";
+    case OC_STACK_INVALID_METHOD:
+        return "OC_STACK_INVALID_METHOD";
+    case OC_STACK_NO_MEMORY:
+        return "OC_STACK_NO_MEMORY";
+    case OC_STACK_COMM_ERROR:
+        return "OC_STACK_COMM_ERROR";
+    case OC_STACK_INVALID_PARAM:
+        return "OC_STACK_INVALID_PARAM";
+    case OC_STACK_NOTIMPL:
+        return "OC_STACK_NOTIMPL";
+    case OC_STACK_NO_RESOURCE:
+        return "OC_STACK_NO_RESOURCE";
+    case OC_STACK_RESOURCE_ERROR:
+        return "OC_STACK_RESOURCE_ERROR";
+    case OC_STACK_SLOW_RESOURCE:
+        return "OC_STACK_SLOW_RESOURCE";
+    case OC_STACK_NO_OBSERVERS:
+        return "OC_STACK_NO_OBSERVERS";
+    #ifdef WITH_PRESENCE
+    case OC_STACK_PRESENCE_STOPPED:
+        return "OC_STACK_PRESENCE_STOPPED";
+    #endif
+    case OC_STACK_ERROR:
+        return "OC_STACK_ERROR";
+    default:
+        return "UNKNOWN";
+    }
+}
+
+OCRepPayload* getPayload(const char* uri, int64_t power, bool state)
+{
+    OCRepPayload* payload = OCRepPayloadCreate();
+    if(!payload)
+    {
+        OIC_LOG(ERROR, TAG, "Failed to allocate Payload");
+        return NULL;
+    }
+
+    OCRepPayloadSetUri(payload, uri);
+    OCRepPayloadSetPropBool(payload, "state", state);
+    OCRepPayloadSetPropInt(payload, "power", power);
+
+    return payload;
+}
+
+//This function takes the request as an input and returns the response
+OCRepPayload* constructResponse (OCEntityHandlerRequest *ehRequest)
+{
+    if(ehRequest->payload && ehRequest->payload->type != PAYLOAD_TYPE_REPRESENTATION)
+    {
+        OIC_LOG(ERROR, TAG, "Incoming payload not a representation");
+        return NULL;
+    }
+
+    OCRepPayload* input = (OCRepPayload*)(ehRequest->payload);
+
+    LEDResource *currLEDResource = &LED;
+
+    if (ehRequest->resource == gLedInstance[0].handle)
+    {
+        currLEDResource = &gLedInstance[0];
+        gResourceUri = (char *) "/a/led/0";
+    }
+    else if (ehRequest->resource == gLedInstance[1].handle)
+    {
+        currLEDResource = &gLedInstance[1];
+        gResourceUri = (char *) "/a/led/1";
+    }
+
+    if(OC_REST_PUT == ehRequest->method)
+    {
+        // Get pointer to query
+        int64_t pow;
+        if(OCRepPayloadGetPropInt(input, "power", &pow))
+        {
+            currLEDResource->power =pow;
+        }
+
+        bool state;
+        if(OCRepPayloadGetPropBool(input, "state", &state))
+        {
+            currLEDResource->state = state;
+        }
+    }
+
+    return getPayload(gResourceUri, currLEDResource->power, currLEDResource->state);
+}
+
+OCEntityHandlerResult ProcessGetRequest (OCEntityHandlerRequest *ehRequest,
+        OCRepPayload **payload)
+{
+    OCEntityHandlerResult ehResult;
+
+    OCRepPayload *getResp = constructResponse(ehRequest);
+
+    if(getResp)
+    {
+        *payload = getResp;
+        ehResult = OC_EH_OK;
+    }
+    else
+    {
+        ehResult = OC_EH_ERROR;
+    }
+
+    return ehResult;
+}
+
+OCEntityHandlerResult ProcessPutRequest (OCEntityHandlerRequest *ehRequest,
+        OCRepPayload **payload)
+{
+    OCEntityHandlerResult ehResult;
+
+    OCRepPayload *putResp = constructResponse(ehRequest);
+
+    if(putResp)
+    {
+        *payload = putResp;
+        ehResult = OC_EH_OK;
+    }
+    else
+    {
+        ehResult = OC_EH_ERROR;
+    }
+
+    return ehResult;
+}
+
+OCEntityHandlerResult ProcessPostRequest (OCEntityHandlerRequest *ehRequest,
+        OCEntityHandlerResponse *response, OCRepPayload **payload)
+{
+    OCRepPayload *respPLPost_led = NULL;
+    OCEntityHandlerResult ehResult = OC_EH_OK;
+
+    /*
+     * The entity handler determines how to process a POST request.
+     * Per the REST paradigm, POST can also be used to update representation of existing
+     * resource or create a new resource.
+     * In the sample below, if the POST is for /a/led then a new instance of the LED
+     * resource is created with default representation (if representation is included in
+     * POST payload it can be used as initial values) as long as the instance is
+     * lesser than max new instance count. Once max instance count is reached, POST on
+     * /a/led updated the representation of /a/led (just like PUT)
+     */
+
+    if (ehRequest->resource == LED.handle)
+    {
+        if (gCurrLedInstance < SAMPLE_MAX_NUM_POST_INSTANCE)
+        {
+            // Create new LED instance
+            char newLedUri[15] = "/a/led/";
+            int newLedUriLength = strlen(newLedUri);
+            snprintf (newLedUri + newLedUriLength, sizeof(newLedUri)-newLedUriLength, "%d", gCurrLedInstance);
+
+            respPLPost_led = OCRepPayloadCreate();
+            OCRepPayloadSetUri(respPLPost_led, gResourceUri);
+            OCRepPayloadSetPropString(respPLPost_led, "createduri", newLedUri);
+
+            if (0 == createLEDResource (newLedUri, &gLedInstance[gCurrLedInstance], false, 0))
+            {
+                OIC_LOG (INFO, TAG, "Created new LED instance");
+                gLedInstance[gCurrLedInstance].state = 0;
+                gLedInstance[gCurrLedInstance].power = 0;
+                gCurrLedInstance++;
+                strncpy ((char *)response->resourceUri, newLedUri, MAX_URI_LENGTH);
+                ehResult = OC_EH_RESOURCE_CREATED;
+            }
+        }
+        else
+        {
+            respPLPost_led = constructResponse(ehRequest);
+        }
+    }
+    else
+    {
+        for (int i = 0; i < SAMPLE_MAX_NUM_POST_INSTANCE; i++)
+        {
+            if (ehRequest->resource == gLedInstance[i].handle)
+            {
+                if (i == 0)
+                {
+                    respPLPost_led = constructResponse(ehRequest);
+                    break;
+                }
+                else if (i == 1)
+                {
+                    respPLPost_led = constructResponse(ehRequest);
+                }
+            }
+        }
+    }
+
+    if (respPLPost_led != NULL)
+    {
+        *payload = respPLPost_led;
+        ehResult = OC_EH_OK;
+    }
+    else
+    {
+        OIC_LOG_V (INFO, TAG, "Payload was NULL");
+        ehResult = OC_EH_ERROR;
+    }
+
+    return ehResult;
+}
+
+OCEntityHandlerResult
+OCEntityHandlerCb (OCEntityHandlerFlag flag,
+        OCEntityHandlerRequest *entityHandlerRequest,
+        void* callbackParam)
+{
+    OIC_LOG_V (INFO, TAG, "Inside entity handler - flags: 0x%x", flag);
+    (void)callbackParam;
+    OCEntityHandlerResult ehResult = OC_EH_ERROR;
+
+    OCEntityHandlerResponse response;
+    memset(&response, 0, sizeof(response));
+
+    // Validate pointer
+    if (!entityHandlerRequest)
+    {
+        OIC_LOG (ERROR, TAG, "Invalid request pointer");
+        return OC_EH_ERROR;
+    }
+
+    OCRepPayload* payload = NULL;
+
+    if (flag & OC_REQUEST_FLAG)
+    {
+        OIC_LOG (INFO, TAG, "Flag includes OC_REQUEST_FLAG");
+        if (entityHandlerRequest)
+        {
+            if (OC_REST_GET == entityHandlerRequest->method)
+            {
+                OIC_LOG (INFO, TAG, "Received OC_REST_GET from client");
+                ehResult = ProcessGetRequest (entityHandlerRequest, &payload);
+            }
+            else if (OC_REST_PUT == entityHandlerRequest->method)
+            {
+                OIC_LOG (INFO, TAG, "Received OC_REST_PUT from client");
+                ehResult = ProcessPutRequest (entityHandlerRequest, &payload);
+            }
+            else if (OC_REST_POST == entityHandlerRequest->method)
+            {
+                OIC_LOG (INFO, TAG, "Received OC_REST_POST from client");
+                ehResult = ProcessPostRequest (entityHandlerRequest, &response, &payload);
+            }
+            else
+            {
+                OIC_LOG_V (INFO, TAG, "Received unsupported method %d from client",
+                        entityHandlerRequest->method);
+                ehResult = OC_EH_ERROR;
+            }
+
+            if (ehResult == OC_EH_OK && ehResult != OC_EH_FORBIDDEN)
+            {
+                // Format the response.  Note this requires some info about the request
+                response.requestHandle = entityHandlerRequest->requestHandle;
+                response.resourceHandle = entityHandlerRequest->resource;
+                response.ehResult = ehResult;
+                response.payload = (OCPayload*)(payload);
+                response.numSendVendorSpecificHeaderOptions = 0;
+                memset(response.sendVendorSpecificHeaderOptions, 0,
+                       sizeof(response.sendVendorSpecificHeaderOptions));
+                memset(response.resourceUri, 0, sizeof(response.resourceUri));
+                // Indicate that response is NOT in a persistent buffer
+                response.persistentBufferFlag = 0;
+
+                // Send the response
+                if (OCDoResponse(&response) != OC_STACK_OK)
+                {
+                    OIC_LOG(ERROR, TAG, "Error sending response");
+                    ehResult = OC_EH_ERROR;
+                }
+            }
+        }
+    }
+
+    OCPayloadDestroy(response.payload);
+    return ehResult;
+}
+
+/* SIGINT handler: set gQuitFlag to 1 for graceful termination */
+void handleSigInt(int signum)
+{
+    if (signum == SIGINT)
+    {
+        gQuitFlag = 1;
+    }
+}
+
+FILE* server_fopen(const char *path, const char *mode)
+{
+    (void)path;
+    return fopen(CRED_FILE, mode);
+}
+
+int main()
+{
+    struct timespec timeout;
+
+    OIC_LOG(DEBUG, TAG, "OCServer is starting...");
+
+    // Initialize Persistent Storage for SVR database
+    OCPersistentStorage ps = {server_fopen, fread, fwrite, fclose, unlink};
+
+    OCRegisterPersistentStorageHandler(&ps);
+
+    if (OCInit(NULL, 0, OC_SERVER) != OC_STACK_OK)
+    {
+        OIC_LOG(ERROR, TAG, "OCStack init error");
+        return 0;
+    }
+
+    /*
+     * Declare and create the example resource: LED
+     */
+    createLEDResource(gResourceUri, &LED, false, 0);
+
+    timeout.tv_sec  = 0;
+    timeout.tv_nsec = 100000000L;
+
+    // Break from loop with Ctrl-C
+    OIC_LOG(INFO, TAG, "Entering ocserver main loop...");
+    signal(SIGINT, handleSigInt);
+    while (!gQuitFlag)
+    {
+        if (OCProcess() != OC_STACK_OK)
+        {
+            OIC_LOG(ERROR, TAG, "OCStack process error");
+            return 0;
+        }
+        nanosleep(&timeout, NULL);
+    }
+
+    OIC_LOG(INFO, TAG, "Exiting ocserver main loop...");
+
+    if (OCStop() != OC_STACK_OK)
+    {
+        OIC_LOG(ERROR, TAG, "OCStack process error");
+    }
+
+    return 0;
+}
+
+int createLEDResource (char *uri, LEDResource *ledResource, bool resourceState, int resourcePower)
+{
+    if (!uri)
+    {
+        OIC_LOG(ERROR, TAG, "Resource URI cannot be NULL");
+        return -1;
+    }
+
+    ledResource->state = resourceState;
+    ledResource->power= resourcePower;
+    OCStackResult res = OCCreateResource(&(ledResource->handle),
+            "core.led",
+            OC_RSRVD_INTERFACE_DEFAULT,
+            uri,
+            OCEntityHandlerCb,
+            NULL,
+            OC_DISCOVERABLE|OC_OBSERVABLE | OC_SECURE);
+    OIC_LOG_V(INFO, TAG, "Created LED resource with result: %s", getResult(res));
+
+    return 0;
+}
index db70815..1bb5efe 100644 (file)
@@ -230,6 +230,19 @@ OCStackResult OCSetOwnerTransferCallbackData(OicSecOxm_t oxm, OTMCallbackData_t*
     return OTMSetOwnershipTransferCallbackData(oxm, callbackData);
 }
 
+/**
+ * API to set a allow status of OxM
+ *
+ * @param[in] oxm Owership transfer method (ref. OicSecOxm_t)
+ * @param[in] allowStatus allow status (true = allow, false = not allow)
+ *
+ * @return OC_STACK_OK in case of success and other value otherwise.
+ */
+OCStackResult OCSetOxmAllowStatus(const OicSecOxm_t oxm, const bool allowStatus)
+{
+    return OTMSetOxmAllowStatus(oxm, allowStatus);
+}
+
 OCStackResult OCDoOwnershipTransfer(void* ctx,
                                       OCProvisionDev_t *targetDevices,
                                       OCProvisionResultCB resultCallback)
index 1bf238f..499ac30 100644 (file)
@@ -60,8 +60,9 @@
 #include "ownershiptransfermanager.h"
 #include "securevirtualresourcetypes.h"
 #include "oxmjustworks.h"
-#ifdef _ENABLE_MULTIPLE_OWNER_
 #include "oxmrandompin.h"
+#include "oxmmanufacturercert.h"
+#ifdef _ENABLE_MULTIPLE_OWNER_
 #include "oxmpreconfpin.h"
 #endif //_ENABLE_MULTIPLE_OWNER_
 #include "otmcontextlist.h"
 #include "pmutility.h"
 #include "srmutility.h"
 #include "provisioningdatabasemanager.h"
-#include "oxmrandompin.h"
 #include "ocpayload.h"
 #include "payload_logging.h"
+#include "pkix_interface.h"
 
 #define TAG "OIC_OTM"
 
+
+#define ALLOWED_OXM         1
+#define NOT_ALLOWED_OXM     0
+
+/**
+ * List of allowed oxm list.
+ * All oxm methods are allowed as default.
+ */
+static uint8_t g_OxmAllowStatus[OIC_OXM_COUNT] = {ALLOWED_OXM, ALLOWED_OXM, ALLOWED_OXM, NOT_ALLOWED_OXM};
+
 /**
  * Variables for pointing the OTMContext to be used in the DTLS handshake result callback.
  */
@@ -108,8 +119,11 @@ OCStackResult OTMSetOTCallback(OicSecOxm_t oxm, OTMCallbackData_t* callbacks)
         callbacks->createOwnerTransferPayloadCB = CreatePinBasedOwnerTransferPayload;
         break;
     case OIC_MANUFACTURER_CERTIFICATE:
-        OIC_LOG(ERROR, TAG, "OIC_MANUFACTURER_CERTIFICATE not supported yet.");
-        return OC_STACK_INVALID_METHOD;
+        callbacks->loadSecretCB = PrepareMCertificateCallback;
+        callbacks->createSecureSessionCB = CreateSecureSessionMCertificateCallback;
+        callbacks->createSelectOxmPayloadCB = CreateMCertificateBasedSelectOxmPayload;
+        callbacks->createOwnerTransferPayloadCB = CreateMCertificateBasedOwnerTransferPayload;
+        break;
     case OIC_DECENTRALIZED_PUBLIC_KEY:
         OIC_LOG(ERROR, TAG, "OIC_DECENTRALIZED_PUBLIC_KEY not supported yet.");
         return OC_STACK_INVALID_METHOD;
@@ -144,6 +158,8 @@ exit:
 static OCStackResult SelectProvisioningMethod(const OicSecOxm_t *supportedMethods,
         size_t numberOfMethods, OicSecOxm_t *selectedMethod)
 {
+    bool isOxmSelected = false;
+
     OIC_LOG(DEBUG, TAG, "IN SelectProvisioningMethod");
 
     if(numberOfMethods == 0 || !supportedMethods)
@@ -152,10 +168,25 @@ static OCStackResult SelectProvisioningMethod(const OicSecOxm_t *supportedMethod
         return OC_STACK_ERROR;
     }
 
-    *selectedMethod  = supportedMethods[0];
     for(size_t i = 0; i < numberOfMethods; i++)
     {
-        if(*selectedMethod < supportedMethods[i])
+        if(ALLOWED_OXM == g_OxmAllowStatus[supportedMethods[i]])
+        {
+            *selectedMethod  = supportedMethods[i];
+            isOxmSelected = true;
+            break;
+        }
+    }
+    if(!isOxmSelected)
+    {
+        OIC_LOG(ERROR, TAG, "Can not find the allowed OxM.");
+        return OC_STACK_NOT_ALLOWED_OXM;
+    }
+
+    for(size_t i = 0; i < numberOfMethods; i++)
+    {
+        if(*selectedMethod < supportedMethods[i] &&
+           ALLOWED_OXM == g_OxmAllowStatus[supportedMethods[i]])
         {
             *selectedMethod =  supportedMethods[i];
         }
@@ -320,6 +351,18 @@ static void SetResult(OTMContext_t* otmCtx, const OCStackResult res)
         OicUuid_t emptyUuid = { .id={0}};
         SetUuidForPinBasedOxm(&emptyUuid);
     }
+    else if(OIC_MANUFACTURER_CERTIFICATE == otmCtx->selectedDeviceInfo->doxm->oxmSel)
+    {
+        //Revert back certificate related callbacks.
+        if(CA_STATUS_OK != CAregisterPkixInfoHandler(GetPkixInfo))
+        {
+            OIC_LOG(WARNING, TAG, "Failed to revert PkixInfoHandler.");
+        }
+        if(CA_STATUS_OK != CAregisterGetCredentialTypesHandler(InitCipherSuiteList))
+        {
+            OIC_LOG(WARNING, TAG, "Failed to revert CredentialTypesHandler.");
+        }
+    }
 
     for(size_t i = 0; i < otmCtx->ctxResultArraySize; i++)
     {
@@ -799,7 +842,6 @@ static OCStackApplicationResult OperationModeUpdateHandler(void *ctx, OCDoHandle
     if  (OC_STACK_RESOURCE_CHANGED == clientResponse->result)
     {
         OCStackResult res = OC_STACK_ERROR;
-        OicSecOxm_t selOxm = otmCtx->selectedDeviceInfo->doxm->oxmSel;
 
         //DTLS Handshake
         //Load secret for temporal secure session.
@@ -1399,7 +1441,6 @@ static OCStackResult PostOwnerTransferModeToResource(OTMContext_t* otmCtx)
     }
 
     OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
-    OicSecOxm_t selectedOxm = deviceInfo->doxm->oxmSel;
     char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
 
     if(!PMGenerateQuery(false,
@@ -1865,6 +1906,23 @@ error:
     return res;
 }
 
+OCStackResult OTMSetOxmAllowStatus(const OicSecOxm_t oxm, const bool allowStatus)
+{
+    OIC_LOG_V(INFO, TAG, "IN %s : oxm=%d, allow status=%s",
+              __func__, oxm, (allowStatus ? "true" : "false"));
+
+    if(OIC_OXM_COUNT <= oxm)
+    {
+        return OC_STACK_INVALID_PARAM;
+    }
+
+    g_OxmAllowStatus[oxm] = (allowStatus ? ALLOWED_OXM : NOT_ALLOWED_OXM);
+
+    OIC_LOG_V(INFO, TAG, "OUT %s", __func__);
+
+    return OC_STACK_OK;
+}
+
 OCStackResult PostProvisioningStatus(OTMContext_t* otmCtx)
 {
     OIC_LOG(INFO, TAG, "IN PostProvisioningStatus");
diff --git a/resource/csdk/security/provisioning/src/oxmmanufacturercert.c b/resource/csdk/security/provisioning/src/oxmmanufacturercert.c
new file mode 100644 (file)
index 0000000..4ba1e86
--- /dev/null
@@ -0,0 +1,143 @@
+/* *****************************************************************
+ *
+ * Copyright 2016 Samsung Electronics All Rights Reserved.
+ *
+ *
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * *****************************************************************/
+
+#include <memory.h>
+
+#include "ocstack.h"
+#include "securevirtualresourcetypes.h"
+#include "doxmresource.h"
+#include "credresource.h"
+#include "cacommon.h"
+#include "cainterface.h"
+#include "casecurityinterface.h"
+#include "ocrandom.h"
+#include "oic_malloc.h"
+#include "logger.h"
+#include "pbkdf2.h"
+#include "global.h"
+#include "base64.h"
+#include "oxmmanufacturercert.h"
+#include "ownershiptransfermanager.h"
+#include "srmresourcestrings.h"
+#include "pkix_interface.h"
+#include "mbedtls/ssl_ciphersuites.h"
+
+#define TAG "OXM_MCertificate"
+
+OCStackResult CreateMCertificateBasedSelectOxmPayload(OTMContext_t* otmCtx, uint8_t **payload, size_t *size)
+{
+    if (!otmCtx || !otmCtx->selectedDeviceInfo || !payload || *payload || !size)
+    {
+        return OC_STACK_INVALID_PARAM;
+    }
+
+    otmCtx->selectedDeviceInfo->doxm->oxmSel = OIC_MANUFACTURER_CERTIFICATE;
+
+    return DoxmToCBORPayload(otmCtx->selectedDeviceInfo->doxm, payload, size, true);
+}
+
+OCStackResult CreateMCertificateBasedOwnerTransferPayload(OTMContext_t* otmCtx, uint8_t **payload, size_t *size)
+{
+    if (!otmCtx || !otmCtx->selectedDeviceInfo || !payload || *payload || !size)
+    {
+        return OC_STACK_INVALID_PARAM;
+    }
+
+    OicUuid_t uuidPT = {.id={0}};
+    *payload = NULL;
+    *size = 0;
+
+    if (OC_STACK_OK != GetDoxmDeviceID(&uuidPT))
+    {
+        OIC_LOG(ERROR, TAG, "Error while retrieving provisioning tool's device ID");
+        return OC_STACK_ERROR;
+    }
+    memcpy(otmCtx->selectedDeviceInfo->doxm->owner.id, uuidPT.id , UUID_LENGTH);
+
+    return DoxmToCBORPayload(otmCtx->selectedDeviceInfo->doxm, payload, size, true);
+}
+
+OCStackResult PrepareMCertificateCallback(OTMContext_t *otmCtx)
+{
+    OIC_LOG(INFO, TAG, "IN PrepareMCertificateCallback");
+
+    if (CA_STATUS_OK != CAregisterPkixInfoHandler(GetManufacturerPkixInfo))
+    {
+        OIC_LOG(ERROR, TAG, "Failed to register PkixInfohandler");
+        return OC_STACK_ERROR;
+    }
+
+    if (CA_STATUS_OK != CAregisterGetCredentialTypesHandler(InitManufacturerCipherSuiteList))
+    {
+        OIC_LOG(ERROR, TAG, "Failed to register CredentialTypesHandler");
+        return OC_STACK_ERROR;
+    }
+
+    OIC_LOG(INFO, TAG, "OUT PrepareMCertificateCallback");
+
+    return OC_STACK_OK;
+}
+
+OCStackResult CreateSecureSessionMCertificateCallback(OTMContext_t* otmCtx)
+{
+    OIC_LOG(INFO, TAG, "IN CreateSecureSessionMCertificateCallback");
+
+    if (!otmCtx || !otmCtx->selectedDeviceInfo)
+    {
+        return OC_STACK_INVALID_PARAM;
+    }
+
+    CAResult_t caresult = CAEnableAnonECDHCipherSuite(false);
+    if (CA_STATUS_OK != caresult)
+    {
+        OIC_LOG_V(ERROR, TAG, "Failed to disable anon cipher suite");
+        return OC_STACK_ERROR;
+    }
+    OIC_LOG(INFO, TAG, "Anonymous cipher suite disabled.");
+
+    caresult  = CASelectCipherSuite(MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8,
+                                    otmCtx->selectedDeviceInfo->endpoint.adapter);
+    if (CA_STATUS_OK != caresult)
+    {
+        OIC_LOG_V(ERROR, TAG, "Failed to select TLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8");
+        return OC_STACK_ERROR;
+    }
+    OIC_LOG(INFO, TAG, "TLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 cipher suite selected.");
+
+    OCProvisionDev_t* selDevInfo = otmCtx->selectedDeviceInfo;
+    CAEndpoint_t *endpoint = (CAEndpoint_t *)OICCalloc(1, sizeof (CAEndpoint_t));
+    if (NULL == endpoint)
+    {
+        return OC_STACK_NO_MEMORY;
+    }
+    memcpy(endpoint,&selDevInfo->endpoint,sizeof(CAEndpoint_t));
+    endpoint->port = selDevInfo->securePort;
+    caresult = CAInitiateHandshake(endpoint);
+    OICFree(endpoint);
+    if (CA_STATUS_OK != caresult)
+    {
+        OIC_LOG_V(ERROR, TAG, "DTLS handshake failure.");
+        return OC_STACK_ERROR;
+    }
+
+    OIC_LOG(INFO, TAG, "OUT CreateSecureSessionMCertificateCallback");
+
+    return OC_STACK_OK;
+}
index 825b401..69c4c67 100644 (file)
@@ -29,6 +29,7 @@
 #include "ocprovisioningmanager.h"
 #include "oxmjustworks.h"
 #include "oxmrandompin.h"
+#include "oxmmanufacturercert.h"
 #include "securevirtualresourcetypes.h"
 #include "provisioningdatabasemanager.h"
 #ifdef _ENABLE_MULTIPLE_OWNER_
@@ -115,6 +116,40 @@ TEST(RandomPinOxMTest, NullParam)
     EXPECT_TRUE(OC_STACK_INVALID_PARAM == res);
 }
 
+TEST(ManufacturerCertOxMTest, NullParam)
+{
+    OTMContext_t* otmCtx = NULL;
+    OCStackResult res = OC_STACK_ERROR;
+    uint8_t *payloadRes = NULL;
+    size_t size = 0;
+
+    res = PrepareMCertificateCallback(otmCtx);
+    EXPECT_TRUE(OC_STACK_INVALID_PARAM == res);
+
+    res = CreateSecureSessionMCertificateCallback(otmCtx);
+    EXPECT_TRUE(OC_STACK_INVALID_PARAM == res);
+
+    res = CreateMCertificateBasedSelectOxmPayload(otmCtx, &payloadRes, &size);
+    EXPECT_TRUE(OC_STACK_INVALID_PARAM == res);
+
+    res = CreateMCertificateBasedOwnerTransferPayload(otmCtx, &payloadRes, &size);
+    EXPECT_TRUE(OC_STACK_INVALID_PARAM == res);
+
+    OTMContext_t otmCtx2;
+    otmCtx2.selectedDeviceInfo = NULL;
+
+    res = InputPinCodeCallback(&otmCtx2);
+    EXPECT_TRUE(OC_STACK_INVALID_PARAM == res);
+
+    res = CreateSecureSessionMCertificateCallback(&otmCtx2);
+    EXPECT_TRUE(OC_STACK_INVALID_PARAM == res);
+
+    res = CreateMCertificateBasedSelectOxmPayload(&otmCtx2, &payloadRes, &size);
+    EXPECT_TRUE(OC_STACK_INVALID_PARAM == res);
+
+    res = CreateMCertificateBasedOwnerTransferPayload(&otmCtx2, &payloadRes, &size);
+    EXPECT_TRUE(OC_STACK_INVALID_PARAM == res);
+}
 
 /****************************************
  * Test the OTM modules with sample server
index 28f9e38..1a42753 100644 (file)
 #include "srmutility.h"
 #include "pinoxmcommon.h"
 
+#if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
+#include "pkix_interface.h"
+#endif
+
 #define TAG  "OIC_SRM_DOXM"
 #define CHAR_ZERO ('0')
 
@@ -1227,6 +1231,30 @@ static OCEntityHandlerResult HandleDoxmPostRequest(const OCEntityHandlerRequest
                     }
 #endif // __WITH_DTLS__ or __WITH_TLS__
                 }
+#if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
+                else if (OIC_MANUFACTURER_CERTIFICATE ==  newDoxm->oxmSel)
+                {
+                    //Save the owner's UUID to derive owner credential
+                    memcpy(&(gDoxm->owner), &(newDoxm->owner), sizeof(OicUuid_t));
+                    gDoxm->oxmSel = newDoxm->oxmSel;
+                    //Update new state in persistent storage
+                    if (UpdatePersistentStorage(gDoxm))
+                    {
+                        ehRet = OC_EH_OK;
+                    }
+                    else
+                    {
+                        OIC_LOG(WARNING, TAG, "Failed to update DOXM in persistent storage");
+                        ehRet = OC_EH_ERROR;
+                    }
+                    CAResult_t caRes = CAEnableAnonECDHCipherSuite(false);
+                    VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
+                    OIC_LOG(INFO, TAG, "ECDH_ANON CipherSuite is DISABLED");
+
+                    VERIFY_SUCCESS(TAG, CA_STATUS_OK == CAregisterPkixInfoHandler(GetManufacturerPkixInfo), ERROR);
+                    VERIFY_SUCCESS(TAG, CA_STATUS_OK == CAregisterGetCredentialTypesHandler(InitManufacturerCipherSuiteList), ERROR);
+                }
+#endif // __WITH_DTLS__ or __WITH_TLS__
             }
 
             /*
@@ -1297,6 +1325,13 @@ static OCEntityHandlerResult HandleDoxmPostRequest(const OCEntityHandlerRequest
                     OIC_LOG(ERROR, TAG, "Failed to update DOXM in persistent storage");
                     ehRet = OC_EH_ERROR;
                 }
+#if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
+                if (OIC_MANUFACTURER_CERTIFICATE == gDoxm->oxmSel)
+                {
+                    CAregisterPkixInfoHandler(GetPkixInfo);
+                    CAregisterGetCredentialTypesHandler(InitCipherSuiteList);
+                }
+#endif // __WITH_DTLS__ or __WITH_TLS__
             }
         }
     }
index 3429ecc..c21c0d7 100644 (file)
@@ -981,6 +981,7 @@ typedef enum
      * This error is pushed from DTLS interface when handshake failure happens
      */
     OC_STACK_AUTHENTICATION_FAILURE,
+    OC_STACK_NOT_ALLOWED_OXM,
 
     /** Insert all new error codes here!.*/
 #ifdef WITH_PRESENCE
index b0a111f..4f856c2 100644 (file)
@@ -124,6 +124,7 @@ namespace OC
         static const char DUPLICATE_UUID[]             = "Duplicate UUID in DB";
         static const char INCONSISTENT_DB[]            = "Data in provisioning DB is inconsistent";
         static const char AUTHENTICATION_FAILURE[]     = "Authentication failure";
+        static const char NOT_ALLOWED_OXM[]            = "Not allowed ownership transfer method";
         static const char PUBLISH_RESOURCE_FAILED[]    = "Publish Resource failure";
         static const char FORBIDDEN_REQ[]              = "Forbidden request";
         static const char INTERNAL_SERVER_ERROR[]      = "Internal server error";
index a8d2d5d..6f2f6b6 100644 (file)
@@ -109,6 +109,8 @@ std::string OC::OCException::reason(const OCStackResult sr)
             return OC::Exception::INCONSISTENT_DB;
         case OC_STACK_AUTHENTICATION_FAILURE:
             return OC::Exception::AUTHENTICATION_FAILURE;
+        case OC_STACK_NOT_ALLOWED_OXM:
+            return OC::Exception::NOT_ALLOWED_OXM;
         case OC_STACK_FORBIDDEN_REQ:
             return OC::Exception::FORBIDDEN_REQ;
         case OC_STACK_INTERNAL_SERVER_ERROR:
index f3fe50e..3c4fcf0 100644 (file)
@@ -74,6 +74,7 @@ namespace OC
                 OC_STACK_DUPLICATE_UUID,
                 OC_STACK_INCONSISTENT_DB,
                 OC_STACK_AUTHENTICATION_FAILURE,
+                OC_STACK_NOT_ALLOWED_OXM,
                 OC_STACK_FORBIDDEN_REQ,
                 OC_STACK_INTERNAL_SERVER_ERROR
             };
@@ -121,6 +122,7 @@ namespace OC
                 OC::Exception::DUPLICATE_UUID,
                 OC::Exception::INCONSISTENT_DB,
                 OC::Exception::AUTHENTICATION_FAILURE,
+                OC::Exception::NOT_ALLOWED_OXM,
                 OC::Exception::FORBIDDEN_REQ,
                 OC::Exception::INTERNAL_SERVER_ERROR
             };