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