1 //******************************************************************
3 // Copyright 2015 Samsung Electronics All Rights Reserved.
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
11 // http://www.apache.org/licenses/LICENSE-2.0
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an "AS IS" BASIS,
15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 // See the License for the specific language governing permissions and
17 // limitations under the License.
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
21 #include "RemoteEnrollee.h"
22 #include "EnrolleeResource.h"
23 #include "CloudResource.h"
24 #include "OCPlatform.h"
25 #include "ESException.h"
27 #include "OCResource.h"
29 #include "EnrolleeSecurity.h"
31 #include "oic_malloc.h"
38 static const char ES_BASE_RES_URI[] = "/oic/res";
39 #define ES_REMOTE_ENROLLEE_TAG "ES_REMOTE_ENROLLEE"
40 #define DISCOVERY_TIMEOUT 5
42 RemoteEnrollee::RemoteEnrollee(std::shared_ptr< OC::OCResource > resource)
44 m_ocResource = resource;
45 m_enrolleeResource = std::make_shared<EnrolleeResource>(m_ocResource);
46 m_securityProvStatusCb = nullptr;
47 m_getConfigurationStatusCb = nullptr;
48 m_securityPinCb = nullptr;
49 m_secProvisioningDbPathCb = nullptr;
50 m_devicePropProvStatusCb = nullptr;
51 m_cloudPropProvStatusCb = nullptr;
53 m_deviceId = resource->sid();
57 ESResult RemoteEnrollee::registerSecurityCallbackHandler(SecurityPinCb securityPinCb,
58 SecProvisioningDbPathCb secProvisioningDbPathCb)
60 // No need to check NULL for m_secProvisioningDbPathCB as this is not a mandatory
61 // callback function. If m_secProvisioningDbPathCB is NULL, provisioning manager
62 // in security layer will try to find the PDM.db file in the local path.
63 // If PDM.db is found, the provisioning manager operations will succeed.
64 // Otherwise all the provisioning manager operations will fail.
65 m_secProvisioningDbPathCb = secProvisioningDbPathCb;
66 m_securityPinCb = securityPinCb;
69 #endif //__WITH_DTLS__
71 void RemoteEnrollee::securityStatusHandler(
72 std::shared_ptr< SecProvisioningStatus > status)
74 OIC_LOG_V(DEBUG, ES_REMOTE_ENROLLEE_TAG, "easySetupStatusCallback status is, UUID = %s,"
75 "Status = %d", status->getDeviceUUID().c_str(),
76 status->getESResult());
78 if(status->getESResult() == ES_OK)
80 OIC_LOG(DEBUG, ES_REMOTE_ENROLLEE_TAG, "Ownership and ACL are successful. "
81 "Continue with Network information provisioning");
83 OIC_LOG(DEBUG,ES_REMOTE_ENROLLEE_TAG,"Before ProvisionEnrollee");
85 m_securityProvStatusCb(status);
89 OIC_LOG(DEBUG, ES_REMOTE_ENROLLEE_TAG, "Ownership and ACL are fail");
91 m_securityProvStatusCb(status);
95 void RemoteEnrollee::getStatusHandler(std::shared_ptr< GetEnrolleeStatus > status)
97 OIC_LOG(DEBUG,ES_REMOTE_ENROLLEE_TAG,"Entering getStatusHandler");
99 OIC_LOG_V(DEBUG,ES_REMOTE_ENROLLEE_TAG,"getStatusHandler = %d", status->getESResult());
101 m_getStatusCb(status);
104 void RemoteEnrollee::getConfigurationStatusHandler (
105 std::shared_ptr< GetConfigurationStatus > status)
107 OIC_LOG(DEBUG,ES_REMOTE_ENROLLEE_TAG,"Entering getConfigurationStatusHandler");
109 OIC_LOG_V(DEBUG,ES_REMOTE_ENROLLEE_TAG,"GetConfigurationStatus = %d",
110 status->getESResult());
112 m_getConfigurationStatusCb(status);
115 void RemoteEnrollee::devicePropProvisioningStatusHandler(
116 std::shared_ptr< DevicePropProvisioningStatus > status)
118 OIC_LOG(DEBUG,ES_REMOTE_ENROLLEE_TAG,"Entering DevicePropProvisioningStatusHandler");
120 OIC_LOG_V(DEBUG,ES_REMOTE_ENROLLEE_TAG,"ProvStatus = %d", status->getESResult());
122 m_devicePropProvStatusCb(status);
127 void RemoteEnrollee::cloudPropProvisioningStatusHandler (
128 std::shared_ptr< CloudPropProvisioningStatus > status)
130 OIC_LOG(DEBUG,ES_REMOTE_ENROLLEE_TAG,"Entering cloudPropProvisioningStatusHandler");
132 OIC_LOG_V(DEBUG,ES_REMOTE_ENROLLEE_TAG,"CloudProvStatus = %d",
133 status->getESCloudState());
135 m_cloudPropProvStatusCb(status);
139 void RemoteEnrollee::onDeviceDiscovered(std::shared_ptr<OC::OCResource> resource)
141 OIC_LOG (DEBUG, ES_REMOTE_ENROLLEE_TAG, "onDeviceDiscovered");
143 std::string resourceURI;
144 std::string hostAddress;
145 std::string hostDeviceID;
151 if(!(resource->connectivityType() & CT_ADAPTER_TCP))
153 // Get the resource URI
154 resourceURI = resource->uri();
155 OIC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_TAG,
156 "URI of the resource: %s", resourceURI.c_str());
158 // Get the resource host address
159 hostAddress = resource->host();
160 OIC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_TAG,
161 "Host address of the resource: %s", hostAddress.c_str());
163 hostDeviceID = resource->sid();
164 OIC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_TAG,
165 "Host DeviceID of the resource: %s", hostDeviceID.c_str());
167 if(!m_deviceId.empty() && m_deviceId == hostDeviceID)
169 OIC_LOG (DEBUG, ES_REMOTE_ENROLLEE_TAG, "Find matched CloudResource");
170 m_ocResource = resource;
171 m_discoveryResponse = true;
177 catch(std::exception& e)
179 OIC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_TAG,
180 "Exception in foundResource: %s", e.what());
184 ESResult RemoteEnrollee::discoverResource()
186 OIC_LOG(DEBUG, ES_REMOTE_ENROLLEE_TAG, "Enter discoverResource");
188 std::string query("");
189 query.append(ES_BASE_RES_URI);
190 query.append("?rt=");
191 query.append(OC_RSRVD_ES_RES_TYPE_PROV);
193 OIC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_TAG, "query = %s", query.c_str());
195 m_discoveryResponse = false;
197 std::function< void (std::shared_ptr<OC::OCResource>) > onDeviceDiscoveredCb =
198 std::bind(&RemoteEnrollee::onDeviceDiscovered, this,
199 std::placeholders::_1);
200 OCStackResult result = OC::OCPlatform::findResource("", query, CT_DEFAULT,
201 onDeviceDiscoveredCb);
203 if (result != OCStackResult::OC_STACK_OK)
205 OIC_LOG(ERROR,ES_REMOTE_ENROLLEE_TAG,
206 "Failed discoverResource");
210 std::unique_lock<std::mutex> lck(m_discoverymtx);
211 m_cond.wait_for(lck, std::chrono::seconds(DISCOVERY_TIMEOUT));
213 if (!m_discoveryResponse)
215 OIC_LOG(ERROR,ES_REMOTE_ENROLLEE_TAG,
216 "Failed discoverResource because timeout");
222 void RemoteEnrollee::provisionSecurity(SecurityProvStatusCb callback)
225 m_securityProvStatusCb = callback;
227 SecurityProvStatusCb securityProvStatusCb = std::bind(
228 &RemoteEnrollee::securityStatusHandler,
230 std::placeholders::_1);
231 //TODO : DBPath is passed empty as of now. Need to take dbpath from application.
232 m_enrolleeSecurity = std::make_shared <EnrolleeSecurity> (m_ocResource, "");
234 m_enrolleeSecurity->registerCallbackHandler(securityProvStatusCb, m_securityPinCb,
235 m_secProvisioningDbPathCb);
239 m_enrolleeSecurity->performOwnershipTransfer();
241 catch (const std::exception& e)
243 OIC_LOG_V(ERROR, ES_REMOTE_ENROLLEE_TAG,
244 "Exception for performOwnershipTransfer : %s", e.what());
246 OIC_LOG(DEBUG,ES_REMOTE_ENROLLEE_TAG,"Fail performOwnershipTransfer");
247 std::shared_ptr< SecProvisioningStatus > securityProvisioningStatus =
248 std::make_shared< SecProvisioningStatus >(nullptr, ES_ERROR);
249 m_securityProvStatusCb(securityProvisioningStatus);
253 OIC_LOG(DEBUG,ES_REMOTE_ENROLLEE_TAG,"Mediator is unsecured.");
255 std::shared_ptr< SecProvisioningStatus > securityProvisioningStatus =
256 std::make_shared< SecProvisioningStatus >(nullptr, ES_ERROR);
257 m_securityProvStatusCb(securityProvisioningStatus);
261 void RemoteEnrollee::getStatus(GetStatusCb callback)
265 throw ESInvalidParameterException("Callback is empty");
268 if (m_enrolleeResource == nullptr)
270 throw ESBadRequestException ("Device not created");
273 m_getStatusCb = callback;
275 GetStatusCb getStatusCb = std::bind(
276 &RemoteEnrollee::getStatusHandler, this, std::placeholders::_1);
277 m_enrolleeResource->registerGetStatusCallback(getStatusCb);
278 m_enrolleeResource->getStatus();
282 void RemoteEnrollee::getConfiguration(GetConfigurationStatusCb callback)
286 throw ESInvalidParameterException("Callback is empty");
289 if (m_enrolleeResource == nullptr)
291 throw ESBadRequestException ("Device not created");
294 m_getConfigurationStatusCb = callback;
296 GetConfigurationStatusCb getConfigurationStatusCb = std::bind(
297 &RemoteEnrollee::getConfigurationStatusHandler, this, std::placeholders::_1);
298 m_enrolleeResource->registerGetConfigurationStatusCallback(getConfigurationStatusCb);
299 m_enrolleeResource->getConfiguration();
302 void RemoteEnrollee::provisionDeviceProperties(const DeviceProp& deviceProp,
303 DevicePropProvStatusCb callback)
305 OIC_LOG(DEBUG,ES_REMOTE_ENROLLEE_TAG,"Enter provisionDeviceProperties");
309 throw ESInvalidParameterException("Callback is empty");
312 m_devicePropProvStatusCb = callback;
314 if (m_enrolleeResource == nullptr)
316 throw ESBadRequestException ("Device not created");
319 if(!deviceProp.toOCRepresentation().hasAttribute(OC_RSRVD_ES_SSID))
321 throw ESBadRequestException ("Invalid Provisiong Data.");
324 DevicePropProvStatusCb devicePropProvStatusCb = std::bind(
325 &RemoteEnrollee::devicePropProvisioningStatusHandler,
326 this, std::placeholders::_1);
328 m_enrolleeResource->registerDevicePropProvStatusCallback(devicePropProvStatusCb);
329 m_enrolleeResource->provisionEnrollee(deviceProp);
332 void RemoteEnrollee::initCloudResource()
334 ESResult result = ES_ERROR;
336 if (m_cloudResource != nullptr)
338 throw ESBadRequestException ("Already created");
341 result = discoverResource();
343 if (result == ES_ERROR)
345 OIC_LOG(ERROR,ES_REMOTE_ENROLLEE_TAG,
346 "Failed to create resource object using discoverResource");
347 throw ESBadRequestException ("Resource object not created");
352 if(m_ocResource != nullptr)
354 m_cloudResource = std::make_shared<CloudResource>(m_ocResource);
356 std::shared_ptr< CloudPropProvisioningStatus > provStatus = std::make_shared<
357 CloudPropProvisioningStatus >(ESResult::ES_OK,
358 ESCloudProvState::ES_CLOUD_ENROLLEE_FOUND);
360 m_cloudPropProvStatusCb(provStatus);
364 throw ESBadGetException ("Resource handle is invalid");
369 void RemoteEnrollee::provisionCloudProperties(const CloudProp& cloudProp,
370 CloudPropProvStatusCb callback)
372 OIC_LOG(DEBUG,ES_REMOTE_ENROLLEE_TAG,"Enter provisionCloudProperties");
373 ESResult res = ES_OK;
377 throw ESInvalidParameterException("Callback is empty");
380 m_cloudPropProvStatusCb = callback;
382 if(!cloudProp.toOCRepresentation().hasAttribute(OC_RSRVD_ES_AUTHCODE) ||
383 !cloudProp.toOCRepresentation().hasAttribute(OC_RSRVD_ES_AUTHPROVIDER) ||
384 !cloudProp.toOCRepresentation().hasAttribute(OC_RSRVD_ES_CISERVER))
386 throw ESBadRequestException ("Invalid Cloud Provisiong Info.");
394 catch (const std::exception& e)
396 OIC_LOG_V(ERROR, ES_REMOTE_ENROLLEE_TAG,
397 "Exception caught in provisionCloudProperties = %s", e.what());
399 std::shared_ptr< CloudPropProvisioningStatus > provStatus = std::make_shared<
400 CloudPropProvisioningStatus >(ESResult::ES_ERROR,
401 ESCloudProvState::ES_CLOUD_ENROLLEE_NOT_FOUND);
402 m_cloudPropProvStatusCb(provStatus);
409 m_enrolleeSecurity = std::make_shared <EnrolleeSecurity> (m_ocResource, "");
411 if(cloudProp.getCloudID().empty())
413 throw ESBadRequestException("Invalid Cloud Server UUID.");
416 res = m_enrolleeSecurity->performACLProvisioningForCloudServer(cloudProp.getCloudID());
418 if(res == ESResult::ES_ERROR)
420 throw ESBadRequestException("Error in provisioning operation!");
425 catch (const std::exception& e)
427 OIC_LOG_V(ERROR, ES_REMOTE_ENROLLEE_TAG,
428 "Exception caught in provisionCloudProperties = %s", e.what());
430 m_cloudResource = nullptr;
432 std::shared_ptr< CloudPropProvisioningStatus > provStatus = std::make_shared<
433 CloudPropProvisioningStatus >(ESResult::ES_ERROR,
434 ESCloudProvState::ES_CLOUD_PROVISIONING_ERROR);
435 m_cloudPropProvStatusCb(provStatus);
440 if (m_cloudResource == nullptr)
442 throw ESBadRequestException ("Cloud Resource not created");
445 CloudPropProvStatusCb cloudPropProvStatusCb = std::bind(
446 &RemoteEnrollee::cloudPropProvisioningStatusHandler,
447 this, std::placeholders::_1);
449 m_cloudResource->registerCloudPropProvisioningStatusCallback(cloudPropProvStatusCb);
450 m_cloudResource->provisionEnrollee(cloudProp);