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