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