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