From 83ec6a5f10a3fd60b08b5f47bfff4d4ab93cbeac Mon Sep 17 00:00:00 2001 From: Martin Ritchie Date: Fri, 6 Jun 2008 16:03:42 +0000 Subject: QPID-1058 : Added new CramMD5HexSaslClient.cs and registered it in the Sasl Factory and the client CallbackHandler git-svn-id: https://svn.apache.org/repos/asf/incubator/qpid/branches/M2.x@663999 13f79535-47bb-0310-9956-ffa450edef68 --- .../Client/Security/CallbackHandlerRegistry.cs | 2 + .../Qpid.Integration.Tests.csproj | 65 +++++++++++++++ dotnet/Qpid.NET.sln | 12 ++- dotnet/Qpid.Sasl/Callbacks.cs | 33 ++++++++ dotnet/Qpid.Sasl/DefaultClientFactory.cs | 4 + .../Qpid.Sasl/Mechanisms/CramMD5HexSaslClient.cs | 96 ++++++++++++++++++++++ dotnet/Qpid.Sasl/Qpid.Sasl.csproj | 3 +- 7 files changed, 213 insertions(+), 2 deletions(-) create mode 100644 dotnet/Qpid.Integration.Tests/Qpid.Integration.Tests.csproj create mode 100644 dotnet/Qpid.Sasl/Mechanisms/CramMD5HexSaslClient.cs diff --git a/dotnet/Qpid.Client/Client/Security/CallbackHandlerRegistry.cs b/dotnet/Qpid.Client/Client/Security/CallbackHandlerRegistry.cs index 85be927ff4..22f1c9d89b 100644 --- a/dotnet/Qpid.Client/Client/Security/CallbackHandlerRegistry.cs +++ b/dotnet/Qpid.Client/Client/Security/CallbackHandlerRegistry.cs @@ -96,6 +96,8 @@ namespace Apache.Qpid.Client.Security _mechanism2HandlerMap.Add(ExternalSaslClient.Mechanism, typeof(UsernamePasswordCallbackHandler)); if ( !_mechanism2HandlerMap.Contains(CramMD5SaslClient.Mechanism) ) _mechanism2HandlerMap.Add(CramMD5SaslClient.Mechanism, typeof(UsernamePasswordCallbackHandler)); + if ( !_mechanism2HandlerMap.Contains(CramMD5HexSaslClient.Mechanism) ) + _mechanism2HandlerMap.Add(CramMD5HexSaslClient.Mechanism, typeof(UsernamePasswordCallbackHandler)); if ( !_mechanism2HandlerMap.Contains(PlainSaslClient.Mechanism) ) _mechanism2HandlerMap.Add(PlainSaslClient.Mechanism, typeof(UsernamePasswordCallbackHandler)); diff --git a/dotnet/Qpid.Integration.Tests/Qpid.Integration.Tests.csproj b/dotnet/Qpid.Integration.Tests/Qpid.Integration.Tests.csproj new file mode 100644 index 0000000000..51d91f2bd3 --- /dev/null +++ b/dotnet/Qpid.Integration.Tests/Qpid.Integration.Tests.csproj @@ -0,0 +1,65 @@ + + + {DE21CEBC-F38C-43EA-B576-38CA9738A00A} + Debug + AnyCPU + Library + Qpid.Integration.Tests + Qpid.Integration.Tests + + + bin\Debug\ + True + Full + False + True + DEBUG;TRACE + + + bin\Release\ + False + None + True + False + TRACE + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dotnet/Qpid.NET.sln b/dotnet/Qpid.NET.sln index 8b174db90f..c5157ed4e5 100644 --- a/dotnet/Qpid.NET.sln +++ b/dotnet/Qpid.NET.sln @@ -1,4 +1,4 @@ -Microsoft Visual Studio Solution File, Format Version 9.00 +Microsoft Visual Studio Solution File, Format Version 9.00 # Visual Studio 2005 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Qpid.Messaging", "Qpid.Messaging\Qpid.Messaging.csproj", "{6688F826-C58E-4C1B-AA1F-22AFAB4B7D07}" EndProject @@ -26,6 +26,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TopicListener", "TopicListe EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestClient", "TestClient\TestClient.csproj", "{9A112DF2-146F-4CF4-919B-9D3BE7D088E9}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Qpid.Integration.Tests", "Qpid.Integration.Tests\Qpid.Integration.Tests.csproj", "{DE21CEBC-F38C-43EA-B576-38CA9738A00A}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -80,6 +82,14 @@ Global {9A112DF2-146F-4CF4-919B-9D3BE7D088E9}.Debug|Any CPU.Build.0 = Debug|Any CPU {9A112DF2-146F-4CF4-919B-9D3BE7D088E9}.Release|Any CPU.ActiveCfg = Release|Any CPU {9A112DF2-146F-4CF4-919B-9D3BE7D088E9}.Release|Any CPU.Build.0 = Release|Any CPU + {666C2D04-C9DC-4D43-B4DF-0989225EABC3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {666C2D04-C9DC-4D43-B4DF-0989225EABC3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {666C2D04-C9DC-4D43-B4DF-0989225EABC3}.Release|Any CPU.Build.0 = Release|Any CPU + {666C2D04-C9DC-4D43-B4DF-0989225EABC3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DE21CEBC-F38C-43EA-B576-38CA9738A00A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DE21CEBC-F38C-43EA-B576-38CA9738A00A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DE21CEBC-F38C-43EA-B576-38CA9738A00A}.Release|Any CPU.Build.0 = Release|Any CPU + {DE21CEBC-F38C-43EA-B576-38CA9738A00A}.Release|Any CPU.ActiveCfg = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/dotnet/Qpid.Sasl/Callbacks.cs b/dotnet/Qpid.Sasl/Callbacks.cs index 90e36beeb8..a5913eb61e 100644 --- a/dotnet/Qpid.Sasl/Callbacks.cs +++ b/dotnet/Qpid.Sasl/Callbacks.cs @@ -21,6 +21,8 @@ using System; using System.Text; +using System.Globalization; +using System.Security.Cryptography; namespace Apache.Qpid.Sasl { @@ -87,6 +89,37 @@ namespace Apache.Qpid.Sasl : base("password:", "", "") { } + + public byte[] HashedText + { + get + { + string _text = this.Text; + System.Security.Cryptography.MD5CryptoServiceProvider x = new System.Security.Cryptography.MD5CryptoServiceProvider(); + byte[] bs = x.ComputeHash(Encoding.UTF8.GetBytes(_text)); + return bs; + } + + } + } // class PasswordCallback + + public class HashedPasswordCallback : TextSaslCallback + { + public HashedPasswordCallback() + : base("password:", "", "") + { + } + + public byte[] HashedText + { + get { + string _text = this.Text; + System.Security.Cryptography.MD5CryptoServiceProvider x = new System.Security.Cryptography.MD5CryptoServiceProvider(); + _text = _text.PadRight(16, '\0'); + byte[] bs = x.ComputeHash(Encoding.UTF8.GetBytes(_text)); + return bs; + } + } } // class PasswordCallback public class RealmCallback : TextSaslCallback diff --git a/dotnet/Qpid.Sasl/DefaultClientFactory.cs b/dotnet/Qpid.Sasl/DefaultClientFactory.cs index d552aa80c0..a38e5d50c7 100644 --- a/dotnet/Qpid.Sasl/DefaultClientFactory.cs +++ b/dotnet/Qpid.Sasl/DefaultClientFactory.cs @@ -31,6 +31,7 @@ namespace Apache.Qpid.Sasl private static readonly string[] SUPPORTED = new string[] { DigestSaslClient.Mechanism, CramMD5SaslClient.Mechanism, + CramMD5HexSaslClient.Mechanism, PlainSaslClient.Mechanism, AnonymousSaslClient.Mechanism, ExternalSaslClient.Mechanism, @@ -50,6 +51,7 @@ namespace Apache.Qpid.Sasl props.Contains(SaslProperties.PolicyPassCredentials) ) { vetoed.Add(CramMD5SaslClient.Mechanism); + vetoed.Add(CramMD5HexSaslClient.Mechanism); vetoed.Add(PlainSaslClient.Mechanism); vetoed.Add(AnonymousSaslClient.Mechanism); vetoed.Add(ExternalSaslClient.Mechanism); @@ -81,6 +83,8 @@ namespace Apache.Qpid.Sasl return new DigestSaslClient(authorizationId, serverName, protocol, props, handler); if ( mechs.Contains(CramMD5SaslClient.Mechanism) ) return new CramMD5SaslClient(authorizationId, props, handler); + if ( mechs.Contains(CramMD5HexSaslClient.Mechanism) ) + return new CramMD5HexSaslClient(authorizationId, props, handler); if ( mechs.Contains(PlainSaslClient.Mechanism) ) return new PlainSaslClient(authorizationId, props, handler); if ( mechs.Contains(AnonymousSaslClient.Mechanism) ) diff --git a/dotnet/Qpid.Sasl/Mechanisms/CramMD5HexSaslClient.cs b/dotnet/Qpid.Sasl/Mechanisms/CramMD5HexSaslClient.cs new file mode 100644 index 0000000000..ed44895658 --- /dev/null +++ b/dotnet/Qpid.Sasl/Mechanisms/CramMD5HexSaslClient.cs @@ -0,0 +1,96 @@ +/* + * + * 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.Security.Cryptography; +using System.Text; + +namespace Apache.Qpid.Sasl.Mechanisms +{ + /// + /// Implements the CRAM-MD5 authentication mechanism as outlined + /// in RFC 2195 + /// + public class CramMD5HexSaslClient : SaslClient + { + public const string Mechanism = "CRAM-MD5-HEX"; + private const int MinPwdLen = 16; + + public CramMD5HexSaslClient( + string authorizationId, + IDictionary properties, + ISaslCallbackHandler handler) + : base(authorizationId, null, null, properties, handler) + { + } + + #region ISaslClient Implementation + // + // ISaslClient Implementation + // + + public override string MechanismName + { + get { return Mechanism; } + } + + public override bool HasInitialResponse + { + get { return false; } + } + + + public override byte[] EvaluateChallenge(byte[] challenge) + { + if ( challenge == null || challenge.Length == 0 ) + throw new ArgumentNullException("challenge"); + + + NameCallback nameCB = new NameCallback(AuthorizationId); + PasswordCallback pwdCB = new PasswordCallback(); + ISaslCallback[] callbacks = { nameCB, pwdCB }; + Handler.Handle(callbacks); + + string username = nameCB.Text; + + //Encode the Hashed Password as Hex + byte[] passwd = Encoding.UTF8.GetBytes(ToHex(pwdCB.HashedText)); + + string s = System.Text.UTF8Encoding.UTF8.GetString(challenge); + + Console.WriteLine("Connection Username = " + username + ", Challenge = " + s + " Secret length - " + passwd.Length + ", Hashed secret - " + ToHex(pwdCB.HashedText)); + + using ( HMAC hmac = new HMACMD5(passwd) ) + { + byte[] value = hmac.ComputeHash(challenge); + string encoded = ToHex(value); + SetComplete(); + Console.WriteLine(username + " " + encoded); + return Encoding.UTF8.GetBytes(username + " " + encoded); + } + } + + #endregion // ISaslClient Implementation + + } // class CramMD5HashedSaslClient + +} // namespace Apache.Qpid.Sasl.Mechanisms diff --git a/dotnet/Qpid.Sasl/Qpid.Sasl.csproj b/dotnet/Qpid.Sasl/Qpid.Sasl.csproj index 891d710379..6efbd5e272 100644 --- a/dotnet/Qpid.Sasl/Qpid.Sasl.csproj +++ b/dotnet/Qpid.Sasl/Qpid.Sasl.csproj @@ -38,6 +38,7 @@ + @@ -61,4 +62,4 @@ --> - + \ No newline at end of file -- cgit v1.2.1