9e2f1d8800a3a78ad874bdfda67dfc8764b2899c
[platform/upstream/iotivity.git] / resource / provisioning / examples / provisioningclient.cpp
1 /* *****************************************************************
2  *
3  * Copyright 2015 Samsung Electronics All Rights Reserved.
4  *
5  *
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *     http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  * *****************************************************************/
20
21 #include <stdio.h>
22 #include <string.h>
23 #include <unistd.h>
24 #include <string>
25 #include <map>
26 #include <cstdlib>
27 #include <pthread.h>
28 #include <mutex>
29 #include <condition_variable>
30
31 #include "logger.h"
32 #include "oic_malloc.h"
33 #include "oic_string.h"
34 #include "OCPlatform.h"
35 #include "OCApi.h"
36 #include "OCProvisioningManager.hpp"
37 #include "oxmjustworks.h"
38 #include "oxmrandompin.h"
39 #include "aclresource.h"
40 #include "utlist.h"
41
42 #define MAX_PERMISSION_LENGTH (5)
43 #define ACL_RESRC_ARRAY_SIZE (3)
44 #define CREATE (1)
45 #define READ (2)
46 #define UPDATE (4)
47 #define DELETE (8)
48 #define NOTIFY (16)
49 #define DASH '-'
50 #define PREDEFINED_TIMEOUT (10)
51 #define MAX_OWNED_DEVICE (10)
52 #define TAG  "provisioningclient"
53
54 #define JSON_DB_PATH "./oic_svr_db_client.json"
55 #define DAT_DB_PATH "./oic_svr_db_client.dat"
56 #define DEV_STATUS_ON "DEV_STATUS_ON"
57 #define DEV_STATUS_OFF "DEV_STATUS_OFF"
58
59 #define DISCOVERY_TIMEOUT 5
60
61 static const OicSecPrm_t  SUPPORTED_PRMS[1] =
62 {
63     PRM_PRE_CONFIGURED,
64 };
65
66 using namespace OC;
67
68 DeviceList_t pUnownedDevList, pOwnedDevList;
69 static int transferDevIdx, ask = 1;
70 static OicSecPconf_t g_pconf;
71 static uint16_t g_credId = 0;
72
73 static FILE* client_open(const char *UNUSED_PARAM, const char *mode)
74 {
75     (void)UNUSED_PARAM;
76     return fopen(DAT_DB_PATH, mode);
77 }
78
79 void printMenu()
80 {
81     std::cout << "\nChoose an option:"<<std::endl;
82     std::cout << "   1. UnOwned Device discovery"<<std::endl;
83     std::cout << "   2. Owned Device discovery"<<std::endl;
84     std::cout << "   3. Ownership transfer"<<std::endl;
85     std::cout << "   4. Provision ACL"<<std::endl;
86     std::cout << "   5. Provision Credentials"<<std::endl;
87     std::cout << "   6. Credential & ACL provisioning b/w two devices"<<std::endl;
88     std::cout << "   7. Unlink Devices"<<std::endl;
89     std::cout << "   8. Remove Device"<<std::endl;
90     std::cout << "   9. Remove Device using UUID"<<std::endl;
91     std::cout << "  10. Get Linked Devices"<<std::endl;
92     std::cout << "  11. Get Device Status"<<std::endl;
93     std::cout << "  12. Provision Direct-Pairing Configuration"<<std::endl;
94 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
95     std::cout << "  13. Save the Trust Cert. Chain into Cred of SVR"<<std::endl;
96     std::cout << "  14. Provision the Trust Cert. Chain"<<std::endl;
97     std::cout << "  15. Read trust cert chain"<<std::endl;
98 #endif // __WITH_DTLS__ || __WITH_TLS__
99     std::cout << "  99. Exit loop"<<std::endl;
100 }
101
102 void moveTransferredDevice()
103 {
104     pOwnedDevList.push_back(pUnownedDevList[transferDevIdx]);
105     pUnownedDevList.erase(pUnownedDevList.begin() + transferDevIdx);
106 }
107
108 void InputPinCB(char* pinBuf, size_t bufSize)
109 {
110     if(pinBuf)
111     {
112         std::cout <<"INPUT PIN : ";
113         std::string ptr;
114         std::cin >> ptr;
115         OICStrcpy(pinBuf, bufSize, ptr.c_str());
116         return;
117     }
118 }
119
120 void printUuid(OicUuid_t uuid)
121 {
122     for (int i = 0; i < UUID_LENGTH; i++)
123     {
124         std::cout <<std::hex << uuid.id[i] << " ";
125     }
126     std::cout<<std::endl;
127 }
128
129 void ownershipTransferCB(PMResultList_t *result, int hasError)
130 {
131     if (hasError)
132     {
133         std::cout << "Error!!! in OwnershipTransfer"<<std::endl;
134     }
135     else
136     {
137         std::cout<< "\nTransferred Ownership successfuly for device : ";
138         printUuid(result->at(0).deviceId);
139         delete result;
140
141         moveTransferredDevice();
142     }
143     ask = 1;
144 }
145
146 void printStatus(int status)
147 {
148     static std::map<int, std::string> devStatus = {{1<<0, DEV_STATUS_ON}, {1<<1, DEV_STATUS_OFF}};
149
150     std::cout <<devStatus[status] <<std::endl;
151 }
152
153 void printDevices(DeviceList_t &list)
154 {
155    for (unsigned int i = 0; i < list.size(); i++ )
156    {
157       std::cout << "Device "<< i+1 <<" ID: ";
158       std::cout << list[i]->getDeviceID() << " From IP: ";
159       std::cout << list[i]->getDevAddr() << std::endl;
160    }
161 }
162
163 /**
164  * Callback function for provisioning ACL, Credentials.
165  *
166  * @param[in]    result Result list
167  * @param[in] hasError indicates if the result has error
168  */
169 void provisionCB(PMResultList_t *result, int hasError)
170 {
171    if (hasError)
172    {
173        std::cout << "Error in provisioning operation!"<<std::endl;
174    }
175    else
176    {
177        std::cout<< "\nReceived provisioning results: ";
178        for (unsigned int i = 0; i < result->size(); i++)
179        {
180            std::cout << "Result is = " << result->at(i).res <<" for device ";
181            printUuid(result->at(i).deviceId);
182        }
183
184        delete result;
185    }
186    printMenu();
187    ask = 1;
188 }
189 /**
190  *
191  * Ask user with which devices it wants to make further actions.
192  * All possible error checks included.
193  * Default behavior in case if only one options leaves are included too.
194  * Expect that user count devices from 1, f.e. 1st, 2nd, 3rd, etc
195  * Use DeviceList_t instead of devicesCount because of print devices info
196  *
197  * @param[in] list owned devices list.
198  * @param[out] out device number array.
199  * @param[in] count how many device numbers need to read.
200  * @return 0 in case of success and other value otherwise.
201  */
202 int readDeviceNumber(DeviceList_t &list, int count, int *out)
203 {
204    if (out == NULL || count <= 0)
205    {
206       std::cout << "Error! Please put valid input parameters" << std::endl;
207       return -1;
208    }
209
210    int devicesCount = list.size();
211
212    //Print current list of owned devices
213    std::cout <<"Owned devices, count = " << devicesCount << std::endl;
214    printDevices(list);
215
216    if (devicesCount < count)
217    {
218       std::cout << "You can't proceed with selected action because Owned devices count ( ";
219       std::cout << devicesCount << " ) are less then required devices ( " << count << " ).";
220       std::cout << "You may need to discover devices again" << std::endl;
221       return -2;
222    }
223
224    std::cout << "Select " << count << " device(s) for provisioning" << std::endl;
225
226    for (int curr = 0; curr < count; curr++)
227    {
228       //select last device by default if only 1 option exist
229       //from user's point of view device counting starts from 1,
230       //so 1st, 2nd, 3rd, etc devices
231       if ((curr == count - 1) && (devicesCount == count))
232       {
233          int sum = 0;
234          for (int i = 0; i < curr; i++)
235          {
236              sum += out[i];
237          }
238
239          out[curr] = (count*(count+1))/2 - sum;
240
241          std::cout << "Device " << curr + 1 << " : " << out[curr];
242          std::cout << " - selected automatically (because no other options exist)" << std::endl;
243          break;
244       }
245
246       int choice;
247       std::cout << "Device " << curr + 1 << " : ";
248       std::cin >> choice;
249
250       if (choice < 1 || choice > devicesCount)
251       {
252          std::cout << "Error! You should enter valid device number!" << std::endl;
253          return -3;
254       }
255
256       //check that user doesn't select the same device twice
257       for (int i = 0; i < curr; i++)
258       {
259          if (out[i] == choice)
260          {
261             std::cout << "Error! You cannot select the same device twice!" << std::endl;
262             return -4;
263          }
264       }
265
266       out[curr] = choice;
267    }
268
269    //Users count devices from 1, so 1st, 2nd, 3rd, etc device
270    //But deviceList array start index is 0, so need to decrease all numbers to 1
271    for (int i = 0; i < count; i++) out[i] -= 1;
272
273    return 0;
274 }
275
276 /**
277  * Perform cleanup for ACL
278  * @param[in]    ACL
279  */
280 static void deleteACL(OicSecAcl_t *acl)
281 {
282     DeleteACLList(acl);
283
284 }
285
286 /**
287  * Calculate ACL permission from string to bit
288  *
289  * @param[in] temp_psm    Input data of ACL permission string
290  * @param[in,out] pms    The pointer of ACL permission value
291  * @return  0 on success otherwise -1.
292  */
293 static int CalculateAclPermission(const char *temp_pms, uint16_t *pms)
294 {
295     int i = 0;
296
297     if (NULL == temp_pms || NULL == pms)
298     {
299         return -1;
300     }
301     *pms = 0;
302     while (temp_pms[i] != '\0')
303     {
304         switch (temp_pms[i])
305         {
306             case 'C':
307                 {
308                     *pms += CREATE;
309                     i++;
310                     break;
311                 }
312             case 'R':
313                 {
314                     *pms += READ;
315                     i++;
316                     break;
317                 }
318             case 'U':
319                 {
320                     *pms += UPDATE;
321                     i++;
322                     break;
323                 }
324             case 'D':
325                 {
326                     *pms += DELETE;
327                     i++;
328                     break;
329                 }
330             case 'N':
331                 {
332                     *pms += NOTIFY;
333                     i++;
334                     break;
335                 }
336             case '_':
337                 {
338                     i++;
339                     break;
340                 }
341             default:
342                 {
343                     return -1;
344                 }
345         }
346     }
347     return 0;
348 }
349
350 /**
351  * Get the ACL property from user
352  *
353  * @param[in]    ACL Datastructure to save user inputs
354  * @return  0 on success otherwise -1.
355  */
356 static int InputACL(OicSecAcl_t *acl)
357 {
358     int ret;
359     char *temp_id, *temp_rsc, *temp_pms;
360
361     printf("******************************************************************************\n");
362     printf("-Set ACL policy for target device\n");
363     printf("******************************************************************************\n");
364     //Set Subject.
365     printf("-URN identifying the subject\n");
366     printf("ex) 1111-1111-1111-1111 (16 Numbers except to '-')\n");
367     printf("Subject : ");
368     ret = scanf("%19ms", &temp_id);
369
370     OicSecAce_t* ace = (OicSecAce_t*)OICCalloc(1, sizeof(OicSecAce_t));
371     if(NULL == ace)
372     {
373         OIC_LOG(ERROR, TAG, "Error while memory allocation");
374         return -1;
375     }
376     LL_APPEND(acl->aces, ace);
377
378     if (1 == ret)
379     {
380         for (int i = 0, j = 0; temp_id[i] != '\0'; i++)
381         {
382             if (DASH != temp_id[i])
383                 ace->subjectuuid.id[j++] = temp_id[i];
384         }
385         OICFree(temp_id);
386     }
387     else
388     {
389         deleteACL(acl);
390         printf("Error while input\n");
391         return -1;
392     }
393
394     //Set Resource.
395     size_t resourcesLen = 0;
396     printf("Num. of Resource : ");
397     ret = scanf("%zu", &resourcesLen);
398     if ((1 != ret) || (resourcesLen <= 0 || resourcesLen > 50))
399     {
400         deleteACL(acl);
401         printf("Error while input\n");
402         return -1;
403     }
404     printf("-URI of resource\n");
405     printf("ex)/oic/sh/temp/0 (Max_URI_Length: %d Byte )\n", MAX_URI_LENGTH);
406     for(size_t i = 0; i < resourcesLen; i++)
407     {
408         OicSecRsrc_t* rsrc = (OicSecRsrc_t*)OICCalloc(1, sizeof(OicSecRsrc_t));
409         if(NULL == rsrc)
410         {
411             deleteACL(acl);
412             OIC_LOG(ERROR, TAG, "Error while memory allocation");
413             return -1;
414         }
415
416         LL_APPEND(ace->resources, rsrc);
417
418         printf("[%zu]Resource : ", i + 1);
419         ret = scanf("%64ms", &temp_rsc);
420         if (1 != ret)
421         {
422             printf("Error while input\n");
423             return -1;
424         }
425
426         rsrc->href = OICStrdup(temp_rsc);
427         OICFree(temp_rsc);
428
429         char* rsrc_in = NULL;
430         size_t arrLen = 0;
431         while(1)
432         {
433             printf("         Enter Number of resource type for [%s]: ", rsrc->href);
434             for(int ret=0; 1!=ret; )
435             {
436                 ret = scanf("%d", &arrLen);
437                 for( ; 0x20<=getchar(); );  // for removing overflow garbages
438                                             // '0x20<=code' is character region
439             }
440             if(ACL_RESRC_ARRAY_SIZE >= arrLen)
441             {
442                 break;
443             }
444             printf("     Entered Wrong Number. Please Enter under %d Again\n", ACL_RESRC_ARRAY_SIZE);
445         }
446
447         rsrc->typeLen = arrLen;
448         rsrc->types = (char**)OICCalloc(arrLen, sizeof(char*));
449         if(!rsrc->types)
450         {
451             OIC_LOG(ERROR, TAG, "createAcl: OICCalloc error return");
452             goto error;
453         }
454
455         for(int i = 0; i < arrLen; i++)
456         {
457             printf("         Enter ResourceType[%d] Name (e.g. core.led): ", i+1);
458             for(int ret=0; 1!=ret; )
459             {
460                 ret = scanf("%64ms", &rsrc_in);  // '128' is ACL_RESRC_MAX_LEN
461                 for( ; 0x20<=getchar(); );  // for removing overflow garbages
462                                             // '0x20<=code' is character region
463             }
464             rsrc->types[i] = OICStrdup(rsrc_in);
465             OICFree(rsrc_in);
466             if(!rsrc->types[i])
467             {
468                 OIC_LOG(ERROR, TAG, "createAcl: OICStrdup error return");
469                 goto error;
470             }
471         }
472
473         while(1)
474         {
475             printf("         Enter Number of interface name for [%s]: ", rsrc->href);
476             for(int ret=0; 1!=ret; )
477             {
478                 ret = scanf("%d", &arrLen);
479                 for( ; 0x20<=getchar(); );  // for removing overflow garbages
480                                             // '0x20<=code' is character region
481             }
482             if(ACL_RESRC_ARRAY_SIZE >= arrLen)
483             {
484                 break;
485             }
486             printf("     Entered Wrong Number. Please Enter under %d Again\n", ACL_RESRC_ARRAY_SIZE);
487         }
488
489         rsrc->interfaceLen = arrLen;
490         rsrc->interfaces = (char**)OICCalloc(arrLen, sizeof(char*));
491         if(!rsrc->interfaces)
492         {
493             OIC_LOG(ERROR, TAG, "createAcl: OICCalloc error return");
494             goto error;
495         }
496
497         for(int i = 0; i < arrLen; i++)
498         {
499             printf("         Enter interfnace[%d] Name (e.g. oic.if.baseline): ", i+1);
500             for(int ret=0; 1!=ret; )
501             {
502                 ret = scanf("%64ms", &rsrc_in);  // '128' is ACL_RESRC_MAX_LEN
503                 for( ; 0x20<=getchar(); );  // for removing overflow garbages
504                                             // '0x20<=code' is character region
505             }
506             rsrc->interfaces[i] = OICStrdup(rsrc_in);
507             OICFree(rsrc_in);
508             if(!rsrc->interfaces[i])
509             {
510                 OIC_LOG(ERROR, TAG, "createAcl: OICStrdup error return");
511                 goto error;
512             }
513         }
514
515     }
516
517     // Set Permission
518     do
519     {
520         printf("-Set the permission(C,R,U,D,N)\n");
521         printf("ex) CRUDN, CRU_N,..(5 Charaters)\n");
522         printf("Permission : ");
523         ret = scanf("%5ms", &temp_pms);
524         if (1 != ret)
525         {
526             printf("Error while input\n");
527             goto error;
528         }
529         ret = CalculateAclPermission(temp_pms, &(ace->permission));
530         OICFree(temp_pms);
531     } while (0 != ret );
532
533     // Set Rowner
534     printf("-URN identifying the rowner\n");
535     printf("ex) 1111-1111-1111-1111 (16 Numbers except to '-')\n");
536
537     printf("Rowner : ");
538     ret = scanf("%19ms", &temp_id);
539     if (1 != ret)
540     {
541         printf("Error while input\n");
542         goto error;
543     }
544
545     for (int k = 0, j = 0; temp_id[k] != '\0'; k++)
546     {
547         if (DASH != temp_id[k])
548         {
549             acl->rownerID.id[j++] = temp_id[k];
550         }
551     }
552     OICFree(temp_id);
553
554     return 0;
555
556 error:
557     DeleteACLList(acl);
558     return -1;
559 }
560
561 static int InputCredentials(Credential &cred)
562 {
563    int choice;
564
565    do
566    {
567        std::cout << "Select credential type from following values:" << std::endl;
568        std::cout << "1:  symmetric pair-wise key" << std::endl;
569        std::cout << "2:  symmetric group key" << std::endl;
570        std::cout << "4:  asymmetric key" << std::endl;
571        std::cout << "8:  signed asymmetric key (aka certificate)" << std::endl;
572        std::cout << "16: PIN /password" << std::endl;
573        std::cout << "Your choice: ";
574
575        std::cin >> choice;
576
577        switch (choice){
578            case 1:
579                cred.setCredentialType(static_cast<OicSecCredType_t>(choice));
580                choice = 0; //validation of the accepted choice.
581                break;
582            case 2:
583            case 4:
584            case 8:
585            case 16:
586                std::cout << "selected type is not supported yet" << std::endl;
587                break;
588            default:
589                std::cout << "Error! Please select valid credential type" << std::endl;
590                break;
591        }
592    } while(0 != choice);
593
594    std::cout << "Please enter key size (valid size is 128 or 256) :";
595    std::cin >> choice;
596
597    if(128 == choice)
598    {
599        cred.setCredentialKeySize(OWNER_PSK_LENGTH_128);
600    }
601    else if(256 == choice)
602    {
603         cred.setCredentialKeySize(OWNER_PSK_LENGTH_256);
604    }
605    else
606    {
607       std::cout << "Error! Please enter valid key size!" << std::endl;
608       return -2;
609    }
610
611    return 0;
612 }
613
614 static void deletePconf()
615 {
616     OICFree(g_pconf.prm);
617     //free pdacl
618     OicSecPdAcl_t* acl = g_pconf.pdacls;
619     if (acl)
620     {
621         /* Clean Resources */
622         for (unsigned int i = 0; i < (acl)->resourcesLen; i++)
623         {
624             OICFree((acl)->resources[i]);
625         }
626         OICFree((acl)->resources);
627
628         /* Clean ACL node itself */
629         /* Required only if acl was created in heap */
630         OICFree((acl));
631     }
632     memset(&g_pconf, 0, sizeof(OicSecPconf_t));
633 }
634
635 static OicSecPdAcl_t* InputPdACL()
636 {
637     int ret;
638     char *temp_rsc, *temp_pms;
639
640     printf("******************************************************************************\n");
641     printf("-Set ACL policy for target DP device\n");
642     printf("******************************************************************************\n");
643
644     OicSecPdAcl_t *acl = (OicSecPdAcl_t *)OICCalloc(1,sizeof(OicSecPdAcl_t));
645     if (NULL == acl)
646     {
647         OIC_LOG(ERROR, TAG, "Error while memory allocation");
648         return NULL;
649     }
650
651     //Set Resource.
652     printf("Num. of Resource : ");
653     ret = scanf("%zu", &acl->resourcesLen);
654     if ((1 != ret) || (acl->resourcesLen <= 0 || acl->resourcesLen > 50))
655     {
656         printf("Error while input\n");
657         OICFree(acl);
658         return NULL;
659     }
660     printf("-URI of resource\n");
661     printf("ex)/oic/sh/temp/0 (Max_URI_Length: %d Byte )\n", MAX_URI_LENGTH);
662     acl->resources = (char **)OICCalloc(acl->resourcesLen, sizeof(char *));
663     if (NULL == acl->resources)
664     {
665         OIC_LOG(ERROR, TAG, "Error while memory allocation");
666         OICFree(acl);
667         return NULL;
668     }
669     for (size_t i = 0; i < acl->resourcesLen; i++)
670     {
671         printf("[%zu]Resource : ", i + 1);
672         ret = scanf("%64ms", &temp_rsc);
673         if (1 != ret)
674         {
675             printf("Error while input\n");
676             OICFree(acl->resources);
677             OICFree(acl);
678             return NULL;
679         }
680
681         acl->resources[i] = OICStrdup(temp_rsc);
682         OICFree(temp_rsc);
683         if (NULL == acl->resources[i])
684         {
685             OIC_LOG(ERROR, TAG, "Error while memory allocation");
686             OICFree(acl->resources);
687             OICFree(acl);
688             return NULL;
689         }
690     }
691
692     // Set Permission
693     do
694     {
695         printf("-Set the permission(C,R,U,D,N)\n");
696         printf("ex) CRUDN, CRU_N,..(5 Charaters)\n");
697         printf("Permission : ");
698         ret = scanf("%5ms", &temp_pms);
699         if (1 != ret)
700         {
701             printf("Error while input\n");
702             OICFree(acl->resources);
703             OICFree(acl);
704             return NULL;
705         }
706         ret = CalculateAclPermission(temp_pms, &(acl->permission));
707         OICFree(temp_pms);
708     } while (0 != ret );
709
710     return acl;
711 }
712
713 void provisionDirectPairingCB(PMResultList_t *result, int hasError)
714 {
715     if (hasError)
716     {
717         std::cout << "Error in provisioning operation!"<<std::endl;
718     }
719     else
720     {
721         std::cout<< "\nReceived provisioning results: Direct Pairing is successful ";
722         for (unsigned int i = 0; i < result->size(); i++)
723         {
724             std::cout << "Result is = " << result->at(i).res <<" for device ";
725             printUuid(result->at(i).deviceId);
726         }
727
728         delete result;
729     }
730     deletePconf();
731     printMenu();
732     ask = 1;
733 }
734
735 static void provisionDP(int dev_num)
736 {
737     OCStackResult rst;
738     std::string pin("");
739
740     // set enable dp
741     g_pconf.edp = true;
742
743     // set default supported PRM types
744     g_pconf.prmLen = sizeof(SUPPORTED_PRMS)/sizeof(OicSecPrm_t);
745     g_pconf.prm = (OicSecPrm_t *)OICCalloc(g_pconf.prmLen, sizeof(OicSecPrm_t));
746     if(g_pconf.prm)
747     {
748         for (size_t i=0; i < g_pconf.prmLen; i++)
749         {
750             g_pconf.prm[i] = SUPPORTED_PRMS[i];
751         }
752     }
753     else
754     {
755         OIC_LOG(ERROR, TAG, "create prm error return");
756         goto PVDP_ERROR;
757     }
758
759     std::cout << "Enter PIN to be configured: ";
760     while (1)
761     {
762         std::cin >> pin;
763         if (pin.length() == DP_PIN_LENGTH)
764         {
765             break;
766         }
767         else
768         {
769             std::cout << "PIN length should be 8, Enter again: ";
770         }
771     }
772
773     memcpy(g_pconf.pin.val, pin.c_str(), DP_PIN_LENGTH);
774
775     // set default pdacl
776
777     g_pconf.pdacls = InputPdACL();
778     if(!g_pconf.pdacls)
779     {
780         OIC_LOG(ERROR, TAG, "InputPdACL error return");
781         goto PVDP_ERROR;
782     }
783
784     // call |OCProvisionDirectPairing| API actually
785     // calling this API with callback actually acts like blocking
786     // for error checking, the return value saved and printed
787     rst = pOwnedDevList[dev_num-1]->provisionDirectPairing(&g_pconf, provisionDirectPairingCB);
788     if(OC_STACK_OK != rst)
789     {
790         OIC_LOG_V(ERROR, TAG, "OCProvisionDirectPairing API error: %d", rst);
791         if (OC_STACK_UNAUTHORIZED_REQ == rst)
792         {
793             OIC_LOG(ERROR, TAG, "Target Server NOT Support Direct-Pairing !!! (DPC == false)");
794         }
795         goto PVDP_ERROR;
796     }
797     return;
798
799 PVDP_ERROR:
800     deletePconf();  // after here |acl| points nothing
801     ask = 1;
802 }
803
804 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
805 static int saveTrustCert(void)
806 {
807
808     // call |OCSaveTrustCertChainBin| API actually
809     printf("   Save Trust Cert. Chain into Cred of SVR.\n");
810
811     ByteArray trustCertChainArray = {0, 0};
812
813     FILE *fp = fopen("rootca.crt", "rb+");
814
815     if (fp)
816     {
817         size_t fsize;
818         if (fseeko(fp, 0, SEEK_END) == 0 && (fsize = ftello(fp)) >= 0)
819         {
820             trustCertChainArray.data = (uint8_t*)OICCalloc(1, fsize);
821             trustCertChainArray.len = fsize;
822             if (NULL == trustCertChainArray.data)
823             {
824                 OIC_LOG(ERROR,TAG,"Failed to allocate memory");
825                 fclose(fp);
826                 return -1;
827             }
828             rewind(fp);
829             fsize = fread(trustCertChainArray.data, 1, fsize, fp);
830             if(0 == fsize)
831             {
832                 OIC_LOG(ERROR,TAG,"Read error");
833             }
834             fclose(fp);
835         }
836     }
837     OIC_LOG_BUFFER(DEBUG, TAG, trustCertChainArray.data, trustCertChainArray.len);
838
839     if(OC_STACK_OK != OCSecure::saveTrustCertChain(trustCertChainArray.data, trustCertChainArray.len,
840                         OIC_ENCODING_PEM,&g_credId))
841     {
842         OIC_LOG(ERROR, TAG, "OCSaveTrustCertChainBin API error");
843         return -1;
844     }
845     printf("CredId of Saved Trust Cert. Chain into Cred of SVR : %d.\n", g_credId);
846
847     return 0;
848 }
849
850 void certChainCallBack(uint16_t credId, uint8_t *trustCertChain,size_t chainSize)
851 {
852     OIC_LOG_V(INFO, TAG, "trustCertChain Changed for credId %u", credId);
853     return;
854 }
855 #endif // __WITH_DTLS__ or __WITH_TLS__
856
857 int main(void)
858 {
859     OCPersistentStorage ps {client_open, fread, fwrite, fclose, unlink };
860
861     // Create PlatformConfig object
862     PlatformConfig cfg {
863         OC::ServiceType::InProc,
864             OC::ModeType::Both,
865             "0.0.0.0",
866             0,
867             OC::QualityOfService::LowQos,
868             &ps
869     };
870
871     OCPlatform::Configure(cfg);
872
873     try
874     {
875         int choice;
876         OicSecAcl_t *acl1 = nullptr, *acl2 = nullptr;
877         if (OCSecure::provisionInit("") != OC_STACK_OK)
878         {
879             std::cout <<"PM Init failed"<< std::endl;
880             return 1;
881         }
882
883         for (int out = 0; !out;)
884         {
885             while (!ask)
886             {
887                 sleep(1);
888             }
889
890             if (acl1)
891             {
892                 deleteACL(acl1);
893                 acl1 = nullptr;
894             }
895
896             if (acl2)
897             {
898                 deleteACL(acl2);
899                 acl2 = nullptr;
900             }
901
902             printMenu();
903             std::cin >> choice;
904             switch(choice) {
905                 case 1:
906                     {
907                         //Secure resource discovery.
908
909                         pUnownedDevList.clear();
910                         std::cout << "Started discovery..." <<std::endl;
911                         OCStackResult result = OCSecure::discoverUnownedDevices(DISCOVERY_TIMEOUT,
912                                 pUnownedDevList);
913                         if (result != OC_STACK_OK)
914                         {
915                             std::cout<< "!!Error - UnOwned Discovery failed."<<std::endl;
916                         }
917                         else if (pUnownedDevList.size())
918                         {
919                             std::cout <<"Found secure devices, count = " <<
920                                 pUnownedDevList.size() << std::endl;
921                             printDevices(pUnownedDevList);
922                         }
923                         else
924                         {
925                             std::cout <<"No Secure devices found"<<std::endl;
926                         }
927                         break;
928                     }
929                 case 2:
930                     {
931                         pOwnedDevList.clear();
932                         std::cout << "Started discovery..." <<std::endl;
933                         OCStackResult result = OCSecure::discoverOwnedDevices(DISCOVERY_TIMEOUT,
934                                 pOwnedDevList);
935                         if (result != OC_STACK_OK)
936                         {
937                             std::cout<< "!!Error - Owned Discovery failed."<<std::endl;
938                         }
939                         else if (pOwnedDevList.size())
940                         {
941                             std::cout <<"Found owned devices, count = " <<
942                                 pOwnedDevList.size() << std::endl;
943                             printDevices(pOwnedDevList);
944                         }
945                         else
946                         {
947                             std::cout <<"No Secure devices found"<<std::endl;
948                         }
949                         break;
950                     }
951                 case 3:
952                     {
953                         unsigned int devNum;
954
955                         if (!pUnownedDevList.size())
956                         {
957                             std::cout <<"There are no more Unowned devices"<<std::endl;
958                             break;
959                         }
960
961                         for (unsigned int i = 0; i < pUnownedDevList.size(); i++ )
962                         {
963                             std::cout << i+1 << ": "<< pUnownedDevList[i]->getDeviceID();
964                             std::cout << " From IP:" << pUnownedDevList[i]->getDevAddr() <<std::endl;
965                         }
966
967                         std::cout <<"Select device number: "<<std::endl;
968                         std::cin >> devNum;
969                         if (devNum > pUnownedDevList.size())
970                         {
971                             std::cout <<"Invalid device number"<<std::endl;
972                             break;
973                         }
974                         transferDevIdx = devNum - 1;
975
976                         //register callbacks for JUST WORKS and PIN methods
977                         std::cout <<"Registering OTM Methods: 1. JUST WORKS and 2. PIN"<<std::endl;
978
979                         {
980                             OTMCallbackData_t justWorksCBData;
981                             justWorksCBData.loadSecretCB = LoadSecretJustWorksCallback;
982                             justWorksCBData.createSecureSessionCB =
983                                 CreateSecureSessionJustWorksCallback;
984                             justWorksCBData.createSelectOxmPayloadCB =
985                                 CreateJustWorksSelectOxmPayload;
986                             justWorksCBData.createOwnerTransferPayloadCB =
987                                 CreateJustWorksOwnerTransferPayload;
988                             OCSecure::setOwnerTransferCallbackData(OIC_JUST_WORKS,
989                                     &justWorksCBData, NULL);
990                         }
991
992                         {
993                             OTMCallbackData_t pinBasedCBData;
994                             pinBasedCBData.loadSecretCB = InputPinCodeCallback;
995                             pinBasedCBData.createSecureSessionCB =
996                                 CreateSecureSessionRandomPinCallback;
997                             pinBasedCBData.createSelectOxmPayloadCB =
998                                 CreatePinBasedSelectOxmPayload;
999                             pinBasedCBData.createOwnerTransferPayloadCB =
1000                                 CreatePinBasedOwnerTransferPayload;
1001                             OCSecure::setOwnerTransferCallbackData(OIC_RANDOM_DEVICE_PIN,
1002                                     &pinBasedCBData, InputPinCB);
1003                         }
1004
1005                         ask = 0;
1006                         std::cout << "Transfering ownership for : "<<
1007                             pUnownedDevList[devNum-1]->getDeviceID()<<std::endl;
1008                         if (pUnownedDevList[devNum-1]->doOwnershipTransfer(ownershipTransferCB)
1009                                 != OC_STACK_OK)
1010                         {
1011                             std::cout<<"OwnershipTransferCallback is failed"<<std::endl;
1012                             ask = 1;
1013                         }
1014                         break;
1015                     }
1016                 case 4: //Provision ACL
1017                     {
1018                         int index;
1019
1020                         if (0 != readDeviceNumber(pOwnedDevList, 1, &index)) break;
1021
1022                         std::cout << "Provision ACL for : "<<
1023                             pOwnedDevList[index]->getDeviceID()<< std::endl;
1024
1025                         acl1 = (OicSecAcl_t *)OICCalloc(1,sizeof(OicSecAcl_t));
1026                         if (NULL == acl1)
1027                         {
1028                             OIC_LOG(ERROR, TAG, "Error while memory allocation");
1029                             break;
1030                         }
1031
1032                         std::cout << "Please input ACL for selected device: " << std::endl;
1033                         if (0 != InputACL(acl1))
1034                         {
1035                             break;
1036                         }
1037
1038                         ask = 0;
1039
1040                         if (pOwnedDevList[index]->provisionACL(acl1, provisionCB) != OC_STACK_OK)
1041                         {
1042                             ask = 1;
1043                             std::cout <<"provisionACL is failed"<< std::endl;
1044                         }
1045                     }
1046                     break;
1047                 case 5: //Provision Credentials
1048                     {
1049                         int devices[2];
1050
1051                         if (0 != readDeviceNumber(pOwnedDevList, 2, devices)) break;
1052
1053                         int first  = devices[0];
1054                         int second = devices[1];
1055
1056                         std::cout << "Provision Credentials to devices: "<<
1057                             pOwnedDevList[first]->getDeviceID();
1058                         std::cout << " and "<< pOwnedDevList[second]->getDeviceID() << std::endl;
1059
1060                         Credential cred( NO_SECURITY_MODE ,0);
1061                         std::cout << "Please input credentials for selected devices: " << std::endl;
1062                         if (0 != InputCredentials(cred))
1063                             break;
1064
1065                         ask = 0;
1066
1067                         if (pOwnedDevList[first]->provisionCredentials(cred,
1068                                     *pOwnedDevList[second].get(), provisionCB) != OC_STACK_OK)
1069                         {
1070                             ask = 1;
1071                             std::cout <<"provisionCredentials is failed"<< std::endl;
1072                         }
1073                     }
1074                     break;
1075                 case 6: //Provision ACL & Creds b/w two devices.
1076                     {
1077                         int devices[2];
1078
1079                         if (0 != readDeviceNumber(pOwnedDevList, 2, devices)) break;
1080
1081                         int first  = devices[0];
1082                         int second = devices[1];
1083
1084                         std::cout << "Provision pairwise devices: "<<
1085                             pOwnedDevList[first]->getDeviceID();
1086                         std::cout << " and "<< pOwnedDevList[second]->getDeviceID() << std::endl;
1087
1088                         Credential cred( NO_SECURITY_MODE, 0);
1089                         std::cout << "Please input credentials for selected devices: " << std::endl;
1090                         if (0 != InputCredentials(cred))
1091                             break;
1092
1093                         acl1 = (OicSecAcl_t *)OICCalloc(1,sizeof(OicSecAcl_t));
1094                         if (NULL == acl1)
1095                         {
1096                             OIC_LOG(ERROR, TAG, "Error while memory allocation");
1097                             break;
1098                         }
1099
1100                         std::cout << "Please input ACL for selected device: " << std::endl;
1101                         if (0 != InputACL(acl1))
1102                         {
1103                             break;
1104                         }
1105
1106                         acl2 = (OicSecAcl_t *)OICCalloc(1,sizeof(OicSecAcl_t));
1107                         if (NULL == acl2)
1108                         {
1109                             OIC_LOG(ERROR, TAG, "Error while memory allocation");
1110                             break;
1111                         }
1112
1113                         std::cout << "Please input ACL for selected device: " << std::endl;
1114                         if (0 != InputACL(acl2))
1115                         {
1116                             break;
1117                         }
1118
1119                         ask = 0;
1120
1121                         if (pOwnedDevList[first]->provisionPairwiseDevices(cred, acl1,
1122                                     *pOwnedDevList[second].get(), acl2, provisionCB) != OC_STACK_OK)
1123                         {
1124                             ask = 1;
1125                             std::cout <<"provisionPairwiseDevices is failed"<< std::endl;
1126                         }
1127                     }
1128                     break;
1129                 case 7: //Unlink Devices
1130                     {
1131                         int devices[2];
1132
1133                         if (0 != readDeviceNumber(pOwnedDevList, 2, devices)) break;
1134
1135                         int first  = devices[0];
1136                         int second = devices[1];
1137
1138                         std::cout << "Unlink devices: "<< pOwnedDevList[first]->getDeviceID();
1139                         std::cout << " and "<< pOwnedDevList[second]->getDeviceID() << std::endl;
1140
1141                         ask = 0;
1142
1143                         if (pOwnedDevList[first]->unlinkDevices(*pOwnedDevList[second].get(),
1144                                     provisionCB) != OC_STACK_OK)
1145                         {
1146                             ask = 1;
1147                             std::cout <<"unlinkDevice is failed"<< std::endl;
1148                         }
1149                         break;
1150                     }
1151                 case 8: //Remove Device
1152                     {
1153                         int index;
1154
1155                         if (0 != readDeviceNumber(pOwnedDevList, 1, &index)) break;
1156
1157                         std::cout << "Remove Device: "<< pOwnedDevList[index]->getDeviceID()<< std::endl;
1158
1159                         ask = 0;
1160
1161                         if (pOwnedDevList[index]->removeDevice(DISCOVERY_TIMEOUT, provisionCB)
1162                                 != OC_STACK_OK)
1163                         {
1164                             ask = 1;
1165                             std::cout <<"removeDevice is failed"<< std::endl;
1166                         }
1167                         break;
1168                     }
1169                 case 9: //Remove Device using UUID
1170                     {
1171                         int index;
1172
1173                         if (0 != readDeviceNumber(pOwnedDevList, 1, &index)) break;
1174
1175                         std::cout << "Remove Device: "<< pOwnedDevList[index]->getDeviceID()<< std::endl;
1176
1177                         ask = 0;
1178
1179                         if (OCSecure::removeDeviceWithUuid(DISCOVERY_TIMEOUT,
1180                                                                        pOwnedDevList[index]->getDeviceID(),
1181                                                                        provisionCB)
1182                                 != OC_STACK_OK)
1183                         {
1184                             ask = 1;
1185                             std::cout <<"removeDevice is failed"<< std::endl;
1186                         }
1187                         break;
1188                     }
1189
1190                 case 10: //Get Linked devices
1191                     {
1192                         UuidList_t linkedUuid;
1193                         unsigned int devNum;
1194
1195                         if (!pOwnedDevList.size())
1196                         {
1197                             std::cout <<"There are no Owned devices yet,"
1198                                 " may need to discover"<<std::endl;
1199                             break;
1200                         }
1201
1202                         for (unsigned int i = 0; i < pOwnedDevList.size(); i++ )
1203                         {
1204                             std::cout << i+1 << ": "<< pOwnedDevList[i]->getDeviceID() <<" From IP:";
1205                             std::cout << pOwnedDevList[i]->getDevAddr() <<std::endl;
1206                         }
1207
1208                         std::cout <<"Select device number: "<<std::endl;
1209                         std::cin >> devNum;
1210                         if (devNum > pOwnedDevList.size())
1211                         {
1212                             std::cout <<"Invalid device number"<<std::endl;
1213                             break;
1214                         }
1215
1216                         if(pOwnedDevList[devNum  -1]->getLinkedDevices(linkedUuid) == OC_STACK_OK)
1217                         {
1218                             if (!linkedUuid.size())
1219                             {
1220                                 std::cout <<"No devices are linked to "<<
1221                                     pOwnedDevList[devNum  -1]->getDeviceID() << std::endl;
1222                             }
1223                             //display the Linked devices (UUIDs)
1224                             for(unsigned int i = 0; i < linkedUuid.size(); i++)
1225                             {
1226                                 printUuid(linkedUuid[i]);
1227                             }
1228                         }
1229                         else
1230                         {
1231                             std::cout <<"Error! in getLinkedDevices"<<std::endl;
1232                         }
1233                         break;
1234                     }
1235                 case 11: //Get device' status
1236                     {
1237                         DeviceList_t unownedList, ownedList;
1238
1239                         if (OCSecure::getDevInfoFromNetwork(DISCOVERY_TIMEOUT, ownedList,
1240                                     unownedList) == OC_STACK_OK)
1241                         {
1242                             std::cout <<"Owned Device' status for" <<std::endl;
1243                             for (unsigned int i = 0; i < ownedList.size(); i++ )
1244                             {
1245                                 std::cout << "Device "<<i+1 <<" ID: '";
1246                                 std::cout << ownedList[i]->getDeviceID() << "' From IP: ";
1247                                 std::cout << ownedList[i]->getDevAddr() << " Status: ";
1248                                 printStatus(ownedList[i]->getDeviceStatus());
1249                             }
1250                             std::cout <<"\nUnOwned Device' status for" <<std::endl;
1251                             for (unsigned int i = 0; i < unownedList.size(); i++ )
1252                             {
1253                                 std::cout << "Device "<<i+1 <<" ID: '";
1254                                 std::cout << unownedList[i]->getDeviceID() << "' From IP: ";
1255                                 std::cout << unownedList[i]->getDevAddr() << " Status: ";
1256                                 printStatus(unownedList[i]->getDeviceStatus());
1257                             }
1258
1259                         }
1260                         break;
1261                     }
1262
1263                 case 12:
1264                     {
1265                         unsigned int devNum;
1266
1267                         if (!pOwnedDevList.size())
1268                         {
1269                             std::cout <<"There are no Owned devices yet,"
1270                                 " may need to discover"<<std::endl;
1271                             break;
1272                         }
1273
1274                         for (unsigned int i = 0; i < pOwnedDevList.size(); i++ )
1275                         {
1276                             std::cout << i+1 << ": "<< pOwnedDevList[i]->getDeviceID() <<" From IP:";
1277                             std::cout << pOwnedDevList[i]->getDevAddr() <<std::endl;
1278                         }
1279
1280                         std::cout <<"Select device number: "<<std::endl;
1281                         std::cin >> devNum;
1282                         if (devNum > pOwnedDevList.size())
1283                         {
1284                             std::cout <<"Invalid device number"<<std::endl;
1285                             break;
1286                         }
1287
1288                         ask = 0;
1289                         provisionDP(devNum);
1290
1291                         break;
1292                     }
1293 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
1294                 case 13:
1295                     {
1296                         std::cout<< "registering cert chain change notifier"<<std::endl;
1297                         OCSecure::registerTrustCertChangeNotifier(certChainCallBack);
1298                         if(saveTrustCert())
1299                         {
1300                             std::cout<<"Error in saving cert"<<std::endl;
1301                         }
1302                         std::cout<< "Unregister notifier"<<std::endl;
1303                         OCSecure::removeTrustCertChangeNotifier();
1304                         break;
1305                     }
1306                 case 14:
1307                     {
1308                         int index;
1309
1310                         if (0 != readDeviceNumber(pOwnedDevList, 1, &index)) break;
1311
1312                         std::cout << "Provision cert for : "<<
1313                             pOwnedDevList[index]->getDeviceID()<< std::endl;
1314
1315                         ask = 0;
1316
1317                         if (pOwnedDevList[index]->provisionTrustCertChain(SIGNED_ASYMMETRIC_KEY,
1318                                                                     g_credId,provisionCB ) != OC_STACK_OK)
1319                         {
1320                             ask = 1;
1321                             std::cout <<"provision cert is failed"<< std::endl;
1322                         }
1323                         break;
1324                     }
1325                 case 15:
1326                     {
1327                         if (0==g_credId)
1328                         {
1329                             std::cout<<"please save cert using option 13.";
1330                         }
1331                         else
1332                         {
1333                             uint8_t *trustCertChain = NULL;
1334                             size_t chainSize = 0;
1335                             if (OC_STACK_OK != OCSecure::readTrustCertChain(g_credId, &trustCertChain,&chainSize))
1336                             {
1337                                 std::cout <<"issue in read trust chain"<< std::endl;
1338                             }
1339                             else
1340                             {
1341                                 std::cout<<"size of cert : "<<chainSize<<std::endl;
1342                             }
1343                         }
1344                         break;
1345                     }
1346 #endif //__WITH_DTLS__ || __WITH_TLS__
1347                 case 99:
1348                 default:
1349                     out = 1;
1350                     break;
1351             }
1352         }
1353     }
1354     catch(OCException& e)
1355     {
1356         oclog() << "Exception in main: "<<e.what();
1357     }
1358
1359     return 0;
1360 }