From: lankamadan Date: Wed, 9 Dec 2015 02:52:48 +0000 (+0900) Subject: [easysetup] Security feature integration for ownership transfer - Dev In Progress X-Git-Tag: 1.2.0+RC1~597^2^2~26 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=b6d5d3c4d4edd9a3a7b54527e4b0c9ccf4724ae4;p=platform%2Fupstream%2Fiotivity.git [easysetup] Security feature integration for ownership transfer - Dev In Progress - Sconscript modifications for security feature addition - EnrolleeSecurity class for handling security handshake - Modifications to support ownership step before provisioning when the enrollee needs security Change-Id: I26b4fa9a4376691b8bfb42bcb023962337147c0b Signed-off-by: lankamadan Reviewed-on: https://gerrit.iotivity.org/gerrit/4461 Tested-by: jenkins-iotivity Reviewed-by: Uze Choi Tested-by: Uze Choi --- diff --git a/service/easy-setup/SConscript b/service/easy-setup/SConscript old mode 100644 new mode 100755 index 58c498a..0cf11b2 --- a/service/easy-setup/SConscript +++ b/service/easy-setup/SConscript @@ -21,9 +21,11 @@ ###################################################################### # easy-setup project build script ###################################################################### -import os +import os.path Import('env') +easysetup_path = os.curdir + ###################################################################### #building Resource client, resourceBroker and resourceCache ###################################################################### @@ -53,7 +55,7 @@ if target_os not in ['windows', 'winrt']: easy_setup_env.AppendUnique(CXXFLAGS = ['-Wall', '-std=c++0x']) if target_os == 'linux': - easy_setup_env.AppendUnique(LIBS = ['pthread']) + easy_setup_env.AppendUnique(LIBS = ['pthread', 'dl']) if target_os in ['android']: easy_setup_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')]) @@ -68,13 +70,16 @@ if target_os == 'linux': easy_setup_env.AppendUnique(RPATH = [env.get('BUILD_DIR')]) easy_setup_env.AppendUnique(CXXFLAGS = ['-pthread']) easy_setup_env.PrependUnique(LIBS = ['oc', 'octbstack', 'oc_logger', 'pthread', 'connectivity_abstraction']) + if env.get('SECURED') == '1': + easy_setup_env.PrependUnique(LIBS = ['ocprovision', 'ocpmapi']) if target_os == 'arduino': easy_setup_env.AppendUnique(CPPPATH = [ - '../../resource/oc_logger/include', - '../../resource/csdk/logger/include', - '../../resource/csdk/stack/include', - '../../extlibs/cjson', + env.get('SRC_DIR') + '/resource/c_common/oic_malloc/include', + env.get('SRC_DIR') + '/resource/oc_logger/include', + env.get('SRC_DIR') + '/resource/csdk/logger/include', + env.get('SRC_DIR') + '/resource/csdk/stack/include', + env.get('SRC_DIR') + '/extlibs/cjson', 'sdk/enrollee/arduino/wifi', 'sdk/enrollee/api', 'sdk/enrollee/src', @@ -86,13 +91,20 @@ if target_os in ['android','linux']: env.get('SRC_DIR') + '/resource/c_common/oic_malloc/include', env.get('SRC_DIR') + '/resource/include', env.get('SRC_DIR') + '/resource/csdk/logger/include', - env.get('SRC_DIR') + '/resource/csdk/stack/include', - env.get('SRC_DIR') + '/resource/csdk/logger/include', + env.get('SRC_DIR') + '/resource/csdk/stack/include', + env.get('SRC_DIR') + '/resource/csdk/logger/include', env.get('SRC_DIR') + '/resource/csdk/security/include', env.get('SRC_DIR') + '/extlibs/cjson', - '/ser/sdk/common', + env.get('SRC_DIR') + '/extlibs/sqlite3', + '/sdk/common', 'sdk/mediator/include', 'sdk/mediator/src']) + if env.get('SECURED') == '1': + easy_setup_env.AppendUnique(CPPPATH = [ + env.get('SRC_DIR') + '/resource/csdk/security/provisioning/include', + env.get('SRC_DIR') + '/resource/csdk/security/provisioning/include/internal', + env.get('SRC_DIR') + '/resource/csdk/security/provisioning/include/oxm']) + ###################################################################### # Source files and Targets @@ -112,17 +124,29 @@ if target_os == 'android': 'sdk/mediator/src/provisioning.cpp']) easy_setup_env.InstallTarget(es_sdk_shared, 'libESSDK') +print"easysetup_path %s" % easysetup_path + +es_src = None + if target_os == 'linux': - es_sdk_shared = easy_setup_env.SharedLibrary('ESSDKLibrary', - ['sdk/mediator/src/RemoteEnrollee.cpp', - 'sdk/mediator/src/RemoteEnrolleeResource.cpp', - 'sdk/mediator/src/EasySetup.cpp', - 'sdk/mediator/src/prov_adapter.cpp', - 'sdk/mediator/src/ESException.cpp', - 'sdk/mediator/src/wifi_provisioning.cpp', - 'sdk/mediator/src/provisioning.cpp']) + if env.get('SECURED') == '1': + env.AppendUnique(es_src = [os.path.join(easysetup_path, 'sdk/mediator/src/EnrolleeSecurity.cpp')]) + + es_common_src = ['sdk/mediator/src/RemoteEnrollee.cpp', + 'sdk/mediator/src/RemoteEnrolleeResource.cpp', + 'sdk/mediator/src/EasySetup.cpp', + 'sdk/mediator/src/prov_adapter.cpp', + 'sdk/mediator/src/ESException.cpp', + 'sdk/mediator/src/wifi_provisioning.cpp', + 'sdk/mediator/src/provisioning.cpp'] + + env.AppendUnique(es_src = es_common_src) + + es_sdk_shared = easy_setup_env.SharedLibrary('ESSDKLibrary', env.get('es_src')) easy_setup_env.InstallTarget(es_sdk_shared, 'libESSDK') +print "Files path is %s" % env.get('es_src') + #Go to build sample apps SConscript('sampleapp/SConscript') diff --git a/service/easy-setup/sampleapp/mediator/linux/SConscript b/service/easy-setup/sampleapp/mediator/linux/SConscript old mode 100644 new mode 100755 index 1af4df2..9926715 --- a/service/easy-setup/sampleapp/mediator/linux/SConscript +++ b/service/easy-setup/sampleapp/mediator/linux/SConscript @@ -55,6 +55,9 @@ mediator_env.PrependUnique(CPPPATH = [ env.get('SRC_DIR') + '/service/easy-setup/sdk/common']) mediator_env.PrependUnique(LIBS = ['oc', 'octbstack', 'oc_logger', 'pthread', 'connectivity_abstraction', 'coap', 'ESSDKLibrary']) +if env.get('SECURED') == '1': + mediator_env.PrependUnique(LIBS = ['ocpmapi', 'ocprovision']) + mediator = mediator_env.Program('mediator', 'mediator_cpp.cpp') diff --git a/service/easy-setup/sampleapp/mediator/linux/mediator_cpp.cpp b/service/easy-setup/sampleapp/mediator/linux/mediator_cpp.cpp old mode 100644 new mode 100755 index dcc105b..d158084 --- a/service/easy-setup/sampleapp/mediator/linux/mediator_cpp.cpp +++ b/service/easy-setup/sampleapp/mediator/linux/mediator_cpp.cpp @@ -19,6 +19,7 @@ //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= #include +#include #include "oic_string.h" #include "EasySetup.h" @@ -28,6 +29,8 @@ #define ES_SAMPLE_APP_TAG "ES_SAMPLE_APP_TAG" #define DECLARE_MENU(FUNC, ...) { #FUNC, FUNC } +#define JSON_DB_PATH "./oic_svr_db_client.json" + using namespace OC; using namespace OIC::Service; @@ -35,6 +38,8 @@ static EasySetup *easySetupIntance = nullptr; static EnrolleeNWProvInfo netInfo; static RemoteEnrollee::shared_ptr remoteEnrollee = nullptr; +static std::string ipaddress, ssid, pwd; + struct CloseApp { }; @@ -88,20 +93,21 @@ void initEasySetup() easySetupIntance = EasySetup::getInstance(); - std::string ipaddress ("192.168.0.100"); - std::cout << "Enter the target enrollee ipv4 address "; + ipaddress = "192.168.0.150"; + //std::cout << "Enter the target enrollee ipv4 address "; - std::string ssid; - std::cout << "Enter the ssid of the target Enrolleer "; - std:: cin >> ssid; + ssid = "hello"; + //std::cout << "Enter the ssid of the target Enrolleer "; + //std:: cin >> ssid; - std::string pwd; - std::cout << "Enter the pwd of the target Enrolleer "; - std::cin >> pwd; + pwd = "helalalal"; + //std::cout << "Enter the pwd of the target Enrolleer "; + //std::cin >> pwd; netInfo.connType = CT_ADAPTER_IP; netInfo.isSecured = false; + netInfo.needSecuredEasysetup = false; OICStrcpy(netInfo.netAddressInfo.WIFI.ipAddress, IPV4_ADDR_SIZE - 1, ipaddress.c_str()); OICStrcpy(netInfo.netAddressInfo.WIFI.ssid, NET_WIFI_SSID_SIZE - 1, ssid.c_str()); OICStrcpy(netInfo.netAddressInfo.WIFI.pwd, NET_WIFI_PWD_SIZE - 1, pwd.c_str()); @@ -154,11 +160,19 @@ void runEasySetupMenu() }; } +static FILE* client_open(const char *UNUSED_PARAM, const char *mode) +{ + (void)UNUSED_PARAM; + return fopen(JSON_DB_PATH, mode); +} + void configurePlatform() { + OCPersistentStorage ps {client_open, fread, fwrite, fclose, unlink }; + PlatformConfig config { - OC::ServiceType::InProc, ModeType::Client, "0.0.0.0", 0, OC::QualityOfService::LowQos + OC::ServiceType::InProc, ModeType::Both, "0.0.0.0", 0, OC::QualityOfService::LowQos, NULL }; OCPlatform::Configure(config); } diff --git a/service/easy-setup/sdk/common/escommon.h b/service/easy-setup/sdk/common/escommon.h old mode 100644 new mode 100755 index b428aea..1e94983 --- a/service/easy-setup/sdk/common/escommon.h +++ b/service/easy-setup/sdk/common/escommon.h @@ -21,6 +21,7 @@ #ifndef ES_COMMON_H_ #define ES_COMMON_H_ +#include #ifndef WITH_ARDUINO #include #endif @@ -32,8 +33,8 @@ #define OIC_STRING_MAX_VALUE 100 #define IPV4_ADDR_SIZE 16 #define IP_PORT 55555 -#define NET_WIFI_SSID_SIZE 16 -#define NET_WIFI_PWD_SIZE 16 +#define NET_WIFI_SSID_SIZE 100 +#define NET_WIFI_PWD_SIZE 100 /** * @brief Mac address length for BT port @@ -188,9 +189,13 @@ typedef union */ typedef struct { - EnrolleeInfo netAddressInfo; /**< Enroller Network Info**/ - OCConnectivityType connType; /**< Connectivity Type**/ - bool isSecured; /**< Secure connection**/ + EnrolleeInfo netAddressInfo; /**< Enroller Network Info**/ + OCConnectivityType connType; /**< Connectivity Type**/ + bool isSecured; /**< Secure connection**/ + // TODO : Ideally isSecured should be renamed to needSecuredEasysetup. + // To provide backward compatibility to v1.0 release, a new variable is being added. + // If isSecured is not used by other applications, isSecured will be depricated. + bool needSecuredEasysetup; /**< Need of secure ownership transfer during easysetup**/ } EnrolleeNWProvInfo; /** @@ -198,6 +203,8 @@ typedef struct */ typedef void (*OCProvisioningStatusCB)(EasySetupInfo *easySetupInfo); +#ifndef WITH_ARDUINO + namespace OIC { namespace Service @@ -218,7 +225,40 @@ namespace OIC ES_PROVISIONED } CurrentESState; -#ifndef WITH_ARDUINO + typedef enum + { + ES_SEC_UNKNOWN = 0, + ES_SEC_OWNED, + ES_SEC_ACL_PROVISIONED, + ES_SEC_CREDS_PROVISIONED + } EnrolleeSecState; + + /** + * Security Provisioning Status + */ + typedef struct { + /// UUID of the target device + std::string devUUID; + /// EasySetup result + ESResult res; + } SecProvisioningResult; + + + /** + * Callback function definition for providing Enrollee security status . + */ + typedef std::function< void(SecProvisioningResult) > EnrolleeSecStatusCb; + + /** + * Callback definition to be invoked when the security stack expects a pin from application. + */ + typedef std::function< void(std::string&) > SecurityPinCb; + + /** + * Callback definition to be invoked when the stack expects a db path. + */ + typedef std::function< void(std::string&) > SecProvisioningDbPathCb; + class ProvisioningStatus { public: @@ -267,9 +307,8 @@ namespace OIC EasySetupState m_easySetupState; EnrolleeNWProvInfo m_enrolleeNWProvInfo; }; -#endif - } } +#endif //WITH_ARDUINO -#endif +#endif //ES_COMMON_H_ diff --git a/service/easy-setup/sdk/enrollee/src/resourceHandler.cpp b/service/easy-setup/sdk/enrollee/src/resourceHandler.cpp old mode 100644 new mode 100755 index 383be91..74efd8b --- a/service/easy-setup/sdk/enrollee/src/resourceHandler.cpp +++ b/service/easy-setup/sdk/enrollee/src/resourceHandler.cpp @@ -21,6 +21,8 @@ #include "resourceHandler.h" #include "ocpayload.h" +#include "oic_string.h" + /** * @var ES_RH_TAG * @brief Logging tag for module name. @@ -172,6 +174,10 @@ OCEntityHandlerResult ProcessPutRequest(OCEntityHandlerRequest *ehRequest, { sprintf(g_prov.tnn, "%s", tnn); } + else + { + OC_LOG (ERROR, ES_RH_TAG, "value is not available"); + } OC_LOG_V(INFO, ES_RH_TAG, "g_prov.tnn %s", g_prov.tnn); @@ -180,6 +186,10 @@ OCEntityHandlerResult ProcessPutRequest(OCEntityHandlerRequest *ehRequest, { sprintf(g_prov.cd, "%s", cd); } + else + { + OC_LOG (ERROR, ES_RH_TAG, "value is not available"); + } OC_LOG_V(INFO, ES_RH_TAG, "g_prov.cd %s", g_prov.cd); diff --git a/service/easy-setup/sdk/mediator/include/RemoteEnrollee.h b/service/easy-setup/sdk/mediator/include/RemoteEnrollee.h index b21d258..485626a 100755 --- a/service/easy-setup/sdk/mediator/include/RemoteEnrollee.h +++ b/service/easy-setup/sdk/mediator/include/RemoteEnrollee.h @@ -28,6 +28,7 @@ namespace OIC namespace Service { class RemoteEnrolleeResource; + class EnrolleeSecurity; /** * This class represents Remote Enrollee device instance. @@ -61,10 +62,30 @@ namespace OIC typedef std::function< void(std::shared_ptr< EasySetupStatus >) > EasySetupStatusCB; +#ifdef __WITH_DTLS__ + /** + * Register Security status and other information callback handlers. + * + * @param enrolleeSecStatusCb Callback to get security status callbacks. + * @param secProvisioningDbCb Callback to be invoked when the stack expects a + * path for the provisioning db. + * @param securityPinCb Callback to get security pin during pin based ownership transfer. + * + * @throws InvalidParameterException If callback is an empty function or null. + * @throws ESBadRequestException If registration is already completed. + * + * @see SecProvisioningResult + */ + ESResult registerSecurityCallbackHandler(EnrolleeSecStatusCb enrolleeSecStatusCb, + SecurityPinCb securityPinCb, SecProvisioningDbPathCb secProvisioningDbPathCb); +#endif //__WITH_DTLS__ + /** * Register EasySetup status handler. * * @param callback Callback to get EasySetup status. + * @param secProvisioningDbCB Callback to be invoked when the stack expects a + * path for the provisioning db. * * @throws InvalidParameterException If callback is an empty function or null. * @throws ESBadRequestException If registration is already completed. @@ -80,32 +101,37 @@ namespace OIC * * @see RemoteEnrollee */ - virtual void startProvisioning(); + void startProvisioning(); /** * Stop provisioning process that is currently in progress. * * @throws BadRequestException If provisioning is not in progress. */ - virtual void stopProvisioning(); + void stopProvisioning(); /** * Check if the Enrollee device provisioned. */ - virtual bool isEnrolleeProvisioned(); + bool isEnrolleeProvisioned(); /** * Get the Provisioning information provided for the current Enrollee. * * @return EnrolleeNWProvInfo Provisioning information provided for the current Enrollee. */ - virtual EnrolleeNWProvInfo& getEnrolleeProvisioningInfo (); + EnrolleeNWProvInfo& getEnrolleeProvisioningInfo (); private: std::shared_ptr< RemoteEnrolleeResource > m_remoteResource; EasySetupStatusCB m_easySetupStatusCb; + EnrolleeSecStatusCb m_enrolleeSecStatusCb; + SecurityPinCb m_securityPinCb; + SecProvisioningDbPathCb m_secProvisioningDbPathCb; EnrolleeNWProvInfo m_enrolleeNWProvInfo; + std::shared_ptr< EnrolleeSecurity > m_enrolleeSecurity; CurrentESState m_currentESState; + bool m_needSecuredEasysetup; void provisioningStatusHandler (std::shared_ptr< ProvisioningStatus > provStatus); }; diff --git a/service/easy-setup/sdk/mediator/src/EnrolleeSecurity.cpp b/service/easy-setup/sdk/mediator/src/EnrolleeSecurity.cpp new file mode 100755 index 0000000..219d429 --- /dev/null +++ b/service/easy-setup/sdk/mediator/src/EnrolleeSecurity.cpp @@ -0,0 +1,306 @@ +//****************************************************************** +// +// 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 "EnrolleeSecurity.h" +#include "oxmjustworks.h" +#include "oxmrandompin.h" +#include "RemoteEnrolleeResource.h" +#include "logger.h" +#include "ESException.h" +#include "oic_malloc.h" + +namespace OIC +{ + namespace Service + { + //TODO : Currently discovery timeout for owned and unowned devices is fixed as 5 + // The value should be accepted from the application as a parameter during ocplatform + // config call + #define ES_SEC_DISCOVERY_TIMEOUT 5 + + EnrolleeSecurity::EnrolleeSecurity( + std::shared_ptr< RemoteEnrolleeResource > remoteEnrolleeResource, + std::string secDbPath) + { + m_enrolleeSecState = EnrolleeSecState::ES_SEC_UNKNOWN; + + //Initializing the provisioning client stack using the db path provided by the + // application. + // Note : If the path is NULL or empty, the PDM.db should be present in the same path. + OCStackResult result = OCSecure::provisionInit(secDbPath); + + if (result != OC_STACK_OK) + { + throw ESPlatformException(result); + } + } + + ESResult EnrolleeSecurity::registerCallbackHandler( + EnrolleeSecStatusCb enrolleeSecStatusCb, SecurityPinCb securityPinCb, + SecProvisioningDbPathCb secProvisioningDbPathCb) + + { + m_enrolleeSecStatusCb = enrolleeSecStatusCb; + m_securityPinCb = securityPinCb; + m_secProvisioningDbPathCb = secProvisioningDbPathCb; + + return ES_ERROR; + } + + std::shared_ptr< OC::OCSecureResource > EnrolleeSecurity::findEnrollee(std::string host, + DeviceList_t &list) + { + for (unsigned int i = 0; i < list.size(); i++) + { + OC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Device %d ID %s ", i + 1, + list[i]->getDeviceID().c_str()); + OC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "From IP :%s", list[i]->getDevAddr().c_str()); + + if(list[i]->getDevAddr() == host) + { + return list[i]; + } + } + + return nullptr; + } + + void EnrolleeSecurity::ownershipTransferCb(OC::PMResultList_t *result, int hasError) + { + if (hasError) + { + OC_LOG(ERROR, ENROLEE_SECURITY_TAG,"Error!!! in OwnershipTransfer"); + } + else + { + OC_LOG(DEBUG, ENROLEE_SECURITY_TAG,"Transferred Ownership successfuly for device : "); + OC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "UUID : %s",result->at(0).deviceId.id); + + delete result; + + //TODO : Decide if we have to manage the owned/unowned devices. + //pOwnedDevList.push_back(pUnownedDevList[transferDevIdx]); + //pUnownedDevList.erase(pUnownedDevList.begin() + transferDevIdx); + } + } + + /** + * Callback function for provisioning ACL, Credentials. + * + * @param[in] result Result list + * @param[in] hasError indicates if the result has error + */ + void EnrolleeSecurity::provisionCb(OC::PMResultList_t *result, int hasError) + { + if (hasError) + { + OC_LOG(ERROR, ENROLEE_SECURITY_TAG, "Error in provisioning operation!"); + } + else + { + OC_LOG(DEBUG, ENROLEE_SECURITY_TAG, "Received provisioning results: "); + for (unsigned int i = 0; i < result->size(); i++) + { + OC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Result is = %d for device",result->at(i).res); OC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "UUID : %s",result->at(0).deviceId.id); + } + + delete result; + } + } + + ESResult EnrolleeSecurity::performOwnershipTransfer() + { + ESResult res = ES_ERROR; + + OC::DeviceList_t pUnownedDevList, pOwnedDevList; + + pOwnedDevList.clear(); + pUnownedDevList.clear(); + + OCStackResult result = OCSecure::discoverOwnedDevices(ES_SEC_DISCOVERY_TIMEOUT, + pOwnedDevList); + if (result != OC_STACK_OK) + { + OC_LOG(ERROR, ENROLEE_SECURITY_TAG, "Owned Discovery failed."); + res = ES_ERROR; + + return res; + } + else if (pOwnedDevList.size()) + { + OC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Found owned devices. Count =%d", + pOwnedDevList.size()); + std::shared_ptr< OC::OCSecureResource > ownedDevice = + findEnrollee( + m_remoteEnrolleeResource->m_enrolleeNWProvInfo.netAddressInfo.WIFI.ipAddress, + pOwnedDevList); + if(ownedDevice) + { + res = ES_OK; + } + } + else + { + OC_LOG(ERROR, ENROLEE_SECURITY_TAG, "No Secure devices found."); + res = ES_ERROR; + + return res; + } + + result = OCSecure::discoverUnownedDevices(ES_SEC_DISCOVERY_TIMEOUT, + pUnownedDevList); + if (result != OC_STACK_OK) + { + OC_LOG(ERROR, ENROLEE_SECURITY_TAG, "UnOwned Discovery failed."); + res = ES_ERROR; + + return res; + } + else if (pUnownedDevList.size()) + { + OC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Found Unowned devices. Count =%d", + pUnownedDevList.size()); + + std::shared_ptr< OC::OCSecureResource > unownedDevice = + findEnrollee( + m_remoteEnrolleeResource->m_enrolleeNWProvInfo.netAddressInfo.WIFI.ipAddress, + pUnownedDevList); + if (unownedDevice) + { + OTMCallbackData_t justWorksCBData; + justWorksCBData.loadSecretCB = LoadSecretJustWorksCallback; + justWorksCBData.createSecureSessionCB = CreateSecureSessionJustWorksCallback; + justWorksCBData.createSelectOxmPayloadCB = CreateJustWorksSelectOxmPayload; + justWorksCBData.createOwnerTransferPayloadCB = + CreateJustWorksOwnerTransferPayload; + OCSecure::setOwnerTransferCallbackData(OIC_JUST_WORKS, &justWorksCBData, NULL); + + OC_LOG_V(DEBUG, ENROLEE_SECURITY_TAG, "Transfering ownership for : %s ", + unownedDevice->getDeviceID().c_str()); + + OC::ResultCallBack ownershipTransferCb = std::bind( + &EnrolleeSecurity::ownershipTransferCb, this, std::placeholders::_1, + std::placeholders::_2); + + if (unownedDevice->doOwnershipTransfer(ownershipTransferCb) != OC_STACK_OK) + { + OC_LOG(ERROR, ENROLEE_SECURITY_TAG, "OwnershipTransferCallback is failed"); + res = ES_ERROR; + } + else + { + if(provisionCreds() == ES_OK) + { + OC_LOG(DEBUG, ENROLEE_SECURITY_TAG, + "provisionCreds success. Continuing with provisioning ACL"); + + if (provisionAcl() == ES_OK) + { + OC_LOG(DEBUG, ENROLEE_SECURITY_TAG, + "provisionAcl success."); + + //returning success; + res = ES_OK; + } + else + { + OC_LOG(ERROR, ENROLEE_SECURITY_TAG, "provisionAcl failed."); + res = ES_ERROR; + } + } + else + { + OC_LOG(ERROR, ENROLEE_SECURITY_TAG, "provisionCreds failed."); + res = ES_ERROR; + } + } + } + } + else + { + OC_LOG(ERROR, ENROLEE_SECURITY_TAG, "No Secure devices found."); + res = ES_ERROR; + + return res; + } + + return res; + } + + ESResult EnrolleeSecurity::provisionAcl() + { + // TODO : Currently device id is hardcoded, but this id has to be obtained from the + // application + OicSecAcl_t *acl = nullptr; + + acl = (OicSecAcl_t *) OICCalloc(1, sizeof(OicSecAcl_t)); + if (nullptr == acl) + { + OC_LOG(ERROR, ENROLEE_SECURITY_TAG, "Error while memory allocation"); + return ES_ERROR; + } + +// std::cout << "Please input ACL for selected device: " << std::endl; +// if (0 != InputACL(acl1)) +// { +// break; +// } + + OC::ResultCallBack provisioningCb = std::bind(&EnrolleeSecurity::provisionCb, this, + std::placeholders::_1, std::placeholders::_2); + + if (m_securedResource->provisionACL(acl, provisioningCb) != OC_STACK_OK) + { + OC_LOG(ERROR, ENROLEE_SECURITY_TAG, "provisionACL is failed"); + } + return ES_ERROR; + } + + ESResult EnrolleeSecurity::provisionCreds() + { +// 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(NO_SECURITY_MODE, 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; +// } + return ES_ERROR; + } + } +} diff --git a/service/easy-setup/sdk/mediator/src/EnrolleeSecurity.h b/service/easy-setup/sdk/mediator/src/EnrolleeSecurity.h new file mode 100755 index 0000000..8adb9d5 --- /dev/null +++ b/service/easy-setup/sdk/mediator/src/EnrolleeSecurity.h @@ -0,0 +1,77 @@ +//****************************************************************** +// +// 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 ENROLLEE_SECURITY_H_ +#define ENROLLEE_SECURITY_H_ + +#include + +#include "escommon.h" +#include "OCProvisioningManager.h" + +namespace OIC +{ + namespace Service + { + #define ENROLEE_SECURITY_TAG "ENROLEE_SECURITY" + + class RemoteEnrolleeResource; + class OCSecureResource; + + /** + * This class contains the methods needed for security layer interaction. + * + * @see EnrolleeSecurity + */ + class EnrolleeSecurity + { + public: + EnrolleeSecurity(std::shared_ptr< RemoteEnrolleeResource > remoteEnrolleeResource, + std::string secDbPath); + + ESResult registerCallbackHandler(EnrolleeSecStatusCb enrolleeSecStatusCb, + SecurityPinCb securityPinCb, SecProvisioningDbPathCb secProvisioningDbPathCb); + + + ESResult performOwnershipTransfer(); + + ESResult provisionCreds(); + + ESResult provisionAcl(); + + private: + std::shared_ptr < RemoteEnrolleeResource > m_remoteEnrolleeResource; + EnrolleeSecStatusCb m_enrolleeSecStatusCb; + SecurityPinCb m_securityPinCb; + SecProvisioningDbPathCb m_secProvisioningDbPathCb; + + EnrolleeSecState m_enrolleeSecState; + std::shared_ptr < OC::OCSecureResource > m_securedResource; + + std::shared_ptr< OC::OCSecureResource > findEnrollee(std::string host, + OC::DeviceList_t &list); + void provisionCb(OC::PMResultList_t *result, int hasError); + void ownershipTransferCb(OC::PMResultList_t *result, int hasError); + }; + } +} + +#endif /* ENROLLEE_SECURITY_H_*/ + diff --git a/service/easy-setup/sdk/mediator/src/RemoteEnrollee.cpp b/service/easy-setup/sdk/mediator/src/RemoteEnrollee.cpp old mode 100644 new mode 100755 index 81867ea..4365a93 --- a/service/easy-setup/sdk/mediator/src/RemoteEnrollee.cpp +++ b/service/easy-setup/sdk/mediator/src/RemoteEnrollee.cpp @@ -22,6 +22,9 @@ #include "RemoteEnrolleeResource.h" #include "ESException.h" #include "logger.h" +#ifdef __WITH_DTLS__ +#include "EnrolleeSecurity.h" +#endif //__WITH_DTLS namespace OIC { @@ -33,14 +36,28 @@ namespace OIC m_enrolleeNWProvInfo(enrolleeNWProvInfo) { m_currentESState = CurrentESState::ES_UNKNOWN; + m_needSecuredEasysetup = enrolleeNWProvInfo.needSecuredEasysetup; OC_LOG ( DEBUG, ES_REMOTE_ENROLLEE_TAG, "Inside RemoteEnrollee constr"); - if (m_easySetupStatusCb) - { - throw ESBadRequestException("Callback handler already registered"); - } } +#ifdef __WITH_DTLS__ + ESResult RemoteEnrollee::registerSecurityCallbackHandler( + EnrolleeSecStatusCb enrolleeSecStatusCb, SecurityPinCb securityPinCb, + SecProvisioningDbPathCb secProvisioningDbPathCb) + { + // No need to check NULL for m_secProvisioningDbPathCB as this is not a mandatory + // callback function. If m_secProvisioningDbPathCB is NULL, provisioning manager + // in security layer will try to find the PDM.db file in the local path. + // If PDM.db is found, the provisioning manager operations will succeed. + // Otherwise all the provisioning manager operations will fail. + m_secProvisioningDbPathCb = secProvisioningDbPathCb; + m_enrolleeSecStatusCb = enrolleeSecStatusCb; + m_securityPinCb = securityPinCb; + return ES_OK; + } +#endif //__WITH_DTLS__ + void RemoteEnrollee::registerEasySetupStatusHandler(EasySetupStatusCB callback) { OC_LOG ( DEBUG, ES_REMOTE_ENROLLEE_TAG, "Entered registerStatusHandler"); @@ -57,9 +74,7 @@ namespace OIC { m_easySetupStatusCb = callback; - m_remoteResource = std::make_shared< RemoteEnrolleeResource >( - m_enrolleeNWProvInfo.netAddressInfo.WIFI.ipAddress, - m_enrolleeNWProvInfo.connType); + m_remoteResource = std::make_shared< RemoteEnrolleeResource >(m_enrolleeNWProvInfo); m_remoteResource->constructResourceObject(); } @@ -141,7 +156,6 @@ namespace OIC return; } - void RemoteEnrollee::startProvisioning() { OC_LOG(DEBUG,ES_REMOTE_ENROLLEE_TAG,"Entering startProvisioning"); @@ -153,13 +167,33 @@ namespace OIC { m_currentESState = CurrentESState::ES_ONBOARDED; +#ifdef __WITH_DTLS__ + if (m_needSecuredEasysetup && m_currentESState < CurrentESState::ES_OWNED) + { + //TODO : DBPath is passed empty as of now. Need to take dbpath from application. + m_enrolleeSecurity = std::make_shared (m_remoteResource, ""); + + m_enrolleeSecurity->registerCallbackHandler(m_enrolleeSecStatusCb, + m_securityPinCb, m_secProvisioningDbPathCb); + + if (m_enrolleeSecurity->performOwnershipTransfer() == ES_ERROR) + { + std::shared_ptr< EasySetupStatus > easySetupStatus = nullptr; + + easySetupStatus = std::make_shared < EasySetupStatus + > (DEVICE_NOT_OWNED, m_enrolleeNWProvInfo); + return; + } + } +#endif + OC_LOG(DEBUG,ES_REMOTE_ENROLLEE_TAG,"Before ProvisionEnrollee"); RemoteEnrolleeResource::ProvStatusCb provStatusCb = std::bind( &RemoteEnrollee::provisioningStatusHandler, this, std::placeholders::_1); m_remoteResource->registerProvStatusCallback(provStatusCb); - m_remoteResource->provisionEnrollee(m_enrolleeNWProvInfo); + m_remoteResource->provisionEnrollee(); } } diff --git a/service/easy-setup/sdk/mediator/src/RemoteEnrolleeResource.cpp b/service/easy-setup/sdk/mediator/src/RemoteEnrolleeResource.cpp index 750f698..9284ea8 100755 --- a/service/easy-setup/sdk/mediator/src/RemoteEnrolleeResource.cpp +++ b/service/easy-setup/sdk/mediator/src/RemoteEnrolleeResource.cpp @@ -32,14 +32,12 @@ namespace OIC namespace Service { #define ES_REMOTE_ENROLLEE_TAG "ES_REMOTE_ENROLLEE" - static const char ES_RES_URI[] = "/oic/prov"; - static const char ES_RES_TYPE[] = "oic.r.prov"; + static const char ES_PROV_RES_URI[] = "/oic/prov"; + static const char ES_PROV_RES_TYPE[] = "oic.r.prov"; - RemoteEnrolleeResource::RemoteEnrolleeResource(const std::string& host, - OCConnectivityType connectivityType) : - m_host(host), m_connectivityType(connectivityType) + RemoteEnrolleeResource::RemoteEnrolleeResource(EnrolleeNWProvInfo enrolleeNWProvInfo) { - + m_enrolleeNWProvInfo = enrolleeNWProvInfo; } void RemoteEnrolleeResource::onProvPostResource(const HeaderOptions& /*headerOptions*/, @@ -145,14 +143,14 @@ namespace OIC OCRepresentation provisioningRepresentation; provisioningRepresentation.setValue(OC_RSRVD_ES_TNN, - m_enrolleeNWProvInfo.netAddressInfo.WIFI.ssid); + std::string(m_enrolleeNWProvInfo.netAddressInfo.WIFI.ssid)); provisioningRepresentation.setValue(OC_RSRVD_ES_CD, - m_enrolleeNWProvInfo.netAddressInfo.WIFI.pwd); + std::string(m_enrolleeNWProvInfo.netAddressInfo.WIFI.pwd)); OC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_TAG, "onProvResource : ssid - %s", - m_enrolleeNWProvInfo.netAddressInfo.WIFI.ssid); + m_enrolleeNWProvInfo.netAddressInfo.WIFI.ssid); OC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_TAG, "onProvResource : pwd - %s", - m_enrolleeNWProvInfo.netAddressInfo.WIFI.pwd); + m_enrolleeNWProvInfo.netAddressInfo.WIFI.pwd); m_ocResource->put(provisioningRepresentation, QueryParamsMap(), std::function< @@ -188,21 +186,22 @@ namespace OIC { std::vector< std::string > m_if = { DEFAULT_INTERFACE }; - std::vector< std::string > m_resTypes = {ES_RES_TYPE}; + std::vector< std::string > m_resTypes = {ES_PROV_RES_TYPE}; OC_LOG(DEBUG, ES_REMOTE_ENROLLEE_TAG, "Before OCPlatform::constructResourceObject"); - OC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_TAG, "m_host = %s", m_host.c_str()); - OC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_TAG, "ES_RES_URI = %s", ES_RES_URI); + OC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_TAG, "m_host = %s", + m_enrolleeNWProvInfo.netAddressInfo.WIFI.ipAddress); + OC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_TAG, "ES_PROV_RES_URI = %s", ES_PROV_RES_URI); OC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_TAG, "m_connectivityType = %d", - m_connectivityType); + m_enrolleeNWProvInfo.connType); OC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_TAG, "m_resTypes = %s", - m_resTypes.at(0).c_str()); + m_resTypes.at(0).c_str()); OC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_TAG, "m_if = %s", m_if.at(0).c_str()); std::string host; - if(m_enrolleeNWProvInfo.isSecured) + if(m_enrolleeNWProvInfo.needSecuredEasysetup) { host.append("coaps://"); } @@ -211,21 +210,24 @@ namespace OIC host.append("coap://"); } - if(m_connectivityType == CT_ADAPTER_IP) + if(m_enrolleeNWProvInfo.connType == CT_ADAPTER_IP) { - host.append(m_host); - //TODO : If the target Enrollee is not a Arduino Wi-Fi device, then m_ocResource - // will be discovered using findResource API of OCPlatform instead of using - // constructResourceObject API. The port number thus will be found during - // resource discovery instead of using 55555 + // TODO : RemoteEnrollee is current handling easysetup on IP transport. + // WiFiRemoteEnrollee need to extend RemoteEnrollee for providing IP specific + // Enrollee easysetup. + + host.append(m_enrolleeNWProvInfo.netAddressInfo.WIFI.ipAddress); + //TODO : If the target Enrollee is not a Arduino Wi-Fi device, + // then the port number will be found during resource discovery instead of + // using 55555 host.append(":55555"); } OC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_TAG, "HOST = %s", host.c_str()); m_ocResource = OC::OCPlatform::constructResourceObject(host, - ES_RES_URI, - m_connectivityType, + ES_PROV_RES_URI, + m_enrolleeNWProvInfo.connType, true, m_resTypes, m_if); @@ -239,7 +241,7 @@ namespace OIC } } - void RemoteEnrolleeResource::provisionEnrollee(const EnrolleeNWProvInfo& enrolleeNWProvInfo) + void RemoteEnrolleeResource::provisionEnrollee() { if(m_ocResource == nullptr) @@ -247,7 +249,6 @@ namespace OIC throw ESBadRequestException ("Resource is not initialized"); } - m_enrolleeNWProvInfo = enrolleeNWProvInfo; OC::QueryParamsMap query; OC::OCRepresentation rep; diff --git a/service/easy-setup/sdk/mediator/src/RemoteEnrolleeResource.h b/service/easy-setup/sdk/mediator/src/RemoteEnrolleeResource.h index 84e1d3c..cc520ec 100755 --- a/service/easy-setup/sdk/mediator/src/RemoteEnrolleeResource.h +++ b/service/easy-setup/sdk/mediator/src/RemoteEnrolleeResource.h @@ -35,6 +35,7 @@ namespace OIC namespace Service { class OCResource; + class EnrolleeSecurity; /** * This class contains the resource discovery methods. @@ -43,20 +44,21 @@ namespace OIC */ class RemoteEnrolleeResource { + friend class EnrolleeSecurity; + public: typedef std::shared_ptr< RemoteEnrolleeResource > Ptr; - typedef std::function< void(std::shared_ptr< ProvisioningStatus > provStatus) > ProvStatusCb; + typedef std::function< void(std::shared_ptr< ProvisioningStatus >) > ProvStatusCb; /** * RemoteEnrolleeResource constructor * - * @param host Host information of the Enrollee device obtained from OnBoarding process. - * @param connectivityType Connectivity type on which OnBoarding is performed + * @param enrolleeNWProvInfo Provisioning information for the Enrollee * * @throw ESBadRequestException is thrown if the parameters are invalid */ - RemoteEnrolleeResource(const std::string& host, OCConnectivityType connectivityType); + RemoteEnrolleeResource(EnrolleeNWProvInfo enrolleeNWProvInfo); ~RemoteEnrolleeResource() = default; @@ -86,26 +88,22 @@ namespace OIC /** * Function for provisioning of Remote Enrollee resource using the information provided. * - * @param enrolleeNWProvInfo Provisioning information for the Enrollee - * * @throws InvalidParameterException If cb is empty. */ - virtual void provisionEnrollee(const EnrolleeNWProvInfo& enrolleeNWProvInfo); + void provisionEnrollee(); /** * Function for unprovisioning of Remote Enrollee and bring to unprovisioned state * * @throws ESBadRequestException If device is not provisioned already. */ - virtual void unprovisionEnrollee(); + void unprovisionEnrollee(); private: std::shared_ptr< OC::OCResource > m_ocResource; std::mutex m_mutex; - std::string m_host; - OCConnectivityType m_connectivityType; ProvStatusCb m_provStatusCb; EnrolleeNWProvInfo m_enrolleeNWProvInfo;