Merge branch '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::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     OCStackResult OCSecure::removeDeviceWithUuid(unsigned short waitTimeForOwnedDeviceDiscovery,
234             std::string uuid,
235             ResultCallBack resultCallback)
236     {
237         if (!resultCallback)
238         {
239             oclog() << "Result calback can't be null";
240             return OC_STACK_INVALID_CALLBACK;
241         }
242
243         OCStackResult result;
244         auto cLock = OCPlatform_impl::Instance().csdkLock().lock();
245
246         if (cLock)
247         {
248             ProvisionContext* context = new ProvisionContext(resultCallback);
249
250             std::lock_guard<std::recursive_mutex> lock(*cLock);
251
252             OicUuid_t targetDev;
253             result = ConvertStrToUuid(uuid.c_str(), &targetDev);
254             if(OC_STACK_OK == result)
255             {
256                 result = OCRemoveDeviceWithUuid(static_cast<void*>(context), waitTimeForOwnedDeviceDiscovery,
257                         &targetDev, &OCSecureResource::callbackWrapper);
258             }
259             else
260             {
261                 oclog() <<"Can not convert struuid to uuid";
262             }
263         }
264         else
265         {
266             oclog() <<"Mutex not found";
267             result = OC_STACK_ERROR;
268         }
269         return result;
270     }
271
272
273     void OCSecureResource::callbackWrapper(void* ctx, int nOfRes, OCProvisionResult_t *arr, bool hasError)
274     {
275         PMResultList_t *results = nullptr;
276         ProvisionContext* context = static_cast<ProvisionContext*>(ctx);
277
278         try
279         {
280             results = new PMResultList_t;
281         }
282         catch (std::bad_alloc& e)
283         {
284             oclog() <<"Bad alloc exception";
285             return;
286         }
287
288         for (int i = 0; i < nOfRes; i++)
289         {
290             results->push_back(arr[i]);
291         }
292
293         std::thread exec(context->callback, results, hasError);
294         exec.detach();
295
296         delete context;
297     }
298
299     OCSecureResource::OCSecureResource(): m_csdkLock(std::weak_ptr<std::recursive_mutex>()),
300                                         devPtr(nullptr)
301     {
302     }
303
304     OCSecureResource::OCSecureResource(std::weak_ptr<std::recursive_mutex> csdkLock,
305             OCProvisionDev_t *dPtr)
306         :m_csdkLock(csdkLock), devPtr(dPtr)
307     {
308     }
309
310     OCSecureResource::~OCSecureResource()
311     {
312         if (devPtr)
313         {
314             OCDeleteDiscoveredDevices(devPtr);
315         }
316     }
317
318     OCStackResult OCSecureResource::doOwnershipTransfer(ResultCallBack resultCallback)
319     {
320         if (!resultCallback)
321         {
322             oclog() <<"Result callback can't be null";
323             return OC_STACK_INVALID_CALLBACK;
324         }
325
326         OCStackResult result;
327         auto cLock = m_csdkLock.lock();
328
329         if (cLock)
330         {
331             ProvisionContext* context = new ProvisionContext(resultCallback);
332
333             std::lock_guard<std::recursive_mutex> lock(*cLock);
334             result = OCDoOwnershipTransfer(static_cast<void*>(context),
335                     devPtr, &OCSecureResource::callbackWrapper);
336         }
337         else
338         {
339             oclog() <<"Mutex not found";
340             result = OC_STACK_ERROR;
341         }
342         return result;
343     }
344
345     OCStackResult OCSecureResource::provisionACL( const OicSecAcl_t* acl,
346             ResultCallBack resultCallback)
347     {
348         if (!acl)
349         {
350             oclog() <<"ACL can't be null";
351             return OC_STACK_INVALID_PARAM;
352         }
353         if (!resultCallback)
354         {
355             oclog() <<"result callback can not be null";
356             return OC_STACK_INVALID_CALLBACK;
357         }
358
359         OCStackResult result;
360         auto cLock = m_csdkLock.lock();
361
362         if (cLock)
363         {
364             ProvisionContext* context = new ProvisionContext(resultCallback);
365
366             std::lock_guard<std::recursive_mutex> lock(*cLock);
367             result = OCProvisionACL(static_cast<void*>(context),
368                     devPtr, const_cast<OicSecAcl_t*>(acl),
369                     &OCSecureResource::callbackWrapper);
370         }
371         else
372         {
373             oclog() <<"Mutex not found";
374             result = OC_STACK_ERROR;
375         }
376         return result;
377     }
378
379     OCStackResult OCSecureResource::provisionCredentials(const Credential &cred,
380             const OCSecureResource &device2, ResultCallBack resultCallback)
381     {
382         if (!resultCallback)
383         {
384             oclog() << "Result calback can't be null";
385             return OC_STACK_INVALID_CALLBACK;
386         }
387
388         OCStackResult result;
389         auto cLock = m_csdkLock.lock();
390
391         if (cLock)
392         {
393             ProvisionContext* context = new ProvisionContext(resultCallback);
394
395             std::lock_guard<std::recursive_mutex> lock(*cLock);
396             result = OCProvisionCredentials(static_cast<void*>(context),
397                     cred.getCredentialType(),
398                     cred.getCredentialKeySize(),
399                     devPtr, device2.getDevPtr(),
400                     &OCSecureResource::callbackWrapper);
401         }
402         else
403         {
404             oclog() <<"Mutex not found";
405             result = OC_STACK_ERROR;
406         }
407         return result;
408     }
409
410     OCStackResult OCSecureResource::provisionPairwiseDevices(const Credential &cred,
411             const OicSecAcl_t* acl1, const OCSecureResource &device2, const OicSecAcl_t* acl2,
412             ResultCallBack resultCallback)
413     {
414         if (!resultCallback)
415         {
416             oclog() << "Result callback can not be null";
417             return OC_STACK_INVALID_CALLBACK;
418         }
419
420         OCStackResult result;
421         auto cLock = m_csdkLock.lock();
422
423         if (cLock)
424         {
425             ProvisionContext* context = new ProvisionContext(resultCallback);
426
427             std::lock_guard<std::recursive_mutex> lock(*cLock);
428             result = OCProvisionPairwiseDevices(static_cast<void*>(context),
429                     cred.getCredentialType(),
430                     cred.getCredentialKeySize(),
431                     devPtr, const_cast<OicSecAcl_t*>(acl1),
432                     device2.getDevPtr(), const_cast<OicSecAcl_t*>(acl2),
433                     &OCSecureResource::callbackWrapper);
434         }
435         else
436         {
437             oclog() <<"Mutex not found";
438             result = OC_STACK_ERROR;
439         }
440         return result;
441     }
442
443     OCStackResult OCSecureResource::unlinkDevices(const OCSecureResource &device2,
444             ResultCallBack resultCallback)
445     {
446         if (!resultCallback)
447         {
448             oclog() << "Result calback can't be null";
449             return OC_STACK_INVALID_CALLBACK;
450         }
451
452         OCStackResult result;
453         auto cLock = m_csdkLock.lock();
454
455         if (cLock)
456         {
457             ProvisionContext* context = new ProvisionContext(resultCallback);
458
459             std::lock_guard<std::recursive_mutex> lock(*cLock);
460
461             result = OCUnlinkDevices(static_cast<void*>(context),
462                     devPtr, device2.getDevPtr(), &OCSecureResource::callbackWrapper);
463         }
464         else
465         {
466             oclog() <<"Mutex not found";
467             result = OC_STACK_ERROR;
468         }
469         return result;
470     }
471
472     OCStackResult OCSecureResource::removeDevice(unsigned short waitTimeForOwnedDeviceDiscovery,
473             ResultCallBack resultCallback)
474     {
475         if (!resultCallback)
476         {
477             oclog() << "Result calback can't be null";
478             return OC_STACK_INVALID_CALLBACK;
479         }
480
481         OCStackResult result;
482         auto cLock = m_csdkLock.lock();
483
484         if (cLock)
485         {
486             ProvisionContext* context = new ProvisionContext(resultCallback);
487
488             std::lock_guard<std::recursive_mutex> lock(*cLock);
489
490             result = OCRemoveDevice(static_cast<void*>(context), waitTimeForOwnedDeviceDiscovery,
491                     devPtr, &OCSecureResource::callbackWrapper);
492         }
493         else
494         {
495             oclog() <<"Mutex not found";
496             result = OC_STACK_ERROR;
497         }
498         return result;
499     }
500
501     OCStackResult OCSecureResource::getLinkedDevices(UuidList_t &uuidList)
502     {
503         OCStackResult result;
504         size_t numOfDevices = -1;
505         auto devUuid = devPtr->doxm->deviceID;
506         auto cLock = m_csdkLock.lock();
507
508         if (cLock)
509         {
510             std::lock_guard<std::recursive_mutex> lock(*cLock);
511
512             OCUuidList_t* linkedDevs = nullptr, *tmp = nullptr;
513             result = OCGetLinkedStatus(&devUuid, &linkedDevs, &numOfDevices);
514             if (result == OC_STACK_OK)
515             {
516                 for (tmp = linkedDevs; tmp; tmp = tmp->next)
517                 {
518                     uuidList.push_back(tmp->dev);
519                 }
520                 OCDeleteUuidList(linkedDevs);
521             }
522         }
523         else
524         {
525             oclog() <<"Mutex not found";
526             result = OC_STACK_ERROR;
527         }
528         return result;
529     }
530
531     OCStackResult OCSecureResource::provisionDirectPairing( const OicSecPconf_t* pconf,
532             ResultCallBack resultCallback)
533     {
534         if (!pconf)
535         {
536             oclog() <<"PCONF can't be null";
537             return OC_STACK_INVALID_PARAM;
538         }
539         if (!resultCallback)
540         {
541             oclog() <<"result callback can not be null";
542             return OC_STACK_INVALID_CALLBACK;
543         }
544
545         OCStackResult result;
546         auto cLock = m_csdkLock.lock();
547
548         if (cLock)
549         {
550             ProvisionContext* context = new ProvisionContext(resultCallback);
551
552             std::lock_guard<std::recursive_mutex> lock(*cLock);
553             result = OCProvisionDirectPairing(static_cast<void*>(context),
554                     devPtr, const_cast<OicSecPconf_t*>(pconf),
555                     &OCSecureResource::callbackWrapper);
556         }
557         else
558         {
559             oclog() <<"Mutex not found";
560             result = OC_STACK_ERROR;
561         }
562         return result;
563     }
564
565     std::string OCSecureResource::getDeviceID()
566     {
567         std::ostringstream deviceId("");
568         char *devID = nullptr;
569
570         validateSecureResource();
571
572         if (OC_STACK_OK == ConvertUuidToStr(&(devPtr->doxm->deviceID), &devID))
573         {
574             deviceId << devID;
575             free(devID);
576         }
577         else
578         {
579             oclog() <<"Can not convert uuid to struuid";
580         }
581         return deviceId.str();
582     }
583
584     OCProvisionDev_t* OCSecureResource::getDevPtr() const
585     {
586         return devPtr;
587     }
588
589     std::string OCSecureResource::getDevAddr()
590     {
591         validateSecureResource();
592         std::string ipAddr(devPtr->endpoint.addr);
593         return ipAddr;
594     }
595
596     int OCSecureResource::getDeviceStatus()
597     {
598         validateSecureResource();
599         return (int)devPtr->devStatus;
600     }
601
602     bool OCSecureResource::getOwnedStatus()
603     {
604         validateSecureResource();
605         return devPtr->doxm->owned;
606     }
607
608     void OCSecureResource::validateSecureResource()
609     {
610         if (!devPtr)
611         {
612             throw OCException("Incomplete secure resource", OC_STACK_RESOURCE_ERROR);
613         }
614     }
615 }