Author: atsushi
Date: 2007-03-22 10:34:16 -0500 (Thu, 22 Mar 2007)
New Revision: 74813

Modified:
   
trunk/olive/class/System.ServiceModel/System.ServiceModel.Security.Tokens/ChangeLog
   
trunk/olive/class/System.ServiceModel/System.ServiceModel.Security.Tokens/SslSecurityTokenAuthenticator.cs
   
trunk/olive/class/System.ServiceModel/System.ServiceModel.Security.Tokens/SslSecurityTokenProvider.cs
   
trunk/olive/class/System.ServiceModel/System.ServiceModel.Security.Tokens/TlsClientSession.cs
Log:
2007-03-22  Atsushi Enomoto  <[EMAIL PROTECTED]>

        * TlsClientSession.cs, SslSecurityTokenProvider.cs,
          SslSecurityTokenAuthenticator.cs : added hash calculation support,
          not working yet though (probably at service side).



Modified: 
trunk/olive/class/System.ServiceModel/System.ServiceModel.Security.Tokens/ChangeLog
===================================================================
--- 
trunk/olive/class/System.ServiceModel/System.ServiceModel.Security.Tokens/ChangeLog
 2007-03-22 15:29:11 UTC (rev 74812)
+++ 
trunk/olive/class/System.ServiceModel/System.ServiceModel.Security.Tokens/ChangeLog
 2007-03-22 15:34:16 UTC (rev 74813)
@@ -1,3 +1,9 @@
+2007-03-22  Atsushi Enomoto  <[EMAIL PROTECTED]>
+
+       * TlsClientSession.cs, SslSecurityTokenProvider.cs,
+         SslSecurityTokenAuthenticator.cs : added hash calculation support,
+         not working yet though (probably at service side).
+
 2007-03-20  Atsushi Enomoto  <[EMAIL PROTECTED]>
 
        * SslSecurityTokenAuthenticator.cs : don't reuse ContextId for SCT.

Modified: 
trunk/olive/class/System.ServiceModel/System.ServiceModel.Security.Tokens/SslSecurityTokenAuthenticator.cs
===================================================================
--- 
trunk/olive/class/System.ServiceModel/System.ServiceModel.Security.Tokens/SslSecurityTokenAuthenticator.cs
  2007-03-22 15:29:11 UTC (rev 74812)
+++ 
trunk/olive/class/System.ServiceModel/System.ServiceModel.Security.Tokens/SslSecurityTokenAuthenticator.cs
  2007-03-22 15:34:16 UTC (rev 74813)
@@ -28,12 +28,14 @@
 using System;
 using System.Collections.Generic;
 using System.Collections.ObjectModel;
+using System.IO;
 using System.Net.Security;
 using System.IdentityModel.Policy;
 using System.IdentityModel.Selectors;
 using System.IdentityModel.Tokens;
 using System.Security.Cryptography;
 using System.Security.Cryptography.X509Certificates;
+using System.Security.Cryptography.Xml;
 using System.ServiceModel.Channels;
 using System.ServiceModel.Description;
 using System.ServiceModel.Security;
@@ -111,20 +113,52 @@
                                return ProcessClientKeyExchange (request);
                }
 
-               Dictionary<string,TlsServerSession> sessions =
-                       new Dictionary<string,TlsServerSession> ();
+               class TlsServerSessionInfo
+               {
+                       public TlsServerSessionInfo (string context, 
TlsServerSession tls)
+                       {
+                               ContextId = context;
+                               Tls = tls;
+                       }
 
+                       public string ContextId;
+                       public TlsServerSession Tls;
+                       public MemoryStream Messages = new MemoryStream ();
+               }
+
+               Dictionary<string,TlsServerSessionInfo> sessions =
+                       new Dictionary<string,TlsServerSessionInfo> ();
+
+               void AppendNegotiationMessageXml (XmlReader reader, 
TlsServerSessionInfo tlsInfo)
+               {
+                       XmlDsigExcC14NTransform t = new XmlDsigExcC14NTransform 
();
+                       XmlDocument doc = new XmlDocument ();
+                       doc.PreserveWhitespace = true;
+                       reader.MoveToContent ();
+                       doc.AppendChild (doc.ReadNode (reader));
+                       t.LoadInput (doc);
+                       MemoryStream stream = (MemoryStream) t.GetOutput ();
+                       byte [] bytes = stream.ToArray ();
+                       tlsInfo.Messages.Write (bytes, 0, bytes.Length);
+               }
+
                Message ProcessClientHello (Message request)
                {
+                       // FIXME: use correct buffer size
+                       MessageBuffer buffer = request.CreateBufferedCopy 
(0x10000);
                        WSTrustRequestSecurityTokenReader reader =
-                               new WSTrustRequestSecurityTokenReader 
(request.GetReaderAtBodyContents (), SecurityTokenSerializer);
+                               new WSTrustRequestSecurityTokenReader 
(buffer.CreateMessage ().GetReaderAtBodyContents (), SecurityTokenSerializer);
                        reader.Read ();
 
                        if (sessions.ContainsKey (reader.Value.Context))
                                throw new InvalidOperationException 
(String.Format ("The context '{0}' already exists in this SSL negotiation 
manager", reader.Value.Context));
 
                        TlsServerSession tls = new TlsServerSession 
(owner.Manager.ServiceCredentials.ServiceCertificate.Certificate, 
owner.IsMutual);
+                       TlsServerSessionInfo tlsInfo = new TlsServerSessionInfo 
(
+                               reader.Value.Context, tls);
 
+                       AppendNegotiationMessageXml (buffer.CreateMessage 
().GetReaderAtBodyContents (), tlsInfo);
+
                        tls.ProcessClientHello 
(reader.Value.BinaryExchange.Value);
                        WstRequestSecurityTokenResponse rstr =
                                new WstRequestSecurityTokenResponse 
(SecurityTokenSerializer);
@@ -135,25 +169,39 @@
                        Message reply = Message.CreateMessage (request.Version, 
Constants.WstIssueReplyAction, rstr);
                        reply.Headers.RelatesTo = request.Headers.MessageId;
 
-                       sessions [reader.Value.Context] = tls;
+                       // FIXME: use correct buffer size
+                       buffer = reply.CreateBufferedCopy (0x10000);
+                       AppendNegotiationMessageXml (buffer.CreateMessage 
().GetReaderAtBodyContents (), tlsInfo);
 
-                       return reply;
+                       sessions [reader.Value.Context] = tlsInfo;
+
+                       return buffer.CreateMessage ();
                }
 
                Message ProcessClientKeyExchange (Message request)
                {
+                       // FIXME: use correct buffer size
+                       MessageBuffer buffer = request.CreateBufferedCopy 
(0x10000);
                        WSTrustRequestSecurityTokenResponseReader reader =
-                               new WSTrustRequestSecurityTokenResponseReader 
(request.GetReaderAtBodyContents (), SecurityTokenSerializer, null);
+                               new WSTrustRequestSecurityTokenResponseReader 
(buffer.CreateMessage ().GetReaderAtBodyContents (), SecurityTokenSerializer, 
null);
                        reader.Read ();
 
-                       TlsServerSession tls;
-                       if (!sessions.TryGetValue (reader.Value.Context, out 
tls))
+                       TlsServerSessionInfo tlsInfo;
+                       if (!sessions.TryGetValue (reader.Value.Context, out 
tlsInfo))
                                throw new InvalidOperationException 
(String.Format ("The context '{0}' does not exist in this SSL negotiation 
manager", reader.Value.Context));
+                       TlsServerSession tls = tlsInfo.Tls;
+
+                       AppendNegotiationMessageXml (buffer.CreateMessage 
().GetReaderAtBodyContents (), tlsInfo);
+//Console.WriteLine (System.Text.Encoding.UTF8.GetString 
(tlsInfo.Messages.ToArray ()));
+
                        tls.ProcessClientKeyExchange 
(reader.Value.BinaryExchange.Value);
 
                        byte [] serverFinished = tls.ProcessServerFinished ();
 
-                       RijndaelManaged aes = new RijndaelManaged ();
+                       // The shared key is computed as:
+                       // 
P_SHA1(encrypted_key,SHA1(exc14n(RST..RSTRs))+"CK-HASH")
+                       byte [] hash = SHA1.Create ().ComputeHash 
(tlsInfo.Messages.GetBuffer (), 0, (int) tlsInfo.Messages.Length);
+                       byte [] ckhash = tls.CreateHash (tls.MasterSecret, 
hash, "CK-HASH");
 
                        WstRequestSecurityTokenResponseCollection col =
                                new WstRequestSecurityTokenResponseCollection 
();
@@ -168,14 +216,14 @@
                                // (do not use sslnego context here.)
                                new UniqueId (),
                                "uuid-" + Guid.NewGuid (),
-                               aes.Key,
+                               ckhash,
                                from,
                                // FIXME: use 
LocalServiceSecuritySettings.NegotiationTimeout
                                from.AddHours (8),
                                null,
                                
owner.Manager.ServiceCredentials.SecureConversationAuthentication.SecurityStateEncoder);
                        rstr.RequestedSecurityToken = sct;
-                       rstr.RequestedProofToken = tls.ProcessApplicationData 
(aes.Key);
+                       rstr.RequestedProofToken = tls.ProcessApplicationData 
(ckhash);
                        rstr.RequestedAttachedReference = new 
LocalIdKeyIdentifierClause (sct.Id);
                        rstr.RequestedUnattachedReference = new 
SecurityContextKeyIdentifierClause (sct.ContextId, null);
                        WstLifetime lt = new WstLifetime ();
@@ -188,10 +236,10 @@
 
                        col.Responses.Add (rstr);
 
-                       // FIXME: add authenticator
+                       // Authenticator is mandatory for MS sslnego.
                        rstr = new WstRequestSecurityTokenResponse 
(SecurityTokenSerializer);
                        rstr.Context = reader.Value.Context;
-                       rstr.Authenticator = tls.CreateAuthHash (aes.Key);
+                       rstr.Authenticator = tls.CreateHash (key, hash, 
"AUTH-HASH");
                        col.Responses.Add (rstr);
 
                        sessions.Remove (reader.Value.Context);

Modified: 
trunk/olive/class/System.ServiceModel/System.ServiceModel.Security.Tokens/SslSecurityTokenProvider.cs
===================================================================
--- 
trunk/olive/class/System.ServiceModel/System.ServiceModel.Security.Tokens/SslSecurityTokenProvider.cs
       2007-03-22 15:29:11 UTC (rev 74812)
+++ 
trunk/olive/class/System.ServiceModel/System.ServiceModel.Security.Tokens/SslSecurityTokenProvider.cs
       2007-03-22 15:34:16 UTC (rev 74813)
@@ -33,6 +33,7 @@
 using System.IdentityModel.Tokens;
 using System.Security.Cryptography;
 using System.Security.Cryptography.X509Certificates;
+using System.Security.Cryptography.Xml;
 using System.ServiceModel;
 using System.ServiceModel.Channels;
 using System.ServiceModel.Description;
@@ -71,8 +72,32 @@
                {
                }
 
+               class TlsnegoClientSessionContext
+               {
+                       XmlDocument doc = new XmlDocument ();
+                       XmlDsigExcC14NTransform t = new XmlDsigExcC14NTransform 
();
+                       MemoryStream stream = new MemoryStream ();
+
+                       public void StoreMessage (XmlReader reader)
+                       {
+                               doc.RemoveAll ();
+                               doc.AppendChild (doc.ReadNode (reader));
+                               t.LoadInput (doc);
+                               MemoryStream s = (MemoryStream) t.GetOutput ();
+                               byte [] bytes = s.ToArray ();
+                               stream.Write (bytes, 0, bytes.Length);
+                       }
+
+                       public byte [] GetC14NResults ()
+                       {
+                               return stream.ToArray ();
+                       }
+               }
+
                public SecurityToken GetToken (TimeSpan timeout)
                {
+                       TlsnegoClientSessionContext tlsctx =
+                               new TlsnegoClientSessionContext ();
                        TlsClientSession tls = new TlsClientSession 
(IssuerAddress.Uri.ToString ());
                        WstRequestSecurityToken rst =
                                new WstRequestSecurityToken ();
@@ -85,11 +110,17 @@
                        request.Headers.MessageId = new UniqueId ();
                        request.Headers.ReplyTo = new EndpointAddress 
(Constants.WsaAnonymousUri);
                        request.Headers.To = TargetAddress.Uri;
-                       Message response = proxy.Issue (request);
+                       MessageBuffer buffer = request.CreateBufferedCopy 
(0x10000);
+                       tlsctx.StoreMessage (buffer.CreateMessage 
().GetReaderAtBodyContents ());
+                       Message response = proxy.Issue (buffer.CreateMessage 
());
 
+                       // FIXME: use correct limitation
+                       buffer = response.CreateBufferedCopy (0x10000);
+                       tlsctx.StoreMessage (buffer.CreateMessage 
().GetReaderAtBodyContents ());
+
                        // receive ServerHello
                        WSTrustRequestSecurityTokenResponseReader reader =
-                               new WSTrustRequestSecurityTokenResponseReader 
(response.GetReaderAtBodyContents (), SecurityTokenSerializer, null);
+                               new WSTrustRequestSecurityTokenResponseReader 
(buffer.CreateMessage ().GetReaderAtBodyContents (), SecurityTokenSerializer, 
null);
                        reader.Read ();
                        if (reader.Value.RequestedSecurityToken != null)
                                return reader.Value.RequestedSecurityToken;
@@ -106,34 +137,50 @@
                        request = Message.CreateMessage 
(IssuerBinding.MessageVersion, Constants.WstIssueReplyAction, rstr);
                        request.Headers.ReplyTo = new EndpointAddress 
(Constants.WsaAnonymousUri);
                        request.Headers.To = TargetAddress.Uri;
+
+                       buffer = request.CreateBufferedCopy (0x10000);
+                       tlsctx.StoreMessage (buffer.CreateMessage 
().GetReaderAtBodyContents ());
+//Console.WriteLine (System.Text.Encoding.UTF8.GetString 
(tlsctx.GetC14NResults ()));
+
                        // FIXME: regeneration of this instance is somehow 
required, but should not be.
                        proxy = new WSTrustSecurityTokenServiceProxy (
                                IssuerBinding, IssuerAddress);
-                       response = proxy.IssueReply (request);
+                       response = proxy.IssueReply (buffer.CreateMessage ());
+                       // FIXME: use correct limitation
+                       buffer = response.CreateBufferedCopy (0x10000);
+                       // don't store this message in tlsctx (it's not part
+                       // of exchange)
 
-MessageBuffer bugg = response.CreateBufferedCopy (10000);
-response = bugg.CreateMessage ();
-Console.WriteLine (bugg.CreateMessage ());
-
                        // FIXME: support simple RSTR
                        WstRequestSecurityTokenResponseCollection coll =
                                new WstRequestSecurityTokenResponseCollection 
();
-                       coll.Read (response.GetReaderAtBodyContents (), 
SecurityTokenSerializer, null);
+                       coll.Read (buffer.CreateMessage 
().GetReaderAtBodyContents (), SecurityTokenSerializer, null);
 
                        WstRequestSecurityTokenResponse r = coll.Responses [0];
                        tls.ProcessServerFinished (r.BinaryExchange.Value);
                        SecurityContextSecurityToken sctSrc =
                                r.RequestedSecurityToken;
 
-                       // the RequestedProofToken looks like below:
-                       // 17 03 01 00 30 1A 37 0A 80 3D 5E F7 6B 54 FA A0 FA 1B
-                       // C2 D6 B8 DB F0 4D E5 62 85 A7 31 0C 8E F9 F4 D9 5C 35
-                       // 99 DA C7 BE 45 8B 58 A1 B3 D0 B0 F8 8E C3 1C 46 A0
-                       // This looks like a TLS ApplicationData which consists
-                       // of 32 bytes of data. It smells like *the* shared key.
+                       // the RequestedProofToken is represented as 32 bytes
+                       // of TLS ApplicationData.
                        byte [] key = tls.ProcessApplicationData (
                                (byte []) r.RequestedProofToken);
 
+                       byte [] actual = coll.Responses.Count > 1 ? 
coll.Responses [1].Authenticator : null;
+                       if (actual == null)
+                               throw new MessageSecurityException ("Token 
authenticator is expected in the RequestSecurityTokenResponse but not found.");
+                       // H = sha1(exc14n(RST..RSTRs))
+
+                       byte [] hash = SHA1.Create ().ComputeHash 
(tlsctx.GetC14NResults ());
+                       byte [] referent = tls.CreateHash (tls.MasterSecret, 
hash, "AUTH-HASH");
+                       bool mismatch = referent.Length != actual.Length;
+                       if (!mismatch)
+                               for (int i = 0; i < referent.Length; i++)
+                                       if (referent [i] != actual [i])
+                                               mismatch = true;
+                       if (mismatch)
+                               throw new MessageSecurityException ("The 
CombinedHash does not match the expected value.");
+
                        // FIXME: get correct parameter values.
                        SecurityContextSecurityToken sct = new 
SecurityContextSecurityToken (sctSrc.ContextId, sctSrc.Id, key,
                                r.Lifetime.Created, r.Lifetime.Expires, null,

Modified: 
trunk/olive/class/System.ServiceModel/System.ServiceModel.Security.Tokens/TlsClientSession.cs
===================================================================
--- 
trunk/olive/class/System.ServiceModel/System.ServiceModel.Security.Tokens/TlsClientSession.cs
       2007-03-22 15:29:11 UTC (rev 74812)
+++ 
trunk/olive/class/System.ServiceModel/System.ServiceModel.Security.Tokens/TlsClientSession.cs
       2007-03-22 15:34:16 UTC (rev 74813)
@@ -46,17 +46,20 @@
                        get { return Context.MasterSecret; }
                }
 
-               public byte [] CreateAuthHash (byte [] key)
+               public byte [] CreateHashAlt (byte [] key, byte [] seedSrc, 
string label)
                {
-                       string label = "AUTH-HASH";
-                       byte [] keyhash = SHA1.Create ().ComputeHash (key);
                        byte [] labelBytes = Encoding.UTF8.GetBytes (label);
-                       byte [] seed = new byte [keyhash.Length + 
labelBytes.Length];
-                       Array.Copy (keyhash, seed, keyhash.Length);
-                       Array.Copy (labelBytes, 0, seed, keyhash.Length, 
labelBytes.Length);
+                       byte [] seed = new byte [seedSrc.Length + 
labelBytes.Length];
+                       Array.Copy (seedSrc, seed, seedSrc.Length);
+                       Array.Copy (labelBytes, 0, seed, seedSrc.Length, 
labelBytes.Length);
                        return Context.Current.Cipher.Expand ("SHA1", key, 
seed, 256 / 8);
                }
 
+               public byte [] CreateHash (byte [] key, byte [] seed, string 
label)
+               {
+                       return Context.Current.Cipher.PRF (key, label, seed, 
256 / 8);
+               }
+
                protected void WriteHandshake (MemoryStream ms)
                {
                        Context.SupportedCiphers = 
CipherSuiteFactory.GetSupportedCiphers (SecurityProtocolType.Tls);

_______________________________________________
Mono-patches maillist  -  [email protected]
http://lists.ximian.com/mailman/listinfo/mono-patches

Reply via email to