8514e335a9179e7bc7f390bf86222538e666301a
[platform/upstream/iotivity.git] / resource / csdk / security / src / crlresource.c
1 //******************************************************************
2 //
3 // Copyright 2015 Samsung Electronics 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 #include <stdlib.h>
22 #include <string.h>
23 #include "ocstack.h"
24 #include "logger.h"
25 #include "oic_malloc.h"
26 #include "cJSON.h"
27 #include "base64.h"
28 #include "resourcemanager.h"
29 #include "psinterface.h"
30 #include "utlist.h"
31 #include "srmresourcestrings.h"
32 #include "doxmresource.h"
33 #include "srmutility.h"
34 #ifdef __WITH_X509__
35 #include "crlresource.h"
36 #include "crl.h"
37 #endif /* __WITH_X509__ */
38
39 #define TAG  "SRM-CRL"
40
41 #define SEPARATOR                   ":"
42 #define SEPARATOR_LEN               (1)
43 #define JSON_CRL_NAME               "\"CRL\""
44 #define JSON_CRL_NAME_LEN           (5)
45 #define OIC_JSON_CRL_NAME           "crl"
46 #define OIC_JSON_CRL_ID             "CRLId"
47 #define OIC_JSON_CRL_THIS_UPDATE    "ThisUpdate"
48 #define OIC_JSON_CRL_DATA           "CRLData"
49 #define CRL_DEFAULT_CRL_ID           1
50 #define CRL_DEFAULT_THIS_UPDATE     "150101000000Z"
51 #define CRL_DEFAULT_CRL_DATA        "-"
52
53 static OCResourceHandle     gCrlHandle  = NULL;
54 static OicSecCrl_t         *gCrl        = NULL;
55
56
57 void DeleteCrlBinData(OicSecCrl_t *crl)
58 {
59     if (crl)
60     {
61         //Clean ThisUpdate
62         OICFree(crl->ThisUpdate.data);
63
64         //clean CrlData
65         OICFree(crl->CrlData.data);
66
67         //Clean crl itself
68         OICFree(crl);
69     }
70 }
71
72 char *BinToCrlJSON(const OicSecCrl_t *crl, const bool isIncResName)
73 {
74     if (NULL == crl)
75     {
76         return NULL;
77     }
78
79     char *base64Buff = NULL;
80     uint32_t outLen = 0;
81     uint32_t base64CRLLen = 0;
82     B64Result b64Ret = B64_OK;
83     char *jsonStr = NULL;
84
85     cJSON *jsonRoot = cJSON_CreateObject();
86     VERIFY_NON_NULL(TAG, jsonRoot, ERROR);
87
88     cJSON *jsonCrl = NULL;
89     if(isIncResName)
90     {
91         jsonCrl = cJSON_CreateObject();
92         VERIFY_NON_NULL(TAG, jsonCrl, ERROR);
93         cJSON_AddItemToObject(jsonRoot, OIC_JSON_CRL_NAME, jsonCrl);
94     }
95     else
96     {
97         jsonCrl = jsonRoot;
98     }
99
100     //CRLId -- Mandatory
101     cJSON_AddNumberToObject(jsonCrl, OIC_JSON_CRL_ID, (int)crl->CrlId);
102
103     //ThisUpdate -- Mandatory
104     outLen = 0;
105     base64CRLLen = B64ENCODE_OUT_SAFESIZE(crl->ThisUpdate.len);
106     base64Buff = OICMalloc(base64CRLLen);
107     b64Ret = b64Encode(crl->ThisUpdate.data, crl->ThisUpdate.len, base64Buff,
108              base64CRLLen, &outLen);
109     VERIFY_SUCCESS(TAG, b64Ret == B64_OK, ERROR);
110     cJSON_AddStringToObject(jsonCrl, OIC_JSON_CRL_THIS_UPDATE, base64Buff);
111     OICFree(base64Buff);
112
113     //CRLData -- Mandatory
114     outLen = 0;
115     base64CRLLen = B64ENCODE_OUT_SAFESIZE(crl->CrlData.len);
116     base64Buff = OICMalloc(base64CRLLen);
117     b64Ret = b64Encode(crl->CrlData.data, crl->CrlData.len, base64Buff,
118              base64CRLLen, &outLen);
119     VERIFY_SUCCESS(TAG, b64Ret == B64_OK, ERROR);
120     cJSON_AddStringToObject(jsonCrl, OIC_JSON_CRL_DATA, base64Buff);
121
122     jsonStr = cJSON_PrintUnformatted(jsonRoot);
123
124 exit:
125     OICFree(base64Buff);
126     if (jsonRoot)
127     {
128         cJSON_Delete(jsonRoot);
129     }
130     return jsonStr;
131 }
132
133 OicSecCrl_t *JSONToCrlBin(const char * jsonStr, const bool isIncResName)
134 {
135     if (NULL == jsonStr)
136     {
137         return NULL;
138     }
139
140     OCStackResult ret = OC_STACK_ERROR;
141     OicSecCrl_t *crl =  NULL;
142     cJSON *jsonCrl = NULL;
143     cJSON *jsonObj = NULL;
144
145     unsigned char *base64Buff = NULL;
146     uint32_t base64CRLLen = 0;
147     uint32_t outLen = 0;
148     B64Result b64Ret = B64_OK;
149
150     cJSON *jsonRoot = cJSON_Parse(jsonStr);
151     VERIFY_NON_NULL(TAG, jsonRoot, ERROR);
152
153     if(isIncResName)
154     {
155         jsonCrl = cJSON_GetObjectItem(jsonRoot, OIC_JSON_CRL_NAME);
156     }
157     else
158     {
159         jsonCrl = jsonRoot;
160     }
161     VERIFY_NON_NULL(TAG, jsonCrl, ERROR);
162
163     crl = (OicSecCrl_t *)OICCalloc(1, sizeof(OicSecCrl_t));
164     VERIFY_NON_NULL(TAG, crl, ERROR);
165
166     //CRLId -- Mandatory
167     jsonObj = cJSON_GetObjectItem(jsonCrl, OIC_JSON_CRL_ID);
168     if(jsonObj)
169     {
170         VERIFY_SUCCESS(TAG, cJSON_Number == jsonObj->type, ERROR);
171         crl->CrlId = (uint16_t)jsonObj->valueint;
172     }
173     else // PUT/POST JSON may not have CRLId so set it to the gCRList->CRLId
174     {
175         VERIFY_NON_NULL(TAG, gCrl, ERROR);
176         crl->CrlId = gCrl->CrlId;
177     }
178
179     //ThisUpdate -- Mandatory
180     jsonObj = cJSON_GetObjectItem(jsonCrl, OIC_JSON_CRL_THIS_UPDATE);
181     if(jsonObj)
182     {
183         VERIFY_SUCCESS(TAG, cJSON_String == jsonObj->type, ERROR);
184         if(cJSON_String == jsonObj->type)
185         {
186             //Check for empty string, in case ThisUpdate field has not been set yet
187             if (jsonObj->valuestring[0])
188             {
189                 base64CRLLen = B64ENCODE_OUT_SAFESIZE(strlen(jsonObj->valuestring));
190                 base64Buff = OICMalloc(base64CRLLen);
191                 b64Ret = b64Decode(jsonObj->valuestring, strlen(jsonObj->valuestring), base64Buff,
192                         base64CRLLen, &outLen);
193                 VERIFY_SUCCESS(TAG, (b64Ret == B64_OK && outLen <= base64CRLLen),
194                                 ERROR);
195                 crl->ThisUpdate.data = OICMalloc(outLen + 1);
196                 memcpy(crl->ThisUpdate.data, base64Buff, outLen);
197                 crl->ThisUpdate.len = outLen;
198                 OICFree(base64Buff);
199                 base64Buff = NULL;
200             }
201         }
202     }
203     else // PUT/POST JSON will not have ThisUpdate so set it to the gCRList->ThisUpdate
204     {
205         VERIFY_NON_NULL(TAG, gCrl, ERROR);
206         outLen = gCrl->ThisUpdate.len;
207         crl->ThisUpdate.data = OICMalloc(outLen + 1);
208         memcpy(crl->ThisUpdate.data, gCrl->ThisUpdate.data, outLen);
209         crl->ThisUpdate.len = outLen;
210     }
211
212     //CRLData -- Mandatory
213     jsonObj = cJSON_GetObjectItem(jsonCrl, OIC_JSON_CRL_DATA);
214     if(jsonObj)
215     {
216         VERIFY_SUCCESS(TAG, cJSON_String == jsonObj->type, ERROR);
217         if(cJSON_String == jsonObj->type)
218         {
219             //Check for empty string, in case CRLData field has not been set yet
220             if (jsonObj->valuestring[0])
221             {
222                 outLen = 0;
223                 base64CRLLen = B64ENCODE_OUT_SAFESIZE(strlen(jsonObj->valuestring));
224                 base64Buff = OICMalloc(base64CRLLen);
225                 b64Ret = b64Decode(jsonObj->valuestring, strlen(jsonObj->valuestring), base64Buff,
226                         base64CRLLen, &outLen);
227                 VERIFY_SUCCESS(TAG, (b64Ret == B64_OK && outLen <= base64CRLLen),
228                                 ERROR);
229                 crl->CrlData.data = OICMalloc(outLen + 1);
230                 memcpy(crl->CrlData.data, base64Buff, outLen);
231                 crl->CrlData.len = outLen;
232                 OICFree(base64Buff);
233                 base64Buff = NULL;
234             }
235         }
236     }
237     else // PUT/POST JSON will not have CRLData so set it to the gCRList->CRLData
238     {
239         VERIFY_NON_NULL(TAG, gCrl, ERROR);
240         outLen = gCrl->CrlData.len;
241         crl->CrlData.data = OICMalloc(outLen + 1);
242         memcpy(crl->CrlData.data, gCrl->CrlData.data, outLen);
243         crl->CrlData.len = outLen;
244     }
245
246     ret = OC_STACK_OK;
247 exit:
248     cJSON_Delete(jsonRoot);
249     OICFree(base64Buff);
250     base64Buff = NULL;
251     if (OC_STACK_OK != ret)
252     {
253         DeleteCrlBinData(crl);
254         crl = NULL;
255     }
256     return crl;
257 }
258
259 OCStackResult UpdateCRLResource(const OicSecCrl_t *crl)
260 {
261     char *jsonStr = NULL;
262     OCStackResult res = OC_STACK_ERROR;
263
264     jsonStr = BinToCrlJSON((OicSecCrl_t *) crl, true);
265     if (!jsonStr)
266     {
267         return OC_STACK_ERROR;
268     }
269
270     cJSON *jsonObj = cJSON_Parse(jsonStr);
271     OICFree(jsonStr);
272
273     if (jsonObj == NULL)
274     {
275         return OC_STACK_ERROR;
276     }
277
278     res = UpdateSVRDatabase(OIC_JSON_CRL_NAME, jsonObj);
279     cJSON_Delete(jsonObj);
280
281     return res;
282 }
283
284 static OCEntityHandlerResult HandleCRLPostRequest(const OCEntityHandlerRequest *ehRequest)
285 {
286     OCEntityHandlerResult ehRet = OC_EH_ERROR;
287
288     char *jsonCRL = (char *)(((OCSecurityPayload *)ehRequest->payload)->securityData);
289
290     if (jsonCRL)
291     {
292         OC_LOG(INFO, TAG, "UpdateSVRDB...");
293         OC_LOG_V(INFO, TAG, "crl: \"%s\"", jsonCRL);
294
295         cJSON *jsonObj = cJSON_Parse(jsonCRL);
296         OicSecCrl_t *crl = NULL;
297         crl = JSONToCrlBin(jsonCRL, false);
298         if (!crl)
299         {
300             OC_LOG(ERROR, TAG, "Error JSONToCrlBin");
301         }
302
303         gCrl->CrlId = crl->CrlId;
304
305         OICFree(gCrl->ThisUpdate.data);
306         gCrl->ThisUpdate.data = NULL;
307         gCrl->ThisUpdate.data = OICMalloc(crl->ThisUpdate.len);
308         memcpy(gCrl->ThisUpdate.data, crl->ThisUpdate.data, crl->ThisUpdate.len);
309         gCrl->ThisUpdate.len = crl->ThisUpdate.len;
310
311         OICFree(gCrl->CrlData.data);
312         gCrl->CrlData.data = NULL;
313         gCrl->CrlData.data = OICMalloc(crl->CrlData.len);
314         memcpy(gCrl->CrlData.data, crl->CrlData.data, crl->CrlData.len);
315         gCrl->CrlData.len = crl->CrlData.len;
316
317         if (OC_STACK_OK == UpdateSVRDatabase(OIC_JSON_CRL_NAME, jsonObj))
318         {
319             OC_LOG(INFO, TAG, "UpdateSVRDB == OK");
320             ehRet = OC_EH_RESOURCE_CREATED;
321         }
322
323         DeleteCrlBinData(crl);
324         cJSON_Delete(jsonObj);
325
326     }
327
328     // Send payload to request originator
329     SendSRMResponse(ehRequest, ehRet, NULL);
330
331     OC_LOG_V(INFO, TAG, "%s RetVal %d", __func__, ehRet);
332     return ehRet;
333 }
334
335
336 /*
337  * This internal method is the entity handler for CRL resource and
338  * will handle REST request (GET/PUT/POST/DEL) for them.
339  */
340 OCEntityHandlerResult CRLEntityHandler(OCEntityHandlerFlag flag,
341                                        OCEntityHandlerRequest *ehRequest,
342                                        void *callbackParameter)
343 {
344     OCEntityHandlerResult ehRet = OC_EH_ERROR;
345     (void)callbackParameter;
346
347     if (!ehRequest)
348     {
349         return ehRet;
350     }
351
352     OC_LOG(INFO, TAG, "Handle CRL resource");
353
354     if (flag & OC_REQUEST_FLAG)
355     {
356         // TODO :  Handle PUT and DEL methods
357         OC_LOG (INFO, TAG, "Flag includes OC_REQUEST_FLAG");
358         switch (ehRequest->method)
359         {
360             case OC_REST_GET:
361                 OC_LOG (INFO, TAG, "Not implemented request method.");
362                 //ehRet = HandleCRLGetRequest(ehRequest);
363                 break;
364
365             case OC_REST_POST:
366                 ehRet = HandleCRLPostRequest(ehRequest);
367                 break;
368
369             default:
370                 ehRet = OC_EH_ERROR;
371                 SendSRMResponse(ehRequest, ehRet, NULL);
372         }
373     }
374
375     return ehRet;
376 }
377
378 /*
379  * This internal method is used to create '/oic/sec/crl' resource.
380  */
381 OCStackResult CreateCRLResource()
382 {
383     OCStackResult ret;
384     ret = OCCreateResource(&gCrlHandle,
385                            OIC_RSRC_TYPE_SEC_CRL,
386                            OIC_MI_DEF,
387                            OIC_RSRC_CRL_URI,
388                            CRLEntityHandler,
389                            NULL,
390                            OC_OBSERVABLE);
391
392     if (OC_STACK_OK != ret)
393     {
394         OC_LOG(FATAL, TAG, "Unable to instantiate CRL resource");
395         DeInitCRLResource();
396     }
397     return ret;
398 }
399
400 /**
401  * Get the default value
402  * @retval  NULL for now. Update it when we finalize the default info.
403  */
404 static OicSecCrl_t *GetCrlDefault()
405 {
406     OicSecCrl_t *defaultCrl = NULL;
407     defaultCrl = (OicSecCrl_t *)OICCalloc(1, sizeof(OicSecCrl_t));
408
409     defaultCrl->CrlId = CRL_DEFAULT_CRL_ID;
410
411     defaultCrl->CrlData.len = strlen(CRL_DEFAULT_CRL_DATA);
412     defaultCrl->CrlData.data = OICMalloc(defaultCrl->CrlData.len);
413     memcpy(defaultCrl->CrlData.data, CRL_DEFAULT_CRL_DATA, defaultCrl->CrlData.len);
414
415     defaultCrl->ThisUpdate.len = strlen(CRL_DEFAULT_THIS_UPDATE);
416     defaultCrl->ThisUpdate.data = OICMalloc(defaultCrl->ThisUpdate.len);
417     memcpy(defaultCrl->ThisUpdate.data, CRL_DEFAULT_THIS_UPDATE, defaultCrl->ThisUpdate.len);
418
419     return defaultCrl;
420 }
421
422 /**
423  * Initialize CRL resource by loading data from persistent storage.
424  *
425  * @retval
426  *     OC_STACK_OK    - no errors
427  *     OC_STACK_ERROR - stack process error
428  */
429 OCStackResult InitCRLResource()
430 {
431     OCStackResult ret = OC_STACK_ERROR;
432     char* jsonSVRDatabase;
433
434     //Read CRL resource from PS
435     jsonSVRDatabase = GetSVRDatabase();
436
437     if (jsonSVRDatabase)
438     {
439         //Convert JSON CRL into binary format
440         gCrl = JSONToCrlBin(jsonSVRDatabase, true);
441     }
442     /*
443      * If SVR database in persistent storage got corrupted or
444      * is not available for some reason, a default CrlResource is created
445      * which allows user to initiate CrlResource provisioning again.
446      */
447     if (!jsonSVRDatabase || !gCrl)
448     {
449         gCrl = GetCrlDefault();
450     }
451
452     ret = CreateCRLResource();
453     OICFree(jsonSVRDatabase);
454     return ret;
455 }
456
457 /**
458  * Perform cleanup for ACL resources.
459  */
460 void DeInitCRLResource()
461 {
462     OCDeleteResource(gCrlHandle);
463     gCrlHandle = NULL;
464     DeleteCrlBinData(gCrl);
465     gCrl = NULL;
466 }
467
468 OicSecCrl_t *GetCRLResource()
469 {
470     OicSecCrl_t *crl =  NULL;
471
472     //Read CRL resource from PS
473     char* jsonSVRDatabase = GetSVRDatabase();
474
475     if (jsonSVRDatabase)
476     {
477         //Convert JSON CRL into binary format
478         crl = JSONToCrlBin(jsonSVRDatabase, true);
479     }
480     /*
481      * If SVR database in persistent storage got corrupted or
482      * is not available for some reason, a default CrlResource is created
483      * which allows user to initiate CrlResource provisioning again.
484      */
485     if (!jsonSVRDatabase || !crl)
486     {
487         crl = GetCrlDefault();
488     }
489     OICFree(jsonSVRDatabase);
490
491     return crl;
492 }
493
494 char *GetBase64CRL()
495 {
496     cJSON *jsonCrl = NULL;
497     cJSON *jsonObj = NULL;
498     char *jsonSVRDatabase = GetSVRDatabase();
499     char* ret = NULL;
500
501     cJSON *jsonRoot = cJSON_Parse(jsonSVRDatabase);
502     VERIFY_NON_NULL(TAG, jsonRoot, ERROR);
503
504     jsonCrl = cJSON_GetObjectItem(jsonRoot, OIC_JSON_CRL_NAME);
505     VERIFY_NON_NULL(TAG, jsonCrl, ERROR);
506
507     //CRLData -- Mandatory
508     jsonObj = cJSON_GetObjectItem(jsonCrl, OIC_JSON_CRL_DATA);
509     if(jsonObj)
510     {
511         VERIFY_SUCCESS(TAG, cJSON_String == jsonObj->type, ERROR);
512         if(cJSON_String == jsonObj->type)
513         {
514             //Check for empty string, in case CRLData field has not been set yet
515             if (jsonObj->valuestring[0])
516             {
517                 ret = jsonObj->valuestring;
518             }
519         }
520     }
521 exit:
522     OICFree(jsonSVRDatabase);
523     cJSON_Delete(jsonRoot);
524     return ret;
525 }
526
527 void  GetDerCrl(ByteArray crlArray)
528 {
529     OicSecCrl_t * crlRes = GetCRLResource();
530     if (crlRes && crlRes->CrlData.len <= crlArray.len)
531     {
532         memcpy(crlArray.data, crlRes->CrlData.data, crlRes->CrlData.len);
533         crlArray.len = crlRes->CrlData.len;
534     }
535     else
536     {
537         crlArray.len = 0;
538     }
539     DeleteCrlBinData(crlRes);
540 }