Beispiel #1
0
        public SecurityToken GetToken(TimeSpan timeout)
        {
            WstRequestSecurityToken req = new WstRequestSecurityToken();
            BodyWriter body             = new WstRequestSecurityTokenWriter(req, SecurityTokenSerializer);
            Message    msg = Message.CreateMessage(IssuerBinding.MessageVersion, Constants.WstIssueAction, body);
            Message    res = comm.Issue(msg);

            // FIXME: provide SecurityTokenResolver (but from where?)
            using (WSTrustRequestSecurityTokenResponseReader resreader = new WSTrustRequestSecurityTokenResponseReader(null, res.GetReaderAtBodyContents(), SecurityTokenSerializer, null)) {
                WstRequestSecurityTokenResponse rstr = resreader.Read();
                if (rstr.RequestedSecurityToken != null)
                {
                    return(rstr.RequestedSecurityToken);
                }
                throw new NotImplementedException("IssuedSecurityTokenProvider did not see RequestedSecurityToken in the response.");
            }
        }
        Message ProcessMessageType3(Message request)
        {
            // FIXME: use correct buffer size
            MessageBuffer buffer = request.CreateBufferedCopy(0x10000);

            Console.WriteLine(buffer.CreateMessage());
            WSTrustRequestSecurityTokenResponseReader reader =
                new WSTrustRequestSecurityTokenResponseReader(Constants.WstSpnegoProofTokenType, buffer.CreateMessage().GetReaderAtBodyContents(), SecurityTokenSerializer, null);

            reader.Read();

            byte [] raw = reader.Value.BinaryExchange.Value;

            bool gss = "NTLMSSP" != Encoding.ASCII.GetString(raw, 0, 7);

            foreach (byte b in raw)
            {
                Console.Write("{0:X02} ", b);
            }
            Console.WriteLine();

            SspiServerSession sspi;

            if (!sessions.TryGetValue(reader.Value.Context, out sspi))
            {
                throw new SecurityNegotiationException(String.Format("The context '{0}' does not exist in this SSL negotiation manager", reader.Value.Context));
            }

            if (gss)
            {
                sspi.ProcessSpnegoProcessContextToken(raw);
            }
            else
            {
                sspi.ProcessMessageType3(raw);
            }

            throw new NotImplementedException();

/*
 *                      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 ();
 *
 *                      // The shared key is computed as recommended in WS-Trust:
 *                      // P_SHA1(encrypted_key,SHA1(exc14n(RST..RSTRs))+"CK-HASH")
 *                      byte [] hash = SHA1.Create ().ComputeHash (tlsInfo.Messages.ToArray ());
 *                      byte [] key = tls.CreateHash (tls.MasterSecret, hash, "CK-HASH");
 * foreach (byte b in hash) Console.Write ("{0:X02} ", b); Console.WriteLine ();
 * foreach (byte b in key) Console.Write ("{0:X02} ", b); Console.WriteLine ();
 *
 *                      WstRequestSecurityTokenResponseCollection col =
 *                              new WstRequestSecurityTokenResponseCollection ();
 *                      WstRequestSecurityTokenResponse rstr =
 *                              new WstRequestSecurityTokenResponse (SecurityTokenSerializer);
 *                      rstr.Context = reader.Value.Context;
 *                      rstr.TokenType = Constants.WsscContextToken;
 *                      DateTime from = DateTime.Now;
 *                      // FIXME: not sure if arbitrary key is used here.
 *                      SecurityContextSecurityToken sct = SecurityContextSecurityToken.CreateCookieSecurityContextToken (
 *                              // Create a new context.
 *                              // (do not use sslnego context here.)
 *                              new UniqueId (),
 *                              "uuid-" + Guid.NewGuid (),
 *                              key,
 *                              from,
 *                              // FIXME: use LocalServiceSecuritySettings.NegotiationTimeout
 *                              from.AddHours (8),
 *                              null,
 *                              owner.Manager.ServiceCredentials.SecureConversationAuthentication.SecurityStateEncoder);
 *                      rstr.RequestedSecurityToken = sct;
 *                      rstr.RequestedProofToken = tls.ProcessApplicationData (key);
 *                      rstr.RequestedAttachedReference = new LocalIdKeyIdentifierClause (sct.Id);
 *                      rstr.RequestedUnattachedReference = new SecurityContextKeyIdentifierClause (sct.ContextId, null);
 *                      WstLifetime lt = new WstLifetime ();
 *                      lt.Created = from;
 *                      // FIXME: use LocalServiceSecuritySettings.NegotiationTimeout
 *                      lt.Expires = from.AddHours (8);
 *                      rstr.Lifetime = lt;
 *                      rstr.BinaryExchange = new WstBinaryExchange (Constants.WstBinaryExchangeValueGss);
 *                      rstr.BinaryExchange.Value = serverFinished;
 *
 *                      col.Responses.Add (rstr);
 *
 *                      // Authenticator is mandatory for MS sslnego.
 *                      rstr = new WstRequestSecurityTokenResponse (SecurityTokenSerializer);
 *                      rstr.Context = reader.Value.Context;
 *                      rstr.Authenticator = tls.CreateHash (key, hash, "AUTH-HASH");
 *                      col.Responses.Add (rstr);
 *
 *                      sessions.Remove (reader.Value.Context);
 *
 *                      return Message.CreateMessage (request.Version, Constants.WstIssueReplyAction, col);
 */
        }
Beispiel #3
0
        public SecurityToken GetToken(TimeSpan timeout)
        {
            TlsnegoClientSessionContext tlsctx =
                new TlsnegoClientSessionContext();
            TlsClientSession        tls = new TlsClientSession(IssuerAddress.Uri.ToString(), client_certificate, owner.Manager.ClientCredentials.ServiceCertificate.Authentication);
            WstRequestSecurityToken rst =
                new WstRequestSecurityToken();
            string contextId = rst.Context;

            // send ClientHello
            rst.BinaryExchange       = new WstBinaryExchange(Constants.WstBinaryExchangeValueTls);
            rst.BinaryExchange.Value = tls.ProcessClientHello();

            Message request = Message.CreateMessage(IssuerBinding.MessageVersion, Constants.WstIssueAction, rst);

            request.Headers.MessageId = new UniqueId();
            request.Headers.ReplyTo   = new EndpointAddress(Constants.WsaAnonymousUri);
            request.Headers.To        = TargetAddress.Uri;
            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(Constants.WstTlsnegoProofTokenType, buffer.CreateMessage().GetReaderAtBodyContents(), SecurityTokenSerializer, null);

            reader.Read();
            if (reader.Value.RequestedSecurityToken != null)
            {
                return(reader.Value.RequestedSecurityToken);
            }

            tls.ProcessServerHello(reader.Value.BinaryExchange.Value);

            // send ClientKeyExchange
            WstRequestSecurityTokenResponse rstr =
                new WstRequestSecurityTokenResponse(SecurityTokenSerializer);

            rstr.Context              = reader.Value.Context;
            rstr.BinaryExchange       = new WstBinaryExchange(Constants.WstBinaryExchangeValueTls);
            rstr.BinaryExchange.Value = tls.ProcessClientKeyExchange();

            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(buffer.CreateMessage());
            // FIXME: use correct limitation
            buffer = response.CreateBufferedCopy(0x10000);

            WstRequestSecurityTokenResponseCollection coll =
                new WstRequestSecurityTokenResponseCollection();

            coll.Read(Constants.WstTlsnegoProofTokenType, buffer.CreateMessage().GetReaderAtBodyContents(), SecurityTokenSerializer, null);
            if (coll.Responses.Count != 2)
            {
                throw new SecurityNegotiationException(String.Format("Expected response is RequestSecurityTokenResponseCollection which contains two RequestSecurityTokenResponse items, but it actually contains {0} items", coll.Responses.Count));
            }

            WstRequestSecurityTokenResponse r = coll.Responses [0];

            tls.ProcessServerFinished(r.BinaryExchange.Value);
            SecurityContextSecurityToken sctSrc =
                r.RequestedSecurityToken;

#if false // FIXME: should this final RSTR included in RSTRC considered too?
            XmlDocument doc = new XmlDocument();
            doc.PreserveWhitespace = true;
            using (XmlDictionaryWriter dw = XmlDictionaryWriter.CreateDictionaryWriter(doc.CreateNavigator().AppendChild()))
            {
                if (r == null)
                {
                    throw new Exception("r");
                }
                if (dw == null)
                {
                    throw new Exception("dw");
                }
                r.WriteBodyContents(dw);
            }
            tlsctx.StoreMessage(XmlDictionaryReader.CreateDictionaryReader(new XmlNodeReader(doc)));
#endif

            // the RequestedProofToken is represented as 32 bytes
            // of TLS ApplicationData.
            // - According to WSE2 doc, it is *the* key, but not
            //   sure it also applies to WCF.
            // - WSS4J also seems to store the encryped shared key.
            // - (Important) It seems that without tls decryption,
            //   .NET fails to recover the key.
            byte [] proof = tls.ProcessApplicationData(
                (byte [])r.RequestedProofToken);
            byte [] key = proof;

            // Authenticate token.

            byte [] actual = coll.Responses [1].Authenticator;
            if (actual == null)
            {
                throw new SecurityNegotiationException("Token authenticator is expected in the RequestSecurityTokenResponse but not found.");
            }

            if (coll.Responses [0].Context != contextId)
            {
                throw new SecurityNegotiationException("The context Id does not match with that of the corresponding token authenticator.");
            }

            // H = sha1(exc14n(RST..RSTRs))
            byte [] hash     = SHA1.Create().ComputeHash(tlsctx.GetC14NResults());
            byte [] referent = tls.CreateHash(key, hash, "AUTH-HASH");
            Console.WriteLine(System.Text.Encoding.ASCII.GetString(tlsctx.GetC14NResults()));
            Console.Write("Hash: ");
            foreach (byte b in hash)
            {
                Console.Write("{0:X02} ", b);
            }
            Console.WriteLine();
            Console.Write("Referent: ");
            foreach (byte b in referent)
            {
                Console.Write("{0:X02} ", b);
            }
            Console.WriteLine();
            Console.Write("Actual: ");
            foreach (byte b in actual)
            {
                Console.Write("{0:X02} ", b);
            }
            Console.WriteLine();
            Console.Write("Proof: ");
            foreach (byte b in proof)
            {
                Console.Write("{0:X02} ", b);
            }
            Console.WriteLine();
            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 SecurityNegotiationException("The CombinedHash does not match the expected value.");
            }

            return(sctSrc);
        }
        Message ProcessClientKeyExchange(Message request)
        {
            // FIXME: use correct buffer size
            MessageBuffer buffer = request.CreateBufferedCopy(0x10000);
            WSTrustRequestSecurityTokenResponseReader reader =
                new WSTrustRequestSecurityTokenResponseReader(Constants.WstTlsnegoProofTokenType, buffer.CreateMessage().GetReaderAtBodyContents(), SecurityTokenSerializer, null);

            reader.Read();

            TlsServerSessionInfo tlsInfo;

            if (!sessions.TryGetValue(reader.Value.Context, out tlsInfo))
            {
                throw new SecurityNegotiationException(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();

            // The shared key is computed as recommended in WS-Trust:
            // P_SHA1(encrypted_key,SHA1(exc14n(RST..RSTRs))+"CK-HASH")
            byte [] hash          = SHA1.Create().ComputeHash(tlsInfo.Messages.ToArray());
            byte [] key           = tls.CreateHash(tls.MasterSecret, hash, "CK-HASH");
            byte [] keyTlsApplied = tls.ProcessApplicationData(key);
            foreach (byte b in hash)
            {
                Console.Write("{0:X02} ", b);
            }
            Console.WriteLine();
            foreach (byte b in key)
            {
                Console.Write("{0:X02} ", b);
            }
            Console.WriteLine();

            WstRequestSecurityTokenResponseCollection col =
                new WstRequestSecurityTokenResponseCollection();
            WstRequestSecurityTokenResponse rstr =
                new WstRequestSecurityTokenResponse(SecurityTokenSerializer);

            rstr.Context   = reader.Value.Context;
            rstr.TokenType = Constants.WsscContextToken;
            DateTime from = DateTime.Now;
            // FIXME: not sure if arbitrary key is used here.
            SecurityContextSecurityToken sct = SecurityContextSecurityToken.CreateCookieSecurityContextToken(
                // Create a new context.
                // (do not use sslnego context here.)
                new UniqueId(),
                "uuid-" + Guid.NewGuid(),
                key,
                from,
                // FIXME: use LocalServiceSecuritySettings.NegotiationTimeout
                from.AddHours(8),
                null,
                owner.Manager.ServiceCredentials.SecureConversationAuthentication.SecurityStateEncoder);

            rstr.RequestedSecurityToken = sct;
            // without this ProcessApplicationData(), .NET seems
            // to fail recovering the key.
            rstr.RequestedProofToken          = keyTlsApplied;
            rstr.RequestedAttachedReference   = new LocalIdKeyIdentifierClause(sct.Id);
            rstr.RequestedUnattachedReference = new SecurityContextKeyIdentifierClause(sct.ContextId, null);
            WstLifetime lt = new WstLifetime();

            lt.Created                = from;
            lt.Expires                = from.Add(SecurityBindingElement.LocalServiceSettings.IssuedCookieLifetime);
            rstr.Lifetime             = lt;
            rstr.BinaryExchange       = new WstBinaryExchange(Constants.WstBinaryExchangeValueTls);
            rstr.BinaryExchange.Value = serverFinished;

            col.Responses.Add(rstr);

            // Authenticator is mandatory for MS sslnego.
            rstr               = new WstRequestSecurityTokenResponse(SecurityTokenSerializer);
            rstr.Context       = reader.Value.Context;
            rstr.Authenticator = tls.CreateHash(key, hash, "AUTH-HASH");
            col.Responses.Add(rstr);

            sessions.Remove(reader.Value.Context);

            // FIXME: get correct tokenRequestor address (probably identity authorized?)
            if (owner.IssuedSecurityTokenHandler != null)
            {
                owner.IssuedSecurityTokenHandler(sct, request.Headers.ReplyTo);
            }

            return(Message.CreateMessage(request.Version, Constants.WstIssueReplyAction, col));
        }
        public SecurityToken GetToken(TimeSpan timeout)
        {
            bool gss = (TargetAddress.Identity == null);
            SspiClientSession sspi = new SspiClientSession();

            WstRequestSecurityToken rst =
                new WstRequestSecurityToken();

            // send MessageType1
            rst.BinaryExchange = new WstBinaryExchange(Constants.WstBinaryExchangeValueGss);
            // When the TargetAddress does not contain the endpoint
            // identity, then .net seems to use Kerberos instead of
            // raw NTLM.
            if (gss)
            {
                rst.BinaryExchange.Value = sspi.ProcessSpnegoInitialContextTokenRequest();
            }
            else
            {
                rst.BinaryExchange.Value = sspi.ProcessMessageType1();
            }

            Message request = Message.CreateMessage(IssuerBinding.MessageVersion, Constants.WstIssueAction, rst);

            request.Headers.MessageId = new UniqueId();
            request.Headers.ReplyTo   = new EndpointAddress(Constants.WsaAnonymousUri);
            request.Headers.To        = TargetAddress.Uri;
            MessageBuffer buffer = request.CreateBufferedCopy(0x10000);
//			tlsctx.StoreMessage (buffer.CreateMessage ().GetReaderAtBodyContents ());

            // receive MessageType2
            Message response = proxy.Issue(buffer.CreateMessage());

            buffer = response.CreateBufferedCopy(0x10000);
//			tlsctx.StoreMessage (buffer.CreateMessage ().GetReaderAtBodyContents ());

            WSTrustRequestSecurityTokenResponseReader reader =
                new WSTrustRequestSecurityTokenResponseReader(Constants.WstSpnegoProofTokenType, buffer.CreateMessage().GetReaderAtBodyContents(), SecurityTokenSerializer, null);

            reader.Read();

            byte [] raw = reader.Value.BinaryExchange.Value;
            if (gss)
            {
                sspi.ProcessSpnegoInitialContextTokenResponse(raw);
            }
            else
            {
                sspi.ProcessMessageType2(raw);
            }

            // send MessageType3
            WstRequestSecurityTokenResponse rstr =
                new WstRequestSecurityTokenResponse(SecurityTokenSerializer);

            rstr.Context        = reader.Value.Context;
            rstr.BinaryExchange = new WstBinaryExchange(Constants.WstBinaryExchangeValueGss);

            NetworkCredential cred = owner.Manager.ClientCredentials.Windows.ClientCredential;
            string            user = string.IsNullOrEmpty(cred.UserName) ? Environment.UserName : cred.UserName;
            string            pass = cred.Password ?? String.Empty;

            if (gss)
            {
                rstr.BinaryExchange.Value = sspi.ProcessSpnegoProcessContextToken(user, pass);
            }
            else
            {
                rstr.BinaryExchange.Value = sspi.ProcessMessageType3(user, pass);
            }

            request = Message.CreateMessage(IssuerBinding.MessageVersion, Constants.WstIssueReplyAction, rstr);
            request.Headers.MessageId = new UniqueId();
            request.Headers.ReplyTo   = new EndpointAddress(Constants.WsaAnonymousUri);
            request.Headers.To        = TargetAddress.Uri;

            buffer = request.CreateBufferedCopy(0x10000);
//			tlsctx.StoreMessage (buffer.CreateMessage ().GetReaderAtBodyContents ());

            proxy = new WSTrustSecurityTokenServiceProxy(
                IssuerBinding, IssuerAddress);
            response = proxy.IssueReply(buffer.CreateMessage());
            // FIXME: use correct limitation
            buffer = response.CreateBufferedCopy(0x10000);
            // don't store this message for ckhash (it's not part
            // of exchange)
            /* Console.WriteLine (buffer.CreateMessage ()); */


            throw new NotImplementedException();
        }