// // SecurityBindingElementTest.cs // // Author: // Atsushi Enomoto // // Copyright (C) 2006 Novell, Inc. http://www.novell.com // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Net; using System.Net.Security; using System.Security.Cryptography.X509Certificates; using System.IdentityModel.Selectors; using System.IdentityModel.Tokens; using System.ServiceModel; using System.ServiceModel.Channels; using System.ServiceModel.Description; using System.ServiceModel.Security; using System.ServiceModel.Security.Tokens; using System.Xml; using NUnit.Framework; using MonoTests.Helpers; namespace MonoTests.System.ServiceModel.Channels { [TestFixture] public class SecurityBindingElementTest { #region Factory methods [Test] public void CreateAnonymousForCertificateBindingElement () { SymmetricSecurityBindingElement be = SecurityBindingElement.CreateAnonymousForCertificateBindingElement (); SecurityAssert.AssertSymmetricSecurityBindingElement ( SecurityAlgorithmSuite.Default, true, // IncludeTimestamp SecurityKeyEntropyMode.CombinedEntropy, MessageProtectionOrder.SignBeforeEncryptAndEncryptSignature, MessageSecurityVersion.Default, true, // RequireSignatureConfirmation SecurityHeaderLayout.Strict, // EndpointSupportingTokenParameters: endorsing, signed, signedEncrypted, signedEndorsing (by count) 0, 0, 0, 0, // ProtectionTokenParameters true, SecurityTokenInclusionMode.Never, SecurityTokenReferenceStyle.Internal, true, // LocalClientSettings true, 60, true, be, ""); // test ProtectionTokenParameters X509SecurityTokenParameters tp = be.ProtectionTokenParameters as X509SecurityTokenParameters; Assert.IsNotNull (tp, "#2-1"); SecurityAssert.AssertSecurityTokenParameters ( SecurityTokenInclusionMode.Never, SecurityTokenReferenceStyle.Internal, true, tp, "Protection"); Assert.AreEqual (X509KeyIdentifierClauseType.Thumbprint, tp.X509ReferenceStyle, "#2-2"); } [Test] public void CreateIssuedTokenBindingElement1 () { IssuedSecurityTokenParameters tp = new IssuedSecurityTokenParameters (); SymmetricSecurityBindingElement be = SecurityBindingElement.CreateIssuedTokenBindingElement (tp); SecurityAssert.AssertSymmetricSecurityBindingElement ( SecurityAlgorithmSuite.Default, true, // IncludeTimestamp SecurityKeyEntropyMode.CombinedEntropy, MessageProtectionOrder.SignBeforeEncryptAndEncryptSignature, MessageSecurityVersion.Default, false, // RequireSignatureConfirmation SecurityHeaderLayout.Strict, // EndpointSupportingTokenParameters: endorsing, signed, signedEncrypted, signedEndorsing (by count) 0, 0, 0, 0, // ProtectionTokenParameters true, SecurityTokenInclusionMode.AlwaysToRecipient, SecurityTokenReferenceStyle.Internal, true, // LocalClientSettings true, 60, true, be, ""); // test ProtectionTokenParameters Assert.AreEqual (tp, be.ProtectionTokenParameters, "#2-1"); SecurityAssert.AssertSecurityTokenParameters ( SecurityTokenInclusionMode.AlwaysToRecipient, SecurityTokenReferenceStyle.Internal, true, tp, "Protection"); } [Test] public void CreateIssuedTokenForCertificateBindingElement1 () { IssuedSecurityTokenParameters tp = new IssuedSecurityTokenParameters (); SymmetricSecurityBindingElement be = SecurityBindingElement.CreateIssuedTokenForCertificateBindingElement (tp); SecurityAssert.AssertSymmetricSecurityBindingElement ( SecurityAlgorithmSuite.Default, true, // IncludeTimestamp SecurityKeyEntropyMode.CombinedEntropy, MessageProtectionOrder.SignBeforeEncryptAndEncryptSignature, MessageSecurityVersion.Default, true, // RequireSignatureConfirmation SecurityHeaderLayout.Strict, // EndpointSupportingTokenParameters: endorsing, signed, signedEncrypted, signedEndorsing (by count) 1, 0, 0, 0, // ProtectionTokenParameters true, SecurityTokenInclusionMode.Never, SecurityTokenReferenceStyle.Internal, true, // LocalClientSettings true, 60, true, be, ""); // test ProtectionTokenParameters X509SecurityTokenParameters ptp = be.ProtectionTokenParameters as X509SecurityTokenParameters; Assert.IsNotNull (ptp, "#2-1"); SecurityAssert.AssertSecurityTokenParameters ( SecurityTokenInclusionMode.Never, SecurityTokenReferenceStyle.Internal, true, ptp, "Protection"); Assert.AreEqual (X509KeyIdentifierClauseType.Thumbprint, ptp.X509ReferenceStyle, "#2-2"); Assert.AreEqual (tp, be.EndpointSupportingTokenParameters.Endorsing [0], "EndpointParams.Endorsing[0]"); } [Test] public void CreateIssuedTokenForSslBindingElement1 () { IssuedSecurityTokenParameters tp = new IssuedSecurityTokenParameters (); SymmetricSecurityBindingElement be = SecurityBindingElement.CreateIssuedTokenForSslBindingElement (tp); SecurityAssert.AssertSymmetricSecurityBindingElement ( SecurityAlgorithmSuite.Default, true, // IncludeTimestamp SecurityKeyEntropyMode.CombinedEntropy, MessageProtectionOrder.SignBeforeEncryptAndEncryptSignature, MessageSecurityVersion.Default, true, // RequireSignatureConfirmation SecurityHeaderLayout.Strict, // EndpointSupportingTokenParameters: endorsing, signed, signedEncrypted, signedEndorsing (by count) 1, 0, 0, 0, // ProtectionTokenParameters true, SecurityTokenInclusionMode.AlwaysToRecipient, SecurityTokenReferenceStyle.Internal, true, // LocalClientSettings true, 60, true, be, ""); Assert.AreEqual (tp, be.EndpointSupportingTokenParameters.Endorsing [0], "EndpointParams.Endorsing[0]"); // FIXME: test ProtectionTokenParameters } [Test] public void CreateKerberosBindingElement () { SymmetricSecurityBindingElement be = SecurityBindingElement.CreateKerberosBindingElement (); SecurityAssert.AssertSymmetricSecurityBindingElement ( SecurityAlgorithmSuite.Basic128, true, // IncludeTimestamp SecurityKeyEntropyMode.CombinedEntropy, MessageProtectionOrder.SignBeforeEncryptAndEncryptSignature, MessageSecurityVersion.Default, false, // RequireSignatureConfirmation SecurityHeaderLayout.Strict, // EndpointSupportingTokenParameters: endorsing, signed, signedEncrypted, signedEndorsing (by count) 0, 0, 0, 0, // ProtectionTokenParameters true, SecurityTokenInclusionMode.Once, SecurityTokenReferenceStyle.Internal, true, // LocalClientSettings true, 60, true, be, ""); // FIXME: test ProtectionTokenParameters } [Test] public void CreateSslNegotiationBindingElement () { SymmetricSecurityBindingElement be = SecurityBindingElement.CreateSslNegotiationBindingElement (true, true); SecurityAssert.AssertSymmetricSecurityBindingElement ( SecurityAlgorithmSuite.Default, true, // IncludeTimestamp SecurityKeyEntropyMode.CombinedEntropy, MessageProtectionOrder.SignBeforeEncryptAndEncryptSignature, MessageSecurityVersion.Default, false, // RequireSignatureConfirmation SecurityHeaderLayout.Strict, // EndpointSupportingTokenParameters: endorsing, signed, signedEncrypted, signedEndorsing (by count) 0, 0, 0, 0, // ProtectionTokenParameters true, SecurityTokenInclusionMode.AlwaysToRecipient, SecurityTokenReferenceStyle.Internal, true, // LocalClientSettings true, 60, true, be, ""); // FIXME: also try different constructor arguments // test ProtectionTokenParameters Assert.AreEqual (typeof (SslSecurityTokenParameters), be.ProtectionTokenParameters.GetType (), "#1"); SslSecurityTokenParameters sp = be.ProtectionTokenParameters as SslSecurityTokenParameters; Assert.AreEqual (true, sp.RequireCancellation, "#2"); Assert.AreEqual (true, sp.RequireClientCertificate, "#3"); } [Test] public void CreateSspiNegotiationBindingElement () { SymmetricSecurityBindingElement be = SecurityBindingElement.CreateSspiNegotiationBindingElement (); SecurityAssert.AssertSymmetricSecurityBindingElement ( SecurityAlgorithmSuite.Default, true, // IncludeTimestamp SecurityKeyEntropyMode.CombinedEntropy, MessageProtectionOrder.SignBeforeEncryptAndEncryptSignature, MessageSecurityVersion.Default, false, // RequireSignatureConfirmation SecurityHeaderLayout.Strict, // EndpointSupportingTokenParameters: endorsing, signed, signedEncrypted, signedEndorsing (by count) 0, 0, 0, 0, // ProtectionTokenParameters true, SecurityTokenInclusionMode.AlwaysToRecipient, SecurityTokenReferenceStyle.Internal, true, // LocalClientSettings true, 60, true, be, ""); // FIXME: Try boolean argument as well. // FIXME: test ProtectionTokenParameters } [Test] public void CreateUserNameForCertificateBindingElement () { SymmetricSecurityBindingElement be = SecurityBindingElement.CreateUserNameForCertificateBindingElement (); SecurityAssert.AssertSymmetricSecurityBindingElement ( SecurityAlgorithmSuite.Default, true, // IncludeTimestamp SecurityKeyEntropyMode.CombinedEntropy, MessageProtectionOrder.SignBeforeEncryptAndEncryptSignature, MessageSecurityVersion.Default, false, // RequireSignatureConfirmation SecurityHeaderLayout.Strict, // EndpointSupportingTokenParameters: endorsing, signed, signedEncrypted, signedEndorsing (by count) 0, 0, 1, 0, // ProtectionTokenParameters true, SecurityTokenInclusionMode.Never, SecurityTokenReferenceStyle.Internal, true, // LocalClientSettings true, 60, true, be, ""); UserNameSecurityTokenParameters up = be.EndpointSupportingTokenParameters.SignedEncrypted [0] as UserNameSecurityTokenParameters; // FIXME: test it // FIXME: test ProtectionTokenParameters } [Test] public void CreateUserNameForSslBindingElement () { SymmetricSecurityBindingElement be = SecurityBindingElement.CreateUserNameForSslBindingElement (); SecurityAssert.AssertSymmetricSecurityBindingElement ( SecurityAlgorithmSuite.Default, true, // IncludeTimestamp SecurityKeyEntropyMode.CombinedEntropy, MessageProtectionOrder.SignBeforeEncryptAndEncryptSignature, MessageSecurityVersion.Default, false, // RequireSignatureConfirmation SecurityHeaderLayout.Strict, // EndpointSupportingTokenParameters: endorsing, signed, signedEncrypted, signedEndorsing (by count) 0, 0, 1, 0, // ProtectionTokenParameters true, SecurityTokenInclusionMode.AlwaysToRecipient, SecurityTokenReferenceStyle.Internal, true, // LocalClientSettings true, 60, true, be, ""); UserNameSecurityTokenParameters up = be.EndpointSupportingTokenParameters.SignedEncrypted [0] as UserNameSecurityTokenParameters; // FIXME: test it // FIXME: test ProtectionTokenParameters } // non-symmetric return value by definition, but still // returns symmetric binding elements. [Test] public void CreateSecureConversationBindingElement () { SymmetricSecurityBindingElement be = SecurityBindingElement.CreateSecureConversationBindingElement (new SymmetricSecurityBindingElement ()) as SymmetricSecurityBindingElement; SecurityAssert.AssertSymmetricSecurityBindingElement ( SecurityAlgorithmSuite.Default, true, // IncludeTimestamp SecurityKeyEntropyMode.CombinedEntropy, MessageProtectionOrder.SignBeforeEncryptAndEncryptSignature, MessageSecurityVersion.Default, false, // RequireSignatureConfirmation SecurityHeaderLayout.Strict, // EndpointSupportingTokenParameters: endorsing, signed, signedEncrypted, signedEndorsing (by count) 0, 0, 0, 0, // ProtectionTokenParameters true, SecurityTokenInclusionMode.AlwaysToRecipient, SecurityTokenReferenceStyle.Internal, true, // LocalClientSettings true, 60, true, be, ""); // test ProtectionTokenParameters SecureConversationSecurityTokenParameters tp = be.ProtectionTokenParameters as SecureConversationSecurityTokenParameters; Assert.IsNotNull (tp, "#2-1"); SecurityAssert.AssertSecurityTokenParameters ( SecurityTokenInclusionMode.AlwaysToRecipient, SecurityTokenReferenceStyle.Internal, true, tp, "Protection"); } #endregion [Test] public void SetKeyDerivation () { SetKeyDerivationCorrect (new TransportSecurityBindingElement (), "transport"); SetKeyDerivationIncorrect (new TransportSecurityBindingElement (), "transport"); SetKeyDerivationCorrect (new SymmetricSecurityBindingElement (), "symmetric"); SetKeyDerivationIncorrect (new SymmetricSecurityBindingElement (), "symmetric"); SetKeyDerivationCorrect (new AsymmetricSecurityBindingElement (), "asymmetric"); SetKeyDerivationIncorrect (new AsymmetricSecurityBindingElement (), "asymmetric"); } void SetKeyDerivationCorrect (SecurityBindingElement be, string label) { X509SecurityTokenParameters p, p2; p = new X509SecurityTokenParameters (); p2 = new X509SecurityTokenParameters (); Assert.AreEqual (true, p.RequireDerivedKeys, label + "#1"); Assert.AreEqual (true, p2.RequireDerivedKeys, label + "#2"); be.EndpointSupportingTokenParameters.Endorsing.Add (p); be.EndpointSupportingTokenParameters.Endorsing.Add (p2); be.SetKeyDerivation (false); Assert.AreEqual (false, p.RequireDerivedKeys, label + "#3"); Assert.AreEqual (false, p2.RequireDerivedKeys, label + "#4"); } void SetKeyDerivationIncorrect (SecurityBindingElement be, string label) { X509SecurityTokenParameters p, p2; p = new X509SecurityTokenParameters (); p2 = new X509SecurityTokenParameters (); // setting in prior - makes no sense be.SetKeyDerivation (false); be.EndpointSupportingTokenParameters.Endorsing.Add (p); be.EndpointSupportingTokenParameters.Endorsing.Add (p2); Assert.AreEqual (true, p.RequireDerivedKeys, label + "#5"); Assert.AreEqual (true, p2.RequireDerivedKeys, label + "#6"); } [Test] [ExpectedException (typeof (ArgumentException))] [Category ("NotWorking")] public void CheckDuplicateAuthenticatorTypesClient () { SymmetricSecurityBindingElement be = new SymmetricSecurityBindingElement (); be.ProtectionTokenParameters = new X509SecurityTokenParameters (); be.EndpointSupportingTokenParameters.Endorsing.Add ( new X509SecurityTokenParameters ()); // This causes multiple supporting token authenticator // of the same type. be.OptionalEndpointSupportingTokenParameters.Endorsing.Add ( new X509SecurityTokenParameters ()); Binding b = new CustomBinding (be, new HttpTransportBindingElement ()); ClientCredentials cred = new ClientCredentials (); cred.ClientCertificate.Certificate = new X509Certificate2 ("Test/Resources/test.pfx", "mono"); IChannelFactory ch = b.BuildChannelFactory (new Uri ("http://localhost:" + NetworkHelpers.FindFreePort ()), cred); try { ch.Open (); } finally { if (ch.State == CommunicationState.Closed) ch.Close (); } } [Test] [ExpectedException (typeof (ArgumentException))] [Category ("NotWorking")] public void CheckDuplicateAuthenticatorTypesService () { SymmetricSecurityBindingElement be = new SymmetricSecurityBindingElement (); be.ProtectionTokenParameters = new X509SecurityTokenParameters (); be.EndpointSupportingTokenParameters.Endorsing.Add ( new X509SecurityTokenParameters ()); // This causes multiple supporting token authenticator // of the same type. be.OptionalEndpointSupportingTokenParameters.Endorsing.Add ( new X509SecurityTokenParameters ()); Binding b = new CustomBinding (be, new HttpTransportBindingElement ()); ServiceCredentials cred = new ServiceCredentials (); cred.ServiceCertificate.Certificate = new X509Certificate2 ("Test/Resources/test.pfx", "mono"); IChannelListener ch = b.BuildChannelListener (new Uri ("http://localhost:" + NetworkHelpers.FindFreePort ()), cred); try { ch.Open (); } finally { if (ch.State == CommunicationState.Closed) ch.Close (); } } [Test] [ExpectedException (typeof (InvalidOperationException))] [Category ("NotWorking")] public void NonEndorsibleParameterInEndorsingSupport () { SymmetricSecurityBindingElement be = new SymmetricSecurityBindingElement (); be.ProtectionTokenParameters = new X509SecurityTokenParameters (); be.EndpointSupportingTokenParameters.Endorsing.Add ( new UserNameSecurityTokenParameters ()); Binding b = new CustomBinding (be, new HttpTransportBindingElement ()); X509Certificate2 cert = new X509Certificate2 ("Test/Resources/test.pfx", "mono"); EndpointAddress ea = new EndpointAddress (new Uri ("http://localhost:" + NetworkHelpers.FindFreePort ()), new X509CertificateEndpointIdentity (cert)); CalcProxy client = new CalcProxy (b, ea); client.ClientCredentials.UserName.UserName = "rupert"; client.Sum (1, 2); } void AssertSecurityCapabilities ( ProtectionLevel request, ProtectionLevel response, bool supportsClientAuth, bool supportsClientWinId, bool supportsServerAuth, ISecurityCapabilities c, string label) { Assert.AreEqual (request, c.SupportedRequestProtectionLevel, label + ".request"); Assert.AreEqual (response, c.SupportedResponseProtectionLevel, label + ".response"); Assert.AreEqual (supportsClientAuth, c.SupportsClientAuthentication, label + ".client-auth"); Assert.AreEqual (supportsClientWinId, c.SupportsClientWindowsIdentity, label + ".client-identity"); Assert.AreEqual (supportsServerAuth, c.SupportsServerAuthentication, label + ".server-auth"); } ISecurityCapabilities GetSecurityCapabilities (SecurityBindingElement be) { BindingContext bc = new BindingContext ( new CustomBinding (), new BindingParameterCollection ()); return be.GetProperty (bc); } [Test] [ExpectedException (typeof (ArgumentNullException))] public void GetPropertyNullBindingContext1 () { new SymmetricSecurityBindingElement () .GetProperty (null); } [Test] [ExpectedException (typeof (ArgumentNullException))] public void GetPropertyNullBindingContext2 () { new AsymmetricSecurityBindingElement () .GetProperty (null); } [Test] public void GetPropertySecurityCapabilities () { ISecurityCapabilities c; RsaSecurityTokenParameters rsa = new RsaSecurityTokenParameters (); UserNameSecurityTokenParameters user = new UserNameSecurityTokenParameters (); X509SecurityTokenParameters x509 = new X509SecurityTokenParameters (); SecureConversationSecurityTokenParameters sc1 = new SecureConversationSecurityTokenParameters (); sc1.BootstrapSecurityBindingElement = new SymmetricSecurityBindingElement (); // empty SecureConversationSecurityTokenParameters sc2 = new SecureConversationSecurityTokenParameters (); sc2.BootstrapSecurityBindingElement = new SymmetricSecurityBindingElement (x509); SecureConversationSecurityTokenParameters sc3 = new SecureConversationSecurityTokenParameters (); sc3.BootstrapSecurityBindingElement = new AsymmetricSecurityBindingElement (null, x509); SecureConversationSecurityTokenParameters sc4 = new SecureConversationSecurityTokenParameters (); sc4.BootstrapSecurityBindingElement = new AsymmetricSecurityBindingElement (x509, null); // no parameters c = GetSecurityCapabilities ( new SymmetricSecurityBindingElement ()); AssertSecurityCapabilities ( ProtectionLevel.EncryptAndSign, ProtectionLevel.EncryptAndSign, false, false, false, c, "#1"); // x509 parameters for both c = GetSecurityCapabilities ( new SymmetricSecurityBindingElement (x509)); AssertSecurityCapabilities ( ProtectionLevel.EncryptAndSign, ProtectionLevel.EncryptAndSign, true, true, true, c, "#2"); // no initiator parameters c = GetSecurityCapabilities ( new AsymmetricSecurityBindingElement (x509, null)); AssertSecurityCapabilities ( ProtectionLevel.EncryptAndSign, ProtectionLevel.EncryptAndSign, false, false, true, c, "#3"); // no recipient parameters c = GetSecurityCapabilities ( new AsymmetricSecurityBindingElement (null, x509)); AssertSecurityCapabilities ( ProtectionLevel.EncryptAndSign, ProtectionLevel.EncryptAndSign, true, true, false, c, "#4"); // initiator does not support identity c = GetSecurityCapabilities ( new AsymmetricSecurityBindingElement (x509, rsa)); AssertSecurityCapabilities ( ProtectionLevel.EncryptAndSign, ProtectionLevel.EncryptAndSign, true, false, true, c, "#5"); // recipient does not support server auth c = GetSecurityCapabilities ( new AsymmetricSecurityBindingElement (user, x509)); AssertSecurityCapabilities ( ProtectionLevel.EncryptAndSign, ProtectionLevel.EncryptAndSign, true, true, false, c, "#6"); // secureconv with no symm. bootstrap params c = GetSecurityCapabilities ( new SymmetricSecurityBindingElement (sc1)); AssertSecurityCapabilities ( ProtectionLevel.EncryptAndSign, ProtectionLevel.EncryptAndSign, false, false, false, c, "#7"); // secureconv with x509 symm. bootstrap params c = GetSecurityCapabilities ( new SymmetricSecurityBindingElement (sc2)); AssertSecurityCapabilities ( ProtectionLevel.EncryptAndSign, ProtectionLevel.EncryptAndSign, true, true, true, c, "#8"); // secureconv with x509 initiator bootstrap params c = GetSecurityCapabilities ( new SymmetricSecurityBindingElement (sc3)); AssertSecurityCapabilities ( ProtectionLevel.EncryptAndSign, ProtectionLevel.EncryptAndSign, true, true, false, c, "#9"); // secureconv with x509 recipient bootstrap params c = GetSecurityCapabilities ( new SymmetricSecurityBindingElement (sc4)); AssertSecurityCapabilities ( ProtectionLevel.EncryptAndSign, ProtectionLevel.EncryptAndSign, false, false, true, c, "#10"); // FIXME: find out such cases that returns other ProtectionLevel values. } } }