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