Add function to save a ACL into local SVR DB
[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::discoverSingleDevice(unsigned short timeout,
125             const OicUuid_t* deviceID,
126             std::shared_ptr<OCSecureResource> &foundDevice)
127     {
128         OCStackResult result;
129         OCProvisionDev_t *pDev = nullptr;
130         auto csdkLock = OCPlatform_impl::Instance().csdkLock();
131         auto cLock = csdkLock.lock();
132
133         if (cLock)
134         {
135             std::lock_guard<std::recursive_mutex> lock(*cLock);
136             result = OCDiscoverSingleDevice(timeout, deviceID, &pDev);
137             if (result == OC_STACK_OK)
138             {
139                 if (pDev)
140                 {
141                     foundDevice.reset(new OCSecureResource(csdkLock, pDev));
142                 }
143                 else
144                 {
145                     oclog() <<"Not found Secure resource!";
146                     foundDevice.reset();
147                 }
148             }
149             else
150             {
151                 oclog() <<"Secure resource discovery failed!";
152             }
153         }
154         else
155         {
156             oclog() <<"Mutex not found";
157             result = OC_STACK_ERROR;
158         }
159
160         return result;
161     }
162
163     OCStackResult OCSecure::setOwnerTransferCallbackData(OicSecOxm_t oxm,
164             OTMCallbackData_t* callbackData, InputPinCallback inputPin)
165     {
166         if (NULL == callbackData || oxm >= OIC_OXM_COUNT)
167         {
168             oclog() <<"Invalid callbackData or OXM type";
169             return OC_STACK_INVALID_PARAM;
170         }
171
172         if ((OIC_RANDOM_DEVICE_PIN == oxm) && !inputPin)
173         {
174             oclog() <<"for OXM type DEVICE_PIN, inputPin callback can't be null";
175             return OC_STACK_INVALID_PARAM;
176         }
177
178         OCStackResult result;
179         auto cLock = OCPlatform_impl::Instance().csdkLock().lock();
180
181         if (cLock)
182         {
183             std::lock_guard<std::recursive_mutex> lock(*cLock);
184             result = OCSetOwnerTransferCallbackData(oxm, callbackData);
185             if (result == OC_STACK_OK && (OIC_RANDOM_DEVICE_PIN == oxm))
186             {
187                 SetInputPinCB(inputPin);
188             }
189         }
190         else
191         {
192             oclog() <<"Mutex not found";
193             result = OC_STACK_ERROR;
194         }
195
196         return result;
197
198     }
199
200     OCStackResult OCSecure::getDevInfoFromNetwork(unsigned short timeout,
201             DeviceList_t &ownedDevList,
202             DeviceList_t &unownedDevList)
203     {
204         OCStackResult result = OC_STACK_OK;
205         OCProvisionDev_t *owned = nullptr, *unowned = nullptr, *tmp = nullptr, *dev = nullptr;
206         auto csdkLock = OCPlatform_impl::Instance().csdkLock();
207         auto cLock = csdkLock.lock();
208
209         if (cLock)
210         {
211             std::lock_guard<std::recursive_mutex> lock(*cLock);
212
213             result = OCGetDevInfoFromNetwork(timeout, &owned, &unowned);
214
215             if (result == OC_STACK_OK)
216             {
217                 dev = owned;
218                 while (dev)
219                 {
220                     tmp = dev;
221                     ownedDevList.push_back(std::shared_ptr<OCSecureResource>(
222                                 new OCSecureResource(csdkLock, dev)));
223                     dev = dev->next;
224                     tmp->next = nullptr;
225                 }
226
227                 dev = unowned;
228                 while (dev)
229                 {
230                     tmp = dev;
231                     unownedDevList.push_back(std::shared_ptr<OCSecureResource>(
232                                 new OCSecureResource(csdkLock,  dev)));
233                     dev = dev->next;
234                     tmp->next = nullptr;
235                 }
236             }
237         }
238         else
239         {
240             oclog() <<"Mutex not found";
241             result = OC_STACK_ERROR;
242         }
243
244         return result;
245     }
246
247     OCStackResult OCSecure::setDisplayPinCB(GeneratePinCallback displayPin)
248     {
249         if (!displayPin)
250         {
251             oclog() <<"displayPin can't be null";
252             return OC_STACK_INVALID_PARAM;
253         }
254
255         OCStackResult result = OC_STACK_OK;
256         auto cLock = OCPlatform_impl::Instance().csdkLock().lock();
257
258         if (cLock)
259         {
260             std::lock_guard<std::recursive_mutex> lock(*cLock);
261             SetGeneratePinCB(displayPin);
262         }
263         else
264         {
265             oclog() <<"Mutex not found";
266             result = OC_STACK_ERROR;
267         }
268
269         return result;
270     }
271
272     OCStackResult OCSecure::removeDeviceWithUuid(unsigned short waitTimeForOwnedDeviceDiscovery,
273             std::string uuid,
274             ResultCallBack resultCallback)
275     {
276         if (!resultCallback)
277         {
278             oclog() << "Result calback can't be null";
279             return OC_STACK_INVALID_CALLBACK;
280         }
281
282         OCStackResult result;
283         auto cLock = OCPlatform_impl::Instance().csdkLock().lock();
284
285         if (cLock)
286         {
287             ProvisionContext* context = new ProvisionContext(resultCallback);
288
289             std::lock_guard<std::recursive_mutex> lock(*cLock);
290
291             OicUuid_t targetDev;
292             result = ConvertStrToUuid(uuid.c_str(), &targetDev);
293             if(OC_STACK_OK == result)
294             {
295                 result = OCRemoveDeviceWithUuid(static_cast<void*>(context), waitTimeForOwnedDeviceDiscovery,
296                         &targetDev, &OCSecureResource::callbackWrapper);
297             }
298             else
299             {
300                 oclog() <<"Can not convert struuid to uuid";
301             }
302         }
303         else
304         {
305             oclog() <<"Mutex not found";
306             result = OC_STACK_ERROR;
307         }
308         return result;
309     }
310
311     OCStackResult OCSecure::saveACL(const OicSecAcl_t* acl)
312     {
313         if (!acl)
314         {
315             oclog() <<"ACL can't be null";
316             return OC_STACK_INVALID_PARAM;
317         }
318
319         OCStackResult result;
320         auto cLock = OCPlatform_impl::Instance().csdkLock().lock();
321
322         if (cLock)
323         {
324             std::lock_guard<std::recursive_mutex> lock(*cLock);
325             result = OCSaveACL(const_cast<OicSecAcl_t*>(acl));
326         }
327         else
328         {
329             oclog() <<"Mutex not found";
330             result = OC_STACK_ERROR;
331         }
332         return result;
333     }
334
335 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
336     OCStackResult OCSecure::saveTrustCertChain(uint8_t *trustCertChain, size_t chainSize,
337                                         OicEncodingType_t encodingType, uint16_t *credId)
338     {
339         if (!trustCertChain)
340         {
341             oclog() <<"trustCertChain can't be null";
342             return OC_STACK_INVALID_PARAM;
343         }
344         if (!credId)
345         {
346             oclog() <<"cred ID can not be null";
347             return OC_STACK_INVALID_PARAM;
348         }
349
350         OCStackResult result;
351         auto cLock = OCPlatform_impl::Instance().csdkLock().lock();
352
353         if (cLock)
354         {
355             std::lock_guard<std::recursive_mutex> lock(*cLock);
356             result = OCSaveTrustCertChain(trustCertChain, chainSize, encodingType, credId );
357         }
358         else
359         {
360             oclog() <<"Mutex not found";
361             result = OC_STACK_ERROR;
362         }
363         return result;
364     }
365 #endif // __WITH_DTLS__ || __WITH_TLS__
366
367     void OCSecureResource::callbackWrapper(void* ctx, int nOfRes, OCProvisionResult_t *arr, bool hasError)
368     {
369         PMResultList_t *results = nullptr;
370         ProvisionContext* context = static_cast<ProvisionContext*>(ctx);
371
372         try
373         {
374             results = new PMResultList_t;
375         }
376         catch (std::bad_alloc& e)
377         {
378             oclog() <<"Bad alloc exception";
379             return;
380         }
381
382         for (int i = 0; i < nOfRes; i++)
383         {
384             results->push_back(arr[i]);
385         }
386
387         std::thread exec(context->callback, results, hasError);
388         exec.detach();
389
390         delete context;
391     }
392
393     OCSecureResource::OCSecureResource(): m_csdkLock(std::weak_ptr<std::recursive_mutex>()),
394                                         devPtr(nullptr)
395     {
396     }
397
398     OCSecureResource::OCSecureResource(std::weak_ptr<std::recursive_mutex> csdkLock,
399             OCProvisionDev_t *dPtr)
400         :m_csdkLock(csdkLock), devPtr(dPtr)
401     {
402     }
403
404     OCSecureResource::~OCSecureResource()
405     {
406         if (devPtr)
407         {
408             OCDeleteDiscoveredDevices(devPtr);
409         }
410     }
411
412     OCStackResult OCSecureResource::doOwnershipTransfer(ResultCallBack resultCallback)
413     {
414         if (!resultCallback)
415         {
416             oclog() <<"Result callback can't 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 = OCDoOwnershipTransfer(static_cast<void*>(context),
429                     devPtr, &OCSecureResource::callbackWrapper);
430         }
431         else
432         {
433             oclog() <<"Mutex not found";
434             result = OC_STACK_ERROR;
435         }
436         return result;
437     }
438
439     OCStackResult OCSecureResource::provisionACL( const OicSecAcl_t* acl,
440             ResultCallBack resultCallback)
441     {
442         if (!acl)
443         {
444             oclog() <<"ACL can't be null";
445             return OC_STACK_INVALID_PARAM;
446         }
447         if (!resultCallback)
448         {
449             oclog() <<"result callback can not be null";
450             return OC_STACK_INVALID_CALLBACK;
451         }
452
453         OCStackResult result;
454         auto cLock = m_csdkLock.lock();
455
456         if (cLock)
457         {
458             ProvisionContext* context = new ProvisionContext(resultCallback);
459
460             std::lock_guard<std::recursive_mutex> lock(*cLock);
461             result = OCProvisionACL(static_cast<void*>(context),
462                     devPtr, const_cast<OicSecAcl_t*>(acl),
463                     &OCSecureResource::callbackWrapper);
464         }
465         else
466         {
467             oclog() <<"Mutex not found";
468             result = OC_STACK_ERROR;
469         }
470         return result;
471     }
472
473     OCStackResult OCSecureResource::provisionCredentials(const Credential &cred,
474             const OCSecureResource &device2, ResultCallBack resultCallback)
475     {
476         if (!resultCallback)
477         {
478             oclog() << "Result calback can't be null";
479             return OC_STACK_INVALID_CALLBACK;
480         }
481
482         OCStackResult result;
483         auto cLock = m_csdkLock.lock();
484
485         if (cLock)
486         {
487             ProvisionContext* context = new ProvisionContext(resultCallback);
488
489             std::lock_guard<std::recursive_mutex> lock(*cLock);
490             result = OCProvisionCredentials(static_cast<void*>(context),
491                     cred.getCredentialType(),
492                     cred.getCredentialKeySize(),
493                     devPtr, device2.getDevPtr(),
494                     &OCSecureResource::callbackWrapper);
495         }
496         else
497         {
498             oclog() <<"Mutex not found";
499             result = OC_STACK_ERROR;
500         }
501         return result;
502     }
503
504     OCStackResult OCSecureResource::provisionPairwiseDevices(const Credential &cred,
505             const OicSecAcl_t* acl1, const OCSecureResource &device2, const OicSecAcl_t* acl2,
506             ResultCallBack resultCallback)
507     {
508         if (!resultCallback)
509         {
510             oclog() << "Result callback can not be null";
511             return OC_STACK_INVALID_CALLBACK;
512         }
513
514         OCStackResult result;
515         auto cLock = m_csdkLock.lock();
516
517         if (cLock)
518         {
519             ProvisionContext* context = new ProvisionContext(resultCallback);
520
521             std::lock_guard<std::recursive_mutex> lock(*cLock);
522             result = OCProvisionPairwiseDevices(static_cast<void*>(context),
523                     cred.getCredentialType(),
524                     cred.getCredentialKeySize(),
525                     devPtr, const_cast<OicSecAcl_t*>(acl1),
526                     device2.getDevPtr(), const_cast<OicSecAcl_t*>(acl2),
527                     &OCSecureResource::callbackWrapper);
528         }
529         else
530         {
531             oclog() <<"Mutex not found";
532             result = OC_STACK_ERROR;
533         }
534         return result;
535     }
536
537     OCStackResult OCSecureResource::unlinkDevices(const OCSecureResource &device2,
538             ResultCallBack resultCallback)
539     {
540         if (!resultCallback)
541         {
542             oclog() << "Result calback can't be null";
543             return OC_STACK_INVALID_CALLBACK;
544         }
545
546         OCStackResult result;
547         auto cLock = m_csdkLock.lock();
548
549         if (cLock)
550         {
551             ProvisionContext* context = new ProvisionContext(resultCallback);
552
553             std::lock_guard<std::recursive_mutex> lock(*cLock);
554
555             result = OCUnlinkDevices(static_cast<void*>(context),
556                     devPtr, device2.getDevPtr(), &OCSecureResource::callbackWrapper);
557         }
558         else
559         {
560             oclog() <<"Mutex not found";
561             result = OC_STACK_ERROR;
562         }
563         return result;
564     }
565
566     OCStackResult OCSecureResource::removeDevice(unsigned short waitTimeForOwnedDeviceDiscovery,
567             ResultCallBack resultCallback)
568     {
569         if (!resultCallback)
570         {
571             oclog() << "Result calback can't be null";
572             return OC_STACK_INVALID_CALLBACK;
573         }
574
575         OCStackResult result;
576         auto cLock = m_csdkLock.lock();
577
578         if (cLock)
579         {
580             ProvisionContext* context = new ProvisionContext(resultCallback);
581
582             std::lock_guard<std::recursive_mutex> lock(*cLock);
583
584             result = OCRemoveDevice(static_cast<void*>(context), waitTimeForOwnedDeviceDiscovery,
585                     devPtr, &OCSecureResource::callbackWrapper);
586         }
587         else
588         {
589             oclog() <<"Mutex not found";
590             result = OC_STACK_ERROR;
591         }
592         return result;
593     }
594
595     OCStackResult OCSecureResource::getLinkedDevices(UuidList_t &uuidList)
596     {
597         OCStackResult result;
598         size_t numOfDevices = -1;
599         auto devUuid = devPtr->doxm->deviceID;
600         auto cLock = m_csdkLock.lock();
601
602         if (cLock)
603         {
604             std::lock_guard<std::recursive_mutex> lock(*cLock);
605
606             OCUuidList_t* linkedDevs = nullptr, *tmp = nullptr;
607             result = OCGetLinkedStatus(&devUuid, &linkedDevs, &numOfDevices);
608             if (result == OC_STACK_OK)
609             {
610                 for (tmp = linkedDevs; tmp; tmp = tmp->next)
611                 {
612                     uuidList.push_back(tmp->dev);
613                 }
614                 OCDeleteUuidList(linkedDevs);
615             }
616         }
617         else
618         {
619             oclog() <<"Mutex not found";
620             result = OC_STACK_ERROR;
621         }
622         return result;
623     }
624
625     OCStackResult OCSecureResource::provisionDirectPairing( const OicSecPconf_t* pconf,
626             ResultCallBack resultCallback)
627     {
628         if (!pconf)
629         {
630             oclog() <<"PCONF can't be null";
631             return OC_STACK_INVALID_PARAM;
632         }
633         if (!resultCallback)
634         {
635             oclog() <<"result callback can not be null";
636             return OC_STACK_INVALID_CALLBACK;
637         }
638
639         OCStackResult result;
640         auto cLock = m_csdkLock.lock();
641
642         if (cLock)
643         {
644             ProvisionContext* context = new ProvisionContext(resultCallback);
645
646             std::lock_guard<std::recursive_mutex> lock(*cLock);
647             result = OCProvisionDirectPairing(static_cast<void*>(context),
648                     devPtr, const_cast<OicSecPconf_t*>(pconf),
649                     &OCSecureResource::callbackWrapper);
650         }
651         else
652         {
653             oclog() <<"Mutex not found";
654             result = OC_STACK_ERROR;
655         }
656         return result;
657     }
658
659 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
660     OCStackResult OCSecureResource::provisionTrustCertChain(OicSecCredType_t type, uint16_t credId,
661                     ResultCallBack resultCallback)
662     {
663         if (SIGNED_ASYMMETRIC_KEY != type)
664         {
665             oclog() <<"Invalid key type";
666             return OC_STACK_INVALID_PARAM;
667         }
668         if (!resultCallback)
669         {
670             oclog() <<"result callback can not be null";
671             return OC_STACK_INVALID_CALLBACK;
672         }
673
674         OCStackResult result;
675         auto cLock = m_csdkLock.lock();
676
677         if (cLock)
678         {
679             ProvisionContext* context = new ProvisionContext(resultCallback);
680
681             std::lock_guard<std::recursive_mutex> lock(*cLock);
682             result = OCProvisionTrustCertChain(static_cast<void*>(context),
683                     type, credId, devPtr,
684                     &OCSecureResource::callbackWrapper);
685         }
686         else
687         {
688             oclog() <<"Mutex not found";
689             result = OC_STACK_ERROR;
690         }
691         return result;
692     }
693 #endif // __WITH_DTLS__ or __WITH_TLS__
694
695     std::string OCSecureResource::getDeviceID()
696     {
697         std::ostringstream deviceId("");
698         char *devID = nullptr;
699
700         validateSecureResource();
701
702         if (OC_STACK_OK == ConvertUuidToStr(&(devPtr->doxm->deviceID), &devID))
703         {
704             deviceId << devID;
705             free(devID);
706         }
707         else
708         {
709             oclog() <<"Can not convert uuid to struuid";
710         }
711         return deviceId.str();
712     }
713
714     OCProvisionDev_t* OCSecureResource::getDevPtr() const
715     {
716         return devPtr;
717     }
718
719     std::string OCSecureResource::getDevAddr()
720     {
721         validateSecureResource();
722         std::string ipAddr(devPtr->endpoint.addr);
723         return ipAddr;
724     }
725
726     int OCSecureResource::getDeviceStatus()
727     {
728         validateSecureResource();
729         return (int)devPtr->devStatus;
730     }
731
732     bool OCSecureResource::getOwnedStatus()
733     {
734         validateSecureResource();
735         return devPtr->doxm->owned;
736     }
737
738     void OCSecureResource::validateSecureResource()
739     {
740         if (!devPtr)
741         {
742             throw OCException("Incomplete secure resource", OC_STACK_RESOURCE_ERROR);
743         }
744     }
745 }