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