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 *****************************************************************/
27 #include "platform_features.h"
29 #include "oic_malloc.h"
30 #include "oic_string.h"
31 #include "ocprovisioningmanager.h"
32 #include "oxmjustworks.h"
33 #include "oxmrandompin.h"
34 #include "securevirtualresourcetypes.h"
35 #include "srmutility.h"
43 // declaration(s) for provisioning client using C-level provisioning API
44 // user input definition for main loop on provisioning client
45 #define _10_DISCOV_ALL_DEVS_ 10
46 #define _11_DISCOV_UNOWN_DEVS_ 11
47 #define _12_DISCOV_OWN_DEVS_ 12
48 #define _20_REGIST_DEVS_ 20
49 #define _30_PROVIS_PAIR_DEVS_ 30
50 #define _31_PROVIS_CRED_ 31
51 #define _32_PROVIS_ACL_ 32
52 #define _33_PROVIS_DP_ 33
53 #define _34_CHECK_LINK_STATUS_ 34
54 #define _40_UNLINK_PAIR_DEVS_ 40
55 #define _50_REMOVE_SELEC_DEV_ 50
56 #define _60_GET_CRED_ 60
57 #define _61_GET_ACL_ 61
58 #define _99_EXIT_PRVN_CLT_ 99
60 #define ACL_RESRC_MAX_NUM 16
61 #define ACL_RESRC_MAX_LEN 128
62 #define ACL_PEMISN_CNT 5
63 #define DISCOVERY_TIMEOUT 10 // 10 sec
64 #define CALLBACK_TIMEOUT 60 // 1 min
65 #define TAG "provisioningclient"
67 static const char* ACL_PEMISN[5] = {"CREATE", "READ", "WRITE", "DELETE", "NOTIFY"};
68 static const char* SVR_DB_FILE_NAME = "oic_svr_db_client.dat";
69 // '_' for separaing from the same constant variable in |srmresourcestrings.c|
70 static const char* PRVN_DB_FILE_NAME = "oic_prvn_mng.db";
71 static const OicSecPrm_t SUPPORTED_PRMS[1] =
76 // |g_ctx| means provision manager application context and
77 // the following, includes |un/own_list|, could be variables, which |g_ctx| has,
78 // for accessing all function(s) for these, they are declared on global domain
79 static const char* g_ctx = "Provision Manager Client Application Context";
80 static char* g_svr_fname;
81 static char* g_prvn_fname;
82 static OCProvisionDev_t* g_own_list;
83 static OCProvisionDev_t* g_unown_list;
85 static int g_unown_cnt;
88 // function declaration(s) for calling them before implementing
89 static OicSecAcl_t* createAcl(const int);
90 static OicSecPdAcl_t* createPdAcl(const int);
91 static OCProvisionDev_t* getDevInst(const OCProvisionDev_t*, const int);
92 static int printDevList(const OCProvisionDev_t*);
93 static size_t printUuidList(const OCUuidList_t*);
94 static int printResultList(const OCProvisionResult_t*, const int);
95 static void printUuid(const OicUuid_t*);
96 static FILE* fopen_prvnMng(const char*, const char*);
97 static int waitCallbackRet(void);
98 static int selectTwoDiffNum(int*, int*, const int, const char*);
100 // callback function(s) for provisioning client using C-level provisioning API
101 static void ownershipTransferCB(void* ctx, int nOfRes, OCProvisionResult_t* arr, bool hasError)
105 OIC_LOG_V(INFO, TAG, "Ownership Transfer SUCCEEDED - ctx: %s", (char*) ctx);
109 OIC_LOG_V(ERROR, TAG, "Ownership Transfer FAILED - ctx: %s", (char*) ctx);
110 printResultList((const OCProvisionResult_t*) arr, nOfRes);
115 static void provisionPairwiseCB(void* ctx, int nOfRes, OCProvisionResult_t* arr, bool hasError)
119 OIC_LOG_V(INFO, TAG, "Provision Pairwise SUCCEEDED - ctx: %s", (char*) ctx);
123 OIC_LOG_V(ERROR, TAG, "Provision Pairwise FAILED - ctx: %s", (char*) ctx);
124 printResultList((const OCProvisionResult_t*) arr, nOfRes);
129 static void provisionCredCB(void* ctx, int nOfRes, OCProvisionResult_t* arr, bool hasError)
133 OIC_LOG_V(INFO, TAG, "Provision Credential SUCCEEDED - ctx: %s", (char*) ctx);
137 OIC_LOG_V(ERROR, TAG, "Provision Credential FAILED - ctx: %s", (char*) ctx);
138 printResultList((const OCProvisionResult_t*) arr, nOfRes);
143 static void provisionAclCB(void* ctx, int nOfRes, OCProvisionResult_t* arr, bool hasError)
147 OIC_LOG_V(INFO, TAG, "Provision ACL SUCCEEDED - ctx: %s", (char*) ctx);
151 OIC_LOG_V(ERROR, TAG, "Provision ACL FAILED - ctx: %s", (char*) ctx);
152 printResultList((const OCProvisionResult_t*) arr, nOfRes);
157 static void getCredCB(void* ctx, int nOfRes, OCProvisionResult_t* arr, bool hasError)
161 OIC_LOG_V(INFO, TAG, "getCredCB SUCCEEDED - ctx: %s", (char*) ctx);
165 OIC_LOG_V(ERROR, TAG, "getCredCB FAILED - ctx: %s", (char*) ctx);
166 printResultList((const OCProvisionResult_t*) arr, nOfRes);
171 static void getAclCB(void* ctx, int nOfRes, OCProvisionResult_t* arr, bool hasError)
175 OIC_LOG_V(INFO, TAG, "getAclCB SUCCEEDED - ctx: %s", (char*) ctx);
179 OIC_LOG_V(ERROR, TAG, "getAclCB FAILED - ctx: %s", (char*) ctx);
180 printResultList((const OCProvisionResult_t*) arr, nOfRes);
185 static void provisionDPCB(void* ctx, int nOfRes, OCProvisionResult_t* arr, bool hasError)
189 OIC_LOG_V(INFO, TAG, "Provision Direct-Pairing SUCCEEDED - ctx: %s", (char*) ctx);
193 OIC_LOG_V(ERROR, TAG, "Provision Direct-Pairing FAILED - ctx: %s", (char*) ctx);
194 printResultList((const OCProvisionResult_t*) arr, nOfRes);
199 static void unlinkDevicesCB(void* ctx, int nOfRes, OCProvisionResult_t* arr, bool hasError)
203 OIC_LOG_V(INFO, TAG, "Unlink Devices SUCCEEDED - ctx: %s", (char*) ctx);
207 OIC_LOG_V(ERROR, TAG, "Unlink Devices FAILED - ctx: %s", (char*) ctx);
208 printResultList((const OCProvisionResult_t*) arr, nOfRes);
213 static void removeDeviceCB(void* ctx, int nOfRes, OCProvisionResult_t* arr, bool hasError)
217 OIC_LOG_V(INFO, TAG, "Remove Device SUCCEEDED - ctx: %s", (char*) ctx);
221 OIC_LOG_V(ERROR, TAG, "Remove Device FAILED - ctx: %s", (char*) ctx);
222 printResultList((const OCProvisionResult_t*) arr, nOfRes);
227 static void inputPinCB(char* pin, size_t len)
229 if(!pin || OXM_RANDOM_PIN_SIZE>=len)
231 OIC_LOG(ERROR, TAG, "inputPinCB invalid parameters");
235 printf(" > INPUT PIN: ");
236 for(int ret=0; 1!=ret; )
238 ret = scanf("%8s", pin);
239 for( ; 0x20<=getchar(); ); // for removing overflow garbages
240 // '0x20<=code' is character region
244 // function(s) for provisioning client using C-level provisioning API
245 static int initProvisionClient(void)
247 // initialize persistent storage for SVR DB
248 static OCPersistentStorage pstStr =
250 .open = fopen_prvnMng,
256 if(OC_STACK_OK != OCRegisterPersistentStorageHandler(&pstStr))
258 OIC_LOG(ERROR, TAG, "OCRegisterPersistentStorageHandler error");
262 // initialize OC stack and provisioning manager
263 if(OC_STACK_OK != OCInit(NULL, 0, OC_CLIENT_SERVER))
265 OIC_LOG(ERROR, TAG, "OCStack init error");
269 if (access(PRVN_DB_FILE_NAME, F_OK) != -1)
271 printf("************************************************************\n");
272 printf("************Provisioning DB file already exists.************\n");
273 printf("************************************************************\n");
277 printf("*************************************************************\n");
278 printf("************No provisioning DB file, creating new************\n");
279 printf("*************************************************************\n");
282 if(OC_STACK_OK != OCInitPM(PRVN_DB_FILE_NAME))
284 OIC_LOG(ERROR, TAG, "OC_PM init error");
288 // register callback function(s) to each OxM
289 OTMCallbackData_t otmcb =
291 .loadSecretCB = LoadSecretJustWorksCallback,
292 .createSecureSessionCB = CreateSecureSessionJustWorksCallback,
293 .createSelectOxmPayloadCB = CreateJustWorksSelectOxmPayload,
294 .createOwnerTransferPayloadCB = CreateJustWorksOwnerTransferPayload
296 if(OC_STACK_OK != OCSetOwnerTransferCallbackData(OIC_JUST_WORKS, &otmcb))
298 OIC_LOG(ERROR, TAG, "OCSetOwnerTransferCallbackData error: OIC_JUST_WORKS");
301 otmcb.loadSecretCB = InputPinCodeCallback;
302 otmcb.createSecureSessionCB = CreateSecureSessionRandomPinCallback;
303 otmcb.createSelectOxmPayloadCB = CreatePinBasedSelectOxmPayload;
304 otmcb.createOwnerTransferPayloadCB = CreatePinBasedOwnerTransferPayload;
305 if(OC_STACK_OK != OCSetOwnerTransferCallbackData(OIC_RANDOM_DEVICE_PIN, &otmcb))
307 OIC_LOG(ERROR, TAG, "OCSetOwnerTransferCallbackData error: OIC_RANDOM_DEVICE_PIN");
310 SetInputPinCB(inputPinCB);
315 static int discoverAllDevices(void)
317 // delete un/owned device lists before updating them
320 OCDeleteDiscoveredDevices(g_own_list);
325 OCDeleteDiscoveredDevices(g_unown_list);
329 // call |OCGetDevInfoFromNetwork| API actually
330 printf(" Discovering All Un/Owned Devices on Network..\n");
331 if(OC_STACK_OK != OCGetDevInfoFromNetwork(DISCOVERY_TIMEOUT, &g_own_list, &g_unown_list))
333 OIC_LOG(ERROR, TAG, "OCGetDevInfoFromNetwork API error");
337 // display the discovered un/owned lists
338 printf(" > Discovered Owned Devices\n");
339 g_own_cnt = printDevList(g_own_list);
340 printf(" > Discovered Unowned Devices\n");
341 g_unown_cnt = printDevList(g_unown_list);
347 static int discoverUnownedDevices(void)
349 // delete unowned device list before updating it
352 OCDeleteDiscoveredDevices(g_unown_list);
356 // call |OCDiscoverUnownedDevices| API actually
357 printf(" Discovering Only Unowned Devices on Network..\n");
358 if(OC_STACK_OK != OCDiscoverUnownedDevices(DISCOVERY_TIMEOUT, &g_unown_list))
360 OIC_LOG(ERROR, TAG, "OCDiscoverUnownedDevices API error");
364 // display the discovered unowned list
365 printf(" > Discovered Unowned Devices\n");
366 g_unown_cnt = printDevList(g_unown_list);
371 static int discoverOwnedDevices(void)
373 // delete owned device list before updating it
376 OCDeleteDiscoveredDevices(g_own_list);
380 // call |OCDiscoverOwnedDevices| API actually
381 printf(" Discovering Only Owned Devices on Network..\n");
382 if(OC_STACK_OK != OCDiscoverOwnedDevices(DISCOVERY_TIMEOUT, &g_own_list))
384 OIC_LOG(ERROR, TAG, "OCDiscoverOwnedDevices API error");
388 // display the discovered owned list
389 printf(" > Discovered Owned Devices\n");
390 g_own_cnt = printDevList(g_own_list);
395 static int registerDevices(void)
397 // check |unown_list| for registering devices
398 if(!g_unown_list || 0>=g_unown_cnt)
400 printf(" > Unowned Device List, to Register Devices, is Empty\n");
401 printf(" > Please Discover Unowned Devices first, with [10|11] Menu\n");
402 return 0; // normal case
405 // call |OCDoOwnershipTransfer| API actually
406 // calling this API with callback actually acts like blocking
407 // for error checking, the return value saved and printed
409 printf(" Registering All Discovered Unowned Devices..\n");
410 OCStackResult rst = OCDoOwnershipTransfer((void*) g_ctx, g_unown_list, ownershipTransferCB);
411 if(OC_STACK_OK != rst)
413 OIC_LOG_V(ERROR, TAG, "OCDoOwnershipTransfer API error: %d", rst);
416 if(waitCallbackRet()) // input |g_doneCB| flag implicitly
418 OIC_LOG(ERROR, TAG, "OCProvisionCredentials callback error");
422 // display the registered result
423 printf(" > Registered Discovered Unowned Devices\n");
424 printf(" > Please Discover Owned Devices for the Registered Result, with [10|12] Menu\n");
429 static int provisionPairwise(void)
431 // check |own_list| for provisioning pairwise devices
432 if(!g_own_list || 2>g_own_cnt)
434 printf(" > Owned Device List, to Provision the Pairwise, is Empty\n");
435 printf(" > Please Register Unowned Devices first, with [20] Menu\n");
436 return 0; // normal case
439 // select two devices for provisioning pairwise devices
440 int dev_num[2] = {0};
441 if(selectTwoDiffNum(&(dev_num[0]), &(dev_num[1]), g_own_cnt, "for Linking Devices"))
443 OIC_LOG(ERROR, TAG, "selectTwoDiffNum error return");
444 return -1; // not need to 'goto' |ERROR| before allocating |acl|
447 // create ACL(s) for each selected device
448 OicSecAcl_t* acl[2] = {0};
449 for(int i=0; 2>i; ++i)
451 acl[i] = createAcl(dev_num[i]);
454 OIC_LOG(ERROR, TAG, "createAcl error return");
459 // call |OCProvisionPairwiseDevices| API actually
460 // calling this API with callback actually acts like blocking
461 // for error checking, the return value saved and printed
463 printf(" Provisioning Selected Pairwise Devices..\n");
465 OCProvisionPairwiseDevices((void*) g_ctx,
466 SYMMETRIC_PAIR_WISE_KEY, OWNER_PSK_LENGTH_128,
467 getDevInst((const OCProvisionDev_t*) g_own_list, dev_num[0]), acl[0],
468 getDevInst((const OCProvisionDev_t*) g_own_list, dev_num[1]), acl[1],
469 provisionPairwiseCB);
470 if(OC_STACK_OK != rst)
472 OIC_LOG_V(ERROR, TAG, "OCProvisionPairwiseDevices API error: %d", rst);
475 if(waitCallbackRet()) // input |g_doneCB| flag implicitly
477 OIC_LOG(ERROR, TAG, "OCProvisionCredentials callback error");
480 OCDeleteACLList(acl[0]);
481 OCDeleteACLList(acl[1]);
483 // display the pairwise-provisioned result
484 printf(" > Provisioned Selected Pairwise Devices\n");
485 printf(" > Please Check Device's Status for the Linked Result, with [33] Menu\n");
490 OCDeleteACLList(acl[0]);
491 OCDeleteACLList(acl[1]);
495 static int provisionCred(void)
497 // check |own_list| for provisioning pairwise credentials
498 if(!g_own_list || 2>g_own_cnt)
500 printf(" > Owned Device List, to Provision Credentials, is Empty\n");
501 printf(" > Please Register Unowned Devices first, with [20] Menu\n");
502 return 0; // normal case
505 // select two devices for provisioning pairwise credentials
506 int dev_num[2] = {0};
507 if(selectTwoDiffNum(&(dev_num[0]), &(dev_num[1]), g_own_cnt, "for Linking CRED(s)"))
509 OIC_LOG(ERROR, TAG, "selectTwoDiffNum error return");
513 printf(" Select PSK length..\n");
514 printf(" 1 - 128bit(Default)\n");
515 printf(" 2 - 256bit\n");
518 for(int ret=0; 1!=ret; )
520 ret = scanf("%d",&sizeOption);
521 for( ; 0x20<=getchar(); ); // for removing overflow garbages
522 // '0x20<=code' is character region
530 size = OWNER_PSK_LENGTH_128;
535 size = OWNER_PSK_LENGTH_256;
540 size = OWNER_PSK_LENGTH_128;
546 // call |OCProvisionCredentials| API actually
547 // calling this API with callback actually acts like blocking
548 // for error checking, the return value saved and printed
550 printf(" Provisioning Selected Pairwise Credentials..\n");
552 OCProvisionCredentials((void*) g_ctx,
553 SYMMETRIC_PAIR_WISE_KEY, size,
554 getDevInst((const OCProvisionDev_t*) g_own_list, dev_num[0]),
555 getDevInst((const OCProvisionDev_t*) g_own_list, dev_num[1]),
557 if(OC_STACK_OK != rst)
559 OIC_LOG_V(ERROR, TAG, "OCProvisionCredentials API error: %d", rst);
562 if(waitCallbackRet()) // input |g_doneCB| flag implicitly
564 OIC_LOG(ERROR, TAG, "OCProvisionCredentials callback error");
568 // display the CRED-provisioned result
569 printf(" > Provisioned Selected Pairwise Crendentials\n");
570 printf(" > Please Check Device's Status for the Linked Result, with [33] Menu\n");
575 static int provisionAcl(void)
577 // check |own_list| for provisioning access control list
578 if(!g_own_list || 1>g_own_cnt)
580 printf(" > Owned Device List, to Provision ACL, is Empty\n");
581 printf(" > Please Register Unowned Devices first, with [20] Menu\n");
582 return 0; // normal case
585 // select device for provisioning access control list
589 printf(" > Enter Device Number, for Provisioning ACL: ");
590 for(int ret=0; 1!=ret; )
592 ret = scanf("%d", &dev_num);
593 for( ; 0x20<=getchar(); ); // for removing overflow garbages
594 // '0x20<=code' is character region
596 if(0<dev_num && g_own_cnt>=dev_num)
600 printf(" Entered Wrong Number. Please Enter Again\n");
603 // create ACL for selected device
604 OicSecAcl_t* acl = NULL;
605 acl = createAcl(dev_num);
608 OIC_LOG(ERROR, TAG, "createAcl error return");
612 // call |OCProvisionACL| API actually
613 // calling this API with callback actually acts like blocking
614 // for error checking, the return value saved and printed
616 printf(" Provisioning Selected ACL..\n");
617 OCProvisionDev_t* dev = getDevInst((const OCProvisionDev_t*) g_own_list, dev_num);
620 OIC_LOG(ERROR, TAG, "provisionAcl: device instance empty");
623 OCStackResult rst = OCProvisionACL((void*) g_ctx, dev, acl, provisionAclCB);
624 if(OC_STACK_OK != rst)
626 OIC_LOG_V(ERROR, TAG, "OCProvisionACL API error: %d", rst);
629 if(waitCallbackRet()) // input |g_doneCB| flag implicitly
631 OIC_LOG(ERROR, TAG, "OCProvisionCredentials callback error");
634 OCDeleteACLList(acl); // after here |acl| points nothing
636 // display the ACL-provisioned result
637 printf(" > Provisioned Selected ACL\n");
642 OCDeleteACLList(acl); // after here |acl| points nothing
646 static int provisionDirectPairing(void)
648 // check |own_list| for provisioning direct-pairing
649 if(!g_own_list || 1>g_own_cnt)
651 printf(" > Owned Device List, to Provision ACL, is Empty\n");
652 printf(" > Please Register Unowned Devices first, with [20] Menu\n");
653 return 0; // normal case
656 // select device for provisioning direct-pairing
660 printf(" > Enter Device Number, for Provisioning Direct-Pairing: ");
661 for(int ret=0; 1!=ret; )
663 ret = scanf("%d", &dev_num);
664 for( ; 0x20<=getchar(); ); // for removing overflow garbages
665 // '0x20<=code' is character region
667 if(0<dev_num && g_own_cnt>=dev_num)
671 printf(" Entered Wrong Number. Please Enter Again\n");
674 // create Direct-Pairing Configuration(PIN, PDACL) for selected device
675 // TODO: default acl -> input from user !
677 memset(&pconf, 0, sizeof(OicSecPconf_t));
682 // set default supported PRM types
683 pconf.prmLen = sizeof(SUPPORTED_PRMS)/sizeof(OicSecPrm_t);
684 pconf.prm = (OicSecPrm_t *)OICCalloc(pconf.prmLen, sizeof(OicSecPrm_t));
687 for (size_t i=0; i<pconf.prmLen; i++)
689 pconf.prm[i] = SUPPORTED_PRMS[i];
694 OIC_LOG(ERROR, TAG, "create prm error return");
699 const char DP_DEFAULT_PIN[] = "00000000";
700 memcpy(pconf.pin.val, DP_DEFAULT_PIN, DP_PIN_LENGTH);
703 pconf.pdacls = createPdAcl(dev_num);
706 OIC_LOG(ERROR, TAG, "createPdAcl error return");
710 // call |OCProvisionDirectPairing| API actually
711 // calling this API with callback actually acts like blocking
712 // for error checking, the return value saved and printed
714 printf(" Atempt Direct-Pairing Provisioning (PIN : [%s])..\n", (char*)pconf.pin.val);
715 OCStackResult rst = OCProvisionDirectPairing((void*) g_ctx,
716 getDevInst((const OCProvisionDev_t*) g_own_list, dev_num),
717 &pconf, provisionDPCB);
718 if(OC_STACK_OK != rst)
720 OIC_LOG_V(ERROR, TAG, "OCProvisionDirectPairing API error: %d", rst);
721 if (OC_STACK_UNAUTHORIZED_REQ == rst)
723 OIC_LOG(ERROR, TAG, "Target Server NOT Support Direct-Pairing !!! (DPC == false)");
727 if(waitCallbackRet()) // input |g_doneCB| flag implicitly
729 OIC_LOG(ERROR, TAG, "OCProvisionCredentials callback error");
732 OCDeletePdAclList(pconf.pdacls);
734 // display the PCONF-provisioned result
735 printf(" > SUCCESS to provision Direct-Pairing !!\n");
740 OCDeletePdAclList(pconf.pdacls); // after here |acl| points nothing
744 static int checkLinkedStatus(void)
746 // check |own_list| for checking selected link status on PRVN DB
747 if(!g_own_list || 1>g_own_cnt)
749 printf(" > Owned Device List, to Check Linked Status on PRVN DB, is Empty\n");
750 printf(" > Please Register Unowned Devices first, with [20] Menu\n");
751 return 0; // normal case
754 // select device for checking selected link status on PRVN DB
758 printf(" > Enter Device Number, for Checking Linked Status on PRVN DB: ");
759 for(int ret=0; 1!=ret; )
761 ret = scanf("%d", &dev_num);
762 for( ; 0x20<=getchar(); ); // for removing overflow garbages
763 // '0x20<=code' is character region
765 if(0<dev_num && g_own_cnt>=dev_num)
769 printf(" Entered Wrong Number. Please Enter Again\n");
772 // call |OCGetLinkedStatus| API actually
773 printf(" Checking Selected Link Status on PRVN DB..\n");
774 OCUuidList_t* dvid_lst = NULL;
776 OCProvisionDev_t* dev = getDevInst((const OCProvisionDev_t*)g_own_list, dev_num);
777 if(!dev || !dev->doxm)
779 OIC_LOG(ERROR, TAG, "checkLinkedStatus: device instance empty");
785 &dev->doxm->deviceID,
786 &dvid_lst, &dvid_cnt)) // allow empty list
788 OIC_LOG(ERROR, TAG, "OCGetLinkedStatus API error");
792 // display the linked status result
793 printf(" > Checked Selected Link Status on PRVN DB\n");
794 if(!dvid_lst || !dvid_cnt) // |size_t| is unsigned
796 printf(" Linked Device List is Empty..\n");
797 return 0; // normal case
799 if(dvid_cnt != printUuidList((const OCUuidList_t*) dvid_lst))
801 OIC_LOG(ERROR, TAG, "printUuidList error return");
804 OCDeleteUuidList(dvid_lst);
809 OCDeleteUuidList(dvid_lst);
813 static int getCred(void)
815 // check |own_list| for checking selected link status on PRVN DB
816 if(!g_own_list || 1>g_own_cnt)
818 printf(" > Owned Device List, to Check Linked Status on PRVN DB, is Empty\n");
819 printf(" > Please Register Unowned Devices first, with [20] Menu\n");
820 return 0; // normal case
823 // select device for checking selected link status on PRVN DB
827 printf(" > Enter Device Number, for Checking Linked Status on PRVN DB: ");
828 for(int ret=0; 1!=ret; )
830 ret = scanf("%d", &dev_num);
831 for( ; 0x20<=getchar(); ); // for removing overflow garbages
832 // '0x20<=code' is character region
834 if(0<dev_num && g_own_cnt>=dev_num)
838 printf(" Entered Wrong Number. Please Enter Again\n");
841 // call |getDevInst| API actually
842 // calling this API with callback actually acts like blocking
843 // for error checking, the return value saved and printed
845 OCProvisionDev_t* dev = getDevInst((const OCProvisionDev_t*) g_own_list, dev_num);
848 OIC_LOG(ERROR, TAG, "getDevInst: device instance empty");
851 OCStackResult rst = OCGetCredResource((void*) g_ctx, dev, getCredCB);
852 if(OC_STACK_OK != rst)
854 OIC_LOG_V(ERROR, TAG, "OCGetCred API error: %d", rst);
857 if(waitCallbackRet()) // input |g_doneCB| flag implicitly
859 OIC_LOG(ERROR, TAG, "OCGetCredResource callback error");
863 // display the result of get credential
864 printf(" > Get Cred SUCCEEDED\n");
872 static int getAcl(void)
874 // check |own_list| for checking selected link status on PRVN DB
875 if(!g_own_list || 1>g_own_cnt)
877 printf(" > Owned Device List, to Check Linked Status on PRVN DB, is Empty\n");
878 printf(" > Please Register Unowned Devices first, with [20] Menu\n");
879 return 0; // normal case
882 // select device for checking selected link status on PRVN DB
886 printf(" > Enter Device Number, for Checking Linked Status on PRVN DB: ");
887 for(int ret=0; 1!=ret; )
889 ret = scanf("%d", &dev_num);
890 for( ; 0x20<=getchar(); ); // for removing overflow garbages
891 // '0x20<=code' is character region
893 if(0<dev_num && g_own_cnt>=dev_num)
897 printf(" Entered Wrong Number. Please Enter Again\n");
900 // call |getDevInst| API actually
901 // calling this API with callback actually acts like blocking
902 // for error checking, the return value saved and printed
904 OCProvisionDev_t* dev = getDevInst((const OCProvisionDev_t*) g_own_list, dev_num);
907 OIC_LOG(ERROR, TAG, "getDevInst: device instance empty");
910 OCStackResult rst = OCGetACLResource((void*) g_ctx, dev, getAclCB);
911 if(OC_STACK_OK != rst)
913 OIC_LOG_V(ERROR, TAG, "OCGetACLResource API error: %d", rst);
917 if(waitCallbackRet()) // input |g_doneCB| flag implicitly
919 OIC_LOG(ERROR, TAG, "OCGetACLResource callback error");
923 // display the result of get credential
924 printf(" > Get ACL SUCCEEDED\n");
932 static int unlinkPairwise(void)
934 // check |own_list| for unlinking pairwise devices
935 if(!g_own_list || 2>g_own_cnt)
937 printf(" > Owned Device List, to Unlink the Pairwise, is Empty\n");
938 printf(" > Please Register Unowned Devices first, with [20] Menu\n");
939 return 0; // normal case
942 // select two devices for unlinking pairwise devices
943 int dev_num[2] = {0};
944 if(selectTwoDiffNum(&(dev_num[0]), &(dev_num[1]), g_own_cnt, "for Unlinking Devices"))
946 OIC_LOG(ERROR, TAG, "selectTwoDiffNum error return");
950 // call |OCUnlinkDevices| API actually
951 // calling this API with callback actually acts like blocking
952 // for error checking, the return value saved and printed
954 printf(" Unlinking Selected Pairwise Devices..\n");
956 OCUnlinkDevices((void*) g_ctx,
957 getDevInst((const OCProvisionDev_t*) g_own_list, dev_num[0]),
958 getDevInst((const OCProvisionDev_t*) g_own_list, dev_num[1]),
960 if(OC_STACK_OK != rst)
962 OIC_LOG_V(ERROR, TAG, "OCUnlinkDevices API error: %d", rst);
965 if(waitCallbackRet()) // input |g_doneCB| flag implicitly
967 OIC_LOG(ERROR, TAG, "OCProvisionCredentials callback error");
971 // display the pairwise-unlinked result
972 printf(" > Unlinked Selected Pairwise Devices\n");
973 printf(" > Please Check Device's Status for the Unlinked Result, with [33] Menu\n");
978 static int removeDevice(void)
980 // check |own_list| for removing device
981 if(!g_own_list || 1>g_own_cnt)
983 printf(" > Owned Device List, to Remove Device, is Empty\n");
984 printf(" > Please Register Unowned Devices first, with [20] Menu\n");
985 return 0; // normal case
988 // select device for removing it
992 printf(" > Enter Device Number, for Removing Device: ");
993 for(int ret=0; 1!=ret; )
995 ret = scanf("%d", &dev_num);
996 for( ; 0x20<=getchar(); ); // for removing overflow garbages
997 // '0x20<=code' is character region
999 if(0<dev_num && g_own_cnt>=dev_num)
1003 printf(" Entered Wrong Number. Please Enter Again\n");
1006 // call |OCRemoveDevice| API actually
1007 // calling this API with callback actually acts like blocking
1008 // for error checking, the return value saved and printed
1010 printf(" Removing Selected Owned Device..\n");
1012 OCRemoveDevice((void*) g_ctx, DISCOVERY_TIMEOUT,
1013 getDevInst((const OCProvisionDev_t*) g_own_list, dev_num), removeDeviceCB);
1014 if(OC_STACK_OK != rst)
1016 OIC_LOG_V(ERROR, TAG, "OCRemoveDevice API error: %d", rst);
1019 if(waitCallbackRet()) // input |g_doneCB| flag implicitly
1021 OIC_LOG(ERROR, TAG, "OCProvisionCredentials callback error");
1025 // display the removed result
1026 printf(" > Removed Selected Owned Device\n");
1027 printf(" > Please Discover Owned Devices for the Registered Result, with [10|12] Menu\n");
1032 static OicSecAcl_t* createAcl(const int dev_num)
1034 if(0>=dev_num || g_own_cnt<dev_num)
1036 OIC_LOG(ERROR, TAG, "createAcl invalid parameters");
1037 return NULL; // not need to 'goto' |ERROR| before allocating |acl|
1040 // allocate memory for |acl| struct
1041 printf(" **** Create ACL for the Selected Device[%d]\n", dev_num);
1042 OicSecAcl_t* acl = (OicSecAcl_t*) OICCalloc(1, sizeof(OicSecAcl_t));
1045 OIC_LOG(ERROR, TAG, "createAcl: OICCalloc error return");
1046 return NULL; // not need to 'goto' |ERROR| before allocating |acl|
1049 // enter |subject| device number
1053 printf(" > [A] Enter Subject Device Number: ");
1054 for(int ret=0; 1!=ret; )
1056 ret = scanf("%d", &num);
1057 for( ; 0x20<=getchar(); ); // for removing overflow garbages
1058 // '0x20<=code' is character region
1060 if(0<num && g_own_cnt>=num && dev_num!=num)
1064 printf(" Entered Wrong Number. Please Enter Again\n");
1067 OCProvisionDev_t* dev = getDevInst((const OCProvisionDev_t*)g_own_list, num);
1068 if(!dev || !dev->doxm)
1070 OIC_LOG(ERROR, TAG, "createAcl: device instance empty");
1073 memcpy(&acl->subject, &dev->doxm->deviceID, UUID_LENGTH);
1075 // enter number of |resources| in 'accessed' device
1078 printf(" > [B] Enter Number of Accessed Resources (under 16): ");
1079 // '16' is |ACL_RESRC_MAX_NUM|
1080 for(int ret=0; 1!=ret; )
1082 ret = scanf("%d", &num);
1083 for( ; 0x20<=getchar(); ); // for removing overflow garbages
1084 // '0x20<=code' is character region
1086 if(0<num && ACL_RESRC_MAX_NUM>=num)
1090 printf(" Entered Wrong Number. Please Enter under 16 Again\n");
1091 // '16' is |ACL_RESRC_MAX_NUM|
1094 // enter actually each 'accessed' |resources| name
1095 printf(" Enter Each Accessed Resource Name (each under 128 char)\n");
1096 // '128' is ACL_RESRC_MAX_LEN
1097 acl->resourcesLen = (unsigned) num;
1098 acl->resources = (char**) OICCalloc(acl->resourcesLen, sizeof(char*));
1101 OIC_LOG(ERROR, TAG, "createAcl: OICCalloc error return");
1104 char rsrc_in[ACL_RESRC_MAX_LEN+1] = {0}; // '1' for null termination
1105 for(int i=0; acl->resourcesLen>(unsigned)i; ++i)
1107 printf(" Enter Accessed Resource[%d] Name: ", i+1);
1108 for(int ret=0; 1!=ret; )
1110 ret = scanf("%128s", rsrc_in); // '128' is ACL_RESRC_MAX_LEN
1111 for( ; 0x20<=getchar(); ); // for removing overflow garbages
1112 // '0x20<=code' is character region
1114 size_t len = strlen(rsrc_in)+1; // '1' for null termination
1115 char* rsrc = (char*) OICCalloc(len, sizeof(char));
1118 OIC_LOG(ERROR, TAG, "createAcl: OICCalloc error return");
1121 OICStrcpy(rsrc, len, rsrc_in);
1122 acl->resources[i] = rsrc; // after here, |rsrc| points nothing
1125 // enter |permission| for this access
1126 printf(" > [C] Enter Permission for This Access\n");
1127 uint16_t pmsn = PERMISSION_FULL_CONTROL; // default full permission
1128 uint16_t pmsn_msk = PERMISSION_CREATE; // default permission mask
1129 for(int i=0; ACL_PEMISN_CNT>i; ++i)
1134 printf(" Enter %s Permission (y/n): ", ACL_PEMISN[i]);
1135 for(int ret=0; 1!=ret; )
1137 ret = scanf("%c", &ans);
1138 for( ; 0x20<=getchar(); ); // for removing overflow garbages
1139 // '0x20<=code' is character region
1141 if('y'==ans || 'Y'==ans || 'n'==ans|| 'N'==ans)
1143 ans &= ~0x20; // for masking lower case, 'y/n'
1146 printf(" Entered Wrong Answer. Please Enter 'y/n' Again\n");
1148 if('N' == ans) // masked lower case, 'n'
1154 acl->permission = pmsn;
1156 // enter |owner| device number
1160 printf(" > [D] Enter Owner Device Number: ");
1161 for(int ret=0; 1!=ret; )
1163 ret = scanf("%d", &own_num);
1164 for( ; 0x20<=getchar(); ); // for removing overflow garbages
1165 // '0x20<=code' is character region
1167 if(0<own_num && g_own_cnt>=own_num)
1171 printf(" Entered Wrong Number. Please Enter Again\n");
1174 dev = getDevInst((const OCProvisionDev_t*)g_own_list, own_num);
1175 if(!dev || !dev->doxm)
1177 OIC_LOG(ERROR, TAG, "createAcl: device instance empty");
1180 memcpy(&acl->rownerID, &dev->doxm->deviceID, sizeof(OicUuid_t));
1186 OCDeleteACLList(acl); // after here |acl| points nothing
1190 static OicSecPdAcl_t* createPdAcl(const int dev_num)
1192 if(0>=dev_num || g_own_cnt<dev_num)
1194 OIC_LOG(ERROR, TAG, "createAcl invalid parameters");
1195 return NULL; // not need to 'goto' |ERROR| before allocating |acl|
1198 // allocate memory for |pdacl| struct
1199 printf(" **** Create PDACL for the Selected Device[%d]\n", dev_num);
1200 OicSecPdAcl_t* pdAcl = (OicSecPdAcl_t*) OICCalloc(1, sizeof(OicSecPdAcl_t));
1203 OIC_LOG(ERROR, TAG, "createAcl: OICCalloc error return");
1204 return NULL; // not need to 'goto' |ERROR| before allocating |acl|
1208 // number of resources
1209 char rsrc_in[][ACL_RESRC_MAX_LEN+1] = {"*", "/rsrc/*"};
1210 pdAcl->resourcesLen = 1;
1213 int num = pdAcl->resourcesLen;
1214 pdAcl->resources = (char**) OICCalloc(num, sizeof(char*));
1215 if(!pdAcl->resources)
1217 OIC_LOG(ERROR, TAG, "createPdAcl: OICCalloc error return");
1220 for(int i=0; num>i; ++i)
1222 size_t len = strlen(rsrc_in[i])+1; // '1' for null termination
1223 char* rsrc = (char*) OICCalloc(len, sizeof(char));
1226 OIC_LOG(ERROR, TAG, "createPdAcl: OICCalloc error return");
1229 OICStrcpy(rsrc, len, rsrc_in[i]);
1230 pdAcl->resources[i] = rsrc; // after here, |rsrc| points nothing
1234 pdAcl->permission = PERMISSION_FULL_CONTROL;
1239 OCDeletePdAclList(pdAcl);
1243 static OCProvisionDev_t* getDevInst(const OCProvisionDev_t* dev_lst, const int dev_num)
1245 if(!dev_lst || 0>=dev_num)
1247 printf(" Device List is Empty..\n");
1251 OCProvisionDev_t* lst = (OCProvisionDev_t*) dev_lst;
1261 return NULL; // in here |lst| is always |NULL|
1264 static int printDevList(const OCProvisionDev_t* dev_lst)
1268 printf(" Device List is Empty..\n\n");
1272 OCProvisionDev_t* lst = (OCProvisionDev_t*) dev_lst;
1276 printf(" [%d] ", ++lst_cnt);
1277 printUuid((const OicUuid_t*) &lst->doxm->deviceID);
1286 static size_t printUuidList(const OCUuidList_t* uid_lst)
1290 printf(" Device List is Empty..\n\n");
1294 OCUuidList_t* lst = (OCUuidList_t*) uid_lst;
1298 printf(" [%zu] ", ++lst_cnt);
1299 printUuid((const OicUuid_t*) &lst->dev);
1308 static int printResultList(const OCProvisionResult_t* rslt_lst, const int rslt_cnt)
1310 if(!rslt_lst || 0>=rslt_cnt)
1312 printf(" Device List is Empty..\n\n");
1317 for( ; rslt_cnt>lst_cnt; ++lst_cnt)
1319 printf(" [%d] ", lst_cnt+1);
1320 printUuid((const OicUuid_t*) &rslt_lst[lst_cnt].deviceId);
1321 printf(" - result: %d\n", rslt_lst[lst_cnt].res);
1328 static void printUuid(const OicUuid_t* uid)
1330 for(int i=0; i<UUID_LENGTH; )
1332 printf("%02X", (*uid).id[i++]);
1333 if(i==4 || i==6 || i==8 || i==10) // canonical format for UUID has '8-4-4-4-12'
1340 static FILE* fopen_prvnMng(const char* path, const char* mode)
1342 (void)path; // unused |path| parameter
1344 // input |g_svr_db_fname| internally by force, not using |path| parameter
1345 // because |OCPersistentStorage::open| is called |OCPersistentStorage| internally
1346 // with its own |SVR_DB_FILE_NAME|
1347 return fopen(SVR_DB_FILE_NAME, mode);
1350 static int waitCallbackRet(void)
1352 for(int i=0; !g_doneCB && CALLBACK_TIMEOUT>i; ++i)
1355 if(OC_STACK_OK != OCProcess())
1357 OIC_LOG(ERROR, TAG, "OCStack process error");
1365 static int selectTwoDiffNum(int* a, int* b, const int max, const char* str)
1367 if(!a || !b || 2>max || !str)
1374 for(int i=0; 2>i; ++i)
1376 int* num = 0==i?a:b;
1379 printf(" > Enter Device[%d] Number, %s: ", i+1, str);
1380 for(int ret=0; 1!=ret; )
1382 ret = scanf("%d", num);
1383 for( ; 0x20<=getchar(); ); // for removing overflow garbages
1384 // '0x20<=code' is character region
1386 if(0<*num && max>=*num)
1390 printf(" Entered Wrong Number. Please Enter Again\n");
1403 static void printMenu(void)
1405 printf("************************************************************\n");
1406 printf("****** OIC Provisioning Client with using C-level API ******\n");
1407 printf("************************************************************\n\n");
1409 printf("** [A] DISCOVER DEVICES ON NETWORK\n");
1410 printf("** 10. Discover All Un/Owned Devices on Network\n");
1411 printf("** 11. Discover Only Unowned Devices on Network\n");
1412 printf("** 12. Discover Only Owned Devices on Network\n\n");
1414 printf("** [B] REGISTER/OWN ALL DISCOVERED UNOWNED DEVICES\n");
1415 printf("** 20. Register/Own All Discovered Unowned Devices\n\n");
1417 printf("** [C] PROVISION/LINK PAIRWISE THINGS\n");
1418 printf("** 30. Provision/Link Pairwise Things\n");
1419 printf("** 31. Provision Credentials for Pairwise Things\n");
1420 printf("** 32. Provision the Selected Access Control List(ACL)\n");
1421 printf("** 33. Provision Direct-Pairing Configuration\n");
1422 printf("** 34. Check Linked Status of the Selected Device on PRVN DB\n\n");
1424 printf("** [D] UNLINK PAIRWISE THINGS\n");
1425 printf("** 40. Unlink Pairwise Things\n\n");
1427 printf("** [E] REMOVE THE SELECTED DEVICE\n");
1428 printf("** 50. Remove the Selected Device\n\n");
1430 printf("** [F] GET SECURITY RESOURCE FOR DEBUGGING ONLY\n");
1431 printf("** 60. Get the Credential resources of the Selected Device\n");
1432 printf("** 61. Get the ACL resources of the Selected Device\n\n");
1434 printf("** [F] EXIT PROVISIONING CLIENT\n");
1435 printf("** 99. Exit Provisionong Client\n\n");
1437 printf("************************************************************\n\n");
1440 #if 0 // Code for enabling path configuration for PDB and SVR DBf
1441 static void printUsage(void)
1444 printf("OIC Provisioning Client with using C-level API\n");
1445 printf("Usage: provisioningclient [option]...\n");
1447 printf(" -h print help for this provisioning client\n");
1448 printf(" -p=[prvn_db_file_path/name] input PRVN DB file path and name\n");
1449 printf(" if not exists, will load default DB file\n");
1450 printf(" (default: |oic_prvn_mng.db| on working dir)\n");
1451 printf(" (ex. -p=oic_prvn_mng.db)\n");
1452 printf(" -s=[svr_db_file_path/name] input SVR DB file path and name\n");
1453 printf(" if not exists, will load default DB file\n");
1454 printf(" (default: |oic_svr_db_client.json| on working dir)\n");
1455 printf(" (ex. -s=oic_svr_db_client.json)\n");
1460 // main function for provisioning client using C-level provisioning API
1463 // initialize provisioning client
1464 if(initProvisionClient())
1466 OIC_LOG(ERROR, TAG, "ProvisionClient init error");
1470 // main loop for provisioning manager
1476 printf(">> Enter Menu Number: ");
1477 for(int ret=0; 1!=ret; )
1479 ret = scanf("%d", &mn_num);
1480 for( ; 0x20<=getchar(); ); // for removing overflow garbages
1481 // '0x20<=code' is character region
1486 case _10_DISCOV_ALL_DEVS_:
1487 if(discoverAllDevices())
1489 OIC_LOG(ERROR, TAG, "_10_DISCOV_ALL_DEVS_: error");
1492 case _11_DISCOV_UNOWN_DEVS_:
1493 if(discoverUnownedDevices())
1495 OIC_LOG(ERROR, TAG, "_11_DISCOV_UNOWN_DEVS_: error");
1498 case _12_DISCOV_OWN_DEVS_:
1499 if(discoverOwnedDevices())
1501 OIC_LOG(ERROR, TAG, "_12_DISCOV_OWN_DEVS_: error");
1504 case _20_REGIST_DEVS_:
1505 if(registerDevices())
1507 OIC_LOG(ERROR, TAG, "_20_REGIST_DEVS_: error");
1510 case _30_PROVIS_PAIR_DEVS_:
1511 if(provisionPairwise())
1513 OIC_LOG(ERROR, TAG, "_30_PROVIS_PAIR_DEVS_: error");
1516 case _31_PROVIS_CRED_:
1519 OIC_LOG(ERROR, TAG, "_31_PROVIS_CRED_: error");
1522 case _32_PROVIS_ACL_:
1525 OIC_LOG(ERROR, TAG, "_32_PROVIS_ACL_: error");
1528 case _33_PROVIS_DP_:
1529 if(provisionDirectPairing())
1531 OIC_LOG(ERROR, TAG, "_33_PROVIS_DP_: error");
1534 case _34_CHECK_LINK_STATUS_:
1535 if(checkLinkedStatus())
1537 OIC_LOG(ERROR, TAG, "_34_CHECK_LINK_STATUS_: error");
1540 case _40_UNLINK_PAIR_DEVS_:
1541 if(unlinkPairwise())
1543 OIC_LOG(ERROR, TAG, "_40_UNLINK_PAIR_DEVS_: error");
1546 case _50_REMOVE_SELEC_DEV_:
1549 OIC_LOG(ERROR, TAG, "_50_REMOVE_SELEC_DEV_: error");
1555 OIC_LOG(ERROR, TAG, "_60_GET_CRED_: error");
1561 OIC_LOG(ERROR, TAG, "_61_GET_ACL_: error");
1564 case _99_EXIT_PRVN_CLT_:
1567 printf(">> Entered Wrong Number. Please Enter Again\n\n");
1573 if(OC_STACK_OK != OCStop())
1575 OIC_LOG(ERROR, TAG, "OCStack stop error");
1577 OCDeleteDiscoveredDevices(g_own_list); // after here |g_own_list| points nothing
1578 OCDeleteDiscoveredDevices(g_unown_list); // after here |g_unown_list| points nothing
1582 OICFree(g_svr_fname); // after here |g_svr_fname| points nothing
1586 OICFree(g_prvn_fname); // after here |g_prvn_fname| points nothing
1588 return 0; // always return normal case
1593 #endif //__cplusplus