Revert back cbor related patches.
[platform/upstream/iotivity.git] / resource / csdk / security / src / amaclresource.c
1 //******************************************************************
2 //
3 // Copyright 2015 Intel Mobile Communications GmbH 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
21
22 #include <stdlib.h>
23 #include <string.h>
24 #include "ocstack.h"
25 #include "logger.h"
26 #include "oic_malloc.h"
27 #include "oic_string.h"
28 #include "cJSON.h"
29 #include "base64.h"
30 #include "resourcemanager.h"
31 #include "psinterface.h"
32 #include "utlist.h"
33 #include "srmresourcestrings.h"
34 #include "amaclresource.h"
35 #include "srmutility.h"
36 #include <stdlib.h>
37 #include <string.h>
38
39 #define TAG  "SRM-AMACL"
40
41 OicSecAmacl_t *gAmacl = NULL;
42 static OCResourceHandle gAmaclHandle = NULL;
43
44 void DeleteAmaclList(OicSecAmacl_t* amacl)
45 {
46     if (amacl)
47     {
48         OicSecAmacl_t *amaclTmp1 = NULL, *amaclTmp2 = NULL;
49         LL_FOREACH_SAFE(amacl, amaclTmp1, amaclTmp2)
50         {
51             LL_DELETE(amacl, amaclTmp1);
52
53             // Clean Resources
54             for (size_t i = 0; i < amaclTmp1->resourcesLen; i++)
55             {
56                 OICFree(amaclTmp1->resources[i]);
57             }
58             OICFree(amaclTmp1->resources);
59
60             // Clean Amss
61             OICFree(amaclTmp1->amss);
62
63             // Clean Owners
64             OICFree(amaclTmp1->owners);
65
66             // Clean Amacl node itself
67             OICFree(amaclTmp1);
68         }
69     }
70 }
71
72 /*
73  * This internal method converts AMACL data into JSON format.
74  *
75  * Note: Caller needs to invoke 'free' when finished using the return string.
76  */
77 char * BinToAmaclJSON(const OicSecAmacl_t * amacl)
78 {
79     cJSON *jsonRoot = NULL;
80     char *jsonStr = NULL;
81
82     if (amacl)
83     {
84         jsonRoot = cJSON_CreateObject();
85         VERIFY_NON_NULL(TAG, jsonRoot, ERROR);
86
87         cJSON *jsonAmaclArray = NULL;
88         cJSON_AddItemToObject (jsonRoot, OIC_JSON_AMACL_NAME, jsonAmaclArray = cJSON_CreateArray());
89         VERIFY_NON_NULL(TAG, jsonAmaclArray, ERROR);
90
91         while(amacl)
92         {
93             char base64Buff[B64ENCODE_OUT_SAFESIZE(sizeof(((OicUuid_t*)0)->id)) + 1] = {};
94             uint32_t outLen = 0;
95             B64Result b64Ret = B64_OK;
96
97             cJSON *jsonAmacl = cJSON_CreateObject();
98
99             // Resources -- Mandatory
100             cJSON *jsonRsrcArray = NULL;
101             cJSON_AddItemToObject(jsonAmacl, OIC_JSON_RESOURCES_NAME, jsonRsrcArray =
102                     cJSON_CreateArray());
103             VERIFY_NON_NULL(TAG, jsonRsrcArray, ERROR);
104             for (unsigned int i = 0; i < amacl->resourcesLen; i++)
105             {
106                 cJSON_AddItemToArray(jsonRsrcArray, cJSON_CreateString(amacl->resources[i]));
107             }
108
109             // Amss -- Mandatory
110             cJSON *jsonAmsArray = NULL;
111             cJSON_AddItemToObject(jsonAmacl, OIC_JSON_AMSS_NAME, jsonAmsArray =
112                     cJSON_CreateArray());
113             VERIFY_NON_NULL(TAG, jsonAmsArray, ERROR);
114             for (unsigned int i = 0; i < amacl->amssLen; i++)
115             {
116                 outLen = 0;
117
118                 b64Ret = b64Encode(amacl->amss[i].id, sizeof(((OicUuid_t*) 0)->id), base64Buff,
119                         sizeof(base64Buff), &outLen);
120                 VERIFY_SUCCESS(TAG, b64Ret == B64_OK, ERROR);
121
122                 cJSON_AddItemToArray(jsonAmsArray, cJSON_CreateString(base64Buff));
123             }
124
125             // Owners -- Mandatory
126             cJSON *jsonOwnrArray = NULL;
127             cJSON_AddItemToObject(jsonAmacl, OIC_JSON_OWNERS_NAME, jsonOwnrArray =
128                     cJSON_CreateArray());
129             VERIFY_NON_NULL(TAG, jsonOwnrArray, ERROR);
130             for (unsigned int i = 0; i < amacl->ownersLen; i++)
131             {
132                 outLen = 0;
133
134                 b64Ret = b64Encode(amacl->owners[i].id, sizeof(((OicUuid_t*) 0)->id), base64Buff,
135                         sizeof(base64Buff), &outLen);
136                 VERIFY_SUCCESS(TAG, b64Ret == B64_OK, ERROR);
137
138                 cJSON_AddItemToArray(jsonOwnrArray, cJSON_CreateString(base64Buff));
139             }
140
141             // Attach current amacl node to Amacl Array
142             cJSON_AddItemToArray(jsonAmaclArray, jsonAmacl);
143             amacl = amacl->next;
144         }
145
146         jsonStr = cJSON_PrintUnformatted(jsonRoot);
147     }
148
149 exit:
150     if (jsonRoot)
151     {
152         cJSON_Delete(jsonRoot);
153     }
154     return jsonStr;
155 }
156
157
158
159
160 /*
161  * This internal method converts JSON AMACL into binary AMACL.
162  */
163 OicSecAmacl_t * JSONToAmaclBin(const char * jsonStr)
164 {
165     OCStackResult ret = OC_STACK_ERROR;
166     OicSecAmacl_t * headAmacl = NULL;
167     OicSecAmacl_t * prevAmacl = NULL;
168     cJSON *jsonRoot = NULL;
169     cJSON *jsonAmaclArray = NULL;
170
171     VERIFY_NON_NULL(TAG, jsonStr, ERROR);
172
173     jsonRoot = cJSON_Parse(jsonStr);
174     VERIFY_NON_NULL(TAG, jsonRoot, ERROR);
175
176     jsonAmaclArray = cJSON_GetObjectItem(jsonRoot, OIC_JSON_AMACL_NAME);
177     VERIFY_NON_NULL(TAG, jsonAmaclArray, INFO);
178
179     if (cJSON_Array == jsonAmaclArray->type)
180     {
181         int numAmacl = cJSON_GetArraySize(jsonAmaclArray);
182         int idx = 0;
183
184         VERIFY_SUCCESS(TAG, numAmacl > 0, INFO);
185         do
186         {
187             cJSON *jsonAmacl = cJSON_GetArrayItem(jsonAmaclArray, idx);
188             VERIFY_NON_NULL(TAG, jsonAmacl, ERROR);
189
190             OicSecAmacl_t *amacl = (OicSecAmacl_t*)OICCalloc(1, sizeof(OicSecAmacl_t));
191             VERIFY_NON_NULL(TAG, amacl, ERROR);
192
193             headAmacl = (headAmacl) ? headAmacl : amacl;
194             if (prevAmacl)
195             {
196                 prevAmacl->next = amacl;
197             }
198
199             size_t jsonObjLen = 0;
200             cJSON *jsonObj = NULL;
201
202             // Resources -- Mandatory
203             jsonObj = cJSON_GetObjectItem(jsonAmacl, OIC_JSON_RESOURCES_NAME);
204             VERIFY_NON_NULL(TAG, jsonObj, ERROR);
205             VERIFY_SUCCESS(TAG, cJSON_Array == jsonObj->type, ERROR);
206
207             amacl->resourcesLen = (size_t)cJSON_GetArraySize(jsonObj);
208             VERIFY_SUCCESS(TAG, amacl->resourcesLen > 0, ERROR);
209             amacl->resources = (char**)OICCalloc(amacl->resourcesLen, sizeof(char*));
210             VERIFY_NON_NULL(TAG, (amacl->resources), ERROR);
211
212             size_t idxx = 0;
213             do
214             {
215                 cJSON *jsonRsrc = cJSON_GetArrayItem(jsonObj, idxx);
216                 VERIFY_NON_NULL(TAG, jsonRsrc, ERROR);
217
218                 jsonObjLen = strlen(jsonRsrc->valuestring) + 1;
219                 amacl->resources[idxx] = (char*)OICMalloc(jsonObjLen);
220                 VERIFY_NON_NULL(TAG, (amacl->resources[idxx]), ERROR);
221                 OICStrcpy(amacl->resources[idxx], jsonObjLen, jsonRsrc->valuestring);
222             } while ( ++idxx < amacl->resourcesLen);
223
224             // Amss -- Mandatory
225             VERIFY_SUCCESS( TAG, OC_STACK_OK == AddUuidArray(jsonAmacl, OIC_JSON_AMSS_NAME,
226                                &(amacl->amssLen), &(amacl->amss)), ERROR);
227
228             // Owners -- Mandatory
229             VERIFY_SUCCESS( TAG, OC_STACK_OK == AddUuidArray(jsonAmacl, OIC_JSON_OWNERS_NAME,
230                                &(amacl->ownersLen), &(amacl->owners)), ERROR);
231
232             prevAmacl = amacl;
233         } while( ++idx < numAmacl);
234     }
235
236     ret = OC_STACK_OK;
237
238 exit:
239     cJSON_Delete(jsonRoot);
240     if (OC_STACK_OK != ret)
241     {
242         DeleteAmaclList(headAmacl);
243         headAmacl = NULL;
244     }
245     return headAmacl;
246 }
247
248 static OCEntityHandlerResult HandleAmaclGetRequest (const OCEntityHandlerRequest * ehRequest)
249 {
250     // Convert Amacl data into JSON for transmission
251     char* jsonStr = BinToAmaclJSON(gAmacl);
252
253     OCEntityHandlerResult ehRet = (jsonStr ? OC_EH_OK : OC_EH_ERROR);
254
255     // Send response payload to request originator
256     SendSRMResponse(ehRequest, ehRet, jsonStr);
257
258     OICFree(jsonStr);
259
260     OIC_LOG_V (DEBUG, TAG, "%s RetVal %d", __func__ , ehRet);
261     return ehRet;
262 }
263
264 static OCEntityHandlerResult HandleAmaclPostRequest (const OCEntityHandlerRequest * ehRequest)
265 {
266     OCEntityHandlerResult ehRet = OC_EH_ERROR;
267
268     // Convert JSON Amacl data into binary. This will also validate the Amacl data received.
269     OicSecAmacl_t* newAmacl = JSONToAmaclBin(((OCSecurityPayload*)ehRequest->payload)->securityData);
270
271     if (newAmacl)
272     {
273         // Append the new Amacl to existing Amacl
274         LL_APPEND(gAmacl, newAmacl);
275
276         // Convert Amacl data into JSON for update to persistent storage
277         char *jsonStr = BinToAmaclJSON(gAmacl);
278         if (jsonStr)
279         {
280             cJSON *jsonAmacl = cJSON_Parse(jsonStr);
281             OICFree(jsonStr);
282
283             if ((jsonAmacl) &&
284                 (OC_STACK_OK == UpdateSVRDatabase(OIC_JSON_AMACL_NAME, jsonAmacl)))
285             {
286                 ehRet = OC_EH_RESOURCE_CREATED;
287             }
288             cJSON_Delete(jsonAmacl);
289         }
290     }
291
292     // Send payload to request originator
293     SendSRMResponse(ehRequest, ehRet, NULL);
294
295     OIC_LOG_V (DEBUG, TAG, "%s RetVal %d", __func__ , ehRet);
296     return ehRet;
297 }
298
299 /*
300  * This internal method is the entity handler for Amacl resources and
301  * will handle REST request (GET/PUT/POST/DEL) for them.
302  */
303 OCEntityHandlerResult AmaclEntityHandler (OCEntityHandlerFlag flag,
304                                           OCEntityHandlerRequest * ehRequest,
305                                           void* callbackParameter)
306 {
307     (void) callbackParameter;
308     OCEntityHandlerResult ehRet = OC_EH_ERROR;
309
310     if (!ehRequest)
311     {
312         return ehRet;
313     }
314
315     if (flag & OC_REQUEST_FLAG)
316     {
317         OIC_LOG (DEBUG, TAG, "Flag includes OC_REQUEST_FLAG");
318         switch (ehRequest->method)
319         {
320             case OC_REST_GET:
321                 ehRet = HandleAmaclGetRequest(ehRequest);
322                 break;
323
324             case OC_REST_POST:
325                 ehRet = HandleAmaclPostRequest(ehRequest);
326                 break;
327
328             default:
329                 ehRet = OC_EH_ERROR;
330                 SendSRMResponse(ehRequest, ehRet, NULL);
331         }
332     }
333
334     return ehRet;
335 }
336
337 /*
338  * This internal method is used to create '/oic/sec/amacl' resource.
339  */
340 OCStackResult CreateAmaclResource()
341 {
342     OCStackResult ret;
343
344     ret = OCCreateResource(&gAmaclHandle,
345                            OIC_RSRC_TYPE_SEC_AMACL,
346                            OIC_MI_DEF,
347                            OIC_RSRC_AMACL_URI,
348                            AmaclEntityHandler,
349                            NULL,
350                            OC_OBSERVABLE);
351
352     if (OC_STACK_OK != ret)
353     {
354         OIC_LOG (FATAL, TAG, "Unable to instantiate Amacl resource");
355         DeInitAmaclResource();
356     }
357     return ret;
358 }
359
360 /**
361  * Initialize Amacl resource by loading data from persistent storage.
362  *
363  * @retval  OC_STACK_OK for Success, otherwise some error value
364  */
365 OCStackResult InitAmaclResource()
366 {
367     OCStackResult ret = OC_STACK_ERROR;
368
369     // Read Amacl resource from PS
370     char* jsonSVRDatabase = GetSVRDatabase();
371
372     if (jsonSVRDatabase)
373     {
374         // Convert JSON Amacl into binary format
375         gAmacl = JSONToAmaclBin(jsonSVRDatabase);
376         OICFree(jsonSVRDatabase);
377     }
378
379     // Instantiate 'oic/sec/amacl' resource
380     ret = CreateAmaclResource();
381
382     if (OC_STACK_OK != ret)
383     {
384         DeInitAmaclResource();
385     }
386     return ret;
387 }
388
389 /**
390  * Perform cleanup for Amacl resources.
391  *
392  * @retval  none
393  */
394 void DeInitAmaclResource()
395 {
396     OCDeleteResource(gAmaclHandle);
397     gAmaclHandle = NULL;
398
399     DeleteAmaclList(gAmacl);
400     gAmacl = NULL;
401 }
402
403
404 OCStackResult AmaclGetAmsDeviceId(const char *resource, OicUuid_t *amsDeviceId)
405 {
406     OicSecAmacl_t *amacl = NULL;
407
408     VERIFY_NON_NULL(TAG, resource, ERROR);
409     VERIFY_NON_NULL(TAG, amsDeviceId, ERROR);
410
411     LL_FOREACH(gAmacl, amacl)
412     {
413         for(size_t i = 0; i < amacl->resourcesLen; i++)
414         {
415             if (strncmp((amacl->resources[i]), resource, strlen(amacl->resources[i])) == 0)
416             {
417                 //Returning the ID of the first AMS service for the resource
418                 memcpy(amsDeviceId, &amacl->amss[0], sizeof(*amsDeviceId));
419                 return OC_STACK_OK;
420             }
421         }
422     }
423
424 exit:
425     return OC_STACK_ERROR;
426 }