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