replace : iotivity -> iotivity-sec
[platform/upstream/iotivity.git] / resource / csdk / security / provisioning / src / cloud / aclid.c
1 /* *****************************************************************
2  *
3  * Copyright 2016 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 #include "utils.h"
21
22 #include "oic_malloc.h"
23 #include "logger.h"
24 #include "ocstack.h"
25 #include "ocpayload.h"
26 #include "pmutility.h"
27 #include "cacommonutil.h"
28 #include "aclresource.h"
29 #include "ocpayloadcbor.h"
30 #include "payload_logging.h"
31 #include "utlist.h"
32 #include "securevirtualresourcetypes.h"
33
34 #define TAG "OIC_CLOUD_ACL_ID"
35
36 /* Although this is already implemented in srmutility.h, we can't include the header file,
37  * because of "redefined VERIFY_NON_NULL"
38  */
39 OCStackResult ConvertUuidToStr(const OicUuid_t* uuid, char** strUuid);
40
41 /**
42  * ACL Id parse from received response
43  *
44  * @param[in] ctx       context
45  * @param[out] data     data required to external application
46  * @param[in] response  peer response
47  * @return  OCStackResult application result
48  */
49 static OCStackResult getAclIdFromResponse(void *ctx, void **data, OCClientResponse *response)
50 {
51     OC_UNUSED(ctx);
52     if (NULL == response->payload)
53     {
54         OIC_LOG(ERROR, TAG, "Receive NULL payload");
55         return OC_STACK_INVALID_PARAM;
56     }
57
58     char *aclid = NULL;
59
60     if (!OCRepPayloadGetPropString((const OCRepPayload *)response->payload, OC_RSRVD_ACL_ID, &aclid))
61     {
62         OIC_LOG_V(ERROR, TAG, "Can't get: %s", OC_RSRVD_ACL_ID);
63         return OC_STACK_MALFORMED_RESPONSE;
64     }
65
66     OIC_LOG_V(INFO, TAG, "Received Acl id = %s", aclid);
67
68     *data = aclid;
69     return OC_STACK_OK;
70 }
71
72 /**
73  * ACL Id by device request received data handler
74  *
75  * @param[in] ctx       context
76  * @param[out] data     data required to external application
77  * @param[in] response  peer response
78  * @return  OCStackResult application result
79  */
80 static OCStackResult handleGetAclIdByDeviceResponse(void *ctx, void **data,
81                                                     OCClientResponse *response)
82 {
83     return getAclIdFromResponse(ctx, data, response);
84 }
85
86 /**
87  * ACL Id create request received data handler
88  *
89  * @param[in] ctx       context
90  * @param[out] data     data required to external application
91  * @param[in] response  peer response
92  * @return  OCStackResult application result
93  */
94 static OCStackResult handleAclIdCreateResponse(void *ctx, void **data, OCClientResponse *response)
95 {
96     return getAclIdFromResponse(ctx, data, response);
97 }
98
99 OCStackResult OCCloudGetAclIdByDevice(void* ctx,
100                                       const char *deviceId,
101                                       const OCDevAddr *endPoint,
102                                       OCCloudResponseCB callback)
103 {
104     char uri[MAX_URI_LENGTH] = { 0 };
105
106     VERIFY_NON_NULL_RET(endPoint, TAG, "NULL endpoint", OC_STACK_INVALID_PARAM);
107     VERIFY_NON_NULL_RET(deviceId, TAG, "NULL input param", OC_STACK_INVALID_PARAM);
108
109     snprintf(uri, MAX_URI_LENGTH, "%s%s:%d%s?%s=%s", DEFAULT_PREFIX,
110             endPoint->addr, endPoint->port, OC_RSRVD_ACL_ID_URL, OC_RSRVD_DEVICE_ID, deviceId);
111
112     OCCallbackData cbData;
113     fillCallbackData(&cbData, ctx, callback, handleGetAclIdByDeviceResponse, NULL);
114
115     return OCDoResource(NULL, OC_REST_GET, uri, NULL, NULL,
116                         CT_ADAPTER_TCP, OC_LOW_QOS, &cbData, NULL, 0);
117 }
118
119 OCStackResult OCCloudAclIdCreate(void* ctx,
120                                  const char *ownerId,
121                                  const char *deviceId,
122                                  const OCDevAddr *endPoint,
123                                  OCCloudResponseCB callback)
124 {
125     char uri[MAX_URI_LENGTH] = { 0 };
126
127     VERIFY_NON_NULL_RET(endPoint, TAG, "NULL endpoint", OC_STACK_INVALID_PARAM);
128     VERIFY_NON_NULL_RET(ownerId, TAG, "NULL input param", OC_STACK_INVALID_PARAM);
129     VERIFY_NON_NULL_RET(deviceId, TAG, "NULL input param", OC_STACK_INVALID_PARAM);
130
131     snprintf(uri, MAX_URI_LENGTH, "%s%s:%d%s?%s=%s&%s=%s", DEFAULT_PREFIX,
132             endPoint->addr, endPoint->port, OC_RSRVD_ACL_ID_URL,
133             OC_RSRVD_OWNER_ID, ownerId, OC_RSRVD_DEVICE_ID, deviceId);
134
135     OCCallbackData cbData;
136     fillCallbackData(&cbData, ctx, callback, handleAclIdCreateResponse, NULL);
137
138     return OCDoResource(NULL, OC_REST_PUT, uri, NULL, NULL,
139                         CT_ADAPTER_TCP, OC_LOW_QOS, &cbData, NULL, 0);
140 }
141
142 OCStackResult OCCloudAclIdDelete(void* ctx,
143                                  const char *aclId,
144                                  const OCDevAddr *endPoint,
145                                  OCCloudResponseCB callback)
146 {
147     char uri[MAX_URI_LENGTH]  = { 0 };
148
149     VERIFY_NON_NULL_RET(endPoint, TAG, "NULL endpoint", OC_STACK_INVALID_PARAM);
150     VERIFY_NON_NULL_RET(aclId, TAG, "NULL input param", OC_STACK_INVALID_PARAM);
151
152     snprintf(uri, MAX_URI_LENGTH, "%s%s:%d%s?%s=%s", DEFAULT_PREFIX,
153             endPoint->addr, endPoint->port, OC_RSRVD_ACL_ID_URL, OC_RSRVD_ACL_ID, aclId);
154
155     OCCallbackData cbData;
156     fillCallbackData(&cbData, ctx, callback, NULL, NULL);
157
158     return OCDoResource(NULL, OC_REST_DELETE, uri, NULL, NULL,
159                         CT_ADAPTER_TCP, OC_LOW_QOS, &cbData, NULL, 0);
160 }
161
162 /**
163  * ACL Get Info received data handler
164  *
165  * @param[in] ctx       context
166  * @param[out] data     data required to external application
167  * @param[in] response  peer response
168  * @return  OCStackResult application result
169  */
170 static OCStackResult handleAclGetInfoResponse(void *ctx, void **data, OCClientResponse *response)
171 {
172     OCStackResult result = OC_STACK_OK;
173     uint8_t *cbor = NULL;
174     size_t size   = 0;
175
176     OC_UNUSED(ctx);
177     OC_UNUSED(data);
178
179     if (NULL == response->payload)
180     {
181         OIC_LOG(ERROR, TAG, "Receive NULL payload\n");
182         return OC_STACK_INVALID_PARAM;
183     }
184
185     result = OCConvertPayload(response->payload, &cbor, &size);
186     if (result != OC_STACK_OK)
187     {
188         OIC_LOG(ERROR, TAG, "Can't convert OCPayload to cbor");
189         goto exit;
190     }
191
192     OicSecAcl_t* acl = CBORPayloadToAcl2(cbor, size);
193     if (NULL == acl)
194     {
195         OIC_LOG(ERROR, TAG, "Can't parse CBOR payload");
196         goto exit;
197     }
198
199     printACL(acl);
200
201     result = InstallACL(acl);
202     if (result != OC_STACK_OK)
203     {
204         OIC_LOG(ERROR, TAG, "Can't update ACL resource");
205     }
206
207     *data = acl;
208 exit:
209     OICFree(cbor);
210     return result;
211 }
212
213 OCStackResult OCCloudAclIndividualGetInfo(void* ctx,
214                                           const char *aclId,
215                                           const OCDevAddr *endPoint,
216                                           OCCloudResponseCB callback)
217 {
218     char uri[MAX_URI_LENGTH]  = { 0 };
219
220     VERIFY_NON_NULL_RET(endPoint, TAG, "NULL endpoint", OC_STACK_INVALID_PARAM);
221     VERIFY_NON_NULL_RET(aclId, TAG, "NULL input param", OC_STACK_INVALID_PARAM);
222
223     snprintf(uri, MAX_URI_LENGTH, "%s%s:%d%s/%s", DEFAULT_PREFIX,
224             endPoint->addr, endPoint->port, OC_RSRVD_ACL_ID_URL, aclId);
225
226     OCCallbackData cbData;
227     fillCallbackData(&cbData, ctx, callback, handleAclGetInfoResponse, NULL);
228
229     return OCDoResource(NULL, OC_REST_GET, uri, NULL, NULL,
230                         CT_ADAPTER_TCP, OC_LOW_QOS, &cbData, NULL, 0);
231 }
232
233 OCStackResult OCCloudAclIndividualUpdateAce(void* ctx,
234                                             const char *aclId,
235                                             const cloudAce_t *aces,
236                                             const OCDevAddr *endPoint,
237                                             OCCloudResponseCB callback)
238 {
239     size_t dimensions[MAX_REP_ARRAY_DEPTH] = { 0 };
240     char uri[MAX_URI_LENGTH]  = { 0 };
241
242     int i = 0, j = 0;
243
244     OCRepPayload **helperPayload  = NULL;
245     OCRepPayload **helperPayload2 = NULL;
246
247     VERIFY_NON_NULL_RET(endPoint, TAG, "NULL endpoint", OC_STACK_INVALID_PARAM);
248     VERIFY_NON_NULL_RET(aclId, TAG, "NULL input param", OC_STACK_INVALID_PARAM);
249     VERIFY_NON_NULL_RET(aces, TAG, "NULL input param", OC_STACK_INVALID_PARAM);
250
251     snprintf(uri, MAX_URI_LENGTH, "%s%s:%d%s/%s", DEFAULT_PREFIX,
252             endPoint->addr, endPoint->port, OC_RSRVD_ACL_ID_URL, aclId);
253
254     OCRepPayload *payload = OCRepPayloadCreate();
255     if (!payload)
256     {
257         OIC_LOG_V(DEBUG, TAG, "Can't allocate memory for payload");
258         goto no_memory;
259     }
260
261     int acllist_count = 0;
262     //code below duplicates LL_COUNT, implemented in newer version of utlist.h
263     {
264         cloudAce_t *ace = (cloudAce_t*)aces;
265         while (ace)
266         {
267             ace = ace->next;
268             acllist_count++;
269         }
270     }
271
272     helperPayload = OICCalloc(acllist_count, sizeof(OCRepPayload *));
273     if (!helperPayload)
274     {
275         OIC_LOG_V(DEBUG, TAG, "Can't allocate memory for helperPayload");
276         goto no_memory;
277     }
278
279     i = 0;
280     cloudAce_t *ace = NULL;
281
282     LL_FOREACH((cloudAce_t*)aces, ace)
283     {
284         OCRepPayload *payload = OCRepPayloadCreate();
285         if (!payload)
286         {
287             OIC_LOG_V(DEBUG, TAG, "Can't allocate memory for helperPayload[i]");
288             goto no_memory;
289         }
290         helperPayload[i++] = payload;
291
292         char *uuid = NULL;
293         if (OC_STACK_OK != ConvertUuidToStr(&ace->subjectuuid, &uuid))
294         {
295             OIC_LOG(ERROR, TAG, "Can't convert subjectuuid to string");
296         }
297
298         OCRepPayloadSetPropString(payload, OC_RSRVD_SUBJECT_UUID, (const char *)uuid);
299         OCRepPayloadSetPropInt(payload, OC_RSRVD_SUBJECT_TYPE, ace->stype);
300         OCRepPayloadSetPropInt(payload, OC_RSRVD_PERMISSION_MASK, ace->permission);
301
302         OICFree(uuid);
303
304         int reslist_count = 0;
305         //code below duplicates LL_COUNT, implemented in newer version of utlist.h
306         {
307             OicSecRsrc_t *res = ace->resources;
308             while (res)
309             {
310                 res = res->next;
311                 reslist_count++;
312             }
313         }
314
315         helperPayload2 = OICCalloc(reslist_count, sizeof(OCRepPayload *));
316         if (!helperPayload2)
317         {
318             goto no_memory;
319         }
320
321         j = 0;
322         OicSecRsrc_t *res = NULL;
323
324         LL_FOREACH(ace->resources, res)
325         {
326             OCRepPayload *payload = OCRepPayloadCreate();
327             if (!payload)
328             {
329                 OIC_LOG_V(DEBUG, TAG, "Can't allocate memory for helperPayload2[j]");
330                 goto no_memory;
331             }
332             helperPayload2[j++] = payload;
333
334             OCRepPayloadSetPropString(payload, OC_RSRVD_HREF, res->href);
335
336             dimensions[0] = res->typeLen;
337             OCRepPayloadSetStringArray(payload, OC_RSRVD_RESOURCE_TYPE,
338                                        (const char **)res->types, dimensions);
339
340             dimensions[0] = res->interfaceLen;
341             OCRepPayloadSetStringArray(payload, OC_RSRVD_INTERFACE,
342                                        (const char **)res->interfaces, dimensions);
343         }
344         dimensions[0] = reslist_count;
345         OCRepPayloadSetPropObjectArray(payload, OC_RSRVD_RESOURCES,
346                 (const OCRepPayload **)helperPayload2, dimensions);
347     }
348     dimensions[0] = acllist_count;
349     OCRepPayloadSetPropObjectArray(payload, OC_RSRVD_ACCESS_CONTROL_LIST,
350             (const OCRepPayload **)helperPayload, dimensions);
351
352     OCCallbackData cbData;
353     fillCallbackData(&cbData, ctx, callback, NULL, NULL);
354
355     OIC_LOG(DEBUG, TAG, "Next payload created:");
356     OIC_LOG_PAYLOAD(DEBUG, (OCPayload *)payload);
357
358     return OCDoResource(NULL, OC_REST_POST, uri, NULL, (OCPayload *)payload,
359                         CT_ADAPTER_TCP, OC_LOW_QOS, &cbData, NULL, 0);
360 no_memory:
361     if (helperPayload2)
362     {
363         for (int k = 0; k < j; k++) OCRepPayloadDestroy(helperPayload2[k]);
364         OICFree(helperPayload2);
365     }
366     if (helperPayload)
367     {
368         for (int k = 0; k < i; k++) OCRepPayloadDestroy(helperPayload[k]);
369         OICFree(helperPayload);
370     }
371     OCRepPayloadDestroy(payload);
372     return OC_STACK_NO_MEMORY;
373 }
374
375 OCStackResult OCCloudAclIndividualUpdate(void* ctx,
376                                             const char *aclId,
377                                             const char *aceId,
378                                             const cloudAce_t *aces,
379                                             const OCDevAddr *endPoint,
380                                             OCCloudResponseCB callback)
381 {
382     size_t dimensions[MAX_REP_ARRAY_DEPTH] = { 0 };
383     char uri[MAX_URI_LENGTH]  = { 0 };
384
385     int i = 0, j = 0;
386
387     OCRepPayload **helperPayload  = NULL;
388     OCRepPayload **helperPayload2 = NULL;
389
390     VERIFY_NON_NULL_RET(endPoint, TAG, "NULL endpoint", OC_STACK_INVALID_PARAM);
391     VERIFY_NON_NULL_RET(aclId, TAG, "NULL input param", OC_STACK_INVALID_PARAM);
392     VERIFY_NON_NULL_RET(aces, TAG, "NULL input param", OC_STACK_INVALID_PARAM);
393
394     snprintf(uri, MAX_URI_LENGTH, "%s%s:%d%s/%s?%s=%s", DEFAULT_PREFIX,
395             endPoint->addr, endPoint->port, OC_RSRVD_ACL_ID_URL, aclId,
396             OC_RSRVD_ACE_ID, aceId);
397
398     OCRepPayload *payload = OCRepPayloadCreate();
399     if (!payload)
400     {
401         OIC_LOG_V(DEBUG, TAG, "Can't allocate memory for payload");
402         goto no_memory;
403     }
404
405     int acllist_count = 1;
406
407     helperPayload = OICCalloc(acllist_count, sizeof(OCRepPayload *));
408     if (!helperPayload)
409     {
410         OIC_LOG_V(DEBUG, TAG, "Can't allocate memory for helperPayload");
411         goto no_memory;
412     }
413
414     i = 0;
415     cloudAce_t *ace = NULL;
416
417     LL_FOREACH((cloudAce_t*)aces, ace)
418     {
419         OCRepPayload *payload = OCRepPayloadCreate();
420         if (!payload)
421         {
422             OIC_LOG_V(DEBUG, TAG, "Can't allocate memory for helperPayload[i]");
423             goto no_memory;
424         }
425         helperPayload[i++] = payload;
426
427         char *uuid = NULL;
428         if (OC_STACK_OK != ConvertUuidToStr(&ace->subjectuuid, &uuid))
429         {
430             OIC_LOG(ERROR, TAG, "Can't convert subjectuuid to string");
431         }
432
433         OCRepPayloadSetPropString(payload, OC_RSRVD_SUBJECT_UUID, (const char *)uuid);
434         OCRepPayloadSetPropInt(payload, OC_RSRVD_SUBJECT_TYPE, ace->stype);
435         OCRepPayloadSetPropInt(payload, OC_RSRVD_PERMISSION_MASK, ace->permission);
436
437         OICFree(uuid);
438
439         int reslist_count = 0;
440         //code below duplicates LL_COUNT, implemented in newer version of utlist.h
441         {
442             OicSecRsrc_t *res = ace->resources;
443             while (res)
444             {
445                 res = res->next;
446                 reslist_count++;
447             }
448         }
449
450         helperPayload2 = OICCalloc(reslist_count, sizeof(OCRepPayload *));
451         if (!helperPayload2)
452         {
453             goto no_memory;
454         }
455
456         j = 0;
457         OicSecRsrc_t *res = NULL;
458
459         LL_FOREACH(ace->resources, res)
460         {
461             OCRepPayload *payload = OCRepPayloadCreate();
462             if (!payload)
463             {
464                 OIC_LOG_V(DEBUG, TAG, "Can't allocate memory for helperPayload2[j]");
465                 goto no_memory;
466             }
467             helperPayload2[j++] = payload;
468
469             OCRepPayloadSetPropString(payload, OC_RSRVD_HREF, res->href);
470
471             dimensions[0] = res->typeLen;
472             OCRepPayloadSetStringArray(payload, OC_RSRVD_RESOURCE_TYPE,
473                                        (const char **)res->types, dimensions);
474
475             dimensions[0] = res->interfaceLen;
476             OCRepPayloadSetStringArray(payload, OC_RSRVD_INTERFACE,
477                                        (const char **)res->interfaces, dimensions);
478         }
479         dimensions[0] = reslist_count;
480         OCRepPayloadSetPropObjectArray(payload, OC_RSRVD_RESOURCES,
481                 (const OCRepPayload **)helperPayload2, dimensions);
482     }
483     dimensions[0] = acllist_count;
484     OCRepPayloadSetPropObjectArray(payload, OC_RSRVD_ACCESS_CONTROL_LIST,
485             (const OCRepPayload **)helperPayload, dimensions);
486
487     OCCallbackData cbData;
488     fillCallbackData(&cbData, ctx, callback, NULL, NULL);
489
490     OIC_LOG(DEBUG, TAG, "Next payload created:");
491     OIC_LOG_PAYLOAD(DEBUG, (OCPayload *)payload);
492
493     return OCDoResource(NULL, OC_REST_POST, uri, NULL, (OCPayload *)payload,
494                         CT_ADAPTER_TCP, OC_LOW_QOS, &cbData, NULL, 0);
495 no_memory:
496     if (helperPayload2)
497     {
498         for (int k = 0; k < j; k++) OCRepPayloadDestroy(helperPayload2[k]);
499         OICFree(helperPayload2);
500     }
501     if (helperPayload)
502     {
503         for (int k = 0; k < i; k++) OCRepPayloadDestroy(helperPayload[k]);
504         OICFree(helperPayload);
505     }
506     OCRepPayloadDestroy(payload);
507     return OC_STACK_NO_MEMORY;
508 }
509
510
511
512 OCStackResult OCCloudAclIndividualDelete(void* ctx,
513                                          const char *aclId,
514                                          const OCDevAddr *endPoint,
515                                          OCCloudResponseCB callback)
516 {
517     char uri[MAX_URI_LENGTH]  = { 0 };
518
519     VERIFY_NON_NULL_RET(endPoint, TAG, "NULL endpoint", OC_STACK_INVALID_PARAM);
520     VERIFY_NON_NULL_RET(aclId, TAG, "NULL input param", OC_STACK_INVALID_PARAM);
521
522     snprintf(uri, MAX_URI_LENGTH, "%s%s:%d%s/%s", DEFAULT_PREFIX,
523             endPoint->addr, endPoint->port, OC_RSRVD_ACL_ID_URL, aclId);
524
525     OCCallbackData cbData;
526     fillCallbackData(&cbData, ctx, callback, NULL, NULL);
527
528     return OCDoResource(NULL, OC_REST_DELETE, uri, NULL, NULL,
529                         CT_ADAPTER_TCP, OC_LOW_QOS, &cbData, NULL, 0);
530 }
531
532 OCStackResult OCCloudAclIndividualDeleteAce(void* ctx,
533                                          const char *aclId,
534                                          const char *aceId,
535                                          const OCDevAddr *endPoint,
536                                          OCCloudResponseCB callback)
537 {
538     char uri[MAX_URI_LENGTH]  = { 0 };
539
540     VERIFY_NON_NULL_RET(endPoint, TAG, "NULL endpoint", OC_STACK_INVALID_PARAM);
541     VERIFY_NON_NULL_RET(aclId, TAG, "NULL input param", OC_STACK_INVALID_PARAM);
542
543     snprintf(uri, MAX_URI_LENGTH, "%s%s:%d%s/%s?%s=%s", DEFAULT_PREFIX,
544             endPoint->addr, endPoint->port, OC_RSRVD_ACL_ID_URL, aclId,
545             OC_RSRVD_ACE_ID, aceId);
546
547     OCCallbackData cbData;
548     fillCallbackData(&cbData, ctx, callback, NULL, NULL);
549
550     return OCDoResource(NULL, OC_REST_DELETE, uri, NULL, NULL,
551                         CT_ADAPTER_TCP, OC_LOW_QOS, &cbData, NULL, 0);
552 }
553
554 OCStackResult ConvertUuidToStr(const OicUuid_t* uuid, char** strUuid)
555 {
556     if (NULL == uuid || NULL == strUuid || NULL != *strUuid)
557     {
558         OIC_LOG(ERROR, TAG, "ConvertUuidToStr : Invalid param");
559         return OC_STACK_INVALID_PARAM;
560     }
561
562     size_t uuidIdx = 0;
563     size_t urnIdx = 0;
564     const size_t urnBufSize = (UUID_LENGTH * 2) + 4 + 1;
565     char *convertedUrn = (char*)OICCalloc(urnBufSize, sizeof(char));
566     VERIFY_NON_NULL(convertedUrn, TAG, "OICCalloc() is failed(convertedUrn)");
567
568     for (uuidIdx = 0, urnIdx = 0; uuidIdx < UUID_LENGTH && urnIdx < urnBufSize;
569             uuidIdx++, urnIdx += 2)
570     {
571         // canonical format for UUID has '8-4-4-4-12'
572         if (4 == uuidIdx || 6 == uuidIdx || 8 == uuidIdx || 10 == uuidIdx)
573         {
574             snprintf(convertedUrn + urnIdx, 2, "%c", '-');
575             urnIdx++;
576         }
577         snprintf(convertedUrn + urnIdx, 3, "%02x", (uint8_t)(uuid->id[uuidIdx]));
578     }
579     convertedUrn[urnBufSize - 1] = '\0';
580
581     *strUuid = convertedUrn;
582     return OC_STACK_OK;
583 }