1 //----------------------------------------------------------------------------- 2 // Copyright (c) Microsoft Corporation. All rights reserved. 3 //----------------------------------------------------------------------------- 4 5 using System.ServiceModel.Diagnostics; 6 using System.ServiceModel.Dispatcher; 7 using System.ServiceModel.Description; 8 using System.ServiceModel.Security; 9 using System.ServiceModel.Configuration; 10 using System.Collections.ObjectModel; 11 using System.Net.Security; 12 13 namespace System.ServiceModel.Channels 14 { 15 using System.Xml; 16 using System.ServiceModel.Security.Tokens; 17 using System.ServiceModel.Security; 18 using System.ServiceModel; 19 using System.IO; 20 using System.Collections.ObjectModel; 21 using System.Collections.Generic; 22 using System.Runtime.InteropServices; 23 24 public class SecurityBindingElementImporter : IPolicyImportExtension 25 { 26 internal const string MaxPolicyRedirectionsKey = "MaxPolicyRedirections"; 27 internal const string SecureConversationBootstrapEncryptionRequirements = "SecureConversationBootstrapEncryptionRequirements"; 28 internal const string SecureConversationBootstrapSignatureRequirements = "SecureConversationBootstrapSignatureRequirements"; 29 internal const string InSecureConversationBootstrapBindingImportMode = "InSecureConversationBootstrapBindingImportMode"; 30 internal const string ContractProtectionLevelKey = "ContractProtectionLevelKey"; 31 32 int maxPolicyRedirections; 33 SecurityBindingElementImporter()34 public SecurityBindingElementImporter() 35 { 36 this.maxPolicyRedirections = 10; 37 } 38 39 public int MaxPolicyRedirections 40 { 41 get 42 { 43 return this.maxPolicyRedirections; 44 } 45 } 46 ImportOperationScopeSupportingTokensPolicy(MetadataImporter importer, PolicyConversionContext policyContext, SecurityBindingElement binding)47 void ImportOperationScopeSupportingTokensPolicy(MetadataImporter importer, PolicyConversionContext policyContext, SecurityBindingElement binding) 48 { 49 foreach (OperationDescription operation in policyContext.Contract.Operations) 50 { 51 string requestAction = null; 52 foreach (MessageDescription message in operation.Messages) 53 { 54 if (message.Direction == MessageDirection.Input) 55 { 56 requestAction = message.Action; 57 break; 58 } 59 } 60 61 SupportingTokenParameters requirements = new SupportingTokenParameters(); 62 SupportingTokenParameters optionalRequirements = new SupportingTokenParameters(); 63 ICollection<XmlElement> operationBindingAssertions = policyContext.GetOperationBindingAssertions(operation); 64 this.ImportSupportingTokenAssertions(importer, policyContext, operationBindingAssertions, requirements, optionalRequirements); 65 if (requirements.Endorsing.Count > 0 66 || requirements.Signed.Count > 0 67 || requirements.SignedEncrypted.Count > 0 68 || requirements.SignedEndorsing.Count > 0) 69 { 70 if (requestAction != null) 71 { 72 binding.OperationSupportingTokenParameters[requestAction] = requirements; 73 } 74 else 75 { 76 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.CannotImportSupportingTokensForOperationWithoutRequestAction))); 77 } 78 } 79 if (optionalRequirements.Endorsing.Count > 0 80 || optionalRequirements.Signed.Count > 0 81 || optionalRequirements.SignedEncrypted.Count > 0 82 || optionalRequirements.SignedEndorsing.Count > 0) 83 { 84 if (requestAction != null) 85 { 86 binding.OptionalOperationSupportingTokenParameters[requestAction] = optionalRequirements; 87 } 88 else 89 { 90 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.CannotImportSupportingTokensForOperationWithoutRequestAction))); 91 } 92 } 93 } 94 } 95 ImportProtectionAssertions(ICollection<XmlElement> assertions, out MessagePartSpecification signedParts, out MessagePartSpecification encryptedParts)96 void ImportProtectionAssertions(ICollection<XmlElement> assertions, out MessagePartSpecification signedParts, out MessagePartSpecification encryptedParts) 97 { 98 XmlElement assertion; 99 100 signedParts = null; 101 encryptedParts = null; 102 103 WSSecurityPolicy securityPolicy; 104 if (WSSecurityPolicy.TryGetSecurityPolicyDriver(assertions, out securityPolicy)) 105 { 106 if (!securityPolicy.TryImportWsspEncryptedPartsAssertion(assertions, out encryptedParts, out assertion) 107 && assertion != null) 108 { 109 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.UnsupportedSecurityPolicyAssertion, assertion.OuterXml))); 110 } 111 112 if (!securityPolicy.TryImportWsspSignedPartsAssertion(assertions, out signedParts, out assertion) 113 && assertion != null) 114 { 115 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.UnsupportedSecurityPolicyAssertion, assertion.OuterXml))); 116 } 117 } 118 119 if (encryptedParts == null) 120 { 121 encryptedParts = MessagePartSpecification.NoParts; 122 } 123 if (signedParts == null) 124 { 125 signedParts = MessagePartSpecification.NoParts; 126 } 127 } 128 ValidateExistingOrSetNewProtectionLevel(MessagePartDescription part, MessageDescription message, OperationDescription operation, ContractDescription contract, ProtectionLevel newProtectionLevel)129 void ValidateExistingOrSetNewProtectionLevel(MessagePartDescription part, MessageDescription message, OperationDescription operation, ContractDescription contract, ProtectionLevel newProtectionLevel) 130 { 131 ProtectionLevel existingProtectionLevel; 132 133 if (part != null && part.HasProtectionLevel) 134 { 135 existingProtectionLevel = part.ProtectionLevel; 136 } 137 else if (message.HasProtectionLevel) 138 { 139 existingProtectionLevel = message.ProtectionLevel; 140 } 141 else if (operation.HasProtectionLevel) 142 { 143 existingProtectionLevel = operation.ProtectionLevel; 144 } 145 else 146 { 147 if (part != null) 148 { 149 part.ProtectionLevel = newProtectionLevel; 150 } 151 else 152 { 153 message.ProtectionLevel = newProtectionLevel; 154 } 155 existingProtectionLevel = newProtectionLevel; 156 } 157 158 if (existingProtectionLevel != newProtectionLevel) 159 { 160 if (part != null && !part.HasProtectionLevel) 161 { 162 part.ProtectionLevel = newProtectionLevel; 163 } 164 else if (part == null && !message.HasProtectionLevel) 165 { 166 message.ProtectionLevel = newProtectionLevel; 167 } 168 else 169 { 170 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.CannotImportProtectionLevelForContract, contract.Name, contract.Namespace))); 171 } 172 } 173 } 174 AddParts(ref MessagePartSpecification parts1, MessagePartSpecification parts2)175 void AddParts(ref MessagePartSpecification parts1, MessagePartSpecification parts2) 176 { 177 if (parts1 == null) 178 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("parts1")); 179 if (parts2 == null) 180 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("parts2")); 181 182 if (!parts2.IsEmpty()) 183 { 184 if (parts1.IsReadOnly) 185 { 186 MessagePartSpecification p = new MessagePartSpecification(); 187 p.Union(parts1); 188 p.Union(parts2); 189 parts1 = p; 190 } 191 else 192 { 193 parts1.Union(parts2); 194 } 195 } 196 } 197 198 class ContractProtectionLevel 199 { 200 bool hasProtectionRequirements; 201 bool hasUniformProtectionLevel; 202 ProtectionLevel uniformProtectionLevel; 203 ContractProtectionLevel(bool hasProtectionRequirements, bool hasUniformProtectionLevel, ProtectionLevel uniformProtectionLevel)204 public ContractProtectionLevel(bool hasProtectionRequirements, bool hasUniformProtectionLevel, ProtectionLevel uniformProtectionLevel) 205 { 206 this.hasProtectionRequirements = hasProtectionRequirements; 207 this.hasUniformProtectionLevel = hasUniformProtectionLevel; 208 this.uniformProtectionLevel = uniformProtectionLevel; 209 } 210 211 public bool HasProtectionRequirements { get { return this.hasProtectionRequirements; } } 212 public bool HasUniformProtectionLevel { get { return this.hasUniformProtectionLevel; } } 213 public ProtectionLevel UniformProtectionLevel { get { return this.uniformProtectionLevel; } } 214 } 215 ImportMessageScopeProtectionPolicy(MetadataImporter importer, PolicyConversionContext policyContext)216 void ImportMessageScopeProtectionPolicy(MetadataImporter importer, PolicyConversionContext policyContext) 217 { 218 MessagePartSpecification endpointSignedParts; 219 MessagePartSpecification endpointEncryptedParts; 220 bool isContractAssociatedWithAtLeastOneOtherBinding; 221 ContractProtectionLevel otherBindingProtectionLevel = null; 222 bool hasContractProtectionLevel = false; 223 bool isContractProtectionLevelUniform = true; 224 ProtectionLevel contractProtectionLevel = ProtectionLevel.None; 225 226 string contractAssociationName = String.Format("{0}:{1}:{2}", ContractProtectionLevelKey, policyContext.Contract.Name, policyContext.Contract.Namespace); 227 if (importer.State.ContainsKey(contractAssociationName)) 228 { 229 isContractAssociatedWithAtLeastOneOtherBinding = true; 230 otherBindingProtectionLevel = (ContractProtectionLevel)importer.State[contractAssociationName]; 231 } 232 else 233 { 234 isContractAssociatedWithAtLeastOneOtherBinding = false; 235 } 236 237 ICollection<XmlElement> endpointBindingAssertions = policyContext.GetBindingAssertions(); 238 this.ImportProtectionAssertions(endpointBindingAssertions, out endpointSignedParts, out endpointEncryptedParts); 239 240 if (importer.State.ContainsKey(InSecureConversationBootstrapBindingImportMode)) 241 { 242 // when importing secure conversation boostrap binding, add the endpoint scope protection requirements 243 // to the importer state to be consumed in SecurityPolicy11.TryImportWsspBootrstapPolicyAssertion 244 if (endpointEncryptedParts != null) 245 importer.State[SecureConversationBootstrapEncryptionRequirements] = endpointEncryptedParts; 246 if (endpointSignedParts != null) 247 importer.State[SecureConversationBootstrapSignatureRequirements] = endpointSignedParts; 248 } 249 250 foreach (OperationDescription operation in policyContext.Contract.Operations) 251 { 252 MessagePartSpecification operationSignedParts; 253 MessagePartSpecification operationEncryptedParts; 254 255 ICollection<XmlElement> operationBindingAssertions = policyContext.GetOperationBindingAssertions(operation); 256 this.ImportProtectionAssertions(operationBindingAssertions, out operationSignedParts, out operationEncryptedParts); 257 this.AddParts(ref operationSignedParts, endpointSignedParts); 258 this.AddParts(ref operationEncryptedParts, endpointEncryptedParts); 259 260 MessagePartSpecification messageSignedParts; 261 MessagePartSpecification messageEncryptedParts; 262 bool hasProtectionLevel = false; 263 bool isProtectionLevelUniform = true; 264 ProtectionLevel protectionLevel = ProtectionLevel.None; 265 266 // import application message protection requirements 267 foreach (MessageDescription message in operation.Messages) 268 { 269 ICollection<XmlElement> messageBindingAssertions = policyContext.GetMessageBindingAssertions(message); 270 this.ImportProtectionAssertions(messageBindingAssertions, out messageSignedParts, out messageEncryptedParts); 271 this.AddParts(ref messageSignedParts, operationSignedParts); 272 this.AddParts(ref messageEncryptedParts, operationEncryptedParts); 273 274 // validate or set body protection level 275 ProtectionLevel newProtectionLevel = GetProtectionLevel(messageSignedParts.IsBodyIncluded, messageEncryptedParts.IsBodyIncluded, message.Action); 276 if (OperationFormatter.IsValidReturnValue(message.Body.ReturnValue)) 277 { 278 ValidateExistingOrSetNewProtectionLevel(message.Body.ReturnValue, message, operation, policyContext.Contract, newProtectionLevel); 279 } 280 foreach (MessagePartDescription body in message.Body.Parts) 281 { 282 ValidateExistingOrSetNewProtectionLevel(body, message, operation, policyContext.Contract, newProtectionLevel); 283 } 284 if (!OperationFormatter.IsValidReturnValue(message.Body.ReturnValue) || message.Body.Parts.Count == 0) 285 { 286 ValidateExistingOrSetNewProtectionLevel(null, message, operation, policyContext.Contract, newProtectionLevel); 287 } 288 289 if (hasProtectionLevel) 290 { 291 if (protectionLevel != newProtectionLevel) 292 { 293 isProtectionLevelUniform = false; 294 } 295 } 296 else 297 { 298 protectionLevel = newProtectionLevel; 299 hasProtectionLevel = true; 300 } 301 if (hasContractProtectionLevel) 302 { 303 if (contractProtectionLevel != newProtectionLevel) 304 { 305 isContractProtectionLevelUniform = false; 306 } 307 } 308 else 309 { 310 contractProtectionLevel = newProtectionLevel; 311 hasContractProtectionLevel = true; 312 } 313 314 // validate o set header protection level 315 foreach (MessageHeaderDescription header in message.Headers) 316 { 317 bool signed = messageSignedParts.IsHeaderIncluded(header.Name, header.Namespace); 318 bool encrypted = messageEncryptedParts.IsHeaderIncluded(header.Name, header.Namespace); 319 newProtectionLevel = GetProtectionLevel(signed, encrypted, message.Action); 320 ValidateExistingOrSetNewProtectionLevel(header, message, operation, policyContext.Contract, newProtectionLevel); 321 322 if (hasProtectionLevel) 323 { 324 if (protectionLevel != newProtectionLevel) 325 { 326 isProtectionLevelUniform = false; 327 } 328 } 329 else 330 { 331 protectionLevel = newProtectionLevel; 332 hasProtectionLevel = true; 333 } 334 if (hasContractProtectionLevel) 335 { 336 if (contractProtectionLevel != newProtectionLevel) 337 { 338 isContractProtectionLevelUniform = false; 339 } 340 } 341 else 342 { 343 contractProtectionLevel = newProtectionLevel; 344 hasContractProtectionLevel = true; 345 } 346 } 347 } 348 349 // normalize protection level settings at the operation scope if possible to help avoid typed message generation 350 if (hasProtectionLevel && isProtectionLevelUniform) 351 { 352 // (Microsoft) remove the foreach message here 353 // foreach (MessageDescription message in operation.Messages) 354 355 this.ResetProtectionLevelForMessages(operation); 356 357 operation.ProtectionLevel = protectionLevel; 358 } 359 360 // import fault protection requirements 361 foreach (FaultDescription fault in operation.Faults) 362 { 363 ICollection<XmlElement> faultBindingAssertions = policyContext.GetFaultBindingAssertions(fault); 364 this.ImportProtectionAssertions(faultBindingAssertions, out messageSignedParts, out messageEncryptedParts); 365 this.AddParts(ref messageSignedParts, operationSignedParts); 366 this.AddParts(ref messageEncryptedParts, operationEncryptedParts); 367 368 // validate or set fault protection level 369 ProtectionLevel newProtectionLevel = GetProtectionLevel(messageSignedParts.IsBodyIncluded, messageEncryptedParts.IsBodyIncluded, fault.Action); 370 if (fault.HasProtectionLevel) 371 { 372 if (fault.ProtectionLevel != newProtectionLevel) 373 { 374 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.CannotImportProtectionLevelForContract, policyContext.Contract.Name, policyContext.Contract.Namespace))); 375 } 376 } 377 else 378 { 379 fault.ProtectionLevel = newProtectionLevel; 380 } 381 if (hasContractProtectionLevel) 382 { 383 if (contractProtectionLevel != newProtectionLevel) 384 { 385 isContractProtectionLevelUniform = false; 386 } 387 } 388 else 389 { 390 contractProtectionLevel = newProtectionLevel; 391 hasContractProtectionLevel = true; 392 } 393 } 394 } 395 396 if (isContractAssociatedWithAtLeastOneOtherBinding) 397 { 398 if (hasContractProtectionLevel != otherBindingProtectionLevel.HasProtectionRequirements 399 || isContractProtectionLevelUniform != otherBindingProtectionLevel.HasUniformProtectionLevel 400 || contractProtectionLevel != otherBindingProtectionLevel.UniformProtectionLevel) 401 { 402 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.CannotImportProtectionLevelForContract, policyContext.Contract.Name, policyContext.Contract.Namespace))); 403 } 404 } 405 else 406 { 407 if (hasContractProtectionLevel && isContractProtectionLevelUniform && contractProtectionLevel == ProtectionLevel.EncryptAndSign) 408 { 409 // remove all explicitly set protection levels on the contract description, since they are uniform across the contract 410 // and match our binding's default of EncryptAndSign 411 foreach (OperationDescription operation in policyContext.Contract.Operations) 412 { 413 this.ResetProtectionLevelForMessages(operation); 414 foreach (FaultDescription fault in operation.Faults) 415 { 416 fault.ResetProtectionLevel(); 417 } 418 operation.ResetProtectionLevel(); 419 } 420 } 421 importer.State[contractAssociationName] = new ContractProtectionLevel(hasContractProtectionLevel, isContractProtectionLevelUniform, contractProtectionLevel); 422 } 423 } 424 ResetProtectionLevelForMessages(OperationDescription operation)425 void ResetProtectionLevelForMessages(OperationDescription operation) 426 { 427 foreach (MessageDescription message in operation.Messages) 428 { 429 if (OperationFormatter.IsValidReturnValue(message.Body.ReturnValue)) 430 { 431 message.Body.ReturnValue.ResetProtectionLevel(); 432 } 433 foreach (MessagePartDescription body in message.Body.Parts) 434 { 435 body.ResetProtectionLevel(); 436 } 437 foreach (MessageHeaderDescription header in message.Headers) 438 { 439 header.ResetProtectionLevel(); 440 } 441 message.ResetProtectionLevel(); 442 } 443 } 444 GetProtectionLevel(bool signed, bool encrypted, string action)445 static ProtectionLevel GetProtectionLevel(bool signed, bool encrypted, string action) 446 { 447 ProtectionLevel result; 448 449 if (encrypted) 450 { 451 if (signed) 452 { 453 result = ProtectionLevel.EncryptAndSign; 454 } 455 else 456 { 457 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidChannelBindingException(SR.GetString(SR.PolicyRequiresConfidentialityWithoutIntegrity, action))); 458 } 459 } 460 else if (signed) 461 { 462 result = ProtectionLevel.Sign; 463 } 464 else 465 { 466 result = ProtectionLevel.None; 467 } 468 469 return result; 470 } 471 ImportSupportingTokenAssertions(MetadataImporter importer, PolicyConversionContext policyContext, ICollection<XmlElement> assertions, SupportingTokenParameters requirements, SupportingTokenParameters optionalRequirements)472 void ImportSupportingTokenAssertions(MetadataImporter importer, PolicyConversionContext policyContext, ICollection<XmlElement> assertions, SupportingTokenParameters requirements, SupportingTokenParameters optionalRequirements) 473 { 474 WSSecurityPolicy securityPolicy; 475 if (WSSecurityPolicy.TryGetSecurityPolicyDriver(assertions, out securityPolicy)) 476 { 477 securityPolicy.TryImportWsspSupportingTokensAssertion( 478 importer, 479 policyContext, 480 assertions, 481 requirements.Signed, 482 requirements.SignedEncrypted, 483 requirements.Endorsing, 484 requirements.SignedEndorsing, 485 optionalRequirements.Signed, 486 optionalRequirements.SignedEncrypted, 487 optionalRequirements.Endorsing, 488 optionalRequirements.SignedEndorsing); 489 } 490 } 491 ImportEndpointScopeMessageBindingAssertions(MetadataImporter importer, PolicyConversionContext policyContext, SecurityBindingElement binding)492 void ImportEndpointScopeMessageBindingAssertions(MetadataImporter importer, PolicyConversionContext policyContext, SecurityBindingElement binding) 493 { 494 XmlElement assertion = null; 495 496 this.ImportSupportingTokenAssertions(importer, policyContext, policyContext.GetBindingAssertions(), binding.EndpointSupportingTokenParameters, binding.OptionalEndpointSupportingTokenParameters); 497 498 WSSecurityPolicy securityPolicy; 499 if (WSSecurityPolicy.TryGetSecurityPolicyDriver(policyContext.GetBindingAssertions(), out securityPolicy)) 500 { 501 if (!securityPolicy.TryImportWsspWssAssertion(importer, policyContext.GetBindingAssertions(), binding, out assertion) 502 && assertion != null) 503 { 504 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.UnsupportedSecurityPolicyAssertion, assertion.OuterXml))); 505 } 506 507 if (!securityPolicy.TryImportWsspTrustAssertion(importer, policyContext.GetBindingAssertions(), binding, out assertion) 508 && assertion != null) 509 { 510 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.UnsupportedSecurityPolicyAssertion, assertion.OuterXml))); 511 } 512 } 513 514 // 515 // We don't have WSTrust assertion => it is possible we are a BasicHttpBinding 516 // Set the flag here so that later when we tried to compare binding element with basic http binding 517 // we can have an exact match. 518 // 519 if (assertion == null) 520 binding.DoNotEmitTrust = true; 521 } 522 523 TryImportSymmetricSecurityBindingElement(MetadataImporter importer, PolicyConversionContext policyContext, out SecurityBindingElement sbe)524 bool TryImportSymmetricSecurityBindingElement(MetadataImporter importer, PolicyConversionContext policyContext, out SecurityBindingElement sbe) 525 { 526 SymmetricSecurityBindingElement binding = null; 527 XmlElement assertion; 528 WSSecurityPolicy securityPolicy; 529 if (WSSecurityPolicy.TryGetSecurityPolicyDriver(policyContext.GetBindingAssertions(), out securityPolicy)) 530 { 531 if (securityPolicy.TryImportWsspSymmetricBindingAssertion(importer, policyContext, policyContext.GetBindingAssertions(), out binding, out assertion)) 532 { 533 this.ImportEndpointScopeMessageBindingAssertions(importer, policyContext, binding); 534 this.ImportOperationScopeSupportingTokensPolicy(importer, policyContext, binding); 535 this.ImportMessageScopeProtectionPolicy(importer, policyContext); 536 policyContext.BindingElements.Add(binding); 537 } 538 else if (assertion != null) 539 { 540 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.UnsupportedSecurityPolicyAssertion, assertion.OuterXml))); 541 } 542 } 543 544 sbe = binding; 545 return binding != null; 546 } 547 TryImportAsymmetricSecurityBindingElement(MetadataImporter importer, PolicyConversionContext policyContext, out SecurityBindingElement sbe)548 bool TryImportAsymmetricSecurityBindingElement(MetadataImporter importer, PolicyConversionContext policyContext, out SecurityBindingElement sbe) 549 { 550 AsymmetricSecurityBindingElement binding = null; 551 XmlElement assertion; 552 WSSecurityPolicy securityPolicy; 553 if (WSSecurityPolicy.TryGetSecurityPolicyDriver(policyContext.GetBindingAssertions(), out securityPolicy)) 554 { 555 if (securityPolicy.TryImportWsspAsymmetricBindingAssertion(importer, policyContext, policyContext.GetBindingAssertions(), out binding, out assertion)) 556 { 557 this.ImportEndpointScopeMessageBindingAssertions(importer, policyContext, binding); 558 this.ImportOperationScopeSupportingTokensPolicy(importer, policyContext, binding); 559 this.ImportMessageScopeProtectionPolicy(importer, policyContext); 560 policyContext.BindingElements.Add(binding); 561 } 562 else if (assertion != null) 563 { 564 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.UnsupportedSecurityPolicyAssertion, assertion.OuterXml))); 565 } 566 } 567 568 sbe = binding; 569 return binding != null; 570 } 571 572 // isDualSecurityModeOnly is true if the binding has both message security and https security enabled. TryImportTransportSecurityBindingElement(MetadataImporter importer, PolicyConversionContext policyContext, out SecurityBindingElement sbe, bool isDualSecurityModeOnly)573 bool TryImportTransportSecurityBindingElement(MetadataImporter importer, PolicyConversionContext policyContext, out SecurityBindingElement sbe, bool isDualSecurityModeOnly) 574 { 575 TransportSecurityBindingElement binding = null; 576 XmlElement assertion; 577 sbe = null; 578 579 WSSecurityPolicy securityPolicy; 580 if (WSSecurityPolicy.TryGetSecurityPolicyDriver(policyContext.GetBindingAssertions(), out securityPolicy)) 581 { 582 if (securityPolicy.TryImportWsspTransportBindingAssertion(importer, policyContext.GetBindingAssertions(), out binding, out assertion)) 583 { 584 this.ImportEndpointScopeMessageBindingAssertions(importer, policyContext, binding); 585 586 // If it is not DualSecurityMode then it is Mixed mode. So we need to look for supporting tokens in the binding. 587 if (!isDualSecurityModeOnly) 588 { 589 this.ImportOperationScopeSupportingTokensPolicy(importer, policyContext, binding); 590 if (importer.State.ContainsKey(InSecureConversationBootstrapBindingImportMode)) 591 { 592 this.ImportMessageScopeProtectionPolicy(importer, policyContext); 593 } 594 595 if (HasSupportingTokens(binding) || binding.IncludeTimestamp) 596 { 597 sbe = binding; 598 policyContext.BindingElements.Add(binding); 599 } 600 } 601 } 602 else if (assertion != null) 603 { 604 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.UnsupportedSecurityPolicyAssertion, assertion.OuterXml))); 605 } 606 } 607 608 return binding != null; 609 } 610 611 HasSupportingTokens(SecurityBindingElement binding)612 static bool HasSupportingTokens(SecurityBindingElement binding) 613 { 614 if (binding.EndpointSupportingTokenParameters.Endorsing.Count > 0 615 || binding.EndpointSupportingTokenParameters.SignedEndorsing.Count > 0 616 || binding.EndpointSupportingTokenParameters.SignedEncrypted.Count > 0 617 || binding.EndpointSupportingTokenParameters.Signed.Count > 0) 618 { 619 return true; 620 } 621 622 foreach (SupportingTokenParameters r in binding.OperationSupportingTokenParameters.Values) 623 { 624 if (r.Endorsing.Count > 0 625 || r.SignedEndorsing.Count > 0 626 || r.SignedEncrypted.Count > 0 627 || r.Signed.Count > 0) 628 { 629 return true; 630 } 631 } 632 633 return false; 634 } 635 IPolicyImportExtension.ImportPolicy(MetadataImporter importer, PolicyConversionContext policyContext)636 void IPolicyImportExtension.ImportPolicy(MetadataImporter importer, PolicyConversionContext policyContext) 637 { 638 if (importer == null) 639 { 640 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("importer"); 641 } 642 if (policyContext == null) 643 { 644 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("policyContext"); 645 } 646 WSSecurityPolicy securityPolicy; 647 if (WSSecurityPolicy.TryGetSecurityPolicyDriver(policyContext.GetBindingAssertions(), out securityPolicy)) 648 { 649 if ((importer.State != null) && (!importer.State.ContainsKey(MaxPolicyRedirectionsKey))) 650 { 651 importer.State.Add(MaxPolicyRedirectionsKey, this.MaxPolicyRedirections); 652 } 653 654 SecurityBindingElement sbe = null; 655 bool success = this.TryImportSymmetricSecurityBindingElement(importer, policyContext, out sbe); 656 if (!success) 657 { 658 success = this.TryImportAsymmetricSecurityBindingElement(importer, policyContext, out sbe); 659 } 660 if (!success) 661 { 662 success = this.TryImportTransportSecurityBindingElement(importer, policyContext, out sbe, false); 663 } 664 else 665 { 666 // We already have found and imported the message security binding element above. Hence this could be the dual mode security. 667 // Now let us see if there is HttpsTransportBinding assertion also below it .This is to avoid the 668 // warning messages while importing wsdl representing the message security over Https transport security scenario. See Bug:136416. 669 670 SecurityBindingElement tbe = null; 671 this.TryImportTransportSecurityBindingElement(importer, policyContext, out tbe, true); 672 } 673 674 if (sbe != null) 675 { 676 SecurityElement config = new SecurityElement(); 677 config.InitializeFrom(sbe, false); 678 if (config.HasImportFailed) 679 { 680 #pragma warning suppress 56506 681 importer.Errors.Add(new MetadataConversionError(SR.GetString(SR.SecurityBindingElementCannotBeExpressedInConfig), true)); 682 } 683 } 684 } 685 } 686 } 687 } 688