Svace memory leak fixes
[platform/upstream/iotivity.git] / resource / csdk / security / provisioning / src / cloud / aclinvite.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 <string.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23
24 #include "occloudprovisioning.h"
25 #include "utils.h"
26
27 #include "oic_malloc.h"
28 #include "logger.h"
29 #include "ocstack.h"
30 #include "ocpayload.h"
31 #include "pmutility.h"
32 #include "cacommonutil.h"
33
34 #define TAG "OIC_CLOUD_ACL_INVITE"
35
36 /**
37  * This helper function parses "name" : { "gid":[], "mid":[] } payload
38  *
39  * @param[in] payload     received payload
40  * @param[in] name        property name
41  * @param[out] out        string array pair to fill
42  * @return  OCStackResult application result
43  */
44 static OCStackResult parseInvitePayload(const OCRepPayload *payload, const char *name, stringArrayPair_t *out)
45 {
46     OCStackResult result = OC_STACK_NO_MEMORY;
47     size_t dimensions[MAX_REP_ARRAY_DEPTH] = { 0 };
48     OCRepPayload **heplerPayload  = NULL;
49     size_t i = 0;
50
51     if (!OCRepPayloadGetPropObjectArray(payload, name, &heplerPayload, dimensions))
52     {
53         OIC_LOG_V(ERROR, TAG, "Can't get: %s", name);
54         return OC_STACK_MALFORMED_RESPONSE;
55     }
56
57     size_t count = calcDimTotal(dimensions);
58
59     stringArray_t *gidlist = &out->gidlist;
60     stringArray_t *midlist = &out->midlist;
61
62     gidlist->length = count;
63     midlist->length = count;
64
65     gidlist->array = OICCalloc(gidlist->length, sizeof(char *));
66     if (NULL == gidlist->array)
67     {
68         OIC_LOG(ERROR, TAG, "Can't allocate gidlist->array");
69         goto exit;
70     }
71
72     midlist->array = OICCalloc(midlist->length, sizeof(char *));
73     if (NULL == midlist->array)
74     {
75         OIC_LOG(ERROR, TAG, "Can't allocate midlist->array");
76         goto exit;
77     }
78
79     for (i = 0; i < gidlist->length; i++)
80     {
81         const OCRepPayload *payload = heplerPayload[i];
82
83         if (!OCRepPayloadGetPropString(payload, OC_RSRVD_GROUP_ID, &gidlist->array[i]))
84         {
85             OIC_LOG_V(ERROR, TAG, "Can't get: %s", OC_RSRVD_GROUP_ID);
86             result = OC_STACK_MALFORMED_RESPONSE;
87             goto exit;
88         }
89
90         if (!OCRepPayloadGetPropString(payload, OC_RSRVD_MEMBER_ID, &midlist->array[i]))
91         {
92             OIC_LOG_V(ERROR, TAG, "Can't get: %s", OC_RSRVD_MEMBER_ID);
93             result = OC_STACK_MALFORMED_RESPONSE;
94             goto exit;
95         }
96         OCRepPayloadDestroy(heplerPayload[i]);
97     }
98
99     result = OC_STACK_OK;
100
101 exit:
102     if (result != OC_STACK_OK)
103     {
104         clearStringArray(gidlist);
105         clearStringArray(midlist);
106
107         for (size_t k = i; k < gidlist->length; k++)
108         {
109             OCRepPayloadDestroy(heplerPayload[i]);
110         }
111     }
112     OICFree(heplerPayload);
113     return result;
114 }
115
116 /**
117  * ACL get invitation request received data handler
118  *
119  * @param[in] ctx       context
120  * @param[out] data     data required to external application
121  * @param[in] response  peer response
122  * @return  OCStackResult application result
123  */
124 static OCStackResult handleAclGetInvitationResponse(void *ctx, void **data, OCClientResponse *response)
125 {
126     OC_UNUSED(ctx);
127     OCStackResult result = OC_STACK_OK;
128
129     if (NULL == response->payload)
130     {
131         OIC_LOG(ERROR, TAG, "Receive NULL payload");
132         return OC_STACK_INVALID_PARAM;
133     }
134
135     inviteResponse_t *answer = OICCalloc(1, sizeof(inviteResponse_t));
136     if (NULL == answer)
137     {
138         OIC_LOG(ERROR, TAG, "Can't allocate answer");
139         return OC_STACK_NO_MEMORY;
140     }
141
142     const OCRepPayload *payload = (const OCRepPayload *)response->payload;
143
144     result = parseInvitePayload(payload, OC_RSRVD_INVITE, &answer->invite);
145     if (result != OC_STACK_OK)
146     {
147         goto exit;
148     }
149
150     result = parseInvitePayload(payload, OC_RSRVD_INVITED, &answer->invited);
151     if (result != OC_STACK_OK)
152     {
153         goto exit;
154     }
155
156     *data = answer;
157 exit:
158     return result;
159 }
160
161 /**
162  * ACL policy check request received data handler
163  *
164  * @param[in] ctx       context
165  * @param[out] data     data required to external application
166  * @param[in] response  peer response
167  * @return  OCStackResult application result
168  */
169 static OCStackResult handleAclPolicyCheckResponse(void *ctx, void **data, OCClientResponse *response)
170 {
171     OC_UNUSED(ctx);
172
173     if (NULL == response->payload)
174     {
175         OIC_LOG(ERROR, TAG, "Receive NULL payload");
176         return OC_STACK_INVALID_PARAM;
177     }
178
179     char *gp = NULL;
180
181     if (!OCRepPayloadGetPropString((const OCRepPayload *)response->payload, OC_RSRVD_GROUP_PERMISSION, &gp))
182     {
183         OIC_LOG_V(ERROR, TAG, "Can't get: %s", OC_RSRVD_GROUP_PERMISSION);
184         return OC_STACK_MALFORMED_RESPONSE;
185     }
186
187     *data = gp;
188     return OC_STACK_OK;
189 }
190
191 OCStackResult OCCloudAclInviteUser(void* ctx,
192                                    const char *userId,
193                                    const stringArray_t *groupIds,
194                                    const stringArray_t *memberIds,
195                                    const OCDevAddr *endPoint,
196                                    OCCloudResponseCB callback)
197 {
198     OCStackResult result = OC_STACK_ERROR;
199     char uri[MAX_URI_LENGTH] = { 0 };
200     size_t i = 0;
201
202     VERIFY_NON_NULL_RET(endPoint, TAG, "NULL endpoint", OC_STACK_INVALID_PARAM);
203     VERIFY_NON_NULL_RET(groupIds, TAG, "NULL input param", OC_STACK_INVALID_PARAM);
204     VERIFY_NON_NULL_RET(memberIds, TAG, "NULL input param", OC_STACK_INVALID_PARAM);
205
206     if (groupIds->length != memberIds->length)
207     {
208         OIC_LOG(ERROR, TAG, "members and groups lists should have the same length!!!");
209         return OC_STACK_INVALID_PARAM;
210     }
211
212     snprintf(uri, MAX_URI_LENGTH, "%s%s:%d%s", DEFAULT_PREFIX,
213             endPoint->addr, endPoint->port, OC_RSRVD_ACL_INVITE_URL);
214
215     OCCallbackData cbData;
216     fillCallbackData(&cbData, ctx, callback, NULL, NULL);
217
218     OCRepPayload *payload = OCRepPayloadCreate();
219     if (!payload)
220     {
221         OICFree(cbData.context);
222         return OC_STACK_NO_MEMORY;
223     }
224
225     OCRepPayload **heplerPayload = OICCalloc(groupIds->length, sizeof(OCRepPayload *));
226     if(NULL == heplerPayload)
227     {
228         OICFree(cbData.context);
229         OCRepPayloadDestroy(payload);
230         OIC_LOG(ERROR, TAG, "Memory Allocation failed!");
231         return OC_STACK_NO_MEMORY;
232     }
233
234     for (i = 0; i < groupIds->length; i++)
235     {
236         heplerPayload[i] = OCRepPayloadCreate();
237         if (!heplerPayload[i])
238         {
239             goto no_memory;
240         }
241         OCRepPayloadSetPropString(heplerPayload[i], OC_RSRVD_GROUP_ID, groupIds->array[i]);
242         OCRepPayloadSetPropString(heplerPayload[i], OC_RSRVD_MEMBER_ID, memberIds->array[i]);
243     }
244
245     //add next fields if they were filled
246     if (userId) OCRepPayloadSetPropString(payload, OC_RSRVD_USER_UUID, userId);
247
248     size_t dimensions[MAX_REP_ARRAY_DEPTH] = {groupIds->length, 0, 0};
249     OCRepPayloadSetPropObjectArray(payload, OC_RSRVD_INVITE,
250             (const struct OCRepPayload **)heplerPayload, dimensions);
251
252     return OCDoResource(NULL, OC_REST_POST, uri, NULL, (OCPayload *)payload,
253                         CT_ADAPTER_TCP, OC_LOW_QOS, &cbData, NULL, 0);
254 no_memory:
255     OCRepPayloadDestroy(payload);
256     for (size_t k = 0; k < i; k++)
257     {
258         OCRepPayloadDestroy(heplerPayload[k]);
259     }
260     OCRepPayloadDestroy(*heplerPayload);
261     return result;
262 }
263
264 OCStackResult OCCloudAclGetInvitation(void* ctx,
265                                       const char *userId,
266                                       const OCDevAddr *endPoint,
267                                       OCCloudResponseCB callback)
268 {
269     char uri[MAX_URI_LENGTH] = { 0 };
270
271     VERIFY_NON_NULL_RET(endPoint, TAG, "NULL endpoint", OC_STACK_INVALID_PARAM);
272
273     snprintf(uri, MAX_URI_LENGTH, "%s%s:%d%s", DEFAULT_PREFIX,
274             endPoint->addr, endPoint->port, OC_RSRVD_ACL_INVITE_URL);
275
276     if (userId)
277     {
278         size_t len = strlen(uri);
279         snprintf(uri + len, MAX_URI_LENGTH -len, "?%s=%s", OC_RSRVD_USER_UUID, userId);
280     }
281
282     OCCallbackData cbData;
283     fillCallbackData(&cbData, ctx, callback, handleAclGetInvitationResponse, NULL);
284
285     return OCDoResource(NULL, OC_REST_GET, uri, NULL, NULL,
286                         CT_ADAPTER_TCP, OC_LOW_QOS, &cbData, NULL, 0);
287 }
288
289 OCStackResult OCCloudAclDeleteInvitation(void* ctx,
290                                          const char *userId,
291                                          const char *groupId,
292                                          const OCDevAddr *endPoint,
293                                          OCCloudResponseCB callback)
294 {
295     char uri[MAX_URI_LENGTH] = { 0 };
296
297     VERIFY_NON_NULL_RET(endPoint, TAG, "NULL endpoint", OC_STACK_INVALID_PARAM);
298     VERIFY_NON_NULL_RET(groupId, TAG, "NULL input param", OC_STACK_INVALID_PARAM);
299
300     snprintf(uri, MAX_URI_LENGTH, "%s%s:%d%s", DEFAULT_PREFIX,
301             endPoint->addr, endPoint->port, OC_RSRVD_ACL_INVITE_URL);
302
303     if (userId)
304     {
305         size_t len = strlen(uri);
306         snprintf(uri + len, MAX_URI_LENGTH - len, "?%s=%s", OC_RSRVD_USER_UUID, userId);
307     }
308
309     size_t len = strlen(uri);
310     snprintf(uri + len, MAX_URI_LENGTH - len, "%c%s=%s", userId?'&':'?', OC_RSRVD_GROUP_ID, groupId);
311
312     OCCallbackData cbData;
313     fillCallbackData(&cbData, ctx, callback, NULL, NULL);
314
315     return OCDoResource(NULL, OC_REST_DELETE, uri, NULL, NULL,
316                         CT_ADAPTER_TCP, OC_LOW_QOS, &cbData, NULL, 0);
317 }
318
319 OCStackResult OCCloudAclCancelInvitation(void* ctx,
320                                          const char *userId,
321                                          const char *groupId,
322                                          const char *memberId,
323                                          const OCDevAddr *endPoint,
324                                          OCCloudResponseCB callback)
325 {
326     char uri[MAX_URI_LENGTH] = { 0 };
327     size_t len = 0 ;
328
329     VERIFY_NON_NULL_RET(endPoint, TAG, "NULL endpoint", OC_STACK_INVALID_PARAM);
330     VERIFY_NON_NULL_RET(groupId, TAG, "NULL input param", OC_STACK_INVALID_PARAM);
331     VERIFY_NON_NULL_RET(memberId, TAG, "NULL input param", OC_STACK_INVALID_PARAM);
332
333     snprintf(uri, MAX_URI_LENGTH, "%s%s:%d%s", DEFAULT_PREFIX,
334             endPoint->addr, endPoint->port, OC_RSRVD_ACL_INVITE_URL);
335
336     if (userId)
337     {
338         size_t len = strlen(uri);
339         snprintf(uri + len, MAX_URI_LENGTH - len, "?%s=%s", OC_RSRVD_USER_UUID, userId);
340     }
341
342     len = strlen(uri);
343     snprintf(uri + len, MAX_URI_LENGTH - len, "%c%s=%s", userId?'&':'?', OC_RSRVD_GROUP_ID, groupId);
344     len = strlen(uri);
345     snprintf(uri + len, MAX_URI_LENGTH - len, "&%s=%s", OC_RSRVD_MEMBER_ID, memberId);
346
347     OCCallbackData cbData;
348     fillCallbackData(&cbData, ctx, callback, NULL, NULL);
349
350     return OCDoResource(NULL, OC_REST_DELETE, uri, NULL, NULL,
351                         CT_ADAPTER_TCP, OC_LOW_QOS, &cbData, NULL, 0);
352 }
353
354 OCStackResult OCCloudAclPolicyCheck(void* ctx,
355                                     const char *subjectId,
356                                     const char *deviceId,
357                                     const char *method,
358                                     const char *user_uri,
359                                     const OCDevAddr *endPoint,
360                                     OCCloudResponseCB callback)
361 {
362     char uri[MAX_URI_LENGTH] = { 0 };
363     size_t len = 0;
364
365     VERIFY_NON_NULL_RET(endPoint, TAG, "NULL endpoint", OC_STACK_INVALID_PARAM);
366     VERIFY_NON_NULL_RET(subjectId, TAG, "NULL input param", OC_STACK_INVALID_PARAM);
367     VERIFY_NON_NULL_RET(deviceId, TAG, "NULL input param", OC_STACK_INVALID_PARAM);
368     VERIFY_NON_NULL_RET(method, TAG, "NULL input param", OC_STACK_INVALID_PARAM);
369     VERIFY_NON_NULL_RET(user_uri, TAG, "NULL input param", OC_STACK_INVALID_PARAM);
370
371     snprintf(uri, MAX_URI_LENGTH, "%s%s:%d%s", DEFAULT_PREFIX,
372             endPoint->addr, endPoint->port, OC_RSRVD_ACL_VERIFY_URL);
373
374     len = strlen(uri);
375     snprintf(uri + len, MAX_URI_LENGTH - len, "?%s=%s", OC_RSRVD_SUBJECT_ID, subjectId);
376     len = strlen(uri);
377     snprintf(uri + len, MAX_URI_LENGTH - len, "&%s=%s", OC_RSRVD_DEVICE_ID, deviceId);
378     len = strlen(uri);
379     snprintf(uri + len, MAX_URI_LENGTH - len, "&%s=%s", OC_RSRVD_REQUEST_METHOD, method);
380     len = strlen(uri);
381     snprintf(uri + len, MAX_URI_LENGTH - len, "&%s=%s", OC_RSRVD_REQUEST_URI, user_uri);
382
383     OCCallbackData cbData;
384     fillCallbackData(&cbData, ctx, callback, handleAclPolicyCheckResponse, NULL);
385
386     return OCDoResource(NULL, OC_REST_GET, uri, NULL, NULL,
387                         CT_ADAPTER_TCP, OC_LOW_QOS, &cbData, NULL, 0);
388 }