57af892c6c4aa72e35d1256ecfe4bc1149ee571f
[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
40 #define MAX_URI_LENGTH (64)
41 #define MAX_PERMISSION_LENGTH (5)
42 #define CREATE (1)
43 #define READ (2)
44 #define UPDATE (4)
45 #define DELETE (8)
46 #define NOTIFY (16)
47 #define DASH '-'
48 #define PREDEFINED_TIMEOUT (10)
49 #define MAX_OWNED_DEVICE (10)
50 #define TAG  "provisioningclient"
51
52 #define JSON_DB_PATH "./oic_svr_db_client.json"
53 #define DAT_DB_PATH "./oic_svr_db_client.dat"
54 #define DEV_STATUS_ON "DEV_STATUS_ON"
55 #define DEV_STATUS_OFF "DEV_STATUS_OFF"
56
57 #define DISCOVERY_TIMEOUT 5
58
59 using namespace OC;
60
61 DeviceList_t pUnownedDevList, pOwnedDevList;
62 static int transferDevIdx, ask = 1;
63
64 static FILE* client_open(const char *UNUSED_PARAM, const char *mode)
65 {
66     (void)UNUSED_PARAM;
67     return fopen(DAT_DB_PATH, mode);
68 }
69
70 void printMenu()
71 {
72     std::cout << "\nChoose an option:"<<std::endl;
73     std::cout << "   1. UnOwned Device discovery"<<std::endl;
74     std::cout << "   2. Owned Device discovery"<<std::endl;
75     std::cout << "   3. Ownership transfer"<<std::endl;
76     std::cout << "   4. Provision ACL"<<std::endl;
77     std::cout << "   5. Provision Credentials"<<std::endl;
78     std::cout << "   6. Credential & ACL provisioning b/w two devices"<<std::endl;
79     std::cout << "   7. Unlink Devices"<<std::endl;
80     std::cout << "   8. Remove Device"<<std::endl;
81     std::cout << "   9. Get Linked Devices"<<std::endl;
82     std::cout << "   10. Get Device Status"<<std::endl;
83     std::cout << "   11. Exit loop"<<std::endl;
84 }
85
86 void moveTransferredDevice()
87 {
88     pOwnedDevList.push_back(pUnownedDevList[transferDevIdx]);
89     pUnownedDevList.erase(pUnownedDevList.begin() + transferDevIdx);
90 }
91
92 void InputPinCB(char* pinBuf, size_t bufSize)
93 {
94     if(pinBuf)
95     {
96         std::cout <<"INPUT PIN : ";
97         std::string ptr;
98         std::cin >> ptr;
99         OICStrcpy(pinBuf, bufSize, ptr.c_str());
100         return;
101     }
102 }
103
104 void printUuid(OicUuid_t uuid)
105 {
106     for (int i = 0; i < UUID_LENGTH; i++)
107     {
108         std::cout <<std::hex << uuid.id[i] << " ";
109     }
110     std::cout<<std::endl;
111 }
112
113 void ownershipTransferCB(PMResultList_t *result, int hasError)
114 {
115     if (hasError)
116     {
117         std::cout << "Error!!! in OwnershipTransfer"<<std::endl;
118     }
119     else
120     {
121         std::cout<< "\nTransferred Ownership successfuly for device : ";
122         printUuid(result->at(0).deviceId);
123         delete result;
124
125         moveTransferredDevice();
126     }
127     ask = 1;
128 }
129
130 void printStatus(int status)
131 {
132     static std::map<int, std::string> devStatus = {{1<<0, DEV_STATUS_ON}, {1<<1, DEV_STATUS_OFF}};
133
134     std::cout <<devStatus[status] <<std::endl;
135 }
136
137 void printDevices(DeviceList_t &list)
138 {
139    for (unsigned int i = 0; i < list.size(); i++ )
140    {
141       std::cout << "Device "<< i+1 <<" ID: ";
142       std::cout << list[i]->getDeviceID() << " From IP: ";
143       std::cout << list[i]->getDevAddr() << std::endl;
144    }
145 }
146
147 /**
148  * Callback function for provisioning ACL, Credentials.
149  *
150  * @param[in]    result Result list
151  * @param[in] hasError indicates if the result has error
152  */
153 void provisionCB(PMResultList_t *result, int hasError)
154 {
155    if (hasError)
156    {
157        std::cout << "Error in provisioning operation!"<<std::endl;
158    }
159    else
160    {
161        std::cout<< "\nReceived provisioning results: ";
162        for (unsigned int i = 0; i < result->size(); i++)
163        {
164            std::cout << "Result is = " << result->at(i).res <<" for device ";
165            printUuid(result->at(i).deviceId);
166        }
167
168        delete result;
169    }
170    printMenu();
171    ask = 1;
172 }
173 /**
174  *
175  * Ask user with which devices it wants to make further actions.
176  * All possible error checks included.
177  * Default behavior in case if only one options leaves are included too.
178  * Expect that user count devices from 1, f.e. 1st, 2nd, 3rd, etc
179  * Use DeviceList_t instead of devicesCount because of print devices info
180  *
181  * @param[in] list owned devices list.
182  * @param[out] out device number array.
183  * @param[in] count how many device numbers need to read.
184  * @return 0 in case of success and other value otherwise.
185  */
186 int readDeviceNumber(DeviceList_t &list, int count, int *out)
187 {
188    if (out == NULL || count <= 0)
189    {
190       std::cout << "Error! Please put valid input parameters" << std::endl;
191       return -1;
192    }
193
194    int devicesCount = list.size();
195
196    //Print current list of owned devices
197    std::cout <<"Owned devices, count = " << devicesCount << std::endl;
198    printDevices(list);
199
200    if (devicesCount < count)
201    {
202       std::cout << "You can't proceed with selected action because Owned devices count ( ";
203       std::cout << devicesCount << " ) are less then required devices ( " << count << " ).";
204       std::cout << "You may need to discover devices again" << std::endl;
205       return -2;
206    }
207
208    std::cout << "Select " << count << " device(s) for provisioning" << std::endl;
209
210    for (int curr = 0; curr < count; curr++)
211    {
212       //select last device by default if only 1 option exist
213       //from user's point of view device counting starts from 1,
214       //so 1st, 2nd, 3rd, etc devices
215       if ((curr == count - 1) && (devicesCount == count))
216       {
217          int sum = 0;
218          for (int i = 0; i < curr; i++)
219          {
220              sum += out[i];
221          }
222
223          out[curr] = (count*(count+1))/2 - sum;
224
225          std::cout << "Device " << curr + 1 << " : " << out[curr];
226          std::cout << " - selected automatically (because no other options exist)" << std::endl;
227          break;
228       }
229
230       int choice;
231       std::cout << "Device " << curr + 1 << " : ";
232       std::cin >> choice;
233
234       if (choice < 1 || choice > devicesCount)
235       {
236          std::cout << "Error! You should enter valid device number!" << std::endl;
237          return -3;
238       }
239
240       //check that user doesn't select the same device twice
241       for (int i = 0; i < curr; i++)
242       {
243          if (out[i] == choice)
244          {
245             std::cout << "Error! You cannot select the same device twice!" << std::endl;
246             return -4;
247          }
248       }
249
250       out[curr] = choice;
251    }
252
253    //Users count devices from 1, so 1st, 2nd, 3rd, etc device
254    //But deviceList array start index is 0, so need to decrease all numbers to 1
255    for (int i = 0; i < count; i++) out[i] -= 1;
256
257    return 0;
258 }
259
260 /**
261  * Perform cleanup for ACL
262  * @param[in]    ACL
263  */
264 static void deleteACL(OicSecAcl_t *acl)
265 {
266     if (acl)
267     {
268         /* Clean Resources */
269         for (unsigned int i = 0; i < (acl)->resourcesLen; i++)
270         {
271             OICFree((acl)->resources[i]);
272         }
273         OICFree((acl)->resources);
274
275         /* Clean Owners */
276         OICFree((acl)->owners);
277
278         /* Clean ACL node itself */
279         /* Required only if acl was created in heap */
280         OICFree((acl));
281     }
282 }
283
284 /**
285  * Calculate ACL permission from string to bit
286  *
287  * @param[in] temp_psm    Input data of ACL permission string
288  * @param[in,out] pms    The pointer of ACL permission value
289  * @return  0 on success otherwise -1.
290  */
291 static int CalculateAclPermission(const char *temp_pms, uint16_t *pms)
292 {
293     int i = 0;
294
295     if (NULL == temp_pms || NULL == pms)
296     {
297         return -1;
298     }
299     *pms = 0;
300     while (temp_pms[i] != '\0')
301     {
302         switch (temp_pms[i])
303         {
304             case 'C':
305                 {
306                     *pms += CREATE;
307                     i++;
308                     break;
309                 }
310             case 'R':
311                 {
312                     *pms += READ;
313                     i++;
314                     break;
315                 }
316             case 'U':
317                 {
318                     *pms += UPDATE;
319                     i++;
320                     break;
321                 }
322             case 'D':
323                 {
324                     *pms += DELETE;
325                     i++;
326                     break;
327                 }
328             case 'N':
329                 {
330                     *pms += NOTIFY;
331                     i++;
332                     break;
333                 }
334             case '_':
335                 {
336                     i++;
337                     break;
338                 }
339             default:
340                 {
341                     return -1;
342                 }
343         }
344     }
345     return 0;
346 }
347
348 /**
349  * Get the ACL property from user
350  *
351  * @param[in]    ACL Datastructure to save user inputs
352  * @return  0 on success otherwise -1.
353  */
354 static int InputACL(OicSecAcl_t *acl)
355 {
356     int ret;
357     char *temp_id, *temp_rsc, *temp_pms;
358
359     printf("******************************************************************************\n");
360     printf("-Set ACL policy for target device\n");
361     printf("******************************************************************************\n");
362     //Set Subject.
363     printf("-URN identifying the subject\n");
364     printf("ex) 1111-1111-1111-1111 (16 Numbers except to '-')\n");
365     printf("Subject : ");
366     ret = scanf("%19ms", &temp_id);
367
368     if (1 == ret)
369     {
370         for (int i = 0, j = 0; temp_id[i] != '\0'; i++)
371         {
372             if (DASH != temp_id[i])
373                 acl->subject.id[j++] = temp_id[i];
374         }
375         OICFree(temp_id);
376     }
377     else
378     {
379         printf("Error while input\n");
380         return -1;
381     }
382
383     //Set Resource.
384     printf("Num. of Resource : ");
385     ret = scanf("%zu", &acl->resourcesLen);
386     if ((1 != ret) || (acl->resourcesLen <= 0 || acl->resourcesLen > 50))
387     {
388         printf("Error while input\n");
389         return -1;
390     }
391     printf("-URI of resource\n");
392     printf("ex)/oic/sh/temp/0 (Max_URI_Length: 64 Byte )\n");
393     acl->resources = (char **)OICCalloc(acl->resourcesLen, sizeof(char *));
394     if (NULL == acl->resources)
395     {
396         OIC_LOG(ERROR, TAG, "Error while memory allocation");
397         return -1;
398     }
399     for (size_t i = 0; i < acl->resourcesLen; i++)
400     {
401         printf("[%zu]Resource : ", i + 1);
402         ret = scanf("%64ms", &temp_rsc);
403         if (1 != ret)
404         {
405             printf("Error while input\n");
406             return -1;
407         }
408
409         acl->resources[i] = OICStrdup(temp_rsc);
410         OICFree(temp_rsc);
411         if (NULL == acl->resources[i])
412         {
413             OIC_LOG(ERROR, TAG, "Error while memory allocation");
414             return -1;
415         }
416     }
417     // Set Permission
418     do
419     {
420         printf("-Set the permission(C,R,U,D,N)\n");
421         printf("ex) CRUDN, CRU_N,..(5 Charaters)\n");
422         printf("Permission : ");
423         ret = scanf("%5ms", &temp_pms);
424         if (1 != ret)
425         {
426             printf("Error while input\n");
427             return -1;
428         }
429         ret = CalculateAclPermission(temp_pms, &(acl->permission));
430         OICFree(temp_pms);
431     } while (0 != ret );
432
433     // Set Rowner
434     printf("Num. of Rowner : ");
435     ret = scanf("%zu", &acl->ownersLen);
436     if ((1 != ret) || (acl->ownersLen <= 0 || acl->ownersLen > 20))
437     {
438         printf("Error while input\n");
439         return -1;
440     }
441     printf("-URN identifying the rowner\n");
442     printf("ex) 1111-1111-1111-1111 (16 Numbers except to '-')\n");
443     acl->owners = (OicUuid_t *)OICCalloc(acl->ownersLen, sizeof(OicUuid_t));
444     if (NULL == acl->owners)
445     {
446         OIC_LOG(ERROR, TAG, "Error while memory allocation");
447         return -1;
448     }
449     for (size_t i = 0; i < acl->ownersLen; i++)
450     {
451         printf("[%zu]Rowner : ", i + 1);
452         ret = scanf("%19ms", &temp_id);
453         if (1 != ret)
454         {
455             printf("Error while input\n");
456             return -1;
457         }
458
459         for (int k = 0, j = 0; temp_id[k] != '\0'; k++)
460         {
461             if (DASH != temp_id[k])
462             {
463                 acl->owners[i].id[j++] = temp_id[k];
464             }
465         }
466         OICFree(temp_id);
467     }
468     return 0;
469 }
470
471 static int InputCredentials(Credential &cred)
472 {
473    int choice;
474
475    do
476    {
477        std::cout << "Select credential type from following values:" << std::endl;
478        std::cout << "1:  symmetric pair-wise key" << std::endl;
479        std::cout << "2:  symmetric group key" << std::endl;
480        std::cout << "4:  asymmetric key" << std::endl;
481        std::cout << "8:  signed asymmetric key (aka certificate)" << std::endl;
482        std::cout << "16: PIN /password" << std::endl;
483        std::cout << "Your choice: ";
484
485        std::cin >> choice;
486
487        switch (choice){
488            case 1:
489                cred.setCredentialType(static_cast<OicSecCredType_t>(choice));
490                choice = 0; //validation of the accepted choice.
491                break;
492            case 2:
493            case 4:
494            case 8:
495            case 16:
496                std::cout << "selected type is not supported yet" << std::endl;
497                break;
498            default:
499                std::cout << "Error! Please select valid credential type" << std::endl;
500                break;
501        }
502    } while(0 != choice);
503
504    std::cout << "Please enter key size (valid size is 128 or 256) :";
505    std::cin >> choice;
506
507    if(128 == choice)
508    {
509        cred.setCredentialKeySize(OWNER_PSK_LENGTH_128);
510    }
511    else if(256 == choice)
512    {
513         cred.setCredentialKeySize(OWNER_PSK_LENGTH_256);
514    }
515    else
516    {
517       std::cout << "Error! Please enter valid key size!" << std::endl;
518       return -2;
519    }
520
521    return 0;
522 }
523
524 int main(void)
525 {
526     OCPersistentStorage ps {client_open, fread, fwrite, fclose, unlink };
527
528     // Create PlatformConfig object
529     PlatformConfig cfg {
530         OC::ServiceType::InProc,
531             OC::ModeType::Both,
532             "0.0.0.0",
533             0,
534             OC::QualityOfService::LowQos,
535             &ps
536     };
537
538     OCPlatform::Configure(cfg);
539
540     try
541     {
542         int choice;
543         OicSecAcl_t *acl1 = nullptr, *acl2 = nullptr;
544         if (OCSecure::provisionInit("") != OC_STACK_OK)
545         {
546             std::cout <<"PM Init failed"<< std::endl;
547             return 1;
548         }
549
550         for (int out = 0; !out;)
551         {
552             while (!ask)
553             {
554                 sleep(1);
555             }
556
557             if (acl1)
558             {
559                 deleteACL(acl1);
560                 acl1 = nullptr;
561             }
562
563             if (acl2)
564             {
565                 deleteACL(acl2);
566                 acl2 = nullptr;
567             }
568
569             printMenu();
570             std::cin >> choice;
571             switch(choice) {
572                 case 1:
573                     {
574                         //Secure resource discovery.
575
576                         pUnownedDevList.clear();
577                         std::cout << "Started discovery..." <<std::endl;
578                         OCStackResult result = OCSecure::discoverUnownedDevices(DISCOVERY_TIMEOUT,
579                                 pUnownedDevList);
580                         if (result != OC_STACK_OK)
581                         {
582                             std::cout<< "!!Error - UnOwned Discovery failed."<<std::endl;
583                         }
584                         else if (pUnownedDevList.size())
585                         {
586                             std::cout <<"Found secure devices, count = " <<
587                                 pUnownedDevList.size() << std::endl;
588                             printDevices(pUnownedDevList);
589                         }
590                         else
591                         {
592                             std::cout <<"No Secure devices found"<<std::endl;
593                         }
594                         break;
595                     }
596                 case 2:
597                     {
598                         pOwnedDevList.clear();
599                         std::cout << "Started discovery..." <<std::endl;
600                         OCStackResult result = OCSecure::discoverOwnedDevices(DISCOVERY_TIMEOUT,
601                                 pOwnedDevList);
602                         if (result != OC_STACK_OK)
603                         {
604                             std::cout<< "!!Error - Owned Discovery failed."<<std::endl;
605                         }
606                         else if (pOwnedDevList.size())
607                         {
608                             std::cout <<"Found owned devices, count = " <<
609                                 pOwnedDevList.size() << std::endl;
610                             printDevices(pOwnedDevList);
611                         }
612                         else
613                         {
614                             std::cout <<"No Secure devices found"<<std::endl;
615                         }
616                         break;
617                     }
618                 case 3:
619                     {
620                         unsigned int devNum;
621
622                         if (!pUnownedDevList.size())
623                         {
624                             std::cout <<"There are no more Unowned devices"<<std::endl;
625                             break;
626                         }
627
628                         for (unsigned int i = 0; i < pUnownedDevList.size(); i++ )
629                         {
630                             std::cout << i+1 << ": "<< pUnownedDevList[i]->getDeviceID();
631                             std::cout << " From IP:" << pUnownedDevList[i]->getDevAddr() <<std::endl;
632                         }
633
634                         std::cout <<"Select device number: "<<std::endl;
635                         std::cin >> devNum;
636                         if (devNum > pUnownedDevList.size())
637                         {
638                             std::cout <<"Invalid device number"<<std::endl;
639                             break;
640                         }
641                         transferDevIdx = devNum - 1;
642
643                         //register callbacks for JUST WORKS and PIN methods
644                         std::cout <<"Registering OTM Methods: 1. JUST WORKS and 2. PIN"<<std::endl;
645
646                         {
647                             OTMCallbackData_t justWorksCBData;
648                             justWorksCBData.loadSecretCB = LoadSecretJustWorksCallback;
649                             justWorksCBData.createSecureSessionCB =
650                                 CreateSecureSessionJustWorksCallback;
651                             justWorksCBData.createSelectOxmPayloadCB =
652                                 CreateJustWorksSelectOxmPayload;
653                             justWorksCBData.createOwnerTransferPayloadCB =
654                                 CreateJustWorksOwnerTransferPayload;
655                             OCSecure::setOwnerTransferCallbackData(OIC_JUST_WORKS,
656                                     &justWorksCBData, NULL);
657                         }
658
659                         {
660                             OTMCallbackData_t pinBasedCBData;
661                             pinBasedCBData.loadSecretCB = InputPinCodeCallback;
662                             pinBasedCBData.createSecureSessionCB =
663                                 CreateSecureSessionRandomPinCallback;
664                             pinBasedCBData.createSelectOxmPayloadCB =
665                                 CreatePinBasedSelectOxmPayload;
666                             pinBasedCBData.createOwnerTransferPayloadCB =
667                                 CreatePinBasedOwnerTransferPayload;
668                             OCSecure::setOwnerTransferCallbackData(OIC_RANDOM_DEVICE_PIN,
669                                     &pinBasedCBData, InputPinCB);
670                         }
671
672                         ask = 0;
673                         std::cout << "Transfering ownership for : "<<
674                             pUnownedDevList[devNum-1]->getDeviceID()<<std::endl;
675                         if (pUnownedDevList[devNum-1]->doOwnershipTransfer(ownershipTransferCB)
676                                 != OC_STACK_OK)
677                         {
678                             std::cout<<"OwnershipTransferCallback is failed"<<std::endl;
679                             ask = 1;
680                         }
681                         break;
682                     }
683                 case 4: //Provision ACL
684                     {
685                         int index;
686
687                         if (0 != readDeviceNumber(pOwnedDevList, 1, &index)) break;
688
689                         std::cout << "Provision ACL for : "<<
690                             pOwnedDevList[index]->getDeviceID()<< std::endl;
691
692                         acl1 = (OicSecAcl_t *)OICCalloc(1,sizeof(OicSecAcl_t));
693                         if (NULL == acl1)
694                         {
695                             OIC_LOG(ERROR, TAG, "Error while memory allocation");
696                             break;
697                         }
698
699                         std::cout << "Please input ACL for selected device: " << std::endl;
700                         if (0 != InputACL(acl1))
701                         {
702                             break;
703                         }
704
705                         ask = 0;
706
707                         if (pOwnedDevList[index]->provisionACL(acl1, provisionCB) != OC_STACK_OK)
708                         {
709                             ask = 1;
710                             std::cout <<"provisionACL is failed"<< std::endl;
711                         }
712                     }
713                     break;
714                 case 5: //Provision Credentials
715                     {
716                         int devices[2];
717
718                         if (0 != readDeviceNumber(pOwnedDevList, 2, devices)) break;
719
720                         int first  = devices[0];
721                         int second = devices[1];
722
723                         std::cout << "Provision Credentials to devices: "<<
724                             pOwnedDevList[first]->getDeviceID();
725                         std::cout << " and "<< pOwnedDevList[second]->getDeviceID() << std::endl;
726
727                         Credential cred( NO_SECURITY_MODE ,0);
728                         std::cout << "Please input credentials for selected devices: " << std::endl;
729                         if (0 != InputCredentials(cred))
730                             break;
731
732                         ask = 0;
733
734                         if (pOwnedDevList[first]->provisionCredentials(cred,
735                                     *pOwnedDevList[second].get(), provisionCB) != OC_STACK_OK)
736                         {
737                             ask = 1;
738                             std::cout <<"provisionCredentials is failed"<< std::endl;
739                         }
740                     }
741                     break;
742                 case 6: //Provision ACL & Creds b/w two devices.
743                     {
744                         int devices[2];
745
746                         if (0 != readDeviceNumber(pOwnedDevList, 2, devices)) break;
747
748                         int first  = devices[0];
749                         int second = devices[1];
750
751                         std::cout << "Provision pairwise devices: "<<
752                             pOwnedDevList[first]->getDeviceID();
753                         std::cout << " and "<< pOwnedDevList[second]->getDeviceID() << std::endl;
754
755                         Credential cred( NO_SECURITY_MODE, 0);
756                         std::cout << "Please input credentials for selected devices: " << std::endl;
757                         if (0 != InputCredentials(cred))
758                             break;
759
760                         acl1 = (OicSecAcl_t *)OICCalloc(1,sizeof(OicSecAcl_t));
761                         if (NULL == acl1)
762                         {
763                             OIC_LOG(ERROR, TAG, "Error while memory allocation");
764                             break;
765                         }
766
767                         std::cout << "Please input ACL for selected device: " << std::endl;
768                         if (0 != InputACL(acl1))
769                         {
770                             break;
771                         }
772
773                         acl2 = (OicSecAcl_t *)OICCalloc(1,sizeof(OicSecAcl_t));
774                         if (NULL == acl2)
775                         {
776                             OIC_LOG(ERROR, TAG, "Error while memory allocation");
777                             break;
778                         }
779
780                         std::cout << "Please input ACL for selected device: " << std::endl;
781                         if (0 != InputACL(acl2))
782                         {
783                             break;
784                         }
785
786                         ask = 0;
787
788                         if (pOwnedDevList[first]->provisionPairwiseDevices(cred, acl1,
789                                     *pOwnedDevList[second].get(), acl2, provisionCB) != OC_STACK_OK)
790                         {
791                             ask = 1;
792                             std::cout <<"provisionPairwiseDevices is failed"<< std::endl;
793                         }
794                     }
795                     break;
796                 case 7: //Unlink Devices
797                     {
798                         int devices[2];
799
800                         if (0 != readDeviceNumber(pOwnedDevList, 2, devices)) break;
801
802                         int first  = devices[0];
803                         int second = devices[1];
804
805                         std::cout << "Unlink devices: "<< pOwnedDevList[first]->getDeviceID();
806                         std::cout << " and "<< pOwnedDevList[second]->getDeviceID() << std::endl;
807
808                         ask = 0;
809
810                         if (pOwnedDevList[first]->unlinkDevices(*pOwnedDevList[second].get(),
811                                     provisionCB) != OC_STACK_OK)
812                         {
813                             ask = 1;
814                             std::cout <<"unlinkDevice is failed"<< std::endl;
815                         }
816                         break;
817                     }
818                 case 8: //Remove Device
819                     {
820                         int index;
821
822                         if (0 != readDeviceNumber(pOwnedDevList, 1, &index)) break;
823
824                         std::cout << "Remove Device: "<< pOwnedDevList[index]->getDeviceID()<< std::endl;
825
826                         ask = 0;
827
828                         if (pOwnedDevList[index]->removeDevice(DISCOVERY_TIMEOUT, provisionCB)
829                                 != OC_STACK_OK)
830                         {
831                             ask = 1;
832                             std::cout <<"removeDevice is failed"<< std::endl;
833                         }
834                         break;
835                     }
836                 case 9: //Get Linked devices
837                     {
838                         UuidList_t linkedUuid;
839                         unsigned int devNum;
840
841                         if (!pOwnedDevList.size())
842                         {
843                             std::cout <<"There are no Owned devices yet,"
844                                 " may need to discover"<<std::endl;
845                             break;
846                         }
847
848                         for (unsigned int i = 0; i < pOwnedDevList.size(); i++ )
849                         {
850                             std::cout << i+1 << ": "<< pOwnedDevList[i]->getDeviceID() <<" From IP:";
851                             std::cout << pOwnedDevList[i]->getDevAddr() <<std::endl;
852                         }
853
854                         std::cout <<"Select device number: "<<std::endl;
855                         std::cin >> devNum;
856                         if (devNum > pOwnedDevList.size())
857                         {
858                             std::cout <<"Invalid device number"<<std::endl;
859                             break;
860                         }
861
862                         if(pOwnedDevList[devNum  -1]->getLinkedDevices(linkedUuid) == OC_STACK_OK)
863                         {
864                             if (!linkedUuid.size())
865                             {
866                                 std::cout <<"No devices are linked to "<<
867                                     pOwnedDevList[devNum  -1]->getDeviceID() << std::endl;
868                             }
869                             //display the Linked devices (UUIDs)
870                             for(unsigned int i = 0; i < linkedUuid.size(); i++)
871                             {
872                                 printUuid(linkedUuid[i]);
873                             }
874                         }
875                         else
876                         {
877                             std::cout <<"Error! in getLinkedDevices"<<std::endl;
878                         }
879                         break;
880                     }
881                 case 10: //Get device' status
882                     {
883                         DeviceList_t unownedList, ownedList;
884
885                         if (OCSecure::getDevInfoFromNetwork(DISCOVERY_TIMEOUT, ownedList,
886                                     unownedList) == OC_STACK_OK)
887                         {
888                             std::cout <<"Owned Device' status for" <<std::endl;
889                             for (unsigned int i = 0; i < ownedList.size(); i++ )
890                             {
891                                 std::cout << "Device "<<i+1 <<" ID: '";
892                                 std::cout << ownedList[i]->getDeviceID() << "' From IP: ";
893                                 std::cout << ownedList[i]->getDevAddr() << " Status: ";
894                                 printStatus(ownedList[i]->getDeviceStatus());
895                             }
896                             std::cout <<"\nUnOwned Device' status for" <<std::endl;
897                             for (unsigned int i = 0; i < unownedList.size(); i++ )
898                             {
899                                 std::cout << "Device "<<i+1 <<" ID: '";
900                                 std::cout << unownedList[i]->getDeviceID() << "' From IP: ";
901                                 std::cout << unownedList[i]->getDevAddr() << " Status: ";
902                                 printStatus(unownedList[i]->getDeviceStatus());
903                             }
904
905                         }
906                         break;
907                     }
908
909                 case 11:
910                 default:
911                     out = 1;
912                     break;
913             }
914         }
915     }
916     catch(OCException& e)
917     {
918         oclog() << "Exception in main: "<<e.what();
919     }
920
921     return 0;
922 }