[IOT-1347] OCCloudAclIdCreate or OCCloudAclIdGetByDevice API doesn't provide the...
[platform/upstream/iotivity.git] / resource / csdk / security / provisioning / src / cloud / aclid.c
1 #include "utils.h"
2
3 #include "oic_malloc.h"
4 #include "logger.h"
5 #include "ocstack.h"
6 #include "ocpayload.h"
7 #include "pmutility.h"
8 #include "srmutility.h"
9 #include "cacommonutil.h"
10 #include "aclresource.h"
11 #include "ocpayloadcbor.h"
12 #include "payload_logging.h"
13 #include "utlist.h"
14
15 #define TAG "CLOUD-ACL-ID"
16
17 /**
18  * ACL Id parse from received response
19  *
20  * @param[in] ctx       context
21  * @param[out] data     data required to external application
22  * @param[in] response  peer response
23  * @return  OCStackResult application result
24  */
25 static OCStackResult getAclIdFromResponse(void *ctx, void **data, OCClientResponse *response)
26 {
27     OC_UNUSED(ctx);
28     if (NULL == response->payload)
29     {
30         OIC_LOG(ERROR, TAG, "Receive NULL payload");
31         return OC_STACK_INVALID_PARAM;
32     }
33
34     char *aclid = NULL;
35
36     if (!OCRepPayloadGetPropString((const OCRepPayload *)response->payload, OC_RSRVD_ACL_ID, &aclid))
37     {
38         OIC_LOG_V(ERROR, TAG, "Can't get: %s", OC_RSRVD_ACL_ID);
39         return OC_STACK_MALFORMED_RESPONSE;
40     }
41
42     OIC_LOG_V(INFO, TAG, "Received Acl id = %s", aclid);
43
44     *data = aclid;
45     return OC_STACK_OK;
46 }
47
48 /**
49  * ACL Id by device request received data handler
50  *
51  * @param[in] ctx       context
52  * @param[out] data     data required to external application
53  * @param[in] response  peer response
54  * @return  OCStackResult application result
55  */
56 static OCStackResult handleGetAclIdByDeviceResponse(void *ctx, void **data,
57                                                     OCClientResponse *response)
58 {
59     return getAclIdFromResponse(ctx, data, response);
60 }
61
62 /**
63  * ACL Id create request received data handler
64  *
65  * @param[in] ctx       context
66  * @param[out] data     data required to external application
67  * @param[in] response  peer response
68  * @return  OCStackResult application result
69  */
70 static OCStackResult handleAclIdCreateResponse(void *ctx, void **data, OCClientResponse *response)
71 {
72     return getAclIdFromResponse(ctx, data, response);
73 }
74
75 OCStackResult OCCloudGetAclIdByDevice(void* ctx,
76                                       const char *deviceId,
77                                       const OCDevAddr *endPoint,
78                                       OCCloudResponseCB callback)
79 {
80     char uri[MAX_URI_LENGTH] = { 0 };
81
82     VERIFY_NON_NULL_RET(endPoint, TAG, "NULL endpoint", OC_STACK_INVALID_PARAM);
83     VERIFY_NON_NULL_RET(deviceId, TAG, "NULL input param", OC_STACK_INVALID_PARAM);
84
85     snprintf(uri, MAX_URI_LENGTH, "%s%s:%d%s?%s=%s", DEFAULT_PREFIX,
86             endPoint->addr, endPoint->port, OC_RSRVD_ACL_ID_URL, OC_RSRVD_DEVICE_ID, deviceId);
87
88     OCCallbackData cbData;
89     fillCallbackData(&cbData, ctx, callback, handleGetAclIdByDeviceResponse, NULL);
90
91     return OCDoResource(NULL, OC_REST_GET, uri, NULL, NULL,
92                         CT_ADAPTER_TCP, OC_LOW_QOS, &cbData, NULL, 0);
93 }
94
95 OCStackResult OCCloudAclIdCreate(void* ctx,
96                                  const char *ownerId,
97                                  const char *deviceId,
98                                  const OCDevAddr *endPoint,
99                                  OCCloudResponseCB callback)
100 {
101     char uri[MAX_URI_LENGTH] = { 0 };
102
103     VERIFY_NON_NULL_RET(endPoint, TAG, "NULL endpoint", OC_STACK_INVALID_PARAM);
104     VERIFY_NON_NULL_RET(ownerId, TAG, "NULL input param", OC_STACK_INVALID_PARAM);
105     VERIFY_NON_NULL_RET(deviceId, TAG, "NULL input param", OC_STACK_INVALID_PARAM);
106
107     snprintf(uri, MAX_URI_LENGTH, "%s%s:%d%s?%s=%s&%s=%s", DEFAULT_PREFIX,
108             endPoint->addr, endPoint->port, OC_RSRVD_ACL_ID_URL,
109             OC_RSRVD_OWNER_ID, ownerId, OC_RSRVD_DEVICE_ID, deviceId);
110
111     OCCallbackData cbData;
112     fillCallbackData(&cbData, ctx, callback, handleAclIdCreateResponse, NULL);
113
114     return OCDoResource(NULL, OC_REST_PUT, uri, NULL, NULL,
115                         CT_ADAPTER_TCP, OC_LOW_QOS, &cbData, NULL, 0);
116 }
117
118 OCStackResult OCCloudAclIdDelete(void* ctx,
119                                  const char *aclId,
120                                  const OCDevAddr *endPoint,
121                                  OCCloudResponseCB callback)
122 {
123     char uri[MAX_URI_LENGTH]  = { 0 };
124
125     VERIFY_NON_NULL_RET(endPoint, TAG, "NULL endpoint", OC_STACK_INVALID_PARAM);
126     VERIFY_NON_NULL_RET(aclId, TAG, "NULL input param", OC_STACK_INVALID_PARAM);
127
128     snprintf(uri, MAX_URI_LENGTH, "%s%s:%d%s?%s=%s", DEFAULT_PREFIX,
129             endPoint->addr, endPoint->port, OC_RSRVD_ACL_ID_URL, OC_RSRVD_ACL_ID, aclId);
130
131     OCCallbackData cbData;
132     fillCallbackData(&cbData, ctx, callback, NULL, NULL);
133
134     return OCDoResource(NULL, OC_REST_DELETE, uri, NULL, NULL,
135                         CT_ADAPTER_TCP, OC_LOW_QOS, &cbData, NULL, 0);
136 }
137
138 /**
139  * ACL Get Info received data handler
140  *
141  * @param[in] ctx       context
142  * @param[out] data     data required to external application
143  * @param[in] response  peer response
144  * @return  OCStackResult application result
145  */
146 static OCStackResult handleAclGetInfoResponse(void *ctx, void **data, OCClientResponse *response)
147 {
148     OCStackResult result = OC_STACK_OK;
149     uint8_t *cbor = NULL;
150     size_t size   = 0;
151
152     OC_UNUSED(ctx);
153     OC_UNUSED(data);
154
155     if (NULL == response->payload)
156     {
157         OIC_LOG(ERROR, TAG, "Receive NULL payload\n");
158         return OC_STACK_INVALID_PARAM;
159     }
160
161     result = OCConvertPayload(response->payload, &cbor, &size);
162     if (result != OC_STACK_OK)
163     {
164         OIC_LOG(ERROR, TAG, "Can't convert OCPayload to cbor");
165         goto exit;
166     }
167
168     OicSecAcl_t* acl = CBORPayloadToAcl2(cbor, size);
169     if (NULL == acl)
170     {
171         OIC_LOG(ERROR, TAG, "Can't parse CBOR payload");
172         goto exit;
173     }
174
175     printACL(acl);
176
177     result = InstallNewACL2(acl);
178     if (result != OC_STACK_OK)
179     {
180         OIC_LOG(ERROR, TAG, "Can't update ACL resource");
181     }
182
183     *data = acl;
184 exit:
185     OICFree(cbor);
186     return result;
187 }
188
189 OCStackResult OCCloudAclIndividualGetInfo(void* ctx,
190                                           const char *aclId,
191                                           const OCDevAddr *endPoint,
192                                           OCCloudResponseCB callback)
193 {
194     char uri[MAX_URI_LENGTH]  = { 0 };
195
196     VERIFY_NON_NULL_RET(endPoint, TAG, "NULL endpoint", OC_STACK_INVALID_PARAM);
197     VERIFY_NON_NULL_RET(aclId, TAG, "NULL input param", OC_STACK_INVALID_PARAM);
198
199     snprintf(uri, MAX_URI_LENGTH, "%s%s:%d%s/%s", DEFAULT_PREFIX,
200             endPoint->addr, endPoint->port, OC_RSRVD_ACL_ID_URL, aclId);
201
202     OCCallbackData cbData;
203     fillCallbackData(&cbData, ctx, callback, handleAclGetInfoResponse, NULL);
204
205     return OCDoResource(NULL, OC_REST_GET, uri, NULL, NULL,
206                         CT_ADAPTER_TCP, OC_LOW_QOS, &cbData, NULL, 0);
207 }
208
209 OCStackResult OCCloudAclIndividualUpdateAce(void* ctx,
210                                             const char *aclId,
211                                             const cloudAce_t *aces,
212                                             const OCDevAddr *endPoint,
213                                             OCCloudResponseCB callback)
214 {
215     size_t dimensions[MAX_REP_ARRAY_DEPTH] = { 0 };
216     char uri[MAX_URI_LENGTH]  = { 0 };
217
218     int i = 0, j = 0;
219
220     OCRepPayload **helperPayload  = NULL;
221     OCRepPayload **helperPayload2 = NULL;
222
223     VERIFY_NON_NULL_RET(endPoint, TAG, "NULL endpoint", OC_STACK_INVALID_PARAM);
224     VERIFY_NON_NULL_RET(aclId, TAG, "NULL input param", OC_STACK_INVALID_PARAM);
225     VERIFY_NON_NULL_RET(aces, TAG, "NULL input param", OC_STACK_INVALID_PARAM);
226
227     snprintf(uri, MAX_URI_LENGTH, "%s%s:%d%s/%s", DEFAULT_PREFIX,
228             endPoint->addr, endPoint->port, OC_RSRVD_ACL_ID_URL, aclId);
229
230     OCRepPayload *payload = OCRepPayloadCreate();
231     if (!payload)
232     {
233         OIC_LOG_V(DEBUG, TAG, "Can't allocate memory for payload");
234         goto no_memory;
235     }
236
237     int acllist_count = 0;
238     //code below duplicates LL_COUNT, implemented in newer version of utlist.h
239     {
240         cloudAce_t *ace = (cloudAce_t*)aces;
241         while (ace)
242         {
243             ace = ace->next;
244             acllist_count++;
245         }
246     }
247
248     helperPayload = OICCalloc(acllist_count, sizeof(OCRepPayload *));
249     if (!helperPayload)
250     {
251         OIC_LOG_V(DEBUG, TAG, "Can't allocate memory for helperPayload");
252         goto no_memory;
253     }
254
255     i = 0;
256     cloudAce_t *ace = NULL;
257
258     LL_FOREACH((cloudAce_t*)aces, ace)
259     {
260         OCRepPayload *payload = OCRepPayloadCreate();
261         if (!payload)
262         {
263             OIC_LOG_V(DEBUG, TAG, "Can't allocate memory for helperPayload[i]");
264             goto no_memory;
265         }
266         helperPayload[i++] = payload;
267
268         char *uuid = NULL;
269         if (OC_STACK_OK != ConvertUuidToStr(&ace->subjectuuid, &uuid))
270         {
271             OIC_LOG(ERROR, TAG, "Can't convert subjectuuid to string");
272         }
273
274         OCRepPayloadSetPropString(payload, OC_RSRVD_ACE_ID, ace->aceId);
275         OCRepPayloadSetPropString(payload, OC_RSRVD_SUBJECT_UUID, (const char *)uuid);
276         OCRepPayloadSetPropInt(payload, OC_RSRVD_SUBJECT_TYPE, ace->stype);
277         OCRepPayloadSetPropInt(payload, OC_RSRVD_PERMISSION_MASK, ace->permission);
278
279         OICFree(uuid);
280
281         int reslist_count = 0;
282         //code below duplicates LL_COUNT, implemented in newer version of utlist.h
283         {
284             OicSecRsrc_t *res = ace->resources;
285             while (res)
286             {
287                 res = res->next;
288                 reslist_count++;
289             }
290         }
291
292         helperPayload2 = OICCalloc(reslist_count, sizeof(OCRepPayload *));
293         if (!helperPayload2)
294         {
295             goto no_memory;
296         }
297
298         j = 0;
299         OicSecRsrc_t *res = NULL;
300
301         LL_FOREACH(ace->resources, res)
302         {
303             OCRepPayload *payload = OCRepPayloadCreate();
304             if (!payload)
305             {
306                 OIC_LOG_V(DEBUG, TAG, "Can't allocate memory for helperPayload2[j]");
307                 goto no_memory;
308             }
309             helperPayload2[j++] = payload;
310
311             OCRepPayloadSetPropString(payload, OC_RSRVD_HREF, res->href);
312
313             dimensions[0] = res->typeLen;
314             OCRepPayloadSetStringArray(payload, OC_RSRVD_RESOURCE_TYPE,
315                                        (const char **)res->types, dimensions);
316
317             dimensions[0] = res->interfaceLen;
318             OCRepPayloadSetStringArray(payload, OC_RSRVD_INTERFACE,
319                                        (const char **)res->interfaces, dimensions);
320         }
321         dimensions[0] = reslist_count;
322         OCRepPayloadSetPropObjectArray(payload, OC_RSRVD_RESOURCES,
323                 (const OCRepPayload **)helperPayload2, dimensions);
324     }
325     dimensions[0] = acllist_count;
326     OCRepPayloadSetPropObjectArray(payload, OC_RSRVD_ACCESS_CONTROL_LIST,
327             (const OCRepPayload **)helperPayload, dimensions);
328
329     OCCallbackData cbData;
330     fillCallbackData(&cbData, ctx, callback, NULL, NULL);
331
332     OIC_LOG(DEBUG, TAG, "Next payload created:");
333     OIC_LOG_PAYLOAD(DEBUG, (OCPayload *)payload);
334
335     return OCDoResource(NULL, OC_REST_POST, uri, NULL, (OCPayload *)payload,
336                         CT_ADAPTER_TCP, OC_LOW_QOS, &cbData, NULL, 0);
337 no_memory:
338     if (helperPayload2)
339     {
340         for (int k = 0; k < j; k++) OCRepPayloadDestroy(helperPayload2[k]);
341         OICFree(helperPayload2);
342     }
343     if (helperPayload)
344     {
345         for (int k = 0; k < i; k++) OCRepPayloadDestroy(helperPayload[k]);
346         OICFree(helperPayload);
347     }
348     OCRepPayloadDestroy(payload);
349     return OC_STACK_NO_MEMORY;
350 }
351
352 OCStackResult OCCloudAclIndividualDelete(void* ctx,
353                                          const char *aclId,
354                                          const OCDevAddr *endPoint,
355                                          OCCloudResponseCB callback)
356 {
357     char uri[MAX_URI_LENGTH]  = { 0 };
358
359     VERIFY_NON_NULL_RET(endPoint, TAG, "NULL endpoint", OC_STACK_INVALID_PARAM);
360     VERIFY_NON_NULL_RET(aclId, TAG, "NULL input param", OC_STACK_INVALID_PARAM);
361
362     snprintf(uri, MAX_URI_LENGTH, "%s%s:%d%s/%s", DEFAULT_PREFIX,
363             endPoint->addr, endPoint->port, OC_RSRVD_ACL_ID_URL, aclId);
364
365     OCCallbackData cbData;
366     fillCallbackData(&cbData, ctx, callback, NULL, NULL);
367
368     return OCDoResource(NULL, OC_REST_DELETE, uri, NULL, NULL,
369                         CT_ADAPTER_TCP, OC_LOW_QOS, &cbData, NULL, 0);
370 }