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