public Message Validate(Message request) { WstRequestSecurityToken req = ReadRequest(request); WstRequestSecurityTokenResponse res = Validate(req); return(CreateResponse(res, Constants.WstValidateReplyAction)); }
public Message Cancel(Message request) { WstRequestSecurityToken req = ReadRequest(request); WstRequestSecurityTokenResponse res = Cancel(req); return(CreateResponse(res, Constants.WstCancelReplyAction)); }
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."); } }
public WstRequestSecurityTokenResponse Issue (WstRequestSecurityToken request) { if (request == null) throw new ArgumentNullException ("request"); foreach (FieldInfo fi in request.GetType ().GetFields ()) Console.WriteLine ("{0}: {1}", fi, fi.GetValue (request)); WstRequestSecurityTokenResponse response = new WstRequestSecurityTokenResponse (); Rijndael aes = Rijndael.Create (); response.TokenType = "http://schemas.xmlsoap.org/ws/2005/02/trust/SymmetricKey"; string id = new UniqueId ().ToString (); response.RequestedSecurityToken = new BinarySecretSecurityToken (id, aes.Key); return response; }
// FIXME: use timeout Message ProcessClientHello(Message request, TimeSpan timeout) { // FIXME: use correct buffer size MessageBuffer buffer = request.CreateBufferedCopy(0x10000); WSTrustRequestSecurityTokenReader reader = new WSTrustRequestSecurityTokenReader(buffer.CreateMessage().GetReaderAtBodyContents(), SecurityTokenSerializer); reader.Read(); if (sessions.ContainsKey(reader.Value.Context)) { throw new SecurityNegotiationException(String.Format("The context '{0}' already exists in this SSL negotiation manager", reader.Value.Context)); } // FIXME: it seems .NET retrieves X509 Certificate through CreateSecurityTokenProvider(somex509requirement).GetToken().SecurityKeys[0] // (should result in X509AsymmetricSecurityKey) and continues tlsstart. // That's not very required feature so I ignore it. 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); rstr.Context = reader.Value.Context; rstr.BinaryExchange = new WstBinaryExchange(Constants.WstBinaryExchangeValueTls); rstr.BinaryExchange.Value = tls.ProcessServerHello(); Message reply = Message.CreateMessage(request.Version, Constants.WstIssueReplyAction, rstr); reply.Headers.RelatesTo = request.Headers.MessageId; // FIXME: use correct buffer size buffer = reply.CreateBufferedCopy(0x10000); AppendNegotiationMessageXml(buffer.CreateMessage().GetReaderAtBodyContents(), tlsInfo); sessions [reader.Value.Context] = tlsInfo; return(buffer.CreateMessage()); }
Message ProcessClientHello(Message request) { // FIXME: use correct buffer size MessageBuffer buffer = request.CreateBufferedCopy(0x10000); WSTrustRequestSecurityTokenReader reader = new WSTrustRequestSecurityTokenReader(buffer.CreateMessage().GetReaderAtBodyContents(), SecurityTokenSerializer); reader.Read(); if (sessions.ContainsKey(reader.Value.Context)) { throw new SecurityNegotiationException(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); rstr.Context = reader.Value.Context; rstr.BinaryExchange = new WstBinaryExchange(Constants.WstBinaryExchangeValueTls); rstr.BinaryExchange.Value = tls.ProcessServerHello(); Message reply = Message.CreateMessage(request.Version, Constants.WstIssueReplyAction, rstr); reply.Headers.RelatesTo = request.Headers.MessageId; // FIXME: use correct buffer size buffer = reply.CreateBufferedCopy(0x10000); AppendNegotiationMessageXml(buffer.CreateMessage().GetReaderAtBodyContents(), tlsInfo); sessions [reader.Value.Context] = tlsInfo; return(buffer.CreateMessage()); }
public WstRequestSecurityTokenResponse Issue(WstRequestSecurityToken request) { if (request == null) { throw new ArgumentNullException("request"); } foreach (FieldInfo fi in request.GetType().GetFields()) { Console.WriteLine("{0}: {1}", fi, fi.GetValue(request)); } WstRequestSecurityTokenResponse response = new WstRequestSecurityTokenResponse(); Rijndael aes = Rijndael.Create(); response.TokenType = "http://schemas.xmlsoap.org/ws/2005/02/trust/SymmetricKey"; string id = new UniqueId().ToString(); response.RequestedSecurityToken = new BinarySecretSecurityToken(id, aes.Key); return(response); }
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(); }
public Message CreateResponse (WstRequestSecurityTokenResponse response, string action) { return Message.CreateMessage (version, action, new WstRequestSecurityTokenResponseWriter (response, serializer)); }
public WSTrustRequestSecurityTokenResponseReader ( string negotiationType, XmlDictionaryReader reader, SecurityTokenSerializer serializer, SecurityTokenResolver resolver) { this.negotiation_type = negotiationType; this.reader = reader; this.serializer = serializer; this.resolver = resolver; res = new WstRequestSecurityTokenResponse (serializer); }
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 ProcessClientHello (Message request) { // FIXME: use correct buffer size MessageBuffer buffer = request.CreateBufferedCopy (0x10000); WSTrustRequestSecurityTokenReader reader = new WSTrustRequestSecurityTokenReader (buffer.CreateMessage ().GetReaderAtBodyContents (), SecurityTokenSerializer); reader.Read (); if (sessions.ContainsKey (reader.Value.Context)) throw new SecurityNegotiationException (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); rstr.Context = reader.Value.Context; rstr.BinaryExchange = new WstBinaryExchange (Constants.WstBinaryExchangeValueTls); rstr.BinaryExchange.Value = tls.ProcessServerHello (); Message reply = Message.CreateMessage (request.Version, Constants.WstIssueReplyAction, rstr); reply.Headers.RelatesTo = request.Headers.MessageId; // FIXME: use correct buffer size buffer = reply.CreateBufferedCopy (0x10000); AppendNegotiationMessageXml (buffer.CreateMessage ().GetReaderAtBodyContents (), tlsInfo); sessions [reader.Value.Context] = tlsInfo; return buffer.CreateMessage (); }
public Message CreateResponse(WstRequestSecurityTokenResponse response, string action) { return(Message.CreateMessage(version, action, new WstRequestSecurityTokenResponseWriter(response, serializer))); }
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) { 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; }
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 (); }
// FIXME: use timeout Message ProcessMessageType1 (Message request, TimeSpan timeout) { // FIXME: use correct buffer size MessageBuffer buffer = request.CreateBufferedCopy (0x10000); WSTrustRequestSecurityTokenReader reader = new WSTrustRequestSecurityTokenReader (buffer.CreateMessage ().GetReaderAtBodyContents (), SecurityTokenSerializer); reader.Read (); if (sessions.ContainsKey (reader.Value.Context)) throw new SecurityNegotiationException (String.Format ("The context '{0}' already exists in this SSL negotiation manager", reader.Value.Context)); /* Console.WriteLine (buffer.CreateMessage ()); */ SspiServerSession sspi = new SspiServerSession (); // AppendNegotiationMessageXml (buffer.CreateMessage ().GetReaderAtBodyContents (), tlsInfo); // FIXME: when an explicit endpoint identity is // specified in the target EndpointAddress at client, // it sends some other kind of binary octets that // include NTLM octet, instead of raw NTLM octet itself. byte [] raw = reader.Value.BinaryExchange.Value; bool gss = "NTLMSSP" != Encoding.ASCII.GetString (raw, 0, 7); if (gss) sspi.ProcessSpnegoInitialContextTokenRequest (raw); else sspi.ProcessMessageType1 (raw); WstRequestSecurityTokenResponse rstr = new WstRequestSecurityTokenResponse (SecurityTokenSerializer); rstr.Context = reader.Value.Context; rstr.BinaryExchange = new WstBinaryExchange (Constants.WstBinaryExchangeValueGss); if (gss) rstr.BinaryExchange.Value = sspi.ProcessSpnegoInitialContextTokenResponse (); else rstr.BinaryExchange.Value = sspi.ProcessMessageType2 (); Message reply = Message.CreateMessage (request.Version, Constants.WstIssueReplyAction, rstr); reply.Headers.RelatesTo = request.Headers.MessageId; // FIXME: use correct buffer size buffer = reply.CreateBufferedCopy (0x10000); // AppendNegotiationMessageXml (buffer.CreateMessage ().GetReaderAtBodyContents (), tlsInfo); sessions [reader.Value.Context] = sspi; return buffer.CreateMessage (); }
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 WstRequestSecurityTokenResponseWriter (WstRequestSecurityTokenResponse res, SecurityTokenSerializer serializer) : base (true) { this.res = res; this.serializer = serializer; }
Message ProcessMessageType1(Message request) { // FIXME: use correct buffer size MessageBuffer buffer = request.CreateBufferedCopy(0x10000); WSTrustRequestSecurityTokenReader reader = new WSTrustRequestSecurityTokenReader(buffer.CreateMessage().GetReaderAtBodyContents(), SecurityTokenSerializer); reader.Read(); if (sessions.ContainsKey(reader.Value.Context)) { throw new SecurityNegotiationException(String.Format("The context '{0}' already exists in this SSL negotiation manager", reader.Value.Context)); } Console.WriteLine(buffer.CreateMessage()); SspiServerSession sspi = new SspiServerSession(); // AppendNegotiationMessageXml (buffer.CreateMessage ().GetReaderAtBodyContents (), tlsInfo); // FIXME: when an explicit endpoint identity is // specified in the target EndpointAddress at client, // it sends some other kind of binary octets that // include NTLM octet, instead of raw NTLM octet itself. byte [] raw = reader.Value.BinaryExchange.Value; bool gss = "NTLMSSP" != Encoding.ASCII.GetString(raw, 0, 7); if (gss) { sspi.ProcessSpnegoInitialContextTokenRequest(raw); } else { sspi.ProcessMessageType1(raw); } WstRequestSecurityTokenResponse rstr = new WstRequestSecurityTokenResponse(SecurityTokenSerializer); rstr.Context = reader.Value.Context; rstr.BinaryExchange = new WstBinaryExchange(Constants.WstBinaryExchangeValueGss); if (gss) { rstr.BinaryExchange.Value = sspi.ProcessSpnegoInitialContextTokenResponse(); } else { rstr.BinaryExchange.Value = sspi.ProcessMessageType2(); } Message reply = Message.CreateMessage(request.Version, Constants.WstIssueReplyAction, rstr); reply.Headers.RelatesTo = request.Headers.MessageId; // FIXME: use correct buffer size buffer = reply.CreateBufferedCopy(0x10000); // AppendNegotiationMessageXml (buffer.CreateMessage ().GetReaderAtBodyContents (), tlsInfo); sessions [reader.Value.Context] = sspi; return(buffer.CreateMessage()); }
// FIXME: use timeout Message ProcessClientHello (Message request, TimeSpan timeout) { // FIXME: use correct buffer size MessageBuffer buffer = request.CreateBufferedCopy (0x10000); WSTrustRequestSecurityTokenReader reader = new WSTrustRequestSecurityTokenReader (buffer.CreateMessage ().GetReaderAtBodyContents (), SecurityTokenSerializer); reader.Read (); if (sessions.ContainsKey (reader.Value.Context)) throw new SecurityNegotiationException (String.Format ("The context '{0}' already exists in this SSL negotiation manager", reader.Value.Context)); // FIXME: it seems .NET retrieves X509 Certificate through CreateSecurityTokenProvider(somex509requirement).GetToken().SecurityKeys[0] // (should result in X509AsymmetricSecurityKey) and continues tlsstart. // That's not very required feature so I ignore it. 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); rstr.Context = reader.Value.Context; rstr.BinaryExchange = new WstBinaryExchange (Constants.WstBinaryExchangeValueTls); rstr.BinaryExchange.Value = tls.ProcessServerHello (); Message reply = Message.CreateMessage (request.Version, Constants.WstIssueReplyAction, rstr); reply.Headers.RelatesTo = request.Headers.MessageId; // FIXME: use correct buffer size buffer = reply.CreateBufferedCopy (0x10000); AppendNegotiationMessageXml (buffer.CreateMessage ().GetReaderAtBodyContents (), tlsInfo); sessions [reader.Value.Context] = tlsInfo; return buffer.CreateMessage (); }