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.");
			}
		}
예제 #2
0
 public void Read(string negotiationType, XmlDictionaryReader r, SecurityTokenSerializer serializer, SecurityTokenResolver resolver)
 {
     r.MoveToContent();
     r.ReadStartElement("RequestSecurityTokenResponseCollection", Constants.WstNamespace);
     while (true)
     {
         r.MoveToContent();
         if (r.NodeType != XmlNodeType.Element)
         {
             break;
         }
         WSTrustRequestSecurityTokenResponseReader rstrr = new WSTrustRequestSecurityTokenResponseReader(negotiationType, r, serializer, resolver);
         rstrr.Read();
         responses.Add(rstrr.Value);
     }
     r.ReadEndElement();
 }
		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);
		}
예제 #4
0
		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 ProcessMessageType3 (Message request, TimeSpan timeout)
		{
			// 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);
*/
		}
예제 #6
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;
		}