Merge remote-tracking branch 'origin/master' into notification-service
[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 "srmutility.h"
23 #include "base64.h"
24 #include "OCProvisioningManager.h"
25
26 namespace OC
27 {
28     OCStackResult OCSecure::provisionInit(const std::string& dbPath)
29     {
30         OCStackResult result;
31         auto cLock = OCPlatform_impl::Instance().csdkLock().lock();
32
33         if (cLock)
34         {
35             std::lock_guard<std::recursive_mutex> lock(*cLock);
36             result = OCInitPM(dbPath.c_str());
37         }
38         else
39         {
40             oclog() <<"Mutex not found";
41             result = OC_STACK_ERROR;
42         }
43
44         return result;
45     }
46
47     OCStackResult OCSecure::discoverUnownedDevices(unsigned short timeout,
48             DeviceList_t &list)
49     {
50         OCStackResult result;
51         OCProvisionDev_t *pDevList = nullptr, *pCurDev = nullptr, *tmp = nullptr;
52         auto csdkLock = OCPlatform_impl::Instance().csdkLock();
53         auto cLock = csdkLock.lock();
54
55         if (cLock)
56         {
57             std::lock_guard<std::recursive_mutex> lock(*cLock);
58             result = OCDiscoverUnownedDevices(timeout, &pDevList);
59             if (result == OC_STACK_OK)
60             {
61                 // Create DeviceList of OCSecureResource's
62                 pCurDev = pDevList;
63                 while (pCurDev)
64                 {
65                     tmp = pCurDev;
66                     list.push_back(std::shared_ptr<OCSecureResource>(
67                                 new OCSecureResource(csdkLock, pCurDev)));
68                     pCurDev = pCurDev->next;
69                     tmp->next = nullptr;
70                 }
71             }
72             else
73             {
74                 oclog() <<"Unowned device discovery failed!";
75             }
76         }
77         else
78         {
79             oclog() <<"Mutex not found";
80             result = OC_STACK_ERROR;
81         }
82
83         return result;
84     }
85
86     OCStackResult OCSecure::discoverOwnedDevices(unsigned short timeout,
87             DeviceList_t &list)
88     {
89         OCStackResult result;
90         OCProvisionDev_t *pDevList = nullptr, *pCurDev = nullptr, *tmp = nullptr;
91         auto csdkLock = OCPlatform_impl::Instance().csdkLock();
92         auto cLock = csdkLock.lock();
93
94         if (cLock)
95         {
96             std::lock_guard<std::recursive_mutex> lock(*cLock);
97             result = OCDiscoverOwnedDevices(timeout, &pDevList);
98             if (result == OC_STACK_OK)
99             {
100                 pCurDev = pDevList;
101                 while (pCurDev)
102                 {
103                     tmp = pCurDev;
104                     list.push_back(std::shared_ptr<OCSecureResource>(
105                                 new OCSecureResource(csdkLock, pCurDev)));
106                     pCurDev = pCurDev->next;
107                     tmp->next = nullptr;
108                 }
109             }
110             else
111             {
112                 oclog() <<"Owned device discovery failed!";
113             }
114         }
115         else
116         {
117             oclog() <<"Mutex not found";
118             result = OC_STACK_ERROR;
119         }
120
121         return result;
122     }
123
124     OCStackResult OCSecure::discoverSecureResource(unsigned short timeout,
125             const std::string& host,
126             OCConnectivityType connType,
127             DeviceList_t &list)
128     {
129         OCStackResult result;
130         OCProvisionDev_t *pDevList = nullptr, *pCurDev = nullptr, *tmp = nullptr;
131         auto csdkLock = OCPlatform_impl::Instance().csdkLock();
132         auto cLock = csdkLock.lock();
133
134         if (cLock)
135         {
136             std::lock_guard<std::recursive_mutex> lock(*cLock);
137             result = OCDiscoverSecureResource(timeout, host.c_str(), connType, &pDevList);
138             if (result == OC_STACK_OK)
139             {
140                 pCurDev = pDevList;
141                 while (pCurDev)
142                 {
143                     tmp = pCurDev;
144                     list.push_back(std::shared_ptr<OCSecureResource>(
145                                 new OCSecureResource(csdkLock, pCurDev)));
146                     pCurDev = pCurDev->next;
147                     tmp->next = nullptr;
148                 }
149             }
150             else
151             {
152                 oclog() <<"Secure resource discovery failed!";
153                 result = OC_STACK_ERROR;
154             }
155         }
156         else
157         {
158             oclog() <<"Mutex not found";
159             result = OC_STACK_ERROR;
160         }
161
162         return result;
163     }
164
165     OCStackResult OCSecure::setOwnerTransferCallbackData(OicSecOxm_t oxm,
166             OTMCallbackData_t* callbackData, InputPinCallback inputPin)
167     {
168         if (NULL == callbackData || oxm >= OIC_OXM_COUNT)
169         {
170             oclog() <<"Invalid callbackData or OXM type";
171             return OC_STACK_INVALID_PARAM;
172         }
173
174         if ((OIC_RANDOM_DEVICE_PIN == oxm) && !inputPin)
175         {
176             oclog() <<"for OXM type DEVICE_PIN, inputPin callback can't be null";
177             return OC_STACK_INVALID_PARAM;
178         }
179
180         OCStackResult result;
181         auto cLock = OCPlatform_impl::Instance().csdkLock().lock();
182
183         if (cLock)
184         {
185             std::lock_guard<std::recursive_mutex> lock(*cLock);
186             result = OCSetOwnerTransferCallbackData(oxm, callbackData);
187             if (result == OC_STACK_OK && (OIC_RANDOM_DEVICE_PIN == oxm))
188             {
189                 SetInputPinCB(inputPin);
190             }
191         }
192         else
193         {
194             oclog() <<"Mutex not found";
195             result = OC_STACK_ERROR;
196         }
197
198         return result;
199
200     }
201
202     OCStackResult OCSecure::getDevInfoFromNetwork(unsigned short timeout,
203             DeviceList_t &ownedDevList,
204             DeviceList_t &unownedDevList)
205     {
206         OCStackResult result = OC_STACK_OK;
207         OCProvisionDev_t *owned = nullptr, *unowned = nullptr, *tmp = nullptr, *dev = nullptr;
208         auto csdkLock = OCPlatform_impl::Instance().csdkLock();
209         auto cLock = csdkLock.lock();
210
211         if (cLock)
212         {
213             std::lock_guard<std::recursive_mutex> lock(*cLock);
214
215             result = OCGetDevInfoFromNetwork(timeout, &owned, &unowned);
216
217             if (result == OC_STACK_OK)
218             {
219                 dev = owned;
220                 while (dev)
221                 {
222                     tmp = dev;
223                     ownedDevList.push_back(std::shared_ptr<OCSecureResource>(
224                                 new OCSecureResource(csdkLock, dev)));
225                     dev = dev->next;
226                     tmp->next = nullptr;
227                 }
228
229                 dev = unowned;
230                 while (dev)
231                 {
232                     tmp = dev;
233                     unownedDevList.push_back(std::shared_ptr<OCSecureResource>(
234                                 new OCSecureResource(csdkLock,  dev)));
235                     dev = dev->next;
236                     tmp->next = nullptr;
237                 }
238             }
239         }
240         else
241         {
242             oclog() <<"Mutex not found";
243             result = OC_STACK_ERROR;
244         }
245
246         return result;
247     }
248
249     OCStackResult OCSecure::setDisplayPinCB(GeneratePinCallback displayPin)
250     {
251         if (!displayPin)
252         {
253             oclog() <<"displayPin can't be null";
254             return OC_STACK_INVALID_PARAM;
255         }
256
257         OCStackResult result = OC_STACK_OK;
258         auto cLock = OCPlatform_impl::Instance().csdkLock().lock();
259
260         if (cLock)
261         {
262             std::lock_guard<std::recursive_mutex> lock(*cLock);
263             SetGeneratePinCB(displayPin);
264         }
265         else
266         {
267             oclog() <<"Mutex not found";
268             result = OC_STACK_ERROR;
269         }
270
271         return result;
272     }
273
274     OCStackResult OCSecure::removeDeviceWithUuid(unsigned short waitTimeForOwnedDeviceDiscovery,
275             std::string uuid,
276             ResultCallBack resultCallback)
277     {
278         if (!resultCallback)
279         {
280             oclog() << "Result calback can't be null";
281             return OC_STACK_INVALID_CALLBACK;
282         }
283
284         OCStackResult result;
285         auto cLock = OCPlatform_impl::Instance().csdkLock().lock();
286
287         if (cLock)
288         {
289             ProvisionContext* context = new ProvisionContext(resultCallback);
290
291             std::lock_guard<std::recursive_mutex> lock(*cLock);
292
293             OicUuid_t targetDev;
294             result = ConvertStrToUuid(uuid.c_str(), &targetDev);
295             if(OC_STACK_OK == result)
296             {
297                 result = OCRemoveDeviceWithUuid(static_cast<void*>(context), waitTimeForOwnedDeviceDiscovery,
298                         &targetDev, &OCSecureResource::callbackWrapper);
299             }
300             else
301             {
302                 oclog() <<"Can not convert struuid to uuid";
303             }
304         }
305         else
306         {
307             oclog() <<"Mutex not found";
308             result = OC_STACK_ERROR;
309         }
310         return result;
311     }
312
313
314     void OCSecureResource::callbackWrapper(void* ctx, int nOfRes, OCProvisionResult_t *arr, bool hasError)
315     {
316         PMResultList_t *results = nullptr;
317         ProvisionContext* context = static_cast<ProvisionContext*>(ctx);
318
319         try
320         {
321             results = new PMResultList_t;
322         }
323         catch (std::bad_alloc& e)
324         {
325             oclog() <<"Bad alloc exception";
326             return;
327         }
328
329         for (int i = 0; i < nOfRes; i++)
330         {
331             results->push_back(arr[i]);
332         }
333
334         std::thread exec(context->callback, results, hasError);
335         exec.detach();
336
337         delete context;
338     }
339
340     OCSecureResource::OCSecureResource(): m_csdkLock(std::weak_ptr<std::recursive_mutex>()),
341                                         devPtr(nullptr)
342     {
343     }
344
345     OCSecureResource::OCSecureResource(std::weak_ptr<std::recursive_mutex> csdkLock,
346             OCProvisionDev_t *dPtr)
347         :m_csdkLock(csdkLock), devPtr(dPtr)
348     {
349     }
350
351     OCSecureResource::~OCSecureResource()
352     {
353         if (devPtr)
354         {
355             OCDeleteDiscoveredDevices(devPtr);
356         }
357     }
358
359     OCStackResult OCSecureResource::doOwnershipTransfer(ResultCallBack resultCallback)
360     {
361         if (!resultCallback)
362         {
363             oclog() <<"Result callback can't be null";
364             return OC_STACK_INVALID_CALLBACK;
365         }
366
367         OCStackResult result;
368         auto cLock = m_csdkLock.lock();
369
370         if (cLock)
371         {
372             ProvisionContext* context = new ProvisionContext(resultCallback);
373
374             std::lock_guard<std::recursive_mutex> lock(*cLock);
375             result = OCDoOwnershipTransfer(static_cast<void*>(context),
376                     devPtr, &OCSecureResource::callbackWrapper);
377         }
378         else
379         {
380             oclog() <<"Mutex not found";
381             result = OC_STACK_ERROR;
382         }
383         return result;
384     }
385
386     OCStackResult OCSecureResource::provisionACL( const OicSecAcl_t* acl,
387             ResultCallBack resultCallback)
388     {
389         if (!acl)
390         {
391             oclog() <<"ACL can't be null";
392             return OC_STACK_INVALID_PARAM;
393         }
394         if (!resultCallback)
395         {
396             oclog() <<"result callback can not be null";
397             return OC_STACK_INVALID_CALLBACK;
398         }
399
400         OCStackResult result;
401         auto cLock = m_csdkLock.lock();
402
403         if (cLock)
404         {
405             ProvisionContext* context = new ProvisionContext(resultCallback);
406
407             std::lock_guard<std::recursive_mutex> lock(*cLock);
408             result = OCProvisionACL(static_cast<void*>(context),
409                     devPtr, const_cast<OicSecAcl_t*>(acl),
410                     &OCSecureResource::callbackWrapper);
411         }
412         else
413         {
414             oclog() <<"Mutex not found";
415             result = OC_STACK_ERROR;
416         }
417         return result;
418     }
419
420     OCStackResult OCSecureResource::provisionCredentials(const Credential &cred,
421             const OCSecureResource &device2, ResultCallBack resultCallback)
422     {
423         if (!resultCallback)
424         {
425             oclog() << "Result calback can't be null";
426             return OC_STACK_INVALID_CALLBACK;
427         }
428
429         OCStackResult result;
430         auto cLock = m_csdkLock.lock();
431
432         if (cLock)
433         {
434             ProvisionContext* context = new ProvisionContext(resultCallback);
435
436             std::lock_guard<std::recursive_mutex> lock(*cLock);
437             result = OCProvisionCredentials(static_cast<void*>(context),
438                     cred.getCredentialType(),
439                     cred.getCredentialKeySize(),
440                     devPtr, device2.getDevPtr(),
441                     &OCSecureResource::callbackWrapper);
442         }
443         else
444         {
445             oclog() <<"Mutex not found";
446             result = OC_STACK_ERROR;
447         }
448         return result;
449     }
450
451     OCStackResult OCSecureResource::provisionPairwiseDevices(const Credential &cred,
452             const OicSecAcl_t* acl1, const OCSecureResource &device2, const OicSecAcl_t* acl2,
453             ResultCallBack resultCallback)
454     {
455         if (!resultCallback)
456         {
457             oclog() << "Result callback can not be null";
458             return OC_STACK_INVALID_CALLBACK;
459         }
460
461         OCStackResult result;
462         auto cLock = m_csdkLock.lock();
463
464         if (cLock)
465         {
466             ProvisionContext* context = new ProvisionContext(resultCallback);
467
468             std::lock_guard<std::recursive_mutex> lock(*cLock);
469             result = OCProvisionPairwiseDevices(static_cast<void*>(context),
470                     cred.getCredentialType(),
471                     cred.getCredentialKeySize(),
472                     devPtr, const_cast<OicSecAcl_t*>(acl1),
473                     device2.getDevPtr(), const_cast<OicSecAcl_t*>(acl2),
474                     &OCSecureResource::callbackWrapper);
475         }
476         else
477         {
478             oclog() <<"Mutex not found";
479             result = OC_STACK_ERROR;
480         }
481         return result;
482     }
483
484     OCStackResult OCSecureResource::unlinkDevices(const OCSecureResource &device2,
485             ResultCallBack resultCallback)
486     {
487         if (!resultCallback)
488         {
489             oclog() << "Result calback can't be null";
490             return OC_STACK_INVALID_CALLBACK;
491         }
492
493         OCStackResult result;
494         auto cLock = m_csdkLock.lock();
495
496         if (cLock)
497         {
498             ProvisionContext* context = new ProvisionContext(resultCallback);
499
500             std::lock_guard<std::recursive_mutex> lock(*cLock);
501
502             result = OCUnlinkDevices(static_cast<void*>(context),
503                     devPtr, device2.getDevPtr(), &OCSecureResource::callbackWrapper);
504         }
505         else
506         {
507             oclog() <<"Mutex not found";
508             result = OC_STACK_ERROR;
509         }
510         return result;
511     }
512
513     OCStackResult OCSecureResource::removeDevice(unsigned short waitTimeForOwnedDeviceDiscovery,
514             ResultCallBack resultCallback)
515     {
516         if (!resultCallback)
517         {
518             oclog() << "Result calback can't be null";
519             return OC_STACK_INVALID_CALLBACK;
520         }
521
522         OCStackResult result;
523         auto cLock = m_csdkLock.lock();
524
525         if (cLock)
526         {
527             ProvisionContext* context = new ProvisionContext(resultCallback);
528
529             std::lock_guard<std::recursive_mutex> lock(*cLock);
530
531             result = OCRemoveDevice(static_cast<void*>(context), waitTimeForOwnedDeviceDiscovery,
532                     devPtr, &OCSecureResource::callbackWrapper);
533         }
534         else
535         {
536             oclog() <<"Mutex not found";
537             result = OC_STACK_ERROR;
538         }
539         return result;
540     }
541
542     OCStackResult OCSecureResource::getLinkedDevices(UuidList_t &uuidList)
543     {
544         OCStackResult result;
545         size_t numOfDevices = -1;
546         auto devUuid = devPtr->doxm->deviceID;
547         auto cLock = m_csdkLock.lock();
548
549         if (cLock)
550         {
551             std::lock_guard<std::recursive_mutex> lock(*cLock);
552
553             OCUuidList_t* linkedDevs = nullptr, *tmp = nullptr;
554             result = OCGetLinkedStatus(&devUuid, &linkedDevs, &numOfDevices);
555             if (result == OC_STACK_OK)
556             {
557                 for (tmp = linkedDevs; tmp; tmp = tmp->next)
558                 {
559                     uuidList.push_back(tmp->dev);
560                 }
561                 OCDeleteUuidList(linkedDevs);
562             }
563         }
564         else
565         {
566             oclog() <<"Mutex not found";
567             result = OC_STACK_ERROR;
568         }
569         return result;
570     }
571
572     OCStackResult OCSecureResource::provisionDirectPairing( const OicSecPconf_t* pconf,
573             ResultCallBack resultCallback)
574     {
575         if (!pconf)
576         {
577             oclog() <<"PCONF can't be null";
578             return OC_STACK_INVALID_PARAM;
579         }
580         if (!resultCallback)
581         {
582             oclog() <<"result callback can not be null";
583             return OC_STACK_INVALID_CALLBACK;
584         }
585
586         OCStackResult result;
587         auto cLock = m_csdkLock.lock();
588
589         if (cLock)
590         {
591             ProvisionContext* context = new ProvisionContext(resultCallback);
592
593             std::lock_guard<std::recursive_mutex> lock(*cLock);
594             result = OCProvisionDirectPairing(static_cast<void*>(context),
595                     devPtr, const_cast<OicSecPconf_t*>(pconf),
596                     &OCSecureResource::callbackWrapper);
597         }
598         else
599         {
600             oclog() <<"Mutex not found";
601             result = OC_STACK_ERROR;
602         }
603         return result;
604     }
605
606     std::string OCSecureResource::getDeviceID()
607     {
608         std::ostringstream deviceId("");
609         char *devID = nullptr;
610
611         validateSecureResource();
612
613         if (OC_STACK_OK == ConvertUuidToStr(&(devPtr->doxm->deviceID), &devID))
614         {
615             deviceId << devID;
616             free(devID);
617         }
618         else
619         {
620             oclog() <<"Can not convert uuid to struuid";
621         }
622         return deviceId.str();
623     }
624
625     OCProvisionDev_t* OCSecureResource::getDevPtr() const
626     {
627         return devPtr;
628     }
629
630     std::string OCSecureResource::getDevAddr()
631     {
632         validateSecureResource();
633         std::string ipAddr(devPtr->endpoint.addr);
634         return ipAddr;
635     }
636
637     int OCSecureResource::getDeviceStatus()
638     {
639         validateSecureResource();
640         return (int)devPtr->devStatus;
641     }
642
643     bool OCSecureResource::getOwnedStatus()
644     {
645         validateSecureResource();
646         return devPtr->doxm->owned;
647     }
648
649     void OCSecureResource::validateSecureResource()
650     {
651         if (!devPtr)
652         {
653             throw OCException("Incomplete secure resource", OC_STACK_RESOURCE_ERROR);
654         }
655     }
656 }