X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=resource%2Fcsdk%2Fsecurity%2Fsrc%2Fsecureresourcemanager.c;h=fc8bd3ddfe753af722dbbaa562fef9fd10a7d0d5;hb=7d7e50d10452c39a79d94e1c5f9f6cd224c1f764;hp=10b46a8597b8b8e6425554f79dc8ac941a7de6a5;hpb=a2593578edc02d063c1335a3e89b19a3b5a4b1ad;p=platform%2Fupstream%2Fiotivity.git diff --git a/resource/csdk/security/src/secureresourcemanager.c b/resource/csdk/security/src/secureresourcemanager.c index 10b46a8..fc8bd3d 100644 --- a/resource/csdk/security/src/secureresourcemanager.c +++ b/resource/csdk/security/src/secureresourcemanager.c @@ -26,18 +26,17 @@ #include "credresource.h" #include "policyengine.h" #include "srmutility.h" -#include "amsmgr.h" #include "oic_string.h" #include "oic_malloc.h" #include "securevirtualresourcetypes.h" #include "secureresourcemanager.h" #include "srmresourcestrings.h" +#include "ocresourcehandler.h" -#define TAG "SRM" - -#ifdef __WITH_X509__ -#include "crlresource.h" -#endif // __WITH_X509__ +#if defined( __WITH_TLS__) || defined(__WITH_DTLS__) +#include "pkix_interface.h" +#endif //__WITH_TLS__ or __WITH_DTLS__ +#define TAG "OIC_SRM" //Request Callback handler static CARequestCallback gRequestHandler = NULL; @@ -45,16 +44,14 @@ static CARequestCallback gRequestHandler = NULL; static CAResponseCallback gResponseHandler = NULL; //Error Callback handler static CAErrorCallback gErrorHandler = NULL; -//Persistent Storage callback handler for open/read/write/close/unlink -static OCPersistentStorage *gPersistentStorageHandler = NULL; //Provisioning response callback static SPResponseCallback gSPResponseHandler = NULL; /** - * A single global Policy Engine context will suffice as long + * A single global Request context will suffice as long * as SRM is single-threaded. */ -PEContext_t g_policyEngineContext; +SRMRequestContext_t g_requestContext; /** * Function to register provisoning API's response callback. @@ -65,165 +62,264 @@ void SRMRegisterProvisioningResponseHandler(SPResponseCallback respHandler) gSPResponseHandler = respHandler; } -void SetResourceRequestType(PEContext_t *context, const char *resourceUri) +void SetRequestedResourceType(SRMRequestContext_t *context) { - context->resourceType = GetSvrTypeFromUri(resourceUri); + context->resourceType = GetSvrTypeFromUri(context->resourceUri); } -static void SRMSendUnAuthorizedAccessresponse(PEContext_t *context) +// Send the response (context->responseInfo) to the requester +// (context->endPoint). +static void SRMSendResponse(SRMRequestContext_t *context) { - CAResponseInfo_t responseInfo = {.result = CA_EMPTY}; - - if (NULL == context || - NULL == context->amsMgrContext->requestInfo) + if (NULL != context + && NULL != context->requestInfo + && NULL != context->endPoint) { - OIC_LOG_V(ERROR, TAG, "%s : NULL Parameter(s)",__func__); - return; - } - - 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)) - { - OIC_LOG(DEBUG, TAG, "Succeed in sending response to a unauthorized request!"); + if (CA_STATUS_OK == CASendResponse(context->endPoint, + &(context->responseInfo))) + { + OIC_LOG_V(DEBUG, TAG, "SRM response sent."); + context->responseSent = true; + } + else + { + OIC_LOG_V(ERROR, TAG, "SRM response failed."); + } } else { - OIC_LOG(ERROR, TAG, "Failed in sending response to a unauthorized request!"); + OIC_LOG_V(ERROR, TAG, "%s : NULL Parameter(s)",__func__); } + + return; } -void SRMSendResponse(SRMAccessResponse_t responseVal) +// Based on the context->responseVal, either call the entity handler for the +// request (which must send the response), or send an ACCESS_DENIED response. +void SRMGenerateResponse(SRMRequestContext_t *context) { - OIC_LOG(DEBUG, TAG, "Sending response to remote device"); + OIC_LOG_V(INFO, TAG, "%s : entering function.", __func__); - if (IsAccessGranted(responseVal) && gRequestHandler) + // If Access Granted, validate parameters and then pass request + // on to resource endpoint. + if (IsAccessGranted(context->responseVal)) { - OIC_LOG_V(INFO, TAG, "%s : Access granted. Passing Request to RI layer", __func__); - if (!g_policyEngineContext.amsMgrContext->endpoint || - !g_policyEngineContext.amsMgrContext->requestInfo) + if(NULL != gRequestHandler + && NULL != context->endPoint + && NULL != context->requestInfo) + { + OIC_LOG_V(INFO, TAG, "%s : Access granted, passing req to endpoint.", + __func__); + gRequestHandler(context->endPoint, context->requestInfo); + context->responseSent = true; // SRM counts on the endpoint to send + // a response. + } + else // error condition; log relevant msg then send DENIED response { - OIC_LOG_V(ERROR, TAG, "%s : Invalid arguments", __func__); - SRMSendUnAuthorizedAccessresponse(&g_policyEngineContext); - goto exit; + OIC_LOG_V(ERROR, TAG, "%s : Null values in context.", __func__); + context->responseVal = ACCESS_DENIED_POLICY_ENGINE_ERROR; + context->responseInfo.result = CA_INTERNAL_SERVER_ERROR; + SRMSendResponse(context); } - gRequestHandler(g_policyEngineContext.amsMgrContext->endpoint, - g_policyEngineContext.amsMgrContext->requestInfo); } - else + else // Access Denied { - OIC_LOG_V(INFO, TAG, "%s : ACCESS_DENIED.", __func__); - SRMSendUnAuthorizedAccessresponse(&g_policyEngineContext); + OIC_LOG_V(INFO, TAG, "%s : Access Denied; sending CA_UNAUTHORIZED_REQ.", + __func__); + // TODO: in future version, differentiate between types of DENIED. + // See JIRA issue 1796 (https://jira.iotivity.org/browse/IOT-1796) + context->responseInfo.result = CA_UNAUTHORIZED_REQ; + SRMSendResponse(context); } - -exit: - //Resetting PE state to AWAITING_REQUEST - SetPolicyEngineState(&g_policyEngineContext, AWAITING_REQUEST); + return; } -/** - * Handle the request from the SRM. - * - * @param endPoint object from which the response is received. - * @param requestInfo contains information for the request. - */ -void SRMRequestHandler(const CAEndpoint_t *endPoint, const CARequestInfo_t *requestInfo) +// Set the value of context->resourceUri, based on the context->requestInfo. +void SetResourceUriAndType(SRMRequestContext_t *context) { - OIC_LOG(DEBUG, TAG, "Received request from remote device"); - - if (!endPoint || !requestInfo) - { - OIC_LOG(ERROR, TAG, "Invalid arguments"); - return; - } - - // Copy the subjectID - OicUuid_t subjectId = {.id = {0}}; - memcpy(subjectId.id, requestInfo->info.identity.id, sizeof(subjectId.id)); + char *uri = strstr(context->requestInfo->info.resourceUri, "?"); + size_t position = 0; - //Check the URI has the query and skip it before checking the permission - char *uri = strstr(requestInfo->info.resourceUri, "?"); - int position = 0; if (uri) { //Skip query and pass the resource uri - position = uri - requestInfo->info.resourceUri; + position = uri - context->requestInfo->info.resourceUri; } else { - position = strlen(requestInfo->info.resourceUri); + position = strlen(context->requestInfo->info.resourceUri); } if (MAX_URI_LENGTH < position || 0 > position) { - OIC_LOG(ERROR, TAG, "Incorrect URI length"); + OIC_LOG_V(ERROR, TAG, "Incorrect URI length."); return; } - SRMAccessResponse_t response = ACCESS_DENIED; - char newUri[MAX_URI_LENGTH + 1]; - OICStrcpyPartial(newUri, MAX_URI_LENGTH + 1, requestInfo->info.resourceUri, position); + OICStrcpyPartial(context->resourceUri, MAX_URI_LENGTH + 1, + context->requestInfo->info.resourceUri, position); - SetResourceRequestType(&g_policyEngineContext, newUri); + // Set the resource type. + context->resourceType = GetSvrTypeFromUri(context->resourceUri); + + return; +} - //New request are only processed if the policy engine state is AWAITING_REQUEST. - if (AWAITING_REQUEST == g_policyEngineContext.state) +// Check if this request is asking to access a "sec" = true resource +// over an unsecure channel. This type of request is forbidden with +// the exception of a few SVRs (see Security Specification). +void CheckRequestForSecResourceOverUnsecureChannel(SRMRequestContext_t *context) +{ + // if request is over unsecure channel, check resource type + if(false == context->secureChannel) { - OIC_LOG_V(DEBUG, TAG, "Processing request with uri, %s for method, %d", - requestInfo->info.resourceUri, requestInfo->method); - response = CheckPermission(&g_policyEngineContext, &subjectId, newUri, - GetPermissionFromCAMethod_t(requestInfo->method)); + OCResource *resPtr = FindResourceByUri(context->resourceUri); + if (NULL != resPtr) + { + // All vertical secure resources and SVR resources other than + // DOXM & PSTAT should reject requests over unsecure channel. + if ((((resPtr->resourceProperties) & OC_SECURE) + && (context->resourceType == NOT_A_SVR_RESOURCE)) + || ((context->resourceType < OIC_SEC_SVR_TYPE_COUNT) + && (context->resourceType != OIC_R_DOXM_TYPE) + && (context->resourceType != OIC_R_PSTAT_TYPE))) + { + // Reject all the requests over coap for secure resource. + context->responseVal = ACCESS_DENIED_SEC_RESOURCE_OVER_UNSECURE_CHANNEL; + context->responseInfo.result = CA_FORBIDDEN_REQ; + SRMSendResponse(context); + } + } + } + + return; +} + +void ClearRequestContext(SRMRequestContext_t *context) +{ + if (NULL == context) + { + + OIC_LOG(ERROR, TAG, "Null context."); } else { - OIC_LOG_V(INFO, TAG, "PE state %d. Ignoring request with uri, %s for method, %d", - g_policyEngineContext.state, requestInfo->info.resourceUri, requestInfo->method); + // Clear context variables. + context->endPoint = NULL; + context->resourceType = OIC_RESOURCE_TYPE_ERROR; + memset(&context->resourceUri, 0, sizeof(context->resourceUri)); + context->requestedPermission = PERMISSION_ERROR; + memset(&context->responseInfo, 0, sizeof(context->responseInfo)); + context->responseSent = false; + context->responseVal = ACCESS_DENIED_POLICY_ENGINE_ERROR; + context->requestInfo = NULL; + context->secureChannel = false; + context->slowResponseSent = false; + context->subjectIdType = SUBJECT_ID_TYPE_ERROR; + memset(&context->subjectUuid, 0, sizeof(context->subjectUuid)); +#ifdef MULTIPLE_OWNER + memset(&context->payload, 0, context->payloadSize); // TODO Samsung reviewer: please confirm + context->payloadSize = 0; // TODO Samsung reviewer: please confirm +#endif //MULTIPLE_OWNER } - if (IsAccessGranted(response) && gRequestHandler) + return; +} + +// Returns true iff Request arrived over secure channel +bool isRequestOverSecureChannel(SRMRequestContext_t *context) +{ + OicUuid_t nullSubjectId = {.id = {0}}; + + // if flag set, return true + if(context->endPoint->flags & CA_SECURE) { - gRequestHandler(endPoint, requestInfo); - return; + return true; + } + // a null subject ID indicates CoAP, so if non-null, also return true + else if(memcmp(context->requestInfo->info.identity.id, + nullSubjectId.id, sizeof(context->requestInfo->info.identity.id)) != 0) + { + return true; } - // 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; + return false; +} - VERIFY_NON_NULL(TAG, gRequestHandler, ERROR); +/** + * Entry point into SRM, called by lower layer to determine whether an incoming + * request should be GRANTED or DENIED. + * + * @param endPoint object from which the response is received. + * @param requestInfo contains information for the request. + */ +void SRMRequestHandler(const CAEndpoint_t *endPoint, const CARequestInfo_t *requestInfo) +{ + OIC_LOG(DEBUG, TAG, "Received request from remote device"); - if (ACCESS_WAITING_FOR_AMS == response) - { - OIC_LOG(INFO, TAG, "Sending slow response"); + SRMRequestContext_t *ctx = &g_requestContext; // Always use our single ctx for now. + + ClearRequestContext(ctx); - UpdateAmsMgrContext(&g_policyEngineContext, endPoint, requestInfo); - responseInfo.result = CA_EMPTY; - responseInfo.info.type = CA_MSG_ACKNOWLEDGE; + if (!endPoint || !requestInfo) + { + OIC_LOG(ERROR, TAG, "Invalid endPoint or requestInfo; can't process."); } else { - /* - * TODO Enhance this logic more to decide between - * CA_UNAUTHORIZED_REQ or CA_FORBIDDEN_REQ depending - * upon SRMAccessResponseReasonCode_t - */ - OIC_LOG(INFO, TAG, "Sending for regular response"); - responseInfo.result = CA_UNAUTHORIZED_REQ; + ctx->endPoint = endPoint; + ctx->requestInfo = requestInfo; + ctx->requestedPermission = GetPermissionFromCAMethod_t(requestInfo->method); + + // Copy the subjectID. + memcpy(ctx->subjectUuid.id, + requestInfo->info.identity.id, sizeof(ctx->subjectUuid.id)); + ctx->subjectIdType = SUBJECT_ID_TYPE_UUID; // only supported type for now + + // Set secure channel boolean. + ctx->secureChannel = isRequestOverSecureChannel(ctx); + + // Set resource URI and type. + SetResourceUriAndType(ctx); + + // Initialize responseInfo. + memcpy(&(ctx->responseInfo.info), &(requestInfo->info), + sizeof(ctx->responseInfo.info)); + ctx->responseInfo.info.payload = NULL; + ctx->responseInfo.result = CA_INTERNAL_SERVER_ERROR; + ctx->responseInfo.info.dataType = CA_RESPONSE_DATA; + + // Before consulting ACL, check if this is a forbidden request type. + CheckRequestForSecResourceOverUnsecureChannel(ctx); + + // If DENIED response wasn't sent already, then it's time to check ACL. + if(false == ctx->responseSent) + { +#ifdef MULTIPLE_OWNER // TODO Samsung: please verify that these two calls belong + // here inside this conditional statement. + // In case of ACL and CRED, The payload required to verify the payload. + // Payload information will be used for subowner's permission verification. + ctx->payload = (uint8_t*)requestInfo->info.payload; + ctx->payloadSize = requestInfo->info.payloadSize; +#endif //MULTIPLE_OWNER + + OIC_LOG_V(DEBUG, TAG, "Processing request with uri, %s for method %d", + ctx->requestInfo->info.resourceUri, ctx->requestInfo->method); + CheckPermission(ctx); + OIC_LOG_V(DEBUG, TAG, "Request for permission %d received responseVal %d.", + ctx->requestedPermission, ctx->responseVal); + + // Now that we have determined the correct response and set responseVal, + // we generate and send the response to the requester. + SRMGenerateResponse(ctx); + } } - if (CA_STATUS_OK != CASendResponse(endPoint, &responseInfo)) + if(false == ctx->responseSent) { - OIC_LOG(ERROR, TAG, "Failed in sending response to a unauthorized request!"); + OIC_LOG(ERROR, TAG, "Exiting SRM without responding to requester!"); } + return; -exit: - responseInfo.result = CA_INTERNAL_SERVER_ERROR; - if (CA_STATUS_OK != CASendResponse(endPoint, &responseInfo)) - { - OIC_LOG(ERROR, TAG, "Failed in sending response to a unauthorized request!"); - } } /** @@ -262,7 +358,7 @@ void SRMResponseHandler(const CAEndpoint_t *endPoint, const CAResponseInfo_t *re void SRMErrorHandler(const CAEndpoint_t *endPoint, const CAErrorInfo_t *errorInfo) { OIC_LOG_V(INFO, TAG, "Received error from remote device with result, %d for request uri, %s", - errorInfo->result, errorInfo->info.resourceUri); + errorInfo->result, errorInfo->info.resourceUri); if (gErrorHandler) { gErrorHandler(endPoint, errorInfo); @@ -270,8 +366,7 @@ void SRMErrorHandler(const CAEndpoint_t *endPoint, const CAErrorInfo_t *errorInf } OCStackResult SRMRegisterHandler(CARequestCallback reqHandler, - CAResponseCallback respHandler, - CAErrorCallback errHandler) + CAResponseCallback respHandler, CAErrorCallback errHandler) { OIC_LOG(DEBUG, TAG, "SRMRegisterHandler !!"); if( !reqHandler || !respHandler || !errHandler) @@ -284,7 +379,7 @@ OCStackResult SRMRegisterHandler(CARequestCallback reqHandler, gErrorHandler = errHandler; -#if defined(__WITH_DTLS__) +#if defined(__WITH_DTLS__) || defined(__WITH_TLS__) CARegisterHandler(SRMRequestHandler, SRMResponseHandler, SRMErrorHandler); #else CARegisterHandler(reqHandler, respHandler, errHandler); @@ -295,18 +390,12 @@ OCStackResult SRMRegisterHandler(CARequestCallback reqHandler, OCStackResult SRMRegisterPersistentStorageHandler(OCPersistentStorage* persistentStorageHandler) { OIC_LOG(DEBUG, TAG, "SRMRegisterPersistentStorageHandler !!"); - if(!persistentStorageHandler) - { - OIC_LOG(ERROR, TAG, "The persistent storage handler is invalid"); - return OC_STACK_INVALID_PARAM; - } - gPersistentStorageHandler = persistentStorageHandler; - return OC_STACK_OK; + return OCRegisterPersistentStorageHandler(persistentStorageHandler); } OCPersistentStorage* SRMGetPersistentStorageHandler() { - return gPersistentStorageHandler; + return OCGetPersistentStorageHandler(); } OCStackResult SRMInitSecureResources() @@ -315,19 +404,15 @@ OCStackResult SRMInitSecureResources() // behavior (for when SVR DB is missing) is settled. InitSecureResources(); OCStackResult ret = OC_STACK_OK; -#if defined(__WITH_DTLS__) - if(CA_STATUS_OK != CARegisterDTLSCredentialsHandler(GetDtlsPskCredentials)) +#if defined(__WITH_DTLS__) || defined(__WITH_TLS__) + if (CA_STATUS_OK != CAregisterPskCredentialsHandler(GetDtlsPskCredentials)) { - OIC_LOG(ERROR, TAG, "Failed to revert DTLS credential handler."); + OIC_LOG(ERROR, TAG, "Failed to revert TLS credential handler."); ret = OC_STACK_ERROR; } - -#endif // (__WITH_DTLS__) -#if defined(__WITH_X509__) - CARegisterDTLSX509CredentialsHandler(GetDtlsX509Credentials); - CARegisterDTLSCrlHandler(GetDerCrl); -#endif // (__WITH_X509__) - + CAregisterPkixInfoHandler(GetPkixInfo); + CAregisterGetCredentialTypesHandler(InitCipherSuiteList); +#endif // __WITH_DTLS__ or __WITH_TLS__ return ret; } @@ -336,16 +421,6 @@ void SRMDeInitSecureResources() DestroySecureResources(); } -OCStackResult SRMInitPolicyEngine() -{ - return InitPolicyEngine(&g_policyEngineContext); -} - -void SRMDeInitPolicyEngine() -{ - DeInitPolicyEngine(&g_policyEngineContext); -} - bool SRMIsSecurityResourceURI(const char* uri) { if (!uri) @@ -364,6 +439,7 @@ bool SRMIsSecurityResourceURI(const char* uri) OIC_RSRC_PCONF_URI, OIC_RSRC_DPAIRING_URI, OIC_RSRC_VER_URI, + OC_RSRVD_PROV_CRL_URL }; // Remove query from Uri for resource string comparison