public static void TestResponseElement( ResponseElement res ) { MemoryStream ms = new MemoryStream(); XmlTextWriter tw = new XmlTextWriter( ms, System.Text.Encoding.ASCII ); res.WriteDocument( tw ); tw.Flush(); ms.Position = 0; ContextDocument cd = new ContextDocument( new XmlTextReader( ms ), XacmlVersion.Version11 ); }
/// <summary> /// Creates a new ContextDocumentReadWrite using the XmlReader instance provided. /// </summary> /// <param name="reader">The XmlReader instance positioned at the begining of the document.</param> /// <param name="schemaVersion">The schema used to validate this context document.</param> public ContextDocumentReadWrite(XmlReader reader, XacmlVersion schemaVersion) { if (reader == null) { throw new ArgumentNullException(nameof(reader)); } // Search for the first element. while (reader.Read() && reader.NodeType != XmlNodeType.Element) { } // Keep the contents of the context document. // HACK: Due to XPath validation the document must be readed twice, the first time to load the instance // and the second one to keep a document to execute XPath sentences. _xmlString = reader.ReadOuterXml(); // Read the contents in a new reader. #if NET20 StringReader sreader = new StringReader(_xmlString); #endif // Prepare the validation. #if NET20 ValidationEventHandler validationHandler = vreader_ValidationEventHandler; XmlReaderSettings settings = new XmlReaderSettings { ValidationType = ValidationType.Schema }; settings.ValidationEventHandler += validationHandler; XmlReader vreader = null; #endif switch (schemaVersion) { case XacmlVersion.Version10: case XacmlVersion.Version11: { Stream policySchemaStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(pol.PolicyDocument.Xacml10PolicySchemaResourceName); Stream contextSchemaStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(Xacml10ContextSchemaResourceName); #if NET10 vreader.Schemas.Add(PolicySchema1.Namespaces.Policy, new XmlTextReader(policySchemaStream)); vreader.Schemas.Add(PolicySchema1.Namespaces.Context, new XmlTextReader(contexSchemaStream)); #endif #if NET20 if (_compiledSchemas11 == null) { _compiledSchemas11 = new XmlSchemaSet(); _compiledSchemas11.Add(XmlSchema.Read(policySchemaStream, validationHandler)); _compiledSchemas11.Add(XmlSchema.Read(contextSchemaStream, validationHandler)); _compiledSchemas11.Compile(); } settings.Schemas.Add(_compiledSchemas11); #endif break; } case XacmlVersion.Version20: { Stream policySchemaStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(pol.PolicyDocumentReadWrite.Xacml20PolicySchemaResourceName); Stream contextSchemaStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(Xacml20ContextSchemaResourceName); if (_compiledSchemas20 == null) { _compiledSchemas20 = new XmlSchemaSet(); if (policySchemaStream != null) { _compiledSchemas20.Add(XmlSchema.Read(policySchemaStream, validationHandler)); } if (contextSchemaStream != null) { _compiledSchemas20.Add(XmlSchema.Read(contextSchemaStream, validationHandler)); } _compiledSchemas20.Compile(); } settings.Schemas.Add(_compiledSchemas20); break; } default: throw new ArgumentException(Resource.ResourceManager[Resource.MessageKey.exc_invalid_version_parameter_value], nameof(reader)); } #if NET20 vreader = XmlReader.Create(sreader, settings); #endif while (vreader.Read()) { //Read all the namespaces and keep them in the _namespaces hashtable. if (vreader.HasAttributes) { while (vreader.MoveToNextAttribute()) { if (vreader.LocalName == PolicySchema1.Namespaces.XMLNS) { _namespaces.Add(vreader.Prefix, vreader.Value); } else if (vreader.Prefix == PolicySchema1.Namespaces.XMLNS) { _namespaces.Add(vreader.LocalName, vreader.Value); } } vreader.MoveToElement(); } switch (vreader.LocalName) { case ContextSchema.RequestElement.Request: _request = new RequestElementReadWrite(vreader, schemaVersion); break; case ContextSchema.ResponseElement.Response: _response = new ResponseElement(vreader, schemaVersion); break; } } }
/// <summary> /// Evaluate the context document using a specified policy /// </summary> /// <param name="policyDocument">The policy instance</param> /// <param name="contextDocument">The context document instance</param> /// <returns>The response document</returns> public ctx.ResponseElement Evaluate( pol.PolicyDocument policyDocument, ctx.ContextDocument contextDocument ) { if (policyDocument == null) throw new ArgumentNullException("policyDocument"); if (contextDocument == null) throw new ArgumentNullException("contextDocument"); EvaluationContext context = new EvaluationContext( this, policyDocument, (ctx.ContextDocument)contextDocument ) ; context.Trace( "Start evaluation" ); context.AddIndent(); if ( policyDocument == null || contextDocument == null ) { // If a validation error was found a response is created with the syntax error message ctx.ResponseElement response = new ctx.ResponseElement( new ctx.ResultElement[] { new ctx.ResultElement( null, Decision.Indeterminate, new ctx.StatusElement( new ctx.StatusCodeElement( StatusCodes.ProcessingError, null, policyDocument.Version ), null, null, policyDocument.Version ), null, policyDocument.Version ) }, policyDocument.Version ); return response; } // Check if both documents are valid if( !policyDocument.IsValidDocument || !contextDocument.IsValidDocument ) { // If a validation error was found a response is created with the syntax error message ctx.ResponseElement response = new ctx.ResponseElement( new ctx.ResultElement[] { new ctx.ResultElement( null, Decision.Indeterminate, new ctx.StatusElement( new ctx.StatusCodeElement( StatusCodes.SyntaxError, null, policyDocument.Version ), null, null, policyDocument.Version ), null, policyDocument.Version ) }, policyDocument.Version ); return response; } // Create a new response contextDocument.Response = new ctx.ResponseElement( (ctx.ResultElement[])null, policyDocument.Version ); try { // Create the evaluable policy intance IMatchEvaluable policy = null; if( policyDocument.PolicySet != null ) { policy = new PolicySet( this, (pol.PolicySetElement)policyDocument.PolicySet ); } else if( policyDocument.Policy != null ) { policy = new Policy( (pol.PolicyElement)policyDocument.Policy ); } // Evaluate the policy or policy set if( policy != null ) { // Creates the evaluable policy set if( policy.AllResources.Count == 0 ) { policy.AllResources.Add( "" ); } string requestedResourceString = String.Empty; Uri requestedResource = null; foreach( ctx.ResourceElement resource in contextDocument.Request.Resources ) { // Keep the requested resource if( resource.IsHierarchical ) { foreach( ctx.AttributeElement attribute in resource.Attributes ) { if( attribute.AttributeId == ResourceElement.ResourceId ) { if( context.PolicyDocument.Version == XacmlVersion.Version10 || context.PolicyDocument.Version == XacmlVersion.Version11 ) { requestedResourceString = attribute.AttributeValues[0].Contents; } else { if( attribute.AttributeValues.Count > 1 ) { throw new NotSupportedException( "resources contains a bag of values" ); } requestedResourceString = attribute.AttributeValues[0].Contents; } } } if( !string.IsNullOrEmpty(requestedResourceString) ) { requestedResource = new Uri( requestedResourceString ); } } // Iterate through the policy resources evaluating each resource in the context document request foreach( string resourceName in policy.AllResources ) { bool mustEvaluate; if( resource.IsHierarchical ) { //Validate if the resource is hierarchically desdendant or children //of the requested resource Uri policyResource = new Uri( resourceName ); if( !(mustEvaluate = requestedResource.Equals( policyResource ) ) ) { // Perform the hierarchical evaluation if( resource.ResourceScopeValue == ctx.ResourceScope.Children ) { mustEvaluate = typ.AnyUri.IsChildrenOf( requestedResource, policyResource ); } else if( resource.ResourceScopeValue == ctx.ResourceScope.Descendants ) { mustEvaluate = typ.AnyUri.IsDescendantOf( requestedResource, policyResource ); } } if( mustEvaluate ) { foreach( ctx.AttributeElementReadWrite attribute in context.CurrentResource.Attributes ) { if( attribute.AttributeId == ResourceElement.ResourceId ) { attribute.AttributeValues[0].Contents = resourceName; break; } } } } else { context.CurrentResource = resource; mustEvaluate = true; } if( mustEvaluate ) { // Evaluates the policy set Decision decision = policy.Evaluate( context ); // Create a status code using the policy execution state ctx.StatusCodeElement scode; if( context.IsMissingAttribute ) { scode = new ctx.StatusCodeElement( StatusCodes.MissingAttribute, null, policyDocument.Version ); } else if( context.ProcessingError ) { scode = new ctx.StatusCodeElement( StatusCodes.ProcessingError, null, policyDocument.Version ); } else { scode = new ctx.StatusCodeElement( StatusCodes.OK, null, policyDocument.Version ); } //Stop the iteration if there is not a hierarchical request if( !resource.IsHierarchical ) { // Ussually when a single resource is requested the ResourceId is not specified in the result IObligationsContainer oblig = policy as IObligationsContainer; contextDocument.Response.Results.Add( new ctx.ResultElement( "", decision, new ctx.StatusElement( scode, "", "", policyDocument.Version ), oblig.Obligations, policyDocument.Version ) ); break; } else { // Adding a resource for each requested resource, using the resourceName as the resourceId of the result IObligationsContainer oblig = policy as IObligationsContainer; contextDocument.Response.Results.Add( new ctx.ResultElement( resourceName, decision, new ctx.StatusElement( scode, "", "", policyDocument.Version ), oblig.Obligations, policyDocument.Version ) ); } } // if( mustEvaluate ) } // foreach( string resourceName in policy.AllResources ) } } //if( policy != null ) } catch( EvaluationException e ) { // If a validation error was found a response is created with the syntax error message contextDocument.Response = new ctx.ResponseElement( new ctx.ResultElement[] { new ctx.ResultElement( null, Decision.Indeterminate, new ctx.StatusElement( new ctx.StatusCodeElement( StatusCodes.ProcessingError, null, policyDocument.Version ), e.Message, e.StackTrace, policyDocument.Version ), null, policyDocument.Version ) }, policyDocument.Version ); } return contextDocument.Response; }
/// <summary> /// Creates a new ContextDocumentReadWrite using the XmlReader instance provided. /// </summary> /// <param name="reader">The XmlReader instance positioned at the begining of the document.</param> /// <param name="schemaVersion">The schema used to validate this context document.</param> public ContextDocumentReadWrite(XmlReader reader, XacmlVersion schemaVersion) { if (reader == null) throw new ArgumentNullException(nameof(reader)); // Search for the first element. while (reader.Read() && reader.NodeType != XmlNodeType.Element) { } // Keep the contents of the context document. // HACK: Due to XPath validation the document must be readed twice, the first time to load the instance // and the second one to keep a document to execute XPath sentences. _xmlString = reader.ReadOuterXml(); // Read the contents in a new reader. #if NET20 StringReader sreader = new StringReader(_xmlString); #endif // Prepare the validation. #if NET20 ValidationEventHandler validationHandler = vreader_ValidationEventHandler; XmlReaderSettings settings = new XmlReaderSettings {ValidationType = ValidationType.Schema}; settings.ValidationEventHandler += validationHandler; XmlReader vreader = null; #endif switch (schemaVersion) { case XacmlVersion.Version10: case XacmlVersion.Version11: { Stream policySchemaStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(pol.PolicyDocument.Xacml10PolicySchemaResourceName); Stream contextSchemaStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(Xacml10ContextSchemaResourceName); #if NET10 vreader.Schemas.Add( PolicySchema1.Namespaces.Policy, new XmlTextReader( policySchemaStream ) ); vreader.Schemas.Add( PolicySchema1.Namespaces.Context, new XmlTextReader( contexSchemaStream ) ); #endif #if NET20 if (_compiledSchemas11 == null) { _compiledSchemas11 = new XmlSchemaSet(); _compiledSchemas11.Add(XmlSchema.Read(policySchemaStream, validationHandler)); _compiledSchemas11.Add(XmlSchema.Read(contextSchemaStream, validationHandler)); _compiledSchemas11.Compile(); } settings.Schemas.Add(_compiledSchemas11); #endif break; } case XacmlVersion.Version20: { Stream policySchemaStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(pol.PolicyDocumentReadWrite.Xacml20PolicySchemaResourceName); Stream contextSchemaStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(Xacml20ContextSchemaResourceName); if (_compiledSchemas20 == null) { _compiledSchemas20 = new XmlSchemaSet(); if (policySchemaStream != null) _compiledSchemas20.Add(XmlSchema.Read(policySchemaStream, validationHandler)); if (contextSchemaStream != null) _compiledSchemas20.Add(XmlSchema.Read(contextSchemaStream, validationHandler)); _compiledSchemas20.Compile(); } settings.Schemas.Add(_compiledSchemas20); break; } default: throw new ArgumentException(Resource.ResourceManager[Resource.MessageKey.exc_invalid_version_parameter_value], nameof(reader)); } #if NET20 vreader = XmlReader.Create(sreader, settings); #endif while (vreader.Read()) { //Read all the namespaces and keep them in the _namespaces hashtable. if (vreader.HasAttributes) { while (vreader.MoveToNextAttribute()) { if (vreader.LocalName == PolicySchema1.Namespaces.XMLNS) { _namespaces.Add(vreader.Prefix, vreader.Value); } else if (vreader.Prefix == PolicySchema1.Namespaces.XMLNS) { _namespaces.Add(vreader.LocalName, vreader.Value); } } vreader.MoveToElement(); } switch (vreader.LocalName) { case ContextSchema.RequestElement.Request: _request = new RequestElementReadWrite(vreader, schemaVersion); break; case ContextSchema.ResponseElement.Response: _response = new ResponseElement(vreader, schemaVersion); break; } } }