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