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