Imported Upstream version 1.1.1
[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::setOwnerTransferCallbackData(OicSecOxm_t oxm,
125             OTMCallbackData_t* callbackData, InputPinCallback inputPin)
126     {
127         if (NULL == callbackData || oxm >= OIC_OXM_COUNT)
128         {
129             oclog() <<"Invalid callbackData or OXM type";
130             return OC_STACK_INVALID_PARAM;
131         }
132
133         if ((OIC_RANDOM_DEVICE_PIN == oxm) && !inputPin)
134         {
135             oclog() <<"for OXM type DEVICE_PIN, inputPin callback can't be null";
136             return OC_STACK_INVALID_PARAM;
137         }
138
139         OCStackResult result;
140         auto cLock = OCPlatform_impl::Instance().csdkLock().lock();
141
142         if (cLock)
143         {
144             std::lock_guard<std::recursive_mutex> lock(*cLock);
145             result = OCSetOwnerTransferCallbackData(oxm, callbackData);
146             if (result == OC_STACK_OK && (OIC_RANDOM_DEVICE_PIN == oxm))
147             {
148                 SetInputPinCB(inputPin);
149             }
150         }
151         else
152         {
153             oclog() <<"Mutex not found";
154             result = OC_STACK_ERROR;
155         }
156
157         return result;
158
159     }
160
161     OCStackResult OCSecure::getDevInfoFromNetwork(unsigned short timeout,
162             DeviceList_t &ownedDevList,
163             DeviceList_t &unownedDevList)
164     {
165         OCStackResult result = OC_STACK_OK;
166         OCProvisionDev_t *owned = nullptr, *unowned = nullptr, *tmp = nullptr, *dev = nullptr;
167         auto csdkLock = OCPlatform_impl::Instance().csdkLock();
168         auto cLock = csdkLock.lock();
169
170         if (cLock)
171         {
172             std::lock_guard<std::recursive_mutex> lock(*cLock);
173
174             result = OCGetDevInfoFromNetwork(timeout, &owned, &unowned);
175
176             if (result == OC_STACK_OK)
177             {
178                 dev = owned;
179                 while (dev)
180                 {
181                     tmp = dev;
182                     ownedDevList.push_back(std::shared_ptr<OCSecureResource>(
183                                 new OCSecureResource(csdkLock, dev)));
184                     dev = dev->next;
185                     tmp->next = nullptr;
186                 }
187
188                 dev = unowned;
189                 while (dev)
190                 {
191                     tmp = dev;
192                     unownedDevList.push_back(std::shared_ptr<OCSecureResource>(
193                                 new OCSecureResource(csdkLock,  dev)));
194                     dev = dev->next;
195                     tmp->next = nullptr;
196                 }
197             }
198         }
199         else
200         {
201             oclog() <<"Mutex not found";
202             result = OC_STACK_ERROR;
203         }
204
205         return result;
206     }
207
208     OCStackResult OCSecure::setDisplayPinCB(GeneratePinCallback displayPin)
209     {
210         if (!displayPin)
211         {
212             oclog() <<"displayPin can't be null";
213             return OC_STACK_INVALID_PARAM;
214         }
215
216         OCStackResult result = OC_STACK_OK;
217         auto cLock = OCPlatform_impl::Instance().csdkLock().lock();
218
219         if (cLock)
220         {
221             std::lock_guard<std::recursive_mutex> lock(*cLock);
222             SetGeneratePinCB(displayPin);
223         }
224         else
225         {
226             oclog() <<"Mutex not found";
227             result = OC_STACK_ERROR;
228         }
229
230         return result;
231     }
232
233     void OCSecureResource::callbackWrapper(void* ctx, int nOfRes, OCProvisionResult_t *arr, bool hasError)
234     {
235         PMResultList_t *results = nullptr;
236         ProvisionContext* context = static_cast<ProvisionContext*>(ctx);
237
238         try
239         {
240             results = new PMResultList_t;
241         }
242         catch (std::bad_alloc& e)
243         {
244             oclog() <<"Bad alloc exception";
245             return;
246         }
247
248         for (int i = 0; i < nOfRes; i++)
249         {
250             results->push_back(arr[i]);
251         }
252
253         std::thread exec(context->callback, results, hasError);
254         exec.detach();
255
256         delete context;
257     }
258
259     OCSecureResource::OCSecureResource(): m_csdkLock(std::weak_ptr<std::recursive_mutex>()),
260                                         devPtr(nullptr)
261     {
262     }
263
264     OCSecureResource::OCSecureResource(std::weak_ptr<std::recursive_mutex> csdkLock,
265             OCProvisionDev_t *dPtr)
266         :m_csdkLock(csdkLock), devPtr(dPtr)
267     {
268     }
269
270     OCSecureResource::~OCSecureResource()
271     {
272         if (devPtr)
273         {
274             OCDeleteDiscoveredDevices(devPtr);
275         }
276     }
277
278     OCStackResult OCSecureResource::doOwnershipTransfer(ResultCallBack resultCallback)
279     {
280         if (!resultCallback)
281         {
282             oclog() <<"Result callback can't be null";
283             return OC_STACK_INVALID_CALLBACK;
284         }
285
286         OCStackResult result;
287         auto cLock = m_csdkLock.lock();
288
289         if (cLock)
290         {
291             ProvisionContext* context = new ProvisionContext(resultCallback);
292
293             std::lock_guard<std::recursive_mutex> lock(*cLock);
294             result = OCDoOwnershipTransfer(static_cast<void*>(context),
295                     devPtr, &OCSecureResource::callbackWrapper);
296         }
297         else
298         {
299             oclog() <<"Mutex not found";
300             result = OC_STACK_ERROR;
301         }
302         return result;
303     }
304
305     OCStackResult OCSecureResource::provisionACL( const OicSecAcl_t* acl,
306             ResultCallBack resultCallback)
307     {
308         if (!acl)
309         {
310             oclog() <<"ACL can't be null";
311             return OC_STACK_INVALID_PARAM;
312         }
313         if (!resultCallback)
314         {
315             oclog() <<"result callback can not be null";
316             return OC_STACK_INVALID_CALLBACK;
317         }
318
319         OCStackResult result;
320         auto cLock = m_csdkLock.lock();
321
322         if (cLock)
323         {
324             ProvisionContext* context = new ProvisionContext(resultCallback);
325
326             std::lock_guard<std::recursive_mutex> lock(*cLock);
327             result = OCProvisionACL(static_cast<void*>(context),
328                     devPtr, const_cast<OicSecAcl_t*>(acl),
329                     &OCSecureResource::callbackWrapper);
330         }
331         else
332         {
333             oclog() <<"Mutex not found";
334             result = OC_STACK_ERROR;
335         }
336         return result;
337     }
338
339     OCStackResult OCSecureResource::provisionCredentials(const Credential &cred,
340             const OCSecureResource &device2, ResultCallBack resultCallback)
341     {
342         if (!resultCallback)
343         {
344             oclog() << "Result calback can't be null";
345             return OC_STACK_INVALID_CALLBACK;
346         }
347
348         OCStackResult result;
349         auto cLock = m_csdkLock.lock();
350
351         if (cLock)
352         {
353             ProvisionContext* context = new ProvisionContext(resultCallback);
354
355             std::lock_guard<std::recursive_mutex> lock(*cLock);
356             result = OCProvisionCredentials(static_cast<void*>(context),
357                     cred.getCredentialType(),
358                     cred.getCredentialKeySize(),
359                     devPtr, device2.getDevPtr(),
360                     &OCSecureResource::callbackWrapper);
361         }
362         else
363         {
364             oclog() <<"Mutex not found";
365             result = OC_STACK_ERROR;
366         }
367         return result;
368     }
369
370     OCStackResult OCSecureResource::provisionPairwiseDevices(const Credential &cred,
371             const OicSecAcl_t* acl1, const OCSecureResource &device2, const OicSecAcl_t* acl2,
372             ResultCallBack resultCallback)
373     {
374         if (!resultCallback)
375         {
376             oclog() << "Result callback can not be null";
377             return OC_STACK_INVALID_CALLBACK;
378         }
379
380         OCStackResult result;
381         auto cLock = m_csdkLock.lock();
382
383         if (cLock)
384         {
385             ProvisionContext* context = new ProvisionContext(resultCallback);
386
387             std::lock_guard<std::recursive_mutex> lock(*cLock);
388             result = OCProvisionPairwiseDevices(static_cast<void*>(context),
389                     cred.getCredentialType(),
390                     cred.getCredentialKeySize(),
391                     devPtr, const_cast<OicSecAcl_t*>(acl1),
392                     device2.getDevPtr(), const_cast<OicSecAcl_t*>(acl2),
393                     &OCSecureResource::callbackWrapper);
394         }
395         else
396         {
397             oclog() <<"Mutex not found";
398             result = OC_STACK_ERROR;
399         }
400         return result;
401     }
402
403     OCStackResult OCSecureResource::unlinkDevices(const OCSecureResource &device2,
404             ResultCallBack resultCallback)
405     {
406         if (!resultCallback)
407         {
408             oclog() << "Result calback can't be null";
409             return OC_STACK_INVALID_CALLBACK;
410         }
411
412         OCStackResult result;
413         auto cLock = m_csdkLock.lock();
414
415         if (cLock)
416         {
417             ProvisionContext* context = new ProvisionContext(resultCallback);
418
419             std::lock_guard<std::recursive_mutex> lock(*cLock);
420
421             result = OCUnlinkDevices(static_cast<void*>(context),
422                     devPtr, device2.getDevPtr(), &OCSecureResource::callbackWrapper);
423         }
424         else
425         {
426             oclog() <<"Mutex not found";
427             result = OC_STACK_ERROR;
428         }
429         return result;
430     }
431
432     OCStackResult OCSecureResource::removeDevice(unsigned short waitTimeForOwnedDeviceDiscovery,
433             ResultCallBack resultCallback)
434     {
435         if (!resultCallback)
436         {
437             oclog() << "Result calback can't be null";
438             return OC_STACK_INVALID_CALLBACK;
439         }
440
441         OCStackResult result;
442         auto cLock = m_csdkLock.lock();
443
444         if (cLock)
445         {
446             ProvisionContext* context = new ProvisionContext(resultCallback);
447
448             std::lock_guard<std::recursive_mutex> lock(*cLock);
449
450             result = OCRemoveDevice(static_cast<void*>(context), waitTimeForOwnedDeviceDiscovery,
451                     devPtr, &OCSecureResource::callbackWrapper);
452         }
453         else
454         {
455             oclog() <<"Mutex not found";
456             result = OC_STACK_ERROR;
457         }
458         return result;
459     }
460
461     OCStackResult OCSecureResource::removeDeviceWithUuid(unsigned short waitTimeForOwnedDeviceDiscovery,
462             std::string uuid,
463             ResultCallBack resultCallback)
464     {
465         if (!resultCallback)
466         {
467             oclog() << "Result calback can't be null";
468             return OC_STACK_INVALID_CALLBACK;
469         }
470
471         OCStackResult result;
472         auto cLock = m_csdkLock.lock();
473
474         if (cLock)
475         {
476             ProvisionContext* context = new ProvisionContext(resultCallback);
477
478             std::lock_guard<std::recursive_mutex> lock(*cLock);
479
480             OicUuid_t targetDev;
481             result = ConvertStrToUuid(uuid.c_str(), &targetDev);
482             if(OC_STACK_OK == result)
483             {
484                 result = OCRemoveDeviceWithUuid(static_cast<void*>(context), waitTimeForOwnedDeviceDiscovery,
485                         &targetDev, &OCSecureResource::callbackWrapper);
486             }
487             else
488             {
489                 oclog() <<"Can not convert struuid to uuid";
490             }
491         }
492         else
493         {
494             oclog() <<"Mutex not found";
495             result = OC_STACK_ERROR;
496         }
497         return result;
498     }
499
500     OCStackResult OCSecureResource::getLinkedDevices(UuidList_t &uuidList)
501     {
502         OCStackResult result;
503         size_t numOfDevices = -1;
504         auto devUuid = devPtr->doxm->deviceID;
505         auto cLock = m_csdkLock.lock();
506
507         if (cLock)
508         {
509             std::lock_guard<std::recursive_mutex> lock(*cLock);
510
511             OCUuidList_t* linkedDevs = nullptr, *tmp = nullptr;
512             result = OCGetLinkedStatus(&devUuid, &linkedDevs, &numOfDevices);
513             if (result == OC_STACK_OK)
514             {
515                 for (tmp = linkedDevs; tmp; tmp = tmp->next)
516                 {
517                     uuidList.push_back(tmp->dev);
518                 }
519                 OCDeleteUuidList(linkedDevs);
520             }
521         }
522         else
523         {
524             oclog() <<"Mutex not found";
525             result = OC_STACK_ERROR;
526         }
527         return result;
528     }
529
530     OCStackResult OCSecureResource::provisionDirectPairing( const OicSecPconf_t* pconf,
531             ResultCallBack resultCallback)
532     {
533         if (!pconf)
534         {
535             oclog() <<"PCONF can't be null";
536             return OC_STACK_INVALID_PARAM;
537         }
538         if (!resultCallback)
539         {
540             oclog() <<"result callback can not be null";
541             return OC_STACK_INVALID_CALLBACK;
542         }
543
544         OCStackResult result;
545         auto cLock = m_csdkLock.lock();
546
547         if (cLock)
548         {
549             ProvisionContext* context = new ProvisionContext(resultCallback);
550
551             std::lock_guard<std::recursive_mutex> lock(*cLock);
552             result = OCProvisionDirectPairing(static_cast<void*>(context),
553                     devPtr, const_cast<OicSecPconf_t*>(pconf),
554                     &OCSecureResource::callbackWrapper);
555         }
556         else
557         {
558             oclog() <<"Mutex not found";
559             result = OC_STACK_ERROR;
560         }
561         return result;
562     }
563
564     std::string OCSecureResource::getDeviceID()
565     {
566         std::ostringstream deviceId("");
567         char *devID = nullptr;
568
569         validateSecureResource();
570
571         if (OC_STACK_OK == ConvertUuidToStr(&(devPtr->doxm->deviceID), &devID))
572         {
573             deviceId << devID;
574             free(devID);
575         }
576         else
577         {
578             oclog() <<"Can not convert uuid to struuid";
579         }
580         return deviceId.str();
581     }
582
583     OCProvisionDev_t* OCSecureResource::getDevPtr() const
584     {
585         return devPtr;
586     }
587
588     std::string OCSecureResource::getDevAddr()
589     {
590         validateSecureResource();
591         std::string ipAddr(devPtr->endpoint.addr);
592         return ipAddr;
593     }
594
595     int OCSecureResource::getDeviceStatus()
596     {
597         validateSecureResource();
598         return (int)devPtr->devStatus;
599     }
600
601     bool OCSecureResource::getOwnedStatus()
602     {
603         validateSecureResource();
604         return devPtr->doxm->owned;
605     }
606
607     void OCSecureResource::validateSecureResource()
608     {
609         if (!devPtr)
610         {
611             throw OCException("Incomplete secure resource", OC_STACK_RESOURCE_ERROR);
612         }
613     }
614 }