const std::vector<std::string>& interfaces);
OCStackResult sendResponse(const std::shared_ptr<OCResourceResponse> pResponse);
+ std::weak_ptr<std::recursive_mutex> csdkLock();
+
private:
PlatformConfig m_cfg;
--- /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.
+ *
+ * *****************************************************************/
+
+#ifndef _OCPROVISIONINGMANAGER_CXX_H
+#define _OCPROVISIONINGMANAGER_CXX_H
+
+#include <thread>
+
+#include "pinoxmcommon.h"
+#include "ocprovisioningmanager.h"
+#include "OCApi.h"
+#include "OCPlatform_impl.h"
+
+namespace OC
+{
+ class OCSecureResource;
+
+ typedef std::vector<std::shared_ptr<OCSecureResource>> DeviceList_t;
+ typedef std::vector<OicUuid_t> UuidList_t;
+ typedef std::vector<OCProvisionResult_t> PMResultList_t;
+ typedef std::function<void(PMResultList_t *result, int hasError)> ResultCallBack;
+
+ struct ProvisionContext
+ {
+ ResultCallBack callback;
+ ProvisionContext(ResultCallBack cb) : callback(cb){}
+ };
+
+ /**
+ * @brief: This class is for credential's to be set to devices.
+ * The types supported are
+ * 0: no security mode
+ * 1: symmetric pair-wise key
+ * 2: symmetric group key
+ * 4: asymmetric key
+ * 8: signed asymmetric key (aka certificate)
+ * 16: PIN /password
+ */
+ class Credential
+ {
+ OicSecCredType_t type;
+ size_t keySize;
+ public:
+ Credential() = default;
+ Credential(OicSecCredType_t type, size_t size) : type(type), keySize(size)
+ {}
+
+ OicSecCredType_t getCredentialType() const
+ {
+ return type;
+ }
+
+ size_t getCredentialKeySize() const
+ {
+ return keySize;
+ }
+
+ void setCredentialType(OicSecCredType_t type)
+ {
+ this->type = type;
+ }
+
+ void setCredentialKeySize(size_t keySize)
+ {
+ this->keySize = keySize;
+ }
+ };
+
+ class OCSecure
+ {
+ public:
+ /**
+ * The API is responsible for initializaton of the provisioning manager. It will load
+ * provisioning database which have owned device's list and their linked status.
+ *
+ * @param[in] dbPath file path of the sqlite3 db
+ *
+ * @return OC_STACK_OK in case of success and other value otherwise.
+ */
+ static OCStackResult provisionInit(const std::string& dbPath);
+
+ /**
+ * API is responsible for discovery of devices in it's subnet. It will list
+ * all the device in subnet which are not yet owned.
+ *
+ * @param[in] timeout Timeout in seconds, time util which function will listen to
+ * responses from client before returning the list of devices.
+ * @param[out] list List of candidate devices to be provisioned
+ * @return OC_STACK_OK in case of success and other value otherwise.
+ */
+ static OCStackResult discoverUnownedDevices(unsigned short timeout,
+ DeviceList_t &list);
+
+ /**
+ * API is responsible for discovery of devices in it's subnet. It will list
+ * all the device in subnet which are already owned by calling provioning client
+ *
+ * @param[in] timeout Timeout in seconds, time util which function will listen to
+ * responses from client before returning the list of devices.
+ * @param[out] list List of owned devices
+ * @return OC_STACK_OK in case of success and other value otherwise.
+ */
+ static OCStackResult discoverOwnedDevices(unsigned short timeout,
+ DeviceList_t &list);
+
+ /**
+ * API for registering Ownershipt transfer methods for a particular transfer Type
+ *
+ * @param[in] oxm Ownership transfer method
+ * @param[in] callbackData Methods for ownership transfer
+ * @param[in] InputPinCallback Method to input pin for verification
+ * @return OC_STACK_OK in case of success and other value otherwise.
+ */
+ static OCStackResult setOwnerTransferCallbackData(OicSecOxm_t oxm,
+ OTMCallbackData_t* callbackData, InputPinCallback inputPin);
+
+ /**
+ * API to get status of all the devices in current subnet. The status include endpoint
+ * information and doxm information which can be extracted duing owned and unowned
+ * discovery. Along with this information, API will provide information about
+ * devices' status.
+ * Device can have following states
+ * - ON/OFF: Device is switched on or off.
+ *
+ * @param[in] timeout waitime for the API.
+ * @param[out] pOwnedDevList list of owned devices.
+ * @param[out] pUnownedDevList list of unowned devices.
+ * @return OC_STACK_OK in case of success and other value otherwise.
+ */
+ static OCStackResult getDevInfoFromNetwork(unsigned short timeout,
+ DeviceList_t &ownedDevList,
+ DeviceList_t &unownedDevList);
+
+ };
+
+ /**
+ * This class represents a Secure virtual Device, which can be provisioned by the
+ * provisioning client.
+ */
+ class OCSecureResource
+ {
+ private:
+ std::weak_ptr<std::recursive_mutex> m_csdkLock;
+ OCProvisionDev_t *devPtr; // pointer to device.
+
+ public:
+ OCSecureResource();
+ OCSecureResource(std::weak_ptr<std::recursive_mutex> csdkLock, OCProvisionDev_t *dPtr);
+
+ ~OCSecureResource();
+
+ /**
+ * API to provision credentials between two devices and ACLs for the devices who
+ * act as a server.
+ *
+ * @param[in] cred Type of credentials & key size to be provisioned to the device.
+ * @param[in] acl1 ACL for device 1. If this is not required set NULL.
+ * @param[in] device2 Second device to be provsioned.
+ * @param[in] acl2 ACL for device 2. If this is not required set NULL.
+ * @param[in] resultCallback Callback will be called when provisioning request recieves
+ * a response from first resource server.
+ * @return OC_STACK_OK in case of success and other value otherwise.
+ */
+ OCStackResult provisionPairwiseDevices(const Credential &cred, const OicSecAcl_t* acl1,
+ const OCSecureResource &device2, const OicSecAcl_t* acl2,
+ ResultCallBack resultCallback);
+
+ /**
+ * API to do ownership transfer for un-owned device.
+ *
+ * @param[in] resultCallback Result callback function to be invoked when
+ * ownership transfer finished.
+ * @return OC_STACK_OK in case of success and other value otherwise.
+ */
+ OCStackResult doOwnershipTransfer(ResultCallBack resultCallback);
+
+ /**
+ * API to send ACL information to resource.
+ *
+ * @param[in] acl ACL to provision.
+ * @param[in] resultCallback callback will be called when provisioning request
+ * recieves a response from resource server.
+ * @return OC_STACK_OK in case of success and other value otherwise.
+ */
+ OCStackResult provisionACL(const OicSecAcl_t* acl,
+ ResultCallBack resultCallback);
+
+ /**
+ * API to provision credential to devices.
+ *
+ * @param[in] cred Type of credentials to be provisioned to the device.
+ * @param[in] device2 Second device' instance,respresenting resourceto be provsioned.
+ * @param[in] resultCallback callback will be called when provisioning request recieves
+ * a response from first resource server.
+ * @return OC_STACK_OK in case of success and other value otherwise.
+ */
+ OCStackResult provisionCredentials(const Credential &cred,
+ const OCSecureResource &device2,
+ ResultCallBack resultCallback);
+
+ /*
+ * API to remove the credential & relasionship between the two devices.
+ *
+ * @param[in] pTargetDev2 second device information to be unlinked.
+ * @param[in] resultCallback callback provided by API user, callback will be called when
+ * device unlink is finished.
+ * @return OC_STACK_OK in case of success and other value otherwise.
+ */
+ OCStackResult unlinkDevices(const OCSecureResource &device2,
+ ResultCallBack resultCallback);
+
+ /*
+ * API to remove device credential from all devices in subnet.
+ *
+ * @param[in] resultCallback callback provided by API user, callback will be called when
+ * credential revocation is finished.
+ * @return OC_STACK_OK in case of success and other value otherwise.
+ */
+ OCStackResult removeDevice(ResultCallBack resultCallback);
+
+ /**
+ * This method is used to get linked devices' IDs.
+ *
+ * @param[out] uuidList information about the list of linked devices' uuids.
+ * @param[out] numOfDevices total number of linked devices.
+ * @return OC_STACK_OK in case of success and other value otherwise.
+ */
+ OCStackResult getLinkedDevices(UuidList_t &uuidList);
+
+ /**
+ * API to get the DeviceID of this resource
+ */
+ std::string getDeviceID();
+
+ OCProvisionDev_t* getDevPtr()const;
+
+ /**
+ * This function returns the Device's IP addr.
+ */
+ std::string getDevAddr();
+
+ /**
+ * This function returns the Device's Status
+ */
+ int getDeviceStatus();
+
+ /**
+ * This function provides the OWNED status of the device.
+ */
+ bool getOwnedStatus();
+
+ private:
+ /**
+ * Common callback wrapper, which will be called from OC-APIs.
+ */
+ static void callbackWrapper(void* ctx, int nOfRes,
+ OCProvisionResult_t *arr, bool hasError);
+
+ void validateSecureResource();
+ };
+
+}
+#endif //_OCPROVISIONINGMANAGER_CXX_H
--- /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.
+#
+#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+Import('env')
+
+ocprovision_env = env.Clone()
+
+######################################################################
+# Build flags
+######################################################################
+ocprovision_env.AppendUnique(CPPPATH = [
+ '../include/',
+ '../csdk/stack/include',
+ '../csdk/logger/include',
+ '../oc_logger/include',
+ '../csdk/security/include',
+ '../csdk/security/provisioning/include',
+ '../csdk/security/provisioning/include/oxm',
+ '../csdk/security/provisioning/include/internal'
+ ])
+
+target_os = env.get('TARGET_OS')
+if target_os not in ['windows', 'winrt']:
+ ocprovision_env.AppendUnique(CXXFLAGS = ['-std=c++0x', '-Wall', '-fPIC'])
+
+if target_os == 'android':
+ ocprovision_env.AppendUnique(CXXFLAGS = ['-frtti', '-fexceptions'])
+ ocprovision_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')])
+ ocprovision_env.AppendUnique(LIBS = ['ocspapi', 'octbstack', 'oc_logger', 'boost_thread', 'gnustl_shared', 'log'])
+
+if target_os in ['darwin', 'ios']:
+ ocprovision_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')])
+ ocprovision_env.AppendUnique(LIBS = ['octbstack', 'oc_logger'])
+
+######################################################################
+# Source files and Targets
+######################################################################
+ocprovision_src = [
+ 'src/OCProvisioningManager.cpp'
+ ]
+
+ocprovision = ocprovision_env.StaticLibrary('ocprovision', ocprovision_src)
+ocprovision_env.InstallTarget(ocprovision, 'libocprovision')
+
+if target_os in ['linux']:
+ SConscript('examples/SConscript')
--- /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.
+#
+#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+##
+# Examples build script
+##
+Import('env')
+# Add third party libraries
+lib_env = env.Clone()
+SConscript(env.get('SRC_DIR') + '/resource/third_party_libs.scons', 'lib_env')
+
+examples_env = lib_env.Clone()
+
+######################################################################
+# Build flags
+######################################################################
+examples_env.AppendUnique(CPPPATH = [
+ '../../include/',
+ '../../csdk/stack/include',
+ '../../csdk/logger/include',
+ '../../oc_logger/include',
+ '../../csdk/security/include',
+ '../../csdk/security/provisioning/include',
+ '../../csdk/security/provisioning/include/oxm',
+ '../../csdk/security/provisioning/include/internal'
+ ])
+
+target_os = env.get('TARGET_OS')
+if target_os not in ['windows', 'winrt']:
+ examples_env.AppendUnique(CXXFLAGS = ['-std=c++0x', '-Wall', '-pthread'])
+
+ # Note: 'pthread' is in libc for android. On other platform, if use
+ # new gcc(>4.9?) it isn't required, otherwise, it's required
+ if target_os != 'android':
+ examples_env.AppendUnique(LIBS = ['-lpthread'])
+
+examples_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')])
+examples_env.AppendUnique(RPATH = [env.get('BUILD_DIR')])
+examples_env.PrependUnique(LIBS = ['ocprovision', 'oc', 'ocpmapi', 'octbstack',
+ 'oc_logger', 'connectivity_abstraction', 'coap'])
+if env.get('SECURED') == '1':
+ examples_env.AppendUnique(LIBS = ['tinydtls'])
+
+if target_os == 'android':
+ examples_env.AppendUnique(CXXFLAGS = ['-frtti', '-fexceptions'])
+ examples_env.AppendUnique(LIBS = ['gnustl_shared'])
+
+ if not env.get('RELEASE'):
+ examples_env.AppendUnique(LIBS = ['log'])
+
+if target_os in ['darwin', 'ios']:
+ examples_env.AppendUnique(CPPDEFINES = ['_DARWIN_C_SOURCE'])
+
+######################################################################
+# Source files and Targets
+######################################################################
+provisioningclient = examples_env.Program('provisioningclient', 'provisioningclient.cpp')
+
+Alias("examples", [provisioningclient])
+env.AppendTarget('examples')
+
+src_dir = examples_env.get('SRC_DIR')
+svr_db_src_dir = src_dir + '/resource/provisioning/examples/'
+svr_db_build_dir = env.get('BUILD_DIR') +'/resource/provisioning/examples/'
+examples_env.Alias("install", examples_env.Install( svr_db_build_dir,
+ svr_db_src_dir + 'oic_svr_db_client.json'))
--- /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 <string>
+#include <map>
+#include <cstdlib>
+#include <pthread.h>
+#include <mutex>
+#include <condition_variable>
+
+#include "logger.h"
+#include "oic_malloc.h"
+#include "oic_string.h"
+#include "OCPlatform.h"
+#include "OCApi.h"
+#include "OCProvisioningManager.h"
+#include "oxmjustworks.h"
+#include "oxmrandompin.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 TAG "provisioningclient"
+
+#define JSON_DB_PATH "./oic_svr_db_client.json"
+#define DEV_STATUS_ON "DEV_STATUS_ON"
+#define DEV_STATUS_OFF "DEV_STATUS_OFF"
+
+#define DISCOVERY_TIMEOUT 5
+
+using namespace OC;
+
+DeviceList_t pUnownedDevList, pOwnedDevList;
+static int transferDevIdx, ask = 1;
+
+OicSecAcl_t defaultAcl =
+{
+ {},
+ 1,
+ NULL,
+ 0x001F,
+ 0,
+ NULL,
+ NULL,
+ 1,
+ NULL,
+ NULL,
+};
+
+static FILE* client_open(const char *path, const char *mode)
+{
+ return fopen(JSON_DB_PATH, mode);
+}
+
+void printMenu()
+{
+ std::cout << "\nChoose an option:"<<std::endl;
+ std::cout << " 1. UnOwned Device discovery"<<std::endl;
+ std::cout << " 2. Owned Device discovery"<<std::endl;
+ std::cout << " 3. Ownership transfer"<<std::endl;
+ std::cout << " 4. Provision ACL"<<std::endl;
+ std::cout << " 5. Provision Credentials"<<std::endl;
+ std::cout << " 6. Credential & ACL provisioning b/w two devices"<<std::endl;
+ std::cout << " 7. Unlink Devices"<<std::endl;
+ std::cout << " 8. Remove Device"<<std::endl;
+ std::cout << " 9. Get Linked Devices"<<std::endl;
+ std::cout << " 10. Get Device Status"<<std::endl;
+ std::cout << " 11. Exit loop"<<std::endl;
+}
+
+void moveTransferredDevice()
+{
+ pOwnedDevList.push_back(pUnownedDevList[transferDevIdx]);
+ pUnownedDevList.erase(pUnownedDevList.begin() + transferDevIdx);
+}
+
+void InputPinCB(char* pinBuf, size_t bufSize)
+{
+ if(pinBuf)
+ {
+ std::cout <<"INPUT PIN : ";
+ std::string ptr;
+ std::cin >> ptr;
+ OICStrcpy(pinBuf, bufSize, ptr.c_str());
+ return;
+ }
+}
+
+void printUuid(OicUuid_t uuid)
+{
+ for (int i = 0; i < UUID_LENGTH; i++)
+ {
+ std::cout << uuid.id[i];
+ }
+ std::cout<<std::endl;
+}
+
+void ownershipTransferCB(PMResultList_t *result, int hasError)
+{
+ if (hasError)
+ {
+ std::cout << "Error!!! in OwnershipTransfer"<<std::endl;
+ }
+ else
+ {
+ std::cout<< "\nTransferred Ownership successfuly for device : ";
+ printUuid(result->at(0).deviceId);
+ delete result;
+
+ moveTransferredDevice();
+ }
+ ask = 1;
+}
+
+void printStatus(int status)
+{
+ static std::map<int, std::string> devStatus = {{1<<0, DEV_STATUS_ON}, {1<<1, DEV_STATUS_OFF}};
+
+ std::cout <<devStatus[status] <<std::endl;
+}
+
+void printDevices(DeviceList_t &list)
+{
+ for (unsigned int i = 0; i < list.size(); i++ )
+ {
+ std::cout << "Device "<< i+1 <<" ID: ";
+ std::cout << list[i]->getDeviceID() << " From IP: ";
+ std::cout << list[i]->getDevAddr() << std::endl;
+ }
+}
+
+/**
+ * Callback function for provisioning ACL, Credentials.
+ *
+ * @param[in] result Result list
+ * @param[in] hasError indicates if the result has error
+ */
+void provisionCB(PMResultList_t *result, int hasError)
+{
+ if (hasError)
+ {
+ std::cout << "Error in provisioning operation!"<<std::endl;
+ }
+ else
+ {
+ std::cout<< "\nReceived provisioning results: ";
+ for (unsigned int i = 0; i < result->size(); i++)
+ {
+ for (int j = 0; j < UUID_LENGTH; j++) std::cout << result->at(i).deviceId.id[j];
+ std::cout << ", result = " << result->at(i).res << std::endl;
+ }
+
+ delete result;
+ }
+ printMenu();
+ ask = 1;
+}
+/**
+ *
+ * Ask user with which devices it wants to make further actions.
+ * All possible error checks included.
+ * Default behavior in case if only one options leaves are included too.
+ * Expect that user count devices from 1, f.e. 1st, 2nd, 3rd, etc
+ * Use DeviceList_t instead of devicesCount because of print devices info
+ *
+ * @param[in] list owned devices list.
+ * @param[out] out device number array.
+ * @param[in] count how many device numbers need to read.
+ * @return 0 in case of success and other value otherwise.
+ */
+int readDeviceNumber(DeviceList_t &list, int count, int *out)
+{
+ if (out == NULL || count <= 0)
+ {
+ std::cout << "Error! Please put valid input parameters" << std::endl;
+ return -1;
+ }
+
+ int devicesCount = list.size();
+
+ //Print current list of owned devices
+ std::cout <<"Owned devices, count = " << devicesCount << std::endl;
+ printDevices(list);
+
+ if (devicesCount < count)
+ {
+ std::cout << "You can't proceed with selected action because Owned devices count ( ";
+ std::cout << devicesCount << " ) are less then required devices ( " << count << " ).";
+ std::cout << "You may need to discover devices again" << std::endl;
+ return -2;
+ }
+
+ std::cout << "Select " << count << " device(s) for provisioning" << std::endl;
+
+ for (int curr = 0; curr < count; curr++)
+ {
+ //select last device by default if only 1 option exist
+ //from user's point of view device counting starts from 1,
+ //so 1st, 2nd, 3rd, etc devices
+ if ((curr == count - 1) && (devicesCount == count))
+ {
+ int sum = 0;
+ for (int i = 0; i < curr; i++)
+ {
+ sum += out[i];
+ }
+
+ out[curr] = (count*(count+1))/2 - sum;
+
+ std::cout << "Device " << curr + 1 << " : " << out[curr];
+ std::cout << " - selected automatically (because no other options exist)" << std::endl;
+ break;
+ }
+
+ int choice;
+ std::cout << "Device " << curr + 1 << " : ";
+ std::cin >> choice;
+
+ if (choice < 1 || choice > devicesCount)
+ {
+ std::cout << "Error! You should enter valid device number!" << std::endl;
+ return -3;
+ }
+
+ //check that user doesn't select the same device twice
+ for (int i = 0; i < curr; i++)
+ {
+ if (out[i] == choice)
+ {
+ std::cout << "Error! You cannot select the same device twice!" << std::endl;
+ return -4;
+ }
+ }
+
+ out[curr] = choice;
+ }
+
+ //Users count devices from 1, so 1st, 2nd, 3rd, etc device
+ //But deviceList array start index is 0, so need to decrease all numbers to 1
+ for (int i = 0; i < count; i++) out[i] -= 1;
+
+ return 0;
+}
+
+/**
+ * Perform cleanup for ACL
+ * @param[in] ACL
+ */
+static void deleteACL(OicSecAcl_t *acl)
+{
+ if (acl)
+ {
+ /* Clean Resources */
+ for (unsigned int i = 0; i < (acl)->resourcesLen; i++)
+ {
+ OICFree((acl)->resources[i]);
+ }
+ OICFree((acl)->resources);
+
+ /* Clean Owners */
+ OICFree((acl)->owners);
+
+ /* Clean ACL node itself */
+ /* Required only if acl was created in heap */
+ //OICFree((acl));
+ }
+}
+
+/**
+ * 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, *temp_rsc, *temp_pms;
+
+ printf("******************************************************************************\n");
+ printf("-Set ACL policy for target device\n");
+ printf("******************************************************************************\n");
+ //Set Subject.
+ printf("-URN identifying the subject\n");
+ printf("ex) 1111-1111-1111-1111 (16 Numbers except to '-')\n");
+ printf("Subject : ");
+ ret = scanf("%19ms", &temp_id);
+
+ if (1 == ret)
+ {
+ for (int i = 0, j = 0; temp_id[i] != '\0'; i++)
+ {
+ if (DASH != temp_id[i])
+ acl->subject.id[j++] = temp_id[i];
+ }
+ OICFree(temp_id);
+ }
+ else
+ {
+ printf("Error while input\n");
+ return -1;
+ }
+
+ //Set Resource.
+ printf("Num. of Resource : ");
+ ret = scanf("%zu", &acl->resourcesLen);
+ printf("-URI of resource\n");
+ printf("ex)/oic/sh/temp/0 (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);
+ ret = scanf("%64ms", &temp_rsc);
+ if (1 != ret)
+ {
+ printf("Error while input\n");
+ return -1;
+ }
+
+ acl->resources[i] = OICStrdup(temp_rsc);
+ OICFree(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 : ");
+ ret = scanf("%5ms", &temp_pms);
+ if (1 != ret)
+ {
+ printf("Error while input\n");
+ return -1;
+ }
+ ret = CalculateAclPermission(temp_pms, &(acl->permission));
+ OICFree(temp_pms);
+ } while (0 != ret );
+
+ // Set Rowner
+ printf("Num. of Rowner : ");
+ ret = scanf("%zu", &acl->ownersLen);
+ printf("-URN identifying the rowner\n");
+ printf("ex) 1111-1111-1111-1111 (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);
+ ret = scanf("%19ms", &temp_id);
+ if (1 != ret)
+ {
+ printf("Error while input\n");
+ return -1;
+ }
+
+ for (int k = 0, j = 0; temp_id[k] != '\0'; k++)
+ {
+ if (DASH != temp_id[k])
+ {
+ acl->owners[i].id[j++] = temp_id[k];
+ }
+ }
+ OICFree(temp_id);
+ }
+ return 0;
+}
+
+static int InputCredentials(Credential &cred)
+{
+ int choice;
+
+ do
+ {
+ std::cout << "Select credential type from following values:" << std::endl;
+ std::cout << "1: symmetric pair-wise key" << std::endl;
+ std::cout << "2: symmetric group key" << std::endl;
+ std::cout << "4: asymmetric key" << std::endl;
+ std::cout << "8: signed asymmetric key (aka certificate)" << std::endl;
+ std::cout << "16: PIN /password" << std::endl;
+ std::cout << "Your choice: ";
+
+ std::cin >> choice;
+
+ switch (choice){
+ case 1:
+ cred.setCredentialType(choice);
+ choice = 0; //validation of the accepted choice.
+ break;
+ case 2:
+ case 4:
+ case 8:
+ case 16:
+ std::cout << "selected type is not supported yet" << std::endl;
+ break;
+ default:
+ std::cout << "Error! Please select valid credential type" << std::endl;
+ break;
+ }
+ } while(0 != choice);
+
+ std::cout << "Please enter key size (valid size is 128 or 256) :";
+ std::cin >> choice;
+
+ if(128 == choice)
+ {
+ cred.setCredentialKeySize(OWNER_PSK_LENGTH_128);
+ }
+ else if(256 == choice)
+ {
+ cred.setCredentialKeySize(OWNER_PSK_LENGTH_256);
+ }
+ else
+ {
+ std::cout << "Error! Please enter valid key size!" << std::endl;
+ return -2;
+ }
+
+ return 0;
+}
+
+int main(void)
+{
+ OCPersistentStorage ps {client_open, fread, fwrite, fclose, unlink };
+
+ // Create PlatformConfig object
+ PlatformConfig cfg {
+ OC::ServiceType::InProc,
+ OC::ModeType::Both,
+ "0.0.0.0",
+ 0,
+ OC::QualityOfService::LowQos,
+ &ps
+ };
+
+ OCPlatform::Configure(cfg);
+
+ try
+ {
+ int choice;
+ if (OCSecure::provisionInit("") != OC_STACK_OK)
+ {
+ std::cout <<"PM Init failed"<< std::endl;
+ //return 1;
+ }
+
+ for (int out = 0; !out;)
+ {
+ while (!ask)
+ {
+ sleep(1);
+ }
+ printMenu();
+ std::cin >> choice;
+ switch(choice) {
+ case 1:
+ {
+ //Secure resource discovery.
+
+ pUnownedDevList.clear();
+ std::cout << "Started discovery..." <<std::endl;
+ OCStackResult result = OCSecure::discoverUnownedDevices(DISCOVERY_TIMEOUT,
+ pUnownedDevList);
+ if (result != OC_STACK_OK)
+ {
+ std::cout<< "!!Error - UnOwned Discovery failed."<<std::endl;
+ }
+ else if (pUnownedDevList.size())
+ {
+ std::cout <<"Found secure devices, count = " <<
+ pUnownedDevList.size() << std::endl;
+ printDevices(pUnownedDevList);
+ }
+ else
+ {
+ std::cout <<"No Secure devices found"<<std::endl;
+ }
+ break;
+ }
+ case 2:
+ {
+ pOwnedDevList.clear();
+ std::cout << "Started discovery..." <<std::endl;
+ OCStackResult result = OCSecure::discoverOwnedDevices(DISCOVERY_TIMEOUT,
+ pOwnedDevList);
+ if (result != OC_STACK_OK)
+ {
+ std::cout<< "!!Error - Owned Discovery failed."<<std::endl;
+ }
+ else if (pOwnedDevList.size())
+ {
+ std::cout <<"Found owned devices, count = " <<
+ pOwnedDevList.size() << std::endl;
+ printDevices(pOwnedDevList);
+ }
+ else
+ {
+ std::cout <<"No Secure devices found"<<std::endl;
+ }
+ break;
+ }
+ case 3:
+ {
+ unsigned int devNum;
+
+ if (!pUnownedDevList.size())
+ {
+ std::cout <<"There are no more Unowned devices"<<std::endl;
+ break;
+ }
+
+ for (unsigned int i = 0; i < pUnownedDevList.size(); i++ )
+ {
+ std::cout << i+1 << ": "<< pUnownedDevList[i]->getDeviceID();
+ std::cout << " From IP:" << pUnownedDevList[i]->getDevAddr() <<std::endl;
+ }
+
+ std::cout <<"Select device number: "<<std::endl;
+ std::cin >> devNum;
+ if (devNum > pUnownedDevList.size())
+ {
+ std::cout <<"Invalid device number"<<std::endl;
+ break;
+ }
+ transferDevIdx = devNum - 1;
+
+ //register callbacks for JUST WORKS and PIN methods
+ std::cout <<"Registering OTM Methods: 1. JUST WORKS and 2. PIN"<<std::endl;
+
+ {
+ OTMCallbackData_t justWorksCBData;
+ justWorksCBData.loadSecretCB = LoadSecretJustWorksCallback;
+ justWorksCBData.createSecureSessionCB =
+ CreateSecureSessionJustWorksCallback;
+ justWorksCBData.createSelectOxmPayloadCB =
+ CreateJustWorksSelectOxmPayload;
+ justWorksCBData.createOwnerTransferPayloadCB =
+ CreateJustWorksOwnerTransferPayload;
+ OCSecure::setOwnerTransferCallbackData(OIC_JUST_WORKS,
+ &justWorksCBData, NULL);
+ }
+
+ {
+ OTMCallbackData_t pinBasedCBData;
+ pinBasedCBData.loadSecretCB = InputPinCodeCallback;
+ pinBasedCBData.createSecureSessionCB =
+ CreateSecureSessionRandomPinCallbak;
+ pinBasedCBData.createSelectOxmPayloadCB =
+ CreatePinBasedSelectOxmPayload;
+ pinBasedCBData.createOwnerTransferPayloadCB =
+ CreatePinBasedOwnerTransferPayload;
+ OCSecure::setOwnerTransferCallbackData(OIC_RANDOM_DEVICE_PIN,
+ &pinBasedCBData, InputPinCB);
+ }
+
+ ask = 0;
+ std::cout << "Transfering ownership for : "<<
+ pUnownedDevList[devNum-1]->getDeviceID()<<std::endl;
+ if (pUnownedDevList[devNum-1]->doOwnershipTransfer(ownershipTransferCB)
+ != OC_STACK_OK)
+ {
+ std::cout<<"OwnershipTransferCallback is failed"<<std::endl;
+ ask = 1;
+ }
+ break;
+ }
+ case 4: //Provision ACL
+ {
+ int index;
+
+ if (0 != readDeviceNumber(pOwnedDevList, 1, &index)) break;
+
+ std::cout << "Provision ACL for : "<<
+ pOwnedDevList[index]->getDeviceID()<< std::endl;
+
+ OicSecAcl_t acl = defaultAcl;
+
+ std::cout << "Please input ACL for selected device: " << std::endl;
+ if (0 != InputACL(&acl))
+ {
+ deleteACL(&acl);
+ break;
+ }
+
+ ask = 0;
+
+ if (pOwnedDevList[index]->provisionACL(&acl, provisionCB) != OC_STACK_OK)
+ {
+ ask = 1;
+ std::cout <<"provisionACL is failed"<< std::endl;
+ }
+ deleteACL(&acl);
+ }
+ break;
+ case 5: //Provision Credentials
+ {
+ int devices[2];
+
+ if (0 != readDeviceNumber(pOwnedDevList, 2, devices)) break;
+
+ int first = devices[0];
+ int second = devices[1];
+
+ std::cout << "Provision Credentials to devices: "<<
+ pOwnedDevList[first]->getDeviceID();
+ std::cout << " and "<< pOwnedDevList[second]->getDeviceID() << std::endl;
+
+ Credential cred(0,0);
+ std::cout << "Please input credentials for selected devices: " << std::endl;
+ if (0 != InputCredentials(cred))
+ break;
+
+ ask = 0;
+
+ if (pOwnedDevList[first]->provisionCredentials(cred,
+ *pOwnedDevList[second].get(), provisionCB) != OC_STACK_OK)
+ {
+ ask = 1;
+ std::cout <<"provisionCredentials is failed"<< std::endl;
+ }
+ }
+ break;
+ case 6: //Provision ACL & Creds b/w two devices.
+ {
+ int devices[2];
+
+ if (0 != readDeviceNumber(pOwnedDevList, 2, devices)) break;
+
+ int first = devices[0];
+ int second = devices[1];
+
+ std::cout << "Provision pairwise devices: "<<
+ pOwnedDevList[first]->getDeviceID();
+ std::cout << " and "<< pOwnedDevList[second]->getDeviceID() << std::endl;
+
+ Credential cred(0,0);
+ std::cout << "Please input credentials for selected devices: " << std::endl;
+ if (0 != InputCredentials(cred))
+ break;
+
+ OicSecAcl_t acl1 = defaultAcl;
+
+ std::cout << "Please input ACL for selected device: " << std::endl;
+ if (0 != InputACL(&acl1))
+ {
+ deleteACL(&acl1);
+ break;
+ }
+
+ OicSecAcl_t acl2 = defaultAcl;
+
+ std::cout << "Please input ACL for selected device: " << std::endl;
+ if (0 != InputACL(&acl2))
+ {
+ deleteACL(&acl2);
+ break;
+ }
+
+ ask = 0;
+
+ if (pOwnedDevList[first]->provisionPairwiseDevices(cred, &acl1,
+ *pOwnedDevList[second].get(), &acl2, provisionCB) != OC_STACK_OK)
+ {
+ ask = 1;
+ std::cout <<"provisionPairwiseDevices is failed"<< std::endl;
+ }
+ deleteACL(&acl1);
+ deleteACL(&acl2);
+ }
+ break;
+ case 7: //Unlink Devices
+ {
+ int devices[2];
+
+ if (0 != readDeviceNumber(pOwnedDevList, 2, devices)) break;
+
+ int first = devices[0];
+ int second = devices[1];
+
+ std::cout << "Unlink devices: "<< pOwnedDevList[first]->getDeviceID();
+ std::cout << " and "<< pOwnedDevList[second]->getDeviceID() << std::endl;
+
+ ask = 0;
+
+ if (pOwnedDevList[first]->unlinkDevices(*pOwnedDevList[second].get(),
+ provisionCB) != OC_STACK_OK)
+ {
+ ask = 1;
+ std::cout <<"removeDevice is failed"<< std::endl;
+ }
+ break;
+ }
+ case 8: //Remove Device
+ {
+ int index;
+
+ if (0 != readDeviceNumber(pOwnedDevList, 1, &index)) break;
+
+ std::cout << "Remove Device: "<< pOwnedDevList[index]->getDeviceID()<< std::endl;
+
+ ask = 0;
+
+ if (pOwnedDevList[index]->removeDevice(provisionCB) != OC_STACK_OK)
+ {
+ ask = 1;
+ std::cout <<"removeDevice is failed"<< std::endl;
+ }
+ break;
+ }
+ case 9: //Get Linked devices
+ {
+ UuidList_t linkedUuid;
+ unsigned int devNum;
+
+ if (!pOwnedDevList.size())
+ {
+ std::cout <<"There are no Owned devices yet,"
+ " may need to discover"<<std::endl;
+ break;
+ }
+
+ for (unsigned int i = 0; i < pOwnedDevList.size(); i++ )
+ {
+ std::cout << i+1 << ": "<< pOwnedDevList[i]->getDeviceID() <<" From IP:";
+ std::cout << pOwnedDevList[i]->getDevAddr() <<std::endl;
+ }
+
+ std::cout <<"Select device number: "<<std::endl;
+ std::cin >> devNum;
+ if (devNum > pOwnedDevList.size())
+ {
+ std::cout <<"Invalid device number"<<std::endl;
+ break;
+ }
+
+ if(pOwnedDevList[devNum -1]->getLinkedDevices(linkedUuid) == OC_STACK_OK)
+ {
+ if (!linkedUuid.size())
+ {
+ std::cout <<"No devices are linked to "<<
+ pOwnedDevList[devNum -1]->getDeviceID() << std::endl;
+ }
+ //display the Linked devices (UUIDs)
+ for(unsigned int i = 0; i < linkedUuid.size(); i++)
+ {
+ printUuid(linkedUuid[i]);
+ }
+ }
+ else
+ {
+ std::cout <<"Error! in getLinkedDevices"<<std::endl;
+ }
+ break;
+ }
+ case 10: //Get device' status
+ {
+ DeviceList_t unownedList, ownedList;
+
+ if (OCSecure::getDevInfoFromNetwork(DISCOVERY_TIMEOUT, ownedList,
+ unownedList) == OC_STACK_OK)
+ {
+ std::cout <<"Owned Device' status for" <<std::endl;
+ for (unsigned int i = 0; i < ownedList.size(); i++ )
+ {
+ std::cout << "Device "<<i+1 <<" ID: '";
+ std::cout << ownedList[i]->getDeviceID() << "' From IP: ";
+ std::cout << ownedList[i]->getDevAddr() << " Status: ";
+ printStatus(ownedList[i]->getDeviceStatus());
+ }
+ std::cout <<"\nUnOwned Device' status for" <<std::endl;
+ for (unsigned int i = 0; i < unownedList.size(); i++ )
+ {
+ std::cout << "Device "<<i+1 <<" ID: '";
+ std::cout << unownedList[i]->getDeviceID() << "' From IP: ";
+ std::cout << unownedList[i]->getDevAddr() << " Status: ";
+ printStatus(unownedList[i]->getDeviceStatus());
+ }
+
+ }
+ break;
+ }
+
+ case 11:
+ default:
+ out = 1;
+ break;
+ }
+ }
+ }
+ catch(OCException& e)
+ {
+ oclog() << "Exception in main: "<<e.what();
+ }
+
+ return 0;
+}
--- /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 "ocstack.h"
+#include "base64.h"
+#include "OCProvisioningManager.h"
+
+namespace OC
+{
+ OCStackResult OCSecure::provisionInit(const std::string& dbPath)
+ {
+ OCStackResult result;
+ auto cLock = OCPlatform_impl::Instance().csdkLock().lock();
+
+ if(cLock)
+ {
+ std::lock_guard<std::recursive_mutex> lock(*cLock);
+ result = OCInitPM(dbPath.c_str());
+ }
+ else
+ {
+ oclog() <<"Mutex not found";
+ result = OC_STACK_ERROR;
+ }
+
+ return result;
+ }
+
+ OCStackResult OCSecure::discoverUnownedDevices(unsigned short timeout,
+ DeviceList_t &list)
+ {
+ OCStackResult result;
+ OCProvisionDev_t *pDevList = nullptr, *pCurDev = nullptr, *tmp = nullptr;
+ auto csdkLock = OCPlatform_impl::Instance().csdkLock();
+ auto cLock = csdkLock.lock();
+
+ if(cLock)
+ {
+ std::lock_guard<std::recursive_mutex> lock(*cLock);
+ result = OCDiscoverUnownedDevices(timeout, &pDevList);
+ if (result == OC_STACK_OK)
+ {
+ // Create DeviceList of OCSecureResource's
+ pCurDev = pDevList;
+ while (pCurDev)
+ {
+ tmp = pCurDev;
+ list.push_back(std::shared_ptr<OCSecureResource>(
+ new OCSecureResource(csdkLock, pCurDev)));
+ pCurDev = pCurDev->next;
+ tmp->next = nullptr;
+ }
+ }
+ else
+ {
+ oclog() <<"Unowned device discovery failed!";
+ }
+ }
+ else
+ {
+ oclog() <<"Mutex not found";
+ result = OC_STACK_ERROR;
+ }
+
+ return result;
+ }
+
+ OCStackResult OCSecure::discoverOwnedDevices(unsigned short timeout,
+ DeviceList_t &list)
+ {
+ OCStackResult result;
+ OCProvisionDev_t *pDevList = nullptr, *pCurDev = nullptr, *tmp = nullptr;
+ auto csdkLock = OCPlatform_impl::Instance().csdkLock();
+ auto cLock = csdkLock.lock();
+
+ if(cLock)
+ {
+ std::lock_guard<std::recursive_mutex> lock(*cLock);
+ result = OCDiscoverOwnedDevices(timeout, &pDevList);
+ if (result == OC_STACK_OK)
+ {
+ pCurDev = pDevList;
+ while (pCurDev)
+ {
+ tmp = pCurDev;
+ list.push_back(std::shared_ptr<OCSecureResource>(
+ new OCSecureResource(csdkLock, pCurDev)));
+ pCurDev = pCurDev->next;
+ tmp->next = nullptr;
+ }
+ }
+ else
+ {
+ oclog() <<"Owned device discovery failed!";
+ }
+ }
+ else
+ {
+ oclog() <<"Mutex not found";
+ result = OC_STACK_ERROR;
+ }
+
+ return result;
+ }
+
+ OCStackResult OCSecure::setOwnerTransferCallbackData(OicSecOxm_t oxm,
+ OTMCallbackData_t* callbackData, InputPinCallback inputPin)
+ {
+ if(NULL == callbackData || oxm >= OIC_OXM_COUNT)
+ {
+ oclog() <<"Invalid callbackData or OXM type";
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ if((OIC_RANDOM_DEVICE_PIN == oxm) && !inputPin)
+ {
+ oclog() <<"for OXM type DEVICE_PIN, inputPin callback can't be null";
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ OCStackResult result;
+ auto cLock = OCPlatform_impl::Instance().csdkLock().lock();
+
+ if(cLock)
+ {
+ std::lock_guard<std::recursive_mutex> lock(*cLock);
+ result = OCSetOwnerTransferCallbackData(oxm, callbackData);
+ if(result == OC_STACK_OK && (OIC_RANDOM_DEVICE_PIN & oxm))
+ {
+ SetInputPinCB(inputPin);
+ }
+ }
+ else
+ {
+ oclog() <<"Mutex not found";
+ result = OC_STACK_ERROR;
+ }
+
+ return result;
+
+ }
+
+ OCStackResult OCSecure::getDevInfoFromNetwork(unsigned short timeout,
+ DeviceList_t &ownedDevList,
+ DeviceList_t &unownedDevList)
+ {
+ OCStackResult result = OC_STACK_OK;
+ OCProvisionDev_t *owned = nullptr, *unowned = nullptr, *tmp = nullptr, *dev = nullptr;
+ auto csdkLock = OCPlatform_impl::Instance().csdkLock();
+ auto cLock = csdkLock.lock();
+
+ if(cLock)
+ {
+ std::lock_guard<std::recursive_mutex> lock(*cLock);
+//TODO: this change is dependent on changesets #2333, 2316. Once these are merged, this code will be
+// updated
+
+// result = OCGetDevInfoFromNetwork(nullptr, timeout, &owned, &unowned);
+
+ if (result == OC_STACK_OK)
+ {
+ dev = owned;
+ while (dev)
+ {
+ tmp = dev;
+ ownedDevList.push_back(std::shared_ptr<OCSecureResource>(
+ new OCSecureResource(csdkLock, dev)));
+ dev = dev->next;
+ tmp->next = nullptr;
+ }
+
+ dev = unowned;
+ while (dev)
+ {
+ tmp = dev;
+ unownedDevList.push_back(std::shared_ptr<OCSecureResource>(
+ new OCSecureResource(csdkLock, dev)));
+ dev = dev->next;
+ tmp->next = nullptr;
+ }
+ }
+ }
+ else
+ {
+ oclog() <<"Mutex not found";
+ result = OC_STACK_ERROR;
+ }
+
+ return result;
+ }
+
+ void OCSecureResource::callbackWrapper(void* ctx, int nOfRes, OCProvisionResult_t *arr, bool hasError)
+ {
+ PMResultList_t *results = nullptr;
+ ProvisionContext* context = static_cast<ProvisionContext*>(ctx);
+
+ results = new PMResultList_t;
+ for (int i = 0; i < nOfRes; i++)
+ {
+ results->push_back(arr[i]);
+ }
+
+ std::thread exec(context->callback, results, hasError);
+ exec.detach();
+
+ delete context;
+ }
+
+ OCSecureResource::OCSecureResource(): m_csdkLock(std::weak_ptr<std::recursive_mutex>()),
+ devPtr(nullptr)
+ {
+ }
+
+ OCSecureResource::OCSecureResource(std::weak_ptr<std::recursive_mutex> csdkLock,
+ OCProvisionDev_t *dPtr)
+ :m_csdkLock(csdkLock), devPtr(dPtr)
+ {
+ }
+
+ OCSecureResource::~OCSecureResource()
+ {
+ if(devPtr)
+ {
+ OCDeleteDiscoveredDevices(devPtr);
+ }
+ }
+
+ OCStackResult OCSecureResource::doOwnershipTransfer(ResultCallBack resultCallback)
+ {
+ if(!resultCallback)
+ {
+ oclog() <<"Result callback can't be null";
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ OCStackResult result;
+ auto cLock = m_csdkLock.lock();
+
+ if(cLock)
+ {
+ ProvisionContext* context = new ProvisionContext(resultCallback);
+
+ std::lock_guard<std::recursive_mutex> lock(*cLock);
+ result = OCDoOwnershipTransfer(static_cast<void*>(context),
+ devPtr, &OCSecureResource::callbackWrapper);
+ }
+ else
+ {
+ oclog() <<"Mutex not found";
+ result = OC_STACK_ERROR;
+ }
+ return result;
+ }
+
+ OCStackResult OCSecureResource::provisionACL( const OicSecAcl_t* acl,
+ ResultCallBack resultCallback)
+ {
+ if(!resultCallback || !acl)
+ {
+ oclog() <<"Result callback or ACL can't be null";
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ OCStackResult result;
+ auto cLock = m_csdkLock.lock();
+
+ if(cLock)
+ {
+ ProvisionContext* context = new ProvisionContext(resultCallback);
+
+ std::lock_guard<std::recursive_mutex> lock(*cLock);
+ result = OCProvisionACL(static_cast<void*>(context),
+ devPtr, const_cast<OicSecAcl_t*>(acl),
+ &OCSecureResource::callbackWrapper);
+ }
+ else
+ {
+ oclog() <<"Mutex not found";
+ result = OC_STACK_ERROR;
+ }
+ return result;
+ }
+
+ OCStackResult OCSecureResource::provisionCredentials(const Credential &cred,
+ const OCSecureResource &device2, ResultCallBack resultCallback)
+ {
+ if(!resultCallback)
+ {
+ oclog() << "Result calback can't be null";
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ OCStackResult result;
+ auto cLock = m_csdkLock.lock();
+
+ if(cLock)
+ {
+ ProvisionContext* context = new ProvisionContext(resultCallback);
+
+ std::lock_guard<std::recursive_mutex> lock(*cLock);
+ result = OCProvisionCredentials(static_cast<void*>(context),
+ cred.getCredentialType(),
+ cred.getCredentialKeySize(),
+ devPtr, device2.getDevPtr(),
+ &OCSecureResource::callbackWrapper);
+ }
+ else
+ {
+ oclog() <<"Mutex not found";
+ result = OC_STACK_ERROR;
+ }
+ return result;
+ }
+
+ OCStackResult OCSecureResource::provisionPairwiseDevices(const Credential &cred,
+ const OicSecAcl_t* acl1, const OCSecureResource &device2, const OicSecAcl_t* acl2,
+ ResultCallBack resultCallback)
+ {
+ if(!resultCallback)
+ {
+ oclog() << "Result calback can't be null";
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ OCStackResult result;
+ auto cLock = m_csdkLock.lock();
+
+ if(cLock)
+ {
+ ProvisionContext* context = new ProvisionContext(resultCallback);
+
+ std::lock_guard<std::recursive_mutex> lock(*cLock);
+ result = OCProvisionPairwiseDevices(static_cast<void*>(context),
+ cred.getCredentialType(),
+ cred.getCredentialKeySize(),
+ devPtr, const_cast<OicSecAcl_t*>(acl1),
+ device2.getDevPtr(), const_cast<OicSecAcl_t*>(acl2),
+ &OCSecureResource::callbackWrapper);
+ }
+ else
+ {
+ oclog() <<"Mutex not found";
+ result = OC_STACK_ERROR;
+ }
+ return result;
+ }
+
+ OCStackResult OCSecureResource::unlinkDevices(const OCSecureResource &device2,
+ ResultCallBack resultCallback)
+ {
+ if(!resultCallback)
+ {
+ oclog() << "Result calback can't be null";
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ OCStackResult result;
+ auto cLock = m_csdkLock.lock();
+
+ if(cLock)
+ {
+ ProvisionContext* context = new ProvisionContext(resultCallback);
+
+ std::lock_guard<std::recursive_mutex> lock(*cLock);
+//TODO: this change is dependent on changesets #2344. Once these are merged, this code will be
+// updated
+
+// result = OCUnlinkDevices(static_cast<void*>(context),
+// devPtr, device2.getDevPtr(), &OCSecureResource::callbackWrapper);
+ }
+ else
+ {
+ oclog() <<"Mutex not found";
+ result = OC_STACK_ERROR;
+ }
+ return result;
+ }
+
+ OCStackResult OCSecureResource::removeDevice(ResultCallBack resultCallback)
+ {
+ if(!resultCallback)
+ {
+ oclog() << "Result calback can't be null";
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ OCStackResult result;
+ auto cLock = m_csdkLock.lock();
+
+ if(cLock)
+ {
+ ProvisionContext* context = new ProvisionContext(resultCallback);
+
+ std::lock_guard<std::recursive_mutex> lock(*cLock);
+//TODO: this change is dependent on changesets #2344. Once these are merged, this code will be
+// updated
+
+// result = OCRemoveDevice(static_cast<void*>(context),
+// devPtr, &OCSecureResource::callbackWrapper);
+ }
+ else
+ {
+ oclog() <<"Mutex not found";
+ result = OC_STACK_ERROR;
+ }
+ return result;
+ }
+
+ OCStackResult OCSecureResource::getLinkedDevices(UuidList_t &uuidList)
+ {
+ OCStackResult result;
+ size_t numOfDevices = -1;
+ auto devUuid = devPtr->doxm->deviceID;
+ auto cLock = m_csdkLock.lock();
+
+ if(cLock)
+ {
+ std::lock_guard<std::recursive_mutex> lock(*cLock);
+//TODO: this change is dependent on changesets #2333, 2316. Once these are merged, this code will be
+// updated
+
+#if CHANGESET_2316
+ OicUuidList* linkedDevs = nullptr, *tmp = nullptr;
+ result = OCGetLinkedStatus(&devUuid, &linkedDevs, &numOfDevices);
+ if (result == OC_STACK_OK)
+ {
+ for (tmp = linkedDevs; tmp; tmp = tmp->next)
+ {
+ uuidList.push_back(tmp->dev);
+ }
+ OCDeleteUuidList(&linkedDevs);
+ }
+#endif
+ }
+ else
+ {
+ oclog() <<"Mutex not found";
+ result = OC_STACK_ERROR;
+ }
+ return result;
+ }
+
+ std::string OCSecureResource::getDeviceID()
+ {
+ char base64Buff[B64ENCODE_OUT_SAFESIZE(sizeof(((OicUuid_t*)0)->id)) + 1] = {0,};
+ uint32_t outLen = 0;
+ B64Result b64Ret = B64_OK;
+ std::ostringstream deviceId("");
+
+ validateSecureResource();
+ b64Ret = b64Encode(devPtr->doxm->deviceID.id, sizeof(devPtr->doxm->deviceID.id), base64Buff,
+ sizeof(base64Buff), &outLen);
+
+ deviceId << base64Buff;
+ return deviceId.str();
+ }
+
+ OCProvisionDev_t* OCSecureResource::getDevPtr() const
+ {
+ return devPtr;
+ }
+
+ std::string OCSecureResource::getDevAddr()
+ {
+ validateSecureResource();
+ std::string ipAddr(devPtr->endpoint.addr);
+ return ipAddr;
+ }
+
+ int OCSecureResource::getDeviceStatus()
+ {
+ validateSecureResource();
+//TODO: this change is dependent on changesets #2333, 2316. Once these are merged, this code will be
+// updated
+// return (int)devPtr->devStatus;
+ return 0;
+ }
+
+ bool OCSecureResource::getOwnedStatus()
+ {
+ validateSecureResource();
+ return devPtr->doxm->owned;
+ }
+
+ void OCSecureResource::validateSecureResource()
+ {
+ if (!devPtr)
+ {
+ throw OCException("Incomplete secure resource", OC_STACK_RESOURCE_ERROR);
+ }
+ }
+}
--- /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 <ocprovisioningmanager.h>
+#include <OCApi.h>
+#include <OCPlatform_impl.h>
+#include <oxmjustworks.h>
+#include <oxmrandompin.h>
+#include <OCProvisioningManager.h>
+#include <gtest/gtest.h>
+
+#define TIMEOUT 5
+
+namespace OCProvisioningTest
+{
+ using namespace OC;
+
+ static OicSecAcl_t defaultAcl =
+ { {},
+ 1,
+ NULL,
+ 0x001F,
+ 0,
+ NULL,
+ NULL,
+ 1,
+ NULL,
+ NULL,
+ };
+
+ void resultCallback(PMResultList_t *result, int hasError)
+ {
+ }
+
+ TEST(ProvisionInitTest, TestWithEmptyPath)
+ {
+ std::string dbPath("");
+ EXPECT_EQ(OC_STACK_OK, OCSecure::provisionInit(dbPath));
+ }
+
+ TEST(ProvisionInitTest, TestValidPath)
+ {
+ std::string dbPath("./dbPath");
+ EXPECT_EQ(OC_STACK_OK, OCSecure::provisionInit(dbPath));
+ }
+
+ TEST(DiscoveryTest, UnownedDevices)
+ {
+ DeviceList_t list;
+ EXPECT_EQ(OC_STACK_OK, OCSecure::discoverUnownedDevices(TIMEOUT, list));
+ }
+
+ TEST(DiscoveryTest, UnownedDevicesZeroTimeout)
+ {
+ DeviceList_t list;
+ EXPECT_EQ(OC_STACK_OK, OCSecure::discoverUnownedDevices(0, list));
+ }
+
+ TEST(DiscoveryTest, OwnedDevices)
+ {
+ DeviceList_t list;
+ EXPECT_EQ(OC_STACK_OK, OCSecure::discoverOwnedDevices(TIMEOUT, list));
+ }
+
+ TEST(DiscoveryTest, OwnedDevicesZeroTimeout)
+ {
+ DeviceList_t list;
+ EXPECT_EQ(OC_STACK_OK, OCSecure::discoverOwnedDevices(0, list));
+ }
+
+ TEST(OwnershipTest, SetOwnershipTransferCBDataNull)
+ {
+ EXPECT_EQ(OC_STACK_INVALID_PARAM, OCSecure::setOwnerTransferCallbackData(
+ OIC_JUST_WORKS, NULL, NULL));
+ }
+
+ TEST(OwnershipTest, SetOwnershipTransferCBData)
+ {
+ OTMCallbackData_t justWorksCBData;
+ justWorksCBData.loadSecretCB = LoadSecretJustWorksCallback;
+ justWorksCBData.createSecureSessionCB = CreateSecureSessionJustWorksCallback;
+ justWorksCBData.createSelectOxmPayloadCB = CreateJustWorksSelectOxmPayload;
+ justWorksCBData.createOwnerTransferPayloadCB = CreateJustWorksOwnerTransferPayload;
+ EXPECT_EQ(OC_STACK_OK, OCSecure::setOwnerTransferCallbackData(OIC_JUST_WORKS,
+ &justWorksCBData, NULL));
+ }
+
+ TEST(OwnershipTest, SetOwnershipTransferCBDataInvalidType)
+ {
+ OTMCallbackData_t justWorksCBData;
+ justWorksCBData.loadSecretCB = LoadSecretJustWorksCallback;
+ justWorksCBData.createSecureSessionCB = CreateSecureSessionJustWorksCallback;
+ justWorksCBData.createSelectOxmPayloadCB = CreateJustWorksSelectOxmPayload;
+ justWorksCBData.createOwnerTransferPayloadCB = CreateJustWorksOwnerTransferPayload;
+ EXPECT_EQ(OC_STACK_INVALID_PARAM, OCSecure::setOwnerTransferCallbackData(OIC_OXM_COUNT,
+ &justWorksCBData, NULL));
+ }
+
+ TEST(OwnershipTest, SetOwnershipTransferCBDataNullInputPin)
+ {
+ OTMCallbackData_t pinBasedCBData;
+ pinBasedCBData.loadSecretCB = InputPinCodeCallback;
+ pinBasedCBData.createSecureSessionCB = CreateSecureSessionRandomPinCallbak;
+ pinBasedCBData.createSelectOxmPayloadCB = CreatePinBasedSelectOxmPayload;
+ pinBasedCBData.createOwnerTransferPayloadCB = CreatePinBasedOwnerTransferPayload;
+ OTMSetOwnershipTransferCallbackData(OIC_RANDOM_DEVICE_PIN, &pinBasedCBData);
+
+ EXPECT_EQ(OC_STACK_INVALID_PARAM, OCSecure::setOwnerTransferCallbackData(
+ OIC_RANDOM_DEVICE_PIN, &pinBasedCBData, NULL));
+ }
+
+ TEST(OwnershipTest, OwnershipTransferNullCallback)
+ {
+ OCSecureResource device;
+ EXPECT_EQ(OC_STACK_INVALID_PARAM, device.doOwnershipTransfer(nullptr));
+ }
+
+ TEST(DeviceInfoTest, DevInfoFromNetwork)
+ {
+ DeviceList_t owned, unowned;
+ EXPECT_EQ(OC_STACK_OK, OCSecure::getDevInfoFromNetwork(TIMEOUT,
+ owned, unowned));
+ }
+
+ TEST(ProvisionAclTest, ProvisionAclTestNullAcl)
+ {
+ OCSecureResource device;
+ EXPECT_EQ(OC_STACK_INVALID_PARAM, device.provisionACL(nullptr, resultCallback));
+ }
+
+ TEST(ProvisionAclTest, ProvisionAclTestNullCallback)
+ {
+ OCSecureResource device;
+ OicSecAcl_t acl = defaultAcl;
+ EXPECT_EQ(OC_STACK_INVALID_PARAM, device.provisionACL(&acl, nullptr));
+ }
+
+ TEST(ProvisionAclTest, ProvisionAclTestNullCallbackNUllAcl)
+ {
+ OCSecureResource device;
+ EXPECT_EQ(OC_STACK_INVALID_PARAM, device.provisionACL(nullptr, nullptr));
+ }
+
+ TEST(ProvisionCredTest, ProvisionCredTestNullCallback)
+ {
+ OCSecureResource device, dev2;
+ Credential cred;
+ EXPECT_EQ(OC_STACK_INVALID_PARAM, device.provisionCredentials(cred, dev2, nullptr));
+ }
+
+ TEST(ProvisionPairwiseTest, ProvisionPairwiseTestNullCallback)
+ {
+ OCSecureResource device, dev2;
+ Credential cred;
+ OicSecAcl_t acl1 = defaultAcl, acl2 = defaultAcl;
+ EXPECT_EQ(OC_STACK_INVALID_PARAM, device.provisionPairwiseDevices(cred, &acl1,
+ dev2, &acl2, nullptr));
+ }
+
+}
--- /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.
+#
+#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+Import('env')
+import os
+import os.path
+provisiontests_env = env.Clone()
+
+src_dir = provisiontests_env.get('SRC_DIR')
+######################################################################
+# Build flags
+######################################################################
+provisiontests_env.PrependUnique(CPPPATH = [
+ '../../include',
+ '../../oc_logger/include',
+ '../../csdk/stack/include',
+ '../../csdk/security/include',
+ '../../csdk/security/provisioning/include',
+ '../../csdk/security/provisioning/include/oxm',
+ '../../csdk/security/provisioning/include/internal',
+ '../../csdk/stack/include/internal',
+ '../../csdk/connectivity/api',
+ '../../csdk/connectivity/external/inc',
+ '../../csdk/ocsocket/include',
+ '../../csdk/ocrandom/include',
+ '../../csdk/logger/include',
+ '../../../extlibs/gtest/gtest-1.7.0/include',
+ '../../../extlibs/hippomocks-master/HippoMocks',
+ '../../../extlibs/hippomocks-master/HippoMocksTest'
+ ])
+
+provisiontests_env.AppendUnique(CXXFLAGS = ['-std=c++0x', '-Wall', '-pthread'])
+provisiontests_env.AppendUnique(LIBS = ['-lpthread'])
+provisiontests_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')])
+provisiontests_env.AppendUnique(LIBPATH = [src_dir + '/extlibs/gtest/gtest-1.7.0/lib/.libs'])
+provisiontests_env.PrependUnique(LIBS = [
+ 'ocprovision',
+ 'oc',
+ 'ocpmapi',
+ 'octbstack',
+ 'oc_logger',
+ 'connectivity_abstraction',
+ 'coap',
+ 'gtest',
+ 'gtest_main',
+ ])
+
+if env.get('SECURED') == '1':
+ provisiontests_env.AppendUnique(LIBS = ['tinydtls'])
+
+if env.get('LOGGING'):
+ provisiontests_env.AppendUnique(CPPDEFINES = ['TB_LOG'])
+
+######################################################################
+# Source files and Targets
+######################################################################
+unittests = provisiontests_env.Program('provisiontests', ['OCProvisioningTest.cpp'])
+
+Alias("provisiontests", [unittests])
+
+env.AppendTarget('provisiontests')
+if env.get('TEST') == '1':
+ target_os = env.get('TARGET_OS')
+ if target_os == 'linux':
+ out_dir = env.get('BUILD_DIR')
+ result_dir = env.get('BUILD_DIR') + '/test_out/'
+ if not os.path.isdir(result_dir):
+ os.makedirs(result_dir)
+ provisiontests_env.AppendENVPath('GTEST_OUTPUT', ['xml:'+ result_dir])
+ provisiontests_env.AppendENVPath('LD_LIBRARY_PATH', [out_dir])
+ provisiontests_env.AppendENVPath('LD_LIBRARY_PATH', ['./extlibs/gtest/gtest-1.7.0/lib/.libs'])
+ ut = provisiontests_env.Command ('ut', None, out_dir + 'resource/provisioning/unittests/provisiontests')
+ AlwaysBuild ('ut')
+
+src_dir = provisiontests_env.get('SRC_DIR')
+svr_db_src_dir = src_dir + '/resource/provisioning/examples/'
+svr_db_build_dir = env.get('BUILD_DIR') +'/resource/provisioning/unittests/'
+provisiontests_env.Alias("install", provisiontests_env.Install( svr_db_build_dir,
+ svr_db_src_dir + 'oic_svr_db_client.json'))
return checked_guard(m_server, &IServerWrapper::sendResponse,
pResponse);
}
+
+ std::weak_ptr<std::recursive_mutex> OCPlatform_impl::csdkLock()
+ {
+ return m_csdkLock;
+ }
} //namespace OC
oclib_env.InstallTarget(oclib, 'liboc')
oclib_env.UserInstallTargetLib(oclib, 'liboc')
+if target_os in ['linux', 'android'] and env.get('SECURED') == '1':
+ SConscript('../provisioning/SConscript')
# Build Provisioning API unit test
if env.get('SECURED') == '1':
SConscript('csdk/security/provisioning/unittest/SConscript')
+ SConscript('provisioning/unittests/SConscript')
elif target_os == 'darwin':
# Verify that 'google unit test' library is installed. If not,