Sync master with 1.1-rel
[platform/upstream/iotivity.git] / resource / csdk / security / provisioning / sample / provisioningclient.c
1 /******************************************************************
2  *
3  * Copyright 2015 Samsung Electronics All Rights Reserved.
4  *
5  *
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *****************************************************************/
20
21 #include <stdio.h>
22 #include <string.h>
23 #ifdef HAVE_UNISTD_H
24 #include <unistd.h>
25 #endif
26
27 #include "platform_features.h"
28 #include "utlist.h"
29 #include "logger.h"
30 #include "oic_malloc.h"
31 #include "oic_string.h"
32 #include "ocprovisioningmanager.h"
33 #include "oxmjustworks.h"
34 #include "oxmrandompin.h"
35 #include "securevirtualresourcetypes.h"
36 #include "srmutility.h"
37 #include "pmtypes.h"
38
39 #ifdef __cplusplus
40 extern "C"
41 {
42 #endif //__cplusplus
43
44 // declaration(s) for provisioning client using C-level provisioning API
45 // user input definition for main loop on provisioning client
46 #define _10_DISCOV_ALL_DEVS_        10
47 #define _11_DISCOV_UNOWN_DEVS_      11
48 #define _12_DISCOV_OWN_DEVS_        12
49 #define _20_REGIST_DEVS_            20
50 #define _30_PROVIS_PAIR_DEVS_       30
51 #define _31_PROVIS_CRED_            31
52 #define _32_PROVIS_ACL_             32
53 #define _33_PROVIS_DP_              33
54 #define _34_CHECK_LINK_STATUS_      34
55 #define _40_UNLINK_PAIR_DEVS_       40
56 #define _50_REMOVE_SELEC_DEV_       50
57 #define _51_REMOVE_DEV_WITH_UUID_   51
58 #define _52_RESET_SELEC_DEV_        52
59 #define _60_GET_CRED_               60
60 #define _61_GET_ACL_                61
61 #define _99_EXIT_PRVN_CLT_          99
62
63 #define ACL_RESRC_MAX_NUM   16
64 #define ACL_RESRC_ARRAY_SIZE   3 //This value is used only for sample (not OCF spec)
65 #define ACL_RESRC_MAX_LEN   128
66 #define ACL_PEMISN_CNT      5
67 #define DISCOVERY_TIMEOUT   10  // 10 sec
68 #define CALLBACK_TIMEOUT    60  // 1 min
69 #define TAG "provisioningclient"
70
71 static const char* ACL_PEMISN[5] = {"CREATE", "READ", "WRITE", "DELETE", "NOTIFY"};
72 static const char* SVR_DB_FILE_NAME = "oic_svr_db_client.dat";
73         // '_' for separaing from the same constant variable in |srmresourcestrings.c|
74 static const char* PRVN_DB_FILE_NAME = "oic_prvn_mng.db";
75 static const OicSecPrm_t  SUPPORTED_PRMS[1] =
76 {
77     PRM_PRE_CONFIGURED,
78 };
79
80 // |g_ctx| means provision manager application context and
81 // the following, includes |un/own_list|, could be variables, which |g_ctx| has,
82 // for accessing all function(s) for these, they are declared on global domain
83 static const char* g_ctx = "Provision Manager Client Application Context";
84 static char* g_svr_fname;
85 static char* g_prvn_fname;
86 static OCProvisionDev_t* g_own_list;
87 static OCProvisionDev_t* g_unown_list;
88 static int g_own_cnt;
89 static int g_unown_cnt;
90 static bool g_doneCB;
91
92 // function declaration(s) for calling them before implementing
93 static OicSecAcl_t* createAcl(const int);
94 static OicSecPdAcl_t* createPdAcl(const int);
95 static OCProvisionDev_t* getDevInst(const OCProvisionDev_t*, const int);
96 static int printDevList(const OCProvisionDev_t*);
97 static size_t printUuidList(const OCUuidList_t*);
98 static int printResultList(const OCProvisionResult_t*, const int);
99 static void printUuid(const OicUuid_t*);
100 static FILE* fopen_prvnMng(const char*, const char*);
101 static int waitCallbackRet(void);
102 static int selectTwoDiffNum(int*, int*, const int, const char*);
103
104 // callback function(s) for provisioning client using C-level provisioning API
105 static void ownershipTransferCB(void* ctx, int nOfRes, OCProvisionResult_t* arr, bool hasError)
106 {
107     if(!hasError)
108     {
109         OIC_LOG_V(INFO, TAG, "Ownership Transfer SUCCEEDED - ctx: %s", (char*) ctx);
110     }
111     else
112     {
113         OIC_LOG_V(ERROR, TAG, "Ownership Transfer FAILED - ctx: %s", (char*) ctx);
114         printResultList((const OCProvisionResult_t*) arr, nOfRes);
115     }
116     g_doneCB = true;
117 }
118
119 static void provisionPairwiseCB(void* ctx, int nOfRes, OCProvisionResult_t* arr, bool hasError)
120 {
121     if(!hasError)
122     {
123         OIC_LOG_V(INFO, TAG, "Provision Pairwise SUCCEEDED - ctx: %s", (char*) ctx);
124     }
125     else
126     {
127         OIC_LOG_V(ERROR, TAG, "Provision Pairwise FAILED - ctx: %s", (char*) ctx);
128         printResultList((const OCProvisionResult_t*) arr, nOfRes);
129     }
130     g_doneCB = true;
131 }
132
133 static void provisionCredCB(void* ctx, int nOfRes, OCProvisionResult_t* arr, bool hasError)
134 {
135     if(!hasError)
136     {
137         OIC_LOG_V(INFO, TAG, "Provision Credential SUCCEEDED - ctx: %s", (char*) ctx);
138     }
139     else
140     {
141         OIC_LOG_V(ERROR, TAG, "Provision Credential FAILED - ctx: %s", (char*) ctx);
142         printResultList((const OCProvisionResult_t*) arr, nOfRes);
143     }
144     g_doneCB = true;
145 }
146
147 static void provisionAclCB(void* ctx, int nOfRes, OCProvisionResult_t* arr, bool hasError)
148 {
149     if(!hasError)
150     {
151         OIC_LOG_V(INFO, TAG, "Provision ACL SUCCEEDED - ctx: %s", (char*) ctx);
152     }
153     else
154     {
155         OIC_LOG_V(ERROR, TAG, "Provision ACL FAILED - ctx: %s", (char*) ctx);
156         printResultList((const OCProvisionResult_t*) arr, nOfRes);
157     }
158     g_doneCB = true;
159 }
160
161 static void getCredCB(void* ctx, int nOfRes, OCProvisionResult_t* arr, bool hasError)
162 {
163     if(!hasError)
164     {
165         OIC_LOG_V(INFO, TAG, "getCredCB SUCCEEDED - ctx: %s", (char*) ctx);
166     }
167     else
168     {
169         OIC_LOG_V(ERROR, TAG, "getCredCB FAILED - ctx: %s", (char*) ctx);
170         printResultList((const OCProvisionResult_t*) arr, nOfRes);
171     }
172     g_doneCB = true;
173 }
174
175 static void getAclCB(void* ctx, int nOfRes, OCProvisionResult_t* arr, bool hasError)
176 {
177     if(!hasError)
178     {
179         OIC_LOG_V(INFO, TAG, "getAclCB SUCCEEDED - ctx: %s", (char*) ctx);
180     }
181     else
182     {
183         OIC_LOG_V(ERROR, TAG, "getAclCB FAILED - ctx: %s", (char*) ctx);
184         printResultList((const OCProvisionResult_t*) arr, nOfRes);
185     }
186     g_doneCB = true;
187 }
188
189 static void provisionDPCB(void* ctx, int nOfRes, OCProvisionResult_t* arr, bool hasError)
190 {
191     if(!hasError)
192     {
193         OIC_LOG_V(INFO, TAG, "Provision Direct-Pairing SUCCEEDED - ctx: %s", (char*) ctx);
194     }
195     else
196     {
197         OIC_LOG_V(ERROR, TAG, "Provision Direct-Pairing FAILED - ctx: %s", (char*) ctx);
198         printResultList((const OCProvisionResult_t*) arr, nOfRes);
199     }
200     g_doneCB = true;
201 }
202
203 static void unlinkDevicesCB(void* ctx, int nOfRes, OCProvisionResult_t* arr, bool hasError)
204 {
205     if(!hasError)
206     {
207         OIC_LOG_V(INFO, TAG, "Unlink Devices SUCCEEDED - ctx: %s", (char*) ctx);
208     }
209     else
210     {
211         OIC_LOG_V(ERROR, TAG, "Unlink Devices FAILED - ctx: %s", (char*) ctx);
212         printResultList((const OCProvisionResult_t*) arr, nOfRes);
213     }
214     g_doneCB = true;
215 }
216
217 static void removeDeviceCB(void* ctx, int nOfRes, OCProvisionResult_t* arr, bool hasError)
218 {
219     if(!hasError)
220     {
221         OIC_LOG_V(INFO, TAG, "Remove Device SUCCEEDED - ctx: %s", (char*) ctx);
222     }
223     else
224     {
225         OIC_LOG_V(ERROR, TAG, "Remove Device FAILED - ctx: %s", (char*) ctx);
226         printResultList((const OCProvisionResult_t*) arr, nOfRes);
227     }
228     g_doneCB = true;
229 }
230
231 static void syncDeviceCB(void* ctx, int nOfRes, OCProvisionResult_t* arr, bool hasError)
232 {
233     if(!hasError)
234     {
235         OIC_LOG_V(INFO, TAG, "Sync Device SUCCEEDED - ctx: %s", (char*) ctx);
236     }
237     else
238     {
239         OIC_LOG_V(ERROR, TAG, "Sync Device FAILED - ctx: %s", (char*) ctx);
240         printResultList((const OCProvisionResult_t*) arr, nOfRes);
241     }
242     g_doneCB = true;
243 }
244
245 static void inputPinCB(char* pin, size_t len)
246 {
247     if(!pin || OXM_RANDOM_PIN_SIZE>=len)
248     {
249         OIC_LOG(ERROR, TAG, "inputPinCB invalid parameters");
250         return;
251     }
252
253     printf("   > INPUT PIN: ");
254     for(int ret=0; 1!=ret; )
255     {
256         ret = scanf("%8s", pin);
257         for( ; 0x20<=getchar(); );  // for removing overflow garbages
258                                     // '0x20<=code' is character region
259     }
260 }
261
262 // function(s) for provisioning client using C-level provisioning API
263 static int initProvisionClient(void)
264 {
265     // initialize persistent storage for SVR DB
266     static OCPersistentStorage pstStr =
267     {
268         .open = fopen_prvnMng,
269         .read = fread,
270         .write = fwrite,
271         .close = fclose,
272         .unlink = unlink
273     };
274     if(OC_STACK_OK != OCRegisterPersistentStorageHandler(&pstStr))
275     {
276         OIC_LOG(ERROR, TAG, "OCRegisterPersistentStorageHandler error");
277         return -1;
278     }
279
280     // initialize OC stack and provisioning manager
281     if(OC_STACK_OK != OCInit(NULL, 0, OC_CLIENT_SERVER))
282     {
283         OIC_LOG(ERROR, TAG, "OCStack init error");
284         return -1;
285     }
286
287     if (access(PRVN_DB_FILE_NAME, F_OK) != -1)
288     {
289         printf("************************************************************\n");
290         printf("************Provisioning DB file already exists.************\n");
291         printf("************************************************************\n");
292     }
293     else
294     {
295         printf("*************************************************************\n");
296         printf("************No provisioning DB file, creating new************\n");
297         printf("*************************************************************\n");
298     }
299
300     if(OC_STACK_OK != OCInitPM(PRVN_DB_FILE_NAME))
301     {
302         OIC_LOG(ERROR, TAG, "OC_PM init error");
303         return -1;
304     }
305
306     // register callback function(s) to each OxM
307     OTMCallbackData_t otmcb =
308     {
309         .loadSecretCB = LoadSecretJustWorksCallback,
310         .createSecureSessionCB = CreateSecureSessionJustWorksCallback,
311         .createSelectOxmPayloadCB = CreateJustWorksSelectOxmPayload,
312         .createOwnerTransferPayloadCB = CreateJustWorksOwnerTransferPayload
313     };
314     if(OC_STACK_OK != OCSetOwnerTransferCallbackData(OIC_JUST_WORKS, &otmcb))
315     {
316         OIC_LOG(ERROR, TAG, "OCSetOwnerTransferCallbackData error: OIC_JUST_WORKS");
317         return -1;
318     }
319     otmcb.loadSecretCB = InputPinCodeCallback;
320     otmcb.createSecureSessionCB = CreateSecureSessionRandomPinCallback;
321     otmcb.createSelectOxmPayloadCB = CreatePinBasedSelectOxmPayload;
322     otmcb.createOwnerTransferPayloadCB = CreatePinBasedOwnerTransferPayload;
323     if(OC_STACK_OK != OCSetOwnerTransferCallbackData(OIC_RANDOM_DEVICE_PIN, &otmcb))
324     {
325         OIC_LOG(ERROR, TAG, "OCSetOwnerTransferCallbackData error: OIC_RANDOM_DEVICE_PIN");
326         return -1;
327     }
328     SetInputPinCB(inputPinCB);
329
330     return 0;
331 }
332
333 static int discoverAllDevices(void)
334 {
335     // delete un/owned device lists before updating them
336     if(g_own_list)
337     {
338         OCDeleteDiscoveredDevices(g_own_list);
339         g_own_list = NULL;
340     }
341     if(g_unown_list)
342     {
343         OCDeleteDiscoveredDevices(g_unown_list);
344         g_unown_list = NULL;
345     }
346
347     // call |OCGetDevInfoFromNetwork| API actually
348     printf("   Discovering All Un/Owned Devices on Network..\n");
349     if(OC_STACK_OK != OCGetDevInfoFromNetwork(DISCOVERY_TIMEOUT, &g_own_list, &g_unown_list))
350     {
351         OIC_LOG(ERROR, TAG, "OCGetDevInfoFromNetwork API error");
352         return -1;
353     }
354
355     // display the discovered un/owned lists
356     printf("   > Discovered Owned Devices\n");
357     g_own_cnt = printDevList(g_own_list);
358     printf("   > Discovered Unowned Devices\n");
359     g_unown_cnt = printDevList(g_unown_list);
360
361     return 0;
362 }
363
364
365 static int discoverUnownedDevices(void)
366 {
367     // delete unowned device list before updating it
368     if(g_unown_list)
369     {
370         OCDeleteDiscoveredDevices(g_unown_list);
371         g_unown_list = NULL;
372     }
373
374     // call |OCDiscoverUnownedDevices| API actually
375     printf("   Discovering Only Unowned Devices on Network..\n");
376     if(OC_STACK_OK != OCDiscoverUnownedDevices(DISCOVERY_TIMEOUT, &g_unown_list))
377     {
378         OIC_LOG(ERROR, TAG, "OCDiscoverUnownedDevices API error");
379         return -1;
380     }
381
382     // display the discovered unowned list
383     printf("   > Discovered Unowned Devices\n");
384     g_unown_cnt = printDevList(g_unown_list);
385
386     return 0;
387 }
388
389 static int discoverOwnedDevices(void)
390 {
391     // delete owned device list before updating it
392     if(g_own_list)
393     {
394         OCDeleteDiscoveredDevices(g_own_list);
395         g_own_list = NULL;
396     }
397
398     // call |OCDiscoverOwnedDevices| API actually
399     printf("   Discovering Only Owned Devices on Network..\n");
400     if(OC_STACK_OK != OCDiscoverOwnedDevices(DISCOVERY_TIMEOUT, &g_own_list))
401     {
402         OIC_LOG(ERROR, TAG, "OCDiscoverOwnedDevices API error");
403         return -1;
404     }
405
406     // display the discovered owned list
407     printf("   > Discovered Owned Devices\n");
408     g_own_cnt = printDevList(g_own_list);
409
410     return 0;
411 }
412
413 static int registerDevices(void)
414 {
415     // check |unown_list| for registering devices
416     if(!g_unown_list || 0>=g_unown_cnt)
417     {
418         printf("   > Unowned Device List, to Register Devices, is Empty\n");
419         printf("   > Please Discover Unowned Devices first, with [10|11] Menu\n");
420         return 0;  // normal case
421     }
422
423     // call |OCDoOwnershipTransfer| API actually
424     // calling this API with callback actually acts like blocking
425     // for error checking, the return value saved and printed
426     g_doneCB = false;
427     printf("   Registering All Discovered Unowned Devices..\n");
428     OCStackResult rst = OCDoOwnershipTransfer((void*) g_ctx, g_unown_list, ownershipTransferCB);
429     if(OC_STACK_OK != rst)
430     {
431         OIC_LOG_V(ERROR, TAG, "OCDoOwnershipTransfer API error: %d", rst);
432         return -1;
433     }
434     if(waitCallbackRet())  // input |g_doneCB| flag implicitly
435     {
436         OIC_LOG(ERROR, TAG, "OCProvisionCredentials callback error");
437         return -1;
438     }
439
440     // display the registered result
441     printf("   > Registered Discovered Unowned Devices\n");
442     printf("   > Please Discover Owned Devices for the Registered Result, with [10|12] Menu\n");
443
444     return 0;
445 }
446
447 static int provisionPairwise(void)
448 {
449     // check |own_list| for provisioning pairwise devices
450     if(!g_own_list || 2>g_own_cnt)
451     {
452         printf("   > Owned Device List, to Provision the Pairwise, is Empty\n");
453         printf("   > Please Register Unowned Devices first, with [20] Menu\n");
454         return 0;  // normal case
455     }
456
457     // select two devices for provisioning pairwise devices
458     int dev_num[2] = {0};
459     if(selectTwoDiffNum(&(dev_num[0]), &(dev_num[1]), g_own_cnt, "for Linking Devices"))
460     {
461         OIC_LOG(ERROR, TAG, "selectTwoDiffNum error return");
462         return -1;  // not need to 'goto' |ERROR| before allocating |acl|
463     }
464
465     // create ACL(s) for each selected device
466     OicSecAcl_t* acl[2] = {0};
467     for(int i=0; 2>i; ++i)
468     {
469         acl[i] = createAcl(dev_num[i]);
470         if(!acl[i])
471         {
472             OIC_LOG(ERROR, TAG, "createAcl error return");
473             goto PVPWS_ERROR;
474         }
475     }
476
477     // call |OCProvisionPairwiseDevices| API actually
478     // calling this API with callback actually acts like blocking
479     // for error checking, the return value saved and printed
480     g_doneCB = false;
481     printf("   Provisioning Selected Pairwise Devices..\n");
482     OCStackResult rst =
483             OCProvisionPairwiseDevices((void*) g_ctx,
484                     SYMMETRIC_PAIR_WISE_KEY, OWNER_PSK_LENGTH_128,
485                     getDevInst((const OCProvisionDev_t*) g_own_list, dev_num[0]), acl[0],
486                     getDevInst((const OCProvisionDev_t*) g_own_list, dev_num[1]), acl[1],
487                     provisionPairwiseCB);
488     if(OC_STACK_OK != rst)
489     {
490         OIC_LOG_V(ERROR, TAG, "OCProvisionPairwiseDevices API error: %d", rst);
491         goto PVPWS_ERROR;
492     }
493     if(waitCallbackRet())  // input |g_doneCB| flag implicitly
494     {
495         OIC_LOG(ERROR, TAG, "OCProvisionCredentials callback error");
496         goto PVPWS_ERROR;
497     }
498     OCDeleteACLList(acl[0]);
499     OCDeleteACLList(acl[1]);
500
501     // display the pairwise-provisioned result
502     printf("   > Provisioned Selected Pairwise Devices\n");
503     printf("   > Please Check Device's Status for the Linked Result, with [33] Menu\n");
504
505     return 0;
506
507 PVPWS_ERROR:
508     OCDeleteACLList(acl[0]);
509     OCDeleteACLList(acl[1]);
510     return -1;
511 }
512
513 static int provisionCred(void)
514 {
515     // check |own_list| for provisioning pairwise credentials
516     if(!g_own_list || 2>g_own_cnt)
517     {
518         printf("   > Owned Device List, to Provision Credentials, is Empty\n");
519         printf("   > Please Register Unowned Devices first, with [20] Menu\n");
520         return 0;  // normal case
521     }
522
523     // select two devices for provisioning pairwise credentials
524     int dev_num[2] = {0};
525     if(selectTwoDiffNum(&(dev_num[0]), &(dev_num[1]), g_own_cnt, "for Linking CRED(s)"))
526     {
527         OIC_LOG(ERROR, TAG, "selectTwoDiffNum error return");
528         return -1;
529     }
530
531     printf("   Select PSK length..\n");
532     printf("   1 - 128bit(Default)\n");
533     printf("   2 - 256bit\n");
534     int sizeOption = 0;
535
536     for(int ret=0; 1!=ret; )
537     {
538          ret = scanf("%d",&sizeOption);
539          for( ; 0x20<=getchar(); );  // for removing overflow garbages
540                                     // '0x20<=code' is character region
541     }
542     size_t size = 0;
543
544     switch(sizeOption)
545     {
546         case 1:
547         {
548             size = OWNER_PSK_LENGTH_128;
549             break;
550         }
551         case 2:
552         {
553             size = OWNER_PSK_LENGTH_256;
554             break;
555         }
556         default:
557         {
558             size = OWNER_PSK_LENGTH_128;
559             break;
560         }
561     }
562
563
564     // call |OCProvisionCredentials| API actually
565     // calling this API with callback actually acts like blocking
566     // for error checking, the return value saved and printed
567     g_doneCB = false;
568     printf("   Provisioning Selected Pairwise Credentials..\n");
569     OCStackResult rst =
570             OCProvisionCredentials((void*) g_ctx,
571                     SYMMETRIC_PAIR_WISE_KEY, size,
572                     getDevInst((const OCProvisionDev_t*) g_own_list, dev_num[0]),
573                     getDevInst((const OCProvisionDev_t*) g_own_list, dev_num[1]),
574                     provisionCredCB);
575     if(OC_STACK_OK != rst)
576     {
577         OIC_LOG_V(ERROR, TAG, "OCProvisionCredentials API error: %d", rst);
578         return -1;
579     }
580     if(waitCallbackRet())  // input |g_doneCB| flag implicitly
581     {
582         OIC_LOG(ERROR, TAG, "OCProvisionCredentials callback error");
583         return -1;
584     }
585
586     // display the CRED-provisioned result
587     printf("   > Provisioned Selected Pairwise Crendentials\n");
588     printf("   > Please Check Device's Status for the Linked Result, with [33] Menu\n");
589
590     return 0;
591 }
592
593 static int provisionAcl(void)
594 {
595     // check |own_list| for provisioning access control list
596     if(!g_own_list || 1>g_own_cnt)
597     {
598         printf("   > Owned Device List, to Provision ACL, is Empty\n");
599         printf("   > Please Register Unowned Devices first, with [20] Menu\n");
600         return 0;  // normal case
601     }
602
603     // select device for provisioning access control list
604     int dev_num = 0;
605     for( ; ; )
606     {
607         printf("   > Enter Device Number, for Provisioning ACL: ");
608         for(int ret=0; 1!=ret; )
609         {
610             ret = scanf("%d", &dev_num);
611             for( ; 0x20<=getchar(); );  // for removing overflow garbages
612                                         // '0x20<=code' is character region
613         }
614         if(0<dev_num && g_own_cnt>=dev_num)
615         {
616             break;
617         }
618         printf("     Entered Wrong Number. Please Enter Again\n");
619     }
620
621     // create ACL for selected device
622     OicSecAcl_t* acl = NULL;
623     acl = createAcl(dev_num);
624     if(!acl)
625     {
626         OIC_LOG(ERROR, TAG, "createAcl error return");
627         goto PVACL_ERROR;
628     }
629
630     // call |OCProvisionACL| API actually
631     // calling this API with callback actually acts like blocking
632     // for error checking, the return value saved and printed
633     g_doneCB = false;
634     printf("   Provisioning Selected ACL..\n");
635     OCProvisionDev_t* dev = getDevInst((const OCProvisionDev_t*) g_own_list, dev_num);
636     if(!dev)
637     {
638         OIC_LOG(ERROR, TAG, "provisionAcl: device instance empty");
639         goto PVACL_ERROR;
640     }
641     OCStackResult rst = OCProvisionACL((void*) g_ctx, dev, acl, provisionAclCB);
642     if(OC_STACK_OK != rst)
643     {
644         OIC_LOG_V(ERROR, TAG, "OCProvisionACL API error: %d", rst);
645         goto PVACL_ERROR;
646     }
647     if(waitCallbackRet())  // input |g_doneCB| flag implicitly
648     {
649         OIC_LOG(ERROR, TAG, "OCProvisionCredentials callback error");
650         goto PVACL_ERROR;
651     }
652     OCDeleteACLList(acl);  // after here |acl| points nothing
653
654     // display the ACL-provisioned result
655     printf("   > Provisioned Selected ACL\n");
656
657     return 0;
658
659 PVACL_ERROR:
660     OCDeleteACLList(acl);  // after here |acl| points nothing
661     return -1;
662 }
663
664 static int provisionDirectPairing(void)
665 {
666     // check |own_list| for provisioning direct-pairing
667     if(!g_own_list || 1>g_own_cnt)
668     {
669         printf("   > Owned Device List, to Provision ACL, is Empty\n");
670         printf("   > Please Register Unowned Devices first, with [20] Menu\n");
671         return 0;  // normal case
672     }
673
674     // select device for provisioning direct-pairing
675     int dev_num = 0;
676     for( ; ; )
677     {
678         printf("   > Enter Device Number, for Provisioning Direct-Pairing: ");
679         for(int ret=0; 1!=ret; )
680         {
681             ret = scanf("%d", &dev_num);
682             for( ; 0x20<=getchar(); );  // for removing overflow garbages
683                                         // '0x20<=code' is character region
684         }
685         if(0<dev_num && g_own_cnt>=dev_num)
686         {
687             break;
688         }
689         printf("     Entered Wrong Number. Please Enter Again\n");
690     }
691
692     // create Direct-Pairing Configuration(PIN, PDACL) for selected device
693     // TODO: default acl -> input from user !
694     OicSecPconf_t pconf;
695     memset(&pconf, 0, sizeof(OicSecPconf_t));
696
697     // set enable dp
698     pconf.edp = true;
699
700     // set default supported PRM types
701     pconf.prmLen = sizeof(SUPPORTED_PRMS)/sizeof(OicSecPrm_t);
702     pconf.prm = (OicSecPrm_t *)OICCalloc(pconf.prmLen, sizeof(OicSecPrm_t));
703     if(pconf.prm)
704     {
705         for (size_t i=0; i<pconf.prmLen; i++)
706         {
707             pconf.prm[i] = SUPPORTED_PRMS[i];
708         }
709     }
710     else
711     {
712         OIC_LOG(ERROR, TAG, "create prm error return");
713         goto PVDP_ERROR;
714     }
715
716     // set default pin
717     const char DP_DEFAULT_PIN[] = "00000000";
718     memcpy(pconf.pin.val, DP_DEFAULT_PIN, DP_PIN_LENGTH);
719
720     // set default pdacl
721     pconf.pdacls = createPdAcl(dev_num);
722     if(!pconf.pdacls)
723     {
724         OIC_LOG(ERROR, TAG, "createPdAcl error return");
725         goto PVDP_ERROR;
726     }
727
728     // call |OCProvisionDirectPairing| API actually
729     // calling this API with callback actually acts like blocking
730     // for error checking, the return value saved and printed
731     g_doneCB = false;
732     printf("   Atempt Direct-Pairing Provisioning (PIN : [%s])..\n", (char*)pconf.pin.val);
733     OCStackResult rst = OCProvisionDirectPairing((void*) g_ctx,
734                                        getDevInst((const OCProvisionDev_t*) g_own_list, dev_num),
735                                        &pconf, provisionDPCB);
736     if(OC_STACK_OK != rst)
737     {
738         OIC_LOG_V(ERROR, TAG, "OCProvisionDirectPairing API error: %d", rst);
739         if (OC_STACK_UNAUTHORIZED_REQ == rst)
740         {
741             OIC_LOG(ERROR, TAG, "Target Server NOT Support Direct-Pairing !!! (DPC == false)");
742         }
743         goto PVDP_ERROR;
744     }
745     if(waitCallbackRet())  // input |g_doneCB| flag implicitly
746     {
747         OIC_LOG(ERROR, TAG, "OCProvisionCredentials callback error");
748         goto PVDP_ERROR;
749     }
750     OCDeletePdAclList(pconf.pdacls);
751
752     // display the PCONF-provisioned result
753     printf("   > SUCCESS to provision Direct-Pairing !!\n");
754
755     return 0;
756
757 PVDP_ERROR:
758     OCDeletePdAclList(pconf.pdacls);  // after here |acl| points nothing
759     return -1;
760 }
761
762 static int checkLinkedStatus(void)
763 {
764     // check |own_list| for checking selected link status on PRVN DB
765     if(!g_own_list || 1>g_own_cnt)
766     {
767         printf("   > Owned Device List, to Check Linked Status on PRVN DB, is Empty\n");
768         printf("   > Please Register Unowned Devices first, with [20] Menu\n");
769         return 0;  // normal case
770     }
771
772     // select device for checking selected link status on PRVN DB
773     int dev_num = 0;
774     for( ; ; )
775     {
776         printf("   > Enter Device Number, for Checking Linked Status on PRVN DB: ");
777         for(int ret=0; 1!=ret; )
778         {
779             ret = scanf("%d", &dev_num);
780             for( ; 0x20<=getchar(); );  // for removing overflow garbages
781                                         // '0x20<=code' is character region
782         }
783         if(0<dev_num && g_own_cnt>=dev_num)
784         {
785             break;
786         }
787         printf("     Entered Wrong Number. Please Enter Again\n");
788     }
789
790     // call |OCGetLinkedStatus| API actually
791     printf("   Checking Selected Link Status on PRVN DB..\n");
792     OCUuidList_t* dvid_lst = NULL;
793     size_t dvid_cnt = 0;
794     OCProvisionDev_t* dev = getDevInst((const OCProvisionDev_t*)g_own_list, dev_num);
795     if(!dev || !dev->doxm)
796     {
797         OIC_LOG(ERROR, TAG, "checkLinkedStatus: device instance empty");
798         goto CKLST_ERROR;
799     }
800
801     if(OC_STACK_OK !=
802             OCGetLinkedStatus(
803                     &dev->doxm->deviceID,
804                     &dvid_lst, &dvid_cnt))  // allow empty list
805     {
806         OIC_LOG(ERROR, TAG, "OCGetLinkedStatus API error");
807         goto CKLST_ERROR;
808     }
809
810     // display the linked status result
811     printf("   > Checked Selected Link Status on PRVN DB\n");
812     if(!dvid_lst || !dvid_cnt)  // |size_t| is unsigned
813     {
814         printf("     Linked Device List is Empty..\n");
815         return 0;  // normal case
816     }
817     if(dvid_cnt != printUuidList((const OCUuidList_t*) dvid_lst))
818     {
819         OIC_LOG(ERROR, TAG, "printUuidList error return");
820         goto CKLST_ERROR;
821     }
822     OCDeleteUuidList(dvid_lst);
823
824     return 0;
825
826 CKLST_ERROR:
827     OCDeleteUuidList(dvid_lst);
828     return -1;
829 }
830
831 static int getCred(void)
832 {
833     // check |own_list| for checking selected link status on PRVN DB
834     if(!g_own_list || 1>g_own_cnt)
835     {
836         printf("   > Owned Device List, to Check Linked Status on PRVN DB, is Empty\n");
837         printf("   > Please Register Unowned Devices first, with [20] Menu\n");
838         return 0;  // normal case
839     }
840
841     // select device for checking selected link status on PRVN DB
842     int dev_num = 0;
843     for( ; ; )
844     {
845         printf("   > Enter Device Number, for Checking Linked Status on PRVN DB: ");
846         for(int ret=0; 1!=ret; )
847         {
848             ret = scanf("%d", &dev_num);
849             for( ; 0x20<=getchar(); );  // for removing overflow garbages
850                                         // '0x20<=code' is character region
851         }
852         if(0<dev_num && g_own_cnt>=dev_num)
853         {
854             break;
855         }
856         printf("     Entered Wrong Number. Please Enter Again\n");
857     }
858
859     // call |getDevInst| API actually
860     // calling this API with callback actually acts like blocking
861     // for error checking, the return value saved and printed
862     g_doneCB = false;
863     OCProvisionDev_t* dev = getDevInst((const OCProvisionDev_t*) g_own_list, dev_num);
864     if(!dev)
865     {
866         OIC_LOG(ERROR, TAG, "getDevInst: device instance empty");
867         goto PVACL_ERROR;
868     }
869     OCStackResult rst = OCGetCredResource((void*) g_ctx, dev, getCredCB);
870     if(OC_STACK_OK != rst)
871     {
872         OIC_LOG_V(ERROR, TAG, "OCGetCred API error: %d", rst);
873         goto PVACL_ERROR;
874     }
875     if(waitCallbackRet())  // input |g_doneCB| flag implicitly
876     {
877         OIC_LOG(ERROR, TAG, "OCGetCredResource callback error");
878         goto PVACL_ERROR;
879     }
880
881     // display the result of get credential
882     printf("   > Get Cred SUCCEEDED\n");
883
884     return 0;
885
886 PVACL_ERROR:
887     return -1;
888 }
889
890 static int getAcl(void)
891 {
892     // check |own_list| for checking selected link status on PRVN DB
893     if(!g_own_list || 1>g_own_cnt)
894     {
895         printf("   > Owned Device List, to Check Linked Status on PRVN DB, is Empty\n");
896         printf("   > Please Register Unowned Devices first, with [20] Menu\n");
897         return 0;  // normal case
898     }
899
900     // select device for checking selected link status on PRVN DB
901     int dev_num = 0;
902     for( ; ; )
903     {
904         printf("   > Enter Device Number, for Checking Linked Status on PRVN DB: ");
905         for(int ret=0; 1!=ret; )
906         {
907             ret = scanf("%d", &dev_num);
908             for( ; 0x20<=getchar(); );  // for removing overflow garbages
909                                         // '0x20<=code' is character region
910         }
911         if(0<dev_num && g_own_cnt>=dev_num)
912         {
913             break;
914         }
915         printf("     Entered Wrong Number. Please Enter Again\n");
916     }
917
918     // call |getDevInst| API actually
919     // calling this API with callback actually acts like blocking
920     // for error checking, the return value saved and printed
921     g_doneCB = false;
922     OCProvisionDev_t* dev = getDevInst((const OCProvisionDev_t*) g_own_list, dev_num);
923     if(!dev)
924     {
925         OIC_LOG(ERROR, TAG, "getDevInst: device instance empty");
926         goto PVACL_ERROR;
927     }
928     OCStackResult rst = OCGetACLResource((void*) g_ctx, dev, getAclCB);
929     if(OC_STACK_OK != rst)
930     {
931         OIC_LOG_V(ERROR, TAG, "OCGetACLResource API error: %d", rst);
932
933         goto PVACL_ERROR;
934     }
935     if(waitCallbackRet())  // input |g_doneCB| flag implicitly
936     {
937         OIC_LOG(ERROR, TAG, "OCGetACLResource callback error");
938         goto PVACL_ERROR;
939     }
940
941     // display the result of get credential
942     printf("   > Get ACL SUCCEEDED\n");
943
944     return 0;
945
946 PVACL_ERROR:
947     return -1;
948 }
949
950 static int unlinkPairwise(void)
951 {
952     // check |own_list| for unlinking pairwise devices
953     if(!g_own_list || 2>g_own_cnt)
954     {
955         printf("   > Owned Device List, to Unlink the Pairwise, is Empty\n");
956         printf("   > Please Register Unowned Devices first, with [20] Menu\n");
957         return 0;  // normal case
958     }
959
960     // select two devices for unlinking pairwise devices
961     int dev_num[2] = {0};
962     if(selectTwoDiffNum(&(dev_num[0]), &(dev_num[1]), g_own_cnt, "for Unlinking Devices"))
963     {
964         OIC_LOG(ERROR, TAG, "selectTwoDiffNum error return");
965         return -1;
966     }
967
968     // call |OCUnlinkDevices| API actually
969     // calling this API with callback actually acts like blocking
970     // for error checking, the return value saved and printed
971     g_doneCB = false;
972     printf("   Unlinking Selected Pairwise Devices..\n");
973     OCStackResult rst =
974             OCUnlinkDevices((void*) g_ctx,
975                     getDevInst((const OCProvisionDev_t*) g_own_list, dev_num[0]),
976                     getDevInst((const OCProvisionDev_t*) g_own_list, dev_num[1]),
977                     unlinkDevicesCB);
978     if(OC_STACK_OK != rst)
979     {
980         OIC_LOG_V(ERROR, TAG, "OCUnlinkDevices API error: %d", rst);
981         return -1;
982     }
983     if(waitCallbackRet())  // input |g_doneCB| flag implicitly
984     {
985         OIC_LOG(ERROR, TAG, "OCProvisionCredentials callback error");
986         return -1;
987     }
988
989     // display the pairwise-unlinked result
990     printf("   > Unlinked Selected Pairwise Devices\n");
991     printf("   > Please Check Device's Status for the Unlinked Result, with [33] Menu\n");
992
993     return 0;
994 }
995
996 static int removeDevice(void)
997 {
998     // check |own_list| for removing device
999     if(!g_own_list || 1>g_own_cnt)
1000     {
1001         printf("   > Owned Device List, to Remove Device, is Empty\n");
1002         printf("   > Please Register Unowned Devices first, with [20] Menu\n");
1003         return 0;  // normal case
1004     }
1005
1006     // select device for removing it
1007     int dev_num = 0;
1008     for( ; ; )
1009     {
1010         printf("   > Enter Device Number, for Removing Device: ");
1011         for(int ret=0; 1!=ret; )
1012         {
1013             ret = scanf("%d", &dev_num);
1014             for( ; 0x20<=getchar(); );  // for removing overflow garbages
1015                                         // '0x20<=code' is character region
1016         }
1017         if(0<dev_num && g_own_cnt>=dev_num)
1018         {
1019             break;
1020         }
1021         printf("     Entered Wrong Number. Please Enter Again\n");
1022     }
1023
1024     // call |OCRemoveDevice| API actually
1025     // calling this API with callback actually acts like blocking
1026     // for error checking, the return value saved and printed
1027     g_doneCB = false;
1028     printf("   Removing Selected Owned Device..\n");
1029     OCStackResult rst =
1030             OCRemoveDevice((void*) g_ctx, DISCOVERY_TIMEOUT,
1031                     getDevInst((const OCProvisionDev_t*) g_own_list, dev_num), removeDeviceCB);
1032     if(OC_STACK_OK != rst)
1033     {
1034         OIC_LOG_V(ERROR, TAG, "OCRemoveDevice API error: %d", rst);
1035         return -1;
1036     }
1037     if(waitCallbackRet())  // input |g_doneCB| flag implicitly
1038     {
1039         OIC_LOG(ERROR, TAG, "OCProvisionCredentials callback error");
1040         return -1;
1041     }
1042
1043     // display the removed result
1044     printf("   > Removed Selected Owned Device\n");
1045     printf("   > Please Discover Owned Devices for the Registered Result, with [10|12] Menu\n");
1046
1047     return 0;
1048 }
1049
1050 static int removeDeviceWithUuid(void)
1051 {
1052     char strUuid[64] = {0};
1053     OicUuid_t revUuid;
1054     printf("Input the UUID : ");
1055     for(int ret=0; 1!=ret; )
1056     {
1057         ret = scanf("%64s", strUuid);
1058         for( ; 0x20<=getchar(); );  // for removing overflow garbages
1059                                     // '0x20<=code' is character region
1060     }
1061     OCStackResult rst = ConvertStrToUuid(strUuid, &revUuid);
1062     if(OC_STACK_OK != rst)
1063     {
1064         OIC_LOG_V(ERROR, TAG, "ConvertStrToUuid API error: %d", rst);
1065         return -1;
1066     }
1067
1068     rst = OCRemoveDeviceWithUuid("RemoveDeviceWithUUID", DISCOVERY_TIMEOUT, &revUuid, removeDeviceCB);
1069     if(OC_STACK_OK != rst)
1070     {
1071         OIC_LOG_V(ERROR, TAG, "OCRemoveDeviceWithUuid API error: %d", rst);
1072         return -1;
1073     }
1074
1075     g_doneCB = false;
1076     if(waitCallbackRet())  // input |g_doneCB| flag implicitly
1077     {
1078         OIC_LOG(ERROR, TAG, "OCRemoveDeviceWithUuid callback error");
1079         return -1;
1080     }
1081
1082     // display the removed result
1083     printf("   > Removed %s Device\n", strUuid);
1084     printf("   > Please Discover Owned Devices for the Registered Result, with [10|12] Menu\n");
1085
1086     return 0;
1087 }
1088
1089 static int resetDevice(void)
1090 {
1091     // check |own_list| for removing device
1092     if (!g_own_list || 1 > g_own_cnt)
1093     {
1094         printf("   > Owned Device List, to Reset Device, is Empty\n");
1095         printf("   > Please Register Unowned Devices first, with [20] Menu\n");
1096         return 0;
1097     }
1098
1099     // select device for removing it
1100     int dev_num = 0;
1101     for ( ; ; )
1102     {
1103         printf("   > Enter Device Number, for Resetting Device: ");
1104         for (int ret = 0; 1 != ret; )
1105         {
1106             ret = scanf("%d", &dev_num);
1107             for ( ; 0x20 <= getchar() ; );  // for removing overflow garbages
1108                                             // '0x20 <= code' is character region
1109         }
1110         if (0 < dev_num && g_own_cnt >= dev_num)
1111         {
1112             break;
1113         }
1114         printf("     Entered Wrong Number. Please Enter Again\n");
1115     }
1116
1117     g_doneCB = false;
1118     printf("   Resetting Selected Owned Device..\n");
1119
1120     OCStackResult rst = OCResetDevice((void *) g_ctx, DISCOVERY_TIMEOUT,
1121                     getDevInst((const OCProvisionDev_t *) g_own_list, dev_num), syncDeviceCB);
1122     if (OC_STACK_OK != rst)
1123     {
1124         OIC_LOG_V(ERROR, TAG, "OCResetDevice API error: %d", rst);
1125         return -1;
1126     }
1127
1128     if (waitCallbackRet())  // input |g_doneCB| flag implicitly
1129     {
1130         OIC_LOG(ERROR, TAG, "OCProvisionCredentials callback error");
1131         return -1;
1132     }
1133
1134     // display the removed result
1135     printf("   > Reset Selected Owned Device SUCCEEDED\n");
1136     printf("   > Please Discover Owned Devices for the Registered Result, with [10|12] Menu\n");
1137
1138     return 0;
1139 }
1140
1141 static OicSecAcl_t* createAcl(const int dev_num)
1142 {
1143     if(0>=dev_num || g_own_cnt<dev_num)
1144     {
1145         OIC_LOG(ERROR, TAG, "createAcl invalid parameters");
1146         return NULL;  // not need to 'goto' |ERROR| before allocating |acl|
1147     }
1148
1149     // allocate memory for |acl| struct
1150     printf("   **** Create ACL for the Selected Device[%d]\n", dev_num);
1151     OicSecAcl_t* acl = (OicSecAcl_t*) OICCalloc(1, sizeof(OicSecAcl_t));
1152     if(!acl)
1153     {
1154         OIC_LOG(ERROR, TAG, "createAcl: OICCalloc error return");
1155         return NULL;  // not need to 'goto' |ERROR| before allocating |acl|
1156     }
1157     OicSecAce_t* ace = (OicSecAce_t*) OICCalloc(1, sizeof(OicSecAce_t));
1158     if(!ace)
1159     {
1160         OIC_LOG(ERROR, TAG, "createAcl: OICCalloc error return");
1161         return NULL;  // not need to 'goto' |ERROR| before allocating |acl|
1162     }
1163     LL_APPEND(acl->aces, ace);
1164
1165     // enter |subject| device number
1166     int num = 0;
1167     for( ; ; )
1168     {
1169         printf("   > [A] Enter Subject Device Number: ");
1170         for(int ret=0; 1!=ret; )
1171         {
1172             ret = scanf("%d", &num);
1173             for( ; 0x20<=getchar(); );  // for removing overflow garbages
1174                                         // '0x20<=code' is character region
1175         }
1176         if(0<num && g_own_cnt>=num && dev_num!=num)
1177         {
1178             break;
1179         }
1180         printf("     Entered Wrong Number. Please Enter Again\n");
1181     }
1182
1183     OCProvisionDev_t* dev = getDevInst((const OCProvisionDev_t*)g_own_list, num);
1184     if(!dev || !dev->doxm)
1185     {
1186         OIC_LOG(ERROR, TAG, "createAcl: device instance empty");
1187         goto CRACL_ERROR;
1188     }
1189     memcpy(&ace->subjectuuid, &dev->doxm->deviceID, UUID_LENGTH);
1190
1191     // enter number of |resources| in 'accessed' device
1192     for( ; ; )
1193     {
1194         printf("   > [B] Enter Number of Accessed Resources (under 16): ");
1195                 // '16' is |ACL_RESRC_MAX_NUM|
1196         for(int ret=0; 1!=ret; )
1197         {
1198             ret = scanf("%d", &num);
1199             for( ; 0x20<=getchar(); );  // for removing overflow garbages
1200                                         // '0x20<=code' is character region
1201         }
1202         if(0<num && ACL_RESRC_MAX_NUM>=num)
1203         {
1204             break;
1205         }
1206         printf("     Entered Wrong Number. Please Enter under 16 Again\n");
1207                 // '16' is |ACL_RESRC_MAX_NUM|
1208     }
1209
1210     // enter actually each 'accessed' |resources| name
1211     printf("         Enter Each Accessed Resource Name (each under 128 char)\n");
1212             // '128' is ACL_RESRC_MAX_LEN
1213
1214     char rsrc_in[ACL_RESRC_MAX_LEN+1] = {0};  // '1' for null termination
1215     for(int i = 0; num > i; ++i)
1216     {
1217         OicSecRsrc_t* rsrc = (OicSecRsrc_t*)OICCalloc(1, sizeof(OicSecRsrc_t));
1218         if(!rsrc)
1219         {
1220             OIC_LOG(ERROR, TAG, "createAcl: OICCalloc error return");
1221             goto CRACL_ERROR;
1222         }
1223
1224         printf("         Enter Accessed Resource[%d] Name: (e.g. /a/led)", i+1);
1225         for(int ret=0; 1!=ret; )
1226         {
1227             ret = scanf("%128s", rsrc_in);  // '128' is ACL_RESRC_MAX_LEN
1228             for( ; 0x20<=getchar(); );  // for removing overflow garbages
1229                                         // '0x20<=code' is character region
1230         }
1231         size_t len = strlen(rsrc_in)+1;  // '1' for null termination
1232         rsrc->href = (char*) OICCalloc(len, sizeof(char));
1233         if(!rsrc)
1234         {
1235             OIC_LOG(ERROR, TAG, "createAcl: OICCalloc error return");
1236             goto CRACL_ERROR;
1237         }
1238         OICStrcpy(rsrc->href, len, rsrc_in);
1239
1240         int arrLen = 0;
1241         while(1)
1242         {
1243             printf("         Enter Number of resource type for [%s] : ", rsrc->href);
1244             for(int ret=0; 1!=ret; )
1245             {
1246                 ret = scanf("%d", &arrLen);
1247                 for( ; 0x20<=getchar(); );  // for removing overflow garbages
1248                                             // '0x20<=code' is character region
1249             }
1250             if(0 < arrLen && ACL_RESRC_ARRAY_SIZE >= arrLen)
1251             {
1252                 break;
1253             }
1254             printf("     Entered Wrong Number. Please Enter under %d Again\n", ACL_RESRC_ARRAY_SIZE);
1255         }
1256
1257         rsrc->typeLen = arrLen;
1258         rsrc->types = (char**)OICCalloc(arrLen, sizeof(char*));
1259         if(!rsrc->types)
1260         {
1261             OIC_LOG(ERROR, TAG, "createAcl: OICCalloc error return");
1262             goto CRACL_ERROR;
1263         }
1264
1265         for(int i = 0; i < arrLen; i++)
1266         {
1267             printf("         Enter ResourceType[%d] Name (e.g. core.led): ", i+1);
1268             for(int ret=0; 1!=ret; )
1269             {
1270                 ret = scanf("%128s", rsrc_in);  // '128' is ACL_RESRC_MAX_LEN
1271                 for( ; 0x20<=getchar(); );  // for removing overflow garbages
1272                                             // '0x20<=code' is character region
1273             }
1274             rsrc->types[i] = OICStrdup(rsrc_in);
1275             if(!rsrc->types[i])
1276             {
1277                 OIC_LOG(ERROR, TAG, "createAcl: OICStrdup error return");
1278                 goto CRACL_ERROR;
1279             }
1280         }
1281
1282         while(1)
1283         {
1284             printf("         Enter Number of interface for [%s]: ", rsrc->href);
1285             for(int ret=0; 1!=ret; )
1286             {
1287                 ret = scanf("%d", &arrLen);
1288                 for( ; 0x20<=getchar(); );  // for removing overflow garbages
1289                                             // '0x20<=code' is character region
1290             }
1291             if(0 < arrLen && ACL_RESRC_ARRAY_SIZE >= arrLen)
1292             {
1293                 break;
1294             }
1295             printf("     Entered Wrong Number. Please Enter under %d Again\n", ACL_RESRC_ARRAY_SIZE);
1296         }
1297
1298         rsrc->interfaceLen = arrLen;
1299         rsrc->interfaces = (char**)OICCalloc(arrLen, sizeof(char*));
1300         if(!rsrc->interfaces)
1301         {
1302             OIC_LOG(ERROR, TAG, "createAcl: OICCalloc error return");
1303             goto CRACL_ERROR;
1304         }
1305
1306         for(int i = 0; i < arrLen; i++)
1307         {
1308             printf("         Enter Interface[%d] Name (e.g. oic.if.baseline): ", i+1);
1309             for(int ret=0; 1!=ret; )
1310             {
1311                 ret = scanf("%128s", rsrc_in);  // '128' is ACL_RESRC_MAX_LEN
1312                 for( ; 0x20<=getchar(); );  // for removing overflow garbages
1313                                             // '0x20<=code' is character region
1314             }
1315             rsrc->interfaces[i] = OICStrdup(rsrc_in);
1316             if(!rsrc->interfaces[i])
1317             {
1318                 OIC_LOG(ERROR, TAG, "createAcl: OICStrdup error return");
1319                 goto CRACL_ERROR;
1320             }
1321         }
1322
1323         LL_APPEND(ace->resources, rsrc);
1324     }
1325
1326     // enter |permission| for this access
1327     printf("   > [C] Enter Permission for This Access\n");
1328     uint16_t pmsn = PERMISSION_FULL_CONTROL;  // default full permission
1329     uint16_t pmsn_msk = PERMISSION_CREATE;  // default permission mask
1330     for(int i=0; ACL_PEMISN_CNT>i; ++i)
1331     {
1332         char ans = 0;
1333         for( ; ; )
1334         {
1335             printf("         Enter %s Permission (y/n): ", ACL_PEMISN[i]);
1336             for(int ret=0; 1!=ret; )
1337             {
1338                 ret = scanf("%c", &ans);
1339                 for( ; 0x20<=getchar(); );  // for removing overflow garbages
1340                                             // '0x20<=code' is character region
1341             }
1342             if('y'==ans || 'Y'==ans || 'n'==ans|| 'N'==ans)
1343             {
1344                 ans &= ~0x20;  // for masking lower case, 'y/n'
1345                 break;
1346             }
1347             printf("         Entered Wrong Answer. Please Enter 'y/n' Again\n");
1348         }
1349         if('N' == ans)  // masked lower case, 'n'
1350         {
1351             pmsn -= pmsn_msk;
1352         }
1353         pmsn_msk <<= 1;
1354     }
1355     ace->permission = pmsn;
1356
1357     return acl;
1358
1359 CRACL_ERROR:
1360     OCDeleteACLList(acl);  // after here |acl| points nothing
1361     return NULL;
1362 }
1363
1364 static OicSecPdAcl_t* createPdAcl(const int dev_num)
1365 {
1366     if(0>=dev_num || g_own_cnt<dev_num)
1367     {
1368         OIC_LOG(ERROR, TAG, "createAcl invalid parameters");
1369         return NULL;  // not need to 'goto' |ERROR| before allocating |acl|
1370     }
1371
1372     // allocate memory for |pdacl| struct
1373     printf("   **** Create PDACL for the Selected Device[%d]\n", dev_num);
1374     OicSecPdAcl_t* pdAcl = (OicSecPdAcl_t*) OICCalloc(1, sizeof(OicSecPdAcl_t));
1375     if(!pdAcl)
1376     {
1377         OIC_LOG(ERROR, TAG, "createAcl: OICCalloc error return");
1378         return NULL;  // not need to 'goto' |ERROR| before allocating |acl|
1379     }
1380
1381
1382     // number of resources
1383     char rsrc_in[][ACL_RESRC_MAX_LEN+1] = {"*", "/rsrc/*"};
1384     pdAcl->resourcesLen = 1;
1385
1386     // resource
1387     int num = pdAcl->resourcesLen;
1388     pdAcl->resources = (char**) OICCalloc(num, sizeof(char*));
1389     if(!pdAcl->resources)
1390     {
1391         OIC_LOG(ERROR, TAG, "createPdAcl: OICCalloc error return");
1392         goto CRPDACL_ERROR;
1393     }
1394     for(int i=0; num>i; ++i)
1395     {
1396         size_t len = strlen(rsrc_in[i])+1;  // '1' for null termination
1397         char* rsrc = (char*) OICCalloc(len, sizeof(char));
1398         if(!rsrc)
1399         {
1400             OIC_LOG(ERROR, TAG, "createPdAcl: OICCalloc error return");
1401             goto CRPDACL_ERROR;
1402         }
1403         OICStrcpy(rsrc, len, rsrc_in[i]);
1404         pdAcl->resources[i] = rsrc;  // after here, |rsrc| points nothing
1405     }
1406
1407     // permission
1408     pdAcl->permission = PERMISSION_FULL_CONTROL;
1409
1410     return pdAcl;
1411
1412 CRPDACL_ERROR:
1413     OCDeletePdAclList(pdAcl);
1414     return NULL;
1415 }
1416
1417 static OCProvisionDev_t* getDevInst(const OCProvisionDev_t* dev_lst, const int dev_num)
1418 {
1419     if(!dev_lst || 0>=dev_num)
1420     {
1421         printf("     Device List is Empty..\n");
1422         return NULL;
1423     }
1424
1425     OCProvisionDev_t* lst = (OCProvisionDev_t*) dev_lst;
1426     for(int i=0; lst; )
1427     {
1428         if(dev_num == ++i)
1429         {
1430             return lst;
1431         }
1432         lst = lst->next;
1433     }
1434
1435     return NULL;  // in here |lst| is always |NULL|
1436 }
1437
1438 static int printDevList(const OCProvisionDev_t* dev_lst)
1439 {
1440     if(!dev_lst)
1441     {
1442         printf("     Device List is Empty..\n\n");
1443         return 0;
1444     }
1445
1446     OCProvisionDev_t* lst = (OCProvisionDev_t*) dev_lst;
1447     int lst_cnt = 0;
1448     for( ; lst; )
1449     {
1450         printf("     [%d] ", ++lst_cnt);
1451         printUuid((const OicUuid_t*) &lst->doxm->deviceID);
1452         printf("\n");
1453         lst = lst->next;
1454     }
1455     printf("\n");
1456
1457     return lst_cnt;
1458 }
1459
1460 static size_t printUuidList(const OCUuidList_t* uid_lst)
1461 {
1462     if(!uid_lst)
1463     {
1464         printf("     Device List is Empty..\n\n");
1465         return 0;
1466     }
1467
1468     OCUuidList_t* lst = (OCUuidList_t*) uid_lst;
1469     size_t lst_cnt = 0;
1470     for( ; lst; )
1471     {
1472         printf("     [%zu] ", ++lst_cnt);
1473         printUuid((const OicUuid_t*) &lst->dev);
1474         printf("\n");
1475         lst = lst->next;
1476     }
1477     printf("\n");
1478
1479     return lst_cnt;
1480 }
1481
1482 static int printResultList(const OCProvisionResult_t* rslt_lst, const int rslt_cnt)
1483 {
1484     if(!rslt_lst || 0>=rslt_cnt)
1485     {
1486         printf("     Device List is Empty..\n\n");
1487         return 0;
1488     }
1489
1490     int lst_cnt = 0;
1491     for( ; rslt_cnt>lst_cnt; ++lst_cnt)
1492     {
1493         printf("     [%d] ", lst_cnt+1);
1494         printUuid((const OicUuid_t*) &rslt_lst[lst_cnt].deviceId);
1495         printf(" - result: %d\n", rslt_lst[lst_cnt].res);
1496     }
1497     printf("\n");
1498
1499     return lst_cnt;
1500 }
1501
1502 static void printUuid(const OicUuid_t* uid)
1503 {
1504     for(int i=0; i<UUID_LENGTH; )
1505     {
1506         printf("%02X", (*uid).id[i++]);
1507         if(i==4 || i==6 || i==8 || i==10)  // canonical format for UUID has '8-4-4-4-12'
1508         {
1509             printf("-");
1510         }
1511     }
1512 }
1513
1514 static FILE* fopen_prvnMng(const char* path, const char* mode)
1515 {
1516     (void)path;  // unused |path| parameter
1517
1518     // input |g_svr_db_fname| internally by force, not using |path| parameter
1519     // because |OCPersistentStorage::open| is called |OCPersistentStorage| internally
1520     // with its own |SVR_DB_FILE_NAME|
1521     return fopen(SVR_DB_FILE_NAME, mode);
1522 }
1523
1524 static int waitCallbackRet(void)
1525 {
1526     for(int i=0; !g_doneCB && CALLBACK_TIMEOUT>i; ++i)
1527     {
1528         sleep(1);
1529         if(OC_STACK_OK != OCProcess())
1530         {
1531             OIC_LOG(ERROR, TAG, "OCStack process error");
1532             return -1;
1533         }
1534     }
1535
1536     return 0;
1537 }
1538
1539 static int selectTwoDiffNum(int* a, int* b, const int max, const char* str)
1540 {
1541     if(!a || !b || 2>max || !str)
1542     {
1543         return -1;
1544     }
1545
1546     for( ; ; )
1547     {
1548         for(int i=0; 2>i; ++i)
1549         {
1550             int* num = 0==i?a:b;
1551             for( ; ; )
1552             {
1553                 printf("   > Enter Device[%d] Number, %s: ", i+1, str);
1554                 for(int ret=0; 1!=ret; )
1555                 {
1556                     ret = scanf("%d", num);
1557                     for( ; 0x20<=getchar(); );  // for removing overflow garbages
1558                                                 // '0x20<=code' is character region
1559                 }
1560                 if(0<*num && max>=*num)
1561                 {
1562                     break;
1563                 }
1564                 printf("     Entered Wrong Number. Please Enter Again\n");
1565             }
1566         }
1567         if(*a != *b)
1568         {
1569             printf("\n");
1570             return 0;
1571         }
1572     }
1573
1574     return -1;
1575 }
1576
1577 static void printMenu(void)
1578 {
1579     printf("************************************************************\n");
1580     printf("****** OIC Provisioning Client with using C-level API ******\n");
1581     printf("************************************************************\n\n");
1582
1583     printf("** [A] DISCOVER DEVICES ON NETWORK\n");
1584     printf("** 10. Discover All Un/Owned Devices on Network\n");
1585     printf("** 11. Discover Only Unowned Devices on Network\n");
1586     printf("** 12. Discover Only Owned Devices on Network\n\n");
1587
1588     printf("** [B] REGISTER/OWN ALL DISCOVERED UNOWNED DEVICES\n");
1589     printf("** 20. Register/Own All Discovered Unowned Devices\n\n");
1590
1591     printf("** [C] PROVISION/LINK PAIRWISE THINGS\n");
1592     printf("** 30. Provision/Link Pairwise Things\n");
1593     printf("** 31. Provision Credentials for Pairwise Things\n");
1594     printf("** 32. Provision the Selected Access Control List(ACL)\n");
1595     printf("** 33. Provision Direct-Pairing Configuration\n");
1596     printf("** 34. Check Linked Status of the Selected Device on PRVN DB\n\n");
1597
1598     printf("** [D] UNLINK PAIRWISE THINGS\n");
1599     printf("** 40. Unlink Pairwise Things\n\n");
1600
1601     printf("** [E] REMOVE THE SELECTED DEVICE\n");
1602     printf("** 50. Remove the Selected Device\n");
1603     printf("** 51. Remove Device with UUID (UUID input is required)\n");
1604     printf("** 52. Reset the Selected Device\n\n");
1605
1606     printf("** [F] GET SECURITY RESOURCE FOR DEBUGGING ONLY\n");
1607     printf("** 60. Get the Credential resources of the Selected Device\n");
1608     printf("** 61. Get the ACL resources of the Selected Device\n\n");
1609
1610     printf("** [F] EXIT PROVISIONING CLIENT\n");
1611     printf("** 99. Exit Provisionong Client\n\n");
1612
1613     printf("************************************************************\n\n");
1614 }
1615
1616 #if 0 // Code for enabling path configuration for PDB and SVR DBf
1617 static void printUsage(void)
1618 {
1619     printf("\n");
1620     printf("OIC Provisioning Client with using C-level API\n");
1621     printf("Usage: provisioningclient [option]...\n");
1622     printf("\n");
1623     printf("  -h                           print help for this provisioning client\n");
1624     printf("  -p=[prvn_db_file_path/name]  input PRVN DB file path and name\n");
1625     printf("                               if not exists, will load default DB file\n");
1626     printf("                               (default: |oic_prvn_mng.db| on working dir)\n");
1627     printf("                               (ex. -p=oic_prvn_mng.db)\n");
1628     printf("  -s=[svr_db_file_path/name]   input SVR DB file path and name\n");
1629     printf("                               if not exists, will load default DB file\n");
1630     printf("                               (default: |oic_svr_db_client.json| on working dir)\n");
1631     printf("                               (ex. -s=oic_svr_db_client.json)\n");
1632     printf("\n");
1633 }
1634 #endif
1635
1636 // main function for provisioning client using C-level provisioning API
1637 int main()
1638 {
1639     // initialize provisioning client
1640     if(initProvisionClient())
1641     {
1642         OIC_LOG(ERROR, TAG, "ProvisionClient init error");
1643         goto PMCLT_ERROR;
1644     }
1645
1646     // main loop for provisioning manager
1647     int mn_num = 0;
1648     for( ; ; )
1649     {
1650         printf("\n");
1651         printMenu();
1652         printf(">> Enter Menu Number: ");
1653         for(int ret=0; 1!=ret; )
1654         {
1655             ret = scanf("%d", &mn_num);
1656             for( ; 0x20<=getchar(); );  // for removing overflow garbages
1657                                         // '0x20<=code' is character region
1658         }
1659         printf("\n");
1660         switch(mn_num)
1661         {
1662         case _10_DISCOV_ALL_DEVS_:
1663             if(discoverAllDevices())
1664             {
1665                 OIC_LOG(ERROR, TAG, "_10_DISCOV_ALL_DEVS_: error");
1666             }
1667             break;
1668         case _11_DISCOV_UNOWN_DEVS_:
1669             if(discoverUnownedDevices())
1670             {
1671                 OIC_LOG(ERROR, TAG, "_11_DISCOV_UNOWN_DEVS_: error");
1672             }
1673             break;
1674         case _12_DISCOV_OWN_DEVS_:
1675             if(discoverOwnedDevices())
1676             {
1677                 OIC_LOG(ERROR, TAG, "_12_DISCOV_OWN_DEVS_: error");
1678             }
1679             break;
1680         case _20_REGIST_DEVS_:
1681             if(registerDevices())
1682             {
1683                 OIC_LOG(ERROR, TAG, "_20_REGIST_DEVS_: error");
1684             }
1685             break;
1686         case _30_PROVIS_PAIR_DEVS_:
1687             if(provisionPairwise())
1688             {
1689                 OIC_LOG(ERROR, TAG, "_30_PROVIS_PAIR_DEVS_: error");
1690             }
1691             break;
1692         case _31_PROVIS_CRED_:
1693             if(provisionCred())
1694             {
1695                 OIC_LOG(ERROR, TAG, "_31_PROVIS_CRED_: error");
1696             }
1697             break;
1698         case _32_PROVIS_ACL_:
1699             if(provisionAcl())
1700             {
1701                 OIC_LOG(ERROR, TAG, "_32_PROVIS_ACL_: error");
1702             }
1703             break;
1704         case _33_PROVIS_DP_:
1705             if(provisionDirectPairing())
1706             {
1707                 OIC_LOG(ERROR, TAG, "_33_PROVIS_DP_: error");
1708             }
1709             break;
1710         case _34_CHECK_LINK_STATUS_:
1711             if(checkLinkedStatus())
1712             {
1713                 OIC_LOG(ERROR, TAG, "_34_CHECK_LINK_STATUS_: error");
1714             }
1715             break;
1716         case _40_UNLINK_PAIR_DEVS_:
1717             if(unlinkPairwise())
1718             {
1719                 OIC_LOG(ERROR, TAG, "_40_UNLINK_PAIR_DEVS_: error");
1720             }
1721             break;
1722         case _50_REMOVE_SELEC_DEV_:
1723             if(removeDevice())
1724             {
1725                 OIC_LOG(ERROR, TAG, "_50_REMOVE_SELEC_DEV_: error");
1726             }
1727             break;
1728         case _51_REMOVE_DEV_WITH_UUID_:
1729             if(removeDeviceWithUuid())
1730             {
1731                 OIC_LOG(ERROR, TAG, "_51_REMOVE_DEV_WITH_UUID_: error");
1732             }
1733             break;
1734         case _52_RESET_SELEC_DEV_:
1735             if(resetDevice())
1736             {
1737                 OIC_LOG(ERROR, TAG, "_52_RESET_SELEC_DEV_: error");
1738             }
1739             break;
1740         case _60_GET_CRED_:
1741             if(getCred())
1742             {
1743                 OIC_LOG(ERROR, TAG, "_60_GET_CRED_: error");
1744             }
1745             break;
1746         case _61_GET_ACL_:
1747             if(getAcl())
1748             {
1749                 OIC_LOG(ERROR, TAG, "_61_GET_ACL_: error");
1750             }
1751             break;
1752         case _99_EXIT_PRVN_CLT_:
1753             goto PMCLT_ERROR;
1754         default:
1755             printf(">> Entered Wrong Number. Please Enter Again\n\n");
1756             break;
1757         }
1758     }
1759
1760 PMCLT_ERROR:
1761     if(OC_STACK_OK != OCStop())
1762     {
1763         OIC_LOG(ERROR, TAG, "OCStack stop error");
1764     }
1765     OCDeleteDiscoveredDevices(g_own_list);  // after here |g_own_list| points nothing
1766     OCDeleteDiscoveredDevices(g_unown_list);  // after here |g_unown_list| points nothing
1767
1768     if(g_svr_fname)
1769     {
1770         OICFree(g_svr_fname);  // after here |g_svr_fname| points nothing
1771     }
1772     if(g_prvn_fname)
1773     {
1774         OICFree(g_prvn_fname);  // after here |g_prvn_fname| points nothing
1775     }
1776     return 0;  // always return normal case
1777 }
1778
1779 #ifdef __cplusplus
1780 }
1781 #endif //__cplusplus