provider model

This commit is contained in:
Torben Könke 2017-06-12 01:30:36 +02:00
parent 235d86668c
commit e8ec2d6b49
5 changed files with 46 additions and 28 deletions

View File

@ -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")]

View File

@ -11,7 +11,7 @@ public class SaslConfigurationSection : ConfigurationSection {
/// saslProvider elements.
/// </summary>
[ConfigurationProperty("saslProviders", IsRequired = false,
IsKey = false, IsDefaultCollection = true)]
IsKey = false, IsDefaultCollection = false)]
public SaslProviderCollection SaslProviders {
get {
return ((SaslProviderCollection) base["saslProviders"]);

View File

@ -1,19 +1,29 @@
using System;
using System.Collections.Generic;
using System.Configuration;
namespace S22.Sasl {
/// <summary>
/// A factory class for producing instances of Sasl mechanisms.
/// </summary>
internal static class SaslFactory {
public static class SaslFactory {
/// <summary>
/// A dictionary of Sasl mechanisms registered with the factory class.
/// </summary>
static Dictionary<string, Type> Mechanisms {
static Dictionary<string, Type> mechanisms {
get;
set;
}
/// <summary>
/// A list of the names of all available mechanisms.
/// </summary>
public static IEnumerable<string> Mechanisms {
get {
return mechanisms.Keys;
}
}
/// <summary>
/// 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.</exception>
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.
/// </summary>
static SaslFactory() {
Mechanisms = new Dictionary<string, Type>(
StringComparer.InvariantCultureIgnoreCase);
// Could be moved to App.config to support SASL "plug-in" mechanisms.
var list = new Dictionary<string, Type>() {
{ "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<string, Type>(
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));
}
}
}
}
}

View File

@ -6,7 +6,7 @@ namespace S22.Sasl {
/// The abstract base class from which all classes implementing a Sasl
/// authentication mechanism must derive.
/// </summary>
internal abstract class SaslMechanism {
public abstract class SaslMechanism {
/// <summary>
/// IANA name of the authentication mechanism.
/// </summary>
@ -48,7 +48,7 @@ internal abstract class SaslMechanism {
/// <summary>
/// </summary>
internal SaslMechanism() {
public SaslMechanism() {
Properties = new Dictionary<string, object>();
}

View File

@ -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>(String.Empty, m.SessionId);
Assert.AreEqual(string.Empty, m.SessionId);
Assert.AreEqual<uint>(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).
/// </summary>
/// <remarks>The exchange was generated with the authorization id
/// (authId) set to the same value as the username.</remarks>
/// <remarks>
/// The exchange was generated with the authorization id (authId) set to the same value
/// as the username.
/// </remarks>
[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<int>(0, clientResponse.Length);
Assert.AreEqual(0, clientResponse.Length);
}
#region Server Message 1