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 *****************************************************************/
26 #include "oic_malloc.h"
27 #include "oic_string.h"
28 #include "ocprovisioningmanager.h"
29 #include "oxmjustworks.h"
30 #include "oxmrandompin.h"
31 #include "securevirtualresourcetypes.h"
32 #include "srmutility.h"
40 // declaration(s) for provisioning client using C-level provisioning API
41 // user input definition for main loop on provisioning client
42 #define _10_DISCOV_ALL_DEVS_ 10
43 #define _11_DISCOV_UNOWN_DEVS_ 11
44 #define _12_DISCOV_OWN_DEVS_ 12
45 #define _20_REGIST_DEVS_ 20
46 #define _30_PROVIS_PAIR_DEVS_ 30
47 #define _31_PROVIS_CRED_ 31
48 #define _32_PROVIS_ACL_ 32
49 #define _33_PROVIS_DP_ 33
50 #define _34_CHECK_LINK_STATUS_ 34
51 #define _40_UNLINK_PAIR_DEVS_ 40
52 #define _50_REMOVE_SELEC_DEV_ 50
53 #define _99_EXIT_PRVN_CLT_ 99
55 #define ACL_RESRC_MAX_NUM 16
56 #define ACL_RESRC_MAX_LEN 128
57 #define ACL_PEMISN_CNT 5
58 #define DISCOVERY_TIMEOUT 10 // 10 sec
59 #define CALLBACK_TIMEOUT 60 // 1 min
60 #define TAG "provisioningclient"
62 static const char* ACL_PEMISN[5] = {"CREATE", "READ", "WRITE", "DELETE", "NOTIFY"};
63 static const char* SVR_DB_FILE_NAME = "oic_svr_db_client.json";
64 // '_' for separaing from the same constant variable in |srmresourcestrings.c|
65 static const char* PRVN_DB_FILE_NAME = "oic_prvn_mng.db";
66 static const OicSecPrm_t SUPPORTED_PRMS[1] =
71 // |g_ctx| means provision manager application context and
72 // the following, includes |un/own_list|, could be variables, which |g_ctx| has,
73 // for accessing all function(s) for these, they are declared on global domain
74 static const char* g_ctx = "Provision Manager Client Application Context";
75 static char* g_svr_fname;
76 static char* g_prvn_fname;
77 static OCProvisionDev_t* g_own_list;
78 static OCProvisionDev_t* g_unown_list;
80 static int g_unown_cnt;
83 // function declaration(s) for calling them before implementing
84 static OicSecAcl_t* createAcl(const int);
85 static OicSecPdAcl_t* createPdAcl(const int);
86 static OCProvisionDev_t* getDevInst(const OCProvisionDev_t*, const int);
87 static int printDevList(const OCProvisionDev_t*);
88 static size_t printUuidList(const OCUuidList_t*);
89 static int printResultList(const OCProvisionResult_t*, const int);
90 static void printUuid(const OicUuid_t*);
91 static FILE* fopen_prvnMng(const char*, const char*);
92 static int waitCallbackRet(void);
93 static int selectTwoDiffNum(int*, int*, const int, const char*);
95 // callback function(s) for provisioning client using C-level provisioning API
96 static void ownershipTransferCB(void* ctx, int nOfRes, OCProvisionResult_t* arr, bool hasError)
100 OIC_LOG_V(INFO, TAG, "Ownership Transfer SUCCEEDED - ctx: %s", (char*) ctx);
104 OIC_LOG_V(ERROR, TAG, "Ownership Transfer FAILED - ctx: %s", (char*) ctx);
105 printResultList((const OCProvisionResult_t*) arr, nOfRes);
110 static void provisionPairwiseCB(void* ctx, int nOfRes, OCProvisionResult_t* arr, bool hasError)
114 OIC_LOG_V(INFO, TAG, "Provision Pairwise SUCCEEDED - ctx: %s", (char*) ctx);
118 OIC_LOG_V(ERROR, TAG, "Provision Pairwise FAILED - ctx: %s", (char*) ctx);
119 printResultList((const OCProvisionResult_t*) arr, nOfRes);
124 static void provisionCredCB(void* ctx, int nOfRes, OCProvisionResult_t* arr, bool hasError)
128 OIC_LOG_V(INFO, TAG, "Provision Credential SUCCEEDED - ctx: %s", (char*) ctx);
132 OIC_LOG_V(ERROR, TAG, "Provision Credential FAILED - ctx: %s", (char*) ctx);
133 printResultList((const OCProvisionResult_t*) arr, nOfRes);
138 static void provisionAclCB(void* ctx, int nOfRes, OCProvisionResult_t* arr, bool hasError)
142 OIC_LOG_V(INFO, TAG, "Provision ACL SUCCEEDED - ctx: %s", (char*) ctx);
146 OIC_LOG_V(ERROR, TAG, "Provision ACL FAILED - ctx: %s", (char*) ctx);
147 printResultList((const OCProvisionResult_t*) arr, nOfRes);
152 static void provisionDPCB(void* ctx, int nOfRes, OCProvisionResult_t* arr, bool hasError)
156 OIC_LOG_V(INFO, TAG, "Provision Direct-Pairing SUCCEEDED - ctx: %s", (char*) ctx);
160 OIC_LOG_V(ERROR, TAG, "Provision Direct-Pairing FAILED - ctx: %s", (char*) ctx);
161 printResultList((const OCProvisionResult_t*) arr, nOfRes);
166 static void unlinkDevicesCB(void* ctx, int nOfRes, OCProvisionResult_t* arr, bool hasError)
170 OIC_LOG_V(INFO, TAG, "Unlink Devices SUCCEEDED - ctx: %s", (char*) ctx);
174 OIC_LOG_V(ERROR, TAG, "Unlink Devices FAILED - ctx: %s", (char*) ctx);
175 printResultList((const OCProvisionResult_t*) arr, nOfRes);
180 static void removeDeviceCB(void* ctx, int nOfRes, OCProvisionResult_t* arr, bool hasError)
184 OIC_LOG_V(INFO, TAG, "Remove Device SUCCEEDED - ctx: %s", (char*) ctx);
188 OIC_LOG_V(ERROR, TAG, "Remove Device FAILED - ctx: %s", (char*) ctx);
189 printResultList((const OCProvisionResult_t*) arr, nOfRes);
194 static void inputPinCB(char* pin, size_t len)
196 if(!pin || OXM_RANDOM_PIN_SIZE>=len)
198 OIC_LOG(ERROR, TAG, "inputPinCB invalid parameters");
202 printf(" > INPUT PIN: ");
203 for(int ret=0; 1!=ret; )
205 ret = scanf("%8s", pin);
206 for( ; 0x20<=getchar(); ); // for removing overflow garbages
207 // '0x20<=code' is character region
211 // function(s) for provisioning client using C-level provisioning API
212 static int initProvisionClient(void)
214 // initialize persistent storage for SVR DB
215 static OCPersistentStorage pstStr =
217 .open = fopen_prvnMng,
223 if(OC_STACK_OK != OCRegisterPersistentStorageHandler(&pstStr))
225 OIC_LOG(ERROR, TAG, "OCRegisterPersistentStorageHandler error");
229 // initialize OC stack and provisioning manager
230 if(OC_STACK_OK != OCInit(NULL, 0, OC_CLIENT_SERVER))
232 OIC_LOG(ERROR, TAG, "OCStack init error");
236 if (access(PRVN_DB_FILE_NAME, F_OK) != -1)
238 printf("************************************************************\n");
239 printf("************Provisioning DB file already exists.************\n");
240 printf("************************************************************\n");
244 printf("*************************************************************\n");
245 printf("************No provisioning DB file, creating new************\n");
246 printf("*************************************************************\n");
249 if(OC_STACK_OK != OCInitPM(PRVN_DB_FILE_NAME))
251 OIC_LOG(ERROR, TAG, "OC_PM init error");
255 // register callback function(s) to each OxM
256 OTMCallbackData_t otmcb =
258 .loadSecretCB = LoadSecretJustWorksCallback,
259 .createSecureSessionCB = CreateSecureSessionJustWorksCallback,
260 .createSelectOxmPayloadCB = CreateJustWorksSelectOxmPayload,
261 .createOwnerTransferPayloadCB = CreateJustWorksOwnerTransferPayload
263 if(OC_STACK_OK != OCSetOwnerTransferCallbackData(OIC_JUST_WORKS, &otmcb))
265 OIC_LOG(ERROR, TAG, "OCSetOwnerTransferCallbackData error: OIC_JUST_WORKS");
268 otmcb.loadSecretCB = InputPinCodeCallback;
269 otmcb.createSecureSessionCB = CreateSecureSessionRandomPinCallback;
270 otmcb.createSelectOxmPayloadCB = CreatePinBasedSelectOxmPayload;
271 otmcb.createOwnerTransferPayloadCB = CreatePinBasedOwnerTransferPayload;
272 if(OC_STACK_OK != OCSetOwnerTransferCallbackData(OIC_RANDOM_DEVICE_PIN, &otmcb))
274 OIC_LOG(ERROR, TAG, "OCSetOwnerTransferCallbackData error: OIC_RANDOM_DEVICE_PIN");
277 SetInputPinCB(inputPinCB);
282 static int discoverAllDevices(void)
284 // delete un/owned device lists before updating them
287 OCDeleteDiscoveredDevices(g_own_list);
292 OCDeleteDiscoveredDevices(g_unown_list);
296 // call |OCGetDevInfoFromNetwork| API actually
297 printf(" Discovering All Un/Owned Devices on Network..\n");
298 if(OC_STACK_OK != OCGetDevInfoFromNetwork(DISCOVERY_TIMEOUT, &g_own_list, &g_unown_list))
300 OIC_LOG(ERROR, TAG, "OCGetDevInfoFromNetwork API error");
304 // display the discovered un/owned lists
305 printf(" > Discovered Owned Devices\n");
306 g_own_cnt = printDevList(g_own_list);
307 printf(" > Discovered Unowned Devices\n");
308 g_unown_cnt = printDevList(g_unown_list);
314 static int discoverUnownedDevices(void)
316 // delete unowned device list before updating it
319 OCDeleteDiscoveredDevices(g_unown_list);
323 // call |OCDiscoverUnownedDevices| API actually
324 printf(" Discovering Only Unowned Devices on Network..\n");
325 if(OC_STACK_OK != OCDiscoverUnownedDevices(DISCOVERY_TIMEOUT, &g_unown_list))
327 OIC_LOG(ERROR, TAG, "OCDiscoverUnownedDevices API error");
331 // display the discovered unowned list
332 printf(" > Discovered Unowned Devices\n");
333 g_unown_cnt = printDevList(g_unown_list);
338 static int discoverOwnedDevices(void)
340 // delete owned device list before updating it
343 OCDeleteDiscoveredDevices(g_own_list);
347 // call |OCDiscoverOwnedDevices| API actually
348 printf(" Discovering Only Owned Devices on Network..\n");
349 if(OC_STACK_OK != OCDiscoverOwnedDevices(DISCOVERY_TIMEOUT, &g_own_list))
351 OIC_LOG(ERROR, TAG, "OCDiscoverOwnedDevices API error");
355 // display the discovered owned list
356 printf(" > Discovered Owned Devices\n");
357 g_own_cnt = printDevList(g_own_list);
362 static int registerDevices(void)
364 // check |unown_list| for registering devices
365 if(!g_unown_list || 0>=g_unown_cnt)
367 printf(" > Unowned Device List, to Register Devices, is Empty\n");
368 printf(" > Please Discover Unowned Devices first, with [10|11] Menu\n");
369 return 0; // normal case
372 // call |OCDoOwnershipTransfer| API actually
373 // calling this API with callback actually acts like blocking
374 // for error checking, the return value saved and printed
376 printf(" Registering All Discovered Unowned Devices..\n");
377 OCStackResult rst = OCDoOwnershipTransfer((void*) g_ctx, g_unown_list, ownershipTransferCB);
378 if(OC_STACK_OK != rst)
380 OIC_LOG_V(ERROR, TAG, "OCDoOwnershipTransfer API error: %d", rst);
383 if(waitCallbackRet()) // input |g_doneCB| flag implicitly
385 OIC_LOG(ERROR, TAG, "OCProvisionCredentials callback error");
389 // display the registered result
390 printf(" > Registered Discovered Unowned Devices\n");
391 printf(" > Please Discover Owned Devices for the Registered Result, with [10|12] Menu\n");
396 static int provisionPairwise(void)
398 // check |own_list| for provisioning pairwise devices
399 if(!g_own_list || 2>g_own_cnt)
401 printf(" > Owned Device List, to Provision the Pairwise, is Empty\n");
402 printf(" > Please Register Unowned Devices first, with [20] Menu\n");
403 return 0; // normal case
406 // select two devices for provisioning pairwise devices
407 int dev_num[2] = {0};
408 if(selectTwoDiffNum(&(dev_num[0]), &(dev_num[1]), g_own_cnt, "for Linking Devices"))
410 OIC_LOG(ERROR, TAG, "selectTwoDiffNum error return");
411 return -1; // not need to 'goto' |ERROR| before allocating |acl|
414 // create ACL(s) for each selected device
415 OicSecAcl_t* acl[2] = {0};
416 for(int i=0; 2>i; ++i)
418 acl[i] = createAcl(dev_num[i]);
421 OIC_LOG(ERROR, TAG, "createAcl error return");
426 // call |OCProvisionPairwiseDevices| API actually
427 // calling this API with callback actually acts like blocking
428 // for error checking, the return value saved and printed
430 printf(" Provisioning Selected Pairwise Devices..\n");
432 OCProvisionPairwiseDevices((void*) g_ctx,
433 SYMMETRIC_PAIR_WISE_KEY, OWNER_PSK_LENGTH_128,
434 getDevInst((const OCProvisionDev_t*) g_own_list, dev_num[0]), acl[0],
435 getDevInst((const OCProvisionDev_t*) g_own_list, dev_num[1]), acl[1],
436 provisionPairwiseCB);
437 if(OC_STACK_OK != rst)
439 OIC_LOG_V(ERROR, TAG, "OCProvisionPairwiseDevices API error: %d", rst);
442 if(waitCallbackRet()) // input |g_doneCB| flag implicitly
444 OIC_LOG(ERROR, TAG, "OCProvisionCredentials callback error");
447 OCDeleteACLList(acl[0]);
448 OCDeleteACLList(acl[1]);
450 // display the pairwise-provisioned result
451 printf(" > Provisioned Selected Pairwise Devices\n");
452 printf(" > Please Check Device's Status for the Linked Result, with [33] Menu\n");
457 OCDeleteACLList(acl[0]);
458 OCDeleteACLList(acl[1]);
462 static int provisionCred(void)
464 // check |own_list| for provisioning pairwise credentials
465 if(!g_own_list || 2>g_own_cnt)
467 printf(" > Owned Device List, to Provision Credentials, is Empty\n");
468 printf(" > Please Register Unowned Devices first, with [20] Menu\n");
469 return 0; // normal case
472 // select two devices for provisioning pairwise credentials
473 int dev_num[2] = {0};
474 if(selectTwoDiffNum(&(dev_num[0]), &(dev_num[1]), g_own_cnt, "for Linking CRED(s)"))
476 OIC_LOG(ERROR, TAG, "selectTwoDiffNum error return");
480 printf(" Select PSK length..\n");
481 printf(" 1 - 128bit(Default)\n");
482 printf(" 2 - 256bit\n");
485 for(int ret=0; 1!=ret; )
487 ret = scanf("%d",&sizeOption);
488 for( ; 0x20<=getchar(); ); // for removing overflow garbages
489 // '0x20<=code' is character region
497 size = OWNER_PSK_LENGTH_128;
502 size = OWNER_PSK_LENGTH_256;
507 size = OWNER_PSK_LENGTH_128;
513 // call |OCProvisionCredentials| API actually
514 // calling this API with callback actually acts like blocking
515 // for error checking, the return value saved and printed
517 printf(" Provisioning Selected Pairwise Credentials..\n");
519 OCProvisionCredentials((void*) g_ctx,
520 SYMMETRIC_PAIR_WISE_KEY, size,
521 getDevInst((const OCProvisionDev_t*) g_own_list, dev_num[0]),
522 getDevInst((const OCProvisionDev_t*) g_own_list, dev_num[1]),
524 if(OC_STACK_OK != rst)
526 OIC_LOG_V(ERROR, TAG, "OCProvisionCredentials API error: %d", rst);
529 if(waitCallbackRet()) // input |g_doneCB| flag implicitly
531 OIC_LOG(ERROR, TAG, "OCProvisionCredentials callback error");
535 // display the CRED-provisioned result
536 printf(" > Provisioned Selected Pairwise Crendentials\n");
537 printf(" > Please Check Device's Status for the Linked Result, with [33] Menu\n");
542 static int provisionAcl(void)
544 // check |own_list| for provisioning access control list
545 if(!g_own_list || 1>g_own_cnt)
547 printf(" > Owned Device List, to Provision ACL, is Empty\n");
548 printf(" > Please Register Unowned Devices first, with [20] Menu\n");
549 return 0; // normal case
552 // select device for provisioning access control list
556 printf(" > Enter Device Number, for Provisioning ACL: ");
557 for(int ret=0; 1!=ret; )
559 ret = scanf("%d", &dev_num);
560 for( ; 0x20<=getchar(); ); // for removing overflow garbages
561 // '0x20<=code' is character region
563 if(0<dev_num && g_own_cnt>=dev_num)
567 printf(" Entered Wrong Number. Please Enter Again\n");
570 // create ACL for selected device
571 OicSecAcl_t* acl = NULL;
572 acl = createAcl(dev_num);
575 OIC_LOG(ERROR, TAG, "createAcl error return");
579 // call |OCProvisionACL| API actually
580 // calling this API with callback actually acts like blocking
581 // for error checking, the return value saved and printed
583 printf(" Provisioning Selected ACL..\n");
584 OCProvisionDev_t* dev = getDevInst((const OCProvisionDev_t*) g_own_list, dev_num);
587 OIC_LOG(ERROR, TAG, "provisionAcl: device instance empty");
590 OCStackResult rst = OCProvisionACL((void*) g_ctx, dev, acl, provisionAclCB);
591 if(OC_STACK_OK != rst)
593 OIC_LOG_V(ERROR, TAG, "OCProvisionACL API error: %d", rst);
596 if(waitCallbackRet()) // input |g_doneCB| flag implicitly
598 OIC_LOG(ERROR, TAG, "OCProvisionCredentials callback error");
601 OCDeleteACLList(acl); // after here |acl| points nothing
603 // display the ACL-provisioned result
604 printf(" > Provisioned Selected ACL\n");
609 OCDeleteACLList(acl); // after here |acl| points nothing
613 static int provisionDirectPairing(void)
615 // check |own_list| for provisioning direct-pairing
616 if(!g_own_list || 1>g_own_cnt)
618 printf(" > Owned Device List, to Provision ACL, is Empty\n");
619 printf(" > Please Register Unowned Devices first, with [20] Menu\n");
620 return 0; // normal case
623 // select device for provisioning direct-pairing
627 printf(" > Enter Device Number, for Provisioning Direct-Pairing: ");
628 for(int ret=0; 1!=ret; )
630 ret = scanf("%d", &dev_num);
631 for( ; 0x20<=getchar(); ); // for removing overflow garbages
632 // '0x20<=code' is character region
634 if(0<dev_num && g_own_cnt>=dev_num)
638 printf(" Entered Wrong Number. Please Enter Again\n");
641 // create Direct-Pairing Configuration(PIN, PDACL) for selected device
642 // TODO: default acl -> input from user !
644 memset(&pconf, 0, sizeof(OicSecPconf_t));
649 // set default supported PRM types
650 pconf.prmLen = sizeof(SUPPORTED_PRMS)/sizeof(OicSecPrm_t);
651 pconf.prm = (OicSecPrm_t *)OICCalloc(pconf.prmLen, sizeof(OicSecPrm_t));
654 for (size_t i=0; i<pconf.prmLen; i++)
656 pconf.prm[i] = SUPPORTED_PRMS[i];
661 OIC_LOG(ERROR, TAG, "create prm error return");
666 const char DP_DEFAULT_PIN[] = "00000000";
667 memcpy(pconf.pin.val, DP_DEFAULT_PIN, DP_PIN_LENGTH);
670 pconf.pdacls = createPdAcl(dev_num);
673 OIC_LOG(ERROR, TAG, "createPdAcl error return");
677 // call |OCProvisionDirectPairing| API actually
678 // calling this API with callback actually acts like blocking
679 // for error checking, the return value saved and printed
681 printf(" Atempt Direct-Pairing Provisioning (PIN : [%s])..\n", (char*)pconf.pin.val);
682 OCStackResult rst = OCProvisionDirectPairing((void*) g_ctx,
683 getDevInst((const OCProvisionDev_t*) g_own_list, dev_num),
684 &pconf, provisionDPCB);
685 if(OC_STACK_OK != rst)
687 OIC_LOG_V(ERROR, TAG, "OCProvisionDirectPairing API error: %d", rst);
688 if (OC_STACK_UNAUTHORIZED_REQ == rst)
690 OIC_LOG(ERROR, TAG, "Target Server NOT Support Direct-Pairing !!! (DPC == false)");
694 if(waitCallbackRet()) // input |g_doneCB| flag implicitly
696 OIC_LOG(ERROR, TAG, "OCProvisionCredentials callback error");
699 OCDeletePdAclList(pconf.pdacls);
701 // display the PCONF-provisioned result
702 printf(" > SUCCESS to provision Direct-Pairing !!\n");
707 OCDeletePdAclList(pconf.pdacls); // after here |acl| points nothing
711 static int checkLinkedStatus(void)
713 // check |own_list| for checking selected link status on PRVN DB
714 if(!g_own_list || 1>g_own_cnt)
716 printf(" > Owned Device List, to Check Linked Status on PRVN DB, is Empty\n");
717 printf(" > Please Register Unowned Devices first, with [20] Menu\n");
718 return 0; // normal case
721 // select device for checking selected link status on PRVN DB
725 printf(" > Enter Device Number, for Checking Linked Status on PRVN DB: ");
726 for(int ret=0; 1!=ret; )
728 ret = scanf("%d", &dev_num);
729 for( ; 0x20<=getchar(); ); // for removing overflow garbages
730 // '0x20<=code' is character region
732 if(0<dev_num && g_own_cnt>=dev_num)
736 printf(" Entered Wrong Number. Please Enter Again\n");
739 // call |OCGetLinkedStatus| API actually
740 printf(" Checking Selected Link Status on PRVN DB..\n");
741 OCUuidList_t* dvid_lst = NULL;
743 OCProvisionDev_t* dev = getDevInst((const OCProvisionDev_t*)g_own_list, dev_num);
744 if(!dev || !dev->doxm)
746 OIC_LOG(ERROR, TAG, "checkLinkedStatus: device instance empty");
752 &dev->doxm->deviceID,
753 &dvid_lst, &dvid_cnt)) // allow empty list
755 OIC_LOG(ERROR, TAG, "OCGetLinkedStatus API error");
759 // display the linked status result
760 printf(" > Checked Selected Link Status on PRVN DB\n");
761 if(!dvid_lst || !dvid_cnt) // |size_t| is unsigned
763 printf(" Linked Device List is Empty..\n");
764 return 0; // normal case
766 if(dvid_cnt != printUuidList((const OCUuidList_t*) dvid_lst))
768 OIC_LOG(ERROR, TAG, "printUuidList error return");
771 OCDeleteUuidList(dvid_lst);
776 OCDeleteUuidList(dvid_lst);
780 static int unlinkPairwise(void)
782 // check |own_list| for unlinking pairwise devices
783 if(!g_own_list || 2>g_own_cnt)
785 printf(" > Owned Device List, to Unlink the Pairwise, is Empty\n");
786 printf(" > Please Register Unowned Devices first, with [20] Menu\n");
787 return 0; // normal case
790 // select two devices for unlinking pairwise devices
791 int dev_num[2] = {0};
792 if(selectTwoDiffNum(&(dev_num[0]), &(dev_num[1]), g_own_cnt, "for Unlinking Devices"))
794 OIC_LOG(ERROR, TAG, "selectTwoDiffNum error return");
798 // call |OCUnlinkDevices| API actually
799 // calling this API with callback actually acts like blocking
800 // for error checking, the return value saved and printed
802 printf(" Unlinking Selected Pairwise Devices..\n");
804 OCUnlinkDevices((void*) g_ctx,
805 getDevInst((const OCProvisionDev_t*) g_own_list, dev_num[0]),
806 getDevInst((const OCProvisionDev_t*) g_own_list, dev_num[1]),
808 if(OC_STACK_OK != rst)
810 OIC_LOG_V(ERROR, TAG, "OCUnlinkDevices API error: %d", rst);
813 if(waitCallbackRet()) // input |g_doneCB| flag implicitly
815 OIC_LOG(ERROR, TAG, "OCProvisionCredentials callback error");
819 // display the pairwise-unlinked result
820 printf(" > Unlinked Selected Pairwise Devices\n");
821 printf(" > Please Check Device's Status for the Unlinked Result, with [33] Menu\n");
826 static int removeDevice(void)
828 // check |own_list| for removing device
829 if(!g_own_list || 1>g_own_cnt)
831 printf(" > Owned Device List, to Remove Device, is Empty\n");
832 printf(" > Please Register Unowned Devices first, with [20] Menu\n");
833 return 0; // normal case
836 // select device for removing it
840 printf(" > Enter Device Number, for Removing Device: ");
841 for(int ret=0; 1!=ret; )
843 ret = scanf("%d", &dev_num);
844 for( ; 0x20<=getchar(); ); // for removing overflow garbages
845 // '0x20<=code' is character region
847 if(0<dev_num && g_own_cnt>=dev_num)
851 printf(" Entered Wrong Number. Please Enter Again\n");
854 // call |OCRemoveDevice| API actually
855 // calling this API with callback actually acts like blocking
856 // for error checking, the return value saved and printed
858 printf(" Removing Selected Owned Device..\n");
860 OCRemoveDevice((void*) g_ctx, DISCOVERY_TIMEOUT,
861 getDevInst((const OCProvisionDev_t*) g_own_list, dev_num), removeDeviceCB);
862 if(OC_STACK_OK != rst)
864 OIC_LOG_V(ERROR, TAG, "OCRemoveDevice API error: %d", rst);
867 if(waitCallbackRet()) // input |g_doneCB| flag implicitly
869 OIC_LOG(ERROR, TAG, "OCProvisionCredentials callback error");
873 // display the removed result
874 printf(" > Removed Selected Owned Device\n");
875 printf(" > Please Discover Owned Devices for the Registered Result, with [10|12] Menu\n");
880 static OicSecAcl_t* createAcl(const int dev_num)
882 if(0>=dev_num || g_own_cnt<dev_num)
884 OIC_LOG(ERROR, TAG, "createAcl invalid parameters");
885 return NULL; // not need to 'goto' |ERROR| before allocating |acl|
888 // allocate memory for |acl| struct
889 printf(" **** Create ACL for the Selected Device[%d]\n", dev_num);
890 OicSecAcl_t* acl = (OicSecAcl_t*) OICCalloc(1, sizeof(OicSecAcl_t));
893 OIC_LOG(ERROR, TAG, "createAcl: OICCalloc error return");
894 return NULL; // not need to 'goto' |ERROR| before allocating |acl|
897 // enter |subject| device number
901 printf(" > [A] Enter Subject Device Number: ");
902 for(int ret=0; 1!=ret; )
904 ret = scanf("%d", &num);
905 for( ; 0x20<=getchar(); ); // for removing overflow garbages
906 // '0x20<=code' is character region
908 if(0<num && g_own_cnt>=num && dev_num!=num)
912 printf(" Entered Wrong Number. Please Enter Again\n");
915 OCProvisionDev_t* dev = getDevInst((const OCProvisionDev_t*)g_own_list, num);
916 if(!dev || !dev->doxm)
918 OIC_LOG(ERROR, TAG, "createAcl: device instance empty");
921 memcpy(&acl->subject, &dev->doxm->deviceID, UUID_LENGTH);
923 // enter number of |resources| in 'accessed' device
926 printf(" > [B] Enter Number of Accessed Resources (under 16): ");
927 // '16' is |ACL_RESRC_MAX_NUM|
928 for(int ret=0; 1!=ret; )
930 ret = scanf("%d", &num);
931 for( ; 0x20<=getchar(); ); // for removing overflow garbages
932 // '0x20<=code' is character region
934 if(0<num && ACL_RESRC_MAX_NUM>=num)
938 printf(" Entered Wrong Number. Please Enter under 16 Again\n");
939 // '16' is |ACL_RESRC_MAX_NUM|
942 // enter actually each 'accessed' |resources| name
943 printf(" Enter Each Accessed Resource Name (each under 128 char)\n");
944 // '128' is ACL_RESRC_MAX_LEN
945 acl->resourcesLen = (unsigned) num;
946 acl->resources = (char**) OICCalloc(acl->resourcesLen, sizeof(char*));
949 OIC_LOG(ERROR, TAG, "createAcl: OICCalloc error return");
952 char rsrc_in[ACL_RESRC_MAX_LEN+1] = {0}; // '1' for null termination
953 for(int i=0; acl->resourcesLen>(unsigned)i; ++i)
955 printf(" Enter Accessed Resource[%d] Name: ", i+1);
956 for(int ret=0; 1!=ret; )
958 ret = scanf("%128s", rsrc_in); // '128' is ACL_RESRC_MAX_LEN
959 for( ; 0x20<=getchar(); ); // for removing overflow garbages
960 // '0x20<=code' is character region
962 size_t len = strlen(rsrc_in)+1; // '1' for null termination
963 char* rsrc = (char*) OICCalloc(len, sizeof(char));
966 OIC_LOG(ERROR, TAG, "createAcl: OICCalloc error return");
969 OICStrcpy(rsrc, len, rsrc_in);
970 acl->resources[i] = rsrc; // after here, |rsrc| points nothing
973 // enter |permission| for this access
974 printf(" > [C] Enter Permission for This Access\n");
975 uint16_t pmsn = PERMISSION_FULL_CONTROL; // default full permission
976 uint16_t pmsn_msk = PERMISSION_CREATE; // default permission mask
977 for(int i=0; ACL_PEMISN_CNT>i; ++i)
982 printf(" Enter %s Permission (y/n): ", ACL_PEMISN[i]);
983 for(int ret=0; 1!=ret; )
985 ret = scanf("%c", &ans);
986 for( ; 0x20<=getchar(); ); // for removing overflow garbages
987 // '0x20<=code' is character region
989 if('y'==ans || 'Y'==ans || 'n'==ans|| 'N'==ans)
991 ans &= ~0x20; // for masking lower case, 'y/n'
994 printf(" Entered Wrong Answer. Please Enter 'y/n' Again\n");
996 if('N' == ans) // masked lower case, 'n'
1002 acl->permission = pmsn;
1004 // enter |owner| device number
1008 printf(" > [D] Enter Owner Device Number: ");
1009 for(int ret=0; 1!=ret; )
1011 ret = scanf("%d", &own_num);
1012 for( ; 0x20<=getchar(); ); // for removing overflow garbages
1013 // '0x20<=code' is character region
1015 if(0<own_num && g_own_cnt>=own_num)
1019 printf(" Entered Wrong Number. Please Enter Again\n");
1022 acl->owners = (OicUuid_t*) OICCalloc(1, sizeof(OicUuid_t));
1025 OIC_LOG(ERROR, TAG, "createAcl: OICCalloc error return");
1029 dev = getDevInst((const OCProvisionDev_t*)g_own_list, own_num);
1030 if(!dev || !dev->doxm)
1032 OIC_LOG(ERROR, TAG, "createAcl: device instance empty");
1035 memcpy(acl->owners, &dev->doxm->deviceID, UUID_LENGTH);
1041 OCDeleteACLList(acl); // after here |acl| points nothing
1045 static OicSecPdAcl_t* createPdAcl(const int dev_num)
1047 if(0>=dev_num || g_own_cnt<dev_num)
1049 OIC_LOG(ERROR, TAG, "createAcl invalid parameters");
1050 return NULL; // not need to 'goto' |ERROR| before allocating |acl|
1053 // allocate memory for |pdacl| struct
1054 printf(" **** Create PDACL for the Selected Device[%d]\n", dev_num);
1055 OicSecPdAcl_t* pdAcl = (OicSecPdAcl_t*) OICCalloc(1, sizeof(OicSecPdAcl_t));
1058 OIC_LOG(ERROR, TAG, "createAcl: OICCalloc error return");
1059 return NULL; // not need to 'goto' |ERROR| before allocating |acl|
1063 // number of resources
1064 char rsrc_in[][ACL_RESRC_MAX_LEN+1] = {"*", "/rsrc/*"};
1065 pdAcl->resourcesLen = 1;
1068 int num = pdAcl->resourcesLen;
1069 pdAcl->resources = (char**) OICCalloc(num, sizeof(char*));
1070 if(!pdAcl->resources)
1072 OIC_LOG(ERROR, TAG, "createPdAcl: OICCalloc error return");
1075 for(int i=0; num>i; ++i)
1077 size_t len = strlen(rsrc_in[i])+1; // '1' for null termination
1078 char* rsrc = (char*) OICCalloc(len, sizeof(char));
1081 OIC_LOG(ERROR, TAG, "createPdAcl: OICCalloc error return");
1084 OICStrcpy(rsrc, len, rsrc_in[i]);
1085 pdAcl->resources[i] = rsrc; // after here, |rsrc| points nothing
1089 pdAcl->permission = PERMISSION_FULL_CONTROL;
1094 OCDeletePdAclList(pdAcl);
1098 static OCProvisionDev_t* getDevInst(const OCProvisionDev_t* dev_lst, const int dev_num)
1100 if(!dev_lst || 0>=dev_num)
1102 printf(" Device List is Empty..\n");
1106 OCProvisionDev_t* lst = (OCProvisionDev_t*) dev_lst;
1116 return NULL; // in here |lst| is always |NULL|
1119 static int printDevList(const OCProvisionDev_t* dev_lst)
1123 printf(" Device List is Empty..\n\n");
1127 OCProvisionDev_t* lst = (OCProvisionDev_t*) dev_lst;
1131 printf(" [%d] ", ++lst_cnt);
1132 printUuid((const OicUuid_t*) &lst->doxm->deviceID);
1141 static size_t printUuidList(const OCUuidList_t* uid_lst)
1145 printf(" Device List is Empty..\n\n");
1149 OCUuidList_t* lst = (OCUuidList_t*) uid_lst;
1153 printf(" [%zu] ", ++lst_cnt);
1154 printUuid((const OicUuid_t*) &lst->dev);
1163 static int printResultList(const OCProvisionResult_t* rslt_lst, const int rslt_cnt)
1165 if(!rslt_lst || 0>=rslt_cnt)
1167 printf(" Device List is Empty..\n\n");
1172 for( ; rslt_cnt>lst_cnt; ++lst_cnt)
1174 printf(" [%d] ", lst_cnt+1);
1175 printUuid((const OicUuid_t*) &rslt_lst[lst_cnt].deviceId);
1176 printf(" - result: %d\n", rslt_lst[lst_cnt].res);
1183 static void printUuid(const OicUuid_t* uid)
1185 for(int i=0; i<UUID_LENGTH; )
1187 printf("%02X", (*uid).id[i++]);
1188 if(i==4 || i==6 || i==8 || i==10) // canonical format for UUID has '8-4-4-4-12'
1195 static FILE* fopen_prvnMng(const char* path, const char* mode)
1197 (void)path; // unused |path| parameter
1199 // input |g_svr_db_fname| internally by force, not using |path| parameter
1200 // because |OCPersistentStorage::open| is called |OCPersistentStorage| internally
1201 // with its own |SVR_DB_FILE_NAME|
1202 return fopen(SVR_DB_FILE_NAME, mode);
1205 static int waitCallbackRet(void)
1207 for(int i=0; !g_doneCB && CALLBACK_TIMEOUT>i; ++i)
1210 if(OC_STACK_OK != OCProcess())
1212 OIC_LOG(ERROR, TAG, "OCStack process error");
1220 static int selectTwoDiffNum(int* a, int* b, const int max, const char* str)
1222 if(!a || !b || 2>=max || !str)
1229 for(int i=0; 2>i; ++i)
1231 int* num = 0==i?a:b;
1234 printf(" > Enter Device[%d] Number, %s: ", i+1, str);
1235 for(int ret=0; 1!=ret; )
1237 ret = scanf("%d", num);
1238 for( ; 0x20<=getchar(); ); // for removing overflow garbages
1239 // '0x20<=code' is character region
1241 if(0<*num && max>=*num)
1245 printf(" Entered Wrong Number. Please Enter Again\n");
1258 static void printMenu(void)
1260 printf("************************************************************\n");
1261 printf("****** OIC Provisioning Client with using C-level API ******\n");
1262 printf("************************************************************\n\n");
1264 printf("** [A] DISCOVER DEVICES ON NETWORK\n");
1265 printf("** 10. Discover All Un/Owned Devices on Network\n");
1266 printf("** 11. Discover Only Unowned Devices on Network\n");
1267 printf("** 12. Discover Only Owned Devices on Network\n\n");
1269 printf("** [B] REGISTER/OWN ALL DISCOVERED UNOWNED DEVICES\n");
1270 printf("** 20. Register/Own All Discovered Unowned Devices\n\n");
1272 printf("** [C] PROVISION/LINK PAIRWISE THINGS\n");
1273 printf("** 30. Provision/Link Pairwise Things\n");
1274 printf("** 31. Provision Credentials for Pairwise Things\n");
1275 printf("** 32. Provision the Selected Access Control List(ACL)\n");
1276 printf("** 33. Provision Direct-Pairing Configuration\n");
1277 printf("** 34. Check Linked Status of the Selected Device on PRVN DB\n\n");
1279 printf("** [D] UNLINK PAIRWISE THINGS\n");
1280 printf("** 40. Unlink Pairwise Things\n\n");
1282 printf("** [E] REMOVE THE SELECTED DEVICE\n");
1283 printf("** 50. Remove the Selected Device\n\n");
1285 printf("** [F] EXIT PROVISIONING CLIENT\n");
1286 printf("** 99. Exit Provisionong Client\n\n");
1288 printf("************************************************************\n\n");
1291 #if 0 // Code for enabling path configuration for PDB and SVR DBf
1292 static void printUsage(void)
1295 printf("OIC Provisioning Client with using C-level API\n");
1296 printf("Usage: provisioningclient [option]...\n");
1298 printf(" -h print help for this provisioning client\n");
1299 printf(" -p=[prvn_db_file_path/name] input PRVN DB file path and name\n");
1300 printf(" if not exists, will load default DB file\n");
1301 printf(" (default: |oic_prvn_mng.db| on working dir)\n");
1302 printf(" (ex. -p=oic_prvn_mng.db)\n");
1303 printf(" -s=[svr_db_file_path/name] input SVR DB file path and name\n");
1304 printf(" if not exists, will load default DB file\n");
1305 printf(" (default: |oic_svr_db_client.json| on working dir)\n");
1306 printf(" (ex. -s=oic_svr_db_client.json)\n");
1311 // main function for provisioning client using C-level provisioning API
1314 // initialize provisioning client
1315 if(initProvisionClient())
1317 OIC_LOG(ERROR, TAG, "ProvisionClient init error");
1321 // main loop for provisioning manager
1327 printf(">> Enter Menu Number: ");
1328 for(int ret=0; 1!=ret; )
1330 ret = scanf("%d", &mn_num);
1331 for( ; 0x20<=getchar(); ); // for removing overflow garbages
1332 // '0x20<=code' is character region
1337 case _10_DISCOV_ALL_DEVS_:
1338 if(discoverAllDevices())
1340 OIC_LOG(ERROR, TAG, "_10_DISCOV_ALL_DEVS_: error");
1343 case _11_DISCOV_UNOWN_DEVS_:
1344 if(discoverUnownedDevices())
1346 OIC_LOG(ERROR, TAG, "_11_DISCOV_UNOWN_DEVS_: error");
1349 case _12_DISCOV_OWN_DEVS_:
1350 if(discoverOwnedDevices())
1352 OIC_LOG(ERROR, TAG, "_12_DISCOV_OWN_DEVS_: error");
1355 case _20_REGIST_DEVS_:
1356 if(registerDevices())
1358 OIC_LOG(ERROR, TAG, "_20_REGIST_DEVS_: error");
1361 case _30_PROVIS_PAIR_DEVS_:
1362 if(provisionPairwise())
1364 OIC_LOG(ERROR, TAG, "_30_PROVIS_PAIR_DEVS_: error");
1367 case _31_PROVIS_CRED_:
1370 OIC_LOG(ERROR, TAG, "_31_PROVIS_CRED_: error");
1373 case _32_PROVIS_ACL_:
1376 OIC_LOG(ERROR, TAG, "_32_PROVIS_ACL_: error");
1379 case _33_PROVIS_DP_:
1380 if(provisionDirectPairing())
1382 OIC_LOG(ERROR, TAG, "_33_PROVIS_DP_: error");
1385 case _34_CHECK_LINK_STATUS_:
1386 if(checkLinkedStatus())
1388 OIC_LOG(ERROR, TAG, "_34_CHECK_LINK_STATUS_: error");
1391 case _40_UNLINK_PAIR_DEVS_:
1392 if(unlinkPairwise())
1394 OIC_LOG(ERROR, TAG, "_40_UNLINK_PAIR_DEVS_: error");
1397 case _50_REMOVE_SELEC_DEV_:
1400 OIC_LOG(ERROR, TAG, "_50_REMOVE_SELEC_DEV_: error");
1403 case _99_EXIT_PRVN_CLT_:
1406 printf(">> Entered Wrong Number. Please Enter Again\n\n");
1412 if(OC_STACK_OK != OCStop())
1414 OIC_LOG(ERROR, TAG, "OCStack stop error");
1416 OCDeleteDiscoveredDevices(g_own_list); // after here |g_own_list| points nothing
1417 OCDeleteDiscoveredDevices(g_unown_list); // after here |g_unown_list| points nothing
1421 OICFree(g_svr_fname); // after here |g_svr_fname| points nothing
1425 OICFree(g_prvn_fname); // after here |g_prvn_fname| points nothing
1427 return 0; // always return normal case
1432 #endif //__cplusplus