Imported Upstream version 1.1.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))
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))
243             {
244                 cborFindResult = cbor_value_get_int(&svcMap, (int *) &svc->svct);
245                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to Find SVCT.");
246             }
247
248             // Owners -- Mandatory
249             if (0 == strcmp(OIC_JSON_OWNERS_NAME, name))
250             {
251                 int i = 0;
252                 CborValue owners = { .parser = NULL };
253
254                 cborFindResult = cbor_value_get_array_length(&svcMap, &svc->ownersLen);
255                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to Find Owner Len.");
256                 cborFindResult = cbor_value_enter_container(&svcMap, &owners);
257                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to Enter Owner Array.");
258                 svc->owners = (OicUuid_t *)OICCalloc(svc->ownersLen, sizeof(*svc->owners));
259                 VERIFY_NON_NULL(TAG, svc->owners, ERROR);
260
261                 while (cbor_value_is_valid(&owners))
262                 {
263                     uint8_t *owner = NULL;
264                     cborFindResult = cbor_value_dup_byte_string(&owners, &owner, &len, NULL);
265                     VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to Find Owner Array Value.");
266                     cborFindResult = cbor_value_advance(&owners);
267                     VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to Advance Owner Array.");
268                     memcpy(svc->owners[i++].id, owner, len);
269                     OICFree(owner);
270                 }
271             }
272             if (CborMapType != type  && cbor_value_is_valid(&svcMap))
273             {
274                 cborFindResult = cbor_value_advance(&svcMap);
275                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to Advance SVC.");
276             }
277             OICFree(name);
278         }
279
280         svc->next = NULL;
281         if (NULL == headSvc)
282         {
283             headSvc = svc;
284         }
285         else
286         {
287             OicSecSvc_t *temp = headSvc;
288             while (temp->next)
289             {
290                 temp = temp->next;
291             }
292             temp->next = svc;
293         }
294         if (cbor_value_is_valid(&svcArray))
295         {
296             cborFindResult = cbor_value_advance(&svcArray);
297             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to Find Name.");
298         }
299     }
300     *secSvc = headSvc;
301     ret = OC_STACK_OK;
302
303 exit:
304     if (CborNoError != cborFindResult)
305     {
306         DeleteSVCList(headSvc);
307         headSvc = NULL;
308         *secSvc = NULL;
309         ret = OC_STACK_ERROR;
310     }
311     return ret;
312 }
313
314 static OCEntityHandlerResult HandleSVCGetRequest(const OCEntityHandlerRequest * ehRequest)
315 {
316     // Convert SVC data into JSON for transmission
317     size_t size = 0;
318     uint8_t *cborSvc = NULL;
319     OCStackResult res =  SVCToCBORPayload(gSvc, &cborSvc, &size);
320     OCEntityHandlerResult ehRet = (res == OC_STACK_OK) ? OC_EH_OK : OC_EH_ERROR;
321
322     // Send response payload to request originator
323     if (OC_STACK_OK != SendSRMResponse(ehRequest, ehRet, cborSvc, size))
324     {
325         ehRet = OC_EH_ERROR;
326         OIC_LOG(ERROR, TAG, "SendSRMResponse failed in HandleSVCGetRequest");
327     }
328
329     OICFree(cborSvc);
330     OIC_LOG_V (DEBUG, TAG, "%s RetVal %d", __func__ , ehRet);
331     return ehRet;
332 }
333
334 static OCEntityHandlerResult HandleSVCPostRequest(const OCEntityHandlerRequest * ehRequest)
335 {
336     OCEntityHandlerResult ehRet = OC_EH_ERROR;
337     uint8_t *payload = ((OCSecurityPayload *) ehRequest->payload)->securityData;
338     size_t size = ((OCSecurityPayload *) ehRequest->payload)->payloadSize;
339     if (payload)
340     {
341         // Convert CBOR SVC data into SVC. This will also validate the SVC data received.
342         OicSecSvc_t *newSvc = NULL;
343         OCStackResult res =  CBORPayloadToSVC(payload, size, &newSvc);
344         if (newSvc && res == OC_STACK_OK)
345         {
346             // Append the new SVC to existing SVC
347             LL_APPEND(gSvc, newSvc);
348
349             // Convert SVC data into JSON for update to persistent storage
350             size_t size = 0;
351             uint8_t *cborPayload = NULL;
352             res = SVCToCBORPayload(gSvc, &cborPayload, &size);
353             if (cborPayload && OC_STACK_OK == res &&
354                 UpdateSecureResourceInPS(OIC_JSON_SVC_NAME, cborPayload, size) == OC_STACK_OK)
355             {
356                 ehRet = OC_EH_RESOURCE_CREATED;
357             }
358             OICFree(cborPayload);
359         }
360     }
361
362     // Send payload to request originator
363     if (OC_STACK_OK != SendSRMResponse(ehRequest, ehRet, NULL, 0))
364     {
365         ehRet = OC_EH_ERROR;
366         OIC_LOG(ERROR, TAG, "SendSRMResponse failed in HandleSVCPostRequest");
367     }
368
369     OIC_LOG_V (DEBUG, TAG, "%s RetVal %d", __func__ , ehRet);
370     return ehRet;
371 }
372
373 /**
374  * This internal method is the entity handler for SVC resources and
375  * will handle REST request (GET/PUT/POST/DEL) for them.
376  */
377 static OCEntityHandlerResult SVCEntityHandler(OCEntityHandlerFlag flag,
378                                               OCEntityHandlerRequest * ehRequest,
379                                               void* callbackParameter)
380 {
381     (void) callbackParameter;
382     OCEntityHandlerResult ehRet = OC_EH_ERROR;
383
384     if (!ehRequest)
385     {
386         return ehRet;
387     }
388
389     if (flag & OC_REQUEST_FLAG)
390     {
391         switch (ehRequest->method)
392         {
393             case OC_REST_GET:
394                 ehRet = HandleSVCGetRequest(ehRequest);
395                 break;
396
397             case OC_REST_POST:
398                 ehRet = HandleSVCPostRequest(ehRequest);
399                 break;
400
401             default:
402                 ehRet = OC_EH_ERROR;
403                 SendSRMResponse(ehRequest, ehRet, NULL, 0);
404         }
405     }
406
407     return ehRet;
408 }
409
410 /**
411  * This internal method is used to create '/oic/sec/svc' resource.
412  */
413 static OCStackResult CreateSVCResource()
414 {
415     OCStackResult ret = OCCreateResource(&gSvcHandle,
416                                          OIC_RSRC_TYPE_SEC_SVC,
417                                          OIC_MI_DEF,
418                                          OIC_RSRC_SVC_URI,
419                                          SVCEntityHandler,
420                                          NULL,
421                                          OC_OBSERVABLE);
422
423     if (OC_STACK_OK != ret)
424     {
425         OIC_LOG(FATAL, TAG, "Unable to instantiate SVC resource");
426         DeInitSVCResource();
427     }
428     return ret;
429 }
430
431 OCStackResult InitSVCResource()
432 {
433     OCStackResult ret = OC_STACK_ERROR;
434
435     OIC_LOG_V(DEBUG, TAG, "Begin %s ", __func__ );
436
437     uint8_t *data = NULL;
438     size_t size = 0;
439     ret = GetSecureVirtualDatabaseFromPS(OIC_JSON_SVC_NAME, &data, &size);
440     // If database read failed
441     if (ret != OC_STACK_OK)
442     {
443         OIC_LOG (DEBUG, TAG, "ReadSVDataFromPS failed");
444     }
445
446     if (data)
447     {
448         // Convert CBOR SVC into binary format
449         ret = CBORPayloadToSVC(data, size, &gSvc);
450         if (ret != OC_STACK_OK)
451         {
452             OIC_LOG (DEBUG, TAG, " ConvertCBOR SVC into binary format failed");
453         }
454         OICFree(data);
455     }
456
457     // Instantiate 'oic.sec.svc'
458     ret = CreateSVCResource();
459
460     if (OC_STACK_OK != ret)
461     {
462         DeInitSVCResource();
463     }
464
465     OIC_LOG_V(DEBUG, TAG, "%s RetVal %d", __func__ , ret);
466     return ret;
467 }
468
469 void DeInitSVCResource()
470 {
471     OCDeleteResource(gSvcHandle);
472     gSvcHandle = NULL;
473
474     DeleteSVCList(gSvc);
475     gSvc = NULL;
476 }