Added PDM Module to Provisioning APIs
[platform/upstream/iotivity.git] / resource / csdk / security / provisioning / sample / provisioningclient.c
1 /******************************************************************
2 *
3 * Copyright 2015 Samsung Electronics All Rights Reserved.
4 *
5 *
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 *      http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 ******************************************************************/
20
21 #include <stdio.h>
22 #include <string.h>
23 #include <unistd.h>
24
25 #include "logger.h"
26 #include "oic_malloc.h"
27 #include "utlist.h"
28 #include "ocprovisioningmanager.h"
29 #include "secureresourceprovider.h"
30 #include "oxmjustworks.h"
31 #include "oxmrandompin.h"
32 #include "pinoxmcommon.h"
33 #include "oic_string.h"
34
35 #define MAX_URI_LENGTH (64)
36 #define MAX_PERMISSION_LENGTH (5)
37 #define CREATE (1)
38 #define READ (2)
39 #define UPDATE (4)
40 #define DELETE (8)
41 #define NOTIFY (16)
42 #define DASH '-'
43 #define PREDEFINED_TIMEOUT (10)
44 #define MAX_OWNED_DEVICE (10)
45 #define TAG  "provisioningclient"
46
47 static char CRED_FILE[] = "oic_svr_db_client.json";
48 static OicSecAcl_t        *gAcl1 = NULL;
49 static OicSecAcl_t        *gAcl2 = NULL;
50 static int gOwnershipState = 0;
51
52 typedef enum
53 {
54     ownershipDone = 1 << 1,
55     finalizeDone = 1 << 2,
56     provisionCredDone = 1 << 3,
57     provisionAclDone = 1 << 4
58 } StateManager;
59
60
61 /**
62  * Perform cleanup for ACL
63  * @param[in]    ACL
64  */
65 static void deleteACL(OicSecAcl_t *acl)
66 {
67     if (acl)
68     {
69         /* Clean Resources */
70         for (size_t i = 0; i < (acl)->resourcesLen; i++)
71         {
72             OICFree((acl)->resources[i]);
73         }
74         OICFree((acl)->resources);
75
76         /* Clean Owners */
77         OICFree((acl)->owners);
78
79         /* Clean ACL node itself */
80         OICFree((acl));
81
82         acl = NULL;
83     }
84 }
85
86 /**
87  * Calculate ACL permission from string to bit
88  *
89  * @param[in] temp_psm    Input data of ACL permission string
90  * @param[in,out] pms    The pointer of ACL permission value
91  * @return  0 on success otherwise -1.
92  */
93 static int CalculateAclPermission(const char *temp_pms, uint16_t *pms)
94 {
95     int i = 0;
96
97     if (NULL == temp_pms || NULL == pms)
98     {
99         return -1;
100     }
101     *pms = 0;
102     while (temp_pms[i] != '\0')
103     {
104         switch (temp_pms[i])
105         {
106             case 'C':
107                 {
108                     *pms += CREATE;
109                     i++;
110                     break;
111                 }
112             case 'R':
113                 {
114                     *pms += READ;
115                     i++;
116                     break;
117                 }
118             case 'U':
119                 {
120                     *pms += UPDATE;
121                     i++;
122                     break;
123                 }
124             case 'D':
125                 {
126                     *pms += DELETE;
127                     i++;
128                     break;
129                 }
130             case 'N':
131                 {
132                     *pms += NOTIFY;
133                     i++;
134                     break;
135                 }
136             case '_':
137                 {
138                     i++;
139                     break;
140                 }
141             default:
142                 {
143                     return -1;
144                 }
145         }
146     }
147     return 0;
148 }
149
150 /**
151  * Get the ACL property from user
152  *
153  * @param[in]    ACL Datastructure to save user inputs
154  * @return  0 on success otherwise -1.
155  */
156 static int InputACL(OicSecAcl_t *acl)
157 {
158     int ret;
159     char temp_id [UUID_LENGTH + 4] = {0,};
160     char temp_rsc[MAX_URI_LENGTH + 1] = {0,};
161     char temp_pms[MAX_PERMISSION_LENGTH + 1] = {0,};
162     printf("******************************************************************************\n");
163     printf("-Set ACL policy for target device\n");
164     printf("******************************************************************************\n");
165     //Set Subject.
166     printf("-URN identifying the subject\n");
167     printf("ex) 1111-1111-1111-1111 (16 Numbers except to '-')\n");
168     printf("Subject : ");
169     char *ptr = NULL;
170     ret = scanf("%19ms", &ptr);
171     if(1==ret)
172     {
173         OICStrcpy(temp_id, sizeof(temp_id), ptr);
174         OICFree(ptr);
175     }
176     else
177     {
178          printf("Error while input\n");
179          return -1;
180     }
181     int j = 0;
182     for (int i = 0; temp_id[i] != '\0'; i++)
183     {
184         if (DASH != temp_id[i])
185         {
186             if(j>UUID_LENGTH)
187             {
188                 printf("Invalid input\n");
189                 return -1;
190             }
191             acl->subject.id[j++] = temp_id[i];
192         }
193     }
194
195     //Set Resource.
196     printf("Num. of Resource : \n");
197     ret = scanf("%zu", &acl->resourcesLen);
198     printf("-URI of resource\n");
199     printf("ex)/oic/sh/temp/0 (Max_URI_Length: 64 Byte )\n");
200     acl->resources = (char **)OICCalloc(acl->resourcesLen, sizeof(char *));
201     if (NULL == acl->resources)
202     {
203         OC_LOG(ERROR, TAG, "Error while memory allocation");
204         return -1;
205     }
206     for (size_t i = 0; i < acl->resourcesLen; i++)
207     {
208         printf("[%zu]Resource : ", i + 1);
209         char *ptr_tempRsc = NULL;
210         ret = scanf("%64ms", &ptr_tempRsc);
211         if (1==ret)
212         {
213             OICStrcpy(temp_rsc, sizeof(temp_rsc), ptr_tempRsc);
214             OICFree(ptr_tempRsc);
215         }
216         else
217         {
218             printf("Error while input\n");
219             return -1;
220         }
221         acl->resources[i] = OICStrdup(temp_rsc);
222
223         if (NULL == acl->resources[i])
224         {
225             OC_LOG(ERROR, TAG, "Error while memory allocation");
226             return -1;
227         }
228     }
229     // Set Permission
230     do
231     {
232         printf("-Set the permission(C,R,U,D,N)\n");
233         printf("ex) CRUDN, CRU_N,..(5 Charaters)\n");
234         printf("Permission : ");
235         char *ptr_temp_pms = NULL;
236         ret = scanf("%5ms", &ptr_temp_pms);
237         if(1 == ret)
238         {
239             OICStrcpy(temp_pms, sizeof(temp_pms), ptr_temp_pms);
240             OICFree(ptr_temp_pms);
241
242         }
243         else
244         {
245             printf("Error while input\n");
246             return -1;
247         }
248     }
249     while (0 != CalculateAclPermission(temp_pms, &(acl->permission)) );
250     // Set Rowner
251     printf("Num. of Rowner : ");
252     ret = scanf("%zu", &acl->ownersLen);
253     printf("-URN identifying the rowner\n");
254     printf("ex) 1111-1111-1111-1111 (16 Numbers except to '-')\n");
255     acl->owners = (OicUuid_t *)OICCalloc(acl->ownersLen, sizeof(OicUuid_t));
256     if (NULL == acl->owners)
257     {
258         OC_LOG(ERROR, TAG, "Error while memory allocation");
259         return -1;
260     }
261     for (size_t i = 0; i < acl->ownersLen; i++)
262     {
263         printf("[%zu]Rowner : ", i + 1);
264         char *ptr_temp_id = NULL;
265         ret = scanf("%19ms", &ptr_temp_id);
266         if (1 == ret)
267         {
268             OICStrcpy(temp_id, sizeof(temp_id), ptr_temp_id);
269             OICFree(ptr_temp_id);
270         }
271         else
272         {
273             printf("Error while input\n");
274             return -1;
275         }
276         j = 0;
277         for (int k = 0; temp_id[k] != '\0'; k++)
278         {
279             if (DASH != temp_id[k])
280             {
281                 acl->owners[i].id[j++] = temp_id[k];
282             }
283         }
284     }
285     return 0;
286 }
287
288
289 //FILE *client_fopen(const char *path, const char *mode)
290 FILE *client_fopen(const char* UNUSED_PARAM , const char *mode)
291 {
292     (void)UNUSED_PARAM;
293     return fopen(CRED_FILE, mode);
294 }
295
296 void PrintfResult(const char* procName, void* ctx, int nOfRes, OCProvisionResult_t *arr, bool hasError)
297 {
298     printf("-----------------------------------------------------------\n");
299     if(!hasError)
300     {
301         printf("%s was successfully done.\n", procName);
302     }
303     else
304     {
305         for(int i = 0; i < nOfRes; i++)
306         {
307             printf("UUID : ");
308             for(int j = 0; j < UUID_LENGTH; i++)
309             {
310                 printf("%c", arr[i].deviceId.id[j]);
311             }
312             printf("\t");
313             printf("Result=%d\n", arr[i].res);
314         }
315     }
316
317     if(ctx)
318     {
319         printf("Context is %s\n", (char*)ctx);
320     }
321     printf("-----------------------------------------------------------\n");
322 }
323
324 void ProvisionCredCB(void* ctx, int nOfRes, OCProvisionResult_t *arr, bool hasError)
325 {
326     if(!hasError)
327     {
328         gOwnershipState = 1;
329         PrintfResult("Provision Credential", ctx, nOfRes, arr, hasError);
330     }
331 }
332
333 void ProvisionAclCB(void* ctx, int nOfRes, OCProvisionResult_t *arr, bool hasError)
334 {
335     if(!hasError)
336     {
337         gOwnershipState = 1;
338         PrintfResult("Provision ACL", ctx, nOfRes, arr, hasError);
339     }
340 }
341
342 void ProvisionPairwiseCB(void* ctx, int nOfRes, OCProvisionResult_t *arr, bool hasError)
343 {
344     if(!hasError)
345     {
346         gOwnershipState = 1;
347         PrintfResult("Provision Pairwise Credential", ctx, nOfRes, arr, hasError);
348     }
349 }
350
351 void OwnershipTransferCB(void* ctx, int nOfRes, OCProvisionResult_t *arr, bool hasError)
352 {
353     if(!hasError)
354     {
355         gOwnershipState = 1;
356         PrintfResult("Ownership transfer", ctx, nOfRes, arr, hasError);
357     }
358 }
359
360 void InputPinCB(char* pinBuf, size_t bufSize)
361 {
362     if(pinBuf)
363     {
364         printf("INPUT PIN : ");
365         char *ptr = NULL;
366         int ret = scanf("%ms", &ptr);
367         if(1 == ret)
368         {
369             OICStrcpy(pinBuf, bufSize, ptr);
370             OICFree(ptr);
371         }
372         else
373         {
374              printf("Error in input\n");
375              return;
376         }
377     }
378 }
379
380 /**
381  * Provisioning client sample using ProvisioningAPI
382  */
383 int main()
384 {
385     OCStackResult res = OC_STACK_OK;
386     int unused;
387     (void)unused;
388
389     // Initialize Persistent Storage for SVR database
390     OCPersistentStorage ps = { .open = client_fopen,
391                                .read = fread,
392                                .write = fwrite,
393                                .close = fclose,
394                                .unlink = unlink };
395
396     OCRegisterPersistentStorageHandler(&ps);
397
398     if (OC_STACK_OK != OCInit(NULL, 0, OC_CLIENT_SERVER))
399     {
400         OC_LOG(ERROR, TAG, "OCStack init error");
401         goto error;
402     }
403
404     if (OC_STACK_OK != OCInitPM(NULL))
405     {
406         OC_LOG(ERROR, TAG, "Initializing DB failure");
407         goto error;
408     }
409
410     OCProvisionDev_t* pDeviceList = NULL;
411     res = OCDiscoverUnownedDevices(PREDEFINED_TIMEOUT, &pDeviceList);
412     if(OC_STACK_OK != res)
413     {
414         OC_LOG_V(ERROR, TAG, "Failed to PMDeviceDiscovery : %d", res);
415         goto error;
416     }
417
418     OCProvisionDev_t* pCurDev = pDeviceList;
419     int i;
420     while(pCurDev !=NULL)
421     {
422         for(i = 0; i < UUID_LENGTH; i++)
423             printf("%c", pCurDev->doxm->deviceID.id[i]);
424         printf("\n");
425         pCurDev = pCurDev->next;
426     }
427
428     //Register callback function to each OxM
429     OTMCallbackData_t justWorksCBData = {.loadSecretCB=NULL,
430                                          .createSecureSessionCB=NULL,
431                                          .createSelectOxmPayloadCB=NULL,
432                                          .createOwnerTransferPayloadCB=NULL};
433     justWorksCBData.loadSecretCB = LoadSecretJustWorksCallback;
434     justWorksCBData.createSecureSessionCB = CreateSecureSessionJustWorksCallback;
435     justWorksCBData.createSelectOxmPayloadCB = CreateJustWorksSelectOxmPayload;
436     justWorksCBData.createOwnerTransferPayloadCB = CreateJustWorksOwnerTransferPayload;
437     OTMSetOwnershipTransferCallbackData(OIC_JUST_WORKS, &justWorksCBData);
438
439     OTMCallbackData_t pinBasedCBData = {.loadSecretCB=NULL,
440                                          .createSecureSessionCB=NULL,
441                                          .createSelectOxmPayloadCB=NULL,
442                                          .createOwnerTransferPayloadCB=NULL};
443     pinBasedCBData.loadSecretCB = InputPinCodeCallback;
444     pinBasedCBData.createSecureSessionCB = CreateSecureSessionRandomPinCallbak;
445     pinBasedCBData.createSelectOxmPayloadCB = CreatePinBasedSelectOxmPayload;
446     pinBasedCBData.createOwnerTransferPayloadCB = CreatePinBasedOwnerTransferPayload;
447     OTMSetOwnershipTransferCallbackData(OIC_RANDOM_DEVICE_PIN, &pinBasedCBData);
448
449     SetInputPinCB(&InputPinCB);
450
451     char* myContext = "OTM Context";
452     //Perform ownership transfer
453     res = OCDoOwnershipTransfer((void*)myContext, pDeviceList, OwnershipTransferCB);
454     if(OC_STACK_OK == res)
455     {
456         OC_LOG(INFO, TAG, "Request for ownership transfer is sent successfully.");
457     }
458     else
459     {
460         OC_LOG_V(ERROR, TAG, "Failed to OCDoOwnershipTransfer : %d", res);
461     }
462
463     gOwnershipState = 0;
464     while ( gOwnershipState == 0 )
465     {
466         if (OCProcess() != OC_STACK_OK)
467         {
468             OC_LOG(ERROR, TAG, "OCStack process error");
469             goto error;
470         }
471         sleep(1);
472     }
473
474 // Credential & ACL provisioning between two devices.
475
476     OCProvisionDev_t *pOwnedList = NULL;
477     OCProvisionDev_t *pOwnedDevices [MAX_OWNED_DEVICE] = {0,};
478     int nOwnedDevice = 0;
479
480     res = OCDiscoverOwnedDevices(PREDEFINED_TIMEOUT, &pOwnedList);
481     if (OC_STACK_OK == res)
482     {
483         printf("################## Owned Device List #######################\n");
484         while (pOwnedList != NULL)
485         {
486             nOwnedDevice ++;
487             printf(" %d : ", nOwnedDevice);
488             for (int i = 0; i < UUID_LENGTH; i++)
489             {
490                 printf("%c", pOwnedList->doxm->deviceID.id[i]);
491             }
492             printf("\n");
493             pOwnedDevices[nOwnedDevice] = pOwnedList;
494             pOwnedList = pOwnedList->next;
495         }
496     }
497     else
498     {
499         OC_LOG(ERROR, TAG, "Error while Owned Device Discovery");
500     }
501
502     int Device1 = 0;
503     int Device2 = 0;
504
505     printf("Select 2 devices for Credential & ACL provisioning\n");
506     printf("Device 1: ");
507     unused = scanf("%d", &Device1);
508     printf("Device 2: ");
509     unused = scanf("%d", &Device2);
510
511
512     gAcl1 = (OicSecAcl_t *)OICCalloc(1,sizeof(OicSecAcl_t));
513     if (NULL == gAcl1)
514     {
515         OC_LOG(ERROR, TAG, "Error while memory allocation");
516         goto error;
517     }
518
519     gAcl2 = (OicSecAcl_t *)OICCalloc(1,sizeof(OicSecAcl_t));
520     if (NULL == gAcl2)
521     {
522         OC_LOG(ERROR, TAG, "Error while memory allocation");
523         goto error;
524     }
525
526     printf("Input ACL for Device1\n");
527     if ( 0 == InputACL(gAcl1))
528     {
529         printf("Success Input ACL\n");
530     }
531     else
532     {
533         OC_LOG(ERROR, TAG, "InputACL error");
534         goto error;
535     }
536
537     printf("Input ACL for Device2\n");
538     if (0 == InputACL(gAcl2))
539     {
540         printf("Success Input ACL\n");
541     }
542     else
543     {
544         OC_LOG(ERROR, TAG, "InputACL error");
545         goto error;
546     }
547     char *ctx = "DUMMY";
548     OCProvisionPairwiseDevices(ctx,SYMMETRIC_PAIR_WISE_KEY, OWNER_PSK_LENGTH_128, pOwnedDevices[Device1],
549                            gAcl1, pOwnedDevices[Device2], gAcl2, ProvisionPairwiseCB);
550
551     gOwnershipState = 0;
552     while ( gOwnershipState == 0 )
553     {
554         if (OCProcess() != OC_STACK_OK)
555         {
556             OC_LOG(ERROR, TAG, "OCStack process error");
557             goto error;
558         }
559         sleep(1);
560     }
561
562     if (OCStop() != OC_STACK_OK)
563     {
564         OC_LOG(ERROR, TAG, "OCStack process error");
565         goto error;
566     }
567
568 error:
569     deleteACL(gAcl1);
570     deleteACL(gAcl2);
571     OCDeleteDiscoveredDevices(pDeviceList);
572     OCDeleteDiscoveredDevices(pOwnedList);
573
574     return 0;
575 }