Multiple Ownership Transfer support.
[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  "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     OicUuid_t nullSubjectId = {.id = {0}};
148     memcpy(subjectId.id, requestInfo->info.identity.id, sizeof(subjectId.id));
149
150     // if subject id is null that means request is sent thru coap.
151     if (memcmp(subjectId.id, nullSubjectId.id, sizeof(subjectId.id)) != 0)
152     {
153         OIC_LOG(INFO, TAG, "request over secure channel");
154         isRequestOverSecureChannel = true;
155     }
156
157     //Check the URI has the query and skip it before checking the permission
158     char *uri = strstr(requestInfo->info.resourceUri, "?");
159     int position = 0;
160     if (uri)
161     {
162         //Skip query and pass the resource uri
163         position = uri - requestInfo->info.resourceUri;
164     }
165     else
166     {
167         position = strlen(requestInfo->info.resourceUri);
168     }
169     if (MAX_URI_LENGTH < position  || 0 > position)
170     {
171         OIC_LOG(ERROR, TAG, "Incorrect URI length");
172         return;
173     }
174     SRMAccessResponse_t response = ACCESS_DENIED;
175     char newUri[MAX_URI_LENGTH + 1];
176     OICStrcpyPartial(newUri, MAX_URI_LENGTH + 1, requestInfo->info.resourceUri, position);
177
178     SetResourceRequestType(&g_policyEngineContext, newUri);
179
180      // Form a 'Error', 'slow response' or 'access deny' response and send to peer
181     CAResponseInfo_t responseInfo = {.result = CA_EMPTY};
182     memcpy(&responseInfo.info, &(requestInfo->info), sizeof(responseInfo.info));
183     responseInfo.info.payload = NULL;
184     responseInfo.info.dataType = CA_RESPONSE_DATA;
185
186     OCResource *resPtr = FindResourceByUri(newUri);
187     if (NULL != resPtr)
188     {
189         // check whether request is for secure resource or not and it should not be a SVR resource
190         if (((resPtr->resourceProperties) & OC_SECURE)
191                             && (g_policyEngineContext.resourceType == NOT_A_SVR_RESOURCE))
192         {
193            // if resource is secure and request is over insecure channel
194             if (!isRequestOverSecureChannel)
195             {
196                 // Reject all the requests over coap for secure resource.
197                 responseInfo.result = CA_FORBIDDEN_REQ;
198                 if (CA_STATUS_OK != CASendResponse(endPoint, &responseInfo))
199                 {
200                     OIC_LOG(ERROR, TAG, "Failed in sending response to a unauthorized request!");
201                 }
202                 return;
203             }
204         }
205     }
206 #ifdef _ENABLE_MULTIPLE_OWNER_
207     /*
208      * In case of ACL and CRED, The payload required to verify the payload.
209      * Payload information will be used for subowner's permission verification.
210      */
211     g_policyEngineContext.payload = (uint8_t*)requestInfo->info.payload;
212     g_policyEngineContext.payloadSize = requestInfo->info.payloadSize;
213 #endif //_ENABLE_MULTIPLE_OWNER_
214
215     //New request are only processed if the policy engine state is AWAITING_REQUEST.
216     if (AWAITING_REQUEST == g_policyEngineContext.state)
217     {
218         OIC_LOG_V(DEBUG, TAG, "Processing request with uri, %s for method, %d",
219                 requestInfo->info.resourceUri, requestInfo->method);
220         response = CheckPermission(&g_policyEngineContext, &subjectId, newUri,
221                 GetPermissionFromCAMethod_t(requestInfo->method));
222     }
223     else
224     {
225         OIC_LOG_V(INFO, TAG, "PE state %d. Ignoring request with uri, %s for method, %d",
226                 g_policyEngineContext.state, requestInfo->info.resourceUri, requestInfo->method);
227     }
228
229     if (IsAccessGranted(response) && gRequestHandler)
230     {
231         gRequestHandler(endPoint, requestInfo);
232         return;
233     }
234
235     VERIFY_NON_NULL(TAG, gRequestHandler, ERROR);
236
237     if (ACCESS_WAITING_FOR_AMS == response)
238     {
239         OIC_LOG(INFO, TAG, "Sending slow response");
240
241         UpdateAmsMgrContext(&g_policyEngineContext, endPoint, requestInfo);
242         responseInfo.result = CA_EMPTY;
243         responseInfo.info.type = CA_MSG_ACKNOWLEDGE;
244     }
245     else
246     {
247         /*
248          * TODO Enhance this logic more to decide between
249          * CA_UNAUTHORIZED_REQ or CA_FORBIDDEN_REQ depending
250          * upon SRMAccessResponseReasonCode_t
251          */
252         OIC_LOG(INFO, TAG, "Sending for regular response");
253         responseInfo.result = CA_UNAUTHORIZED_REQ;
254     }
255
256     if (CA_STATUS_OK != CASendResponse(endPoint, &responseInfo))
257     {
258         OIC_LOG(ERROR, TAG, "Failed in sending response to a unauthorized request!");
259     }
260     return;
261 exit:
262     responseInfo.result = CA_INTERNAL_SERVER_ERROR;
263     if (CA_STATUS_OK != CASendResponse(endPoint, &responseInfo))
264     {
265         OIC_LOG(ERROR, TAG, "Failed in sending response to a unauthorized request!");
266     }
267 }
268
269 /**
270  * Handle the response from the SRM.
271  *
272  * @param endPoint points to the remote endpoint.
273  * @param responseInfo contains response information from the endpoint.
274  */
275 void SRMResponseHandler(const CAEndpoint_t *endPoint, const CAResponseInfo_t *responseInfo)
276 {
277     OIC_LOG(DEBUG, TAG, "Received response from remote device");
278
279     // isProvResponse flag is to check whether response is catered by provisioning APIs or not.
280     // When token sent by CA response matches with token generated by provisioning request,
281     // gSPResponseHandler returns true and response is not sent to RI layer. In case
282     // gSPResponseHandler is null and isProvResponse is false response then the response is for
283     // RI layer.
284     bool isProvResponse = false;
285
286     if (gSPResponseHandler)
287     {
288         isProvResponse = gSPResponseHandler(endPoint, responseInfo);
289     }
290     if (!isProvResponse && gResponseHandler)
291     {
292         gResponseHandler(endPoint, responseInfo);
293     }
294 }
295
296 /**
297  * Handle the error from the SRM.
298  *
299  * @param endPoint is the remote endpoint.
300  * @param errorInfo contains error information from the endpoint.
301  */
302 void SRMErrorHandler(const CAEndpoint_t *endPoint, const CAErrorInfo_t *errorInfo)
303 {
304     OIC_LOG_V(INFO, TAG, "Received error from remote device with result, %d for request uri, %s",
305             errorInfo->result, errorInfo->info.resourceUri);
306     if (gErrorHandler)
307     {
308         gErrorHandler(endPoint, errorInfo);
309     }
310 }
311
312 OCStackResult SRMRegisterHandler(CARequestCallback reqHandler,
313                                  CAResponseCallback respHandler,
314                                  CAErrorCallback errHandler)
315 {
316     OIC_LOG(DEBUG, TAG, "SRMRegisterHandler !!");
317     if( !reqHandler || !respHandler || !errHandler)
318     {
319         OIC_LOG(ERROR, TAG, "Callback handlers are invalid");
320         return OC_STACK_INVALID_PARAM;
321     }
322     gRequestHandler = reqHandler;
323     gResponseHandler = respHandler;
324     gErrorHandler = errHandler;
325
326
327 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
328     CARegisterHandler(SRMRequestHandler, SRMResponseHandler, SRMErrorHandler);
329 #else
330     CARegisterHandler(reqHandler, respHandler, errHandler);
331 #endif /* __WITH_DTLS__ */
332     return OC_STACK_OK;
333 }
334
335 OCStackResult SRMRegisterPersistentStorageHandler(OCPersistentStorage* persistentStorageHandler)
336 {
337     OIC_LOG(DEBUG, TAG, "SRMRegisterPersistentStorageHandler !!");
338     if(!persistentStorageHandler)
339     {
340         OIC_LOG(ERROR, TAG, "The persistent storage handler is invalid");
341         return OC_STACK_INVALID_PARAM;
342     }
343     gPersistentStorageHandler = persistentStorageHandler;
344     return OC_STACK_OK;
345 }
346
347 OCPersistentStorage* SRMGetPersistentStorageHandler()
348 {
349     return gPersistentStorageHandler;
350 }
351
352 OCStackResult SRMInitSecureResources()
353 {
354     // TODO: temporarily returning OC_STACK_OK every time until default
355     // behavior (for when SVR DB is missing) is settled.
356     InitSecureResources();
357     OCStackResult ret = OC_STACK_OK;
358 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
359     if (CA_STATUS_OK != CAregisterPskCredentialsHandler(GetDtlsPskCredentials))
360     {
361         OIC_LOG(ERROR, TAG, "Failed to revert TLS credential handler.");
362         ret = OC_STACK_ERROR;
363     }
364     CAregisterPkixInfoHandler(GetPkixInfo);
365     CAregisterGetCredentialTypesHandler(InitCipherSuiteList);
366 #endif // __WITH_DTLS__ or __WITH_TLS__
367     return ret;
368 }
369
370 void SRMDeInitSecureResources()
371 {
372     DestroySecureResources();
373 }
374
375 OCStackResult SRMInitPolicyEngine()
376 {
377     return InitPolicyEngine(&g_policyEngineContext);
378 }
379
380 void SRMDeInitPolicyEngine()
381 {
382     DeInitPolicyEngine(&g_policyEngineContext);
383 }
384
385 bool SRMIsSecurityResourceURI(const char* uri)
386 {
387     if (!uri)
388     {
389         return false;
390     }
391
392     const char *rsrcs[] = {
393         OIC_RSRC_SVC_URI,
394         OIC_RSRC_AMACL_URI,
395         OIC_RSRC_CRL_URI,
396         OIC_RSRC_CRED_URI,
397         OIC_RSRC_ACL_URI,
398         OIC_RSRC_DOXM_URI,
399         OIC_RSRC_PSTAT_URI,
400         OIC_RSRC_PCONF_URI,
401         OIC_RSRC_DPAIRING_URI,
402         OIC_RSRC_VER_URI,
403         OC_RSRVD_PROV_CRL_URL
404     };
405
406     // Remove query from Uri for resource string comparison
407     size_t uriLen = strlen(uri);
408     char *query = strchr (uri, '?');
409     if (query)
410     {
411         uriLen = query - uri;
412     }
413
414     for (size_t i = 0; i < sizeof(rsrcs)/sizeof(rsrcs[0]); i++)
415     {
416         size_t svrLen = strlen(rsrcs[i]);
417
418         if ((uriLen == svrLen) &&
419             (strncmp(uri, rsrcs[i], svrLen) == 0))
420         {
421             return true;
422         }
423     }
424
425     return false;
426 }
427
428 /**
429  * Get the Secure Virtual Resource (SVR) type from the URI.
430  * @param   uri [IN] Pointer to URI in question.
431  * @return  The OicSecSvrType_t of the URI passed (note: if not a Secure Virtual
432             Resource, e.g. /a/light, will return "NOT_A_SVR_TYPE" enum value)
433  */
434 static const char URI_QUERY_CHAR = '?';
435 OicSecSvrType_t GetSvrTypeFromUri(const char* uri)
436 {
437     if (!uri)
438     {
439         return NOT_A_SVR_RESOURCE;
440     }
441
442     // Remove query from Uri for resource string comparison
443     size_t uriLen = strlen(uri);
444     char *query = strchr (uri, URI_QUERY_CHAR);
445     if (query)
446     {
447         uriLen = query - uri;
448     }
449
450     size_t svrLen = 0;
451
452     svrLen = strlen(OIC_RSRC_ACL_URI);
453     if(uriLen == svrLen)
454     {
455         if(0 == strncmp(uri, OIC_RSRC_ACL_URI, svrLen))
456         {
457             return OIC_R_ACL_TYPE;
458         }
459     }
460
461     svrLen = strlen(OIC_RSRC_AMACL_URI);
462     if(uriLen == svrLen)
463     {
464         if(0 == strncmp(uri, OIC_RSRC_AMACL_URI, svrLen))
465         {
466             return OIC_R_AMACL_TYPE;
467         }
468     }
469
470     svrLen = strlen(OIC_RSRC_CRED_URI);
471     if(uriLen == svrLen)
472     {
473         if(0 == strncmp(uri, OIC_RSRC_CRED_URI, svrLen))
474         {
475             return OIC_R_CRED_TYPE;
476         }
477     }
478
479     svrLen = strlen(OIC_RSRC_CRL_URI);
480     if(uriLen == svrLen)
481     {
482         if(0 == strncmp(uri, OIC_RSRC_CRL_URI, svrLen))
483         {
484             return OIC_R_CRL_TYPE;
485         }
486     }
487
488     svrLen = strlen(OIC_RSRC_DOXM_URI);
489     if(uriLen == svrLen)
490     {
491         if(0 == strncmp(uri, OIC_RSRC_DOXM_URI, svrLen))
492         {
493             return OIC_R_DOXM_TYPE;
494         }
495     }
496
497     svrLen = strlen(OIC_RSRC_DPAIRING_URI);
498     if(uriLen == svrLen)
499     {
500         if(0 == strncmp(uri, OIC_RSRC_DPAIRING_URI, svrLen))
501         {
502             return OIC_R_DPAIRING_TYPE;
503         }
504     }
505
506     svrLen = strlen(OIC_RSRC_PCONF_URI);
507     if(uriLen == svrLen)
508     {
509         if(0 == strncmp(uri, OIC_RSRC_PCONF_URI, svrLen))
510         {
511             return OIC_R_PCONF_TYPE;
512         }
513     }
514
515     svrLen = strlen(OIC_RSRC_PSTAT_URI);
516     if(uriLen == svrLen)
517     {
518         if(0 == strncmp(uri, OIC_RSRC_PSTAT_URI, svrLen))
519         {
520             return OIC_R_PSTAT_TYPE;
521         }
522     }
523
524     svrLen = strlen(OIC_RSRC_SVC_URI);
525     if(uriLen == svrLen)
526     {
527         if(0 == strncmp(uri, OIC_RSRC_SVC_URI, svrLen))
528         {
529             return OIC_R_SVC_TYPE;
530         }
531     }
532
533     svrLen = strlen(OIC_RSRC_SACL_URI);
534     if(uriLen == svrLen)
535     {
536         if(0 == strncmp(uri, OIC_RSRC_SACL_URI, svrLen))
537         {
538             return OIC_R_SACL_TYPE;
539         }
540     }
541
542     return NOT_A_SVR_RESOURCE;
543 }