--- /dev/null
+//******************************************************************
+//
+// Copyright 2015 Intel Mobile Communications GmbH 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 <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <signal.h>
+#include <pthread.h>
+#include <iostream>
+#include <sstream>
+#include "ocstack.h"
+#include "logger.h"
+#include "cJSON.h"
+#include "global.h"
+#include "cainterface.h"
+#include "cacommon.h"
+#include "ocstackinternal.h"
+#include "payload_logging.h"
+#include "ocpayload.h"
+
+
+#define TAG "DEMO"
+#define DEFAULT_CONTEXT_VALUE 0x99
+#define STATE "state"
+#define OPEN_DURATION "openDuration"
+#define OPEN_ALARM "openAlarm"
+
+static const char MULTICAST_DISCOVERY_QUERY[] = "/oic/res";
+
+volatile sig_atomic_t gQuitFlag = 0;
+OCPersistentStorage ps = {0, 0, 0, 0, 0};
+static const char *gResourceUri = "/a/door";
+uint8_t lightIpAddr[4] = {};
+uint16_t lightPortNu;
+static bool isUpdated = false;
+static std::string coapServerIP;
+static std::string coapServerPort;
+static std::string coapServerResource;
+static OCConnectivityType ocConnType;
+
+static std::string address;
+
+static int coapSecureResource;
+
+static const char CRED_FILE[] = "oic_svr_db_door.json";
+
+CAEndpoint_t endpoint = {CA_DEFAULT_ADAPTER, CA_DEFAULT_FLAGS, 0, {0}, 0};
+
+// myDoorState_t variable to store resource's state .
+typedef enum
+{
+ STATE_OPEN, /**< State is opened */
+ STATE_CLOSED /**< State is closed*/
+} myDoorState_t;
+
+//Structure to represent a door resource and its attributes
+typedef struct DOORRESOURCE
+{
+ OCResourceHandle handle;
+ myDoorState_t state; //ReadOnly, The state of the door (open or closed)"
+ char *openDuration; //ReadOnly, The time duration the door has been open
+ bool openAlarm ; //The state of the door open alarm
+
+} DoorResource;
+
+static DoorResource Door;
+
+int parseClientResponse(OCClientResponse * clientResponse)
+{
+ if(!clientResponse)
+ {
+ return 0;
+ }
+
+ OCResourcePayload* res = ((OCDiscoveryPayload*)clientResponse->payload)->resources;
+
+ // Initialize all global variables
+ coapServerResource.clear();
+ coapSecureResource = 0;
+
+ while (res)
+ {
+ coapServerResource.assign(res->uri);
+ OC_LOG_V(INFO, TAG, "Uri -- %s", coapServerResource.c_str());
+
+ if (res->secure)
+ {
+ endpoint.port = res->port;
+ coapSecureResource = 1;
+ }
+
+ OC_LOG_V(INFO, TAG, "Secure -- %s", coapSecureResource == 1 ? "YES" : "NO");
+
+ // If we discovered a secure resource, exit from here
+ if (coapSecureResource)
+ {
+ break;
+ }
+
+ res = res->next;
+ }
+
+ return 0;
+}
+
+OCRepPayload* getPayload(const char* uri, int64_t state, char* openDuration, bool openAlarm)
+{
+ OCRepPayload* payload = OCRepPayloadCreate();
+ if (!payload)
+ {
+ OC_LOG(ERROR, TAG, PCF("Failed to allocate Payload"));
+ return nullptr;
+ }
+
+ OCRepPayloadSetUri(payload, uri);
+ OCRepPayloadSetPropInt(payload, STATE, state);
+ OCRepPayloadSetPropString(payload, OPEN_DURATION, openDuration);
+ OCRepPayloadSetPropBool(payload, OPEN_ALARM, openAlarm);
+
+ 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)
+ {
+ OC_LOG(ERROR, TAG, PCF("Incoming payload not a representation"));
+ return nullptr;
+ }
+
+ DoorResource *currdoorResource = &Door;
+
+ return getPayload(gResourceUri, currdoorResource->state, currdoorResource->openDuration, currdoorResource->openAlarm);
+}
+
+OCEntityHandlerResult ProcessGetRequest(OCEntityHandlerRequest *ehRequest,
+ OCRepPayload **payload)
+{
+ OCEntityHandlerResult ehResult = OC_EH_ERROR;
+
+ OCRepPayload *getResp = constructResponse(ehRequest);
+
+ if(getResp)
+ {
+ *payload = getResp;
+ ehResult = OC_EH_OK;
+ }
+
+ return ehResult;
+}
+
+OCEntityHandlerResult OCEntityHandlerCb(OCEntityHandlerFlag flag,
+ OCEntityHandlerRequest *entityHandlerRequest,
+ void* /*callbackParam*/)
+{
+ OC_LOG_V (INFO, TAG, "Inside entity handler - flags: 0x%x", flag);
+
+ OCEntityHandlerResult ehResult = OC_EH_ERROR;
+ OCEntityHandlerResponse response;
+
+ // Validate pointer
+ if (!entityHandlerRequest)
+ {
+ OC_LOG (ERROR, TAG, "Invalid request pointer");
+ return OC_EH_ERROR;
+ }
+
+ OCRepPayload* payload = nullptr;
+
+ if (flag & OC_REQUEST_FLAG)
+ {
+ OC_LOG (INFO, TAG, "Flag includes OC_REQUEST_FLAG");
+
+ if (entityHandlerRequest)
+ {
+ switch(entityHandlerRequest->method)
+ {
+ case OC_REST_GET:
+ {
+ OC_LOG (INFO, TAG, "Received OC_REST_GET from client");
+ ehResult = ProcessGetRequest (entityHandlerRequest, &payload);
+ }
+ break;
+ default:
+ {
+ OC_LOG_V (INFO, TAG, "Received unsupported method %d from client",
+ entityHandlerRequest->method);
+ ehResult = OC_EH_ERROR;
+ }
+ break;
+ }
+
+ 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 = reinterpret_cast<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)
+ {
+ OC_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)
+{
+ return fopen(CRED_FILE, mode);
+}
+
+void SetPersistentHandler(OCPersistentStorage *ps)
+{
+ if (ps)
+ {
+ ps->open = server_fopen;
+ ps->read = fread;
+ ps->write = fwrite;
+ ps->close = fclose;
+ ps->unlink = unlink;
+
+ OCRegisterPersistentStorageHandler(ps);
+ }
+}
+
+/**
+ * GetResult is returned result to string.
+ * @param result [IN] stack result
+ * @return converted OCStackResult as string for debugging
+ */
+static 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";
+ case OC_STACK_UNAUTHORIZED_REQ:
+ return "OC_STACK_UNAUTHORIZED_REQ";
+ #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";
+ }
+}
+
+
+/**
+ * CreateDoorResource creates a new door resource by calling the OCCreateResource() method.
+ * @param uri [IN] uri
+ * @param doorResource [IN] info of resource
+ * @return ::OC_STACK_OK on success, some other value upon failure.
+ */
+int createDoorResource (const char *uri, DoorResource *doorResource)
+{
+ if (!uri)
+ {
+ OC_LOG(ERROR, TAG, "Resource URI cannot be NULL");
+
+ }
+
+ doorResource->state = STATE_CLOSED; //1:closed , 0: open
+ char str[] = "10min";
+ doorResource->openDuration = str;
+ doorResource->openAlarm = false;
+ OCStackResult res = OCCreateResource(&(doorResource->handle),
+ "core.door",
+ OC_RSRVD_INTERFACE_DEFAULT,
+ uri,
+ OCEntityHandlerCb,
+ NULL,
+ OC_DISCOVERABLE | OC_OBSERVABLE | OC_SECURE);
+
+ OC_LOG_V(INFO, TAG, "Created Door resource with result: %s", getResult(res));
+ return 0;
+}
+
+OCStackApplicationResult putReqCB(void * ctx, OCDoHandle /*handle*/, OCClientResponse *clientResponse)
+{
+ if (ctx == (void *)DEFAULT_CONTEXT_VALUE)
+ {
+ OC_LOG(INFO, TAG, "Callback Context for PUT recvd successfully");
+ }
+
+ if (clientResponse)
+ {
+ OC_LOG_V(INFO, TAG, "StackResult: %s", getResult(clientResponse->result));
+ OC_LOG_V(INFO, TAG, "SEQUENCE NUMBER: %d", clientResponse->sequenceNumber);
+ OC_LOG_PAYLOAD(INFO, TAG, clientResponse->payload);
+ if ((OCSecurityPayload*)clientResponse->payload)
+ {
+ OC_LOG_V(INFO, TAG, "=============> Put Response",
+ ((OCSecurityPayload*)clientResponse->payload)->securityData);
+ }
+ }
+ return OC_STACK_DELETE_TRANSACTION;
+}
+
+OCStackApplicationResult getReqCB(void * /*ctx*/, OCDoHandle /*handle*/, OCClientResponse *clientResponse)
+{
+ OC_LOG(INFO, TAG, "Callback Context for GET query recvd successfully");
+
+ if (clientResponse)
+ {
+ OC_LOG_V(INFO, TAG, "StackResult: %s", getResult(clientResponse->result));
+ OC_LOG_V(INFO, TAG, "SEQUENCE NUMBER: %d", clientResponse->sequenceNumber);
+ OC_LOG_PAYLOAD(INFO, TAG, clientResponse->payload);
+ if ((OCSecurityPayload*)clientResponse->payload)
+ {
+ OC_LOG(INFO, TAG, PCF("=============> Get Response"));
+ }
+ }
+ return OC_STACK_DELETE_TRANSACTION;
+}
+
+// This is a function called back when a device is discovered
+OCStackApplicationResult discoveryReqCB(void* /*ctx*/, OCDoHandle /*handle*/,
+ OCClientResponse * clientResponse)
+{
+ OC_LOG(INFO, TAG, "Callback Context for DISCOVER query recvd successfully");
+
+ if (clientResponse)
+ {
+ OC_LOG_V(INFO, TAG, "StackResult: %s", getResult(clientResponse->result));
+ OC_LOG_V(INFO, TAG,
+ "Device =============> Discovered @ %s:%d",
+ clientResponse->devAddr.addr,
+ clientResponse->devAddr.port);
+
+ if (clientResponse->result == OC_STACK_OK)
+ {
+ OC_LOG_PAYLOAD(INFO, TAG, clientResponse->payload);
+ ocConnType = clientResponse->connType;
+ parseClientResponse(clientResponse);
+ }
+ }
+
+ return OC_STACK_KEEP_TRANSACTION;
+
+}
+
+
+
+void initAddress()
+{
+ static bool initFlag = false;
+ if (!initFlag)
+ {
+ OC_LOG(INFO, TAG, "Enter IP address (with optional port) of the Server hosting resource\n");
+ OC_LOG(INFO, TAG, "IPv4: 192.168.0.15:45454\n");
+ OC_LOG(INFO, TAG, "IPv6: [fe80::20c:29ff:fe1b:9c5]:45454\n");
+
+ std::cin >> address;
+ }
+ initFlag = true;
+}
+
+// Local function to send get request of light resource
+void SendGetRequest()
+{
+ OCStackResult ret;
+ OC_LOG(INFO, TAG, "Send Get REQ to Light server");
+
+ initAddress();
+
+ char szQueryUri[64] = { '\0'};
+ OCDoHandle handle;
+ OCCallbackData cbData;
+ cbData.cb = getReqCB;
+ cbData.context = (void *)DEFAULT_CONTEXT_VALUE;
+ cbData.cd = NULL;
+ OC_LOG_V(INFO, TAG, "Get payload from Door sample = /a/light ");
+ snprintf(szQueryUri, sizeof(szQueryUri), "coaps://%s/a/light", const_cast<char*> (address.c_str())); // lightPortNu);
+ ret = OCDoResource(&handle, OC_REST_GET, szQueryUri, 0, NULL, ocConnType, OC_LOW_QOS,
+ &cbData, NULL, 0);
+ if (ret != OC_STACK_OK)
+ {
+ OC_LOG(ERROR, TAG, "OCStack resource error");
+ }
+}
+
+
+void *input_function(void * /*data*/)
+{
+ char input;
+ char szQueryUri[64] = { 0 };
+ OCDoHandle handle;
+ OCCallbackData cbData;
+ cbData.cb = discoveryReqCB;
+ cbData.context = (void *)DEFAULT_CONTEXT_VALUE;
+ cbData.cd = NULL;
+
+ strcpy(szQueryUri, MULTICAST_DISCOVERY_QUERY);
+
+ while (1)
+ {
+ std::cin >> input;
+ switch (input)
+ {
+ case 'D':
+ case 'd':
+ if (isUpdated == false)
+ {
+ OC_LOG(INFO, TAG, "isUpdated is false...");
+ OCDoResource(&handle, OC_REST_DISCOVER, szQueryUri, 0, 0, CT_DEFAULT, OC_LOW_QOS, &cbData, NULL, 0);
+
+ }
+ break;
+ case 'G':
+ case 'g':
+ isUpdated = true;
+ if (isUpdated == true)
+ {
+ OC_LOG(INFO, TAG, "isUpdated is true...");
+ SendGetRequest();
+ }
+ break;
+ case 'Q':
+ case 'q':
+ gQuitFlag = 1;
+ return 0;
+ default: break;
+ }
+ }
+ return 0;
+}
+
+static void PrintUsage()
+{
+ OC_LOG(INFO, TAG, "*******************************************");
+ OC_LOG(INFO, TAG, "Input D or d to discover Resources");
+ OC_LOG(INFO, TAG, "Input G or g to initiate Get Request");
+ OC_LOG(INFO, TAG, "Input Q or q to exit");
+ OC_LOG(INFO, TAG, "*******************************************");
+}
+
+int main()
+{
+
+ OC_LOG(INFO, TAG, "OCServer is starting...");
+ SetPersistentHandler(&ps);
+ //PrintUsage();
+ if (OCInit(NULL, 0, OC_SERVER) != OC_STACK_OK)
+ {
+ OC_LOG(ERROR, TAG, "OCStack init error");
+ return 0;
+ }
+
+ /*
+ * Declare and create the example resource: Door
+ */
+ createDoorResource(gResourceUri, &Door);
+ PrintUsage();
+
+ //select ciphersuite for certificates
+ CASelectCipherSuite(TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8);
+
+ struct timespec timeout;
+ timeout.tv_sec = 0;
+ timeout.tv_nsec = 100000000L;
+
+ // Break from loop with Ctrl-C
+ OC_LOG(INFO, TAG, "Entering ocserver main loop...");
+ signal(SIGINT, handleSigInt);
+ int thr_id;
+ pthread_t p_thread;
+ thr_id = pthread_create(&p_thread, NULL, input_function, (void *)NULL);
+ if (thr_id < 0)
+ {
+ OC_LOG(ERROR, TAG, "create thread error");
+ return 0;
+ }
+
+ while (!gQuitFlag)
+ {
+
+ if (OCProcess() != OC_STACK_OK)
+ {
+ OC_LOG(ERROR, TAG, "OCStack process error");
+ return 0;
+ }
+
+
+ nanosleep(&timeout, NULL);
+ }
+
+ pthread_join(p_thread, NULL);
+
+ OC_LOG(INFO, TAG, "Exiting ocserver main loop...");
+
+ if (OCStop() != OC_STACK_OK)
+ {
+ OC_LOG(ERROR, TAG, "OCStack process error");
+ }
+
+ return 0;
+}
--- /dev/null
+{
+ "acl": [
+ {
+ "sub": "Kg==",
+ "rsrc": [
+ "/oic/res",
+ "/oic/res/d",
+ "/oic/res/types/d",
+ "/oic/presence"
+ ],
+ "perms": 2,
+ "ownrs" : [
+ "ZG9vckRldmljZVVVSUQwMA=="
+ ]
+ },
+ {
+ "sub": "Kg==",
+ "rsrc": [
+ "/oic/sec/doxm",
+ "/oic/sec/pstat",
+ "/oic/sec/acl",
+ "/oic/sec/crl",
+ "/oic/sec/cred"
+ ],
+ "perms": 6,
+ "ownrs" : [
+ "ZG9vckRldmljZVVVSUQwMA=="
+ ]
+ }
+ ],
+ "pstat": {
+ "isop": false,
+ "deviceid": "ZG9vckRldmljZVVVSUQwMA==",
+ "commithash": 0,
+ "cm": 0,
+ "tm": 0,
+ "om": 3,
+ "sm": [3]
+ },
+ "doxm": {
+ "oxm": [0],
+ "oxmsel": 0,
+ "owned": false,
+ "deviceid": "ZG9vckRldmljZVVVSUQwMA=="
+ }
+}
--- /dev/null
+//******************************************************************
+//
+// Copyright 2015 Intel Mobile Communications GmbH 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 <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <signal.h>
+#include <iostream>
+#include <pthread.h>
+#include "ocstack.h"
+#include "logger.h"
+#include "cJSON.h"
+#include "global.h"
+#include "cainterface.h"
+#include "cacommon.h"
+#include "ocpayload.h"
+
+#define TAG "DEMO"
+
+volatile sig_atomic_t gQuitFlag = 0;
+OCPersistentStorage ps = {0, 0, 0, 0, 0};
+const char *gResourceUri = (char *)"/a/light";
+
+//Secure Virtual Resource database for Iotivity Server
+//It contains Server's Identity and the PSK credentials
+//of other devices which the server trusts
+static char CRED_FILE[] = "oic_svr_db_light.json";
+
+
+//Structure to represent a light resource and its attributes
+typedef struct LIGHTRESOURCE
+{
+ OCResourceHandle handle;
+ //Attributes
+ int brightness; // 0-100
+} LightResource;
+
+// Structure to represent a light resource and its attributes
+static LightResource Light;
+
+OCRepPayload* getPayload(const char* uri, int64_t brightness)
+{
+ OCRepPayload* payload = OCRepPayloadCreate();
+ if(!payload)
+ {
+ OC_LOG(ERROR, TAG, PCF("Failed to allocate Payload"));
+ return nullptr;
+ }
+
+ OCRepPayloadSetUri(payload, uri);
+ OCRepPayloadSetPropInt(payload, "brightness", brightness);
+
+ return payload;
+}
+
+//This function takes the request as an input and returns the response
+OCRepPayload* constructResponse(OCEntityHandlerRequest *ehRequest)
+{
+ if(!ehRequest)
+ {
+ return nullptr;
+ }
+
+ if(ehRequest->payload && ehRequest->payload->type != PAYLOAD_TYPE_REPRESENTATION)
+ {
+ OC_LOG(ERROR, TAG, PCF("Incoming payload not a representation"));
+ return nullptr;
+ }
+
+ return getPayload(gResourceUri, Light.brightness);
+}
+
+OCEntityHandlerResult ProcessGetRequest (OCEntityHandlerRequest *ehRequest,
+ OCRepPayload **payload)
+{
+ OCEntityHandlerResult ehResult = OC_EH_ERROR;
+
+ OCRepPayload *getResp = constructResponse(ehRequest);
+
+ if(getResp && payload)
+ {
+ *payload = getResp;
+ ehResult = OC_EH_OK;
+ }
+
+ return ehResult;
+}
+
+
+OCEntityHandlerResult OCEntityHandlerCb (OCEntityHandlerFlag flag,
+ OCEntityHandlerRequest *entityHandlerRequest,
+ void* /*callbackParam*/)
+{
+ OC_LOG_V (INFO, TAG, "Inside entity handler - flags: 0x%x", flag);
+
+ OCEntityHandlerResult ehResult = OC_EH_ERROR;
+ OCEntityHandlerResponse response;
+
+ // Validate pointer
+ if (!entityHandlerRequest)
+ {
+ OC_LOG (ERROR, TAG, "Invalid request pointer");
+ return OC_EH_ERROR;
+ }
+
+ OCRepPayload* payload = nullptr;
+
+ if (flag & OC_REQUEST_FLAG)
+ {
+ OC_LOG (INFO, TAG, "Flag includes OC_REQUEST_FLAG");
+ if (entityHandlerRequest)
+ {
+ switch(entityHandlerRequest->method)
+ {
+ case OC_REST_GET:
+ {
+ OC_LOG (INFO, TAG, "Received OC_REST_GET from client");
+ ehResult = ProcessGetRequest (entityHandlerRequest, &payload);
+ }
+ break;
+ default:
+ {
+ OC_LOG_V (INFO, TAG, "Received unsupported method %d from client",
+ entityHandlerRequest->method);
+ ehResult = OC_EH_ERROR;
+ }
+ break;
+ }
+
+ 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 = reinterpret_cast<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)
+ {
+ OC_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)
+{
+ return fopen(CRED_FILE, mode);
+}
+
+void SetPersistentHandler(OCPersistentStorage *ps)
+
+{
+
+ if (ps)
+
+ {
+
+ ps->open = server_fopen;
+
+ ps->read = fread;
+
+ ps->write = fwrite;
+
+ ps->close = fclose;
+
+ ps->unlink = unlink;
+
+
+ OCRegisterPersistentStorageHandler(ps);
+
+ }
+
+}
+/**
+ * GetResult is returned result to string.
+ * @param result [IN] stack result
+ * @return converted OCStackResult as string for debugging
+ */
+static 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";
+ case OC_STACK_ERROR:
+ return "OC_STACK_ERROR";
+ default:
+ return "UNKNOWN";
+ }
+}
+
+/**
+ * CreateLightResource creates a new light resource by calling the OCCreateResource() method.
+ * @param uri [IN] uri
+ * @param lightResource [IN] info of resource
+ * @return ::OC_STACK_OK on success, some other value upon failure.
+ */
+int createLightResource (const char *uri, LightResource *lightResource)
+{
+ if (!uri)
+ {
+ OC_LOG(ERROR, TAG, "Resource URI cannot be NULL");
+
+ }
+
+ lightResource->brightness = 0;
+ OCStackResult res = OCCreateResource(&(lightResource->handle),
+ "core.light",
+ OC_RSRVD_INTERFACE_DEFAULT,
+ uri,
+ OCEntityHandlerCb,
+ NULL,
+ OC_DISCOVERABLE|OC_OBSERVABLE | OC_SECURE);
+
+ OC_LOG_V(INFO, TAG, "Created Light resource with result: %s", getResult(res));
+ return 0;
+}
+
+
+int main()
+{
+ OC_LOG(DEBUG, TAG, "OCServer is starting...");
+ SetPersistentHandler(&ps);
+ if (OCInit(NULL, 0, OC_SERVER) != OC_STACK_OK)
+ {
+ OC_LOG(ERROR, TAG, "OCStack init error");
+ return 0;
+ }
+
+ /*
+ * Declare and create the example resource: Light
+ */
+ createLightResource(gResourceUri, &Light);
+
+ CASelectCipherSuite(TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8);
+
+ struct timespec timeout;
+ timeout.tv_sec = 0;
+ timeout.tv_nsec = 100000000L;
+
+ // Break from loop with Ctrl-C
+ OC_LOG(INFO, TAG, "Entering ocserver main loop...");
+ signal(SIGINT, handleSigInt);
+ while (!gQuitFlag)
+ {
+ if (OCProcess() != OC_STACK_OK)
+ {
+ OC_LOG(ERROR, TAG, "OCStack process error");
+ return 0;
+ }
+
+ nanosleep(&timeout, NULL);
+ }
+
+ OC_LOG(INFO, TAG, "Exiting ocserver main loop...");
+
+ if (OCStop() != OC_STACK_OK)
+ {
+ OC_LOG(ERROR, TAG, "OCStack process error");
+ }
+
+ return 0;
+}
--- /dev/null
+{
+ "acl": [
+ {
+ "sub": "Kg==",
+ "rsrc": [
+ "/oic/res",
+ "/oic/res/d",
+ "/oic/res/types/d",
+ "/oic/presence"
+ ],
+ "perms": 2,
+ "ownrs" : [
+ "bGlnaHREZXZpY2VVVUlEMA=="
+ ]
+ },
+ {
+ "sub": "Kg==",
+ "rsrc": [
+ "/oic/sec/doxm",
+ "/oic/sec/pstat",
+ "/oic/sec/acl",
+ "/oic/sec/crl",
+ "/oic/sec/cred"
+ ],
+ "perms": 6,
+ "ownrs" : [
+ "bGlnaHREZXZpY2VVVUlEMA=="
+ ]
+ }
+ ],
+ "pstat": {
+ "isop": false,
+ "deviceid": "bGlnaHREZXZpY2VVVUlEMA==",
+ "commithash": 0,
+ "cm": 0,
+ "tm": 0,
+ "om": 3,
+ "sm": [3]
+ },
+ "doxm": {
+ "oxm": [0],
+ "oxmsel": 0,
+ "owned": false,
+ "deviceid": "bGlnaHREZXZpY2VVVUlEMA=="
+ }
+}
--- /dev/null
+# Open three terminal windows in linux
+# The first one use for start Light server
+# Note: Here and below $PROJ_DIR is root directory of iotivity project (e.g /path/to/iotivity)
+$ cd $PROJ_DIR/out/linux/x86_64/release/resource/csdk/security/provisioning/ck_manager/sample/Light_Resource
+$ cp $PROJ_DIR/resource/csdk/security/provisioning/ck_manager/sample/Light_Resource/*.json ./
+$ ./Light_server
+
+# Second terminal window use for start Door server
+$ cp $PROJ_DIR/resource/csdk/security/provisioning/ck_manager/sample/Door_Resource/*.json ./
+$ ./Door_server
+
+# And third terminal window use for start provisioning_client
+# provisioning_client ask for input ACL data:
+# 1. Controller device. Enter ID of the doorDeviceUUID00
+# 2. Controlee device. Enter ID of the lightDeviceUUID0
+# 3. Subject : doorDeviceUUID00
+# 4. Num. of Resource : 1
+# 5. [1]Resource : /a/light
+# 6. permissions: CRUDN
+# 7. Num. of Rowner : 1
+# 8. [1]Rowner : lightDeviceUUID0
+#
+# After successfull sending acl provisioning_client will ask you for CRL data:
+# 1. Enter number of revoced certificates(1..9): 1
+# 2. Revoced certificate 0: Serial number (E. g.: 100): 3
+# And then you should see message about successfull sending CRL
+#
+# Note: provisioning_client send ACL and CRL only to Light sever
+
+$ cd $PROJ_DIR/out/linux/x86_64/release/resource/csdk/security/provisioning/ck_manager/sample
+$ rm ckminfo.dat
+$ cp $PROJ_DIR/resource/csdk/security/provisioning/ck_manager/sample/oic_svr_db_pt.json ./
+$ ./provisioningclient
+Provisioning device ID : doorDeviceUUID00
+Provisioning Success~!!
+Provisioning device ID : lightDeviceUUID0
+Provisioning Success~!!
+Sending credential is succeed~!!
+******************************************************************************
+-Set ACL policy for target device
+******************************************************************************
+-URN identifying the subject
+ex) doorDeviceUUID00 (16 Numbers except to '-')
+Subject : doorDeviceUUID00
+Num. of Resource : 1
+-URI of resource
+ex) /a/light (Max_URI_Length: 64 Byte )
+[1]Resource : /a/light
+-Set the permission(C,R,U,D,N)
+ex) CRUDN, CRU_N,..(5 Charaters)
+Permission : CRUDN
+Num. of Rowner : 1
+-URN identifying the rowner
+ex) lightDeviceUUID0 (16 Numbers except to '-')
+[1]Rowner : lightDeviceUUID0
+Sending ACL is succeed~!!
+Enter number of revoced certificates (1..9)
+1
+Revoked certificate 0:
+Serial number (E. g.: 100):
+2
+Sending CRL is succeed~!!
+
+# Change window to terminal where Door server is running
+# Enter 'd' for discovery. You should see output like this:
+21:56.283 INFO: DEMO: isUpdated is false...
+21:56.495 INFO: DEMO: Callback Context for DISCOVER query recvd successfully
+21:56.495 INFO: DEMO: StackResult: OC_STACK_OK
+21:56.495 INFO: DEMO: Device =============> Discovered @ 10.0.2.15:37942
+21:56.495 INFO: DEMO: Payload Type: Discovery
+21:56.495 INFO: DEMO: Resource #1
+21:56.495 INFO: DEMO: URI:/a/light
+21:56.495 INFO: DEMO: SID:
+21:56.495 INFO: DEMO: F0 5A 6C 8B 59 66 48 89 BE 1E 4E EF FA 23 4E FD
+21:56.495 INFO: DEMO: Resource Types:
+21:56.495 INFO: DEMO: core.light
+21:56.495 INFO: DEMO: Interfaces:
+21:56.495 INFO: DEMO: oic.if.baseline
+21:56.495 INFO: DEMO: Bitmap: 3
+21:56.495 INFO: DEMO: Secure?: true
+21:56.495 INFO: DEMO: Port: 43910
+21:56.495 INFO: DEMO:
+21:56.495 INFO: DEMO: Uri -- /a/light
+21:56.495 INFO: DEMO: Secure -- YES
+21:56.591 INFO: DEMO: Callback Context for DISCOVER query recvd successfully
+21:56.591 INFO: DEMO: StackResult: OC_STACK_OK
+21:56.591 INFO: DEMO: Device =============> Discovered @ 10.0.2.15:55808
+21:56.591 INFO: DEMO: Payload Type: Discovery
+21:56.591 INFO: DEMO: Resource #1
+21:56.591 INFO: DEMO: URI:/a/door
+21:56.591 INFO: DEMO: SID:
+21:56.591 INFO: DEMO: E9 68 45 ED 5D E1 4A F3 86 31 FD 0E 5E 25 EB B3
+21:56.591 INFO: DEMO: Resource Types:
+21:56.591 INFO: DEMO: core.door
+21:56.591 INFO: DEMO: Interfaces:
+21:56.591 INFO: DEMO: oic.if.baseline
+21:56.591 INFO: DEMO: Bitmap: 3
+21:56.591 INFO: DEMO: Secure?: true
+21:56.591 INFO: DEMO: Port: 41403
+21:56.591 INFO: DEMO:
+21:56.591 INFO: DEMO: Uri -- /a/door
+21:56.591 INFO: DEMO: Secure -- YES
+
+# If you can see /a/light discowered then this is success.
+# Next you should enter g to start get request
+# Enter address : 10.0.2.15:43910
+# Port you can find here
+21:56.495 INFO: DEMO: URI:/a/light
+21:56.495 INFO: DEMO: SID:
+21:56.495 INFO: DEMO: F0 5A 6C 8B 59 66 48 89 BE 1E 4E EF FA 23 4E FD
+21:56.495 INFO: DEMO: Resource Types:
+21:56.495 INFO: DEMO: core.light
+21:56.495 INFO: DEMO: Interfaces:
+21:56.495 INFO: DEMO: oic.if.baseline
+21:56.495 INFO: DEMO: Bitmap: 3
+21:56.495 INFO: DEMO: Secure?: true
+21:56.495 INFO: DEMO: Port: 43910
+
+# If you see this lines in output:
+22:31.647 INFO: DEMO: Callback Context for GET query recvd successfully
+22:31.647 INFO: DEMO: StackResult: OC_STACK_OK
+22:31.647 INFO: DEMO: SEQUENCE NUMBER: 2
+22:31.647 INFO: DEMO: Payload Type: Representation
+22:31.647 INFO: DEMO: Resource #1
+22:31.647 INFO: DEMO: URI:/a/light
+22:31.647 INFO: DEMO: Resource Types:
+22:31.647 INFO: DEMO: Interfaces:
+22:31.647 INFO: DEMO: Values:
+22:31.647 INFO: DEMO: brightness(int):0
+22:31.647 INFO: DEMO: =============> Get Response
+# then certificate did not rejected with CRL
+# if not then it did.
--- /dev/null
+{
+ "acl": [
+ {
+ "sub": "Kg==",
+ "rsrc": [
+ "/oic/res",
+ "/oic/d",
+ "/oic/p",
+ "/oic/res/types/d",
+ "/oic/ad"
+ ],
+ "perms": 2,
+ "ownrs" : ["YWRtaW5EZXZpY2VVVUlEMA=="]
+ },
+ {
+ "sub": "Kg==",
+ "rsrc": [
+ "/oic/sec/doxm",
+ "/oic/sec/pstat",
+ "/oic/sec/acl",
+ "/oic/sec/cred"
+ ],
+ "perms": 7,
+ "ownrs" : ["YWRtaW5EZXZpY2VVVUlEMA=="]
+ }
+ ],
+ "pstat": {
+ "isop": true,
+ "deviceid": "YWRtaW5EZXZpY2VVVUlEMA==",
+ "ch": 0,
+ "cm": 0,
+ "tm": 0,
+ "om": 3,
+ "sm": [3]
+ },
+ "doxm": {
+ "oxm": [0],
+ "oxmsel": 0,
+ "owned": true,
+ "deviceid": "YWRtaW5EZXZpY2VVVUlEMA==",
+ "ownr": "YWRtaW5EZXZpY2VVVUlEMA=="
+ }
+}
--- /dev/null
+/******************************************************************
+*
+* Copyright 2015 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 <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "logger.h"
+#include "oic_malloc.h"
+#include "utlist.h"
+#include "ocprovisioningmanager.h"
+#include "secureresourceprovider.h"
+#include "oxmjustworks.h"
+#include "oic_string.h"
+#include "securevirtualresourcetypes.h"
+#include "cacommon.h"
+#include "ck_manager.h"
+#include "ckm_info.h"
+#include "crlresource.h"
+
+#define MAX_URI_LENGTH (64)
+#define MAX_PERMISSION_LENGTH (5)
+#define CREATE (1)
+#define READ (2)
+#define UPDATE (4)
+#define DELETE (8)
+#define NOTIFY (16)
+#define DASH '-'
+#define PREDEFINED_TIMEOUT (10)
+#define MAX_OWNED_DEVICE (10)
+#define DATE_LENGTH (14)
+#define TAG "provisioningclient"
+
+static OicSecAcl_t *gAcl = NULL;
+static OicSecCrl_t *gCrl = NULL;
+static char PROV_TOOL_DB_FILE[] = "oic_svr_db_pt.json";
+static int gOwnershipState = 0;
+
+typedef enum
+{
+ ownershipDone = 1 << 1,
+ finalizeDone = 1 << 2,
+ provisionAclDone = 1 << 3,
+ provisionCert1Done = 1 << 4,
+ provisionCert2Done = 1 << 5,
+ provisionCrlDone = 1 << 6
+} StateManager;
+
+
+/**
+ * Perform cleanup for ACL
+ * @param[in] ACL
+ */
+static void deleteACL(OicSecAcl_t *acl)
+{
+ if (acl)
+ {
+ /* Clean Resources */
+ for (size_t i = 0; i < (acl)->resourcesLen; i++)
+ {
+ OICFree((acl)->resources[i]);
+ }
+ OICFree((acl)->resources);
+
+ /* Clean Owners */
+ OICFree((acl)->owners);
+
+ /* Clean ACL node itself */
+ OICFree((acl));
+
+ acl = NULL;
+ }
+}
+
+void deleteCrl(OicSecCrl_t *crl)
+{
+ if (crl)
+ {
+ //Clean ThisUpdate
+ OICFree(crl->ThisUpdate.data);
+
+ //clean CrlData
+ OICFree(crl->CrlData.data);
+
+ //Clean crl itself
+ OICFree(crl);
+ }
+}
+
+/**
+ * Calculate ACL permission from string to bit
+ *
+ * @param[in] temp_psm Input data of ACL permission string
+ * @param[in,out] pms The pointer of ACL permission value
+ * @return 0 on success otherwise -1.
+ */
+static int CalculateAclPermission(const char *temp_pms, uint16_t *pms)
+{
+ int i = 0;
+
+ if (NULL == temp_pms || NULL == pms)
+ {
+ return -1;
+ }
+ *pms = 0;
+ while (temp_pms[i] != '\0')
+ {
+ switch (temp_pms[i])
+ {
+ case 'C':
+ {
+ *pms += CREATE;
+ i++;
+ break;
+ }
+ case 'R':
+ {
+ *pms += READ;
+ i++;
+ break;
+ }
+ case 'U':
+ {
+ *pms += UPDATE;
+ i++;
+ break;
+ }
+ case 'D':
+ {
+ *pms += DELETE;
+ i++;
+ break;
+ }
+ case 'N':
+ {
+ *pms += NOTIFY;
+ i++;
+ break;
+ }
+ case '_':
+ {
+ i++;
+ break;
+ }
+ default:
+ {
+ return -1;
+ }
+ }
+ }
+ return 0;
+}
+
+/**
+ * Get the ACL property from user
+ *
+ * @param[in] ACL Datastructure to save user inputs
+ * @return 0 on success otherwise -1.
+ */
+static int InputACL(OicSecAcl_t *acl)
+{
+ int ret;
+ char temp_id [UUID_LENGTH + 4] = {0,};
+ char temp_rsc[MAX_URI_LENGTH + 1] = {0,};
+ char temp_pms[MAX_PERMISSION_LENGTH + 1] = {0,};
+ printf("******************************************************************************\n");
+ printf("-Set ACL policy for target device\n");
+ printf("******************************************************************************\n");
+ //Set Subject.
+ printf("-URN identifying the subject\n");
+ printf("ex) doorDeviceUUID00 (16 Numbers except to '-')\n");
+ printf("Subject : ");
+ char *ptr = NULL;
+ ret = scanf("%19ms", &ptr);
+ if(1==ret)
+ {
+ OICStrcpy(temp_id, sizeof(temp_id), ptr);
+ OICFree(ptr);
+ }
+ else
+ {
+ printf("Error while input\n");
+ return -1;
+ }
+ int j = 0;
+ for (int i = 0; temp_id[i] != '\0'; i++)
+ {
+ if (DASH != temp_id[i])
+ {
+ if(j>UUID_LENGTH)
+ {
+ printf("Invalid input\n");
+ return -1;
+ }
+ acl->subject.id[j++] = temp_id[i];
+ }
+ }
+
+ //Set Resource.
+ printf("Num. of Resource : \n");
+ ret = scanf("%zu", &acl->resourcesLen);
+ printf("-URI of resource\n");
+ printf("ex) /a/light (Max_URI_Length: 64 Byte )\n");
+ acl->resources = (char **)OICCalloc(acl->resourcesLen, sizeof(char *));
+ if (NULL == acl->resources)
+ {
+ OC_LOG(ERROR, TAG, "Error while memory allocation");
+ return -1;
+ }
+ for (size_t i = 0; i < acl->resourcesLen; i++)
+ {
+ printf("[%zu]Resource : ", i + 1);
+ char *ptr_tempRsc = NULL;
+ ret = scanf("%64ms", &ptr_tempRsc);
+ if (1==ret)
+ {
+ OICStrcpy(temp_rsc, sizeof(temp_rsc), ptr_tempRsc);
+ OICFree(ptr_tempRsc);
+ }
+ else
+ {
+ printf("Error while input\n");
+ return -1;
+ }
+ acl->resources[i] = OICStrdup(temp_rsc);
+
+ if (NULL == acl->resources[i])
+ {
+ OC_LOG(ERROR, TAG, "Error while memory allocation");
+ return -1;
+ }
+ }
+ // Set Permission
+ do
+ {
+ printf("-Set the permission(C,R,U,D,N)\n");
+ printf("ex) CRUDN, CRU_N,..(5 Charaters)\n");
+ printf("Permission : ");
+ char *ptr_temp_pms = NULL;
+ ret = scanf("%5ms", &ptr_temp_pms);
+ if(1 == ret)
+ {
+ OICStrcpy(temp_pms, sizeof(temp_pms), ptr_temp_pms);
+ OICFree(ptr_temp_pms);
+
+ }
+ else
+ {
+ printf("Error while input\n");
+ return -1;
+ }
+ }
+ while (0 != CalculateAclPermission(temp_pms, &(acl->permission)) );
+ // Set Rowner
+ printf("Num. of Rowner : ");
+ ret = scanf("%zu", &acl->ownersLen);
+ printf("-URN identifying the rowner\n");
+ printf("ex) lightDeviceUUID0 (16 Numbers except to '-')\n");
+ acl->owners = (OicUuid_t *)OICCalloc(acl->ownersLen, sizeof(OicUuid_t));
+ if (NULL == acl->owners)
+ {
+ OC_LOG(ERROR, TAG, "Error while memory allocation");
+ return -1;
+ }
+ for (size_t i = 0; i < acl->ownersLen; i++)
+ {
+ printf("[%zu]Rowner : ", i + 1);
+ char *ptr_temp_id = NULL;
+ ret = scanf("%19ms", &ptr_temp_id);
+ if (1 == ret)
+ {
+ OICStrcpy(temp_id, sizeof(temp_id), ptr_temp_id);
+ OICFree(ptr_temp_id);
+ }
+ else
+ {
+ printf("Error while input\n");
+ return -1;
+ }
+ j = 0;
+ for (int k = 0; temp_id[k] != '\0'; k++)
+ {
+ if (DASH != temp_id[k])
+ {
+ acl->owners[i].id[j++] = temp_id[k];
+ }
+ }
+ }
+ return 0;
+}
+
+
+//FILE *client_fopen(const char *path, const char *mode)
+FILE *client_fopen(const char* UNUSED_PARAM , const char *mode)
+{
+ (void)UNUSED_PARAM;
+ return fopen(PROV_TOOL_DB_FILE, mode);
+}
+
+void PrintfResult(const char* procName, void* ctx, int nOfRes, OCProvisionResult_t *arr, bool hasError)
+{
+ printf("-----------------------------------------------------------\n");
+ if(!hasError)
+ {
+ printf("%s was successfully done.\n", procName);
+ }
+ else
+ {
+ for(int i = 0; i < nOfRes; i++)
+ {
+ printf("UUID : ");
+ for(int j = 0; j < UUID_LENGTH; j++)
+ {
+ printf("%c", arr[i].deviceId.id[j]);
+ }
+ printf("\t");
+ printf("Result=%d\n", arr[i].res);
+ }
+ }
+
+ if(ctx)
+ {
+ printf("Context is %s\n", (char*)ctx);
+ }
+ printf("-----------------------------------------------------------\n");
+}
+
+void ProvisionCertCB(void* ctx, int nOfRes, OCProvisionResult_t *arr, bool hasError)
+{
+ if(!hasError)
+ {
+ gOwnershipState = 1;
+ PrintfResult("Provision Credential", ctx, nOfRes, arr, hasError);
+ }
+ else printf("Cert provisioning error\n-----------------------------------------");
+}
+
+void ProvisionAclCB(void* ctx, int nOfRes, OCProvisionResult_t *arr, bool hasError)
+{
+ if(!hasError)
+ {
+ gOwnershipState = 1;
+ PrintfResult("Provision ACL", ctx, nOfRes, arr, hasError);
+ }
+}
+
+void ProvisionCrlCB(void* ctx, int nOfRes, OCProvisionResult_t *arr, bool hasError)
+{
+ if(!hasError)
+ {
+ gOwnershipState = 1;
+ PrintfResult("Provision CRL", ctx, nOfRes, arr, hasError);
+ }
+}
+
+
+
+void OwnershipTransferCB(void* ctx, int nOfRes, OCProvisionResult_t *arr, bool hasError)
+{
+ if(!hasError)
+ {
+ gOwnershipState = 1;
+ PrintfResult("Ownership transfer", ctx, nOfRes, arr, hasError);
+ }
+}
+
+static short IsCKMInfoFileExists()
+{
+ FILE *ckmInf = fopen(CA_STORAGE_FILE, "r");
+ if (NULL != ckmInf)
+ {
+ fclose(ckmInf);
+ return 1;
+ }
+ return 0;
+}
+
+static PKIError InitCA()
+{
+ FUNCTION_INIT();
+
+ if (IsCKMInfoFileExists())
+ {
+ CHECK_CALL(InitCKMInfo);
+ }
+ else
+ {
+ ByteArray rootName = BYTE_ARRAY_INITIALIZER;
+ ByteArray CAPubKey = BYTE_ARRAY_INITIALIZER;
+ ByteArray CAPrivKey = BYTE_ARRAY_INITIALIZER;
+ ByteArray rootCert = BYTE_ARRAY_INITIALIZER;
+
+
+ uint8_t rootCertData[ISSUER_MAX_CERT_SIZE];
+ uint8_t CAPubKeyData[PUBLIC_KEY_SIZE];
+ uint8_t CAPrivKeyData[PRIVATE_KEY_SIZE];
+ const char rootNameStr[] = "Sample_Root";
+
+ CAPubKey.data = CAPubKeyData;
+ CAPubKey.len = PUBLIC_KEY_SIZE;
+ CAPrivKey.data = CAPrivKeyData;
+ CAPrivKey.len = PRIVATE_KEY_SIZE;
+ rootCert.data = rootCertData;
+ rootCert.len = ISSUER_MAX_CERT_SIZE;
+ rootName.data = (uint8_t *)rootNameStr;
+ rootName.len = strlen(rootNameStr);
+
+ CHECK_CALL(SetRootName, rootName);
+ CHECK_CALL(GenerateCAKeyPair, &CAPrivKey, &CAPubKey);
+ CHECK_CALL(SetSerialNumber, 1);
+ CHECK_CALL(CKMIssueRootCertificate, NULL, NULL, &rootCert);
+ CHECK_CALL(SetCACertificate, &rootCert);
+ }
+
+ FUNCTION_CLEAR();
+}
+
+static int InputCRL(OicSecCrl_t *crlRes)
+{
+ FUNCTION_INIT(
+ ByteArray crl = BYTE_ARRAY_INITIALIZER;
+ );
+
+ const int MAX_Revoked_NUMBER = 9;
+ uint8_t uint8ThisUpdateTime[DATE_LENGTH] = "130101000005Z";
+ uint32_t revokedNumbers[MAX_Revoked_NUMBER];
+ const uint8_t* revocationDates[MAX_Revoked_NUMBER];
+ // const uint8_t revocationDatesContent[MAX_Revoked_NUMBER][DATE_LENGTH];
+ uint32_t nuberOfRevoked = 0;
+ printf("Enter number of Revoked certificates(1..%d)\n", MAX_Revoked_NUMBER);
+ scanf("%u", &nuberOfRevoked);
+
+ for (size_t i = 0; i < nuberOfRevoked; ++i)
+ {
+ printf("Revoked certificate %d:", i);
+ printf("Serial number (E. g.: 100):");
+ scanf("%u", &revokedNumbers[i]);
+ revocationDates[i] = (const uint8_t*)"130101000005Z";
+ }
+
+ crl.len = CRL_MIN_SIZE + nuberOfRevoked * (sizeof(CertificateRevocationInfo_t) + 4)/* + 1000*/;
+ crl.data = (uint8_t *)OICCalloc(1, crl.len);
+
+ CHECK_CALL(CKMIssueCRL, uint8ThisUpdateTime, nuberOfRevoked, revokedNumbers,
+ revocationDates, &crl);
+ PRINT_BYTE_ARRAY("CRL:\n",crl);
+ CHECK_CALL(SetCertificateRevocationList, &crl);
+ crlRes->CrlData = crl;
+ crlRes->ThisUpdate.data = uint8ThisUpdateTime;
+ crlRes->ThisUpdate.len = DATE_LENGTH;
+ crlRes->CrlId = 1;
+
+
+ FUNCTION_CLEAR(
+ //OICFree(crl.data);
+ );
+}
+
+
+/**
+ * Provisioning client sample using ProvisioningAPI
+ */
+int main()
+{
+ OCStackResult res = OC_STACK_OK;
+
+ // Initialize Persistent Storage for SVR database
+ OCPersistentStorage ps = { .open = client_fopen,
+ .read = fread,
+ .write = fwrite,
+ .close = fclose,
+ .unlink = unlink};
+
+ OCRegisterPersistentStorageHandler(&ps);
+
+ if (OC_STACK_OK != OCInit(NULL, 0, OC_CLIENT_SERVER))
+ {
+ OC_LOG(ERROR, TAG, "OCStack init error");
+ goto error;
+ }
+
+ OCProvisionDev_t* pDeviceList = NULL;
+ res = OCDiscoverUnownedDevices(PREDEFINED_TIMEOUT, &pDeviceList);
+ if(OC_STACK_OK != res)
+ {
+ OC_LOG_V(ERROR, TAG, "Failed to PMDeviceDiscovery : %d", res);
+ goto error;
+ }
+
+ OCProvisionDev_t* pCurDev = pDeviceList;
+ int i;
+ while(pCurDev !=NULL)
+ {
+ for(i = 0; i < UUID_LENGTH; i++)
+ {
+ printf("%c", pCurDev->doxm->deviceID.id[i]);
+ }
+ printf("\n");
+ pCurDev = pCurDev->next;
+ }
+
+ //Register callback function to each OxM
+ OTMCallbackData_t justWorksCBData = {.loadSecretCB=NULL,
+ .createSecureSessionCB=NULL,
+ .createSelectOxmPayloadCB=NULL,
+ .createOwnerTransferPayloadCB=NULL};
+ justWorksCBData.loadSecretCB = LoadSecretJustWorksCallback;
+ justWorksCBData.createSecureSessionCB = CreateSecureSessionJustWorksCallback;
+ justWorksCBData.createSelectOxmPayloadCB = CreateJustWorksSelectOxmPayload;
+ justWorksCBData.createOwnerTransferPayloadCB = CreateJustWorksOwnerTransferPayload;
+ OTMSetOwnershipTransferCallbackData(OIC_JUST_WORKS, &justWorksCBData);
+
+ char* myContext = "OTM Context";
+ //Perform ownership transfer
+ res = OCDoOwnershipTransfer((void*)myContext, pDeviceList, OwnershipTransferCB);
+ if(OC_STACK_OK == res)
+ {
+ OC_LOG(INFO, TAG, "Request for ownership transfer is sent successfully.");
+ }
+ else
+ {
+ OC_LOG_V(ERROR, TAG, "Failed to OCDoOwnershipTransfer : %d", res);
+ }
+
+ gOwnershipState = 0;
+ while (gOwnershipState == 0)
+ {
+ if (OCProcess() != OC_STACK_OK)
+ {
+ OC_LOG(ERROR, TAG, "OCStack process error");
+ goto error;
+ }
+ sleep(1);
+ }
+
+// Credential & ACL provisioning between two devices.
+
+ OCProvisionDev_t *pOwnedList = NULL;
+ OCProvisionDev_t *pOwnedDevices [MAX_OWNED_DEVICE] = {0,};
+ int nOwnedDevice = 0;
+
+ res = OCDiscoverOwnedDevices(PREDEFINED_TIMEOUT, &pOwnedList);
+ if (OC_STACK_OK == res)
+ {
+ printf("################## Owned Device List #######################\n");
+ while (pOwnedList != NULL)
+ {
+ nOwnedDevice ++;
+ printf(" %d : ", nOwnedDevice);
+ for (int i = 0; i < UUID_LENGTH; i++)
+ {
+ printf("%c", pOwnedList->doxm->deviceID.id[i]);
+ }
+ printf("\n");
+ pOwnedDevices[nOwnedDevice] = pOwnedList;
+ pOwnedList = pOwnedList->next;
+ }
+ }
+ else
+ {
+ OC_LOG(ERROR, TAG, "Error while Owned Device Discovery");
+ }
+
+ int Device1 = 0;
+ int Device2 = 0;
+
+ printf("Select 2 devices for Credential & ACL provisioning\n");
+ printf("Device 1: ");
+ scanf("%d", &Device1);
+ printf("Device 2: ");
+ scanf("%d", &Device2);
+
+
+ gAcl = (OicSecAcl_t *)OICCalloc(1,sizeof(OicSecAcl_t));
+ if (NULL == gAcl)
+ {
+ OC_LOG(ERROR, TAG, "Error while memory allocation");
+ goto error;
+ }
+
+ if (PKI_SUCCESS != InitCA())
+ {
+ OC_LOG(ERROR, TAG, "CA init error");
+ goto error;
+ }
+
+
+ char *ctx = "DUMMY";
+
+ res = OCProvisionCredentials(ctx, SIGNED_ASYMMETRIC_KEY, 0, pOwnedDevices[Device1],
+ NULL, ProvisionCertCB);
+ if (OC_STACK_OK != res) OC_LOG_V(ERROR, TAG, "Failed to provision Device 1 : %d", res);
+ gOwnershipState = 0;
+ while ( gOwnershipState == 0 )
+ {
+ if (OCProcess() != OC_STACK_OK)
+ {
+ OC_LOG(ERROR, TAG, "OCStack process error");
+ goto error;
+ }
+ sleep(1);
+ }
+
+ res = OCProvisionCredentials(ctx, SIGNED_ASYMMETRIC_KEY, 0, pOwnedDevices[Device2],
+ NULL, ProvisionCertCB);
+ if (OC_STACK_OK != res)
+ {
+ OC_LOG_V(ERROR, TAG, "Failed to provision Device 2 : %d", res);
+ }
+
+ gOwnershipState = 0;
+ while (gOwnershipState == 0)
+ {
+ if (OCProcess() != OC_STACK_OK)
+ {
+ OC_LOG(ERROR, TAG, "OCStack process error");
+ goto error;
+ }
+ sleep(1);
+ }
+
+ printf("Input ACL for Device2\n");
+ if (0 == InputACL(gAcl))
+ {
+ printf("Success Input ACL\n");
+ }
+ else
+ {
+ OC_LOG(ERROR, TAG, "InputACL error");
+ goto error;
+ }
+ res = OCProvisionACL(ctx, pOwnedDevices[Device2], gAcl, &ProvisionAclCB);
+ if (OC_STACK_OK != res)
+ {
+ OC_LOG_V(ERROR, TAG, "Failed to ACL provision Device 2 : %d", res);
+ }
+
+ gOwnershipState = 0;
+ while (gOwnershipState == 0)
+ {
+ if (OCProcess() != OC_STACK_OK)
+ {
+ OC_LOG(ERROR, TAG, "OCStack process error");
+ goto error;
+ }
+ sleep(1);
+ }
+ gCrl = (OicSecCrl_t *)OICMalloc(sizeof(OicSecCrl_t));
+ if (PKI_SUCCESS != InputCRL(gCrl))
+ {
+ OC_LOG(ERROR, TAG, "CA init error");
+ goto error;
+ }
+
+ PRINT_BYTE_ARRAY("gCrl = \n", gCrl->CrlData);
+
+
+ res = OCProvisionCRL(ctx, pOwnedDevices[Device2], gCrl, &ProvisionCrlCB);
+ if (OC_STACK_OK != res) OC_LOG_V(ERROR, TAG, "Failed to CRL provision Device 2 : %d", res);
+
+ gOwnershipState = 0;
+ while (gOwnershipState == 0)
+ {
+ if (OCProcess() != OC_STACK_OK)
+ {
+ OC_LOG(ERROR, TAG, "OCStack process error");
+ goto error;
+ }
+ sleep(1);
+ }
+
+ if (OCStop() != OC_STACK_OK)
+ {
+ OC_LOG(ERROR, TAG, "OCStack process error");
+ goto error;
+ }
+
+error:
+ deleteACL(gAcl);
+ OCDeleteDiscoveredDevices(&pDeviceList);
+ OCDeleteDiscoveredDevices(&pOwnedList);
+
+ return 0;
+}