[IOT-1347] OCCloudAclIdCreate or OCCloudAclIdGetByDevice API doesn't provide the...
[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 exit:
139     return result;
140 }
141
142 /**
143  * ACL policy check request received data handler
144  *
145  * @param[in] ctx       context
146  * @param[out] data     data required to external application
147  * @param[in] response  peer response
148  * @return  OCStackResult application result
149  */
150 static OCStackResult handleAclPolicyCheckResponse(void *ctx, void **data, OCClientResponse *response)
151 {
152     OC_UNUSED(ctx);
153
154     if (NULL == response->payload)
155     {
156         OIC_LOG(ERROR, TAG, "Receive NULL payload");
157         return OC_STACK_INVALID_PARAM;
158     }
159
160     char *gp = NULL;
161
162     if (!OCRepPayloadGetPropString((const OCRepPayload *)response->payload, OC_RSRVD_GROUP_PERMISSION, &gp))
163     {
164         OIC_LOG_V(ERROR, TAG, "Can't get: %s", OC_RSRVD_GROUP_PERMISSION);
165         return OC_STACK_MALFORMED_RESPONSE;
166     }
167
168     *data = gp;
169     return OC_STACK_OK;
170 }
171
172 OCStackResult OCCloudAclInviteUser(void* ctx,
173                                    const char *userId,
174                                    const stringArray_t *groupIds,
175                                    const stringArray_t *memberIds,
176                                    const OCDevAddr *endPoint,
177                                    OCCloudResponseCB callback)
178 {
179     OCStackResult result = OC_STACK_ERROR;
180     char uri[MAX_URI_LENGTH] = { 0 };
181     size_t i = 0;
182
183     VERIFY_NON_NULL_RET(endPoint, TAG, "NULL endpoint", OC_STACK_INVALID_PARAM);
184     VERIFY_NON_NULL_RET(groupIds, TAG, "NULL input param", OC_STACK_INVALID_PARAM);
185     VERIFY_NON_NULL_RET(memberIds, TAG, "NULL input param", OC_STACK_INVALID_PARAM);
186
187     if (groupIds->length != memberIds->length)
188     {
189         OIC_LOG(ERROR, TAG, "members and groups lists should have the same length!!!");
190         return OC_STACK_INVALID_PARAM;
191     }
192
193     snprintf(uri, MAX_URI_LENGTH, "%s%s:%d%s", DEFAULT_PREFIX,
194             endPoint->addr, endPoint->port, OC_RSRVD_ACL_INVITE_URL);
195
196     OCCallbackData cbData;
197     fillCallbackData(&cbData, ctx, callback, NULL, NULL);
198
199     OCRepPayload *payload = OCRepPayloadCreate();
200     if (!payload)
201     {
202         return OC_STACK_NO_MEMORY;
203     }
204
205     OCRepPayload **heplerPayload = OICCalloc(groupIds->length, sizeof(OCRepPayload *));
206
207     for (i = 0; i < groupIds->length; i++)
208     {
209         heplerPayload[i] = OCRepPayloadCreate();
210         if (!heplerPayload[i])
211         {
212             goto no_memory;
213         }
214         OCRepPayloadSetPropString(heplerPayload[i], OC_RSRVD_GROUP_ID, groupIds->array[i]);
215         OCRepPayloadSetPropString(heplerPayload[i], OC_RSRVD_MEMBER_ID, memberIds->array[i]);
216     }
217
218     //add next fields if they were filled
219     if (userId) OCRepPayloadSetPropString(payload, OC_RSRVD_USER_UUID, userId);
220
221     size_t dimensions[MAX_REP_ARRAY_DEPTH] = {groupIds->length, 0, 0};
222     OCRepPayloadSetPropObjectArray(payload, OC_RSRVD_INVITE,
223             (const struct OCRepPayload **)heplerPayload, dimensions);
224
225     return OCDoResource(NULL, OC_REST_POST, uri, NULL, (OCPayload *)payload,
226                         CT_ADAPTER_TCP, OC_LOW_QOS, &cbData, NULL, 0);
227 no_memory:
228     OCRepPayloadDestroy(payload);
229     for (size_t k = 0; k < i; k++)
230     {
231         OCRepPayloadDestroy(heplerPayload[k]);
232     }
233     OCRepPayloadDestroy(*heplerPayload);
234     return result;
235 }
236
237 OCStackResult OCCloudAclGetInvitation(void* ctx,
238                                       const char *userId,
239                                       const OCDevAddr *endPoint,
240                                       OCCloudResponseCB callback)
241 {
242     char uri[MAX_URI_LENGTH] = { 0 };
243
244     VERIFY_NON_NULL_RET(endPoint, TAG, "NULL endpoint", OC_STACK_INVALID_PARAM);
245
246     snprintf(uri, MAX_URI_LENGTH, "%s%s:%d%s", DEFAULT_PREFIX,
247             endPoint->addr, endPoint->port, OC_RSRVD_ACL_INVITE_URL);
248
249     if (userId)
250     {
251         size_t len = strlen(uri);
252         snprintf(uri + len, MAX_URI_LENGTH -len, "?%s=%s", OC_RSRVD_USER_UUID, userId);
253     }
254
255     OCCallbackData cbData;
256     fillCallbackData(&cbData, ctx, callback, handleAclGetInvitationResponse, NULL);
257
258     return OCDoResource(NULL, OC_REST_GET, uri, NULL, NULL,
259                         CT_ADAPTER_TCP, OC_LOW_QOS, &cbData, NULL, 0);
260 }
261
262 OCStackResult OCCloudAclDeleteInvitation(void* ctx,
263                                          const char *userId,
264                                          const char *groupId,
265                                          const OCDevAddr *endPoint,
266                                          OCCloudResponseCB callback)
267 {
268     char uri[MAX_URI_LENGTH] = { 0 };
269
270     VERIFY_NON_NULL_RET(endPoint, TAG, "NULL endpoint", OC_STACK_INVALID_PARAM);
271     VERIFY_NON_NULL_RET(groupId, TAG, "NULL input param", 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     size_t len = strlen(uri);
283     snprintf(uri + len, MAX_URI_LENGTH - len, "%c%s=%s", userId?'&':'?', OC_RSRVD_GROUP_ID, groupId);
284
285     OCCallbackData cbData;
286     fillCallbackData(&cbData, ctx, callback, NULL, NULL);
287
288     return OCDoResource(NULL, OC_REST_DELETE, uri, NULL, NULL,
289                         CT_ADAPTER_TCP, OC_LOW_QOS, &cbData, NULL, 0);
290 }
291
292 OCStackResult OCCloudAclCancelInvitation(void* ctx,
293                                          const char *userId,
294                                          const char *groupId,
295                                          const char *memberId,
296                                          const OCDevAddr *endPoint,
297                                          OCCloudResponseCB callback)
298 {
299     char uri[MAX_URI_LENGTH] = { 0 };
300     size_t len = 0 ;
301
302     VERIFY_NON_NULL_RET(endPoint, TAG, "NULL endpoint", OC_STACK_INVALID_PARAM);
303     VERIFY_NON_NULL_RET(groupId, TAG, "NULL input param", OC_STACK_INVALID_PARAM);
304     VERIFY_NON_NULL_RET(memberId, TAG, "NULL input param", OC_STACK_INVALID_PARAM);
305
306     snprintf(uri, MAX_URI_LENGTH, "%s%s:%d%s", DEFAULT_PREFIX,
307             endPoint->addr, endPoint->port, OC_RSRVD_ACL_INVITE_URL);
308
309     if (userId)
310     {
311         size_t len = strlen(uri);
312         snprintf(uri + len, MAX_URI_LENGTH - len, "?%s=%s", OC_RSRVD_USER_UUID, userId);
313     }
314
315     len = strlen(uri);
316     snprintf(uri + len, MAX_URI_LENGTH - len, "%c%s=%s", userId?'&':'?', OC_RSRVD_GROUP_ID, groupId);
317     len = strlen(uri);
318     snprintf(uri + len, MAX_URI_LENGTH - len, "&%s=%s", OC_RSRVD_MEMBER_ID, memberId);
319
320     OCCallbackData cbData;
321     fillCallbackData(&cbData, ctx, callback, NULL, NULL);
322
323     return OCDoResource(NULL, OC_REST_DELETE, uri, NULL, NULL,
324                         CT_ADAPTER_TCP, OC_LOW_QOS, &cbData, NULL, 0);
325 }
326
327 OCStackResult OCCloudAclPolicyCheck(void* ctx,
328                                     const char *subjectId,
329                                     const char *deviceId,
330                                     const char *method,
331                                     const char *user_uri,
332                                     const OCDevAddr *endPoint,
333                                     OCCloudResponseCB callback)
334 {
335     char uri[MAX_URI_LENGTH] = { 0 };
336     size_t len = 0;
337
338     VERIFY_NON_NULL_RET(endPoint, TAG, "NULL endpoint", OC_STACK_INVALID_PARAM);
339     VERIFY_NON_NULL_RET(subjectId, TAG, "NULL input param", OC_STACK_INVALID_PARAM);
340     VERIFY_NON_NULL_RET(deviceId, TAG, "NULL input param", OC_STACK_INVALID_PARAM);
341     VERIFY_NON_NULL_RET(method, TAG, "NULL input param", OC_STACK_INVALID_PARAM);
342     VERIFY_NON_NULL_RET(user_uri, TAG, "NULL input param", OC_STACK_INVALID_PARAM);
343
344     snprintf(uri, MAX_URI_LENGTH, "%s%s:%d%s", DEFAULT_PREFIX,
345             endPoint->addr, endPoint->port, OC_RSRVD_ACL_VERIFY_URL);
346
347     len = strlen(uri);
348     snprintf(uri + len, MAX_URI_LENGTH - len, "?%s=%s", OC_RSRVD_SUBJECT_ID, subjectId);
349     len = strlen(uri);
350     snprintf(uri + len, MAX_URI_LENGTH - len, "&%s=%s", OC_RSRVD_DEVICE_ID, deviceId);
351     len = strlen(uri);
352     snprintf(uri + len, MAX_URI_LENGTH - len, "&%s=%s", OC_RSRVD_REQUEST_METHOD, method);
353     len = strlen(uri);
354     snprintf(uri + len, MAX_URI_LENGTH - len, "&%s=%s", OC_RSRVD_REQUEST_URI, user_uri);
355
356     OCCallbackData cbData;
357     fillCallbackData(&cbData, ctx, callback, handleAclPolicyCheckResponse, NULL);
358
359     return OCDoResource(NULL, OC_REST_GET, uri, NULL, NULL,
360                         CT_ADAPTER_TCP, OC_LOW_QOS, &cbData, NULL, 0);
361 }