You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by rg...@apache.org on 2007/01/29 11:46:30 UTC

svn commit: r501001 [2/2] - in /incubator/qpid/trunk/qpid/dotnet: ./ Qpid.Client.Tests/ Qpid.Client.Tests/Security/ Qpid.Client.Tests/connection/ Qpid.Client/ Qpid.Client/Client/ Qpid.Client/Client/Configuration/ Qpid.Client/Client/Handler/ Qpid.Client...

Added: incubator/qpid/trunk/qpid/dotnet/Qpid.Sasl/Configuration/SaslConfigurationSectionHandler.cs
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/dotnet/Qpid.Sasl/Configuration/SaslConfigurationSectionHandler.cs?view=auto&rev=501001
==============================================================================
--- incubator/qpid/trunk/qpid/dotnet/Qpid.Sasl/Configuration/SaslConfigurationSectionHandler.cs (added)
+++ incubator/qpid/trunk/qpid/dotnet/Qpid.Sasl/Configuration/SaslConfigurationSectionHandler.cs Mon Jan 29 02:46:27 2007
@@ -0,0 +1,83 @@
+/*
+ *
+ * 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.Configuration;
+using System.Text;
+using System.Xml;
+
+namespace Qpid.Sasl.Configuration
+{
+   /// <summary>
+   /// Defines the configuration section to configure extra 
+   /// Sasl client factories
+   /// </summary>
+   public class SaslConfigurationSectionHandler 
+      : IConfigurationSectionHandler
+   {
+      public object Create(object parent, object configContext, XmlNode section)
+      {
+         IList clientFactories = SaslConfiguration.GetDefaultClientFactories();
+
+         foreach ( XmlNode node in section.ChildNodes )
+         {
+            if ( node.LocalName == "clientFactories" )
+            {
+               ProcessFactories(node, clientFactories);
+            }
+         }
+
+         SaslConfiguration config = new SaslConfiguration(clientFactories);
+         return config;
+      }
+
+      
+      private void ProcessFactories(XmlNode node, IList factories)
+      {
+         foreach ( XmlNode child in node.ChildNodes )
+         {
+            Type type;
+            switch ( child.LocalName )
+            {
+            case "add":
+               type = Type.GetType(child.Attributes["type"].Value);
+               if ( !factories.Contains(type) )
+                  factories.Add(type);
+               break;
+            case "remove":
+               type = Type.GetType(child.Attributes["type"].Value);
+               if ( factories.Contains(type) )
+                  factories.Remove(type);
+               break;
+            case "clear":
+               factories.Clear();
+               break;
+            default:
+               // gives obsolete warning but needed for .NET 1.1 support
+               throw new ConfigurationException(string.Format("Unknown element '{0}' in section '{0}'", child.LocalName, node.LocalName));
+            }
+         }
+      }
+   } // class SaslConfigurationSectionHandler
+
+} // namespace Qpid.Sasl.Configuration
+

Added: incubator/qpid/trunk/qpid/dotnet/Qpid.Sasl/DefaultClientFactory.cs
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/dotnet/Qpid.Sasl/DefaultClientFactory.cs?view=auto&rev=501001
==============================================================================
--- incubator/qpid/trunk/qpid/dotnet/Qpid.Sasl/DefaultClientFactory.cs (added)
+++ incubator/qpid/trunk/qpid/dotnet/Qpid.Sasl/DefaultClientFactory.cs Mon Jan 29 02:46:27 2007
@@ -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.Text;
+
+using Qpid.Sasl.Mechanisms;
+
+namespace Qpid.Sasl
+{
+   public class DefaultClientFactory : ISaslClientFactory
+   {
+      private static readonly string[] SUPPORTED = new string[] { 
+               DigestSaslClient.Mechanism,
+               CramMD5SaslClient.Mechanism,
+               PlainSaslClient.Mechanism, 
+               AnonymousSaslClient.Mechanism,
+            };
+
+      public string[] GetSupportedMechanisms(IDictionary props)
+      {
+         if ( props == null )
+            throw new ArgumentNullException("props");
+
+         ArrayList vetoed = new ArrayList();
+
+         if ( props.Contains(SaslProperties.PolicyNoPlainText) ||
+             props.Contains(SaslProperties.PolicyNoDictionary) ||
+             props.Contains(SaslProperties.PolicyNoActive) ||
+             props.Contains(SaslProperties.PolicyForwardSecrecy) ||
+             props.Contains(SaslProperties.PolicyPassCredentials) )
+         {
+            vetoed.Add(CramMD5SaslClient.Mechanism);
+            vetoed.Add(PlainSaslClient.Mechanism);
+            vetoed.Add(AnonymousSaslClient.Mechanism);
+         } 
+         if ( props.Contains(SaslProperties.PolicyNoAnonymous) )
+         {
+            vetoed.Add(AnonymousSaslClient.Mechanism);
+         }
+
+         ArrayList available = new ArrayList();
+         foreach ( string mech in SUPPORTED )
+         {
+            if ( !vetoed.Contains(mech) )
+               available.Add(mech);
+         }
+         return (string[])available.ToArray(typeof(string));
+      }
+
+      public ISaslClient CreateClient(
+         string[] mechanisms, string authorizationId,
+         string protocol, string serverName, 
+         IDictionary props, ISaslCallbackHandler handler
+         )
+      {
+         foreach ( string mech in mechanisms )
+         {
+            switch ( mech )
+            {
+            case PlainSaslClient.Mechanism:
+               return new PlainSaslClient(authorizationId, props, handler);
+            case CramMD5SaslClient.Mechanism:
+               return new CramMD5SaslClient(authorizationId, props, handler);
+            case AnonymousSaslClient.Mechanism:
+               return new AnonymousSaslClient(authorizationId, props, handler);
+            case DigestSaslClient.Mechanism:
+               return new DigestSaslClient(authorizationId, serverName, protocol, props, handler);
+            }
+         }
+         // unknown mechanism
+         return null;
+      }
+   } // class DefaultClientFactory
+
+} // namespace Qpid.Sasl
+

Added: incubator/qpid/trunk/qpid/dotnet/Qpid.Sasl/ISaslCallbackHandler.cs
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/dotnet/Qpid.Sasl/ISaslCallbackHandler.cs?view=auto&rev=501001
==============================================================================
--- incubator/qpid/trunk/qpid/dotnet/Qpid.Sasl/ISaslCallbackHandler.cs (added)
+++ incubator/qpid/trunk/qpid/dotnet/Qpid.Sasl/ISaslCallbackHandler.cs Mon Jan 29 02:46:27 2007
@@ -0,0 +1,34 @@
+/*
+ *
+ * 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.Text;
+
+namespace Qpid.Sasl
+{
+   public interface ISaslCallbackHandler
+   {
+      void Handle(ISaslCallback[] callbacks);
+
+   } // interface ISaslCallbackHandler
+
+} // namespace Qpid.Sasl
+

Added: incubator/qpid/trunk/qpid/dotnet/Qpid.Sasl/ISaslClient.cs
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/dotnet/Qpid.Sasl/ISaslClient.cs?view=auto&rev=501001
==============================================================================
--- incubator/qpid/trunk/qpid/dotnet/Qpid.Sasl/ISaslClient.cs (added)
+++ incubator/qpid/trunk/qpid/dotnet/Qpid.Sasl/ISaslClient.cs Mon Jan 29 02:46:27 2007
@@ -0,0 +1,41 @@
+/*
+ *
+ * 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.Text;
+
+namespace Qpid.Sasl
+{
+   public interface ISaslClient
+   {
+      string MechanismName { get; }
+      bool HasInitialResponse { get; }
+      bool IsComplete { get; }
+
+      byte[] EvaluateChallenge(byte[] challenge);
+      object GetNegotiatedProperty(string propName);
+      byte[] Unwrap(byte[] buffer, int offset, int length);
+      byte[] Wrap(byte[] buffer, int offset, int lenght);
+
+   } // interface ISaslClient
+
+} // namespace Qpid.Sasl
+

Added: incubator/qpid/trunk/qpid/dotnet/Qpid.Sasl/ISaslClientFactory.cs
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/dotnet/Qpid.Sasl/ISaslClientFactory.cs?view=auto&rev=501001
==============================================================================
--- incubator/qpid/trunk/qpid/dotnet/Qpid.Sasl/ISaslClientFactory.cs (added)
+++ incubator/qpid/trunk/qpid/dotnet/Qpid.Sasl/ISaslClientFactory.cs Mon Jan 29 02:46:27 2007
@@ -0,0 +1,39 @@
+/*
+ *
+ * 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;
+
+namespace Qpid.Sasl
+{
+   public interface ISaslClientFactory
+   {
+      string[] GetSupportedMechanisms(IDictionary props);
+      ISaslClient CreateClient(
+         string[] mechanisms, string authorizationId, 
+         string protocol, string serverName, 
+         IDictionary props, ISaslCallbackHandler handler
+         );
+   } // interface ISaslClientFactory
+
+} // namespace Qpid.Sasl
+

Added: incubator/qpid/trunk/qpid/dotnet/Qpid.Sasl/MD5HMAC.cs
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/dotnet/Qpid.Sasl/MD5HMAC.cs?view=auto&rev=501001
==============================================================================
--- incubator/qpid/trunk/qpid/dotnet/Qpid.Sasl/MD5HMAC.cs (added)
+++ incubator/qpid/trunk/qpid/dotnet/Qpid.Sasl/MD5HMAC.cs Mon Jan 29 02:46:27 2007
@@ -0,0 +1,115 @@
+/*
+ *
+ * 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.Security.Cryptography;
+
+namespace Qpid.Sasl
+{
+   /// <summary>
+   /// Rough HMAC MD5 implementation as presented in
+   /// RFC 2104. Used because the HMACMD5 class in the 
+   /// .NET framework is not available in v1.1.
+   /// </summary>
+   public sealed class MD5HMAC : IDisposable
+   {
+      private const int BLOCK_LEN = 64;
+      private MD5 _hash;
+      private byte[] _key;
+      private byte[] _ipad;
+      private byte[] _opad;
+
+      public MD5HMAC(byte[] key)
+      {
+         if ( key == null || key.Length == 0 )
+            throw new ArgumentNullException("key");
+
+         _hash = new MD5CryptoServiceProvider();
+
+         byte[] theKey = key;
+         if ( theKey.Length > BLOCK_LEN )
+         {
+            theKey = _hash.ComputeHash(theKey);
+         }
+         // pad key with 0's up to BLOCK_LEN
+         _key = new byte[BLOCK_LEN];
+         Array.Copy(theKey, _key, theKey.Length);
+
+         CreatePads();
+      }
+
+      public byte[] ComputeHash(byte[] input)
+      {
+         // H(K XOR opad, H(K XOR ipad, text))
+         return H(_opad, H(_ipad, input));
+      }
+
+      public void Dispose()
+      {
+         if ( _hash != null )
+         {
+            ((IDisposable)_hash).Dispose();
+            _hash = null;
+         }
+      }
+
+      #region Private Methods
+      //
+      // Private Methods
+      //
+
+      private void CreatePads()
+      {
+         _ipad = new byte[BLOCK_LEN];
+         _opad = new byte[BLOCK_LEN];
+         for ( int i = 0; i < BLOCK_LEN; i++ )
+         {
+            _ipad[i] = 0x36;
+            _opad[i] = 0x5c;
+         }
+
+         XOR(_ipad, _key);
+         XOR(_opad, _key);
+      }
+
+      private static void XOR(byte[] dest, byte[] other)
+      {
+         // assume both are same size
+         for ( int i = 0; i < dest.Length; i++ )
+         {
+            dest[i] ^= other[i];
+         }
+      }
+
+      private byte[] H(byte[] v1, byte[] v2)
+      {
+         byte[] total = new byte[v1.Length + v2.Length];
+         Array.Copy(v1, total, v1.Length);
+         Array.Copy(v2, 0, total, v1.Length, v2.Length);
+
+         return _hash.ComputeHash(total);
+      }
+
+      #endregion // Private Methods
+
+   } // class MD5HMAC
+
+} // namespace Qpid.Sasl

Added: incubator/qpid/trunk/qpid/dotnet/Qpid.Sasl/Mechanisms/AnonymousSaslClient.cs
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/dotnet/Qpid.Sasl/Mechanisms/AnonymousSaslClient.cs?view=auto&rev=501001
==============================================================================
--- incubator/qpid/trunk/qpid/dotnet/Qpid.Sasl/Mechanisms/AnonymousSaslClient.cs (added)
+++ incubator/qpid/trunk/qpid/dotnet/Qpid.Sasl/Mechanisms/AnonymousSaslClient.cs Mon Jan 29 02:46:27 2007
@@ -0,0 +1,69 @@
+/*
+ *
+ * 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;
+
+namespace Qpid.Sasl.Mechanisms
+{
+   /// <summary>
+   /// Implements the ANONYMOUS authentication mechanism
+   /// as outlined in RFC 2245
+   /// </summary>
+   public class AnonymousSaslClient : SaslClient
+   {
+      public const string Mechanism = "ANONYMOUS";
+
+      public AnonymousSaslClient(
+         string authid, IDictionary properties, 
+         ISaslCallbackHandler handler)
+         : base(authid, null, null, properties, handler)
+      {
+      }
+
+      #region ISaslClient Implementation
+      //
+      // ISaslClient Implementation
+      //
+
+      public override string MechanismName
+      {
+         get { return Mechanism; }
+      }
+
+      public override bool HasInitialResponse
+      {
+         get { return true; }
+      }
+
+      public override byte[] EvaluateChallenge(byte[] challenge)
+      {
+         // ignore challenge
+         SetComplete();
+         return Encoding.UTF8.GetBytes(AuthorizationId);
+      }
+
+      #endregion // ISaslClient Implementation
+
+   } // class AnonymousSaslClient
+
+} // namespace Qpid.Sasl.Mechanisms

Added: incubator/qpid/trunk/qpid/dotnet/Qpid.Sasl/Mechanisms/CramMD5SaslClient.cs
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/dotnet/Qpid.Sasl/Mechanisms/CramMD5SaslClient.cs?view=auto&rev=501001
==============================================================================
--- incubator/qpid/trunk/qpid/dotnet/Qpid.Sasl/Mechanisms/CramMD5SaslClient.cs (added)
+++ incubator/qpid/trunk/qpid/dotnet/Qpid.Sasl/Mechanisms/CramMD5SaslClient.cs Mon Jan 29 02:46:27 2007
@@ -0,0 +1,91 @@
+/*
+ *
+ * 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 Qpid.Sasl.Mechanisms
+{
+   /// <summary>
+   /// Implements the CRAM-MD5 authentication mechanism as outlined
+   /// in RFC 2195
+   /// </summary>
+   public class CramMD5SaslClient : SaslClient
+   {
+      public const string Mechanism = "CRAM-MD5";
+      private const int MinPwdLen = 16;
+
+      public CramMD5SaslClient(
+         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;
+         string passwd = pwdCB.Text.PadRight(MinPwdLen, '\0');
+
+         byte[] secret = Encoding.UTF8.GetBytes(passwd);
+
+         //using ( HMAC hmac = new HMACMD5(secret) )
+         using ( MD5HMAC hmac = new MD5HMAC(secret) )
+         {
+            byte[] value = hmac.ComputeHash(challenge);
+            string encoded = ToHex(value);
+            SetComplete();
+            return Encoding.UTF8.GetBytes(username + " " + encoded);
+         }
+
+      }
+
+      #endregion // ISaslClient Implementation
+
+   } // class CramMD5SaslClient
+
+} // namespace Qpid.Sasl.Mechanisms

Added: incubator/qpid/trunk/qpid/dotnet/Qpid.Sasl/Mechanisms/DigestSaslClient.cs
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/dotnet/Qpid.Sasl/Mechanisms/DigestSaslClient.cs?view=auto&rev=501001
==============================================================================
--- incubator/qpid/trunk/qpid/dotnet/Qpid.Sasl/Mechanisms/DigestSaslClient.cs (added)
+++ incubator/qpid/trunk/qpid/dotnet/Qpid.Sasl/Mechanisms/DigestSaslClient.cs Mon Jan 29 02:46:27 2007
@@ -0,0 +1,576 @@
+/*
+ *
+ * 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.Globalization;
+using System.Security.Cryptography;
+using System.Text;
+
+namespace Qpid.Sasl.Mechanisms
+{
+
+   /// <summary>
+   /// Implements the DIGEST MD5 authentication mechanism
+   /// as outlined in RFC 2831
+   /// </summary>
+   public class DigestSaslClient : SaslClient
+   {
+      public const string Mechanism = "DIGEST-MD5";
+      private static readonly MD5 _md5 = new MD5CryptoServiceProvider();
+      private int _state;
+      private string _cnonce;
+      private Encoding _encoding = Encoding.UTF8;
+
+      public string Cnonce
+      {
+         get { return _cnonce; }
+         set { _cnonce = value; }
+      }
+
+      public DigestSaslClient(
+         string authid, string serverName, string protocol, 
+         IDictionary properties, ISaslCallbackHandler handler)
+         : base(authid, serverName, protocol, properties, handler)
+      {
+         _cnonce = Guid.NewGuid().ToString("N");
+      }
+
+      #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");
+
+         switch ( _state++ )
+         {
+         case 0: return OnInitialChallenge(challenge);
+         case 1: return OnFinalResponse(challenge);
+         }
+         throw new SaslException("Invalid State for authentication");
+      }
+
+      #endregion // ISaslClient Implementation
+
+      
+      #region Private Methods
+      //
+      // Private Methods
+      //
+
+      /// <summary>
+      /// Process the first challenge from the server
+      /// and calculate a response
+      /// </summary>
+      /// <param name="challenge">The server issued challenge</param>
+      /// <returns>Client response</returns>
+      private byte[] OnInitialChallenge(byte[] challenge)
+      {
+         DigestChallenge dch = 
+            DigestChallenge.Parse(_encoding.GetString(challenge));
+         // validate input challenge
+         if ( dch.Nonce == null || dch.Nonce.Length == 0 )
+            throw new SaslException("Nonce value missing in server challenge");
+         if ( dch.Algorithm != "md5-sess" )
+            throw new SaslException("Invalid or missing algorithm value in server challenge");
+
+
+         NameCallback nameCB = new NameCallback(AuthorizationId);
+         PasswordCallback pwdCB = new PasswordCallback();
+         RealmCallback realmCB = new RealmCallback(dch.Realm);
+         ISaslCallback[] callbacks = { nameCB, pwdCB, realmCB };
+         Handler.Handle(callbacks);
+
+         DigestResponse response = new DigestResponse();
+         response.Username = nameCB.Text;
+         response.Realm = realmCB.Text;
+         response.Nonce = dch.Nonce;
+         response.Cnonce = Cnonce;
+         response.NonceCount = 1;
+         response.Qop = DigestQop.Auth; // only auth supported for now
+         response.DigestUri = Protocol.ToLower() + "/" + ServerName;
+         response.MaxBuffer = dch.MaxBuffer;
+         response.Charset = dch.Charset;
+         response.Cipher = null; // not supported for now
+         response.Authzid = AuthorizationId;
+         response.AuthParam = dch.AuthParam;
+
+         response.Response = CalculateResponse(
+            nameCB.Text, realmCB.Text, pwdCB.Text, 
+            dch.Nonce, response.NonceCount, response.Qop, response.DigestUri
+            );
+
+         return _encoding.GetBytes(response.ToString());
+      }
+
+      /// <summary>
+      /// Process the second server challenge
+      /// </summary>
+      /// <param name="challenge">Server issued challenge</param>
+      /// <returns>The client response</returns>
+      private byte[] OnFinalResponse(byte[] challenge)
+      {
+         DigestChallenge dch = 
+            DigestChallenge.Parse(_encoding.GetString(challenge));
+
+         if ( dch.Rspauth == null || dch.Rspauth.Length == 0 )
+            throw new SaslException("Expected 'rspauth' in server challenge not found");
+
+         SetComplete();
+         return new byte[0];
+      }
+
+      
+      
+      /// <summary>
+      /// Calculate the response field of the client response
+      /// </summary>
+      /// <param name="username">The user name</param>
+      /// <param name="realm">The realm</param>
+      /// <param name="passwd">The user's password</param>
+      /// <param name="nonce">Server nonce value</param>
+      /// <param name="nc">Client nonce count (always 1)</param>
+      /// <param name="qop">Quality of Protection</param>
+      /// <param name="digestUri">Digest-URI</param>
+      /// <returns>The value for the response field</returns>
+      private string CalculateResponse(
+         string username, string realm, string passwd, 
+         string nonce, int nc, string qop, string digestUri
+         )
+      {
+         string a1 = CalcHexA1(username, realm, passwd, nonce);
+         string a2 = CalcHexA2(digestUri, qop);
+
+         string ncs = nc.ToString("x8", CultureInfo.InvariantCulture);
+         StringBuilder prekd = new StringBuilder();
+         prekd.Append(a1).Append(':').Append(nonce).Append(':')
+            .Append(ncs).Append(':').Append(Cnonce)
+            .Append(':').Append(qop).Append(':').Append(a2);
+
+         return ToHex(CalcH(_encoding.GetBytes(prekd.ToString())));
+      }
+
+      private string CalcHexA1(
+         string username, string realm, 
+         string passwd, string nonce
+         )
+      {
+         bool hasAuthId = AuthorizationId != null && AuthorizationId.Length > 0;
+
+         string premd = username + ":" + realm + ":" + passwd;
+         byte[] temp1 = CalcH(_encoding.GetBytes(premd));
+         
+
+         int a1len = 16 + 1 + nonce.Length + 1 + Cnonce.Length;
+         if ( hasAuthId )
+            a1len += 1 + AuthorizationId.Length;
+
+         byte[] buffer = new byte[a1len];
+         Array.Copy(temp1, buffer, temp1.Length);
+
+         string p2 = ":" + nonce + ":" + Cnonce;
+         if ( hasAuthId )
+            p2 += ":" + AuthorizationId;
+
+         byte[] temp2 = _encoding.GetBytes(p2);
+         Array.Copy(temp2, 0, buffer, 16, temp2.Length);
+
+         return ToHex(CalcH(buffer));
+      }
+
+      private string CalcHexA2(string digestUri, string qop)
+      {
+         string a2 = "AUTHENTICATE:" + digestUri;
+         if ( qop != DigestQop.Auth )
+            a2 += ":00000000000000000000000000000000";
+         return ToHex(CalcH(_encoding.GetBytes(a2)));
+      }
+
+      private static byte[] CalcH(byte[] value)
+      {
+         return _md5.ComputeHash(value);
+      }
+
+      #endregion // Private Methods
+
+
+   } // class DigestSaslClient
+
+
+   /// <summary>
+   /// Available QOP options in the DIGEST scheme
+   /// </summary>
+   public sealed class DigestQop
+   {
+      public const string Auth = "auth";
+      public const string AuthInt = "auth-int";
+      public const string AuthConf = "auth-conf";
+   } // class DigestQop
+
+
+   /// <summary>
+   /// Represents and parses a digest server challenge
+   /// </summary>
+   public class DigestChallenge
+   {
+      private string _realm = "localhost";
+      private string _nonce;
+      private string[] _qopOptions = { DigestQop.Auth };
+      private bool _stale;
+      private int _maxBuffer = 65536;
+      private string _charset = "ISO 8859-1";
+      private string _algorithm;
+      private string[] _cipherOptions;
+      private string _authParam;
+      private string _rspauth;
+
+      #region Properties
+      //
+      // Properties
+      //
+
+      public string Realm
+      {
+         get { return _realm; }
+      }
+
+      public string Nonce
+      {
+         get { return _nonce; }
+      }
+
+      public string[] QopOptions
+      {
+         get { return _qopOptions; }
+      }
+
+      public bool Stale
+      {
+         get { return _stale; }
+      }
+
+      public int MaxBuffer
+      {
+         get { return _maxBuffer; }
+         set { _maxBuffer = value; }
+      }
+
+      public string Charset
+      {
+         get { return _charset; }
+      }
+
+      public string Algorithm
+      {
+         get { return _algorithm; }
+      }
+
+      public string[] CipherOptions
+      {
+         get { return _cipherOptions; }
+      }
+
+      public string AuthParam
+      {
+         get { return _authParam; }
+      }
+
+      public string Rspauth
+      {
+         get { return _rspauth; }
+      }
+
+      #endregion // Properties
+
+      public static DigestChallenge Parse(string challenge)
+      {
+         DigestChallenge parsed = new DigestChallenge();
+         StringDictionary parts = ParseParameters(challenge);
+         foreach ( string optname in parts.Keys )
+         {
+            switch ( optname )
+            {
+            case "realm":
+               parsed._realm = parts[optname];
+               break;
+            case "nonce":
+               parsed._nonce = parts[optname];
+               break;
+            case "qop-options":
+               parsed._qopOptions = GetOptions(parts[optname]);
+               break;
+            case "cipher-opts":
+               parsed._cipherOptions = GetOptions(parts[optname]);
+               break;
+            case "stale":
+               parsed._stale = Convert.ToBoolean(parts[optname], CultureInfo.InvariantCulture);
+               break;
+            case "maxbuf":
+               parsed._maxBuffer = Convert.ToInt32(parts[optname], CultureInfo.InvariantCulture);
+               break;
+            case "charset":
+               parsed._charset = parts[optname];
+               break;
+            case "algorithm":
+               parsed._algorithm = parts[optname];
+               break;
+            case "auth-param":
+               parsed._authParam = parts[optname];
+               break;
+            case "rspauth":
+               parsed._rspauth = parts[optname];
+               break;
+            }
+         }
+
+         return parsed;
+      }
+
+
+      public static StringDictionary ParseParameters(string source)
+      {
+         if ( source == null )
+            throw new ArgumentNullException("source");
+
+         StringDictionary ret = new StringDictionary();
+
+         string remaining = source.Trim();
+         while ( remaining.Length > 0 )
+         {
+            int equals = remaining.IndexOf('=');
+            if ( equals < 0 )
+               break;
+
+            string optname = remaining.Substring(0, equals).Trim();
+            remaining = remaining.Substring(equals + 1);
+
+            string value = ParseQuoted(ref remaining);
+            ret[optname] = value.Trim();
+         }
+         return ret;
+      }
+
+      private static string ParseQuoted(ref string str)
+      {
+         string ns = str.TrimStart();
+
+         int start = 0;
+         bool quoted = ns[0] == '\"';
+         if ( quoted ) start++;
+         bool inquotes = quoted;
+         bool escaped = false;
+
+         int pos = start;
+         for ( ; pos < ns.Length; pos++ )
+         {
+            if ( !inquotes && ns[pos] == ',' )
+               break;
+
+            // at end of quotes?
+            if ( quoted && !escaped && ns[pos] == '\"' ) 
+               inquotes = false;
+            // is this char an escape for the next one?
+            escaped = inquotes && ns[pos] == '\\';
+         }
+         // pos has end of string
+         string value = ns.Substring(start, pos-start).Trim();
+         if ( quoted )
+         {
+            // remove trailing quote
+            value = value.Substring(0, value.Length - 1);
+         }
+         str = ns.Substring(pos < ns.Length-1 ? pos+1 : pos);
+         return value;
+      }
+
+      private static string[] GetOptions(string value)
+      {
+         return value.Split(' ');
+      }
+
+   } // class DigestChallenge
+
+
+   /// <summary>
+   /// Represents and knows how to write a 
+   /// digest client response
+   /// </summary>
+   public class DigestResponse
+   {
+      private string _username;
+      private string _realm;
+      private string _nonce;
+      private string _cnonce;
+      private int _nonceCount;
+      private string _qop;
+      private string _digestUri;
+      private string _response;
+      private int _maxBuffer;
+      private string _charset;
+      private string _cipher;
+      private string _authzid;
+      private string _authParam;
+
+      #region Properties
+      //
+      // Properties
+      //
+
+      public string Username
+      {
+         get { return _username; }
+         set { _username = value; }
+      }
+
+      public string Realm
+      {
+         get { return _realm; }
+         set { _realm = value; }
+      }
+
+      public string Nonce
+      {
+         get { return _nonce; }
+         set { _nonce = value; }
+      }
+
+      public string Cnonce
+      {
+         get { return _cnonce; }
+         set { _cnonce = value; }
+      }
+
+      public int NonceCount
+      {
+         get { return _nonceCount; }
+         set { _nonceCount = value; }
+      }
+
+      public string Qop
+      {
+         get { return _qop; }
+         set { _qop = value; }
+      }
+
+      public string DigestUri
+      {
+         get { return _digestUri; }
+         set { _digestUri = value; }
+      }
+
+      public string Response
+      {
+         get { return _response; }
+         set { _response = value; }
+      }
+
+      public int MaxBuffer
+      {
+         get { return _maxBuffer; }
+         set { _maxBuffer = value; }
+      }
+
+      public string Charset
+      {
+         get { return _charset; }
+         set { _charset = value; }
+      }
+
+      public string Cipher
+      {
+         get { return _cipher; }
+         set { _cipher = value; }
+      }
+
+      public string Authzid
+      {
+         get { return _authzid; }
+         set { _authzid = value; }
+      }
+
+      public string AuthParam
+      {
+         get { return _authParam; }
+         set { _authParam = value; }
+      }
+
+      #endregion // Properties
+
+
+      public override string ToString()
+      {
+         StringBuilder buffer = new StringBuilder();
+         Pair(buffer, "username", Username, true);
+         Pair(buffer, "realm", Realm, true);
+         Pair(buffer, "nonce", Nonce, true);
+         Pair(buffer, "cnonce", Cnonce, true);
+         string nc = NonceCount.ToString("x8", CultureInfo.InvariantCulture);
+         Pair(buffer, "nc", nc, false);
+         Pair(buffer, "qop", Qop, false);
+         Pair(buffer, "digest-uri", DigestUri, true);
+         Pair(buffer, "response", Response, true);
+         string maxBuffer = MaxBuffer.ToString(CultureInfo.InvariantCulture);
+         Pair(buffer, "maxbuf", maxBuffer, false);
+         Pair(buffer, "charset", Charset, false);
+         Pair(buffer, "cipher", Cipher, false);
+         Pair(buffer, "authzid", Authzid, true);
+         Pair(buffer, "auth-param", AuthParam, true);
+
+         return buffer.ToString().TrimEnd(',');
+      }
+
+      private static void Pair(StringBuilder buffer, string name, string value, bool quoted)
+      {
+         if ( value != null && value.Length > 0 )
+         {
+            buffer.Append(name);
+            buffer.Append('=');
+            if ( quoted )
+            {
+               buffer.Append('\"');
+               buffer.Append(value.Replace("\"", "\\\""));
+               buffer.Append('\"');
+            } else
+            {
+               buffer.Append(value);
+            }
+            buffer.Append(',');
+         }
+      }
+
+   } // class DigestResponse
+
+} // namespace Qpid.Sasl.Mechanisms

Added: incubator/qpid/trunk/qpid/dotnet/Qpid.Sasl/Mechanisms/PlainSaslClient.cs
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/dotnet/Qpid.Sasl/Mechanisms/PlainSaslClient.cs?view=auto&rev=501001
==============================================================================
--- incubator/qpid/trunk/qpid/dotnet/Qpid.Sasl/Mechanisms/PlainSaslClient.cs (added)
+++ incubator/qpid/trunk/qpid/dotnet/Qpid.Sasl/Mechanisms/PlainSaslClient.cs Mon Jan 29 02:46:27 2007
@@ -0,0 +1,81 @@
+/*
+ *
+ * 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;
+
+namespace Qpid.Sasl.Mechanisms
+{
+
+   /// <summary>
+   /// Implements the PLAIN authentication mechanism
+   /// as outlined in RFC 4616
+   /// </summary>
+   public class PlainSaslClient : SaslClient
+   {
+      public const string Mechanism = "PLAIN";
+
+      public PlainSaslClient(
+         string authid, IDictionary properties, 
+         ISaslCallbackHandler handler)
+         : base(authid, null, null, properties, handler)
+      {
+      }
+
+      #region ISaslClient Implementation
+      //
+      // ISaslClient Implementation
+      //
+
+      public override string MechanismName
+      {
+         get { return Mechanism; }
+      }
+
+      public override bool HasInitialResponse
+      {
+         get { return true; }
+      }
+
+      public override byte[] EvaluateChallenge(byte[] challenge)
+      {
+         // ignore challenge
+
+         NameCallback nameCB = new NameCallback();
+         PasswordCallback pwdCB = new PasswordCallback();
+         ISaslCallback[] callbacks = { nameCB, pwdCB };
+         Handler.Handle(callbacks);
+
+         string username = nameCB.Text;
+         string authid = AuthorizationId;
+         string passwd = pwdCB.Text;
+
+         string response = 
+            string.Format("{0}\0{1}\0{2}", authid, username, passwd);
+         SetComplete();
+         return Encoding.UTF8.GetBytes(response);
+      }
+
+      #endregion // ISaslClient Implementation
+
+   } // class PlainSaslClient
+} // namespace Qpid.Sasl.Mechanisms

Added: incubator/qpid/trunk/qpid/dotnet/Qpid.Sasl/Properties/AssemblyInfo.cs
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/dotnet/Qpid.Sasl/Properties/AssemblyInfo.cs?view=auto&rev=501001
==============================================================================
--- incubator/qpid/trunk/qpid/dotnet/Qpid.Sasl/Properties/AssemblyInfo.cs (added)
+++ incubator/qpid/trunk/qpid/dotnet/Qpid.Sasl/Properties/AssemblyInfo.cs Mon Jan 29 02:46:27 2007
@@ -0,0 +1,37 @@
+using System;
+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("Qpid.Sasl")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Apache Qpid")]
+[assembly: AssemblyProduct("Apache Qpid")]
+[assembly: AssemblyCopyright("Copyright © 2007 The 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("27ea23e4-6f84-4a54-8f1f-5725e6d767cc")]
+
+// 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("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
+[assembly: CLSCompliant(true)]

Added: incubator/qpid/trunk/qpid/dotnet/Qpid.Sasl/Qpid.Sasl.csproj
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/dotnet/Qpid.Sasl/Qpid.Sasl.csproj?view=auto&rev=501001
==============================================================================
--- incubator/qpid/trunk/qpid/dotnet/Qpid.Sasl/Qpid.Sasl.csproj (added)
+++ incubator/qpid/trunk/qpid/dotnet/Qpid.Sasl/Qpid.Sasl.csproj Mon Jan 29 02:46:27 2007
@@ -0,0 +1,63 @@
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>8.0.50727</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{1465B0EE-6452-42A6-AB73-B2F9EABEEE75}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>Qpid.Sasl</RootNamespace>
+    <AssemblyName>Qpid.Sasl</AssemblyName>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\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\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Callbacks.cs" />
+    <Compile Include="Configuration\SaslConfiguration.cs" />
+    <Compile Include="Configuration\SaslConfigurationSectionHandler.cs" />
+    <Compile Include="MD5HMAC.cs" />
+    <Compile Include="SaslException.cs" />
+    <Compile Include="Mechanisms\AnonymousSaslClient.cs" />
+    <Compile Include="Mechanisms\DigestSaslClient.cs" />
+    <Compile Include="Sasl.cs" />
+    <Compile Include="DefaultClientFactory.cs" />
+    <Compile Include="ISaslCallbackHandler.cs" />
+    <Compile Include="ISaslClientFactory.cs" />
+    <Compile Include="Mechanisms\CramMD5SaslClient.cs" />
+    <Compile Include="SaslProperties.cs" />
+    <Compile Include="ISaslClient.cs" />
+    <Compile Include="Mechanisms\PlainSaslClient.cs" />
+    <Compile Include="SaslClient.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+  </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>

Added: incubator/qpid/trunk/qpid/dotnet/Qpid.Sasl/Sasl.cs
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/dotnet/Qpid.Sasl/Sasl.cs?view=auto&rev=501001
==============================================================================
--- incubator/qpid/trunk/qpid/dotnet/Qpid.Sasl/Sasl.cs (added)
+++ incubator/qpid/trunk/qpid/dotnet/Qpid.Sasl/Sasl.cs Mon Jan 29 02:46:27 2007
@@ -0,0 +1,115 @@
+/*
+ *
+ * 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.Configuration;
+using System.Text;
+
+using Qpid.Sasl.Configuration;
+
+namespace Qpid.Sasl
+{
+   /// <summary>
+   /// Static class used to access the SASL functionality. 
+   /// The core SASL mechanism is described in RFC 2222.
+   /// </summary>
+   /// <remarks>
+   /// Only client side mechanisms are implemented.
+   /// <para>
+   /// New client side factories can be added programatically using the 
+   /// RegisterClientFactory method, or through the application 
+   /// configuration file, like this:
+   /// </para>
+   /// <example><![CDATA[
+   /// <configuration>
+   ///   <configSections>
+   ///      <section name="qpid.sasl" type="Qpid.Sasl.Configuration.SaslConfigurationSectionHandler, Qpid.Sasl"/>
+   ///   </configSections>
+   ///
+   ///   <qpid.sasl>
+   ///      <clientFactories>
+   ///         <add type="Qpid.Sasl.Tests.TestClientFactory, Qpid.Sasl.Tests"/>
+   ///      </clientFactories>
+   ///   </qpid.sasl>
+   /// </configuration>
+   /// ]]></example>
+   /// </remarks>
+   public sealed class Sasl
+   {
+      private static IList _clientFactories;
+      
+
+      static Sasl()
+      {
+         SaslConfiguration config = SaslConfiguration.GetConfiguration();
+         _clientFactories = config.ClientFactories;
+      }
+      private Sasl()
+      {
+      }
+
+      public static ISaslClient CreateClient(
+         string[] mechanisms, string authorizationId,
+         string protocol, string serverName,
+         IDictionary props, ISaslCallbackHandler handler
+         )
+      {
+         ISaslClientFactory factory = FindFactory(mechanisms, props);
+         if ( factory == null )
+            return null;
+
+         return factory.CreateClient (
+            mechanisms, authorizationId, 
+            protocol, serverName, props, handler
+            );
+      }
+
+      public static void RegisterClientFactory(ISaslClientFactory factory)
+      {
+         lock ( _clientFactories )
+         {
+            _clientFactories.Add(factory);
+         }
+      }
+
+      private static ISaslClientFactory FindFactory(string[] mechanisms, IDictionary props)
+      {
+         lock ( _clientFactories )
+         {
+            foreach ( ISaslClientFactory factory in _clientFactories )
+            {
+               string[] mechs = factory.GetSupportedMechanisms(props);
+               foreach ( string m1 in mechs )
+               {
+                  foreach (string m2 in mechanisms )
+                  {
+                     if ( m1 == m2 )
+                        return factory;
+                  }
+               }
+            }
+            return null;
+         }
+      }
+   } // class Sasl
+
+} // namespace Qpid.Sasl.Mechanisms

Added: incubator/qpid/trunk/qpid/dotnet/Qpid.Sasl/SaslClient.cs
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/dotnet/Qpid.Sasl/SaslClient.cs?view=auto&rev=501001
==============================================================================
--- incubator/qpid/trunk/qpid/dotnet/Qpid.Sasl/SaslClient.cs (added)
+++ incubator/qpid/trunk/qpid/dotnet/Qpid.Sasl/SaslClient.cs Mon Jan 29 02:46:27 2007
@@ -0,0 +1,145 @@
+/*
+ *
+ * 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.Globalization;
+using System.Text;
+
+namespace Qpid.Sasl
+{
+   public abstract class SaslClient : ISaslClient
+   {
+      private bool _isComplete;
+      private IDictionary _properties;
+      private string _authorizationId;
+      private string _serverName;
+      private string _protocol;
+      private ISaslCallbackHandler _handler;
+
+      protected string AuthorizationId
+      {
+         get { return _authorizationId; }
+      }
+      protected string ServerName
+      {
+         get { return _serverName; }
+      }
+
+      protected string Protocol
+      {
+         get { return _protocol; }
+      }
+
+      protected ISaslCallbackHandler Handler
+      {
+         get { return _handler; }
+      }
+
+      protected IDictionary Properties
+      {
+         get { return _properties; }
+      }
+
+      protected SaslClient(
+         string authid, string serverName, 
+         string protocol, IDictionary properties, 
+         ISaslCallbackHandler handler)
+      {
+         if ( properties == null )
+            throw new ArgumentNullException("properties");
+         if ( handler == null )
+            throw new ArgumentNullException("handler");
+
+         _authorizationId = authid==null ? "" : authid;
+         _serverName = serverName;
+         _protocol = protocol;
+         _properties = properties;
+         _handler = handler;
+
+         if ( _serverName == null || _serverName.Length == 0 )
+         {
+            _serverName = System.Net.Dns.GetHostName();
+         }
+      }
+
+
+
+
+      #region ISaslClient Implementation
+      //
+      // ISaslClient Implementation
+      //
+
+      public abstract string MechanismName { get; }
+
+      public abstract bool HasInitialResponse { get; }
+
+      public bool IsComplete
+      {
+         get { return _isComplete; }
+      }
+
+      public abstract byte[] EvaluateChallenge(byte[] challenge);
+
+      public virtual object GetNegotiatedProperty(string propName)
+      {
+         return null;
+      }
+
+      public virtual byte[] Unwrap(byte[] buffer, int offset, int length)
+      {
+         throw new NotImplementedException();
+      }
+
+      public virtual byte[] Wrap(byte[] buffer, int offset, int lenght)
+      {
+         throw new NotImplementedException();
+      }
+
+      #endregion // ISaslClient Implementation
+
+
+      #region Helper Methods
+      //
+      // Helper Methods
+      //
+
+      protected void SetComplete()
+      {
+         _isComplete = true;
+      }
+
+      protected static string ToHex(byte[] buffer)
+      {
+         StringBuilder builder = new StringBuilder();
+         foreach ( byte b in buffer )
+         {
+            builder.Append(b.ToString("x2", CultureInfo.InvariantCulture));
+         }
+         return builder.ToString();
+      }
+
+      #endregion // Helper Methods
+
+   } // class SaslClient
+
+} // namespace Qpid.Sasl.Mechanisms

Added: incubator/qpid/trunk/qpid/dotnet/Qpid.Sasl/SaslException.cs
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/dotnet/Qpid.Sasl/SaslException.cs?view=auto&rev=501001
==============================================================================
--- incubator/qpid/trunk/qpid/dotnet/Qpid.Sasl/SaslException.cs (added)
+++ incubator/qpid/trunk/qpid/dotnet/Qpid.Sasl/SaslException.cs Mon Jan 29 02:46:27 2007
@@ -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;
+using System.Collections;
+using System.Runtime.Serialization;
+using System.Text;
+
+namespace Qpid.Sasl
+{
+   /// <summary>
+   /// Reports an exception during the processing of an SASL
+   /// Operation. Only used for authentication-relared errors
+   /// </summary>
+   [Serializable]
+   public class SaslException : Exception
+   {
+      public SaslException()
+      {
+      }
+
+      public SaslException(string message)
+         : base(message)
+      {
+      }
+      public SaslException(string message, Exception innerException)
+         : base(message, innerException)
+      {
+      }
+
+      protected SaslException(SerializationInfo info, StreamingContext ctxt)
+         : base(info, ctxt)
+      {
+      }
+
+   } // class SaslException
+
+} // namespace Qpid.Sasl.Mechanisms

Added: incubator/qpid/trunk/qpid/dotnet/Qpid.Sasl/SaslProperties.cs
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/dotnet/Qpid.Sasl/SaslProperties.cs?view=auto&rev=501001
==============================================================================
--- incubator/qpid/trunk/qpid/dotnet/Qpid.Sasl/SaslProperties.cs (added)
+++ incubator/qpid/trunk/qpid/dotnet/Qpid.Sasl/SaslProperties.cs Mon Jan 29 02:46:27 2007
@@ -0,0 +1,42 @@
+/*
+ *
+ * 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;
+
+namespace Qpid.Sasl
+{
+   public sealed class SaslProperties
+   {
+      public const string PolicyNoPlainText = "NOPLAINTEXT";
+      public const string PolicyNoActive = "NOACTIVE";
+      public const string PolicyNoDictionary = "NODICTIONARY";
+      public const string PolicyNoAnonymous = "NOANONYMOUS";
+      public const string PolicyForwardSecrecy = "FORWARD_SECRECY";
+      public const string PolicyPassCredentials = "PASS_CREDENTIALS";
+
+      public const string Qop = "QOP";
+      public const string Strength = "STRENGTH";
+ 
+   } // class SaslProperties
+
+} // namespace Qpid.Sasl.Mechanisms