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