Resolved JIRA issue [IOT-999]
[platform/upstream/iotivity.git] / resource / provisioning / src / OCProvisioningManager.cpp
1 /* *****************************************************************
2  *
3  * Copyright 2015 Samsung Electronics All Rights Reserved.
4  *
5  *
6  *
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
10  *
11  *     http://www.apache.org/licenses/LICENSE-2.0
12  *
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.
18  *
19  * *****************************************************************/
20
21 #include "ocstack.h"
22 #include "base64.h"
23 #include "OCProvisioningManager.h"
24
25 namespace OC
26 {
27     OCStackResult OCSecure::provisionInit(const std::string& dbPath)
28     {
29         OCStackResult result;
30         auto cLock = OCPlatform_impl::Instance().csdkLock().lock();
31
32         if(cLock)
33         {
34             std::lock_guard<std::recursive_mutex> lock(*cLock);
35             result = OCInitPM(dbPath.c_str());
36         }
37         else
38         {
39             oclog() <<"Mutex not found";
40             result = OC_STACK_ERROR;
41         }
42
43         return result;
44     }
45
46     OCStackResult OCSecure::discoverUnownedDevices(unsigned short timeout,
47             DeviceList_t &list)
48     {
49         OCStackResult result;
50         OCProvisionDev_t *pDevList = nullptr, *pCurDev = nullptr, *tmp = nullptr;
51         auto csdkLock = OCPlatform_impl::Instance().csdkLock();
52         auto cLock = csdkLock.lock();
53
54         if(cLock)
55         {
56             std::lock_guard<std::recursive_mutex> lock(*cLock);
57             result = OCDiscoverUnownedDevices(timeout, &pDevList);
58             if (result == OC_STACK_OK)
59             {
60                 // Create DeviceList of OCSecureResource's
61                 pCurDev = pDevList;
62                 while (pCurDev)
63                 {
64                     tmp = pCurDev;
65                     list.push_back(std::shared_ptr<OCSecureResource>(
66                                 new OCSecureResource(csdkLock, pCurDev)));
67                     pCurDev = pCurDev->next;
68                     tmp->next = nullptr;
69                 }
70             }
71             else
72             {
73                 oclog() <<"Unowned device discovery failed!";
74             }
75         }
76         else
77         {
78             oclog() <<"Mutex not found";
79             result = OC_STACK_ERROR;
80         }
81
82         return result;
83     }
84
85     OCStackResult OCSecure::discoverOwnedDevices(unsigned short timeout,
86             DeviceList_t &list)
87     {
88         OCStackResult result;
89         OCProvisionDev_t *pDevList = nullptr, *pCurDev = nullptr, *tmp = nullptr;
90         auto csdkLock = OCPlatform_impl::Instance().csdkLock();
91         auto cLock = csdkLock.lock();
92
93         if(cLock)
94         {
95             std::lock_guard<std::recursive_mutex> lock(*cLock);
96             result = OCDiscoverOwnedDevices(timeout, &pDevList);
97             if (result == OC_STACK_OK)
98             {
99                 pCurDev = pDevList;
100                 while (pCurDev)
101                 {
102                     tmp = pCurDev;
103                     list.push_back(std::shared_ptr<OCSecureResource>(
104                                 new OCSecureResource(csdkLock, pCurDev)));
105                     pCurDev = pCurDev->next;
106                     tmp->next = nullptr;
107                 }
108             }
109             else
110             {
111                 oclog() <<"Owned device discovery failed!";
112             }
113         }
114         else
115         {
116             oclog() <<"Mutex not found";
117             result = OC_STACK_ERROR;
118         }
119
120         return result;
121     }
122
123     OCStackResult OCSecure::setOwnerTransferCallbackData(OicSecOxm_t oxm,
124             OTMCallbackData_t* callbackData, InputPinCallback inputPin)
125     {
126         if(NULL == callbackData || oxm >= OIC_OXM_COUNT)
127         {
128             oclog() <<"Invalid callbackData or OXM type";
129             return OC_STACK_INVALID_PARAM;
130         }
131
132         if((OIC_RANDOM_DEVICE_PIN == oxm) && !inputPin)
133         {
134             oclog() <<"for OXM type DEVICE_PIN, inputPin callback can't be null";
135             return OC_STACK_INVALID_PARAM;
136         }
137
138         OCStackResult result;
139         auto cLock = OCPlatform_impl::Instance().csdkLock().lock();
140
141         if(cLock)
142         {
143             std::lock_guard<std::recursive_mutex> lock(*cLock);
144             result = OCSetOwnerTransferCallbackData(oxm, callbackData);
145             if(result == OC_STACK_OK && (OIC_RANDOM_DEVICE_PIN == oxm))
146             {
147                 SetInputPinCB(inputPin);
148             }
149         }
150         else
151         {
152             oclog() <<"Mutex not found";
153             result = OC_STACK_ERROR;
154         }
155
156         return result;
157
158     }
159
160     OCStackResult OCSecure::getDevInfoFromNetwork(unsigned short timeout,
161             DeviceList_t &ownedDevList,
162             DeviceList_t &unownedDevList)
163     {
164         OCStackResult result = OC_STACK_OK;
165         OCProvisionDev_t *owned = nullptr, *unowned = nullptr, *tmp = nullptr, *dev = nullptr;
166         auto csdkLock = OCPlatform_impl::Instance().csdkLock();
167         auto cLock = csdkLock.lock();
168
169         if(cLock)
170         {
171             std::lock_guard<std::recursive_mutex> lock(*cLock);
172
173             result = OCGetDevInfoFromNetwork(timeout, &owned, &unowned);
174
175             if (result == OC_STACK_OK)
176             {
177                 dev = owned;
178                 while (dev)
179                 {
180                     tmp = dev;
181                     ownedDevList.push_back(std::shared_ptr<OCSecureResource>(
182                                 new OCSecureResource(csdkLock, dev)));
183                     dev = dev->next;
184                     tmp->next = nullptr;
185                 }
186
187                 dev = unowned;
188                 while (dev)
189                 {
190                     tmp = dev;
191                     unownedDevList.push_back(std::shared_ptr<OCSecureResource>(
192                                 new OCSecureResource(csdkLock,  dev)));
193                     dev = dev->next;
194                     tmp->next = nullptr;
195                 }
196             }
197         }
198         else
199         {
200             oclog() <<"Mutex not found";
201             result = OC_STACK_ERROR;
202         }
203
204         return result;
205     }
206
207     OCStackResult OCSecure::setDisplayPinCB(GeneratePinCallback displayPin)
208     {
209         if(!displayPin)
210         {
211             oclog() <<"displayPin can't be null";
212             return OC_STACK_INVALID_PARAM;
213         }
214
215         OCStackResult result = OC_STACK_OK;
216         auto cLock = OCPlatform_impl::Instance().csdkLock().lock();
217
218         if(cLock)
219         {
220             std::lock_guard<std::recursive_mutex> lock(*cLock);
221             SetGeneratePinCB(displayPin);
222         }
223         else
224         {
225             oclog() <<"Mutex not found";
226             result = OC_STACK_ERROR;
227         }
228
229         return result;
230     }
231
232     void OCSecureResource::callbackWrapper(void* ctx, int nOfRes, OCProvisionResult_t *arr, bool hasError)
233     {
234         PMResultList_t *results = nullptr;
235         ProvisionContext* context = static_cast<ProvisionContext*>(ctx);
236
237         try
238         {
239             results = new PMResultList_t;
240         }
241         catch (std::bad_alloc& e)
242         {
243             oclog() <<"Bad alloc exception";
244             return;
245         }
246
247         for (int i = 0; i < nOfRes; i++)
248         {
249             results->push_back(arr[i]);
250         }
251
252         std::thread exec(context->callback, results, hasError);
253         exec.detach();
254
255         delete context;
256     }
257
258     OCSecureResource::OCSecureResource(): m_csdkLock(std::weak_ptr<std::recursive_mutex>()),
259                                         devPtr(nullptr)
260     {
261     }
262
263     OCSecureResource::OCSecureResource(std::weak_ptr<std::recursive_mutex> csdkLock,
264             OCProvisionDev_t *dPtr)
265         :m_csdkLock(csdkLock), devPtr(dPtr)
266     {
267     }
268
269     OCSecureResource::~OCSecureResource()
270     {
271         if(devPtr)
272         {
273             OCDeleteDiscoveredDevices(devPtr);
274         }
275     }
276
277     OCStackResult OCSecureResource::doOwnershipTransfer(ResultCallBack resultCallback)
278     {
279         if(!resultCallback)
280         {
281             oclog() <<"Result callback can't be null";
282             return OC_STACK_INVALID_CALLBACK;
283         }
284
285         OCStackResult result;
286         auto cLock = m_csdkLock.lock();
287
288         if(cLock)
289         {
290             ProvisionContext* context = new ProvisionContext(resultCallback);
291
292             std::lock_guard<std::recursive_mutex> lock(*cLock);
293             result = OCDoOwnershipTransfer(static_cast<void*>(context),
294                     devPtr, &OCSecureResource::callbackWrapper);
295         }
296         else
297         {
298             oclog() <<"Mutex not found";
299             result = OC_STACK_ERROR;
300         }
301         return result;
302     }
303
304     OCStackResult OCSecureResource::provisionACL( const OicSecAcl_t* acl,
305             ResultCallBack resultCallback)
306     {
307         if(!acl)
308         {
309             oclog() <<"ACL can't be null";
310             return OC_STACK_INVALID_PARAM;
311         }
312         if(!resultCallback)
313         {
314             oclog() <<"result callback can not be null";
315             return OC_STACK_INVALID_CALLBACK;
316         }
317
318         OCStackResult result;
319         auto cLock = m_csdkLock.lock();
320
321         if(cLock)
322         {
323             ProvisionContext* context = new ProvisionContext(resultCallback);
324
325             std::lock_guard<std::recursive_mutex> lock(*cLock);
326             result = OCProvisionACL(static_cast<void*>(context),
327                     devPtr, const_cast<OicSecAcl_t*>(acl),
328                     &OCSecureResource::callbackWrapper);
329         }
330         else
331         {
332             oclog() <<"Mutex not found";
333             result = OC_STACK_ERROR;
334         }
335         return result;
336     }
337
338     OCStackResult OCSecureResource::provisionCredentials(const Credential &cred,
339             const OCSecureResource &device2, ResultCallBack resultCallback)
340     {
341         if(!resultCallback)
342         {
343             oclog() << "Result calback can't be null";
344             return OC_STACK_INVALID_CALLBACK;
345         }
346
347         OCStackResult result;
348         auto cLock = m_csdkLock.lock();
349
350         if(cLock)
351         {
352             ProvisionContext* context = new ProvisionContext(resultCallback);
353
354             std::lock_guard<std::recursive_mutex> lock(*cLock);
355             result = OCProvisionCredentials(static_cast<void*>(context),
356                     cred.getCredentialType(),
357                     cred.getCredentialKeySize(),
358                     devPtr, device2.getDevPtr(),
359                     &OCSecureResource::callbackWrapper);
360         }
361         else
362         {
363             oclog() <<"Mutex not found";
364             result = OC_STACK_ERROR;
365         }
366         return result;
367     }
368
369     OCStackResult OCSecureResource::provisionPairwiseDevices(const Credential &cred,
370             const OicSecAcl_t* acl1, const OCSecureResource &device2, const OicSecAcl_t* acl2,
371             ResultCallBack resultCallback)
372     {
373         if(!resultCallback)
374         {
375             oclog() << "Result callback can not be null";
376             return OC_STACK_INVALID_CALLBACK;
377         }
378
379         OCStackResult result;
380         auto cLock = m_csdkLock.lock();
381
382         if(cLock)
383         {
384             ProvisionContext* context = new ProvisionContext(resultCallback);
385
386             std::lock_guard<std::recursive_mutex> lock(*cLock);
387             result = OCProvisionPairwiseDevices(static_cast<void*>(context),
388                     cred.getCredentialType(),
389                     cred.getCredentialKeySize(),
390                     devPtr, const_cast<OicSecAcl_t*>(acl1),
391                     device2.getDevPtr(), const_cast<OicSecAcl_t*>(acl2),
392                     &OCSecureResource::callbackWrapper);
393         }
394         else
395         {
396             oclog() <<"Mutex not found";
397             result = OC_STACK_ERROR;
398         }
399         return result;
400     }
401
402     OCStackResult OCSecureResource::unlinkDevices(const OCSecureResource &device2,
403             ResultCallBack resultCallback)
404     {
405         if(!resultCallback)
406         {
407             oclog() << "Result calback can't be null";
408             return OC_STACK_INVALID_CALLBACK;
409         }
410
411         OCStackResult result;
412         auto cLock = m_csdkLock.lock();
413
414         if(cLock)
415         {
416             ProvisionContext* context = new ProvisionContext(resultCallback);
417
418             std::lock_guard<std::recursive_mutex> lock(*cLock);
419
420             result = OCUnlinkDevices(static_cast<void*>(context),
421                     devPtr, device2.getDevPtr(), &OCSecureResource::callbackWrapper);
422         }
423         else
424         {
425             oclog() <<"Mutex not found";
426             result = OC_STACK_ERROR;
427         }
428         return result;
429     }
430
431     OCStackResult OCSecureResource::removeDevice(unsigned short waitTimeForOwnedDeviceDiscovery,
432             ResultCallBack resultCallback)
433     {
434         if(!resultCallback)
435         {
436             oclog() << "Result calback can't be null";
437             return OC_STACK_INVALID_CALLBACK;
438         }
439
440         OCStackResult result;
441         auto cLock = m_csdkLock.lock();
442
443         if(cLock)
444         {
445             ProvisionContext* context = new ProvisionContext(resultCallback);
446
447             std::lock_guard<std::recursive_mutex> lock(*cLock);
448
449             result = OCRemoveDevice(static_cast<void*>(context), waitTimeForOwnedDeviceDiscovery,
450                     devPtr, &OCSecureResource::callbackWrapper);
451         }
452         else
453         {
454             oclog() <<"Mutex not found";
455             result = OC_STACK_ERROR;
456         }
457         return result;
458     }
459
460     OCStackResult OCSecureResource::getLinkedDevices(UuidList_t &uuidList)
461     {
462         OCStackResult result;
463         size_t numOfDevices = -1;
464         auto devUuid = devPtr->doxm->deviceID;
465         auto cLock = m_csdkLock.lock();
466
467         if(cLock)
468         {
469             std::lock_guard<std::recursive_mutex> lock(*cLock);
470
471             OCUuidList_t* linkedDevs = nullptr, *tmp = nullptr;
472             result = OCGetLinkedStatus(&devUuid, &linkedDevs, &numOfDevices);
473             if (result == OC_STACK_OK)
474             {
475                 for (tmp = linkedDevs; tmp; tmp = tmp->next)
476                 {
477                     uuidList.push_back(tmp->dev);
478                 }
479                 OCDeleteUuidList(linkedDevs);
480             }
481         }
482         else
483         {
484             oclog() <<"Mutex not found";
485             result = OC_STACK_ERROR;
486         }
487         return result;
488     }
489
490     std::string OCSecureResource::getDeviceID()
491     {
492         char base64Buff[B64ENCODE_OUT_SAFESIZE(sizeof(((OicUuid_t*)0)->id)) + 1] = {0,};
493         uint32_t outLen = 0;
494         B64Result b64Ret = B64_OK;
495         std::ostringstream deviceId("");
496
497         validateSecureResource();
498         b64Ret = b64Encode(devPtr->doxm->deviceID.id, sizeof(devPtr->doxm->deviceID.id), base64Buff,
499                 sizeof(base64Buff), &outLen);
500
501         if (B64_OK == b64Ret)
502         {
503             deviceId << base64Buff;
504         }
505         return deviceId.str();
506     }
507
508     OCProvisionDev_t* OCSecureResource::getDevPtr() const
509     {
510         return devPtr;
511     }
512
513     std::string OCSecureResource::getDevAddr()
514     {
515         validateSecureResource();
516         std::string ipAddr(devPtr->endpoint.addr);
517         return ipAddr;
518     }
519
520     int OCSecureResource::getDeviceStatus()
521     {
522         validateSecureResource();
523         return (int)devPtr->devStatus;
524     }
525
526     bool OCSecureResource::getOwnedStatus()
527     {
528         validateSecureResource();
529         return devPtr->doxm->owned;
530     }
531
532     void OCSecureResource::validateSecureResource()
533     {
534         if (!devPtr)
535         {
536             throw OCException("Incomplete secure resource", OC_STACK_RESOURCE_ERROR);
537         }
538     }
539 }