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