diff --git a/src/System.Private.ServiceModel/tests/Scenarios/Binding/WS/TransportWithMessageCredentialSecurity/BasicHttpTransportWithMessageCredentialSecurityTests.cs b/src/System.Private.ServiceModel/tests/Scenarios/Binding/WS/TransportWithMessageCredentialSecurity/BasicHttpTransportWithMessageCredentialSecurityTests.cs index 3d497e65706..e01fd5ebe9a 100644 --- a/src/System.Private.ServiceModel/tests/Scenarios/Binding/WS/TransportWithMessageCredentialSecurity/BasicHttpTransportWithMessageCredentialSecurityTests.cs +++ b/src/System.Private.ServiceModel/tests/Scenarios/Binding/WS/TransportWithMessageCredentialSecurity/BasicHttpTransportWithMessageCredentialSecurityTests.cs @@ -1,6 +1,7 @@ using System; using System.Security.Cryptography.X509Certificates; using System.ServiceModel; +using System.ServiceModel.Channels; using Infrastructure.Common; using Xunit; @@ -151,4 +152,66 @@ public static void Https_SecModeTransWithMessCred_UserNameClientCredential_Succe ScenarioTestHelpers.CloseCommunicationObjects((ICommunicationObject)serviceProxy, factory); } } + + [WcfTheory] + [Condition(nameof(Root_Certificate_Installed), + nameof(SSL_Available))] + [OuterLoop] + [InlineData(true)] + [InlineData(false)] + public static void Https_InvalidClientCredential_EnableUnsecuredResponse_DifferentException(bool enableUnsecuredResponse) + { + EndpointAddress endpointAddress = null; + string testString = "Hello"; + string username = null; + string password = null; + ChannelFactory factory = null; + IWcfService serviceProxy = null; + TransferMode transferMode = TransferMode.Buffered; + try + { + // *** SETUP *** \\ + TextMessageEncodingBindingElement textEncoding = new TextMessageEncodingBindingElement { MessageVersion = MessageVersion.Soap11 }; + HttpsTransportBindingElement httpsTransport = new HttpsTransportBindingElement() { TransferMode = transferMode }; + TransportSecurityBindingElement sec = SecurityBindingElement.CreateUserNameOverTransportBindingElement(); + sec.EnableUnsecuredResponse = enableUnsecuredResponse; + CustomBinding customBinding = new CustomBinding(sec, textEncoding, httpsTransport); + endpointAddress = new EndpointAddress(new Uri(Endpoints.BasicHttps_SecModeTransWithMessCred_ClientCredTypeUserName + $"/{Enum.GetName(typeof(TransferMode), transferMode)}")); + factory = new ChannelFactory(customBinding, endpointAddress); + username = Guid.NewGuid().ToString("n").Substring(0, 8); + char[] usernameArr = username.ToCharArray(); + Array.Reverse(usernameArr); + password = new string(usernameArr); + factory.Credentials.UserName.UserName = username; + factory.Credentials.UserName.Password = password + "1";//invalid password + + serviceProxy = factory.CreateChannel(); + + // *** EXECUTE *** \\ + string result = serviceProxy.Echo(testString); + + // *** VALIDATE *** \\ + Assert.Fail("should throw exception earlier"); + + // *** CLEANUP *** \\ + ((ICommunicationObject)serviceProxy).Close(); + factory.Close(); + } + catch (Exception ex) + { + if (enableUnsecuredResponse) + { + Assert.True(ex is System.ServiceModel.Security.SecurityAccessDeniedException); + } + else + { + Assert.True(ex is System.ServiceModel.Security.MessageSecurityException); + } + } + finally + { + // *** ENSURE CLEANUP *** \\ + ScenarioTestHelpers.CloseCommunicationObjects((ICommunicationObject)serviceProxy, factory); + } + } } diff --git a/src/System.ServiceModel.Primitives/ref/System.ServiceModel.Security.cs b/src/System.ServiceModel.Primitives/ref/System.ServiceModel.Security.cs index 06c34623f95..81ad720ecd0 100644 --- a/src/System.ServiceModel.Primitives/ref/System.ServiceModel.Security.cs +++ b/src/System.ServiceModel.Primitives/ref/System.ServiceModel.Security.cs @@ -89,6 +89,7 @@ internal SecurityBindingElement() { } public override T GetProperty(System.ServiceModel.Channels.BindingContext context) { return default; } public override string ToString() { return default; } public System.ServiceModel.Security.SecurityKeyEntropyMode KeyEntropyMode { get { return default;} set { } } + public bool EnableUnsecuredResponse { get { return default; } set { } } } public enum SecurityHeaderLayout { diff --git a/src/System.ServiceModel.Security/tests/ServiceModel/SecutityBindingElementTest.cs b/src/System.ServiceModel.Security/tests/ServiceModel/SecutityBindingElementTest.cs index 54dd1e90a6f..aa2022041c7 100644 --- a/src/System.ServiceModel.Security/tests/ServiceModel/SecutityBindingElementTest.cs +++ b/src/System.ServiceModel.Security/tests/ServiceModel/SecutityBindingElementTest.cs @@ -43,6 +43,22 @@ public static void Property_KeyEntropyMode() Assert.Equal(SecurityKeyEntropyMode.CombinedEntropy, securityBindingElement.KeyEntropyMode); } + [WcfFact] + public static void Property_EnableUnsecuredResponse() + { + //default value in derived class + TransportSecurityBindingElement securityBindingElement = new TransportSecurityBindingElement(); + Assert.False(securityBindingElement.EnableUnsecuredResponse); + + //initializable from derived class ctor + securityBindingElement = new TransportSecurityBindingElement() { EnableUnsecuredResponse = true}; + Assert.True(securityBindingElement.EnableUnsecuredResponse); + + //property settable + securityBindingElement.EnableUnsecuredResponse = false; + Assert.False(securityBindingElement.EnableUnsecuredResponse); + } + [WcfFact] public static void Method_CreateIssuedTokenOverTransportBindingElement() {