Merge branch 'plugin-interface' into master
[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         results = new PMResultList_t;
238         for (int i = 0; i < nOfRes; i++)
239         {
240             results->push_back(arr[i]);
241         }
242
243         std::thread exec(context->callback, results, hasError);
244         exec.detach();
245
246         delete context;
247     }
248
249     OCSecureResource::OCSecureResource(): m_csdkLock(std::weak_ptr<std::recursive_mutex>()),
250                                         devPtr(nullptr)
251     {
252     }
253
254     OCSecureResource::OCSecureResource(std::weak_ptr<std::recursive_mutex> csdkLock,
255             OCProvisionDev_t *dPtr)
256         :m_csdkLock(csdkLock), devPtr(dPtr)
257     {
258     }
259
260     OCSecureResource::~OCSecureResource()
261     {
262         if(devPtr)
263         {
264             OCDeleteDiscoveredDevices(devPtr);
265         }
266     }
267
268     OCStackResult OCSecureResource::doOwnershipTransfer(ResultCallBack resultCallback)
269     {
270         if(!resultCallback)
271         {
272             oclog() <<"Result callback can't be null";
273             return OC_STACK_INVALID_PARAM;
274         }
275
276         OCStackResult result;
277         auto cLock = m_csdkLock.lock();
278
279         if(cLock)
280         {
281             ProvisionContext* context = new ProvisionContext(resultCallback);
282
283             std::lock_guard<std::recursive_mutex> lock(*cLock);
284             result = OCDoOwnershipTransfer(static_cast<void*>(context),
285                     devPtr, &OCSecureResource::callbackWrapper);
286         }
287         else
288         {
289             oclog() <<"Mutex not found";
290             result = OC_STACK_ERROR;
291         }
292         return result;
293     }
294
295     OCStackResult OCSecureResource::provisionACL( const OicSecAcl_t* acl,
296             ResultCallBack resultCallback)
297     {
298         if(!resultCallback || !acl)
299         {
300             oclog() <<"Result callback or ACL can't be null";
301             return OC_STACK_INVALID_PARAM;
302         }
303
304         OCStackResult result;
305         auto cLock = m_csdkLock.lock();
306
307         if(cLock)
308         {
309             ProvisionContext* context = new ProvisionContext(resultCallback);
310
311             std::lock_guard<std::recursive_mutex> lock(*cLock);
312             result = OCProvisionACL(static_cast<void*>(context),
313                     devPtr, const_cast<OicSecAcl_t*>(acl),
314                     &OCSecureResource::callbackWrapper);
315         }
316         else
317         {
318             oclog() <<"Mutex not found";
319             result = OC_STACK_ERROR;
320         }
321         return result;
322     }
323
324     OCStackResult OCSecureResource::provisionCredentials(const Credential &cred,
325             const OCSecureResource &device2, ResultCallBack resultCallback)
326     {
327         if(!resultCallback)
328         {
329             oclog() << "Result calback can't be null";
330             return OC_STACK_INVALID_PARAM;
331         }
332
333         OCStackResult result;
334         auto cLock = m_csdkLock.lock();
335
336         if(cLock)
337         {
338             ProvisionContext* context = new ProvisionContext(resultCallback);
339
340             std::lock_guard<std::recursive_mutex> lock(*cLock);
341             result = OCProvisionCredentials(static_cast<void*>(context),
342                     cred.getCredentialType(),
343                     cred.getCredentialKeySize(),
344                     devPtr, device2.getDevPtr(),
345                     &OCSecureResource::callbackWrapper);
346         }
347         else
348         {
349             oclog() <<"Mutex not found";
350             result = OC_STACK_ERROR;
351         }
352         return result;
353     }
354
355     OCStackResult OCSecureResource::provisionPairwiseDevices(const Credential &cred,
356             const OicSecAcl_t* acl1, const OCSecureResource &device2, const OicSecAcl_t* acl2,
357             ResultCallBack resultCallback)
358     {
359         if(!resultCallback)
360         {
361             oclog() << "Result calback can't be null";
362             return OC_STACK_INVALID_PARAM;
363         }
364
365         OCStackResult result;
366         auto cLock = m_csdkLock.lock();
367
368         if(cLock)
369         {
370             ProvisionContext* context = new ProvisionContext(resultCallback);
371
372             std::lock_guard<std::recursive_mutex> lock(*cLock);
373             result = OCProvisionPairwiseDevices(static_cast<void*>(context),
374                     cred.getCredentialType(),
375                     cred.getCredentialKeySize(),
376                     devPtr, const_cast<OicSecAcl_t*>(acl1),
377                     device2.getDevPtr(), const_cast<OicSecAcl_t*>(acl2),
378                     &OCSecureResource::callbackWrapper);
379         }
380         else
381         {
382             oclog() <<"Mutex not found";
383             result = OC_STACK_ERROR;
384         }
385         return result;
386     }
387
388     OCStackResult OCSecureResource::unlinkDevices(const OCSecureResource &device2,
389             ResultCallBack resultCallback)
390     {
391         if(!resultCallback)
392         {
393             oclog() << "Result calback can't be null";
394             return OC_STACK_INVALID_PARAM;
395         }
396
397         OCStackResult result;
398         auto cLock = m_csdkLock.lock();
399
400         if(cLock)
401         {
402             ProvisionContext* context = new ProvisionContext(resultCallback);
403
404             std::lock_guard<std::recursive_mutex> lock(*cLock);
405
406             result = OCUnlinkDevices(static_cast<void*>(context),
407                     devPtr, device2.getDevPtr(), &OCSecureResource::callbackWrapper);
408         }
409         else
410         {
411             oclog() <<"Mutex not found";
412             result = OC_STACK_ERROR;
413         }
414         return result;
415     }
416
417     OCStackResult OCSecureResource::removeDevice(unsigned short waitTimeForOwnedDeviceDiscovery,
418             ResultCallBack resultCallback)
419     {
420         if(!resultCallback)
421         {
422             oclog() << "Result calback can't be null";
423             return OC_STACK_INVALID_PARAM;
424         }
425
426         OCStackResult result;
427         auto cLock = m_csdkLock.lock();
428
429         if(cLock)
430         {
431             ProvisionContext* context = new ProvisionContext(resultCallback);
432
433             std::lock_guard<std::recursive_mutex> lock(*cLock);
434
435             result = OCRemoveDevice(static_cast<void*>(context), waitTimeForOwnedDeviceDiscovery,
436                     devPtr, &OCSecureResource::callbackWrapper);
437         }
438         else
439         {
440             oclog() <<"Mutex not found";
441             result = OC_STACK_ERROR;
442         }
443         return result;
444     }
445
446     OCStackResult OCSecureResource::getLinkedDevices(UuidList_t &uuidList)
447     {
448         OCStackResult result;
449         size_t numOfDevices = -1;
450         auto devUuid = devPtr->doxm->deviceID;
451         auto cLock = m_csdkLock.lock();
452
453         if(cLock)
454         {
455             std::lock_guard<std::recursive_mutex> lock(*cLock);
456
457             OCUuidList_t* linkedDevs = nullptr, *tmp = nullptr;
458             result = OCGetLinkedStatus(&devUuid, &linkedDevs, &numOfDevices);
459             if (result == OC_STACK_OK)
460             {
461                 for (tmp = linkedDevs; tmp; tmp = tmp->next)
462                 {
463                     uuidList.push_back(tmp->dev);
464                 }
465                 OCDeleteUuidList(linkedDevs);
466             }
467         }
468         else
469         {
470             oclog() <<"Mutex not found";
471             result = OC_STACK_ERROR;
472         }
473         return result;
474     }
475
476     std::string OCSecureResource::getDeviceID()
477     {
478         char base64Buff[B64ENCODE_OUT_SAFESIZE(sizeof(((OicUuid_t*)0)->id)) + 1] = {0,};
479         uint32_t outLen = 0;
480         B64Result b64Ret = B64_OK;
481         std::ostringstream deviceId("");
482
483         validateSecureResource();
484         b64Ret = b64Encode(devPtr->doxm->deviceID.id, sizeof(devPtr->doxm->deviceID.id), base64Buff,
485                 sizeof(base64Buff), &outLen);
486
487         if (B64_OK == b64Ret)
488         {
489             deviceId << base64Buff;
490         }
491         return deviceId.str();
492     }
493
494     OCProvisionDev_t* OCSecureResource::getDevPtr() const
495     {
496         return devPtr;
497     }
498
499     std::string OCSecureResource::getDevAddr()
500     {
501         validateSecureResource();
502         std::string ipAddr(devPtr->endpoint.addr);
503         return ipAddr;
504     }
505
506     int OCSecureResource::getDeviceStatus()
507     {
508         validateSecureResource();
509         return (int)devPtr->devStatus;
510     }
511
512     bool OCSecureResource::getOwnedStatus()
513     {
514         validateSecureResource();
515         return devPtr->doxm->owned;
516     }
517
518     void OCSecureResource::validateSecureResource()
519     {
520         if (!devPtr)
521         {
522             throw OCException("Incomplete secure resource", OC_STACK_RESOURCE_ERROR);
523         }
524     }
525 }