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