From e8ec2d6b4950d60142fc4e58cbbae34d032fe916 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torben=20K=C3=B6nke?= Date: Mon, 12 Jun 2017 01:30:36 +0200 Subject: [PATCH] provider model --- Properties/AssemblyInfo.cs | 4 +-- SaslConfiguration.cs | 2 +- SaslFactory.cs | 51 ++++++++++++++++++++++++++------------ SaslMechanism.cs | 4 +-- Tests/SrpTest.cs | 13 +++++----- 5 files changed, 46 insertions(+), 28 deletions(-) diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs index 9ea4708..1ef82c9 100644 --- a/Properties/AssemblyInfo.cs +++ b/Properties/AssemblyInfo.cs @@ -32,5 +32,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: AssemblyVersion("1.0.0.1")] +[assembly: AssemblyFileVersion("1.0.0.1")] diff --git a/SaslConfiguration.cs b/SaslConfiguration.cs index 7825bbe..403d88d 100644 --- a/SaslConfiguration.cs +++ b/SaslConfiguration.cs @@ -11,7 +11,7 @@ public class SaslConfigurationSection : ConfigurationSection { /// saslProvider elements. /// [ConfigurationProperty("saslProviders", IsRequired = false, - IsKey = false, IsDefaultCollection = true)] + IsKey = false, IsDefaultCollection = false)] public SaslProviderCollection SaslProviders { get { return ((SaslProviderCollection) base["saslProviders"]); diff --git a/SaslFactory.cs b/SaslFactory.cs index 53bb942..9e4a085 100644 --- a/SaslFactory.cs +++ b/SaslFactory.cs @@ -1,19 +1,29 @@ using System; using System.Collections.Generic; +using System.Configuration; namespace S22.Sasl { /// /// A factory class for producing instances of Sasl mechanisms. /// - internal static class SaslFactory { + public static class SaslFactory { /// /// A dictionary of Sasl mechanisms registered with the factory class. /// - static Dictionary Mechanisms { + static Dictionary mechanisms { get; set; } + /// + /// A list of the names of all available mechanisms. + /// + public static IEnumerable Mechanisms { + get { + return mechanisms.Keys; + } + } + /// /// Creates an instance of the Sasl mechanism with the specified /// name. @@ -26,11 +36,11 @@ internal static class SaslFactory { /// specified name is not registered with Sasl.SaslFactory. public static SaslMechanism Create(string name) { name.ThrowIfNull("name"); - if (!Mechanisms.ContainsKey(name)) { + if (!mechanisms.ContainsKey(name)) { throw new SaslException("A Sasl mechanism with the specified name " + "is not registered with Sasl.SaslFactory."); } - Type t = Mechanisms[name]; + Type t = mechanisms[name]; object o = Activator.CreateInstance(t, true); return o as SaslMechanism; } @@ -57,7 +67,7 @@ internal static class SaslFactory { "of Sasl.SaslMechanism"); } try { - Mechanisms.Add(name, t); + mechanisms.Add(name, t); } catch (Exception e) { throw new SaslException("Registration of Sasl mechanism failed.", e); } @@ -67,17 +77,26 @@ internal static class SaslFactory { /// Static class constructor. Initializes static properties. /// static SaslFactory() { - Mechanisms = new Dictionary( - StringComparer.InvariantCultureIgnoreCase); - - // Could be moved to App.config to support SASL "plug-in" mechanisms. - var list = new Dictionary() { - { "PLAIN", typeof(Sasl.Mechanisms.SaslPlain) }, - { "DIGEST-MD5", typeof(Sasl.Mechanisms.SaslDigestMd5) }, - { "SCRAM-SHA-1", typeof(Sasl.Mechanisms.SaslScramSha1) }, - }; - foreach (string key in list.Keys) - Mechanisms.Add(key, list[key]); + mechanisms = new Dictionary( + StringComparer.InvariantCultureIgnoreCase) { + { "Plain", typeof(Mechanisms.SaslPlain) }, + { "Cram-Md5", typeof(Mechanisms.SaslCramMd5) }, + { "Digest-Md5", typeof(Mechanisms.SaslDigestMd5) }, + { "Scram-Sha-1", typeof(Mechanisms.SaslScramSha1) }, + { "Ntlm", typeof(Mechanisms.SaslNtlm) }, + { "Ntlmv2", typeof(Mechanisms.SaslNtlmv2) }, + { "OAuth", typeof(Mechanisms.SaslOAuth) }, + { "OAuth2", typeof(Mechanisms.SaslOAuth2) }, + { "Srp", typeof(Mechanisms.SaslSrp) } + }; + // Register any custom mechanisms configured in the app.config. + var configSection = ConfigurationManager.GetSection("saslConfigSection") + as SaslConfigurationSection; + if (configSection != null) { + foreach(SaslProvider provider in configSection.SaslProviders) { + mechanisms.Add(provider.Name, Type.GetType(provider.Type)); + } + } } } } diff --git a/SaslMechanism.cs b/SaslMechanism.cs index 5b62b6b..bd87a44 100644 --- a/SaslMechanism.cs +++ b/SaslMechanism.cs @@ -6,7 +6,7 @@ namespace S22.Sasl { /// The abstract base class from which all classes implementing a Sasl /// authentication mechanism must derive. /// - internal abstract class SaslMechanism { + public abstract class SaslMechanism { /// /// IANA name of the authentication mechanism. /// @@ -48,7 +48,7 @@ internal abstract class SaslMechanism { /// /// - internal SaslMechanism() { + public SaslMechanism() { Properties = new Dictionary(); } diff --git a/Tests/SrpTest.cs b/Tests/SrpTest.cs index fb17c54..0506a83 100644 --- a/Tests/SrpTest.cs +++ b/Tests/SrpTest.cs @@ -85,10 +85,9 @@ public class SrpTest { [TestCategory("Srp")] public void DeserializeServerSecondMessage() { ServerMessage2 m = ServerMessage2.Deserialize(serverMessage2); - Assert.IsTrue(m.Proof.SequenceEqual(expectedServerProof)); Assert.IsTrue(m.InitialVector.SequenceEqual(expectedInitialVector)); - Assert.AreEqual(String.Empty, m.SessionId); + Assert.AreEqual(string.Empty, m.SessionId); Assert.AreEqual(0, m.Ttl); } @@ -96,8 +95,10 @@ public class SrpTest { /// Verifies the various parts of a sample authentication exchange /// (Challenge generated by the Cyrus Sasl library). /// - /// The exchange was generated with the authorization id - /// (authId) set to the same value as the username. + /// + /// The exchange was generated with the authorization id (authId) set to the same value + /// as the username. + /// [TestMethod] [TestCategory("Srp")] public void VerifyAuthenticationExchange() { @@ -109,16 +110,14 @@ public class SrpTest { // Ensure the expected client initial-response is generated. byte[] clientResponse = m.GetResponse(new byte[0]); Assert.IsTrue(clientResponse.SequenceEqual(expectedClientFirst)); - // Hand the server-challenge to the client and verify the expected // client-response is generated. clientResponse = m.GetResponse(serverFirst); Assert.IsTrue(clientResponse.SequenceEqual(expectedClientSecond)); - // Finally, hand the server-evidence to the client and verify the client // responds with the empty string which concludes authentication. clientResponse = m.GetResponse(serverSecond); - Assert.AreEqual(0, clientResponse.Length); + Assert.AreEqual(0, clientResponse.Length); } #region Server Message 1