d77a75e839070ecd69e385f2242a19c938bdc561
[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     ehRet = ((SendSRMResponse(ehRequest, ehRet, cborSvc, size)) == OC_STACK_OK) ?
328                    OC_EH_OK : OC_EH_ERROR;
329
330     OICFree(cborSvc);
331     OIC_LOG_V (DEBUG, TAG, "%s RetVal %d", __func__ , ehRet);
332     return ehRet;
333 }
334
335 static OCEntityHandlerResult HandleSVCPostRequest(const OCEntityHandlerRequest * ehRequest)
336 {
337     OCEntityHandlerResult ehRet = OC_EH_ERROR;
338     uint8_t *payload = ((OCSecurityPayload *) ehRequest->payload)->securityData;
339     size_t size = ((OCSecurityPayload *) ehRequest->payload)->payloadSize;
340     if (payload)
341     {
342         // Convert CBOR SVC data into SVC. This will also validate the SVC data received.
343         OicSecSvc_t *newSvc = NULL;
344         OCStackResult res =  CBORPayloadToSVC(payload, size, &newSvc);
345         if (newSvc && res == OC_STACK_OK)
346         {
347             // Append the new SVC to existing SVC
348             LL_APPEND(gSvc, newSvc);
349
350             // Convert SVC data into JSON for update to persistent storage
351             size_t size = 0;
352             uint8_t *cborPayload = NULL;
353             res = SVCToCBORPayload(gSvc, &cborPayload, &size);
354             if (cborPayload && OC_STACK_OK == res &&
355                 UpdateSecureResourceInPS(OIC_JSON_SVC_NAME, cborPayload, size) == OC_STACK_OK)
356             {
357                 ehRet = OC_EH_CHANGED;
358             }
359             OICFree(cborPayload);
360         }
361     }
362
363     // Send payload to request originator
364     if (OC_STACK_OK != SendSRMResponse(ehRequest, ehRet, NULL, 0))
365     {
366         ehRet = OC_EH_ERROR;
367         OIC_LOG(ERROR, TAG, "SendSRMResponse failed in HandleSVCPostRequest");
368     }
369
370     OIC_LOG_V (DEBUG, TAG, "%s RetVal %d", __func__ , ehRet);
371     return ehRet;
372 }
373
374 /**
375  * This internal method is the entity handler for SVC resources and
376  * will handle REST request (GET/PUT/POST/DEL) for them.
377  */
378 static OCEntityHandlerResult SVCEntityHandler(OCEntityHandlerFlag flag,
379                                               OCEntityHandlerRequest * ehRequest,
380                                               void* callbackParameter)
381 {
382     (void) callbackParameter;
383     OCEntityHandlerResult ehRet = OC_EH_ERROR;
384
385     if (!ehRequest)
386     {
387         return ehRet;
388     }
389
390     if (flag & OC_REQUEST_FLAG)
391     {
392         switch (ehRequest->method)
393         {
394             case OC_REST_GET:
395                 ehRet = HandleSVCGetRequest(ehRequest);
396                 break;
397
398             case OC_REST_POST:
399                 ehRet = HandleSVCPostRequest(ehRequest);
400                 break;
401
402             default:
403                 ehRet = OC_EH_ERROR;
404                 SendSRMResponse(ehRequest, ehRet, NULL, 0);
405         }
406     }
407
408     return ehRet;
409 }
410
411 /**
412  * This internal method is used to create '/oic/sec/svc' resource.
413  */
414 static OCStackResult CreateSVCResource()
415 {
416     OCStackResult ret = OCCreateResource(&gSvcHandle,
417                                          OIC_RSRC_TYPE_SEC_SVC,
418                                          OC_RSRVD_INTERFACE_DEFAULT,
419                                          OIC_RSRC_SVC_URI,
420                                          SVCEntityHandler,
421                                          NULL,
422                                          OC_OBSERVABLE);
423
424     if (OC_STACK_OK != ret)
425     {
426         OIC_LOG(FATAL, TAG, "Unable to instantiate SVC resource");
427         DeInitSVCResource();
428     }
429     return ret;
430 }
431
432 OCStackResult InitSVCResource()
433 {
434     OCStackResult ret = OC_STACK_ERROR;
435
436     OIC_LOG_V(DEBUG, TAG, "Begin %s ", __func__ );
437
438     uint8_t *data = NULL;
439     size_t size = 0;
440     ret = GetSecureVirtualDatabaseFromPS(OIC_JSON_SVC_NAME, &data, &size);
441     // If database read failed
442     if (ret != OC_STACK_OK)
443     {
444         OIC_LOG (DEBUG, TAG, "ReadSVDataFromPS failed");
445     }
446
447     if (data)
448     {
449         // Convert CBOR SVC into binary format
450         ret = CBORPayloadToSVC(data, size, &gSvc);
451         if (ret != OC_STACK_OK)
452         {
453             OIC_LOG (DEBUG, TAG, " ConvertCBOR SVC into binary format failed");
454         }
455         OICFree(data);
456     }
457
458     // Instantiate 'oic.sec.svc'
459     ret = CreateSVCResource();
460
461     if (OC_STACK_OK != ret)
462     {
463         DeInitSVCResource();
464     }
465
466     OIC_LOG_V(DEBUG, TAG, "%s RetVal %d", __func__ , ret);
467     return ret;
468 }
469
470 void DeInitSVCResource()
471 {
472     OCDeleteResource(gSvcHandle);
473     gSvcHandle = NULL;
474
475     DeleteSVCList(gSvc);
476     gSvc = NULL;
477 }