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 _60_GET_CRED_ 60
54 #define _99_EXIT_PRVN_CLT_ 99
56 #define ACL_RESRC_MAX_NUM 16
57 #define ACL_RESRC_MAX_LEN 128
58 #define ACL_PEMISN_CNT 5
59 #define DISCOVERY_TIMEOUT 10 // 10 sec
60 #define CALLBACK_TIMEOUT 60 // 1 min
61 #define TAG "provisioningclient"
63 static const char* ACL_PEMISN[5] = {"CREATE", "READ", "WRITE", "DELETE", "NOTIFY"};
64 static const char* SVR_DB_FILE_NAME = "oic_svr_db_client.dat";
65 // '_' for separaing from the same constant variable in |srmresourcestrings.c|
66 static const char* PRVN_DB_FILE_NAME = "oic_prvn_mng.db";
67 static const OicSecPrm_t SUPPORTED_PRMS[1] =
72 // |g_ctx| means provision manager application context and
73 // the following, includes |un/own_list|, could be variables, which |g_ctx| has,
74 // for accessing all function(s) for these, they are declared on global domain
75 static const char* g_ctx = "Provision Manager Client Application Context";
76 static char* g_svr_fname;
77 static char* g_prvn_fname;
78 static OCProvisionDev_t* g_own_list;
79 static OCProvisionDev_t* g_unown_list;
81 static int g_unown_cnt;
84 // function declaration(s) for calling them before implementing
85 static OicSecAcl_t* createAcl(const int);
86 static OicSecPdAcl_t* createPdAcl(const int);
87 static OCProvisionDev_t* getDevInst(const OCProvisionDev_t*, const int);
88 static int printDevList(const OCProvisionDev_t*);
89 static size_t printUuidList(const OCUuidList_t*);
90 static int printResultList(const OCProvisionResult_t*, const int);
91 static void printUuid(const OicUuid_t*);
92 static FILE* fopen_prvnMng(const char*, const char*);
93 static int waitCallbackRet(void);
94 static int selectTwoDiffNum(int*, int*, const int, const char*);
96 // callback function(s) for provisioning client using C-level provisioning API
97 static void ownershipTransferCB(void* ctx, int nOfRes, OCProvisionResult_t* arr, bool hasError)
101 OIC_LOG_V(INFO, TAG, "Ownership Transfer SUCCEEDED - ctx: %s", (char*) ctx);
105 OIC_LOG_V(ERROR, TAG, "Ownership Transfer FAILED - ctx: %s", (char*) ctx);
106 printResultList((const OCProvisionResult_t*) arr, nOfRes);
111 static void provisionPairwiseCB(void* ctx, int nOfRes, OCProvisionResult_t* arr, bool hasError)
115 OIC_LOG_V(INFO, TAG, "Provision Pairwise SUCCEEDED - ctx: %s", (char*) ctx);
119 OIC_LOG_V(ERROR, TAG, "Provision Pairwise FAILED - ctx: %s", (char*) ctx);
120 printResultList((const OCProvisionResult_t*) arr, nOfRes);
125 static void provisionCredCB(void* ctx, int nOfRes, OCProvisionResult_t* arr, bool hasError)
129 OIC_LOG_V(INFO, TAG, "Provision Credential SUCCEEDED - ctx: %s", (char*) ctx);
133 OIC_LOG_V(ERROR, TAG, "Provision Credential FAILED - ctx: %s", (char*) ctx);
134 printResultList((const OCProvisionResult_t*) arr, nOfRes);
139 static void provisionAclCB(void* ctx, int nOfRes, OCProvisionResult_t* arr, bool hasError)
143 OIC_LOG_V(INFO, TAG, "Provision ACL SUCCEEDED - ctx: %s", (char*) ctx);
147 OIC_LOG_V(ERROR, TAG, "Provision ACL FAILED - ctx: %s", (char*) ctx);
148 printResultList((const OCProvisionResult_t*) arr, nOfRes);
153 static void getCredCB(void* ctx, int nOfRes, OCProvisionResult_t* arr, bool hasError)
157 OIC_LOG_V(INFO, TAG, "getCredCB SUCCEEDED - ctx: %s", (char*) ctx);
161 OIC_LOG_V(ERROR, TAG, "getCredCB FAILED - ctx: %s", (char*) ctx);
162 printResultList((const OCProvisionResult_t*) arr, nOfRes);
167 static void provisionDPCB(void* ctx, int nOfRes, OCProvisionResult_t* arr, bool hasError)
171 OIC_LOG_V(INFO, TAG, "Provision Direct-Pairing SUCCEEDED - ctx: %s", (char*) ctx);
175 OIC_LOG_V(ERROR, TAG, "Provision Direct-Pairing FAILED - ctx: %s", (char*) ctx);
176 printResultList((const OCProvisionResult_t*) arr, nOfRes);
181 static void unlinkDevicesCB(void* ctx, int nOfRes, OCProvisionResult_t* arr, bool hasError)
185 OIC_LOG_V(INFO, TAG, "Unlink Devices SUCCEEDED - ctx: %s", (char*) ctx);
189 OIC_LOG_V(ERROR, TAG, "Unlink Devices FAILED - ctx: %s", (char*) ctx);
190 printResultList((const OCProvisionResult_t*) arr, nOfRes);
195 static void removeDeviceCB(void* ctx, int nOfRes, OCProvisionResult_t* arr, bool hasError)
199 OIC_LOG_V(INFO, TAG, "Remove Device SUCCEEDED - ctx: %s", (char*) ctx);
203 OIC_LOG_V(ERROR, TAG, "Remove Device FAILED - ctx: %s", (char*) ctx);
204 printResultList((const OCProvisionResult_t*) arr, nOfRes);
209 static void inputPinCB(char* pin, size_t len)
211 if(!pin || OXM_RANDOM_PIN_SIZE>=len)
213 OIC_LOG(ERROR, TAG, "inputPinCB invalid parameters");
217 printf(" > INPUT PIN: ");
218 for(int ret=0; 1!=ret; )
220 ret = scanf("%8s", pin);
221 for( ; 0x20<=getchar(); ); // for removing overflow garbages
222 // '0x20<=code' is character region
226 // function(s) for provisioning client using C-level provisioning API
227 static int initProvisionClient(void)
229 // initialize persistent storage for SVR DB
230 static OCPersistentStorage pstStr =
232 .open = fopen_prvnMng,
238 if(OC_STACK_OK != OCRegisterPersistentStorageHandler(&pstStr))
240 OIC_LOG(ERROR, TAG, "OCRegisterPersistentStorageHandler error");
244 // initialize OC stack and provisioning manager
245 if(OC_STACK_OK != OCInit(NULL, 0, OC_CLIENT_SERVER))
247 OIC_LOG(ERROR, TAG, "OCStack init error");
251 if (access(PRVN_DB_FILE_NAME, F_OK) != -1)
253 printf("************************************************************\n");
254 printf("************Provisioning DB file already exists.************\n");
255 printf("************************************************************\n");
259 printf("*************************************************************\n");
260 printf("************No provisioning DB file, creating new************\n");
261 printf("*************************************************************\n");
264 if(OC_STACK_OK != OCInitPM(PRVN_DB_FILE_NAME))
266 OIC_LOG(ERROR, TAG, "OC_PM init error");
270 // register callback function(s) to each OxM
271 OTMCallbackData_t otmcb =
273 .loadSecretCB = LoadSecretJustWorksCallback,
274 .createSecureSessionCB = CreateSecureSessionJustWorksCallback,
275 .createSelectOxmPayloadCB = CreateJustWorksSelectOxmPayload,
276 .createOwnerTransferPayloadCB = CreateJustWorksOwnerTransferPayload
278 if(OC_STACK_OK != OCSetOwnerTransferCallbackData(OIC_JUST_WORKS, &otmcb))
280 OIC_LOG(ERROR, TAG, "OCSetOwnerTransferCallbackData error: OIC_JUST_WORKS");
283 otmcb.loadSecretCB = InputPinCodeCallback;
284 otmcb.createSecureSessionCB = CreateSecureSessionRandomPinCallback;
285 otmcb.createSelectOxmPayloadCB = CreatePinBasedSelectOxmPayload;
286 otmcb.createOwnerTransferPayloadCB = CreatePinBasedOwnerTransferPayload;
287 if(OC_STACK_OK != OCSetOwnerTransferCallbackData(OIC_RANDOM_DEVICE_PIN, &otmcb))
289 OIC_LOG(ERROR, TAG, "OCSetOwnerTransferCallbackData error: OIC_RANDOM_DEVICE_PIN");
292 SetInputPinCB(inputPinCB);
297 static int discoverAllDevices(void)
299 // delete un/owned device lists before updating them
302 OCDeleteDiscoveredDevices(g_own_list);
307 OCDeleteDiscoveredDevices(g_unown_list);
311 // call |OCGetDevInfoFromNetwork| API actually
312 printf(" Discovering All Un/Owned Devices on Network..\n");
313 if(OC_STACK_OK != OCGetDevInfoFromNetwork(DISCOVERY_TIMEOUT, &g_own_list, &g_unown_list))
315 OIC_LOG(ERROR, TAG, "OCGetDevInfoFromNetwork API error");
319 // display the discovered un/owned lists
320 printf(" > Discovered Owned Devices\n");
321 g_own_cnt = printDevList(g_own_list);
322 printf(" > Discovered Unowned Devices\n");
323 g_unown_cnt = printDevList(g_unown_list);
329 static int discoverUnownedDevices(void)
331 // delete unowned device list before updating it
334 OCDeleteDiscoveredDevices(g_unown_list);
338 // call |OCDiscoverUnownedDevices| API actually
339 printf(" Discovering Only Unowned Devices on Network..\n");
340 if(OC_STACK_OK != OCDiscoverUnownedDevices(DISCOVERY_TIMEOUT, &g_unown_list))
342 OIC_LOG(ERROR, TAG, "OCDiscoverUnownedDevices API error");
346 // display the discovered unowned list
347 printf(" > Discovered Unowned Devices\n");
348 g_unown_cnt = printDevList(g_unown_list);
353 static int discoverOwnedDevices(void)
355 // delete owned device list before updating it
358 OCDeleteDiscoveredDevices(g_own_list);
362 // call |OCDiscoverOwnedDevices| API actually
363 printf(" Discovering Only Owned Devices on Network..\n");
364 if(OC_STACK_OK != OCDiscoverOwnedDevices(DISCOVERY_TIMEOUT, &g_own_list))
366 OIC_LOG(ERROR, TAG, "OCDiscoverOwnedDevices API error");
370 // display the discovered owned list
371 printf(" > Discovered Owned Devices\n");
372 g_own_cnt = printDevList(g_own_list);
377 static int registerDevices(void)
379 // check |unown_list| for registering devices
380 if(!g_unown_list || 0>=g_unown_cnt)
382 printf(" > Unowned Device List, to Register Devices, is Empty\n");
383 printf(" > Please Discover Unowned Devices first, with [10|11] Menu\n");
384 return 0; // normal case
387 // call |OCDoOwnershipTransfer| API actually
388 // calling this API with callback actually acts like blocking
389 // for error checking, the return value saved and printed
391 printf(" Registering All Discovered Unowned Devices..\n");
392 OCStackResult rst = OCDoOwnershipTransfer((void*) g_ctx, g_unown_list, ownershipTransferCB);
393 if(OC_STACK_OK != rst)
395 OIC_LOG_V(ERROR, TAG, "OCDoOwnershipTransfer API error: %d", rst);
398 if(waitCallbackRet()) // input |g_doneCB| flag implicitly
400 OIC_LOG(ERROR, TAG, "OCProvisionCredentials callback error");
404 // display the registered result
405 printf(" > Registered Discovered Unowned Devices\n");
406 printf(" > Please Discover Owned Devices for the Registered Result, with [10|12] Menu\n");
411 static int provisionPairwise(void)
413 // check |own_list| for provisioning pairwise devices
414 if(!g_own_list || 2>g_own_cnt)
416 printf(" > Owned Device List, to Provision the Pairwise, is Empty\n");
417 printf(" > Please Register Unowned Devices first, with [20] Menu\n");
418 return 0; // normal case
421 // select two devices for provisioning pairwise devices
422 int dev_num[2] = {0};
423 if(selectTwoDiffNum(&(dev_num[0]), &(dev_num[1]), g_own_cnt, "for Linking Devices"))
425 OIC_LOG(ERROR, TAG, "selectTwoDiffNum error return");
426 return -1; // not need to 'goto' |ERROR| before allocating |acl|
429 // create ACL(s) for each selected device
430 OicSecAcl_t* acl[2] = {0};
431 for(int i=0; 2>i; ++i)
433 acl[i] = createAcl(dev_num[i]);
436 OIC_LOG(ERROR, TAG, "createAcl error return");
441 // call |OCProvisionPairwiseDevices| API actually
442 // calling this API with callback actually acts like blocking
443 // for error checking, the return value saved and printed
445 printf(" Provisioning Selected Pairwise Devices..\n");
447 OCProvisionPairwiseDevices((void*) g_ctx,
448 SYMMETRIC_PAIR_WISE_KEY, OWNER_PSK_LENGTH_128,
449 getDevInst((const OCProvisionDev_t*) g_own_list, dev_num[0]), acl[0],
450 getDevInst((const OCProvisionDev_t*) g_own_list, dev_num[1]), acl[1],
451 provisionPairwiseCB);
452 if(OC_STACK_OK != rst)
454 OIC_LOG_V(ERROR, TAG, "OCProvisionPairwiseDevices API error: %d", rst);
457 if(waitCallbackRet()) // input |g_doneCB| flag implicitly
459 OIC_LOG(ERROR, TAG, "OCProvisionCredentials callback error");
462 OCDeleteACLList(acl[0]);
463 OCDeleteACLList(acl[1]);
465 // display the pairwise-provisioned result
466 printf(" > Provisioned Selected Pairwise Devices\n");
467 printf(" > Please Check Device's Status for the Linked Result, with [33] Menu\n");
472 OCDeleteACLList(acl[0]);
473 OCDeleteACLList(acl[1]);
477 static int provisionCred(void)
479 // check |own_list| for provisioning pairwise credentials
480 if(!g_own_list || 2>g_own_cnt)
482 printf(" > Owned Device List, to Provision Credentials, is Empty\n");
483 printf(" > Please Register Unowned Devices first, with [20] Menu\n");
484 return 0; // normal case
487 // select two devices for provisioning pairwise credentials
488 int dev_num[2] = {0};
489 if(selectTwoDiffNum(&(dev_num[0]), &(dev_num[1]), g_own_cnt, "for Linking CRED(s)"))
491 OIC_LOG(ERROR, TAG, "selectTwoDiffNum error return");
495 printf(" Select PSK length..\n");
496 printf(" 1 - 128bit(Default)\n");
497 printf(" 2 - 256bit\n");
500 for(int ret=0; 1!=ret; )
502 ret = scanf("%d",&sizeOption);
503 for( ; 0x20<=getchar(); ); // for removing overflow garbages
504 // '0x20<=code' is character region
512 size = OWNER_PSK_LENGTH_128;
517 size = OWNER_PSK_LENGTH_256;
522 size = OWNER_PSK_LENGTH_128;
528 // call |OCProvisionCredentials| API actually
529 // calling this API with callback actually acts like blocking
530 // for error checking, the return value saved and printed
532 printf(" Provisioning Selected Pairwise Credentials..\n");
534 OCProvisionCredentials((void*) g_ctx,
535 SYMMETRIC_PAIR_WISE_KEY, size,
536 getDevInst((const OCProvisionDev_t*) g_own_list, dev_num[0]),
537 getDevInst((const OCProvisionDev_t*) g_own_list, dev_num[1]),
539 if(OC_STACK_OK != rst)
541 OIC_LOG_V(ERROR, TAG, "OCProvisionCredentials API error: %d", rst);
544 if(waitCallbackRet()) // input |g_doneCB| flag implicitly
546 OIC_LOG(ERROR, TAG, "OCProvisionCredentials callback error");
550 // display the CRED-provisioned result
551 printf(" > Provisioned Selected Pairwise Crendentials\n");
552 printf(" > Please Check Device's Status for the Linked Result, with [33] Menu\n");
557 static int provisionAcl(void)
559 // check |own_list| for provisioning access control list
560 if(!g_own_list || 1>g_own_cnt)
562 printf(" > Owned Device List, to Provision ACL, is Empty\n");
563 printf(" > Please Register Unowned Devices first, with [20] Menu\n");
564 return 0; // normal case
567 // select device for provisioning access control list
571 printf(" > Enter Device Number, for Provisioning ACL: ");
572 for(int ret=0; 1!=ret; )
574 ret = scanf("%d", &dev_num);
575 for( ; 0x20<=getchar(); ); // for removing overflow garbages
576 // '0x20<=code' is character region
578 if(0<dev_num && g_own_cnt>=dev_num)
582 printf(" Entered Wrong Number. Please Enter Again\n");
585 // create ACL for selected device
586 OicSecAcl_t* acl = NULL;
587 acl = createAcl(dev_num);
590 OIC_LOG(ERROR, TAG, "createAcl error return");
594 // call |OCProvisionACL| API actually
595 // calling this API with callback actually acts like blocking
596 // for error checking, the return value saved and printed
598 printf(" Provisioning Selected ACL..\n");
599 OCProvisionDev_t* dev = getDevInst((const OCProvisionDev_t*) g_own_list, dev_num);
602 OIC_LOG(ERROR, TAG, "provisionAcl: device instance empty");
605 OCStackResult rst = OCProvisionACL((void*) g_ctx, dev, acl, provisionAclCB);
606 if(OC_STACK_OK != rst)
608 OIC_LOG_V(ERROR, TAG, "OCProvisionACL API error: %d", rst);
611 if(waitCallbackRet()) // input |g_doneCB| flag implicitly
613 OIC_LOG(ERROR, TAG, "OCProvisionCredentials callback error");
616 OCDeleteACLList(acl); // after here |acl| points nothing
618 // display the ACL-provisioned result
619 printf(" > Provisioned Selected ACL\n");
624 OCDeleteACLList(acl); // after here |acl| points nothing
628 static int provisionDirectPairing(void)
630 // check |own_list| for provisioning direct-pairing
631 if(!g_own_list || 1>g_own_cnt)
633 printf(" > Owned Device List, to Provision ACL, is Empty\n");
634 printf(" > Please Register Unowned Devices first, with [20] Menu\n");
635 return 0; // normal case
638 // select device for provisioning direct-pairing
642 printf(" > Enter Device Number, for Provisioning Direct-Pairing: ");
643 for(int ret=0; 1!=ret; )
645 ret = scanf("%d", &dev_num);
646 for( ; 0x20<=getchar(); ); // for removing overflow garbages
647 // '0x20<=code' is character region
649 if(0<dev_num && g_own_cnt>=dev_num)
653 printf(" Entered Wrong Number. Please Enter Again\n");
656 // create Direct-Pairing Configuration(PIN, PDACL) for selected device
657 // TODO: default acl -> input from user !
659 memset(&pconf, 0, sizeof(OicSecPconf_t));
664 // set default supported PRM types
665 pconf.prmLen = sizeof(SUPPORTED_PRMS)/sizeof(OicSecPrm_t);
666 pconf.prm = (OicSecPrm_t *)OICCalloc(pconf.prmLen, sizeof(OicSecPrm_t));
669 for (size_t i=0; i<pconf.prmLen; i++)
671 pconf.prm[i] = SUPPORTED_PRMS[i];
676 OIC_LOG(ERROR, TAG, "create prm error return");
681 const char DP_DEFAULT_PIN[] = "00000000";
682 memcpy(pconf.pin.val, DP_DEFAULT_PIN, DP_PIN_LENGTH);
685 pconf.pdacls = createPdAcl(dev_num);
688 OIC_LOG(ERROR, TAG, "createPdAcl error return");
692 // call |OCProvisionDirectPairing| API actually
693 // calling this API with callback actually acts like blocking
694 // for error checking, the return value saved and printed
696 printf(" Atempt Direct-Pairing Provisioning (PIN : [%s])..\n", (char*)pconf.pin.val);
697 OCStackResult rst = OCProvisionDirectPairing((void*) g_ctx,
698 getDevInst((const OCProvisionDev_t*) g_own_list, dev_num),
699 &pconf, provisionDPCB);
700 if(OC_STACK_OK != rst)
702 OIC_LOG_V(ERROR, TAG, "OCProvisionDirectPairing API error: %d", rst);
703 if (OC_STACK_UNAUTHORIZED_REQ == rst)
705 OIC_LOG(ERROR, TAG, "Target Server NOT Support Direct-Pairing !!! (DPC == false)");
709 if(waitCallbackRet()) // input |g_doneCB| flag implicitly
711 OIC_LOG(ERROR, TAG, "OCProvisionCredentials callback error");
714 OCDeletePdAclList(pconf.pdacls);
716 // display the PCONF-provisioned result
717 printf(" > SUCCESS to provision Direct-Pairing !!\n");
722 OCDeletePdAclList(pconf.pdacls); // after here |acl| points nothing
726 static int checkLinkedStatus(void)
728 // check |own_list| for checking selected link status on PRVN DB
729 if(!g_own_list || 1>g_own_cnt)
731 printf(" > Owned Device List, to Check Linked Status on PRVN DB, is Empty\n");
732 printf(" > Please Register Unowned Devices first, with [20] Menu\n");
733 return 0; // normal case
736 // select device for checking selected link status on PRVN DB
740 printf(" > Enter Device Number, for Checking Linked Status on PRVN DB: ");
741 for(int ret=0; 1!=ret; )
743 ret = scanf("%d", &dev_num);
744 for( ; 0x20<=getchar(); ); // for removing overflow garbages
745 // '0x20<=code' is character region
747 if(0<dev_num && g_own_cnt>=dev_num)
751 printf(" Entered Wrong Number. Please Enter Again\n");
754 // call |OCGetLinkedStatus| API actually
755 printf(" Checking Selected Link Status on PRVN DB..\n");
756 OCUuidList_t* dvid_lst = NULL;
758 OCProvisionDev_t* dev = getDevInst((const OCProvisionDev_t*)g_own_list, dev_num);
759 if(!dev || !dev->doxm)
761 OIC_LOG(ERROR, TAG, "checkLinkedStatus: device instance empty");
767 &dev->doxm->deviceID,
768 &dvid_lst, &dvid_cnt)) // allow empty list
770 OIC_LOG(ERROR, TAG, "OCGetLinkedStatus API error");
774 // display the linked status result
775 printf(" > Checked Selected Link Status on PRVN DB\n");
776 if(!dvid_lst || !dvid_cnt) // |size_t| is unsigned
778 printf(" Linked Device List is Empty..\n");
779 return 0; // normal case
781 if(dvid_cnt != printUuidList((const OCUuidList_t*) dvid_lst))
783 OIC_LOG(ERROR, TAG, "printUuidList error return");
786 OCDeleteUuidList(dvid_lst);
791 OCDeleteUuidList(dvid_lst);
795 static int getCred(void)
797 // check |own_list| for checking selected link status on PRVN DB
798 if(!g_own_list || 1>g_own_cnt)
800 printf(" > Owned Device List, to Check Linked Status on PRVN DB, is Empty\n");
801 printf(" > Please Register Unowned Devices first, with [20] Menu\n");
802 return 0; // normal case
805 // select device for checking selected link status on PRVN DB
809 printf(" > Enter Device Number, for Checking Linked Status on PRVN DB: ");
810 for(int ret=0; 1!=ret; )
812 ret = scanf("%d", &dev_num);
813 for( ; 0x20<=getchar(); ); // for removing overflow garbages
814 // '0x20<=code' is character region
816 if(0<dev_num && g_own_cnt>=dev_num)
820 printf(" Entered Wrong Number. Please Enter Again\n");
823 // call |getDevInst| API actually
824 // calling this API with callback actually acts like blocking
825 // for error checking, the return value saved and printed
827 OCProvisionDev_t* dev = getDevInst((const OCProvisionDev_t*) g_own_list, dev_num);
830 OIC_LOG(ERROR, TAG, "getDevInst: device instance empty");
833 OCStackResult rst = OCGetCredResource((void*) g_ctx, dev, getCredCB);
834 if(OC_STACK_OK != rst)
836 OIC_LOG_V(ERROR, TAG, "OCGetCred API error: %d", rst);
839 if(waitCallbackRet()) // input |g_doneCB| flag implicitly
841 OIC_LOG(ERROR, TAG, "OCGetCredResource callback error");
845 // display the result of get credential
846 printf(" > Get Cred SUCCEEDED\n");
854 static int unlinkPairwise(void)
856 // check |own_list| for unlinking pairwise devices
857 if(!g_own_list || 2>g_own_cnt)
859 printf(" > Owned Device List, to Unlink the Pairwise, is Empty\n");
860 printf(" > Please Register Unowned Devices first, with [20] Menu\n");
861 return 0; // normal case
864 // select two devices for unlinking pairwise devices
865 int dev_num[2] = {0};
866 if(selectTwoDiffNum(&(dev_num[0]), &(dev_num[1]), g_own_cnt, "for Unlinking Devices"))
868 OIC_LOG(ERROR, TAG, "selectTwoDiffNum error return");
872 // call |OCUnlinkDevices| API actually
873 // calling this API with callback actually acts like blocking
874 // for error checking, the return value saved and printed
876 printf(" Unlinking Selected Pairwise Devices..\n");
878 OCUnlinkDevices((void*) g_ctx,
879 getDevInst((const OCProvisionDev_t*) g_own_list, dev_num[0]),
880 getDevInst((const OCProvisionDev_t*) g_own_list, dev_num[1]),
882 if(OC_STACK_OK != rst)
884 OIC_LOG_V(ERROR, TAG, "OCUnlinkDevices API error: %d", rst);
887 if(waitCallbackRet()) // input |g_doneCB| flag implicitly
889 OIC_LOG(ERROR, TAG, "OCProvisionCredentials callback error");
893 // display the pairwise-unlinked result
894 printf(" > Unlinked Selected Pairwise Devices\n");
895 printf(" > Please Check Device's Status for the Unlinked Result, with [33] Menu\n");
900 static int removeDevice(void)
902 // check |own_list| for removing device
903 if(!g_own_list || 1>g_own_cnt)
905 printf(" > Owned Device List, to Remove Device, is Empty\n");
906 printf(" > Please Register Unowned Devices first, with [20] Menu\n");
907 return 0; // normal case
910 // select device for removing it
914 printf(" > Enter Device Number, for Removing Device: ");
915 for(int ret=0; 1!=ret; )
917 ret = scanf("%d", &dev_num);
918 for( ; 0x20<=getchar(); ); // for removing overflow garbages
919 // '0x20<=code' is character region
921 if(0<dev_num && g_own_cnt>=dev_num)
925 printf(" Entered Wrong Number. Please Enter Again\n");
928 // call |OCRemoveDevice| API actually
929 // calling this API with callback actually acts like blocking
930 // for error checking, the return value saved and printed
932 printf(" Removing Selected Owned Device..\n");
934 OCRemoveDevice((void*) g_ctx, DISCOVERY_TIMEOUT,
935 getDevInst((const OCProvisionDev_t*) g_own_list, dev_num), removeDeviceCB);
936 if(OC_STACK_OK != rst)
938 OIC_LOG_V(ERROR, TAG, "OCRemoveDevice API error: %d", rst);
941 if(waitCallbackRet()) // input |g_doneCB| flag implicitly
943 OIC_LOG(ERROR, TAG, "OCProvisionCredentials callback error");
947 // display the removed result
948 printf(" > Removed Selected Owned Device\n");
949 printf(" > Please Discover Owned Devices for the Registered Result, with [10|12] Menu\n");
954 static OicSecAcl_t* createAcl(const int dev_num)
956 if(0>=dev_num || g_own_cnt<dev_num)
958 OIC_LOG(ERROR, TAG, "createAcl invalid parameters");
959 return NULL; // not need to 'goto' |ERROR| before allocating |acl|
962 // allocate memory for |acl| struct
963 printf(" **** Create ACL for the Selected Device[%d]\n", dev_num);
964 OicSecAcl_t* acl = (OicSecAcl_t*) OICCalloc(1, sizeof(OicSecAcl_t));
967 OIC_LOG(ERROR, TAG, "createAcl: OICCalloc error return");
968 return NULL; // not need to 'goto' |ERROR| before allocating |acl|
971 // enter |subject| device number
975 printf(" > [A] Enter Subject Device Number: ");
976 for(int ret=0; 1!=ret; )
978 ret = scanf("%d", &num);
979 for( ; 0x20<=getchar(); ); // for removing overflow garbages
980 // '0x20<=code' is character region
982 if(0<num && g_own_cnt>=num && dev_num!=num)
986 printf(" Entered Wrong Number. Please Enter Again\n");
989 OCProvisionDev_t* dev = getDevInst((const OCProvisionDev_t*)g_own_list, num);
990 if(!dev || !dev->doxm)
992 OIC_LOG(ERROR, TAG, "createAcl: device instance empty");
995 memcpy(&acl->subject, &dev->doxm->deviceID, UUID_LENGTH);
997 // enter number of |resources| in 'accessed' device
1000 printf(" > [B] Enter Number of Accessed Resources (under 16): ");
1001 // '16' is |ACL_RESRC_MAX_NUM|
1002 for(int ret=0; 1!=ret; )
1004 ret = scanf("%d", &num);
1005 for( ; 0x20<=getchar(); ); // for removing overflow garbages
1006 // '0x20<=code' is character region
1008 if(0<num && ACL_RESRC_MAX_NUM>=num)
1012 printf(" Entered Wrong Number. Please Enter under 16 Again\n");
1013 // '16' is |ACL_RESRC_MAX_NUM|
1016 // enter actually each 'accessed' |resources| name
1017 printf(" Enter Each Accessed Resource Name (each under 128 char)\n");
1018 // '128' is ACL_RESRC_MAX_LEN
1019 acl->resourcesLen = (unsigned) num;
1020 acl->resources = (char**) OICCalloc(acl->resourcesLen, sizeof(char*));
1023 OIC_LOG(ERROR, TAG, "createAcl: OICCalloc error return");
1026 char rsrc_in[ACL_RESRC_MAX_LEN+1] = {0}; // '1' for null termination
1027 for(int i=0; acl->resourcesLen>(unsigned)i; ++i)
1029 printf(" Enter Accessed Resource[%d] Name: ", i+1);
1030 for(int ret=0; 1!=ret; )
1032 ret = scanf("%128s", rsrc_in); // '128' is ACL_RESRC_MAX_LEN
1033 for( ; 0x20<=getchar(); ); // for removing overflow garbages
1034 // '0x20<=code' is character region
1036 size_t len = strlen(rsrc_in)+1; // '1' for null termination
1037 char* rsrc = (char*) OICCalloc(len, sizeof(char));
1040 OIC_LOG(ERROR, TAG, "createAcl: OICCalloc error return");
1043 OICStrcpy(rsrc, len, rsrc_in);
1044 acl->resources[i] = rsrc; // after here, |rsrc| points nothing
1047 // enter |permission| for this access
1048 printf(" > [C] Enter Permission for This Access\n");
1049 uint16_t pmsn = PERMISSION_FULL_CONTROL; // default full permission
1050 uint16_t pmsn_msk = PERMISSION_CREATE; // default permission mask
1051 for(int i=0; ACL_PEMISN_CNT>i; ++i)
1056 printf(" Enter %s Permission (y/n): ", ACL_PEMISN[i]);
1057 for(int ret=0; 1!=ret; )
1059 ret = scanf("%c", &ans);
1060 for( ; 0x20<=getchar(); ); // for removing overflow garbages
1061 // '0x20<=code' is character region
1063 if('y'==ans || 'Y'==ans || 'n'==ans|| 'N'==ans)
1065 ans &= ~0x20; // for masking lower case, 'y/n'
1068 printf(" Entered Wrong Answer. Please Enter 'y/n' Again\n");
1070 if('N' == ans) // masked lower case, 'n'
1076 acl->permission = pmsn;
1078 // enter |owner| device number
1082 printf(" > [D] Enter Owner Device Number: ");
1083 for(int ret=0; 1!=ret; )
1085 ret = scanf("%d", &own_num);
1086 for( ; 0x20<=getchar(); ); // for removing overflow garbages
1087 // '0x20<=code' is character region
1089 if(0<own_num && g_own_cnt>=own_num)
1093 printf(" Entered Wrong Number. Please Enter Again\n");
1096 dev = getDevInst((const OCProvisionDev_t*)g_own_list, own_num);
1097 if(!dev || !dev->doxm)
1099 OIC_LOG(ERROR, TAG, "createAcl: device instance empty");
1102 memcpy(&acl->rownerID, &dev->doxm->deviceID, sizeof(OicUuid_t));
1108 OCDeleteACLList(acl); // after here |acl| points nothing
1112 static OicSecPdAcl_t* createPdAcl(const int dev_num)
1114 if(0>=dev_num || g_own_cnt<dev_num)
1116 OIC_LOG(ERROR, TAG, "createAcl invalid parameters");
1117 return NULL; // not need to 'goto' |ERROR| before allocating |acl|
1120 // allocate memory for |pdacl| struct
1121 printf(" **** Create PDACL for the Selected Device[%d]\n", dev_num);
1122 OicSecPdAcl_t* pdAcl = (OicSecPdAcl_t*) OICCalloc(1, sizeof(OicSecPdAcl_t));
1125 OIC_LOG(ERROR, TAG, "createAcl: OICCalloc error return");
1126 return NULL; // not need to 'goto' |ERROR| before allocating |acl|
1130 // number of resources
1131 char rsrc_in[][ACL_RESRC_MAX_LEN+1] = {"*", "/rsrc/*"};
1132 pdAcl->resourcesLen = 1;
1135 int num = pdAcl->resourcesLen;
1136 pdAcl->resources = (char**) OICCalloc(num, sizeof(char*));
1137 if(!pdAcl->resources)
1139 OIC_LOG(ERROR, TAG, "createPdAcl: OICCalloc error return");
1142 for(int i=0; num>i; ++i)
1144 size_t len = strlen(rsrc_in[i])+1; // '1' for null termination
1145 char* rsrc = (char*) OICCalloc(len, sizeof(char));
1148 OIC_LOG(ERROR, TAG, "createPdAcl: OICCalloc error return");
1151 OICStrcpy(rsrc, len, rsrc_in[i]);
1152 pdAcl->resources[i] = rsrc; // after here, |rsrc| points nothing
1156 pdAcl->permission = PERMISSION_FULL_CONTROL;
1161 OCDeletePdAclList(pdAcl);
1165 static OCProvisionDev_t* getDevInst(const OCProvisionDev_t* dev_lst, const int dev_num)
1167 if(!dev_lst || 0>=dev_num)
1169 printf(" Device List is Empty..\n");
1173 OCProvisionDev_t* lst = (OCProvisionDev_t*) dev_lst;
1183 return NULL; // in here |lst| is always |NULL|
1186 static int printDevList(const OCProvisionDev_t* dev_lst)
1190 printf(" Device List is Empty..\n\n");
1194 OCProvisionDev_t* lst = (OCProvisionDev_t*) dev_lst;
1198 printf(" [%d] ", ++lst_cnt);
1199 printUuid((const OicUuid_t*) &lst->doxm->deviceID);
1208 static size_t printUuidList(const OCUuidList_t* uid_lst)
1212 printf(" Device List is Empty..\n\n");
1216 OCUuidList_t* lst = (OCUuidList_t*) uid_lst;
1220 printf(" [%zu] ", ++lst_cnt);
1221 printUuid((const OicUuid_t*) &lst->dev);
1230 static int printResultList(const OCProvisionResult_t* rslt_lst, const int rslt_cnt)
1232 if(!rslt_lst || 0>=rslt_cnt)
1234 printf(" Device List is Empty..\n\n");
1239 for( ; rslt_cnt>lst_cnt; ++lst_cnt)
1241 printf(" [%d] ", lst_cnt+1);
1242 printUuid((const OicUuid_t*) &rslt_lst[lst_cnt].deviceId);
1243 printf(" - result: %d\n", rslt_lst[lst_cnt].res);
1250 static void printUuid(const OicUuid_t* uid)
1252 for(int i=0; i<UUID_LENGTH; )
1254 printf("%02X", (*uid).id[i++]);
1255 if(i==4 || i==6 || i==8 || i==10) // canonical format for UUID has '8-4-4-4-12'
1262 static FILE* fopen_prvnMng(const char* path, const char* mode)
1264 (void)path; // unused |path| parameter
1266 // input |g_svr_db_fname| internally by force, not using |path| parameter
1267 // because |OCPersistentStorage::open| is called |OCPersistentStorage| internally
1268 // with its own |SVR_DB_FILE_NAME|
1269 return fopen(SVR_DB_FILE_NAME, mode);
1272 static int waitCallbackRet(void)
1274 for(int i=0; !g_doneCB && CALLBACK_TIMEOUT>i; ++i)
1277 if(OC_STACK_OK != OCProcess())
1279 OIC_LOG(ERROR, TAG, "OCStack process error");
1287 static int selectTwoDiffNum(int* a, int* b, const int max, const char* str)
1289 if(!a || !b || 2>=max || !str)
1296 for(int i=0; 2>i; ++i)
1298 int* num = 0==i?a:b;
1301 printf(" > Enter Device[%d] Number, %s: ", i+1, str);
1302 for(int ret=0; 1!=ret; )
1304 ret = scanf("%d", num);
1305 for( ; 0x20<=getchar(); ); // for removing overflow garbages
1306 // '0x20<=code' is character region
1308 if(0<*num && max>=*num)
1312 printf(" Entered Wrong Number. Please Enter Again\n");
1325 static void printMenu(void)
1327 printf("************************************************************\n");
1328 printf("****** OIC Provisioning Client with using C-level API ******\n");
1329 printf("************************************************************\n\n");
1331 printf("** [A] DISCOVER DEVICES ON NETWORK\n");
1332 printf("** 10. Discover All Un/Owned Devices on Network\n");
1333 printf("** 11. Discover Only Unowned Devices on Network\n");
1334 printf("** 12. Discover Only Owned Devices on Network\n\n");
1336 printf("** [B] REGISTER/OWN ALL DISCOVERED UNOWNED DEVICES\n");
1337 printf("** 20. Register/Own All Discovered Unowned Devices\n\n");
1339 printf("** [C] PROVISION/LINK PAIRWISE THINGS\n");
1340 printf("** 30. Provision/Link Pairwise Things\n");
1341 printf("** 31. Provision Credentials for Pairwise Things\n");
1342 printf("** 32. Provision the Selected Access Control List(ACL)\n");
1343 printf("** 33. Provision Direct-Pairing Configuration\n");
1344 printf("** 34. Check Linked Status of the Selected Device on PRVN DB\n\n");
1346 printf("** [D] UNLINK PAIRWISE THINGS\n");
1347 printf("** 40. Unlink Pairwise Things\n\n");
1349 printf("** [E] REMOVE THE SELECTED DEVICE\n");
1350 printf("** 50. Remove the Selected Device\n\n");
1352 printf("** [F] GET SECURITY RESOURCE FOR DEBUGGING ONLY\n");
1353 printf("** 60. Get the Credential resources of the Selected Device\n\n");
1355 printf("** [F] EXIT PROVISIONING CLIENT\n");
1356 printf("** 99. Exit Provisionong Client\n\n");
1358 printf("************************************************************\n\n");
1361 #if 0 // Code for enabling path configuration for PDB and SVR DBf
1362 static void printUsage(void)
1365 printf("OIC Provisioning Client with using C-level API\n");
1366 printf("Usage: provisioningclient [option]...\n");
1368 printf(" -h print help for this provisioning client\n");
1369 printf(" -p=[prvn_db_file_path/name] input PRVN DB file path and name\n");
1370 printf(" if not exists, will load default DB file\n");
1371 printf(" (default: |oic_prvn_mng.db| on working dir)\n");
1372 printf(" (ex. -p=oic_prvn_mng.db)\n");
1373 printf(" -s=[svr_db_file_path/name] input SVR DB file path and name\n");
1374 printf(" if not exists, will load default DB file\n");
1375 printf(" (default: |oic_svr_db_client.json| on working dir)\n");
1376 printf(" (ex. -s=oic_svr_db_client.json)\n");
1381 // main function for provisioning client using C-level provisioning API
1384 // initialize provisioning client
1385 if(initProvisionClient())
1387 OIC_LOG(ERROR, TAG, "ProvisionClient init error");
1391 // main loop for provisioning manager
1397 printf(">> Enter Menu Number: ");
1398 for(int ret=0; 1!=ret; )
1400 ret = scanf("%d", &mn_num);
1401 for( ; 0x20<=getchar(); ); // for removing overflow garbages
1402 // '0x20<=code' is character region
1407 case _10_DISCOV_ALL_DEVS_:
1408 if(discoverAllDevices())
1410 OIC_LOG(ERROR, TAG, "_10_DISCOV_ALL_DEVS_: error");
1413 case _11_DISCOV_UNOWN_DEVS_:
1414 if(discoverUnownedDevices())
1416 OIC_LOG(ERROR, TAG, "_11_DISCOV_UNOWN_DEVS_: error");
1419 case _12_DISCOV_OWN_DEVS_:
1420 if(discoverOwnedDevices())
1422 OIC_LOG(ERROR, TAG, "_12_DISCOV_OWN_DEVS_: error");
1425 case _20_REGIST_DEVS_:
1426 if(registerDevices())
1428 OIC_LOG(ERROR, TAG, "_20_REGIST_DEVS_: error");
1431 case _30_PROVIS_PAIR_DEVS_:
1432 if(provisionPairwise())
1434 OIC_LOG(ERROR, TAG, "_30_PROVIS_PAIR_DEVS_: error");
1437 case _31_PROVIS_CRED_:
1440 OIC_LOG(ERROR, TAG, "_31_PROVIS_CRED_: error");
1443 case _32_PROVIS_ACL_:
1446 OIC_LOG(ERROR, TAG, "_32_PROVIS_ACL_: error");
1449 case _33_PROVIS_DP_:
1450 if(provisionDirectPairing())
1452 OIC_LOG(ERROR, TAG, "_33_PROVIS_DP_: error");
1455 case _34_CHECK_LINK_STATUS_:
1456 if(checkLinkedStatus())
1458 OIC_LOG(ERROR, TAG, "_34_CHECK_LINK_STATUS_: error");
1461 case _40_UNLINK_PAIR_DEVS_:
1462 if(unlinkPairwise())
1464 OIC_LOG(ERROR, TAG, "_40_UNLINK_PAIR_DEVS_: error");
1467 case _50_REMOVE_SELEC_DEV_:
1470 OIC_LOG(ERROR, TAG, "_50_REMOVE_SELEC_DEV_: error");
1476 OIC_LOG(ERROR, TAG, "_60_GET_CRED_: error");
1479 case _99_EXIT_PRVN_CLT_:
1482 printf(">> Entered Wrong Number. Please Enter Again\n\n");
1488 if(OC_STACK_OK != OCStop())
1490 OIC_LOG(ERROR, TAG, "OCStack stop error");
1492 OCDeleteDiscoveredDevices(g_own_list); // after here |g_own_list| points nothing
1493 OCDeleteDiscoveredDevices(g_unown_list); // after here |g_unown_list| points nothing
1497 OICFree(g_svr_fname); // after here |g_svr_fname| points nothing
1501 OICFree(g_prvn_fname); // after here |g_prvn_fname| points nothing
1503 return 0; // always return normal case
1508 #endif //__cplusplus