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