X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=resource%2Fcsdk%2Fsecurity%2Fsrc%2Fpolicyengine.c;h=e38fc38848668dc86d91ee5c5756de8908261046;hb=7f00f942c39b7bc27c7eeecf213a239c3fe4173c;hp=4a4694d381b3e0f6b39f280a39deac323079e6fc;hpb=9c42f3fe634ac3ee088e9a7592a35f319549f745;p=platform%2Fupstream%2Fiotivity.git diff --git a/resource/csdk/security/src/policyengine.c b/resource/csdk/security/src/policyengine.c index 4a4694d..e38fc38 100644 --- a/resource/csdk/security/src/policyengine.c +++ b/resource/csdk/security/src/policyengine.c @@ -19,6 +19,7 @@ //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= #include +#include "utlist.h" #include "oic_malloc.h" #include "policyengine.h" #include "amsmgr.h" @@ -36,7 +37,7 @@ #include "amaclresource.h" #include "credresource.h" -#define TAG "SRM-PE" +#define TAG "OIC_SRM_PE" uint16_t GetPermissionFromCAMethod_t(const CAMethod_t method) { @@ -46,10 +47,15 @@ uint16_t GetPermissionFromCAMethod_t(const CAMethod_t method) case CA_GET: perm = (uint16_t)PERMISSION_READ; break; - case CA_POST: // For now we treat all PUT & POST as Write - case CA_PUT: // because we don't know if resource exists yet. + case CA_POST: // Treat all POST as Write (Update) because + // we don't know if resource exists yet. + // This will be addressed in IoTivity impl of OCF 1.0 perm = (uint16_t)PERMISSION_WRITE; break; + case CA_PUT: // Per convention, OIC/OCF uses PUT only for Create, + // never for Update. + perm = (uint16_t)PERMISSION_CREATE; + break; case CA_DELETE: perm = (uint16_t)PERMISSION_DELETE; break; @@ -98,7 +104,6 @@ void SetPolicyEngineState(PEContext_t *context, const PEState_t state) memset(&context->subject, 0, sizeof(context->subject)); memset(&context->resource, 0, sizeof(context->resource)); context->permission = 0x0; - context->matchingAclFound = false; context->amsProcessing = false; context->retVal = ACCESS_DENIED_POLICY_ENGINE_ERROR; @@ -124,21 +129,117 @@ void SetPolicyEngineState(PEContext_t *context, const PEState_t state) static bool IsRequestFromDevOwner(PEContext_t *context) { bool retVal = false; - OicUuid_t ownerid; if(NULL == context) { return retVal; } + /* if(OC_STACK_OK == GetDoxmDevOwnerId(&ownerid)) { retVal = UuidCmp(&context->subject, &ownerid); } + */ + // TODO: Added as workaround for CTT + OicSecDoxm_t* doxm = (OicSecDoxm_t*) GetDoxmResourceData(); + if (doxm) + { + retVal = UuidCmp(&doxm->owner, &context->subject); + } return retVal; } + +#ifdef MULTIPLE_OWNER +/** + * Compare the request's subject to SubOwner. + * + * @return true if context->subjectId exist subowner list, else false. + */ +static bool IsRequestFromSubOwner(PEContext_t *context) +{ + bool retVal = false; + + if(NULL == context) + { + return retVal; + } + + if(IsSubOwner(&context->subject)) + { + retVal = true; + } + + if(true == retVal) + { + OIC_LOG(INFO, TAG, "PE.IsRequestFromSubOwner(): returning true"); + } + else + { + OIC_LOG(INFO, TAG, "PE.IsRequestFromSubOwner(): returning false"); + } + + return retVal; +} + + +/** + * Verify the SubOwner's request. + * + * @return true if request is valid, else false. + */ +static bool IsValidRequestFromSubOwner(PEContext_t *context) +{ + bool isValidRequest = false; + + if(NULL == context) + { + return isValidRequest; + } + + switch(context->resourceType) + { + case OIC_R_DOXM_TYPE: + //SubOwner has READ permission only for DOXM + if(PERMISSION_READ == context->permission) + { + isValidRequest = true; + } + break; + case OIC_R_PSTAT_TYPE: + //SubOwner has full permsion for PSTAT except RESET + isValidRequest = IsValidPstatAccessForSubOwner(context->payload, context->payloadSize); + break; + case OIC_R_CRED_TYPE: + //SubOwner can only access the credential which is registered as the eowner. + isValidRequest = IsValidCredentialAccessForSubOwner(&context->subject, context->payload, context->payloadSize); + break; + case OIC_R_ACL_TYPE: + //SubOwner can only access the ACL which is registered as the eowner. + isValidRequest = IsValidAclAccessForSubOwner(&context->subject, context->payload, context->payloadSize); + break; + default: + //SubOwner has full permission for all resource except the security resource + isValidRequest = true; + break; + } + + if(isValidRequest) + { + OIC_LOG(INFO, TAG, "PE.IsValidRequestFromSubOwner(): returning true"); + } + else + { + OIC_LOG(INFO, TAG, "PE.IsValidRequestFromSubOwner(): returning false"); + } + + return isValidRequest; +} +#endif //MULTIPLE_OWNER + + // TODO - remove these function placeholders as they are implemented // in the resource entity handler code. // Note that because many SVRs do not have a rowner, in those cases we @@ -149,18 +250,14 @@ static bool IsRequestFromDevOwner(PEContext_t *context) OCStackResult GetCrlRownerId(OicUuid_t *rowner) { + OC_UNUSED(rowner); rowner = NULL; return OC_STACK_ERROR; } OCStackResult GetSaclRownerId(OicUuid_t *rowner) { - rowner = NULL; - return OC_STACK_ERROR; -} - -OCStackResult GetSvcRownerId(OicUuid_t *rowner) -{ + OC_UNUSED(rowner); rowner = NULL; return OC_STACK_ERROR; } @@ -175,7 +272,6 @@ static GetSvrRownerId_t GetSvrRownerId[OIC_SEC_SVR_TYPE_COUNT] = { GetPconfRownerId, GetPstatRownerId, GetSaclRownerId, - GetSvcRownerId }; /** @@ -214,9 +310,9 @@ bool IsRequestFromResourceOwner(PEContext_t *context) return retVal; } -inline static bool IsRequestSubjectEmpty(PEContext_t *context) +INLINE_API bool IsRequestSubjectEmpty(PEContext_t *context) { - OicUuid_t emptySubject = {.id={}}; + OicUuid_t emptySubject = {.id={0}}; if(NULL == context) { @@ -235,7 +331,7 @@ inline static bool IsRequestSubjectEmpty(PEContext_t *context) * * @return true if 'permission' bits include all 'request' bits. */ -static inline bool IsPermissionAllowingRequest(const uint16_t permission, +INLINE_API bool IsPermissionAllowingRequest(const uint16_t permission, const uint16_t request) { if (request == (request & permission)) @@ -253,7 +349,7 @@ static inline bool IsPermissionAllowingRequest(const uint16_t permission, * * @return true if 'subject' is the wildcard, false if it is not. */ -static inline bool IsWildCardSubject(OicUuid_t *subject) +INLINE_API bool IsWildCardSubject(OicUuid_t *subject) { if(NULL == subject) { @@ -289,12 +385,10 @@ static void CopyParamsToContext(PEContext_t *context, memcpy(&context->subject, subjectId, sizeof(OicUuid_t)); // Copy the resource string into context. - length = strlen(resource) + 1; - if (0 < length) - { - strncpy(context->resource, resource, length); - context->resource[length - 1] = '\0'; - } + length = sizeof(context->resource) - 1; + strncpy(context->resource, resource, length); + context->resource[length] = '\0'; + // Assign the permission field. context->permission = requestedPermission; @@ -308,28 +402,32 @@ static void CopyParamsToContext(PEContext_t *context, * @return true if access is within valid time period or if the period or recurrence is not present. * false if period and recurrence present and the access is not within valid time period. */ -static bool IsAccessWithinValidTime(const OicSecAcl_t *acl) +static bool IsAccessWithinValidTime(const OicSecAce_t *ace) { #ifndef WITH_ARDUINO //Period & Recurrence not supported on Arduino due - //lack of absolute time - if (NULL== acl || NULL == acl->periods || 0 == acl->prdRecrLen) + //lack of absolute time + if (NULL== ace || NULL == ace->validities) { return true; } //periods & recurrences rules are paired. - if (NULL == acl->recurrences) + if (NULL == ace->validities->recurrences) { return false; } - for (size_t i = 0; i < acl->prdRecrLen; i++) + OicSecValidity_t* validity = NULL; + LL_FOREACH(ace->validities, validity) { - if (IOTVTICAL_VALID_ACCESS == IsRequestWithinValidTime(acl->periods[i], - acl->recurrences[i])) + for(size_t i = 0; i < validity->recurrenceLen; i++) { - OIC_LOG(INFO, TAG, "Access request is in allowed time period"); - return true; + if (IOTVTICAL_VALID_ACCESS == IsRequestWithinValidTime(validity->period, + validity->recurrences[i])) + { + OIC_LOG(INFO, TAG, "Access request is in allowed time period"); + return true; + } } } OIC_LOG(ERROR, TAG, "Access request is in invalid time period"); @@ -341,24 +439,25 @@ static bool IsAccessWithinValidTime(const OicSecAcl_t *acl) } /** - * Check whether 'resource' is in the passed ACL. + * Check whether 'resource' is in the passed ACE. * * @param resource is the resource being searched. - * @param acl is the ACL to check. + * @param ace is the ACE to check. * * @return true if 'resource' found, otherwise false. */ - static bool IsResourceInAcl(const char *resource, const OicSecAcl_t *acl) + static bool IsResourceInAce(const char *resource, const OicSecAce_t *ace) { - if (NULL== acl || NULL == resource) + if (NULL== ace || NULL == resource) { return false; } - for (size_t n = 0; n < acl->resourcesLen; n++) - { - if (0 == strcmp(resource, acl->resources[n]) || // TODO null terms? - 0 == strcmp(WILDCARD_RESOURCE_URI, acl->resources[n])) + OicSecRsrc_t* rsrc = NULL; + LL_FOREACH(ace->resources, rsrc) + { + if (0 == strcmp(resource, rsrc->href) || // TODO null terms? + 0 == strcmp(WILDCARD_RESOURCE_URI, rsrc->href)) { return true; } @@ -381,38 +480,48 @@ static void ProcessAccessRequest(PEContext_t *context) OIC_LOG(DEBUG, TAG, "Entering ProcessAccessRequest()"); if (NULL != context) { - const OicSecAcl_t *currentAcl = NULL; - OicSecAcl_t *savePtr = NULL; + const OicSecAce_t *currentAce = NULL; + OicSecAce_t *savePtr = NULL; // Start out assuming subject not found. context->retVal = ACCESS_DENIED_SUBJECT_NOT_FOUND; + char *strUuid = NULL; + if (OC_STACK_OK == ConvertUuidToStr(&context->subject, &strUuid)) + { + OIC_LOG_V(DEBUG, TAG, "%s: subject : %s" ,__func__, strUuid); + OICFree(strUuid); + } + else + { + OIC_LOG(ERROR, TAG, "Can't convert subject uuid to string"); + } + // Loop through all ACLs with a matching Subject searching for the right // ACL for this request. do { - OIC_LOG_V(DEBUG, TAG, "%s: getting ACL..." ,__func__); - currentAcl = GetACLResourceData(&context->subject, &savePtr); + OIC_LOG_V(DEBUG, TAG, "%s: getting ACE..." ,__func__); + currentAce = GetACLResourceData(&context->subject, &savePtr); - if (NULL != currentAcl) + if (NULL != currentAce) { // Found the subject, so how about resource? - OIC_LOG_V(DEBUG, TAG, "%s:found ACL matching subject" ,__func__); + OIC_LOG_V(DEBUG, TAG, "%s:found ACE matching subject" ,__func__); // Subject was found, so err changes to Rsrc not found for now. context->retVal = ACCESS_DENIED_RESOURCE_NOT_FOUND; OIC_LOG_V(DEBUG, TAG, "%s:Searching for resource..." ,__func__); - if (IsResourceInAcl(context->resource, currentAcl)) + if (IsResourceInAce(context->resource, currentAce)) { - OIC_LOG_V(INFO, TAG, "%s:found matching resource in ACL" ,__func__); - context->matchingAclFound = true; + OIC_LOG_V(INFO, TAG, "%s:found matching resource in ACE" ,__func__); // Found the resource, so it's down to valid period & permission. context->retVal = ACCESS_DENIED_INVALID_PERIOD; - if (IsAccessWithinValidTime(currentAcl)) + if (IsAccessWithinValidTime(currentAce)) { context->retVal = ACCESS_DENIED_INSUFFICIENT_PERMISSION; - if (IsPermissionAllowingRequest(currentAcl->permission, context->permission)) + if (IsPermissionAllowingRequest(currentAce->permission, context->permission)) { context->retVal = ACCESS_GRANTED; } @@ -423,7 +532,7 @@ static void ProcessAccessRequest(PEContext_t *context) { OIC_LOG_V(INFO, TAG, "%s:no ACL found matching subject for resource %s",__func__, context->resource); } - } while ((NULL != currentAcl) && (false == context->matchingAclFound)); + } while ((NULL != currentAce) && (ACCESS_GRANTED != context->retVal)); if (IsAccessGranted(context->retVal)) { @@ -462,27 +571,52 @@ SRMAccessResponse_t CheckPermission(PEContext_t *context, CopyParamsToContext(context, subjectId, resource, requestedPermission); } - // Before doing any processing, check if request coming - // from DevOwner and if so, always GRANT. - if (IsRequestFromDevOwner(context)) + // Before doing any ACL processing, check if request a) coming + // from DevOwner AND b) the device is in Ready for OTM or Reset state + // (which in IoTivity is equivalent to isOp == false && owned == false) + // AND c) the request is for a SVR resource. + // If all 3 conditions are met, grant request. + bool isDeviceOwned = true; // default to value that will not grant access + if (OC_STACK_OK != GetDoxmIsOwned(&isDeviceOwned)) // if runtime error, don't grant + { + context->retVal = ACCESS_DENIED_POLICY_ENGINE_ERROR; + } + // If we were able to get the value of doxm->isOwned, proceed with + // test for implicit access... + else if (IsRequestFromDevOwner(context) // if from DevOwner + && (GetPstatIsop() == false) // AND if pstat->isOp == false + && (isDeviceOwned == false) // AND if doxm->isOwned == false + && (context->resourceType != NOT_A_SVR_RESOURCE)) // AND if SVR type { context->retVal = ACCESS_GRANTED; } - // Then check if request is for a SVR and coming from rowner + // If not granted via DevOwner status and not a subowner, + // then check if request is for a SVR and coming from rowner else if (IsRequestFromResourceOwner(context)) { context->retVal = ACCESS_GRANTED; } +#ifdef MULTIPLE_OWNER + //Then check if request from SubOwner + else if(IsRequestFromSubOwner(context)) + { + if(IsValidRequestFromSubOwner(context)) + { + context->retVal = ACCESS_GRANTED; + } + } +#endif //MULTIPLE_OWNER // Else request is a "normal" request that must be tested against ACL else { - OicUuid_t saveSubject = {.id={}}; + OicUuid_t saveSubject = {.id={0}}; bool isSubEmpty = IsRequestSubjectEmpty(context); ProcessAccessRequest(context); - // If matching ACL not found, and subject != wildcard, try wildcard. - if ((false == context->matchingAclFound) && \ + // If access not already granted, and requested subject != wildcard, + // try looking for a wildcard ACE that grants access. + if ((ACCESS_GRANTED != context->retVal) && \ (false == IsWildCardSubject(&context->subject))) { //Saving subject for Amacl check