Merge branch 'security-summit' into 'master'
[platform/upstream/iotivity.git] / resource / csdk / security / src / secureresourcemanager.c
index ab56071..13ff964 100644 (file)
 //
 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 
+#include <string.h>
 #include "ocstack.h"
 #include "logger.h"
 #include "cainterface.h"
-#include "secureresourcemanager.h"
 #include "resourcemanager.h"
 #include "credresource.h"
 #include "policyengine.h"
+#include "srmutility.h"
+#include "amsmgr.h"
 #include "oic_string.h"
-#include <string.h>
+#include "oic_malloc.h"
+#include "securevirtualresourcetypes.h"
+#include "secureresourcemanager.h"
+#include "srmresourcestrings.h"
 
-#define TAG  PCF("SRM")
+#define TAG  "SRM"
+
+#ifdef __WITH_X509__
+#include "crlresource.h"
+#endif // __WITH_X509__
 
 //Request Callback handler
 static CARequestCallback gRequestHandler = NULL;
@@ -55,6 +64,55 @@ void SRMRegisterProvisioningResponseHandler(SPResponseCallback respHandler)
 {
     gSPResponseHandler = respHandler;
 }
+
+
+static void SRMSendUnAuthorizedAccessresponse(PEContext_t *context)
+{
+    CAResponseInfo_t responseInfo = {.result = CA_EMPTY};
+    memcpy(&responseInfo.info, &(context->amsMgrContext->requestInfo->info),
+            sizeof(responseInfo.info));
+    responseInfo.info.payload = NULL;
+    responseInfo.result = CA_UNAUTHORIZED_REQ;
+    if (CA_STATUS_OK != CASendResponse(context->amsMgrContext->endpoint, &responseInfo))
+    {
+        OC_LOG(ERROR, TAG, "Failed in sending response to a unauthorized request!");
+    }
+    else
+    {
+        OC_LOG(INFO, TAG, "Succeed in sending response to a unauthorized request!");
+    }
+}
+
+
+void SRMSendResponse(SRMAccessResponse_t responseVal)
+{
+    OC_LOG(INFO, TAG, "Sending response to remote device");
+
+    if (IsAccessGranted(responseVal) && gRequestHandler)
+    {
+        OC_LOG_V(INFO, TAG, "%s : Access granted. Passing Request to RI layer", __func__);
+        if (!g_policyEngineContext.amsMgrContext->endpoint ||
+                !g_policyEngineContext.amsMgrContext->requestInfo)
+        {
+            OC_LOG_V(ERROR, TAG, "%s : Invalid arguments", __func__);
+            SRMSendUnAuthorizedAccessresponse(&g_policyEngineContext);
+            goto exit;
+        }
+        gRequestHandler(g_policyEngineContext.amsMgrContext->endpoint,
+                g_policyEngineContext.amsMgrContext->requestInfo);
+    }
+    else
+    {
+        OC_LOG_V(INFO, TAG, "%s : ACCESS_DENIED.", __func__);
+        SRMSendUnAuthorizedAccessresponse(&g_policyEngineContext);
+    }
+
+exit:
+    //Resting PE state to AWAITING_REQUEST
+    SetPolicyEngineState(&g_policyEngineContext, AWAITING_REQUEST);
+}
+
+
 /**
  * @brief   Handle the request from the SRM.
  * @param   endPoint       [IN] Endpoint object from which the response is received.
@@ -63,11 +121,11 @@ void SRMRegisterProvisioningResponseHandler(SPResponseCallback respHandler)
  */
 void SRMRequestHandler(const CAEndpoint_t *endPoint, const CARequestInfo_t *requestInfo)
 {
-    OC_LOG(INFO, TAG, PCF("Received request from remote device"));
+    OC_LOG(INFO, TAG, "Received request from remote device");
 
     if (!endPoint || !requestInfo)
     {
-        OC_LOG(ERROR, TAG, PCF("Invalid arguments"));
+        OC_LOG(ERROR, TAG, "Invalid arguments");
         return;
     }
 
@@ -80,42 +138,55 @@ void SRMRequestHandler(const CAEndpoint_t *endPoint, const CARequestInfo_t *requ
     int position = 0;
     if (uri)
     {
+        //Skip query and pass the resource uri
         position = uri - requestInfo->info.resourceUri;
     }
-    if (position > MAX_URI_LENGTH)
+    else
+    {
+        position = strlen(requestInfo->info.resourceUri);
+    }
+    if (MAX_URI_LENGTH < position  || 0 > position)
     {
-        OC_LOG(ERROR, TAG, PCF("URI length is too long"));
+        OC_LOG(ERROR, TAG, "Incorrect URI length");
         return;
     }
     SRMAccessResponse_t response = ACCESS_DENIED;
-    if (position > 0)
+    char newUri[MAX_URI_LENGTH + 1];
+    OICStrcpyPartial(newUri, MAX_URI_LENGTH + 1, requestInfo->info.resourceUri, position);
+
+    //New request are only processed if the policy engine state is AWAITING_REQUEST.
+    if(AWAITING_REQUEST == g_policyEngineContext.state)
     {
-        char newUri[MAX_URI_LENGTH + 1];
-        OICStrcpyPartial(newUri, MAX_URI_LENGTH + 1, requestInfo->info.resourceUri, position);
-        //Skip query and pass the newUri.
-        response = CheckPermission(&g_policyEngineContext, &subjectId,
-                              newUri,
-                              GetPermissionFromCAMethod_t(requestInfo->method));
+        OC_LOG_V(INFO, TAG, "Processing request with uri, %s for method, %d",
+                requestInfo->info.resourceUri, requestInfo->method);
+        response = CheckPermission(&g_policyEngineContext, &subjectId, newUri,
+                GetPermissionFromCAMethod_t(requestInfo->method));
     }
     else
     {
-        //Pass resourceUri if there is no query info.
-        response = CheckPermission(&g_policyEngineContext, &subjectId,
-                              requestInfo->info.resourceUri,
-                              GetPermissionFromCAMethod_t(requestInfo->method));
+        OC_LOG_V(INFO, TAG, "PE state %d. Ignoring request with uri, %s for method, %d",
+                g_policyEngineContext.state, requestInfo->info.resourceUri, requestInfo->method);
     }
+
     if (IsAccessGranted(response) && gRequestHandler)
     {
         return (gRequestHandler(endPoint, requestInfo));
     }
 
-    // Form a 'access deny' or 'Error' response and send to peer
+    // Form a 'Error', 'slow response' or 'access deny' response and send to peer
     CAResponseInfo_t responseInfo = {.result = CA_EMPTY};
     memcpy(&responseInfo.info, &(requestInfo->info), sizeof(responseInfo.info));
     responseInfo.info.payload = NULL;
-    if (!gRequestHandler)
+
+    VERIFY_NON_NULL(TAG, gRequestHandler, ERROR);
+
+    if(ACCESS_WAITING_FOR_AMS == response)
     {
-        responseInfo.result = CA_INTERNAL_SERVER_ERROR;
+        OC_LOG(INFO, TAG, "Sending slow response");
+
+        UpdateAmsMgrContext(&g_policyEngineContext, endPoint, requestInfo);
+        responseInfo.result = CA_EMPTY;
+        responseInfo.info.type = CA_MSG_ACKNOWLEDGE;
     }
     else
     {
@@ -124,12 +195,20 @@ void SRMRequestHandler(const CAEndpoint_t *endPoint, const CARequestInfo_t *requ
          * CA_UNAUTHORIZED_REQ or CA_FORBIDDEN_REQ depending
          * upon SRMAccessResponseReasonCode_t
          */
+        OC_LOG(INFO, TAG, "Sending for regular response");
         responseInfo.result = CA_UNAUTHORIZED_REQ;
     }
 
     if (CA_STATUS_OK != CASendResponse(endPoint, &responseInfo))
     {
-        OC_LOG(ERROR, TAG, PCF("Failed in sending response to a unauthorized request!"));
+        OC_LOG(ERROR, TAG, "Failed in sending response to a unauthorized request!");
+    }
+    return;
+exit:
+    responseInfo.result = CA_INTERNAL_SERVER_ERROR;
+    if (CA_STATUS_OK != CASendResponse(endPoint, &responseInfo))
+    {
+        OC_LOG(ERROR, TAG, "Failed in sending response to a unauthorized request!");
     }
 }
 
@@ -141,7 +220,7 @@ void SRMRequestHandler(const CAEndpoint_t *endPoint, const CARequestInfo_t *requ
  */
 void SRMResponseHandler(const CAEndpoint_t *endPoint, const CAResponseInfo_t *responseInfo)
 {
-    OC_LOG(INFO, TAG, PCF("Received response from remote device"));
+    OC_LOG(INFO, TAG, "Received response from remote device");
 
     // isProvResponse flag is to check whether response is catered by provisioning APIs or not.
     // When token sent by CA response matches with token generated by provisioning request,
@@ -169,7 +248,8 @@ void SRMResponseHandler(const CAEndpoint_t *endPoint, const CAResponseInfo_t *re
  */
 void SRMErrorHandler(const CAEndpoint_t *endPoint, const CAErrorInfo_t *errorInfo)
 {
-    OC_LOG(INFO, TAG, PCF("Received error from remote device"));
+    OC_LOG_V(INFO, TAG, "Received error from remote device with result, %d for request uri, %s",
+            errorInfo->result, errorInfo->info.resourceUri);
     if (gErrorHandler)
     {
         gErrorHandler(endPoint, errorInfo);
@@ -190,10 +270,10 @@ OCStackResult SRMRegisterHandler(CARequestCallback reqHandler,
                                  CAResponseCallback respHandler,
                                  CAErrorCallback errHandler)
 {
-    OC_LOG(INFO, TAG, PCF("SRMRegisterHandler !!"));
+    OC_LOG(INFO, TAG, "SRMRegisterHandler !!");
     if( !reqHandler || !respHandler || !errHandler)
     {
-        OC_LOG(ERROR, TAG, PCF("Callback handlers are invalid"));
+        OC_LOG(ERROR, TAG, "Callback handlers are invalid");
         return OC_STACK_INVALID_PARAM;
     }
     gRequestHandler = reqHandler;
@@ -218,10 +298,10 @@ OCStackResult SRMRegisterHandler(CARequestCallback reqHandler,
  */
 OCStackResult SRMRegisterPersistentStorageHandler(OCPersistentStorage* persistentStorageHandler)
 {
-    OC_LOG(INFO, TAG, PCF("SRMRegisterPersistentStorageHandler !!"));
+    OC_LOG(INFO, TAG, "SRMRegisterPersistentStorageHandler !!");
     if(!persistentStorageHandler)
     {
-        OC_LOG(ERROR, TAG, PCF("The persistent storage handler is invalid"));
+        OC_LOG(ERROR, TAG, "The persistent storage handler is invalid");
         return OC_STACK_INVALID_PARAM;
     }
     gPersistentStorageHandler = persistentStorageHandler;
@@ -253,6 +333,10 @@ OCStackResult SRMInitSecureResources()
 #if defined(__WITH_DTLS__)
     CARegisterDTLSCredentialsHandler(GetDtlsPskCredentials);
 #endif // (__WITH_DTLS__)
+#if defined(__WITH_X509__)
+    CARegisterDTLSX509CredentialsHandler(GetDtlsX509Credentials);
+    CARegisterDTLSCrlHandler(GetDerCrl);
+#endif // (__WITH_X509__)
 
     return OC_STACK_OK;
 }
@@ -283,3 +367,26 @@ void SRMDeInitPolicyEngine()
 {
     return DeInitPolicyEngine(&g_policyEngineContext);
 }
+
+/**
+ * @brief   Check the security resource URI.
+ * @param   uri [IN] Pointers to security resource URI.
+ * @return  true if the URI is one of security resources, otherwise false.
+ */
+bool SRMIsSecurityResourceURI(const char* uri)
+{
+    bool result = false;
+    if (!uri)
+    {
+        return result;
+    }
+
+    if (strcmp(uri, OIC_RSRC_AMACL_URI) == 0 || strcmp(uri, OIC_RSRC_ACL_URI) == 0
+            || strcmp(uri, OIC_RSRC_PSTAT_URI) == 0
+            || strncmp(OIC_RSRC_DOXM_URI, uri, sizeof(OIC_RSRC_DOXM_URI) - 1) == 0
+            || strcmp(uri, OIC_RSRC_CRED_URI) == 0 || strcmp(uri, OIC_RSRC_SVC_URI) == 0)
+    {
+        result = true;
+    }
+    return result;
+}