[CONPRO-311] Fix due to TinyCBOR v0.4 Release
[platform/upstream/iotivity.git] / resource / csdk / security / src / svcresource.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 #include <stdlib.h>
21 #include <string.h>
22
23 #include "ocstack.h"
24 #include "ocpayload.h"
25 #include "ocpayloadcbor.h"
26 #include "oic_malloc.h"
27 #include "utlist.h"
28 #include "payload_logging.h"
29 #include "resourcemanager.h"
30 #include "psinterface.h"
31 #include "svcresource.h"
32 #include "srmresourcestrings.h"
33 #include "srmutility.h"
34
35 #include "security_internals.h"
36
37 #define TAG  "OIC_SRM_SVC"
38
39 /** Default cbor payload size. This value is increased in case of CborErrorOutOfMemory.
40  * The value of payload size is increased until reaching belox max cbor size. */
41 static const uint16_t CBOR_SIZE = 512;
42
43 /** Max cbor size payload. */
44 static const uint16_t CBOR_MAX_SIZE = 4400;
45
46 /** SVC Map size - Number of mandatory items. */
47 static const uint8_t SVC_MAP_SIZE = 3;
48
49 static OicSecSvc_t        *gSvc = NULL;
50 static OCResourceHandle    gSvcHandle = NULL;
51
52 void DeleteSVCList(OicSecSvc_t* svc)
53 {
54     if (svc)
55     {
56         OicSecSvc_t *svcTmp1 = NULL, *svcTmp2 = NULL;
57         LL_FOREACH_SAFE(svc, svcTmp1, svcTmp2)
58         {
59             LL_DELETE(svc, svcTmp1);
60
61             // Clean Owners
62             OICFree(svcTmp1->owners);
63
64             // Clean SVC node itself
65             OICFree(svcTmp1);
66         }
67     }
68 }
69
70 static size_t svcElementsCount(const OicSecSvc_t *secSvc)
71 {
72     size_t size = 0;
73     for (const OicSecSvc_t *svc = secSvc; svc; svc = svc->next)
74     {
75         size++;
76     }
77     return size;
78 }
79
80 OCStackResult SVCToCBORPayload(const OicSecSvc_t *svc, uint8_t **cborPayload,
81                                size_t *cborSize)
82 {
83     if (NULL == svc || NULL == cborPayload || NULL != *cborPayload || NULL == cborSize)
84     {
85        return OC_STACK_INVALID_PARAM;
86     }
87
88     size_t cborLen = *cborSize;
89     if (0 == cborLen)
90     {
91         cborLen = CBOR_SIZE;
92     }
93     *cborPayload = NULL;
94     *cborSize = 0;
95
96     int64_t cborEncoderResult = CborNoError;
97     OCStackResult ret = OC_STACK_ERROR;
98     CborEncoder encoder;
99     CborEncoder svcArray;
100
101     uint8_t *outPayload = (uint8_t *)OICCalloc(1, cborLen);
102     VERIFY_NON_NULL(TAG, outPayload, ERROR);
103
104     cbor_encoder_init(&encoder, outPayload, cborLen, 0);
105
106     // Create SVC Array
107     cborEncoderResult = cbor_encoder_create_array(&encoder, &svcArray, svcElementsCount(svc));
108     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to Create SVC Array.");
109
110     while (svc)
111     {
112         CborEncoder svcMap;
113         CborEncoder owners;
114
115         cborEncoderResult = cbor_encoder_create_map(&svcArray, &svcMap, SVC_MAP_SIZE);
116         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to Create SVC Map.");
117
118         // Service Device Identity
119         cborEncoderResult = cbor_encode_text_string(&svcMap, OIC_JSON_SERVICE_DEVICE_ID,
120             strlen(OIC_JSON_SERVICE_DEVICE_ID));
121         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to Add SVC Device Id.");
122         cborEncoderResult = cbor_encode_byte_string(&svcMap, (uint8_t *)svc->svcdid.id,
123             sizeof(svc->svcdid.id));
124         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to ");
125
126         // Service Type
127         cborEncoderResult = cbor_encode_text_string(&svcMap, OIC_JSON_SERVICE_TYPE,
128             strlen(OIC_JSON_SERVICE_TYPE));
129         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to Add SVC Serv Type Tag.");
130         cborEncoderResult = cbor_encode_int(&svcMap, svc->svct);
131         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to Add SVC Serv Type Value.");
132
133         // Owners
134         // TODO: Need to modification to single ROwner, (Currently SINGLE_SERVICE_CLIENT_DRIVEN only)
135         cborEncoderResult = cbor_encode_text_string(&svcMap, OIC_JSON_OWNERS_NAME,
136             strlen(OIC_JSON_OWNERS_NAME));
137         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to Add SVC Owners Tag.");
138         cborEncoderResult = cbor_encoder_create_array(&svcMap, &owners, svc->ownersLen);
139         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to Add SVC Array.");
140         for (size_t i = 0; i < svc->ownersLen; i++)
141         {
142             cborEncoderResult = cbor_encode_byte_string(&owners, (uint8_t *)svc->owners[i].id,
143                 sizeof(svc->owners[i].id));
144             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to Add SVC Owners Value.");
145         }
146         cborEncoderResult = cbor_encoder_close_container(&svcMap, &owners);
147         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to Close SVC Array.");
148
149         cborEncoderResult = cbor_encoder_close_container(&svcArray, &svcMap);
150         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to Close SVC Map.");
151
152         svc = svc->next;
153     }
154
155     cborEncoderResult = cbor_encoder_close_container(&encoder, &svcArray);
156     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed to Close SVC Array.");
157
158     if (CborNoError == cborEncoderResult)
159     {
160         *cborPayload = outPayload;
161         *cborSize = cbor_encoder_get_buffer_size(&encoder, outPayload);
162         ret = OC_STACK_OK;
163     }
164
165 exit:
166     if ((CborErrorOutOfMemory == cborEncoderResult) && (cborLen < CBOR_MAX_SIZE))
167     {
168         // reallocate and try again!
169         OICFree(outPayload);
170         outPayload = NULL;
171         // Since the allocated initial memory failed, double the memory.
172         cborLen += cbor_encoder_get_buffer_size(&encoder, encoder.end);
173         cborEncoderResult = CborNoError;
174         ret = SVCToCBORPayload(svc, cborPayload, &cborLen);
175         *cborSize = cborLen;
176     }
177
178     if (CborNoError != cborEncoderResult)
179     {
180         OICFree(outPayload);
181         outPayload = NULL;
182         *cborSize = 0;
183         *cborPayload = NULL;
184         ret = OC_STACK_ERROR;
185     }
186
187     return ret;
188 }
189
190 OCStackResult CBORPayloadToSVC(const uint8_t *cborPayload, size_t size,
191                                OicSecSvc_t **secSvc)
192 {
193     if (NULL == cborPayload || NULL == secSvc || NULL != *secSvc || 0 == size)
194     {
195         return OC_STACK_INVALID_PARAM;
196     }
197
198     *secSvc = NULL;
199
200     OCStackResult ret = OC_STACK_ERROR;
201
202     CborValue svcCbor = { .parser = NULL };
203     CborParser parser = { .end = NULL };
204     CborError cborFindResult = CborNoError;
205
206     cbor_parser_init(cborPayload, size, 0, &parser, &svcCbor);
207     OicSecSvc_t *headSvc = NULL;
208
209     CborValue svcArray = { .parser = NULL };
210     cborFindResult = cbor_value_enter_container(&svcCbor, &svcArray);
211     VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to Enter SVC Array.");
212
213     while (cbor_value_is_valid(&svcArray))
214     {
215         CborValue svcMap = { .parser = NULL };
216         OicSecSvc_t *svc = (OicSecSvc_t *) OICCalloc(1, sizeof(OicSecSvc_t));
217         VERIFY_NON_NULL(TAG, svc, ERROR);
218         cborFindResult = cbor_value_enter_container(&svcArray, &svcMap);
219         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to Enter SVC Map.");
220
221         while (cbor_value_is_valid(&svcMap))
222         {
223             char* name = NULL;
224             size_t len = 0;
225             CborType type = CborInvalidType;
226
227             cborFindResult = cbor_value_dup_text_string(&svcMap, &name, &len, NULL);
228             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to Find Name.");
229             cborFindResult = cbor_value_advance(&svcMap);
230             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to Advance.");
231
232             type = cbor_value_get_type(&svcMap);
233             // Service Device Identity
234             if (0 == strcmp(OIC_JSON_SERVICE_DEVICE_ID, name) && cbor_value_is_byte_string(&svcMap))
235             {
236                 uint8_t *subjectId = NULL;
237                 cborFindResult = cbor_value_dup_byte_string(&svcMap, &subjectId, &len, NULL);
238                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to Find SubjectId.");
239                 memcpy(svc->svcdid.id, subjectId, len);
240                 OICFree(subjectId);
241             }
242             // Service Type
243             if (0 == strcmp(OIC_JSON_SERVICE_TYPE, name) && cbor_value_is_integer(&svcMap))
244             {
245                 int svct;
246
247                 cborFindResult = cbor_value_get_int(&svcMap, &svct);
248                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to Find SVCT.");
249                 svc->svct = (OicSecSvcType_t)svct;
250             }
251
252             // Owners -- Mandatory
253             if (0 == strcmp(OIC_JSON_OWNERS_NAME, name) && cbor_value_is_array(&svcMap))
254             {
255                 int i = 0;
256                 CborValue owners = { .parser = NULL };
257
258                 cborFindResult = cbor_value_get_array_length(&svcMap, &svc->ownersLen);
259                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to Find Owner Len.");
260                 cborFindResult = cbor_value_enter_container(&svcMap, &owners);
261                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to Enter Owner Array.");
262                 svc->owners = (OicUuid_t *)OICCalloc(svc->ownersLen, sizeof(*svc->owners));
263                 VERIFY_NON_NULL(TAG, svc->owners, ERROR);
264
265                 while (cbor_value_is_valid(&owners) && cbor_value_is_byte_string(&owners))
266                 {
267                     uint8_t *owner = NULL;
268                     cborFindResult = cbor_value_dup_byte_string(&owners, &owner, &len, NULL);
269                     VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to Find Owner Array Value.");
270                     cborFindResult = cbor_value_advance(&owners);
271                     VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to Advance Owner Array.");
272                     memcpy(svc->owners[i++].id, owner, len);
273                     OICFree(owner);
274                 }
275             }
276             if (CborMapType != type  && cbor_value_is_valid(&svcMap))
277             {
278                 cborFindResult = cbor_value_advance(&svcMap);
279                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to Advance SVC.");
280             }
281             OICFree(name);
282         }
283
284         svc->next = NULL;
285         if (NULL == headSvc)
286         {
287             headSvc = svc;
288         }
289         else
290         {
291             OicSecSvc_t *temp = headSvc;
292             while (temp->next)
293             {
294                 temp = temp->next;
295             }
296             temp->next = svc;
297         }
298         if (cbor_value_is_valid(&svcArray))
299         {
300             cborFindResult = cbor_value_advance(&svcArray);
301             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to Find Name.");
302         }
303     }
304     *secSvc = headSvc;
305     ret = OC_STACK_OK;
306
307 exit:
308     if (CborNoError != cborFindResult)
309     {
310         DeleteSVCList(headSvc);
311         headSvc = NULL;
312         *secSvc = NULL;
313         ret = OC_STACK_ERROR;
314     }
315     return ret;
316 }
317
318 static OCEntityHandlerResult HandleSVCGetRequest(const OCEntityHandlerRequest * ehRequest)
319 {
320     // Convert SVC data into JSON for transmission
321     size_t size = 0;
322     uint8_t *cborSvc = NULL;
323     OCStackResult res =  SVCToCBORPayload(gSvc, &cborSvc, &size);
324     OCEntityHandlerResult ehRet = (res == OC_STACK_OK) ? OC_EH_OK : OC_EH_ERROR;
325
326     // Send response payload to request originator
327     if (OC_STACK_OK != SendSRMResponse(ehRequest, ehRet, cborSvc, size))
328     {
329         ehRet = OC_EH_ERROR;
330         OIC_LOG(ERROR, TAG, "SendSRMResponse failed in HandleSVCGetRequest");
331     }
332
333     OICFree(cborSvc);
334     OIC_LOG_V (DEBUG, TAG, "%s RetVal %d", __func__ , ehRet);
335     return ehRet;
336 }
337
338 static OCEntityHandlerResult HandleSVCPostRequest(const OCEntityHandlerRequest * ehRequest)
339 {
340     OCEntityHandlerResult ehRet = OC_EH_ERROR;
341     uint8_t *payload = ((OCSecurityPayload *) ehRequest->payload)->securityData;
342     size_t size = ((OCSecurityPayload *) ehRequest->payload)->payloadSize;
343     if (payload)
344     {
345         // Convert CBOR SVC data into SVC. This will also validate the SVC data received.
346         OicSecSvc_t *newSvc = NULL;
347         OCStackResult res =  CBORPayloadToSVC(payload, size, &newSvc);
348         if (newSvc && res == OC_STACK_OK)
349         {
350             // Append the new SVC to existing SVC
351             LL_APPEND(gSvc, newSvc);
352
353             // Convert SVC data into JSON for update to persistent storage
354             size_t size = 0;
355             uint8_t *cborPayload = NULL;
356             res = SVCToCBORPayload(gSvc, &cborPayload, &size);
357             if (cborPayload && OC_STACK_OK == res &&
358                 UpdateSecureResourceInPS(OIC_JSON_SVC_NAME, cborPayload, size) == OC_STACK_OK)
359             {
360                 ehRet = OC_EH_CHANGED;
361             }
362             OICFree(cborPayload);
363         }
364     }
365
366     // Send payload to request originator
367     if (OC_STACK_OK != SendSRMResponse(ehRequest, ehRet, NULL, 0))
368     {
369         ehRet = OC_EH_ERROR;
370         OIC_LOG(ERROR, TAG, "SendSRMResponse failed in HandleSVCPostRequest");
371     }
372
373     OIC_LOG_V (DEBUG, TAG, "%s RetVal %d", __func__ , ehRet);
374     return ehRet;
375 }
376
377 /**
378  * This internal method is the entity handler for SVC resources and
379  * will handle REST request (GET/PUT/POST/DEL) for them.
380  */
381 static OCEntityHandlerResult SVCEntityHandler(OCEntityHandlerFlag flag,
382                                               OCEntityHandlerRequest * ehRequest,
383                                               void* callbackParameter)
384 {
385     (void) callbackParameter;
386     OCEntityHandlerResult ehRet = OC_EH_ERROR;
387
388     if (!ehRequest)
389     {
390         return ehRet;
391     }
392
393     if (flag & OC_REQUEST_FLAG)
394     {
395         switch (ehRequest->method)
396         {
397             case OC_REST_GET:
398                 ehRet = HandleSVCGetRequest(ehRequest);
399                 break;
400
401             case OC_REST_POST:
402                 ehRet = HandleSVCPostRequest(ehRequest);
403                 break;
404
405             default:
406                 ehRet = OC_EH_ERROR;
407                 SendSRMResponse(ehRequest, ehRet, NULL, 0);
408         }
409     }
410
411     return ehRet;
412 }
413
414 /**
415  * This internal method is used to create '/oic/sec/svc' resource.
416  */
417 static OCStackResult CreateSVCResource()
418 {
419     OCStackResult ret = OCCreateResource(&gSvcHandle,
420                                          OIC_RSRC_TYPE_SEC_SVC,
421                                          OC_RSRVD_INTERFACE_DEFAULT,
422                                          OIC_RSRC_SVC_URI,
423                                          SVCEntityHandler,
424                                          NULL,
425                                          OC_OBSERVABLE);
426
427     if (OC_STACK_OK != ret)
428     {
429         OIC_LOG(FATAL, TAG, "Unable to instantiate SVC resource");
430         DeInitSVCResource();
431     }
432     return ret;
433 }
434
435 OCStackResult InitSVCResource()
436 {
437     OCStackResult ret = OC_STACK_ERROR;
438
439     OIC_LOG_V(DEBUG, TAG, "Begin %s ", __func__ );
440
441     uint8_t *data = NULL;
442     size_t size = 0;
443     ret = GetSecureVirtualDatabaseFromPS(OIC_JSON_SVC_NAME, &data, &size);
444     // If database read failed
445     if (ret != OC_STACK_OK)
446     {
447         OIC_LOG (DEBUG, TAG, "ReadSVDataFromPS failed");
448     }
449
450     if (data)
451     {
452         // Convert CBOR SVC into binary format
453         ret = CBORPayloadToSVC(data, size, &gSvc);
454         if (ret != OC_STACK_OK)
455         {
456             OIC_LOG (DEBUG, TAG, " ConvertCBOR SVC into binary format failed");
457         }
458         OICFree(data);
459     }
460
461     // Instantiate 'oic.sec.svc'
462     ret = CreateSVCResource();
463
464     if (OC_STACK_OK != ret)
465     {
466         DeInitSVCResource();
467     }
468
469     OIC_LOG_V(DEBUG, TAG, "%s RetVal %d", __func__ , ret);
470     return ret;
471 }
472
473 void DeInitSVCResource()
474 {
475     OCDeleteResource(gSvcHandle);
476     gSvcHandle = NULL;
477
478     DeleteSVCList(gSvc);
479     gSvc = NULL;
480 }