in src/dotnet-svcutil/lib/src/FrameworkFork/System.ServiceModel/System/ServiceModel/Channels/AsymmetricSecurityBindingElement.cs [215:422]
private void ImportMessageScopeProtectionPolicy(MetadataImporter importer, PolicyConversionContext policyContext)
{
MessagePartSpecification endpointSignedParts;
MessagePartSpecification endpointEncryptedParts;
bool isContractAssociatedWithAtLeastOneOtherBinding;
ContractProtectionLevel otherBindingProtectionLevel = null;
bool hasContractProtectionLevel = false;
bool isContractProtectionLevelUniform = true;
ProtectionLevel contractProtectionLevel = ProtectionLevel.None;
string contractAssociationName = String.Format("{0}:{1}:{2}", ContractProtectionLevelKey, policyContext.Contract.Name, policyContext.Contract.Namespace);
if (importer.State.ContainsKey(contractAssociationName))
{
isContractAssociatedWithAtLeastOneOtherBinding = true;
otherBindingProtectionLevel = (ContractProtectionLevel)importer.State[contractAssociationName];
}
else
{
isContractAssociatedWithAtLeastOneOtherBinding = false;
}
ICollection<XmlElement> endpointBindingAssertions = policyContext.GetBindingAssertions();
this.ImportProtectionAssertions(endpointBindingAssertions, out endpointSignedParts, out endpointEncryptedParts);
if (importer.State.ContainsKey(InSecureConversationBootstrapBindingImportMode))
{
// when importing secure conversation boostrap binding, add the endpoint scope protection requirements
// to the importer state to be consumed in SecurityPolicy11.TryImportWsspBootrstapPolicyAssertion
if (endpointEncryptedParts != null)
importer.State[SecureConversationBootstrapEncryptionRequirements] = endpointEncryptedParts;
if (endpointSignedParts != null)
importer.State[SecureConversationBootstrapSignatureRequirements] = endpointSignedParts;
}
foreach (OperationDescription operation in policyContext.Contract.Operations)
{
MessagePartSpecification operationSignedParts;
MessagePartSpecification operationEncryptedParts;
ICollection<XmlElement> operationBindingAssertions = policyContext.GetOperationBindingAssertions(operation);
this.ImportProtectionAssertions(operationBindingAssertions, out operationSignedParts, out operationEncryptedParts);
this.AddParts(ref operationSignedParts, endpointSignedParts);
this.AddParts(ref operationEncryptedParts, endpointEncryptedParts);
MessagePartSpecification messageSignedParts;
MessagePartSpecification messageEncryptedParts;
bool hasProtectionLevel = false;
bool isProtectionLevelUniform = true;
ProtectionLevel protectionLevel = ProtectionLevel.None;
// import application message protection requirements
foreach (MessageDescription message in operation.Messages)
{
ICollection<XmlElement> messageBindingAssertions = policyContext.GetMessageBindingAssertions(message);
this.ImportProtectionAssertions(messageBindingAssertions, out messageSignedParts, out messageEncryptedParts);
this.AddParts(ref messageSignedParts, operationSignedParts);
this.AddParts(ref messageEncryptedParts, operationEncryptedParts);
// validate or set body protection level
ProtectionLevel newProtectionLevel = GetProtectionLevel(messageSignedParts.IsBodyIncluded, messageEncryptedParts.IsBodyIncluded, message.Action);
if (OperationFormatter.IsValidReturnValue(message.Body.ReturnValue))
{
ValidateExistingOrSetNewProtectionLevel(message.Body.ReturnValue, message, operation, policyContext.Contract, newProtectionLevel);
}
foreach (MessagePartDescription body in message.Body.Parts)
{
ValidateExistingOrSetNewProtectionLevel(body, message, operation, policyContext.Contract, newProtectionLevel);
}
if (!OperationFormatter.IsValidReturnValue(message.Body.ReturnValue) || message.Body.Parts.Count == 0)
{
ValidateExistingOrSetNewProtectionLevel(null, message, operation, policyContext.Contract, newProtectionLevel);
}
if (hasProtectionLevel)
{
if (protectionLevel != newProtectionLevel)
{
isProtectionLevelUniform = false;
}
}
else
{
protectionLevel = newProtectionLevel;
hasProtectionLevel = true;
}
if (hasContractProtectionLevel)
{
if (contractProtectionLevel != newProtectionLevel)
{
isContractProtectionLevelUniform = false;
}
}
else
{
contractProtectionLevel = newProtectionLevel;
hasContractProtectionLevel = true;
}
// validate o set header protection level
foreach (MessageHeaderDescription header in message.Headers)
{
bool signed = messageSignedParts.IsHeaderIncluded(header.Name, header.Namespace);
bool encrypted = messageEncryptedParts.IsHeaderIncluded(header.Name, header.Namespace);
newProtectionLevel = GetProtectionLevel(signed, encrypted, message.Action);
ValidateExistingOrSetNewProtectionLevel(header, message, operation, policyContext.Contract, newProtectionLevel);
if (hasProtectionLevel)
{
if (protectionLevel != newProtectionLevel)
{
isProtectionLevelUniform = false;
}
}
else
{
protectionLevel = newProtectionLevel;
hasProtectionLevel = true;
}
if (hasContractProtectionLevel)
{
if (contractProtectionLevel != newProtectionLevel)
{
isContractProtectionLevelUniform = false;
}
}
else
{
contractProtectionLevel = newProtectionLevel;
hasContractProtectionLevel = true;
}
}
}
// normalize protection level settings at the operation scope if possible to help avoid typed message generation
if (hasProtectionLevel && isProtectionLevelUniform)
{
// (hongmeig) remove the foreach message here
// foreach (MessageDescription message in operation.Messages)
this.ResetProtectionLevelForMessages(operation);
operation.ProtectionLevel = protectionLevel;
}
// import fault protection requirements
foreach (FaultDescription fault in operation.Faults)
{
ICollection<XmlElement> faultBindingAssertions = policyContext.GetFaultBindingAssertions(fault);
this.ImportProtectionAssertions(faultBindingAssertions, out messageSignedParts, out messageEncryptedParts);
this.AddParts(ref messageSignedParts, operationSignedParts);
this.AddParts(ref messageEncryptedParts, operationEncryptedParts);
// validate or set fault protection level
ProtectionLevel newProtectionLevel = GetProtectionLevel(messageSignedParts.IsBodyIncluded, messageEncryptedParts.IsBodyIncluded, fault.Action);
if (fault.HasProtectionLevel)
{
if (fault.ProtectionLevel != newProtectionLevel)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(string.Format(SRServiceModel.CannotImportProtectionLevelForContract, policyContext.Contract.Name, policyContext.Contract.Namespace)));
}
}
else
{
fault.ProtectionLevel = newProtectionLevel;
}
if (hasContractProtectionLevel)
{
if (contractProtectionLevel != newProtectionLevel)
{
isContractProtectionLevelUniform = false;
}
}
else
{
contractProtectionLevel = newProtectionLevel;
hasContractProtectionLevel = true;
}
}
}
if (isContractAssociatedWithAtLeastOneOtherBinding)
{
if (hasContractProtectionLevel != otherBindingProtectionLevel.HasProtectionRequirements
|| isContractProtectionLevelUniform != otherBindingProtectionLevel.HasUniformProtectionLevel
|| contractProtectionLevel != otherBindingProtectionLevel.UniformProtectionLevel)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(string.Format(SRServiceModel.CannotImportProtectionLevelForContract, policyContext.Contract.Name, policyContext.Contract.Namespace)));
}
}
else
{
if (hasContractProtectionLevel && isContractProtectionLevelUniform && contractProtectionLevel == ProtectionLevel.EncryptAndSign)
{
// remove all explicitly set protection levels on the contract description, since they are uniform across the contract
// and match our binding's default of EncryptAndSign
foreach (OperationDescription operation in policyContext.Contract.Operations)
{
this.ResetProtectionLevelForMessages(operation);
foreach (FaultDescription fault in operation.Faults)
{
fault.ResetProtectionLevel();
}
operation.ResetProtectionLevel();
}
}
importer.State[contractAssociationName] = new ContractProtectionLevel(hasContractProtectionLevel, isContractProtectionLevelUniform, contractProtectionLevel);
}
}