From d2bd8d82d88b85e8a8abc9cc3990a4ac0554369e Mon Sep 17 00:00:00 2001 From: "i.pazderskyy" Date: Thu, 24 Sep 2015 17:36:25 +0300 Subject: [PATCH] Add sample of PKIX provisioning Includes provisioning client, door and light samples Change-Id: I1457076f665ff8226a779bfe683e5a7536cabe83 Signed-off-by: Dmytro Zhuravlev Signed-off-by: i.pazderskyy Reviewed-on: https://gerrit.iotivity.org/gerrit/2480 Tested-by: jenkins-iotivity Reviewed-by: Jon A. Cruz --- .../sample/Door_Resource/Door_sample.cpp | 574 +++++++++++++++++ .../sample/Door_Resource/oic_svr_db_door.json | 46 ++ .../sample/Light_Resource/Light_sample.cpp | 334 ++++++++++ .../sample/Light_Resource/oic_svr_db_light.json | 46 ++ .../provisioning/ck_manager/sample/README.txt | 132 ++++ .../ck_manager/sample/oic_svr_db_pt.json | 43 ++ .../ck_manager/sample/provisioningclient.c | 701 +++++++++++++++++++++ 7 files changed, 1876 insertions(+) create mode 100755 resource/csdk/security/provisioning/ck_manager/sample/Door_Resource/Door_sample.cpp create mode 100644 resource/csdk/security/provisioning/ck_manager/sample/Door_Resource/oic_svr_db_door.json create mode 100755 resource/csdk/security/provisioning/ck_manager/sample/Light_Resource/Light_sample.cpp create mode 100755 resource/csdk/security/provisioning/ck_manager/sample/Light_Resource/oic_svr_db_light.json create mode 100644 resource/csdk/security/provisioning/ck_manager/sample/README.txt create mode 100644 resource/csdk/security/provisioning/ck_manager/sample/oic_svr_db_pt.json create mode 100644 resource/csdk/security/provisioning/ck_manager/sample/provisioningclient.c diff --git a/resource/csdk/security/provisioning/ck_manager/sample/Door_Resource/Door_sample.cpp b/resource/csdk/security/provisioning/ck_manager/sample/Door_Resource/Door_sample.cpp new file mode 100755 index 0000000..c4db6bc --- /dev/null +++ b/resource/csdk/security/provisioning/ck_manager/sample/Door_Resource/Door_sample.cpp @@ -0,0 +1,574 @@ +//****************************************************************** +// +// 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 +#include +#include +#include +#include +#include +#include +#include +#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(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 (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; +} diff --git a/resource/csdk/security/provisioning/ck_manager/sample/Door_Resource/oic_svr_db_door.json b/resource/csdk/security/provisioning/ck_manager/sample/Door_Resource/oic_svr_db_door.json new file mode 100644 index 0000000..21aa0e7 --- /dev/null +++ b/resource/csdk/security/provisioning/ck_manager/sample/Door_Resource/oic_svr_db_door.json @@ -0,0 +1,46 @@ +{ + "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==" + } +} diff --git a/resource/csdk/security/provisioning/ck_manager/sample/Light_Resource/Light_sample.cpp b/resource/csdk/security/provisioning/ck_manager/sample/Light_Resource/Light_sample.cpp new file mode 100755 index 0000000..9a3f82e --- /dev/null +++ b/resource/csdk/security/provisioning/ck_manager/sample/Light_Resource/Light_sample.cpp @@ -0,0 +1,334 @@ +//****************************************************************** +// +// 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 +#include +#include +#include +#include +#include +#include +#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(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; +} diff --git a/resource/csdk/security/provisioning/ck_manager/sample/Light_Resource/oic_svr_db_light.json b/resource/csdk/security/provisioning/ck_manager/sample/Light_Resource/oic_svr_db_light.json new file mode 100755 index 0000000..d10b71e --- /dev/null +++ b/resource/csdk/security/provisioning/ck_manager/sample/Light_Resource/oic_svr_db_light.json @@ -0,0 +1,46 @@ +{ + "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==" + } +} diff --git a/resource/csdk/security/provisioning/ck_manager/sample/README.txt b/resource/csdk/security/provisioning/ck_manager/sample/README.txt new file mode 100644 index 0000000..5338d76 --- /dev/null +++ b/resource/csdk/security/provisioning/ck_manager/sample/README.txt @@ -0,0 +1,132 @@ +# 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. diff --git a/resource/csdk/security/provisioning/ck_manager/sample/oic_svr_db_pt.json b/resource/csdk/security/provisioning/ck_manager/sample/oic_svr_db_pt.json new file mode 100644 index 0000000..49fb2a8 --- /dev/null +++ b/resource/csdk/security/provisioning/ck_manager/sample/oic_svr_db_pt.json @@ -0,0 +1,43 @@ +{ + "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==" + } +} diff --git a/resource/csdk/security/provisioning/ck_manager/sample/provisioningclient.c b/resource/csdk/security/provisioning/ck_manager/sample/provisioningclient.c new file mode 100644 index 0000000..466cfe9 --- /dev/null +++ b/resource/csdk/security/provisioning/ck_manager/sample/provisioningclient.c @@ -0,0 +1,701 @@ +/****************************************************************** +* +* 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 +#include +#include + +#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; +} -- 2.7.4