#include "oic_malloc.h"
#include "policyengine.h"
+#include "amsmgr.h"
#include "resourcemanager.h"
#include "securevirtualresourcetypes.h"
#include "srmresourcestrings.h"
#include "aclresource.h"
#include "srmutility.h"
#include "doxmresource.h"
+#include "iotvticalendar.h"
#include <string.h>
-#define TAG PCF("SRM-PE")
+#define TAG "SRM-PE"
/**
* Return the uint16_t CRUDN permission corresponding to passed CAMethod_t.
return true;
}
-
/**
* Set the state and clear other stateful context vars.
*/
void SetPolicyEngineState(PEContext_t *context, const PEState_t state)
{
+ if(NULL == context)
+ {
+ return;
+ }
+
// Clear stateful context variables.
- OICFree(context->subject);
- context->subject = NULL;
- OICFree(context->resource);
- context->resource = NULL;
+ 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;
+ FreeCARequestInfo(context->amsMgrContext->requestInfo);
+ OICFree(context->amsMgrContext->endpoint);
+ memset(context->amsMgrContext, 0, sizeof(AmsMgrContext_t));
+
// Set state.
context->state = state;
}
bool retVal = false;
OicUuid_t owner;
+ if(NULL == context)
+ {
+ return OC_STACK_ERROR;
+ }
+
if(OC_STACK_OK == GetDoxmDevOwnerId(&owner))
{
- retVal = UuidCmp(context->subject, &owner);
+ retVal = UuidCmp(&context->subject, &owner);
}
return retVal;
}
+
+inline static bool IsRequestSubjectEmpty(PEContext_t *context)
+{
+ OicUuid_t emptySubject = {.id={}};
+
+ if(NULL == context)
+ {
+ return false;
+ }
+
+ return (memcmp(&context->subject, &emptySubject, sizeof(OicUuid_t)) == 0) ?
+ true : false;
+}
+
+
/**
* Bitwise check to see if 'permission' contains 'request'.
* @param permission The allowed CRUDN permission.
*/
static inline bool IsWildCardSubject(OicUuid_t *subject)
{
+ if(NULL == subject)
+ {
+ return false;
+ }
+
// Because always comparing to string literal, use strcmp()
if(0 == memcmp(subject, &WILDCARD_SUBJECT_ID, sizeof(OicUuid_t)))
{
{
size_t length = 0;
- // Free any existing subject.
- OICFree(context->subject);
- // Copy the subjectId into context.
- context->subject = (OicUuid_t*)OICMalloc(sizeof(OicUuid_t));
- VERIFY_NON_NULL(TAG, context->subject, ERROR);
- memcpy(context->subject, subjectId, sizeof(OicUuid_t));
+ if(NULL == context || NULL == subjectId || NULL == resource)
+ {
+ return;
+ }
+
+ memcpy(&context->subject, subjectId, sizeof(OicUuid_t));
// Copy the resource string into context.
length = strlen(resource) + 1;
if(0 < length)
{
- OICFree(context->resource);
- context->resource = (char*)OICMalloc(length);
- VERIFY_NON_NULL(TAG, context->resource, ERROR);
strncpy(context->resource, resource, length);
context->resource[length - 1] = '\0';
}
// Assign the permission field.
context->permission = requestedPermission;
+}
-exit:
- return;
+
+/**
+ * Check whether 'resource' is getting accessed within the valid time period.
+ * @param acl The ACL to check.
+ * @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)
+{
+#ifndef WITH_ARDUINO //Period & Recurrence not supported on Arduino due
+ //lack of absolute time
+ if(NULL== acl || NULL == acl->periods || 0 == acl->prdRecrLen)
+ {
+ return true;
+ }
+
+ //periods & recurrences rules are paired.
+ if(NULL == acl->recurrences)
+ {
+ return false;
+ }
+
+ for(size_t i = 0; i < acl->prdRecrLen; i++)
+ {
+ if(IOTVTICAL_VALID_ACCESS == IsRequestWithinValidTime(acl->periods[i],
+ acl->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");
+ return false;
+
+#else
+ return true;
+#endif
}
/**
* @return true if 'resource' found, otherwise false.
*/
bool IsResourceInAcl(const char *resource, const OicSecAcl_t *acl)
- {
- for(size_t n = 0; n < acl->resourcesLen; n++)
+{
+ if(NULL== acl || NULL == resource)
{
- if(0 == strcmp(resource, acl->resources[n]) || // TODO null terms?
- 0 == strcmp(WILDCARD_RESOURCE_URI, acl->resources[n]))
- {
- return true;
- }
+ 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]))
+ {
+ return true;
+ }
}
return false;
- }
+}
+
/**
* Find ACLs containing context->subject.
* Search each ACL for requested resource.
- * If resource found, check for context->permission.
+ * If resource found, check for context->permission and period validity.
+ * If the ACL is not found locally and AMACL for the resource is found
+ * then sends the request to AMS service for the ACL
* Set context->retVal to result from first ACL found which contains
* correct subject AND resource.
*
*/
void ProcessAccessRequest(PEContext_t *context)
{
- OC_LOG(INFO, TAG, PCF("Entering ProcessAccessRequest()"));
+ OIC_LOG(DEBUG, TAG, "Entering ProcessAccessRequest()");
if(NULL != context)
{
const OicSecAcl_t *currentAcl = NULL;
// Start out assuming subject not found.
context->retVal = ACCESS_DENIED_SUBJECT_NOT_FOUND;
+
+ // Loop through all ACLs with a matching Subject searching for the right
+ // ACL for this request.
do
{
- OC_LOG(INFO, TAG, PCF("ProcessAccessRequest(): getting ACL..."));
- currentAcl = GetACLResourceData(context->subject, &savePtr);
+ OIC_LOG_V(DEBUG, TAG, "%s: getting ACL..." ,__func__);
+ currentAcl = GetACLResourceData(&context->subject, &savePtr);
+
if(NULL != currentAcl)
{
// Found the subject, so how about resource?
- OC_LOG(INFO, TAG, PCF("ProcessAccessRequest(): \
- found ACL matching subject."));
+ OIC_LOG_V(DEBUG, TAG, "%s:found ACL matching subject" ,__func__);
+
+ // Subject was found, so err changes to Rsrc not found for now.
context->retVal = ACCESS_DENIED_RESOURCE_NOT_FOUND;
- OC_LOG(INFO, TAG, PCF("ProcessAccessRequest(): \
- Searching for resource..."));
+ OIC_LOG_V(DEBUG, TAG, "%s:Searching for resource..." ,__func__);
if(IsResourceInAcl(context->resource, currentAcl))
{
- OC_LOG(INFO, TAG, PCF("ProcessAccessRequest(): \
- found matching resource in ACL."));
+ OIC_LOG_V(INFO, TAG, "%s:found matching resource in ACL" ,__func__);
context->matchingAclFound = true;
- // Found the resource, so it's down to permission.
- context->retVal = ACCESS_DENIED_INSUFFICIENT_PERMISSION;
- if(IsPermissionAllowingRequest(currentAcl->permission, \
- context->permission))
+
+ // Found the resource, so it's down to valid period & permission.
+ context->retVal = ACCESS_DENIED_INVALID_PERIOD;
+ if(IsAccessWithinValidTime(currentAcl))
{
- context->retVal = ACCESS_GRANTED;
+ context->retVal = ACCESS_DENIED_INSUFFICIENT_PERMISSION;
+ if(IsPermissionAllowingRequest(currentAcl->permission, context->permission))
+ {
+ context->retVal = ACCESS_GRANTED;
+ }
}
}
}
else
{
- OC_LOG(INFO, TAG, PCF("ProcessAccessRequest(): \
- no ACL found matching subject ."));
+ OIC_LOG_V(INFO, TAG, "%s:no ACL found matching subject for resource %s",__func__, context->resource);
}
}
while((NULL != currentAcl) && (false == context->matchingAclFound));
if(IsAccessGranted(context->retVal))
{
- OC_LOG(INFO, TAG, PCF("ProcessAccessRequest(): \
- Leaving ProcessAccessRequest(ACCESS_GRANTED)"));
+ OIC_LOG_V(INFO, TAG, "%s:Leaving ProcessAccessRequest(ACCESS_GRANTED)", __func__);
}
else
{
- OC_LOG(INFO, TAG, PCF("ProcessAccessRequest(): \
- Leaving ProcessAccessRequest(ACCESS_DENIED)"));
+ OIC_LOG_V(INFO, TAG, "%s:Leaving ProcessAccessRequest(ACCESS_DENIED)", __func__);
}
}
else
{
- OC_LOG(INFO, TAG, PCF("ProcessAccessRequest(): \
- Leaving ProcessAccessRequest(context is NULL)"));
+ OIC_LOG_V(ERROR, TAG, "%s:Leaving ProcessAccessRequest(context is NULL)", __func__);
}
-
}
/**
VERIFY_NON_NULL(TAG, resource, ERROR);
// Each state machine context can only be processing one request at a time.
- // Therefore if the context is not in AWAITING_REQUEST state, return error.
- // Otherwise, change to BUSY state and begin processing request.
- if(AWAITING_REQUEST == context->state)
+ // Therefore if the context is not in AWAITING_REQUEST or AWAITING_AMS_RESPONSE
+ // state, return error. Otherwise, change to BUSY state and begin processing request.
+ if(AWAITING_REQUEST == context->state || AWAITING_AMS_RESPONSE == context->state)
{
- SetPolicyEngineState(context, BUSY);
- CopyParamsToContext(context, subjectId, resource, requestedPermission);
+ if(AWAITING_REQUEST == context->state)
+ {
+ SetPolicyEngineState(context, BUSY);
+ CopyParamsToContext(context, subjectId, resource, requestedPermission);
+ }
+
// Before doing any processing, check if request coming
// from DevOwner and if so, always GRANT.
if(IsRequestFromDevOwner(context))
}
else
{
+ OicUuid_t saveSubject = {.id={}};
+ bool isSubEmpty = IsRequestSubjectEmpty(context);
+
ProcessAccessRequest(context);
+
// If matching ACL not found, and subject != wildcard, try wildcard.
if((false == context->matchingAclFound) && \
- (false == IsWildCardSubject(context->subject)))
+ (false == IsWildCardSubject(&context->subject)))
{
- OICFree(context->subject);
- context->subject = (OicUuid_t*)OICMalloc(sizeof(OicUuid_t));
- VERIFY_NON_NULL(TAG, context->subject, ERROR);
- memcpy(context->subject, &WILDCARD_SUBJECT_ID,
- sizeof(OicUuid_t));
+ //Saving subject for Amacl check
+ memcpy(&saveSubject, &context->subject,sizeof(OicUuid_t));
+
+ //Setting context subject to WILDCARD_SUBJECT_ID
+ //TODO: change ProcessAccessRequest method signature to
+ //ProcessAccessRequest(context, subject) so that context
+ //subject is not tempered.
+ memset(&context->subject, 0, sizeof(context->subject));
+ memcpy(&context->subject, &WILDCARD_SUBJECT_ID,sizeof(OicUuid_t));
ProcessAccessRequest(context); // TODO anonymous subj can result
// in confusing err code return.
}
+
+ //No local ACE found for the request so checking Amacl resource
+ if(ACCESS_GRANTED != context->retVal)
+ {
+ //If subject is not empty then restore the original subject
+ //else keep the subject to WILDCARD_SUBJECT_ID
+ if(!isSubEmpty)
+ {
+ memcpy(&context->subject, &saveSubject, sizeof(OicUuid_t));
+ }
+
+ //FoundAmaclForRequest method checks for Amacl and fills up
+ //context->amsMgrContext->amsDeviceId with the AMS deviceId
+ //if Amacl was found for the requested resource.
+ if(FoundAmaclForRequest(context))
+ {
+ ProcessAMSRequest(context);
+ }
+ }
}
}
else
// Capture retVal before resetting state for next request.
retVal = context->retVal;
- SetPolicyEngineState(context, AWAITING_REQUEST);
+
+ if(!context->amsProcessing)
+ {
+ OIC_LOG(INFO, TAG, "Resetting PE context and PE State to AWAITING_REQUEST");
+ SetPolicyEngineState(context, AWAITING_REQUEST);
+ }
exit:
return retVal;
*/
OCStackResult InitPolicyEngine(PEContext_t *context)
{
- if(NULL != context)
+ if(NULL == context)
{
- SetPolicyEngineState(context, AWAITING_REQUEST);
+ return OC_STACK_ERROR;
}
+ context->amsMgrContext = (AmsMgrContext_t *)OICCalloc(1, sizeof(AmsMgrContext_t));
+ if(NULL == context->amsMgrContext)
+ {
+ return OC_STACK_ERROR;
+ }
+
+ SetPolicyEngineState(context, AWAITING_REQUEST);
return OC_STACK_OK;
}
if(NULL != context)
{
SetPolicyEngineState(context, STOPPED);
+ OICFree(context->amsMgrContext);
}
-
return;
}