1 /* *****************************************************************
3 * Copyright 2015 Samsung Electronics All Rights Reserved.
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 * *****************************************************************/
23 #include "ocprovisioningmanager.h"
24 #include "pmutility.h"
25 #include "srmutility.h"
26 #include "ownershiptransfermanager.h"
27 #include "oic_malloc.h"
29 #include "secureresourceprovider.h"
30 #include "provisioningdatabasemanager.h"
31 #include "credresource.h"
33 #include "aclresource.h" //Note: SRM internal header
34 #include "pconfresource.h"
38 typedef struct Linkdata Linkdata_t;
42 const OCProvisionDev_t *pDev1;
43 OicSecAcl_t *pDev1Acl;
44 const OCProvisionDev_t *pDev2;
45 OicSecAcl_t *pDev2Acl;
46 OCProvisionResult_t *resArr;
48 int currentCountResults;
49 OCProvisionResultCB resultCallback;
54 * The function is responsible for initializaton of the provisioning manager. It will load
55 * provisioning database which have owned device's list and their linked status.
56 * TODO: In addition, if there is a device(s) which has not up-to-date credentials, this function will
57 * automatically try to update the deivce(s).
59 * @param[in] dbPath file path of the sqlite3 db
61 * @return OC_STACK_OK in case of success and other value otherwise.
63 OCStackResult OCInitPM(const char* dbPath)
65 return PDMInit(dbPath);
69 * The function is responsible for discovery of owned/unowned device is specified endpoint.
70 * It will return when found one or more device even though timeout is not exceeded
72 * @param[in] timeout Timeout in seconds, value till which function will listen to responses from
73 * server before returning the list of devices.
74 * @param[in] host address of target endpoint
75 * @param[in] connType connectivity type of endpoint
76 * @param[out] ppList List of device.
77 * @return OTM_SUCCESS in case of success and other value otherwise.
79 OCStackResult OCDiscoverSecureResource(unsigned short timeout, const char* host,
80 OCConnectivityType connType, OCProvisionDev_t **ppList)
82 if( ppList == NULL || *ppList != NULL || 0 == timeout || host == NULL)
84 return OC_STACK_INVALID_PARAM;
87 return PMSingleDeviceDiscovery(timeout, host, connType, ppList);
91 * The function is responsible for discovery of device is current subnet. It will list
92 * all the device in subnet which are not yet owned. Please call OCInit with OC_CLIENT_SERVER as
95 * @param[in] timeout Timeout in seconds, value till which function will listen to responses from
96 * server before returning the list of devices.
97 * @param[out] ppList List of candidate devices to be provisioned
98 * @return OTM_SUCCESS in case of success and other value otherwise.
100 OCStackResult OCDiscoverUnownedDevices(unsigned short timeout, OCProvisionDev_t **ppList)
102 if( ppList == NULL || *ppList != NULL || 0 == timeout)
104 return OC_STACK_INVALID_PARAM;
107 return PMDeviceDiscovery(timeout, false, ppList);
111 * The function is responsible for discovery of owned device is current subnet. It will list
112 * all the device in subnet which are owned by calling provisioning client.
114 * @param[in] timeout Timeout in seconds, value till which function will listen to responses from
115 * server before returning the list of devices.
116 * @param[out] ppList List of device owned by provisioning tool.
117 * @return OTM_SUCCESS in case of success and other value otherwise.
119 OCStackResult OCDiscoverOwnedDevices(unsigned short timeout, OCProvisionDev_t **ppList)
121 if( ppList == NULL || *ppList != NULL || 0 == timeout)
123 return OC_STACK_INVALID_PARAM;
126 return PMDeviceDiscovery(timeout, true, ppList);
130 * API to register for particular OxM.
132 * @param[in] Ownership transfer method.
133 * @param[in] Implementation of callback functions for owership transfer.
134 * @return OC_STACK_OK in case of success and other value otherwise.
136 OCStackResult OCSetOwnerTransferCallbackData(OicSecOxm_t oxm, OTMCallbackData_t* callbackData)
138 if(NULL == callbackData)
140 return OC_STACK_INVALID_CALLBACK ;
143 return OTMSetOwnershipTransferCallbackData(oxm, callbackData);
146 OCStackResult OCDoOwnershipTransfer(void* ctx,
147 OCProvisionDev_t *targetDevices,
148 OCProvisionResultCB resultCallback)
150 if( NULL == targetDevices )
152 return OC_STACK_INVALID_PARAM;
156 OIC_LOG(INFO, TAG, "OCDoOwnershipTransfer : NULL Callback");
157 return OC_STACK_INVALID_CALLBACK;
159 return OTMDoOwnershipTransfer(ctx, targetDevices, resultCallback);
163 * This function deletes memory allocated to linked list created by OCDiscover_XXX_Devices API.
165 * @param[in] pList Pointer to OCProvisionDev_t which should be deleted.
167 void OCDeleteDiscoveredDevices(OCProvisionDev_t *pList)
169 PMDeleteDeviceList(pList);
173 * this function sends ACL information to resource.
175 * @param[in] ctx Application context would be returned in result callback.
176 * @param[in] selectedDeviceInfo Selected target device.
177 * @param[in] acl ACL to provision.
178 * @param[in] resultCallback callback provided by API user, callback will be called when provisioning
179 request recieves a response from resource server.
180 * @return OC_STACK_OK in case of success and other value otherwise.
182 OCStackResult OCProvisionACL(void* ctx, const OCProvisionDev_t *selectedDeviceInfo, OicSecAcl_t *acl,
183 OCProvisionResultCB resultCallback)
185 return SRPProvisionACL(ctx, selectedDeviceInfo, acl, resultCallback);
189 * this function requests CRED information to resource.
191 * @param[in] ctx Application context would be returned in result callback.
192 * @param[in] selectedDeviceInfo Selected target device.
193 * @param[in] resultCallback callback provided by API user, callback will be called when provisioning
194 request recieves a response from resource server.
195 * @return OC_STACK_OK in case of success and other value otherwise.
197 OCStackResult OCGetCredResource(void* ctx, const OCProvisionDev_t *selectedDeviceInfo,
198 OCProvisionResultCB resultCallback)
200 return SRPGetCredResource(ctx, selectedDeviceInfo, resultCallback);
204 * this function requests ACL information to resource.
206 * @param[in] ctx Application context would be returned in result callback.
207 * @param[in] selectedDeviceInfo Selected target device.
208 * @param[in] resultCallback callback provided by API user, callback will be called when provisioning
209 request recieves a response from resource server.
210 * @return OC_STACK_OK in case of success and other value otherwise.
212 OCStackResult OCGetACLResource(void* ctx, const OCProvisionDev_t *selectedDeviceInfo,
213 OCProvisionResultCB resultCallback)
215 return SRPGetACLResource(ctx, selectedDeviceInfo, resultCallback);
219 * function to provision credential to devices.
221 * @param[in] ctx Application context would be returned in result callback.
222 * @param[in] type Type of credentials to be provisioned to the device.
223 * @param[in] pDev1 Pointer to OCProvisionDev_t instance,respresenting resource to be provsioned.
224 @param[in] pDev2 Pointer to OCProvisionDev_t instance,respresenting resource to be provsioned.
225 * @param[in] resultCallback callback provided by API user, callback will be called when
226 * provisioning request recieves a response from first resource server.
227 * @return OC_STACK_OK in case of success and other value otherwise.
229 OCStackResult OCProvisionCredentials(void *ctx, OicSecCredType_t type, size_t keySize,
230 const OCProvisionDev_t *pDev1,
231 const OCProvisionDev_t *pDev2,
232 OCProvisionResultCB resultCallback)
234 return SRPProvisionCredentials(ctx, type, keySize,
235 pDev1, pDev2, resultCallback);
240 * this function sends Direct-Pairing Configuration to a device.
242 * @param[in] ctx Application context would be returned in result callback.
243 * @param[in] selectedDeviceInfo Selected target device.
244 * @param[in] pconf PCONF pointer.
245 * @param[in] resultCallback callback provided by API user, callback will be called when provisioning
246 request recieves a response from resource server.
247 * @return OC_STACK_OK in case of success and other value otherwise.
249 OCStackResult OCProvisionDirectPairing(void* ctx, const OCProvisionDev_t *selectedDeviceInfo, OicSecPconf_t *pconf,
250 OCProvisionResultCB resultCallback)
252 return SRPProvisionDirectPairing(ctx, selectedDeviceInfo, pconf, resultCallback);
256 * Function to unlink devices.
257 * This function will remove the credential & relationship between the two devices.
259 * @param[in] ctx Application context would be returned in result callback
260 * @param[in] pTargetDev1 first device information to be unlinked.
261 * @param[in] pTargetDev2 second device information to be unlinked.
262 * @param[in] resultCallback callback provided by API user, callback will be called when
263 * device unlink is finished.
264 * @return OC_STACK_OK in case of success and other value otherwise.
266 OCStackResult OCUnlinkDevices(void* ctx,
267 const OCProvisionDev_t* pTargetDev1,
268 const OCProvisionDev_t* pTargetDev2,
269 OCProvisionResultCB resultCallback)
271 OIC_LOG(INFO, TAG, "IN OCUnlinkDevices");
272 OCUuidList_t* idList = NULL;
275 if (!pTargetDev1 || !pTargetDev2 || !pTargetDev1->doxm || !pTargetDev2->doxm)
277 OIC_LOG(ERROR, TAG, "OCUnlinkDevices : NULL parameters");
278 return OC_STACK_INVALID_PARAM;
282 OIC_LOG(INFO, TAG, "OCUnlinkDevices : NULL Callback");
283 return OC_STACK_INVALID_CALLBACK;
285 if (0 == memcmp(&pTargetDev1->doxm->deviceID, &pTargetDev2->doxm->deviceID, sizeof(OicUuid_t)))
287 OIC_LOG(INFO, TAG, "OCUnlinkDevices : Same device ID");
288 return OC_STACK_INVALID_PARAM;
291 // Get linked devices with the first device.
292 OCStackResult res = PDMGetLinkedDevices(&(pTargetDev1->doxm->deviceID), &idList, &numOfDev);
293 if (OC_STACK_OK != res)
295 OIC_LOG(ERROR, TAG, "OCUnlinkDevices : PDMgetOwnedDevices failed");
300 OIC_LOG(DEBUG, TAG, "OCUnlinkDevices : Can not find linked devices");
301 res = OC_STACK_INVALID_PARAM; // Input devices are not linked, No request is made
305 // Check the linked devices contains the second device. If yes send credential DELETE request.
306 OCUuidList_t* curDev = idList;
307 while (NULL != curDev)
309 if (memcmp(pTargetDev2->doxm->deviceID.id, curDev->dev.id, sizeof(curDev->dev.id)) == 0)
311 res = SRPUnlinkDevices(ctx, pTargetDev1, pTargetDev2, resultCallback);
312 if (OC_STACK_OK != res)
314 OIC_LOG(ERROR, TAG, "OCUnlinkDevices : Failed to unlink devices.");
318 curDev = curDev->next;
320 OIC_LOG(DEBUG, TAG, "No matched pair found from provisioning database");
321 res = OC_STACK_INVALID_PARAM; // Input devices are not linked, No request is made
324 OIC_LOG(INFO, TAG, "OUT OCUnlinkDevices");
326 PDMDestoryOicUuidLinkList(idList);
330 static OCStackResult RemoveDeviceInfoFromLocal(const OCProvisionDev_t* pTargetDev)
332 // Remove credential of revoked device from SVR database
333 OCStackResult res = OC_STACK_ERROR;
334 const OicSecCred_t *cred = NULL;
335 cred = GetCredResourceData(&pTargetDev->doxm->deviceID);
338 OIC_LOG(ERROR, TAG, "OCRemoveDevice : Failed to get credential of remove device.");
342 res = RemoveCredential(&cred->subject);
343 if (res != OC_STACK_RESOURCE_DELETED)
345 OIC_LOG(ERROR, TAG, "OCRemoveDevice : Failed to remove credential.");
350 * Change the device status as stale status.
351 * If all request are successed, this device information will be deleted.
353 res = PDMSetDeviceStale(&pTargetDev->doxm->deviceID);
354 if (res != OC_STACK_OK)
356 OIC_LOG(ERROR, TAG, "OCRemoveDevice : Failed to set device status as stale");
360 // TODO: We need to add new mechanism to clean up the stale state of the device.
362 //Close the DTLS session of the removed device.
363 CAEndpoint_t* endpoint = (CAEndpoint_t *)&pTargetDev->endpoint;
364 endpoint->port = pTargetDev->securePort;
365 CAResult_t caResult = CACloseDtlsSession(endpoint);
366 if(CA_STATUS_OK != caResult)
368 OIC_LOG_V(WARNING, TAG, "OCRemoveDevice : Failed to close DTLS session : %d", caResult);
376 * Function to device revocation
377 * This function will remove credential of target device from all devices in subnet.
379 * @param[in] ctx Application context would be returned in result callback
380 * @param[in] waitTimeForOwnedDeviceDiscovery Maximum wait time for owned device discovery.(seconds)
381 * @param[in] pTargetDev Device information to be revoked.
382 * @param[in] resultCallback callback provided by API user, callback will be called when
383 * credential revocation is finished.
384 * @return OC_STACK_OK in case of success and other value otherwise.
386 OCStackResult OCRemoveDevice(void* ctx, unsigned short waitTimeForOwnedDeviceDiscovery,
387 const OCProvisionDev_t* pTargetDev,
388 OCProvisionResultCB resultCallback)
390 OIC_LOG(INFO, TAG, "IN OCRemoveDevice");
391 OCStackResult res = OC_STACK_ERROR;
392 if (!pTargetDev || 0 == waitTimeForOwnedDeviceDiscovery)
394 OIC_LOG(INFO, TAG, "OCRemoveDevice : Invalied parameters");
395 return OC_STACK_INVALID_PARAM;
399 OIC_LOG(INFO, TAG, "OCRemoveDevice : NULL Callback");
400 return OC_STACK_INVALID_CALLBACK;
403 // Send DELETE requests to linked devices
404 OCStackResult resReq = OC_STACK_ERROR; // Check that we have to wait callback or not.
405 resReq = SRPRemoveDevice(ctx, waitTimeForOwnedDeviceDiscovery, pTargetDev, resultCallback);
406 if (OC_STACK_OK != resReq)
408 if (OC_STACK_CONTINUE == resReq)
410 OIC_LOG(DEBUG, TAG, "OCRemoveDevice : Revoked device has no linked device except PT.");
414 OIC_LOG(ERROR, TAG, "OCRemoveDevice : Failed to invoke SRPRemoveDevice");
420 res = RemoveDeviceInfoFromLocal(pTargetDev);
421 if(OC_STACK_OK != res)
423 OIC_LOG(ERROR, TAG, "Filed to remove the device information from local.");
427 if(OC_STACK_CONTINUE == resReq)
430 * If there is no linked device, PM does not send any request.
431 * So we should directly invoke the result callback to inform the result of OCRemoveDevice.
435 resultCallback(ctx, 0, NULL, false);
441 OIC_LOG(INFO, TAG, "OUT OCRemoveDevice");
446 * Function to device revocation
447 * This function will remove credential of target device from all devices in subnet.
449 * @param[in] ctx Application context would be returned in result callback
450 * @param[in] waitTimeForOwnedDeviceDiscovery Maximum wait time for owned device discovery.(seconds)
451 * @param[in] pTargetDev Device information to be revoked.
452 * @param[in] resultCallback callback provided by API user, callback will be called when
453 * credential revocation is finished.
454 * @return OC_STACK_OK in case of success and other value otherwise.
456 OCStackResult OCRemoveDeviceWithUuid(void* ctx, unsigned short waitTimeForOwnedDeviceDiscovery,
457 const OicUuid_t* pTargetUuid,
458 OCProvisionResultCB resultCallback)
460 OIC_LOG(INFO, TAG, "IN OCRemoveDeviceWithUuid");
461 OCStackResult res = OC_STACK_ERROR;
462 if (!pTargetUuid || 0 == waitTimeForOwnedDeviceDiscovery)
464 OIC_LOG(INFO, TAG, "OCRemoveDeviceWithUuid : Invalied parameters");
465 return OC_STACK_INVALID_PARAM;
469 OIC_LOG(INFO, TAG, "OCRemoveDeviceWithUuid : NULL Callback");
470 return OC_STACK_INVALID_CALLBACK;
473 OCProvisionDev_t* pOwnedDevList = NULL;
474 //2. Find owned device from the network
475 res = PMDeviceDiscovery(waitTimeForOwnedDeviceDiscovery, true, &pOwnedDevList);
476 if (OC_STACK_OK != res)
478 OIC_LOG(ERROR, TAG, "OCRemoveDeviceWithUuid : Failed to PMDeviceDiscovery");
482 OCProvisionDev_t* pTargetDev = NULL;
483 LL_FOREACH(pOwnedDevList, pTargetDev)
485 if(memcmp(&pTargetDev->doxm->deviceID.id, pTargetUuid->id, sizeof(pTargetUuid->id)) == 0)
491 char* strUuid = NULL;
492 if(OC_STACK_OK != ConvertUuidToStr(pTargetUuid, &strUuid))
494 OIC_LOG(WARNING, TAG, "Failed to covert UUID to String.");
500 OIC_LOG_V(INFO, TAG, "[%s] is dectected on the network.", strUuid);
501 OIC_LOG_V(INFO, TAG, "Trying [%s] revocation.", strUuid);
503 // Send DELETE requests to linked devices
504 OCStackResult resReq = OC_STACK_ERROR; // Check that we have to wait callback or not.
505 resReq = SRPRemoveDeviceWithoutDiscovery(ctx, pOwnedDevList, pTargetDev, resultCallback);
506 if (OC_STACK_OK != resReq)
508 if (OC_STACK_CONTINUE == resReq)
510 OIC_LOG(DEBUG, TAG, "OCRemoveDeviceWithUuid : Revoked device has no linked device except PT.");
514 OIC_LOG(ERROR, TAG, "OCRemoveDeviceWithUuid : Failed to invoke SRPRemoveDevice");
521 res = RemoveDeviceInfoFromLocal(pTargetDev);
522 if(OC_STACK_OK != res)
524 OIC_LOG(ERROR, TAG, "OCRemoveDeviceWithUuid : Filed to remove the device information from local.");
529 if(OC_STACK_CONTINUE == resReq)
532 * If there is no linked device, PM does not send any request.
533 * So we should directly invoke the result callback to inform the result of OCRemoveDevice.
537 resultCallback(ctx, 0, NULL, false);
544 OIC_LOG_V(WARNING, TAG, "OCRemoveDeviceWithUuid : Failed to find the [%s] on the network.", strUuid);
545 res = OC_STACK_ERROR;
550 PMDeleteDeviceList(pOwnedDevList);
551 OIC_LOG(INFO, TAG, "OUT OCRemoveDeviceWithUuid");
556 * Function to reset the target device.
557 * This function will remove credential and ACL of target device from all devices in subnet.
559 * @param[in] ctx Application context would be returned in result callback
560 * @param[in] waitTimeForOwnedDeviceDiscovery Maximum wait time for owned device discovery.(seconds)
561 * @param[in] pTargetDev Device information to be revoked.
562 * @param[in] resultCallback callback provided by API user, callback will be called when
563 * credential revocation is finished.
564 * @return OC_STACK_OK in case of success and other value otherwise.
566 OCStackResult OCResetDevice(void* ctx, unsigned short waitTimeForOwnedDeviceDiscovery,
567 const OCProvisionDev_t* pTargetDev,
568 OCProvisionResultCB resultCallback)
570 OIC_LOG(INFO, TAG, "IN OCResetDevice");
571 OCStackResult res = OC_STACK_ERROR;
572 if (!pTargetDev || 0 == waitTimeForOwnedDeviceDiscovery)
574 OIC_LOG(INFO, TAG, "OCResetDevice : Invalid parameters");
575 return OC_STACK_INVALID_PARAM;
579 OIC_LOG(INFO, TAG, "OCResetDevice : NULL Callback");
580 return OC_STACK_INVALID_CALLBACK;
583 // Send DELETE requests to linked devices
584 res = SRPSyncDevice(ctx, waitTimeForOwnedDeviceDiscovery, pTargetDev, resultCallback);
585 if (OC_STACK_CONTINUE == res)
587 OIC_LOG(DEBUG, TAG, "OCResetDevice : Target device has no linked device except PT.");
590 resultCallback(ctx, 0, NULL, false);
592 SRPResetDevice(pTargetDev, resultCallback);
595 else if(OC_STACK_OK != res)
597 OIC_LOG(ERROR, TAG, "OCResetDevice : Failed to invoke SRPSyncDevice");
599 OIC_LOG(INFO, TAG, "OUT OCResetDevice");
604 * Internal Function to update result in link result array.
606 static void UpdateLinkResults(Linkdata_t *link, int device, OCStackResult stackresult)
609 OIC_LOG_V(INFO,TAG,"value of link->currentCountResults is %d",link->currentCountResults);
612 memcpy(link->resArr[(link->currentCountResults)].deviceId.id, link->pDev1->doxm->deviceID.id,UUID_LENGTH);
616 memcpy(link->resArr[(link->currentCountResults)].deviceId.id, link->pDev2->doxm->deviceID.id,UUID_LENGTH);
618 link->resArr[(link->currentCountResults)].res = stackresult;
619 ++(link->currentCountResults);
624 * Callback to handle ACL provisioning for device 2.
626 static void AclProv2CB(void* ctx, int nOfRes, OCProvisionResult_t *arr, bool hasError)
631 OIC_LOG(ERROR,TAG,"Context is Null in ACLProv 2");
635 Linkdata_t *link = (Linkdata_t*)ctx;
636 OCProvisionResultCB resultCallback = link->resultCallback;
641 UpdateLinkResults(link, 2,arr[0].res);
642 OIC_LOG(ERROR,TAG,"Error occured while ACL provisioning device 1");
643 ((OCProvisionResultCB)(resultCallback))(link->ctx, link->currentCountResults,
646 OICFree(link->resArr);
650 UpdateLinkResults(link, 2, arr[0].res);
651 ((OCProvisionResultCB)(resultCallback))(link->ctx, link->currentCountResults,
654 OICFree(link->resArr);
660 * Callback to handle ACL provisioning for device 1
662 static void AclProv1CB(void* ctx, int nOfRes, OCProvisionResult_t *arr, bool hasError)
667 OIC_LOG(ERROR,TAG,"Context is Null in ACLProv1");
671 Linkdata_t *link = (Linkdata_t*)ctx;
672 OCProvisionResultCB resultCallback = link->resultCallback;
676 OIC_LOG(ERROR,TAG,"Error occured while ACL provisioning device 1");
677 UpdateLinkResults(link, 1, arr[0].res);
678 ((OCProvisionResultCB)(resultCallback))(link->ctx, link->currentCountResults,
681 OICFree(link->resArr);
685 UpdateLinkResults(link, 1, arr[0].res);
686 if (NULL != link->pDev2Acl)
688 OCStackResult res = SRPProvisionACL(ctx, link->pDev2, link->pDev2Acl, &AclProv2CB);
689 if (OC_STACK_OK!=res)
691 UpdateLinkResults(link, 2, res);
692 ((OCProvisionResultCB)(resultCallback))(link->ctx, link->currentCountResults,
700 ((OCProvisionResultCB)(resultCallback))(link->ctx, link->currentCountResults,
703 OICFree(link->resArr);
711 * Callback to handle credential provisioning.
713 static void ProvisionCredsCB(void* ctx, int nOfRes, OCProvisionResult_t *arr, bool hasError)
717 OIC_LOG(ERROR,TAG,"Error occured while credential provisioning");
720 Linkdata_t *link = (Linkdata_t*)ctx;
721 OCProvisionResultCB resultCallback = link->resultCallback;
722 OIC_LOG_V(INFO, TAG, "has error returned %d",hasError);
723 UpdateLinkResults(link, 1, arr[0].res);
724 UpdateLinkResults(link, 2, arr[1].res);
727 OIC_LOG(ERROR,TAG,"Error occured while credential provisioning");
728 ((OCProvisionResultCB)(resultCallback))(link->ctx, nOfRes,
731 OICFree(link->resArr);
735 if (NULL != link->pDev1Acl)
738 OCStackResult res = SRPProvisionACL(ctx, link->pDev1, link->pDev1Acl, &AclProv1CB);
739 if (OC_STACK_OK!=res)
741 OIC_LOG(ERROR, TAG, "Error while provisioning ACL for device 1");
742 UpdateLinkResults(link, 1, res);
743 ((OCProvisionResultCB)(resultCallback))(link->ctx, link->currentCountResults,
746 OICFree(link->resArr);
750 else if (NULL!=link->pDev2Acl)
752 OIC_LOG(ERROR, TAG, "ACL for device 1 is NULL");
753 OCStackResult res = SRPProvisionACL(ctx, link->pDev2, link->pDev2Acl, &AclProv2CB);
754 if (OC_STACK_OK!=res)
756 OIC_LOG(ERROR, TAG, "Error while provisioning ACL for device 2");
757 UpdateLinkResults(link, 2, res);
758 ((OCProvisionResultCB)(resultCallback))(link->ctx, link->currentCountResults,
761 OICFree(link->resArr);
767 OIC_LOG(INFO, TAG, "ACLs of both devices are NULL");
768 ((OCProvisionResultCB)(resultCallback))(link->ctx, link->currentCountResults,
771 OICFree(link->resArr);
777 * function to provision credentials between two devices and ACLs for the devices who act as a server.
779 * @param[in] ctx Application context would be returned in result callback.
780 * @param[in] type Type of credentials to be provisioned to the device.
781 * @param[in] pDev1 Pointer to OCProvisionDev_t instance,respresenting resource to be provsioned.
782 * @param[in] acl ACL for device 1. If this is not required set NULL.
783 * @param[in] pDev2 Pointer to OCProvisionDev_t instance,respresenting resource to be provsioned.
784 * @param[in] acl ACL for device 2. If this is not required set NULL.
785 * @param[in] resultCallback callback provided by API user, callback will be called when
786 * provisioning request recieves a response from first resource server.
787 * @return OC_STACK_OK in case of success and other value otherwise.
789 OCStackResult OCProvisionPairwiseDevices(void* ctx, OicSecCredType_t type, size_t keySize,
790 const OCProvisionDev_t *pDev1, OicSecAcl_t *pDev1Acl,
791 const OCProvisionDev_t *pDev2, OicSecAcl_t *pDev2Acl,
792 OCProvisionResultCB resultCallback)
795 if (!pDev1 || !pDev2 || !pDev1->doxm || !pDev2->doxm)
797 OIC_LOG(ERROR, TAG, "OCProvisionPairwiseDevices : Invalid parameters");
798 return OC_STACK_INVALID_PARAM;
802 OIC_LOG(INFO, TAG, "OCProvisionPairwiseDevices : NULL Callback");
803 return OC_STACK_INVALID_CALLBACK;
805 if (!(keySize == OWNER_PSK_LENGTH_128 || keySize == OWNER_PSK_LENGTH_256))
807 OIC_LOG(INFO, TAG, "OCProvisionPairwiseDevices : Invalid key size");
808 return OC_STACK_INVALID_PARAM;
810 if (0 == memcmp(&pDev1->doxm->deviceID, &pDev2->doxm->deviceID, sizeof(OicUuid_t)))
812 OIC_LOG(INFO, TAG, "OCProvisionPairwiseDevices : Same device ID");
813 return OC_STACK_INVALID_PARAM;
816 OIC_LOG(DEBUG, TAG, "Checking link in DB");
817 bool linkExists = true;
818 OCStackResult res = PDMIsLinkExists(&pDev1->doxm->deviceID, &pDev2->doxm->deviceID, &linkExists);
819 if(res != OC_STACK_OK)
821 OIC_LOG(ERROR, TAG, "Internal Error Occured");
826 OIC_LOG(ERROR, TAG, "Link already exists");
827 return OC_STACK_INVALID_PARAM;
830 int noOfResults = 2; // Initial Value
831 if (NULL != pDev1Acl)
835 if (NULL != pDev2Acl)
839 Linkdata_t *link = (Linkdata_t*) OICMalloc(sizeof(Linkdata_t));
842 OIC_LOG(ERROR, TAG, "Failed to memory allocation");
843 return OC_STACK_NO_MEMORY;
845 OIC_LOG_V(INFO,TAG, "Maximum no od results %d",noOfResults);
848 link->pDev1Acl = pDev1Acl;
850 link->pDev2Acl = pDev2Acl;
852 // 1 call for each device for credential provisioning. implict call by SRPProvisioning credential
853 // 1 call for ACL provisioning for device 1 and 1 call for ACL provisioning for device 2.
854 link->numOfResults = noOfResults;
855 link->resultCallback = resultCallback;
856 link->currentCountResults = 0;
857 link->resArr = (OCProvisionResult_t*) OICMalloc(sizeof(OCProvisionResult_t)*noOfResults);
858 res = SRPProvisionCredentials(link, type, keySize,
859 pDev1, pDev2, &ProvisionCredsCB);
860 if (res != OC_STACK_OK)
862 OICFree(link->resArr);
869 OCStackResult OCGetDevInfoFromNetwork(unsigned short waittime,
870 OCProvisionDev_t** pOwnedDevList,
871 OCProvisionDev_t** pUnownedDevList)
873 //TODO will be replaced by more efficient logic
874 if (pOwnedDevList == NULL || *pOwnedDevList != NULL || pUnownedDevList == NULL
875 || *pUnownedDevList != NULL || 0 == waittime)
877 return OC_STACK_INVALID_PARAM;
880 // Code for unowned discovery
881 OCProvisionDev_t *unownedDevice = NULL;
882 OCStackResult res = OCDiscoverUnownedDevices(waittime/2, &unownedDevice);
883 if (OC_STACK_OK != res)
885 OIC_LOG(ERROR,TAG, "Error in unowned discovery");
889 // Code for owned discovery
890 OCProvisionDev_t *ownedDevice = NULL;
891 res = OCDiscoverOwnedDevices(waittime/2, &ownedDevice);
892 if (OC_STACK_OK != res)
894 OIC_LOG(ERROR,TAG, "Error in owned discovery");
895 PMDeleteDeviceList(unownedDevice);
899 // Code to get list of all the owned devices.
900 OCUuidList_t *uuidList = NULL;
901 size_t numOfDevices = 0;
902 res = PDMGetOwnedDevices(&uuidList, &numOfDevices);
903 if (OC_STACK_OK != res)
905 OIC_LOG(ERROR, TAG, "Error while getting info from DB");
906 PMDeleteDeviceList(unownedDevice);
907 PMDeleteDeviceList(ownedDevice);
911 // Code to compare devices in owned list and deviceid from DB.
912 OCProvisionDev_t* pCurDev = ownedDevice;
913 size_t deleteCnt = 0;
916 if(true == PMDeleteFromUUIDList(&uuidList, &pCurDev->doxm->deviceID))
920 pCurDev = pCurDev->next;
922 // If there is no remaind device in uuidList, we have to assign NULL to prevent free.
923 if (deleteCnt == numOfDevices)
927 // Code to add information of the devices which are currently off in owned list.
928 OCUuidList_t *powerOffDeviceList = uuidList;
929 while (powerOffDeviceList)
931 OCProvisionDev_t *ptr = (OCProvisionDev_t *)OICCalloc(1, sizeof (OCProvisionDev_t));
934 OIC_LOG(ERROR,TAG,"Fail to allocate memory");
935 PMDeleteDeviceList(unownedDevice);
936 PMDeleteDeviceList(ownedDevice);
937 OCDeleteUuidList(uuidList);
938 return OC_STACK_NO_MEMORY;
941 ptr->doxm = (OicSecDoxm_t*)OICCalloc(1, sizeof(OicSecDoxm_t));
942 if (NULL == ptr->doxm)
944 OIC_LOG(ERROR,TAG,"Fail to allocate memory");
945 PMDeleteDeviceList(unownedDevice);
946 PMDeleteDeviceList(ownedDevice);
947 OCDeleteUuidList(uuidList);
949 return OC_STACK_NO_MEMORY;
952 memcpy(ptr->doxm->deviceID.id, powerOffDeviceList->dev.id, sizeof(ptr->doxm->deviceID.id));
954 ptr->devStatus = DEV_STATUS_OFF;
955 LL_PREPEND(ownedDevice, ptr);
956 powerOffDeviceList = powerOffDeviceList->next;
959 OCDeleteUuidList(uuidList);
960 *pOwnedDevList = ownedDevice;
961 *pUnownedDevList = unownedDevice;
965 OCStackResult OCGetLinkedStatus(const OicUuid_t* uuidOfDevice, OCUuidList_t** uuidList,
966 size_t* numOfDevices)
968 return PDMGetLinkedDevices(uuidOfDevice, uuidList, numOfDevices);
971 void OCDeleteUuidList(OCUuidList_t* pList)
973 PDMDestoryOicUuidLinkList(pList);
977 * This function deletes ACL data.
979 * @param pAcl Pointer to OicSecAcl_t structure.
981 void OCDeleteACLList(OicSecAcl_t* pAcl)
987 * This function deletes PDACL data.
989 * @param pPdAcl Pointer to OicSecPdAcl_t structure.
991 void OCDeletePdAclList(OicSecPdAcl_t* pPdAcl)
993 FreePdAclList(pPdAcl);
999 * this function sends CRL information to resource.
1001 * @param[in] ctx Application context would be returned in result callback.
1002 * @param[in] selectedDeviceInfo Selected target device.
1003 * @param[in] crl CRL to provision.
1004 * @param[in] resultCallback callback provided by API user, callback will be called when provisioning
1005 request recieves a response from resource server.
1006 * @return OC_STACK_OK in case of success and other value otherwise.
1008 OCStackResult OCProvisionCRL(void* ctx, const OCProvisionDev_t *selectedDeviceInfo, OicSecCrl_t *crl,
1009 OCProvisionResultCB resultCallback)
1011 return SRPProvisionCRL(ctx, selectedDeviceInfo, crl, resultCallback);
1013 #endif // __WITH_X509__