[CONPRO-296] Check Null parameter in GetACLResourceData()
[platform/upstream/iotivity.git] / resource / csdk / security / src / secureresourcemanager.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
21 #include <string.h>
22 #include "ocstack.h"
23 #include "logger.h"
24 #include "cainterface.h"
25 #include "resourcemanager.h"
26 #include "credresource.h"
27 #include "policyengine.h"
28 #include "srmutility.h"
29 #include "amsmgr.h"
30 #include "oic_string.h"
31 #include "oic_malloc.h"
32 #include "securevirtualresourcetypes.h"
33 #include "secureresourcemanager.h"
34 #include "srmresourcestrings.h"
35 #include "ocresourcehandler.h"
36
37 #if defined( __WITH_TLS__) || defined(__WITH_DTLS__)
38 #include "pkix_interface.h"
39 #endif //__WITH_TLS__ or __WITH_DTLS__
40 #define TAG  "OIC_SRM"
41
42 //Request Callback handler
43 static CARequestCallback gRequestHandler = NULL;
44 //Response Callback handler
45 static CAResponseCallback gResponseHandler = NULL;
46 //Error Callback handler
47 static CAErrorCallback gErrorHandler = NULL;
48 //Persistent Storage callback handler for open/read/write/close/unlink
49 static OCPersistentStorage *gPersistentStorageHandler =  NULL;
50 //Provisioning response callback
51 static SPResponseCallback gSPResponseHandler = NULL;
52
53 /**
54  * A single global Policy Engine context will suffice as long
55  * as SRM is single-threaded.
56  */
57 PEContext_t g_policyEngineContext;
58
59 /**
60  * Function to register provisoning API's response callback.
61  * @param respHandler response handler callback.
62  */
63 void SRMRegisterProvisioningResponseHandler(SPResponseCallback respHandler)
64 {
65     gSPResponseHandler = respHandler;
66 }
67
68 void SetResourceRequestType(PEContext_t *context, const char *resourceUri)
69 {
70     context->resourceType = GetSvrTypeFromUri(resourceUri);
71 }
72
73 static void SRMSendUnAuthorizedAccessresponse(PEContext_t *context)
74 {
75     CAResponseInfo_t responseInfo = {.result = CA_EMPTY};
76
77     if (NULL == context ||
78        NULL == context->amsMgrContext->requestInfo)
79     {
80         OIC_LOG_V(ERROR, TAG, "%s : NULL Parameter(s)",__func__);
81         return;
82     }
83
84     memcpy(&responseInfo.info, &(context->amsMgrContext->requestInfo->info),
85             sizeof(responseInfo.info));
86     responseInfo.info.payload = NULL;
87     responseInfo.result = CA_UNAUTHORIZED_REQ;
88     responseInfo.info.dataType = CA_RESPONSE_DATA;
89
90     if (CA_STATUS_OK == CASendResponse(context->amsMgrContext->endpoint, &responseInfo))
91     {
92         OIC_LOG(DEBUG, TAG, "Succeed in sending response to a unauthorized request!");
93     }
94     else
95     {
96         OIC_LOG(ERROR, TAG, "Failed in sending response to a unauthorized request!");
97     }
98 }
99
100 void SRMSendResponse(SRMAccessResponse_t responseVal)
101 {
102     OIC_LOG(DEBUG, TAG, "Sending response to remote device");
103
104     if (IsAccessGranted(responseVal) && gRequestHandler)
105     {
106         OIC_LOG_V(INFO, TAG, "%s : Access granted. Passing Request to RI layer", __func__);
107         if (!g_policyEngineContext.amsMgrContext->endpoint ||
108             !g_policyEngineContext.amsMgrContext->requestInfo)
109         {
110             OIC_LOG_V(ERROR, TAG, "%s : Invalid arguments", __func__);
111             SRMSendUnAuthorizedAccessresponse(&g_policyEngineContext);
112             goto exit;
113         }
114         gRequestHandler(g_policyEngineContext.amsMgrContext->endpoint,
115                 g_policyEngineContext.amsMgrContext->requestInfo);
116     }
117     else
118     {
119         OIC_LOG_V(INFO, TAG, "%s : ACCESS_DENIED.", __func__);
120         SRMSendUnAuthorizedAccessresponse(&g_policyEngineContext);
121     }
122
123 exit:
124     //Resetting PE state to AWAITING_REQUEST
125     SetPolicyEngineState(&g_policyEngineContext, AWAITING_REQUEST);
126 }
127
128 /**
129  * Handle the request from the SRM.
130  *
131  * @param endPoint object from which the response is received.
132  * @param requestInfo contains information for the request.
133  */
134 void SRMRequestHandler(const CAEndpoint_t *endPoint, const CARequestInfo_t *requestInfo)
135 {
136     OIC_LOG(DEBUG, TAG, "Received request from remote device");
137
138     bool isRequestOverSecureChannel = false;
139     if (!endPoint || !requestInfo)
140     {
141         OIC_LOG(ERROR, TAG, "Invalid arguments");
142         return;
143     }
144
145     // Copy the subjectID
146     OicUuid_t subjectId = {.id = {0}};
147     memcpy(subjectId.id, requestInfo->info.identity.id, sizeof(subjectId.id));
148     if (endPoint->flags & CA_SECURE)
149     {
150         OIC_LOG(INFO, TAG, "request over secure channel");
151         isRequestOverSecureChannel = true;
152     }
153
154     //Check the URI has the query and skip it before checking the permission
155     char *uri = strstr(requestInfo->info.resourceUri, "?");
156     int position = 0;
157     if (uri)
158     {
159         //Skip query and pass the resource uri
160         position = uri - requestInfo->info.resourceUri;
161     }
162     else
163     {
164         position = strlen(requestInfo->info.resourceUri);
165     }
166     if (MAX_URI_LENGTH < position  || 0 > position)
167     {
168         OIC_LOG(ERROR, TAG, "Incorrect URI length");
169         return;
170     }
171     SRMAccessResponse_t response = ACCESS_DENIED;
172     char newUri[MAX_URI_LENGTH + 1];
173     OICStrcpyPartial(newUri, MAX_URI_LENGTH + 1, requestInfo->info.resourceUri, position);
174
175     SetResourceRequestType(&g_policyEngineContext, newUri);
176
177      // Form a 'Error', 'slow response' or 'access deny' response and send to peer
178     CAResponseInfo_t responseInfo = {.result = CA_EMPTY};
179     memcpy(&responseInfo.info, &(requestInfo->info), sizeof(responseInfo.info));
180     responseInfo.info.payload = NULL;
181     responseInfo.info.dataType = CA_RESPONSE_DATA;
182
183     OCResource *resPtr = FindResourceByUri(newUri);
184     if (NULL != resPtr)
185     {
186         // check whether request is for secure resource or not and it should not be a SVR resource
187         if (((resPtr->resourceProperties) & OC_SECURE)
188                             && (g_policyEngineContext.resourceType == NOT_A_SVR_RESOURCE))
189         {
190            // if resource is secure and request is over insecure channel
191             if (!isRequestOverSecureChannel)
192             {
193                 // Reject all the requests over coap for secure resource.
194                 responseInfo.result = CA_FORBIDDEN_REQ;
195                 if (CA_STATUS_OK != CASendResponse(endPoint, &responseInfo))
196                 {
197                     OIC_LOG(ERROR, TAG, "Failed in sending response to a unauthorized request!");
198                 }
199                 return;
200             }
201         }
202     }
203 #ifdef _ENABLE_MULTIPLE_OWNER_
204     /*
205      * In case of ACL and CRED, The payload required to verify the payload.
206      * Payload information will be used for subowner's permission verification.
207      */
208     g_policyEngineContext.payload = (uint8_t*)requestInfo->info.payload;
209     g_policyEngineContext.payloadSize = requestInfo->info.payloadSize;
210 #endif //_ENABLE_MULTIPLE_OWNER_
211
212     //New request are only processed if the policy engine state is AWAITING_REQUEST.
213     if (AWAITING_REQUEST == g_policyEngineContext.state)
214     {
215         OIC_LOG_V(DEBUG, TAG, "Processing request with uri, %s for method, %d",
216                 requestInfo->info.resourceUri, requestInfo->method);
217         response = CheckPermission(&g_policyEngineContext, &subjectId, newUri,
218                 GetPermissionFromCAMethod_t(requestInfo->method));
219     }
220     else
221     {
222         OIC_LOG_V(INFO, TAG, "PE state %d. Ignoring request with uri, %s for method, %d",
223                 g_policyEngineContext.state, requestInfo->info.resourceUri, requestInfo->method);
224     }
225
226     if (IsAccessGranted(response) && gRequestHandler)
227     {
228         gRequestHandler(endPoint, requestInfo);
229         return;
230     }
231
232     VERIFY_NON_NULL(TAG, gRequestHandler, ERROR);
233
234     if (ACCESS_WAITING_FOR_AMS == response)
235     {
236         OIC_LOG(INFO, TAG, "Sending slow response");
237
238         UpdateAmsMgrContext(&g_policyEngineContext, endPoint, requestInfo);
239         responseInfo.result = CA_EMPTY;
240         responseInfo.info.type = CA_MSG_ACKNOWLEDGE;
241     }
242     else
243     {
244         /*
245          * TODO Enhance this logic more to decide between
246          * CA_UNAUTHORIZED_REQ or CA_FORBIDDEN_REQ depending
247          * upon SRMAccessResponseReasonCode_t
248          */
249         OIC_LOG(INFO, TAG, "Sending for regular response");
250         responseInfo.result = CA_UNAUTHORIZED_REQ;
251     }
252
253     if (CA_STATUS_OK != CASendResponse(endPoint, &responseInfo))
254     {
255         OIC_LOG(ERROR, TAG, "Failed in sending response to a unauthorized request!");
256     }
257     return;
258 exit:
259     responseInfo.result = CA_INTERNAL_SERVER_ERROR;
260     if (CA_STATUS_OK != CASendResponse(endPoint, &responseInfo))
261     {
262         OIC_LOG(ERROR, TAG, "Failed in sending response to a unauthorized request!");
263     }
264 }
265
266 /**
267  * Handle the response from the SRM.
268  *
269  * @param endPoint points to the remote endpoint.
270  * @param responseInfo contains response information from the endpoint.
271  */
272 void SRMResponseHandler(const CAEndpoint_t *endPoint, const CAResponseInfo_t *responseInfo)
273 {
274     OIC_LOG(DEBUG, TAG, "Received response from remote device");
275
276     // isProvResponse flag is to check whether response is catered by provisioning APIs or not.
277     // When token sent by CA response matches with token generated by provisioning request,
278     // gSPResponseHandler returns true and response is not sent to RI layer. In case
279     // gSPResponseHandler is null and isProvResponse is false response then the response is for
280     // RI layer.
281     bool isProvResponse = false;
282
283     if (gSPResponseHandler)
284     {
285         isProvResponse = gSPResponseHandler(endPoint, responseInfo);
286     }
287     if (!isProvResponse && gResponseHandler)
288     {
289         gResponseHandler(endPoint, responseInfo);
290     }
291 }
292
293 /**
294  * Handle the error from the SRM.
295  *
296  * @param endPoint is the remote endpoint.
297  * @param errorInfo contains error information from the endpoint.
298  */
299 void SRMErrorHandler(const CAEndpoint_t *endPoint, const CAErrorInfo_t *errorInfo)
300 {
301     OIC_LOG_V(INFO, TAG, "Received error from remote device with result, %d for request uri, %s",
302             errorInfo->result, errorInfo->info.resourceUri);
303     if (gErrorHandler)
304     {
305         gErrorHandler(endPoint, errorInfo);
306     }
307 }
308
309 OCStackResult SRMRegisterHandler(CARequestCallback reqHandler,
310                                  CAResponseCallback respHandler,
311                                  CAErrorCallback errHandler)
312 {
313     OIC_LOG(DEBUG, TAG, "SRMRegisterHandler !!");
314     if( !reqHandler || !respHandler || !errHandler)
315     {
316         OIC_LOG(ERROR, TAG, "Callback handlers are invalid");
317         return OC_STACK_INVALID_PARAM;
318     }
319     gRequestHandler = reqHandler;
320     gResponseHandler = respHandler;
321     gErrorHandler = errHandler;
322
323
324 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
325     CARegisterHandler(SRMRequestHandler, SRMResponseHandler, SRMErrorHandler);
326 #else
327     CARegisterHandler(reqHandler, respHandler, errHandler);
328 #endif /* __WITH_DTLS__ */
329     return OC_STACK_OK;
330 }
331
332 OCStackResult SRMRegisterPersistentStorageHandler(OCPersistentStorage* persistentStorageHandler)
333 {
334     OIC_LOG(DEBUG, TAG, "SRMRegisterPersistentStorageHandler !!");
335     if(!persistentStorageHandler)
336     {
337         OIC_LOG(ERROR, TAG, "The persistent storage handler is invalid");
338         return OC_STACK_INVALID_PARAM;
339     }
340     gPersistentStorageHandler = persistentStorageHandler;
341     return OC_STACK_OK;
342 }
343
344 OCPersistentStorage* SRMGetPersistentStorageHandler()
345 {
346     return gPersistentStorageHandler;
347 }
348
349 OCStackResult SRMInitSecureResources()
350 {
351     // TODO: temporarily returning OC_STACK_OK every time until default
352     // behavior (for when SVR DB is missing) is settled.
353     InitSecureResources();
354     OCStackResult ret = OC_STACK_OK;
355 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
356     if (CA_STATUS_OK != CAregisterPskCredentialsHandler(GetDtlsPskCredentials))
357     {
358         OIC_LOG(ERROR, TAG, "Failed to revert TLS credential handler.");
359         ret = OC_STACK_ERROR;
360     }
361     CAregisterPkixInfoHandler(GetPkixInfo);
362     CAregisterGetCredentialTypesHandler(InitCipherSuiteList);
363 #endif // __WITH_DTLS__ or __WITH_TLS__
364     return ret;
365 }
366
367 void SRMDeInitSecureResources()
368 {
369     DestroySecureResources();
370 }
371
372 OCStackResult SRMInitPolicyEngine()
373 {
374     return InitPolicyEngine(&g_policyEngineContext);
375 }
376
377 void SRMDeInitPolicyEngine()
378 {
379     DeInitPolicyEngine(&g_policyEngineContext);
380 }
381
382 bool SRMIsSecurityResourceURI(const char* uri)
383 {
384     if (!uri)
385     {
386         return false;
387     }
388
389     const char *rsrcs[] = {
390         OIC_RSRC_SVC_URI,
391         OIC_RSRC_AMACL_URI,
392         OIC_RSRC_CRL_URI,
393         OIC_RSRC_CRED_URI,
394         OIC_RSRC_ACL_URI,
395         OIC_RSRC_DOXM_URI,
396         OIC_RSRC_PSTAT_URI,
397         OIC_RSRC_PCONF_URI,
398         OIC_RSRC_DPAIRING_URI,
399         OIC_RSRC_VER_URI,
400         OC_RSRVD_PROV_CRL_URL
401     };
402
403     // Remove query from Uri for resource string comparison
404     size_t uriLen = strlen(uri);
405     char *query = strchr (uri, '?');
406     if (query)
407     {
408         uriLen = query - uri;
409     }
410
411     for (size_t i = 0; i < sizeof(rsrcs)/sizeof(rsrcs[0]); i++)
412     {
413         size_t svrLen = strlen(rsrcs[i]);
414
415         if ((uriLen == svrLen) &&
416             (strncmp(uri, rsrcs[i], svrLen) == 0))
417         {
418             return true;
419         }
420     }
421
422     return false;
423 }
424
425 /**
426  * Get the Secure Virtual Resource (SVR) type from the URI.
427  * @param   uri [IN] Pointer to URI in question.
428  * @return  The OicSecSvrType_t of the URI passed (note: if not a Secure Virtual
429             Resource, e.g. /a/light, will return "NOT_A_SVR_TYPE" enum value)
430  */
431 static const char URI_QUERY_CHAR = '?';
432 OicSecSvrType_t GetSvrTypeFromUri(const char* uri)
433 {
434     if (!uri)
435     {
436         return NOT_A_SVR_RESOURCE;
437     }
438
439     // Remove query from Uri for resource string comparison
440     size_t uriLen = strlen(uri);
441     char *query = strchr (uri, URI_QUERY_CHAR);
442     if (query)
443     {
444         uriLen = query - uri;
445     }
446
447     size_t svrLen = 0;
448
449     svrLen = strlen(OIC_RSRC_ACL_URI);
450     if(uriLen == svrLen)
451     {
452         if(0 == strncmp(uri, OIC_RSRC_ACL_URI, svrLen))
453         {
454             return OIC_R_ACL_TYPE;
455         }
456     }
457
458     svrLen = strlen(OIC_RSRC_AMACL_URI);
459     if(uriLen == svrLen)
460     {
461         if(0 == strncmp(uri, OIC_RSRC_AMACL_URI, svrLen))
462         {
463             return OIC_R_AMACL_TYPE;
464         }
465     }
466
467     svrLen = strlen(OIC_RSRC_CRED_URI);
468     if(uriLen == svrLen)
469     {
470         if(0 == strncmp(uri, OIC_RSRC_CRED_URI, svrLen))
471         {
472             return OIC_R_CRED_TYPE;
473         }
474     }
475
476     svrLen = strlen(OIC_RSRC_CRL_URI);
477     if(uriLen == svrLen)
478     {
479         if(0 == strncmp(uri, OIC_RSRC_CRL_URI, svrLen))
480         {
481             return OIC_R_CRL_TYPE;
482         }
483     }
484
485     svrLen = strlen(OIC_RSRC_DOXM_URI);
486     if(uriLen == svrLen)
487     {
488         if(0 == strncmp(uri, OIC_RSRC_DOXM_URI, svrLen))
489         {
490             return OIC_R_DOXM_TYPE;
491         }
492     }
493
494     svrLen = strlen(OIC_RSRC_DPAIRING_URI);
495     if(uriLen == svrLen)
496     {
497         if(0 == strncmp(uri, OIC_RSRC_DPAIRING_URI, svrLen))
498         {
499             return OIC_R_DPAIRING_TYPE;
500         }
501     }
502
503     svrLen = strlen(OIC_RSRC_PCONF_URI);
504     if(uriLen == svrLen)
505     {
506         if(0 == strncmp(uri, OIC_RSRC_PCONF_URI, svrLen))
507         {
508             return OIC_R_PCONF_TYPE;
509         }
510     }
511
512     svrLen = strlen(OIC_RSRC_PSTAT_URI);
513     if(uriLen == svrLen)
514     {
515         if(0 == strncmp(uri, OIC_RSRC_PSTAT_URI, svrLen))
516         {
517             return OIC_R_PSTAT_TYPE;
518         }
519     }
520
521     svrLen = strlen(OIC_RSRC_SVC_URI);
522     if(uriLen == svrLen)
523     {
524         if(0 == strncmp(uri, OIC_RSRC_SVC_URI, svrLen))
525         {
526             return OIC_R_SVC_TYPE;
527         }
528     }
529
530     svrLen = strlen(OIC_RSRC_SACL_URI);
531     if(uriLen == svrLen)
532     {
533         if(0 == strncmp(uri, OIC_RSRC_SACL_URI, svrLen))
534         {
535             return OIC_R_SACL_TYPE;
536         }
537     }
538
539     return NOT_A_SVR_RESOURCE;
540 }