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