summaryrefslogtreecommitdiff
path: root/qpid/dotnet/Qpid.Sasl.Tests
diff options
context:
space:
mode:
authorRobert Godfrey <rgodfrey@apache.org>2011-08-14 16:21:34 +0000
committerRobert Godfrey <rgodfrey@apache.org>2011-08-14 16:21:34 +0000
commitd84a3a50dbb794c4383de7e5eca730ca602771e7 (patch)
tree7c6177573a2eedc172de2cbd8354ce7b4ea1e8fe /qpid/dotnet/Qpid.Sasl.Tests
parent0aba202a7e2483f04fc77bbe4faa88bb86fe5b9b (diff)
parent47551f3aa2dd46b8daeeb9683a668464203ffa06 (diff)
downloadqpid-python-d84a3a50dbb794c4383de7e5eca730ca602771e7.tar.gz
Create sandbox from correct revision
git-svn-id: https://svn.apache.org/repos/asf/qpid/branches/rg-amqp-1-0-sandbox@1157557 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'qpid/dotnet/Qpid.Sasl.Tests')
-rw-r--r--qpid/dotnet/Qpid.Sasl.Tests/App.config33
-rw-r--r--qpid/dotnet/Qpid.Sasl.Tests/Mechanisms/AnonymousSaslClientTests.cs72
-rw-r--r--qpid/dotnet/Qpid.Sasl.Tests/Mechanisms/CramMD5SaslClientTests.cs90
-rw-r--r--qpid/dotnet/Qpid.Sasl.Tests/Mechanisms/DigestSaslClientTests.cs249
-rw-r--r--qpid/dotnet/Qpid.Sasl.Tests/Mechanisms/ExternalSaslClientTests.cs71
-rw-r--r--qpid/dotnet/Qpid.Sasl.Tests/Mechanisms/PlainSaslClientTests.cs88
-rw-r--r--qpid/dotnet/Qpid.Sasl.Tests/Properties/AssemblyInfo.cs56
-rw-r--r--qpid/dotnet/Qpid.Sasl.Tests/Qpid.Sasl.Tests.csproj86
-rw-r--r--qpid/dotnet/Qpid.Sasl.Tests/SaslTests.cs133
-rw-r--r--qpid/dotnet/Qpid.Sasl.Tests/TestClientFactory.cs75
-rw-r--r--qpid/dotnet/Qpid.Sasl.Tests/default.build52
11 files changed, 1005 insertions, 0 deletions
diff --git a/qpid/dotnet/Qpid.Sasl.Tests/App.config b/qpid/dotnet/Qpid.Sasl.Tests/App.config
new file mode 100644
index 0000000000..021399939e
--- /dev/null
+++ b/qpid/dotnet/Qpid.Sasl.Tests/App.config
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+
+-->
+
+<configuration>
+ <configSections>
+ <section name="qpid.sasl" type="Apache.Qpid.Sasl.Configuration.SaslConfigurationSectionHandler, Apache.Qpid.Sasl"/>
+ </configSections>
+
+ <qpid.sasl>
+ <clientFactories>
+ <add type="Apache.Qpid.Sasl.Tests.TestClientFactory, Apache.Qpid.Sasl.Tests"/>
+ </clientFactories>
+ </qpid.sasl>
+</configuration>
diff --git a/qpid/dotnet/Qpid.Sasl.Tests/Mechanisms/AnonymousSaslClientTests.cs b/qpid/dotnet/Qpid.Sasl.Tests/Mechanisms/AnonymousSaslClientTests.cs
new file mode 100644
index 0000000000..5839f310e1
--- /dev/null
+++ b/qpid/dotnet/Qpid.Sasl.Tests/Mechanisms/AnonymousSaslClientTests.cs
@@ -0,0 +1,72 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+using System;
+using System.Collections;
+using System.Text;
+
+using NUnit.Framework;
+using Apache.Qpid.Sasl;
+using Apache.Qpid.Sasl.Mechanisms;
+
+namespace Apache.Qpid.Sasl.Tests.Mechanisms
+{
+ [TestFixture]
+ public class AnonymousSaslClientTests : ISaslCallbackHandler
+ {
+ private const string AUTHID = "nobody@nowhere.com";
+
+ [Test]
+ public void ReturnsRightMechanismName()
+ {
+ ISaslClient client = new AnonymousSaslClient(AUTHID, new Hashtable(), this);
+
+ Assert.AreEqual("ANONYMOUS", client.MechanismName);
+ }
+
+ [Test]
+ public void HasInitialResponseReturnsTrue()
+ {
+ ISaslClient client = new AnonymousSaslClient(AUTHID, new Hashtable(), this);
+
+ Assert.IsTrue(client.HasInitialResponse);
+ }
+
+ [Test]
+ public void CanEvaluateChallenge()
+ {
+ Hashtable props = new Hashtable();
+ ISaslClient client = new AnonymousSaslClient(AUTHID, props, this);
+
+ Assert.IsFalse(client.IsComplete);
+ byte[] response = client.EvaluateChallenge(new byte[0]);
+ Assert.AreEqual(AUTHID, Encoding.UTF8.GetString(response));
+
+ Assert.IsTrue(client.IsComplete);
+ }
+
+ void ISaslCallbackHandler.Handle(ISaslCallback[] callbacks)
+ {
+ }
+
+ } // class AnonymousSaslClientTests
+
+} // namespace Apache.Qpid.Sasl.Tests.Mechanisms
diff --git a/qpid/dotnet/Qpid.Sasl.Tests/Mechanisms/CramMD5SaslClientTests.cs b/qpid/dotnet/Qpid.Sasl.Tests/Mechanisms/CramMD5SaslClientTests.cs
new file mode 100644
index 0000000000..baeeafb2d2
--- /dev/null
+++ b/qpid/dotnet/Qpid.Sasl.Tests/Mechanisms/CramMD5SaslClientTests.cs
@@ -0,0 +1,90 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+using System;
+using System.Collections;
+using System.Text;
+
+using NUnit.Framework;
+using Apache.Qpid.Sasl;
+using Apache.Qpid.Sasl.Mechanisms;
+
+namespace Apache.Qpid.Sasl.Tests.Mechanisms
+{
+ [TestFixture]
+ public class CramMD5SaslClientTests : ISaslCallbackHandler
+ {
+ private const string USERNAME = "testuser";
+ private const string PASSWORD = "tanstaaftanstaaf";
+ private const string AUTHID = "test";
+
+ [Test]
+ public void ReturnsRightMechanismName()
+ {
+ ISaslClient client = new CramMD5SaslClient(AUTHID, new Hashtable(), this);
+
+ Assert.AreEqual("CRAM-MD5", client.MechanismName);
+ }
+
+ [Test]
+ public void HasInitialResponseReturnsFalse()
+ {
+ ISaslClient client = new CramMD5SaslClient(AUTHID, new Hashtable(), this);
+
+ Assert.IsFalse(client.HasInitialResponse);
+ }
+
+ [Test]
+ public void CanEvaluateChallenge()
+ {
+ Hashtable props = new Hashtable();
+
+ ISaslClient client = new CramMD5SaslClient(AUTHID, props, this);
+
+ Assert.IsFalse(client.IsComplete);
+
+ byte[] challenge =
+ Encoding.UTF8.GetBytes("<1896.697170952@postoffice.reston.mci.net>");
+ byte[] response = client.EvaluateChallenge(challenge);
+ string[] parts = Encoding.UTF8.GetString(response).Split(' ');
+
+ Assert.AreEqual(2, parts.Length);
+ Assert.AreEqual(USERNAME, parts[0]);
+ Assert.AreEqual("b913a602c7eda7a495b4e6e7334d3890", parts[1]);
+ Assert.IsTrue(client.IsComplete);
+ }
+
+ void ISaslCallbackHandler.Handle(ISaslCallback[] callbacks)
+ {
+ foreach ( ISaslCallback cb in callbacks )
+ {
+ if ( cb is NameCallback )
+ {
+ ((NameCallback)cb).Text = USERNAME;
+ } else if ( cb is PasswordCallback )
+ {
+ ((PasswordCallback)cb).Text = PASSWORD;
+ }
+ }
+ }
+ } // class CramMD5SaslClientTests
+
+} // namespace Apache.Qpid.Sasl.Tests.Mechanisms
diff --git a/qpid/dotnet/Qpid.Sasl.Tests/Mechanisms/DigestSaslClientTests.cs b/qpid/dotnet/Qpid.Sasl.Tests/Mechanisms/DigestSaslClientTests.cs
new file mode 100644
index 0000000000..5a18ebaefd
--- /dev/null
+++ b/qpid/dotnet/Qpid.Sasl.Tests/Mechanisms/DigestSaslClientTests.cs
@@ -0,0 +1,249 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+using System;
+using System.Collections;
+using System.Collections.Specialized;
+using System.Text;
+
+using NUnit.Framework;
+using Apache.Qpid.Sasl;
+using Apache.Qpid.Sasl.Mechanisms;
+
+namespace Apache.Qpid.Sasl.Tests.Mechanisms
+{
+ [TestFixture]
+ public class DigestSaslClientTests : ISaslCallbackHandler
+ {
+ private const string USERNAME = "chris";
+ private const string PASSWORD = "secret";
+ private const string AUTHID = null;
+ private const string PROTOCOL = "IMAP";
+ private const string SERVERNAME = "elwood.innosoft.com";
+
+ #region Digest Challenge Parsing Tests
+ //
+ // Digest Challenge Parsing Tests
+ //
+
+ [Test]
+ public void CanParseSimpleString()
+ {
+ string challenge = "realm=\"elwood.innosoft.com\", algorithm=md5-sess";
+ StringDictionary values = DigestChallenge.ParseParameters(challenge);
+ Assert.AreEqual(2, values.Count);
+ Assert.AreEqual("elwood.innosoft.com", values["realm"]);
+ Assert.AreEqual("md5-sess", values["algorithm"]);
+ }
+
+ [Test]
+ public void CanParseEscapedQuotes()
+ {
+ string challenge = "realm=\"elwood\\\".innosoft.com\", algorithm=md5-sess";
+ StringDictionary values = DigestChallenge.ParseParameters(challenge);
+ Assert.AreEqual(2, values.Count);
+ Assert.AreEqual("elwood\\\".innosoft.com", values["realm"]);
+ Assert.AreEqual("md5-sess", values["algorithm"]);
+ }
+
+ [Test]
+ public void CanParseEmbeddedDelimiter()
+ {
+ string challenge = "realm=\"elwood,innosoft.com\", algorithm=md5-sess";
+ StringDictionary values = DigestChallenge.ParseParameters(challenge);
+ Assert.AreEqual(2, values.Count);
+ Assert.AreEqual("elwood,innosoft.com", values["realm"]);
+ Assert.AreEqual("md5-sess", values["algorithm"]);
+ }
+
+ [Test]
+ public void CanParse1()
+ {
+ string challenge = "realm=\"elwood.innosoft.com\",nonce=\"OA6MG9tEQGm2hh\",qop=\"auth\",algorithm=md5-sess,charset=utf-8";
+ DigestChallenge parsed = DigestChallenge.Parse(challenge);
+
+ Assert.AreEqual("elwood.innosoft.com", parsed.Realm);
+ Assert.AreEqual("OA6MG9tEQGm2hh", parsed.Nonce);
+ Assert.Contains("auth", parsed.QopOptions);
+ Assert.AreEqual("md5-sess", parsed.Algorithm);
+ Assert.AreEqual("utf-8", parsed.Charset);
+ }
+
+ #endregion // Digest Challenge Parsing Tests
+
+
+ #region Digest Response Tests
+ //
+ // Digest Response Tests
+ //
+
+ [Test]
+ public void CanWriteResponse()
+ {
+ DigestResponse resp = new DigestResponse();
+ resp.Username = "user";
+ resp.Realm = "nowhere.com";
+ resp.Nonce = "OA9BSXrbuRhWay";
+ resp.Cnonce = "OA9BSuZWMSpW8m";
+ resp.NonceCount = 16;
+ resp.DigestUri = "acap/elwood.innosoft.com";
+ resp.Response = "6084c6db3fede7352c551284490fd0fc";
+ resp.Qop = "auth";
+ resp.MaxBuffer = 65536;
+ resp.Cipher = "3des";
+ resp.Authzid = "user2";
+ resp.AuthParam = "ap";
+ resp.Charset = "utf-8";
+
+ string expected = "username=\"user\",realm=\"nowhere.com\",nonce=\"OA9BSXrbuRhWay\",cnonce=\"OA9BSuZWMSpW8m\",nc=00000010,qop=auth,digest-uri=\"acap/elwood.innosoft.com\",response=\"6084c6db3fede7352c551284490fd0fc\",maxbuf=65536,charset=utf-8,cipher=3des,authzid=\"user2\",auth-param=\"ap\"";
+ Assert.AreEqual(expected, resp.ToString());
+ }
+
+ [Test]
+ public void CanWriteEscapedSecuence()
+ {
+ DigestResponse resp = new DigestResponse();
+ resp.Username = "us\"er";
+
+ string expected = "username=\"us\\\"er\",nc=00000000,maxbuf=0";
+ Assert.AreEqual(expected, resp.ToString());
+ }
+
+ #endregion // Digest Response Tests
+
+
+ #region Authentication Tests
+ //
+ // Authentication Tests
+ //
+
+ [Test]
+ public void ReturnsRightMechanismName()
+ {
+ ISaslClient client = CreateClient();
+
+ Assert.AreEqual("DIGEST-MD5", client.MechanismName);
+ }
+
+ [Test]
+ public void HasInitialResponseReturnsFalse()
+ {
+ ISaslClient client = CreateClient();
+
+ Assert.IsFalse(client.HasInitialResponse);
+ }
+
+ [Test]
+ public void CanAuthenticate()
+ {
+ string challenge = "realm=\"elwood.innosoft.com\",nonce=\"OA6MG9tEQGm2hh\",qop=\"auth\",algorithm=md5-sess,charset=utf-8";
+ DigestSaslClient client = CreateClient();
+ client.Cnonce = "OA6MHXh6VqTrRk";
+
+ byte[] bresp = client.EvaluateChallenge(Encoding.UTF8.GetBytes(challenge));
+ string response = Encoding.UTF8.GetString(bresp);
+ string expectedResp = "username=\"chris\",realm=\"elwood.innosoft.com\",nonce=\"OA6MG9tEQGm2hh\",cnonce=\"" +
+ client.Cnonce + "\",nc=00000001,qop=auth,digest-uri=\"imap/elwood.innosoft.com\",response=\"d388dad90d4bbd760a152321f2143af7\",maxbuf=65536,charset=utf-8";
+
+ Assert.AreEqual(expectedResp, response);
+ Assert.IsFalse(client.IsComplete);
+
+ string challenge2 = "rspauth=ea40f60335c427b5527b84dbabcdfffd";
+ bresp = client.EvaluateChallenge(Encoding.UTF8.GetBytes(challenge2));
+ // client responds with zero-length array
+ Assert.AreEqual(0, bresp.Length);
+ Assert.IsTrue(client.IsComplete);
+ }
+
+ [Test]
+ [ExpectedException(typeof(ArgumentNullException))]
+ public void ThrowsExceptionWhenChallengeIsMissing()
+ {
+ DigestSaslClient client = CreateClient();
+ client.EvaluateChallenge(null);
+ }
+
+
+ [Test]
+ [ExpectedException(typeof(SaslException))]
+ public void ThrowsExceptionWhenNonceMissing()
+ {
+ string challenge = "realm=\"elwood.innosoft.com\"";
+ DigestSaslClient client = CreateClient();
+
+ client.EvaluateChallenge(Encoding.UTF8.GetBytes(challenge));
+ }
+
+ [Test]
+ [ExpectedException(typeof(SaslException))]
+ public void ThrowsExceptionWhenAlgorithmMissing()
+ {
+ string challenge = "realm=\"elwood.innosoft.com\",nonce=\"asdasadsad\"";
+ DigestSaslClient client = CreateClient();
+
+ client.EvaluateChallenge(Encoding.UTF8.GetBytes(challenge));
+ }
+
+ [Test]
+ [ExpectedException(typeof(SaslException))]
+ public void ThrowsExceptionWhenSecondChallengeInvalid()
+ {
+ string challenge = "realm=\"elwood.innosoft.com\",nonce=\"OA6MG9tEQGm2hh\",qop=\"auth\",algorithm=md5-sess,charset=utf-8";
+ DigestSaslClient client = CreateClient();
+
+ byte[] bresp = client.EvaluateChallenge(Encoding.UTF8.GetBytes(challenge));
+ Encoding.UTF8.GetString(bresp);
+
+ // repeat challenge 1, which is incorrect
+ client.EvaluateChallenge(Encoding.UTF8.GetBytes(challenge));
+ }
+
+ private DigestSaslClient CreateClient()
+ {
+ return new DigestSaslClient(
+ AUTHID, SERVERNAME, PROTOCOL,
+ new Hashtable(), this
+ );
+ }
+
+ void ISaslCallbackHandler.Handle(ISaslCallback[] callbacks)
+ {
+ foreach ( ISaslCallback cb in callbacks )
+ {
+ if ( cb is NameCallback )
+ {
+ ((NameCallback)cb).Text = USERNAME;
+ } else if ( cb is PasswordCallback )
+ {
+ ((PasswordCallback)cb).Text = PASSWORD;
+ } else if ( cb is RealmCallback )
+ {
+ ((RealmCallback)cb).Text = SERVERNAME;
+ }
+ }
+ }
+
+ #endregion // Authentication Tests
+
+
+ } // class DigestSaslClientTests
+
+} // namespace Apache.Qpid.Sasl.Tests.Mechanisms
diff --git a/qpid/dotnet/Qpid.Sasl.Tests/Mechanisms/ExternalSaslClientTests.cs b/qpid/dotnet/Qpid.Sasl.Tests/Mechanisms/ExternalSaslClientTests.cs
new file mode 100644
index 0000000000..57efcf7614
--- /dev/null
+++ b/qpid/dotnet/Qpid.Sasl.Tests/Mechanisms/ExternalSaslClientTests.cs
@@ -0,0 +1,71 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+using System;
+using System.Collections;
+using System.Text;
+
+using NUnit.Framework;
+using Apache.Qpid.Sasl;
+using Apache.Qpid.Sasl.Mechanisms;
+
+namespace Apache.Qpid.Sasl.Tests.Mechanisms
+{
+ [TestFixture]
+ public class ExternalSaslClientTests : ISaslCallbackHandler
+ {
+ private const string AUTHID = "nobody@nowhere.com";
+
+ [Test]
+ public void ReturnsRightMechanismName()
+ {
+ ISaslClient client = new ExternalSaslClient(AUTHID, new Hashtable(), this);
+
+ Assert.AreEqual("EXTERNAL", client.MechanismName);
+ }
+
+ [Test]
+ public void HasInitialResponseReturnsTrue()
+ {
+ ISaslClient client = new ExternalSaslClient(AUTHID, new Hashtable(), this);
+
+ Assert.IsTrue(client.HasInitialResponse);
+ }
+
+ [Test]
+ public void CanEvaluateChallenge()
+ {
+ ISaslClient client = new ExternalSaslClient(AUTHID, new Hashtable(), this);
+
+ Assert.IsFalse(client.IsComplete);
+ byte[] response = client.EvaluateChallenge(new byte[0]);
+ Assert.AreEqual(AUTHID, Encoding.UTF8.GetString(response));
+
+ Assert.IsTrue(client.IsComplete);
+ }
+
+ void ISaslCallbackHandler.Handle(ISaslCallback[] callbacks)
+ {
+ }
+
+ } // class AnonymousSaslClientTests
+
+} // namespace Apache.Qpid.Sasl.Tests.Mechanisms
diff --git a/qpid/dotnet/Qpid.Sasl.Tests/Mechanisms/PlainSaslClientTests.cs b/qpid/dotnet/Qpid.Sasl.Tests/Mechanisms/PlainSaslClientTests.cs
new file mode 100644
index 0000000000..f4fc00e038
--- /dev/null
+++ b/qpid/dotnet/Qpid.Sasl.Tests/Mechanisms/PlainSaslClientTests.cs
@@ -0,0 +1,88 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+using System;
+using System.Collections;
+using System.Text;
+
+using NUnit.Framework;
+using Apache.Qpid.Sasl;
+using Apache.Qpid.Sasl.Mechanisms;
+
+namespace Apache.Qpid.Sasl.Tests.Mechanisms
+{
+ [TestFixture]
+ public class PlainSaslClientTests : ISaslCallbackHandler
+ {
+ private const string USERNAME = "testuser";
+ private const string PASSWORD = "thepasswd";
+ private const string AUTHID = "theauth";
+
+ [Test]
+ public void ReturnsRightMechanismName()
+ {
+ ISaslClient client = new PlainSaslClient(AUTHID, new Hashtable(), this);
+
+ Assert.AreEqual("PLAIN", client.MechanismName);
+ }
+
+ [Test]
+ public void HasInitialResponseReturnsTrue()
+ {
+ ISaslClient client = new PlainSaslClient(AUTHID, new Hashtable(), this);
+
+ Assert.IsTrue(client.HasInitialResponse);
+ }
+
+ [Test]
+ public void CanEvaluateChallenge()
+ {
+ Hashtable props = new Hashtable();
+ ISaslClient client = new PlainSaslClient(AUTHID, props, this);
+
+ Assert.IsFalse(client.IsComplete);
+ byte[] response = client.EvaluateChallenge(new byte[0]);
+ string[] parts = Encoding.UTF8.GetString(response).Split('\0');
+
+ Assert.AreEqual(3, parts.Length);
+ Assert.AreEqual(AUTHID, parts[0]);
+ Assert.AreEqual(USERNAME, parts[1]);
+ Assert.AreEqual(PASSWORD, parts[2]);
+ Assert.IsTrue(client.IsComplete);
+ }
+
+ void ISaslCallbackHandler.Handle(ISaslCallback[] callbacks)
+ {
+ foreach ( ISaslCallback cb in callbacks )
+ {
+ if ( cb is NameCallback )
+ {
+ ((NameCallback)cb).Text = USERNAME;
+ } else if ( cb is PasswordCallback )
+ {
+ ((PasswordCallback)cb).Text = PASSWORD;
+ }
+ }
+ }
+
+ } // class PlainSaslClientTests
+
+} // namespace Apache.Qpid.Sasl.Tests.Mechanisms
diff --git a/qpid/dotnet/Qpid.Sasl.Tests/Properties/AssemblyInfo.cs b/qpid/dotnet/Qpid.Sasl.Tests/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000000..e795c267a7
--- /dev/null
+++ b/qpid/dotnet/Qpid.Sasl.Tests/Properties/AssemblyInfo.cs
@@ -0,0 +1,56 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Apache.Qpid.Sasl.Tests")]
+[assembly: AssemblyDescription("Built from svn revision number: ")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Apache Software Foundation")]
+[assembly: AssemblyProduct("Apache.Qpid.Sasl.Tests")]
+[assembly: AssemblyCopyright("Apache Software Foundation")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("84cc3267-8019-4fad-a426-0a40155b3352")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Revision and Build Numbers
+// by using the '*' as shown below:
+[assembly: AssemblyVersion("0.5.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/qpid/dotnet/Qpid.Sasl.Tests/Qpid.Sasl.Tests.csproj b/qpid/dotnet/Qpid.Sasl.Tests/Qpid.Sasl.Tests.csproj
new file mode 100644
index 0000000000..f1a7b07e5a
--- /dev/null
+++ b/qpid/dotnet/Qpid.Sasl.Tests/Qpid.Sasl.Tests.csproj
@@ -0,0 +1,86 @@
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+
+-->
+
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>8.0.50727</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{587B3520-EBB9-41ED-B019-E96116B651CE}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Apache.Qpid.Sasl.Tests</RootNamespace>
+ <AssemblyName>Apache.Qpid.Sasl.Tests</AssemblyName>
+ <FileUpgradeFlags>
+ </FileUpgradeFlags>
+ <OldToolsVersion>2.0</OldToolsVersion>
+ <UpgradeBackupLocation>
+ </UpgradeBackupLocation>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>..\bin\net-2.0\debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <UseVSHostingProcess>true</UseVSHostingProcess>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>..\bin\net-2.0\release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="nunit.framework, Version=2.2.8.0, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\Qpid.Client.Tests\lib\nunit\nunit.framework.dll</HintPath>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="**\*.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\Qpid.Sasl\Qpid.Sasl.csproj">
+ <Project>{1465B0EE-6452-42A6-AB73-B2F9EABEEE75}</Project>
+ <Name>Qpid.Sasl</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="App.config" />
+ </ItemGroup>
+ <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project>
diff --git a/qpid/dotnet/Qpid.Sasl.Tests/SaslTests.cs b/qpid/dotnet/Qpid.Sasl.Tests/SaslTests.cs
new file mode 100644
index 0000000000..e7ae91d6b6
--- /dev/null
+++ b/qpid/dotnet/Qpid.Sasl.Tests/SaslTests.cs
@@ -0,0 +1,133 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+using System;
+using System.Collections;
+using System.Text;
+
+using NUnit.Framework;
+using Apache.Qpid.Sasl;
+using Apache.Qpid.Sasl.Mechanisms;
+
+namespace Apache.Qpid.Sasl.Tests
+{
+ [TestFixture]
+ public class SaslTests : ISaslCallbackHandler
+ {
+
+ [Test]
+ public void CanCreatePlain()
+ {
+ Hashtable props = new Hashtable();
+ string[] mechanisms = new string[] { "PLAIN", "OTHER" };
+ ISaslClient client = Sasl.CreateClient(mechanisms, "", "", "", props, this);
+
+ Assert.IsNotNull(client);
+ Assert.IsInstanceOfType(typeof(PlainSaslClient), client);
+ }
+
+ [Test]
+ public void CanCreateCramMD5()
+ {
+ Hashtable props = new Hashtable();
+ string[] mechanisms = new string[] { "CRAM-MD5", "OTHER" };
+ ISaslClient client = Sasl.CreateClient(mechanisms, "", "", "", props, this);
+
+ Assert.IsNotNull(client);
+ Assert.IsInstanceOfType(typeof(CramMD5SaslClient), client);
+ }
+
+ [Test]
+ public void CanCreateAnonymous()
+ {
+ Hashtable props = new Hashtable();
+ string[] mechanisms = new string[] { "ANONYMOUS", "OTHER" };
+ ISaslClient client = Sasl.CreateClient(mechanisms, "", "", "", props, this);
+
+ Assert.IsNotNull(client);
+ Assert.IsInstanceOfType(typeof(AnonymousSaslClient), client);
+ }
+
+ [Test]
+ public void CanCreateDigest()
+ {
+ Hashtable props = new Hashtable();
+ string[] mechanisms = new string[] { "DIGEST-MD5", "OTHER" };
+ ISaslClient client = Sasl.CreateClient(mechanisms, "", "", "", props, this);
+
+ Assert.IsNotNull(client);
+ Assert.IsInstanceOfType(typeof(DigestSaslClient), client);
+ }
+
+ [Test]
+ public void CanCreateExternal()
+ {
+ Hashtable props = new Hashtable();
+ string[] mechanisms = new string[] { "EXTERNAL", "OTHER" };
+ ISaslClient client = Sasl.CreateClient(mechanisms, "", "", "", props, this);
+
+ Assert.IsNotNull(client);
+ Assert.IsInstanceOfType(typeof(ExternalSaslClient), client);
+ }
+
+ [Test]
+ public void ReturnsNullIfNoFactoryFound()
+ {
+ Hashtable props = new Hashtable();
+ props.Add(SaslProperties.PolicyNoPlainText, true);
+ string[] mechanisms = new string[] { "PLAIN", "OTHER" };
+ ISaslClient client = Sasl.CreateClient(mechanisms, "", "", "", props, this);
+
+ Assert.IsNull(client);
+ }
+
+ [Test]
+ public void ParsesConfigurationSection()
+ {
+ // if the TEST mechanism is available, then we know
+ // the configuration section worked!
+ Hashtable props = new Hashtable();
+ string[] mechanisms = new string[] { "TEST" };
+ ISaslClient client = Sasl.CreateClient(mechanisms, "", "", "", props, this);
+
+ Assert.IsNotNull(client);
+ Assert.IsInstanceOfType(typeof(TestSaslClient), client);
+ }
+
+ [Test]
+ public void ChoosesStrongerMechanism()
+ {
+ Hashtable props = new Hashtable();
+ string[] mechanisms = new string[] { "PLAIN", "OTHER", "CRAM-MD5" };
+ ISaslClient client = Sasl.CreateClient(mechanisms, "", "", "", props, this);
+
+ Assert.IsNotNull(client);
+ Assert.IsInstanceOfType(typeof(CramMD5SaslClient), client);
+ }
+
+
+ void ISaslCallbackHandler.Handle(ISaslCallback[] callbacks)
+ {
+ }
+
+ } // class SaslTests
+
+} // namespace Apache.Qpid.Sasl.Tests
diff --git a/qpid/dotnet/Qpid.Sasl.Tests/TestClientFactory.cs b/qpid/dotnet/Qpid.Sasl.Tests/TestClientFactory.cs
new file mode 100644
index 0000000000..62099237e9
--- /dev/null
+++ b/qpid/dotnet/Qpid.Sasl.Tests/TestClientFactory.cs
@@ -0,0 +1,75 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+using System;
+using System.Collections;
+using System.Text;
+
+using NUnit.Framework;
+using Apache.Qpid.Sasl;
+using Apache.Qpid.Sasl.Mechanisms;
+
+namespace Apache.Qpid.Sasl.Tests
+{
+ public class TestClientFactory : ISaslClientFactory
+ {
+ public string[] GetSupportedMechanisms(IDictionary props)
+ {
+ return new string[] { TestSaslClient.Mechanism };
+ }
+
+ public ISaslClient CreateClient(string[] mechanisms, string authorizationId, string protocol, string serverName, IDictionary props, ISaslCallbackHandler handler)
+ {
+ foreach ( string mech in mechanisms )
+ {
+ if ( mech == TestSaslClient.Mechanism )
+ return new TestSaslClient(props, handler);
+ }
+ return null;
+ }
+
+ } // class TestClientFactory
+
+ internal class TestSaslClient : SaslClient
+ {
+ public const string Mechanism = "TEST";
+
+ public override string MechanismName
+ {
+ get { return Mechanism; }
+ }
+ public override bool HasInitialResponse
+ {
+ get { return false; }
+ }
+
+ public TestSaslClient(IDictionary props, ISaslCallbackHandler handler)
+ : base("", "", "", props, handler)
+ {
+ }
+
+ public override byte[] EvaluateChallenge(byte[] challenge)
+ {
+ throw new NotImplementedException();
+ }
+ } // class TestSaslClient
+
+} // namespace Apache.Qpid.Sasl.Tests
diff --git a/qpid/dotnet/Qpid.Sasl.Tests/default.build b/qpid/dotnet/Qpid.Sasl.Tests/default.build
new file mode 100644
index 0000000000..5b51c0a6fa
--- /dev/null
+++ b/qpid/dotnet/Qpid.Sasl.Tests/default.build
@@ -0,0 +1,52 @@
+<?xml version="1.0"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+
+-->
+
+<project name="Apache.Qpid.Sasl" default="test">
+
+ <target name="build">
+ <csc target="library"
+ define="${build.defines}"
+ warnaserror="true" debug="${build.debug}"
+ output="${build.dir}/${project::get-name()}.Tests.dll">
+
+ <sources>
+ <include name="**/*.cs" />
+ </sources>
+ <references>
+ <include name="${build.dir}/nunit.framework.dll" />
+ <include name="${build.dir}/${project::get-name()}.dll" />
+ </references>
+
+ </csc>
+ <copy
+ tofile="${build.dir}/${project::get-name()}.Tests.dll.config"
+ file="App.config"
+ />
+ </target>
+ <target name="test" depends="build">
+ <nunit2>
+ <formatter type="${nant.formatter}" usefile="false" />
+ <test assemblyname="${build.dir}/${project::get-name()}.Tests.dll" />
+ </nunit2>
+ </target>
+</project>
+