replaced OC_LOG with OIC_LOG in security
[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
36 #define TAG  "SRM"
37
38 #ifdef __WITH_X509__
39 #include "crlresource.h"
40 #endif // __WITH_X509__
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  * @brief 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
69 static void SRMSendUnAuthorizedAccessresponse(PEContext_t *context)
70 {
71     CAResponseInfo_t responseInfo = {.result = CA_EMPTY};
72
73     if(NULL == context ||
74        NULL == context->amsMgrContext->requestInfo)
75     {
76         OIC_LOG_V(ERROR, TAG, "%s : NULL Parameter(s)",__func__);
77         return;
78     }
79
80     memcpy(&responseInfo.info, &(context->amsMgrContext->requestInfo->info),
81             sizeof(responseInfo.info));
82     responseInfo.info.payload = NULL;
83     responseInfo.result = CA_UNAUTHORIZED_REQ;
84
85     if (CA_STATUS_OK == CASendResponse(context->amsMgrContext->endpoint, &responseInfo))
86     {
87         OIC_LOG(DEBUG, TAG, "Succeed in sending response to a unauthorized request!");
88     }
89     else
90     {
91         OIC_LOG(ERROR, TAG, "Failed in sending response to a unauthorized request!");
92     }
93 }
94
95
96 void SRMSendResponse(SRMAccessResponse_t responseVal)
97 {
98     OIC_LOG(DEBUG, TAG, "Sending response to remote device");
99
100     if (IsAccessGranted(responseVal) && gRequestHandler)
101     {
102         OIC_LOG_V(INFO, TAG, "%s : Access granted. Passing Request to RI layer", __func__);
103         if (!g_policyEngineContext.amsMgrContext->endpoint ||
104             !g_policyEngineContext.amsMgrContext->requestInfo)
105         {
106             OIC_LOG_V(ERROR, TAG, "%s : Invalid arguments", __func__);
107             SRMSendUnAuthorizedAccessresponse(&g_policyEngineContext);
108             goto exit;
109         }
110         gRequestHandler(g_policyEngineContext.amsMgrContext->endpoint,
111                 g_policyEngineContext.amsMgrContext->requestInfo);
112     }
113     else
114     {
115         OIC_LOG_V(INFO, TAG, "%s : ACCESS_DENIED.", __func__);
116         SRMSendUnAuthorizedAccessresponse(&g_policyEngineContext);
117     }
118
119 exit:
120     //Resetting PE state to AWAITING_REQUEST
121     SetPolicyEngineState(&g_policyEngineContext, AWAITING_REQUEST);
122 }
123
124
125 /**
126  * @brief   Handle the request from the SRM.
127  * @param   endPoint       [IN] Endpoint object from which the response is received.
128  * @param   requestInfo    [IN] Information for the request.
129  * @return  NONE
130  */
131 void SRMRequestHandler(const CAEndpoint_t *endPoint, const CARequestInfo_t *requestInfo)
132 {
133     OIC_LOG(DEBUG, TAG, "Received request from remote device");
134
135     if (!endPoint || !requestInfo)
136     {
137         OIC_LOG(ERROR, TAG, "Invalid arguments");
138         return;
139     }
140
141     // Copy the subjectID
142     OicUuid_t subjectId = {.id = {0}};
143     memcpy(subjectId.id, requestInfo->info.identity.id, sizeof(subjectId.id));
144
145     //Check the URI has the query and skip it before checking the permission
146     char *uri = strstr(requestInfo->info.resourceUri, "?");
147     int position = 0;
148     if (uri)
149     {
150         //Skip query and pass the resource uri
151         position = uri - requestInfo->info.resourceUri;
152     }
153     else
154     {
155         position = strlen(requestInfo->info.resourceUri);
156     }
157     if (MAX_URI_LENGTH < position  || 0 > position)
158     {
159         OIC_LOG(ERROR, TAG, "Incorrect URI length");
160         return;
161     }
162     SRMAccessResponse_t response = ACCESS_DENIED;
163     char newUri[MAX_URI_LENGTH + 1];
164     OICStrcpyPartial(newUri, MAX_URI_LENGTH + 1, requestInfo->info.resourceUri, position);
165
166     //New request are only processed if the policy engine state is AWAITING_REQUEST.
167     if(AWAITING_REQUEST == g_policyEngineContext.state)
168     {
169         OIC_LOG_V(DEBUG, TAG, "Processing request with uri, %s for method, %d",
170                 requestInfo->info.resourceUri, requestInfo->method);
171         response = CheckPermission(&g_policyEngineContext, &subjectId, newUri,
172                 GetPermissionFromCAMethod_t(requestInfo->method));
173     }
174     else
175     {
176         OIC_LOG_V(INFO, TAG, "PE state %d. Ignoring request with uri, %s for method, %d",
177                 g_policyEngineContext.state, requestInfo->info.resourceUri, requestInfo->method);
178     }
179
180     if (IsAccessGranted(response) && gRequestHandler)
181     {
182         return (gRequestHandler(endPoint, requestInfo));
183     }
184
185     // Form a 'Error', 'slow response' or 'access deny' response and send to peer
186     CAResponseInfo_t responseInfo = {.result = CA_EMPTY};
187     memcpy(&responseInfo.info, &(requestInfo->info), sizeof(responseInfo.info));
188     responseInfo.info.payload = NULL;
189
190     VERIFY_NON_NULL(TAG, gRequestHandler, ERROR);
191
192     if(ACCESS_WAITING_FOR_AMS == response)
193     {
194         OIC_LOG(INFO, TAG, "Sending slow response");
195
196         UpdateAmsMgrContext(&g_policyEngineContext, endPoint, requestInfo);
197         responseInfo.result = CA_EMPTY;
198         responseInfo.info.type = CA_MSG_ACKNOWLEDGE;
199     }
200     else
201     {
202         /*
203          * TODO Enhance this logic more to decide between
204          * CA_UNAUTHORIZED_REQ or CA_FORBIDDEN_REQ depending
205          * upon SRMAccessResponseReasonCode_t
206          */
207         OIC_LOG(INFO, TAG, "Sending for regular response");
208         responseInfo.result = CA_UNAUTHORIZED_REQ;
209     }
210
211     if (CA_STATUS_OK != CASendResponse(endPoint, &responseInfo))
212     {
213         OIC_LOG(ERROR, TAG, "Failed in sending response to a unauthorized request!");
214     }
215     return;
216 exit:
217     responseInfo.result = CA_INTERNAL_SERVER_ERROR;
218     if (CA_STATUS_OK != CASendResponse(endPoint, &responseInfo))
219     {
220         OIC_LOG(ERROR, TAG, "Failed in sending response to a unauthorized request!");
221     }
222 }
223
224 /**
225  * @brief   Handle the response from the SRM.
226  * @param   endPoint     [IN] The remote endpoint.
227  * @param   responseInfo [IN] Response information from the endpoint.
228  * @return  NONE
229  */
230 void SRMResponseHandler(const CAEndpoint_t *endPoint, const CAResponseInfo_t *responseInfo)
231 {
232     OIC_LOG(DEBUG, TAG, "Received response from remote device");
233
234     // isProvResponse flag is to check whether response is catered by provisioning APIs or not.
235     // When token sent by CA response matches with token generated by provisioning request,
236     // gSPResponseHandler returns true and response is not sent to RI layer. In case
237     // gSPResponseHandler is null and isProvResponse is false response then the response is for
238     // RI layer.
239     bool isProvResponse = false;
240
241     if (gSPResponseHandler)
242     {
243         isProvResponse = gSPResponseHandler(endPoint, responseInfo);
244     }
245     if (!isProvResponse && gResponseHandler)
246     {
247         gResponseHandler(endPoint, responseInfo);
248     }
249 }
250
251
252 /**
253  * @brief   Handle the error from the SRM.
254  * @param   endPoint  [IN] The remote endpoint.
255  * @param   errorInfo [IN] Error information from the endpoint.
256  * @return  NONE
257  */
258 void SRMErrorHandler(const CAEndpoint_t *endPoint, const CAErrorInfo_t *errorInfo)
259 {
260     OIC_LOG_V(INFO, TAG, "Received error from remote device with result, %d for request uri, %s",
261             errorInfo->result, errorInfo->info.resourceUri);
262     if (gErrorHandler)
263     {
264         gErrorHandler(endPoint, errorInfo);
265     }
266 }
267
268
269 /**
270  * @brief   Register request and response callbacks.
271  *          Requests and responses are delivered in these callbacks.
272  * @param   reqHandler   [IN] Request handler callback ( for GET,PUT ..etc)
273  * @param   respHandler  [IN] Response handler callback.
274  * @return
275  *     OC_STACK_OK    - No errors; Success
276  *     OC_STACK_INVALID_PARAM - invalid parameter
277  */
278 OCStackResult SRMRegisterHandler(CARequestCallback reqHandler,
279                                  CAResponseCallback respHandler,
280                                  CAErrorCallback errHandler)
281 {
282     OIC_LOG(DEBUG, TAG, "SRMRegisterHandler !!");
283     if( !reqHandler || !respHandler || !errHandler)
284     {
285         OIC_LOG(ERROR, TAG, "Callback handlers are invalid");
286         return OC_STACK_INVALID_PARAM;
287     }
288     gRequestHandler = reqHandler;
289     gResponseHandler = respHandler;
290     gErrorHandler = errHandler;
291
292
293 #if defined(__WITH_DTLS__)
294     CARegisterHandler(SRMRequestHandler, SRMResponseHandler, SRMErrorHandler);
295 #else
296     CARegisterHandler(reqHandler, respHandler, errHandler);
297 #endif /* __WITH_DTLS__ */
298     return OC_STACK_OK;
299 }
300
301 /**
302  * @brief   Register Persistent storage callback.
303  * @param   persistentStorageHandler [IN] Pointers to open, read, write, close & unlink handlers.
304  * @return
305  *     OC_STACK_OK    - No errors; Success
306  *     OC_STACK_INVALID_PARAM - Invalid parameter
307  */
308 OCStackResult SRMRegisterPersistentStorageHandler(OCPersistentStorage* persistentStorageHandler)
309 {
310     OIC_LOG(DEBUG, TAG, "SRMRegisterPersistentStorageHandler !!");
311     if(!persistentStorageHandler)
312     {
313         OIC_LOG(ERROR, TAG, "The persistent storage handler is invalid");
314         return OC_STACK_INVALID_PARAM;
315     }
316     gPersistentStorageHandler = persistentStorageHandler;
317     return OC_STACK_OK;
318 }
319
320 /**
321  * @brief   Get Persistent storage handler pointer.
322  * @return
323  *     The pointer to Persistent Storage callback handler
324  */
325
326 OCPersistentStorage* SRMGetPersistentStorageHandler()
327 {
328     return gPersistentStorageHandler;
329 }
330
331
332 /**
333  * @brief   Initialize all secure resources ( /oic/sec/cred, /oic/sec/acl, /oic/sec/pstat etc).
334  * @retval  OC_STACK_OK for Success, otherwise some error value
335  */
336 OCStackResult SRMInitSecureResources()
337 {
338     // TODO: temporarily returning OC_STACK_OK every time until default
339     // behavior (for when SVR DB is missing) is settled.
340     InitSecureResources();
341
342 #if defined(__WITH_DTLS__)
343     CARegisterDTLSCredentialsHandler(GetDtlsPskCredentials);
344 #endif // (__WITH_DTLS__)
345 #if defined(__WITH_X509__)
346     CARegisterDTLSX509CredentialsHandler(GetDtlsX509Credentials);
347     CARegisterDTLSCrlHandler(GetDerCrl);
348 #endif // (__WITH_X509__)
349
350     return OC_STACK_OK;
351 }
352
353 /**
354  * @brief   Perform cleanup for secure resources ( /oic/sec/cred, /oic/sec/acl, /oic/sec/pstat etc).
355  * @retval  none
356  */
357 void SRMDeInitSecureResources()
358 {
359     DestroySecureResources();
360 }
361
362 /**
363  * @brief   Initialize Policy Engine.
364  * @return  OC_STACK_OK for Success, otherwise some error value.
365  */
366 OCStackResult SRMInitPolicyEngine()
367 {
368     return InitPolicyEngine(&g_policyEngineContext);
369 }
370
371 /**
372  * @brief   Cleanup Policy Engine.
373  * @return  none
374  */
375 void SRMDeInitPolicyEngine()
376 {
377     return DeInitPolicyEngine(&g_policyEngineContext);
378 }
379
380 /**
381  * @brief   Check the security resource URI.
382  * @param   uri [IN] Pointers to security resource URI.
383  * @return  true if the URI is one of security resources, otherwise false.
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     };
401
402     // Remove query from Uri for resource string comparison
403     size_t uriLen = strlen(uri);
404     char *query = strchr (uri, '?');
405     if (query)
406     {
407         uriLen = query - uri;
408     }
409
410     for (size_t i = 0; i < sizeof(rsrcs)/sizeof(rsrcs[0]); i++)
411     {
412         size_t svrLen = strlen(rsrcs[i]);
413
414         if ((uriLen == svrLen) &&
415             (strncmp(uri, rsrcs[i], svrLen) == 0))
416         {
417             return true;
418         }
419     }
420
421     return false;
422 }