You've already forked linux-packaging-mono
Imported Upstream version 5.18.0.142
Former-commit-id: 7467d4b717762eeaf652d77f1486dd11ffb1ff1f
This commit is contained in:
parent
e52655b4dc
commit
0abdbe5a7d
@ -1,322 +0,0 @@
|
||||
//
|
||||
// SpnegoSecurityTokenAuthenticator.cs
|
||||
//
|
||||
// Author:
|
||||
// Atsushi Enomoto <atsushi@ximian.com>
|
||||
//
|
||||
// Copyright (C) 2007 Novell, Inc. http://www.novell.com
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
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;
|
||||
using System.ServiceModel.Security.Tokens;
|
||||
using System.Text;
|
||||
using System.Xml;
|
||||
using Mono.Security;
|
||||
|
||||
using ReqType = System.ServiceModel.Security.Tokens.ServiceModelSecurityTokenRequirement;
|
||||
|
||||
namespace System.ServiceModel.Security.Tokens
|
||||
{
|
||||
// FIXME: implement all
|
||||
class SpnegoSecurityTokenAuthenticator : CommunicationSecurityTokenAuthenticator
|
||||
{
|
||||
ServiceCredentialsSecurityTokenManager manager;
|
||||
SpnegoAuthenticatorCommunicationObject comm;
|
||||
|
||||
public SpnegoSecurityTokenAuthenticator (
|
||||
ServiceCredentialsSecurityTokenManager manager,
|
||||
SecurityTokenRequirement r)
|
||||
{
|
||||
this.manager = manager;
|
||||
comm = new SpnegoAuthenticatorCommunicationObject (this);
|
||||
}
|
||||
|
||||
public ServiceCredentialsSecurityTokenManager Manager {
|
||||
get { return manager; }
|
||||
}
|
||||
|
||||
public override AuthenticatorCommunicationObject Communication {
|
||||
get { return comm; }
|
||||
}
|
||||
|
||||
protected override bool CanValidateTokenCore (SecurityToken token)
|
||||
{
|
||||
throw new NotImplementedException ();
|
||||
}
|
||||
|
||||
protected override ReadOnlyCollection<IAuthorizationPolicy>
|
||||
ValidateTokenCore (SecurityToken token)
|
||||
{
|
||||
throw new NotImplementedException ();
|
||||
}
|
||||
}
|
||||
|
||||
class SpnegoAuthenticatorCommunicationObject : AuthenticatorCommunicationObject
|
||||
{
|
||||
SpnegoSecurityTokenAuthenticator owner;
|
||||
|
||||
public SpnegoAuthenticatorCommunicationObject (SpnegoSecurityTokenAuthenticator owner)
|
||||
{
|
||||
this.owner = owner;
|
||||
}
|
||||
|
||||
WSTrustSecurityTokenServiceProxy proxy;
|
||||
|
||||
protected internal override TimeSpan DefaultCloseTimeout {
|
||||
get { throw new NotImplementedException (); }
|
||||
}
|
||||
|
||||
protected internal override TimeSpan DefaultOpenTimeout {
|
||||
get { throw new NotImplementedException (); }
|
||||
}
|
||||
|
||||
public override Message ProcessNegotiation (Message request, TimeSpan timeout)
|
||||
{
|
||||
if (request.Headers.Action == Constants.WstIssueAction)
|
||||
return ProcessMessageType1 (request, timeout);
|
||||
else
|
||||
return ProcessMessageType3 (request, timeout);
|
||||
}
|
||||
|
||||
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,SspiServerSession> sessions =
|
||||
new Dictionary<string,SspiServerSession> ();
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
// 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 ();
|
||||
}
|
||||
|
||||
// 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);
|
||||
*/
|
||||
}
|
||||
|
||||
protected override void OnAbort ()
|
||||
{
|
||||
throw new NotImplementedException ();
|
||||
}
|
||||
|
||||
protected override void OnOpen (TimeSpan timeout)
|
||||
{
|
||||
if (State == CommunicationState.Opened)
|
||||
throw new InvalidOperationException ("Already opened.");
|
||||
|
||||
EnsureProperties ();
|
||||
|
||||
proxy = new WSTrustSecurityTokenServiceProxy (
|
||||
IssuerBinding, IssuerAddress);
|
||||
}
|
||||
|
||||
protected override IAsyncResult OnBeginOpen (TimeSpan timeout, AsyncCallback callback, object state)
|
||||
{
|
||||
throw new NotImplementedException ();
|
||||
}
|
||||
|
||||
protected override void OnEndOpen (IAsyncResult result)
|
||||
{
|
||||
throw new NotImplementedException ();
|
||||
}
|
||||
|
||||
protected override void OnClose (TimeSpan timeout)
|
||||
{
|
||||
if (proxy != null)
|
||||
proxy.Close ();
|
||||
}
|
||||
|
||||
protected override IAsyncResult OnBeginClose (TimeSpan timeout, AsyncCallback callback, object state)
|
||||
{
|
||||
throw new NotImplementedException ();
|
||||
}
|
||||
|
||||
protected override void OnEndClose (IAsyncResult result)
|
||||
{
|
||||
throw new NotImplementedException ();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,203 +0,0 @@
|
||||
//
|
||||
// SpnegoSecurityTokenProvider.cs
|
||||
//
|
||||
// Author:
|
||||
// Atsushi Enomoto <atsushi@ximian.com>
|
||||
//
|
||||
// Copyright (C) 2007 Novell, Inc. http://www.novell.com
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
using System.Net;
|
||||
using System.Security.Principal;
|
||||
using System.IdentityModel.Selectors;
|
||||
using System.IdentityModel.Tokens;
|
||||
using System.ServiceModel.Channels;
|
||||
using System.ServiceModel.Description;
|
||||
using System.ServiceModel.Security.Tokens;
|
||||
using System.Xml;
|
||||
using Mono.Security;
|
||||
|
||||
// mhm, why is this class not in S.SM.S.Tokens??
|
||||
namespace System.ServiceModel.Security
|
||||
{
|
||||
// Anyways we won't support SSPI until it becomes open.
|
||||
internal class SpnegoSecurityTokenProvider : CommunicationSecurityTokenProvider
|
||||
{
|
||||
ClientCredentialsSecurityTokenManager manager;
|
||||
SecurityTokenRequirement requirement;
|
||||
SpnegoCommunicationObject comm;
|
||||
|
||||
public SpnegoSecurityTokenProvider (ClientCredentialsSecurityTokenManager manager, SecurityTokenRequirement requirement)
|
||||
{
|
||||
this.manager = manager;
|
||||
comm = new SpnegoCommunicationObject (this);
|
||||
}
|
||||
|
||||
public ClientCredentialsSecurityTokenManager Manager {
|
||||
get { return manager; }
|
||||
}
|
||||
|
||||
public override ProviderCommunicationObject Communication {
|
||||
get { return comm; }
|
||||
}
|
||||
|
||||
public override SecurityToken GetOnlineToken (TimeSpan timeout)
|
||||
{
|
||||
return comm.GetToken (timeout);
|
||||
}
|
||||
}
|
||||
|
||||
class SpnegoCommunicationObject : ProviderCommunicationObject
|
||||
{
|
||||
SpnegoSecurityTokenProvider owner;
|
||||
|
||||
public SpnegoCommunicationObject (SpnegoSecurityTokenProvider owner)
|
||||
{
|
||||
this.owner = owner;
|
||||
}
|
||||
|
||||
WSTrustSecurityTokenServiceProxy proxy;
|
||||
|
||||
protected internal override TimeSpan DefaultCloseTimeout {
|
||||
get { throw new NotImplementedException (); }
|
||||
}
|
||||
|
||||
protected internal override TimeSpan DefaultOpenTimeout {
|
||||
get { throw new NotImplementedException (); }
|
||||
}
|
||||
|
||||
protected override void OnAbort ()
|
||||
{
|
||||
throw new NotImplementedException ();
|
||||
}
|
||||
|
||||
protected override void OnOpen (TimeSpan timeout)
|
||||
{
|
||||
if (State == CommunicationState.Opened)
|
||||
throw new InvalidOperationException ("Already opened.");
|
||||
|
||||
EnsureProperties ();
|
||||
|
||||
proxy = new WSTrustSecurityTokenServiceProxy (
|
||||
IssuerBinding, IssuerAddress);
|
||||
}
|
||||
|
||||
protected override IAsyncResult OnBeginOpen (TimeSpan timeout, AsyncCallback callback, object state)
|
||||
{
|
||||
throw new NotImplementedException ();
|
||||
}
|
||||
|
||||
protected override void OnEndOpen (IAsyncResult result)
|
||||
{
|
||||
throw new NotImplementedException ();
|
||||
}
|
||||
|
||||
protected override void OnClose (TimeSpan timeout)
|
||||
{
|
||||
if (proxy != null)
|
||||
proxy.Close ();
|
||||
}
|
||||
|
||||
protected override IAsyncResult OnBeginClose (TimeSpan timeout, AsyncCallback callback, object state)
|
||||
{
|
||||
throw new NotImplementedException ();
|
||||
}
|
||||
|
||||
protected override void OnEndClose (IAsyncResult result)
|
||||
{
|
||||
throw new NotImplementedException ();
|
||||
}
|
||||
|
||||
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 ();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,306 +0,0 @@
|
||||
//
|
||||
// SslSecurityTokenAuthenticator.cs
|
||||
//
|
||||
// Author:
|
||||
// Atsushi Enomoto <atsushi@ximian.com>
|
||||
//
|
||||
// Copyright (C) 2007 Novell, Inc. http://www.novell.com
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
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;
|
||||
using System.ServiceModel.Security.Tokens;
|
||||
using System.Xml;
|
||||
|
||||
using ReqType = System.ServiceModel.Security.Tokens.ServiceModelSecurityTokenRequirement;
|
||||
|
||||
namespace System.ServiceModel.Security.Tokens
|
||||
{
|
||||
// FIXME: implement all
|
||||
class SslSecurityTokenAuthenticator : CommunicationSecurityTokenAuthenticator
|
||||
{
|
||||
ServiceCredentialsSecurityTokenManager manager;
|
||||
SslAuthenticatorCommunicationObject comm;
|
||||
bool mutual;
|
||||
|
||||
public SslSecurityTokenAuthenticator (
|
||||
ServiceCredentialsSecurityTokenManager manager,
|
||||
SecurityTokenRequirement r)
|
||||
{
|
||||
this.manager = manager;
|
||||
mutual = (r.TokenType == ServiceModelSecurityTokenTypes.MutualSslnego);
|
||||
comm = new SslAuthenticatorCommunicationObject (this);
|
||||
}
|
||||
|
||||
public bool IsMutual {
|
||||
get { return mutual; }
|
||||
}
|
||||
|
||||
public ServiceCredentialsSecurityTokenManager Manager {
|
||||
get { return manager; }
|
||||
}
|
||||
|
||||
public override AuthenticatorCommunicationObject Communication {
|
||||
get { return comm; }
|
||||
}
|
||||
|
||||
protected override bool CanValidateTokenCore (SecurityToken token)
|
||||
{
|
||||
throw new NotImplementedException ();
|
||||
}
|
||||
|
||||
protected override ReadOnlyCollection<IAuthorizationPolicy>
|
||||
ValidateTokenCore (SecurityToken token)
|
||||
{
|
||||
throw new NotImplementedException ();
|
||||
}
|
||||
}
|
||||
|
||||
class SslAuthenticatorCommunicationObject : AuthenticatorCommunicationObject
|
||||
{
|
||||
SslSecurityTokenAuthenticator owner;
|
||||
|
||||
public SslAuthenticatorCommunicationObject (SslSecurityTokenAuthenticator owner)
|
||||
{
|
||||
this.owner = owner;
|
||||
}
|
||||
|
||||
WSTrustSecurityTokenServiceProxy proxy;
|
||||
|
||||
protected internal override TimeSpan DefaultCloseTimeout {
|
||||
get { throw new NotImplementedException (); }
|
||||
}
|
||||
|
||||
protected internal override TimeSpan DefaultOpenTimeout {
|
||||
get { throw new NotImplementedException (); }
|
||||
}
|
||||
|
||||
public override Message ProcessNegotiation (Message request, TimeSpan timeout)
|
||||
{
|
||||
if (request.Headers.Action == Constants.WstIssueAction)
|
||||
return ProcessClientHello (request, timeout);
|
||||
else
|
||||
return ProcessClientKeyExchange (request, timeout);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
// 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 ();
|
||||
}
|
||||
|
||||
// FIXME: use timeout
|
||||
Message ProcessClientKeyExchange (Message request, TimeSpan timeout)
|
||||
{
|
||||
// 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);
|
||||
}
|
||||
|
||||
protected override void OnAbort ()
|
||||
{
|
||||
throw new NotImplementedException ();
|
||||
}
|
||||
|
||||
protected override void OnOpen (TimeSpan timeout)
|
||||
{
|
||||
if (State == CommunicationState.Opened)
|
||||
throw new InvalidOperationException ("Already opened.");
|
||||
|
||||
EnsureProperties ();
|
||||
|
||||
proxy = new WSTrustSecurityTokenServiceProxy (
|
||||
IssuerBinding, IssuerAddress);
|
||||
}
|
||||
|
||||
protected override IAsyncResult OnBeginOpen (TimeSpan timeout, AsyncCallback callback, object state)
|
||||
{
|
||||
throw new NotImplementedException ();
|
||||
}
|
||||
|
||||
protected override void OnEndOpen (IAsyncResult result)
|
||||
{
|
||||
throw new NotImplementedException ();
|
||||
}
|
||||
|
||||
protected override void OnClose (TimeSpan timeout)
|
||||
{
|
||||
if (proxy != null)
|
||||
proxy.Close ();
|
||||
}
|
||||
|
||||
protected override IAsyncResult OnBeginClose (TimeSpan timeout, AsyncCallback callback, object state)
|
||||
{
|
||||
throw new NotImplementedException ();
|
||||
}
|
||||
|
||||
protected override void OnEndClose (IAsyncResult result)
|
||||
{
|
||||
throw new NotImplementedException ();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,284 +0,0 @@
|
||||
//
|
||||
// SslSecurityTokenProvider.cs
|
||||
//
|
||||
// Author:
|
||||
// Atsushi Enomoto <atsushi@ximian.com>
|
||||
//
|
||||
// Copyright (C) 2006-2007 Novell, Inc. http://www.novell.com
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Net.Security;
|
||||
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;
|
||||
using System.ServiceModel.Channels;
|
||||
using System.ServiceModel.Description;
|
||||
using System.ServiceModel.Security;
|
||||
using System.ServiceModel.Security.Tokens;
|
||||
using System.Xml;
|
||||
|
||||
using ReqType = System.ServiceModel.Security.Tokens.ServiceModelSecurityTokenRequirement;
|
||||
|
||||
namespace System.ServiceModel.Security.Tokens
|
||||
{
|
||||
class SslSecurityTokenProvider : CommunicationSecurityTokenProvider
|
||||
{
|
||||
SslCommunicationObject comm;
|
||||
ClientCredentialsSecurityTokenManager manager;
|
||||
|
||||
public SslSecurityTokenProvider (ClientCredentialsSecurityTokenManager manager, bool mutual)
|
||||
{
|
||||
this.manager = manager;
|
||||
comm = new SslCommunicationObject (this, mutual);
|
||||
}
|
||||
|
||||
public override ProviderCommunicationObject Communication {
|
||||
get { return comm; }
|
||||
}
|
||||
|
||||
public ClientCredentialsSecurityTokenManager Manager {
|
||||
get { return manager; }
|
||||
}
|
||||
|
||||
public override SecurityToken GetOnlineToken (TimeSpan timeout)
|
||||
{
|
||||
return comm.GetToken (timeout);
|
||||
}
|
||||
}
|
||||
|
||||
class SslCommunicationObject : ProviderCommunicationObject
|
||||
{
|
||||
SslSecurityTokenProvider owner;
|
||||
WSTrustSecurityTokenServiceProxy proxy;
|
||||
X509Certificate2 client_certificate;
|
||||
|
||||
|
||||
public SslCommunicationObject (SslSecurityTokenProvider owner, bool mutual)
|
||||
{
|
||||
if (mutual) {
|
||||
client_certificate = owner.Manager.ClientCredentials.ClientCertificate.Certificate;
|
||||
if (client_certificate == null)
|
||||
throw new InvalidOperationException ("ClientCertificate is required for mutual SSL negotiation.");
|
||||
}
|
||||
this.owner = owner;
|
||||
}
|
||||
|
||||
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 (), 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;
|
||||
}
|
||||
|
||||
protected internal override TimeSpan DefaultCloseTimeout {
|
||||
get { throw new NotImplementedException (); }
|
||||
}
|
||||
|
||||
protected internal override TimeSpan DefaultOpenTimeout {
|
||||
get { throw new NotImplementedException (); }
|
||||
}
|
||||
|
||||
protected override void OnAbort ()
|
||||
{
|
||||
throw new NotImplementedException ();
|
||||
}
|
||||
|
||||
protected override void OnOpen (TimeSpan timeout)
|
||||
{
|
||||
if (State == CommunicationState.Opened)
|
||||
throw new InvalidOperationException ("Already opened.");
|
||||
|
||||
EnsureProperties ();
|
||||
|
||||
proxy = new WSTrustSecurityTokenServiceProxy (
|
||||
IssuerBinding, IssuerAddress);
|
||||
}
|
||||
|
||||
protected override IAsyncResult OnBeginOpen (TimeSpan timeout, AsyncCallback callback, object state)
|
||||
{
|
||||
throw new NotImplementedException ();
|
||||
}
|
||||
|
||||
protected override void OnEndOpen (IAsyncResult result)
|
||||
{
|
||||
throw new NotImplementedException ();
|
||||
}
|
||||
|
||||
protected override void OnClose (TimeSpan timeout)
|
||||
{
|
||||
if (proxy != null)
|
||||
proxy.Close ();
|
||||
}
|
||||
|
||||
protected override IAsyncResult OnBeginClose (TimeSpan timeout, AsyncCallback callback, object state)
|
||||
{
|
||||
throw new NotImplementedException ();
|
||||
}
|
||||
|
||||
protected override void OnEndClose (IAsyncResult result)
|
||||
{
|
||||
throw new NotImplementedException ();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,270 +0,0 @@
|
||||
//
|
||||
// TlsClientSession.cs
|
||||
//
|
||||
// Author:
|
||||
// Atsushi Enomoto <atsushi@ximian.com>
|
||||
//
|
||||
// Copyright (C) 2007 Novell, Inc. http://www.novell.com
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.IdentityModel.Selectors;
|
||||
using System.Security.Cryptography;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Text;
|
||||
using Mono.Security.Protocol.Tls;
|
||||
using Mono.Security.Protocol.Tls.Handshake;
|
||||
using Mono.Security.Protocol.Tls.Handshake.Client;
|
||||
|
||||
namespace System.ServiceModel.Security.Tokens
|
||||
{
|
||||
internal abstract class TlsSession
|
||||
{
|
||||
protected abstract Context Context { get; }
|
||||
|
||||
protected abstract RecordProtocol Protocol { get; }
|
||||
|
||||
public byte [] MasterSecret {
|
||||
get { return Context.MasterSecret; }
|
||||
}
|
||||
|
||||
public byte [] CreateHash (byte [] key, byte [] seedSrc, string label)
|
||||
{
|
||||
byte [] labelBytes = Encoding.UTF8.GetBytes (label);
|
||||
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 [] CreateHashAlt (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);
|
||||
ms.WriteByte (0x16); // Handshake
|
||||
ms.WriteByte (3); // version-major
|
||||
ms.WriteByte (1); // version-minor
|
||||
}
|
||||
|
||||
protected void WriteChangeCipherSpec (MemoryStream ms)
|
||||
{
|
||||
ms.WriteByte (0x14); // Handshake
|
||||
ms.WriteByte (3); // version-major
|
||||
ms.WriteByte (1); // version-minor
|
||||
ms.WriteByte (0); // size-upper
|
||||
ms.WriteByte (1); // size-lower
|
||||
ms.WriteByte (1); // ChangeCipherSpec content (1 byte)
|
||||
}
|
||||
|
||||
protected void ReadHandshake (MemoryStream ms)
|
||||
{
|
||||
if (ms.ReadByte () != 0x16)
|
||||
throw new Exception ("INTERNAL ERROR: handshake is expected");
|
||||
Context.ChangeProtocol ((short) (ms.ReadByte () * 0x100 + ms.ReadByte ()));
|
||||
}
|
||||
|
||||
protected void ReadChangeCipherSpec (MemoryStream ms)
|
||||
{
|
||||
if (ms.ReadByte () != 0x14)
|
||||
throw new Exception ("INTERNAL ERROR: ChangeCipherSpec is expected");
|
||||
Context.ChangeProtocol ((short) (ms.ReadByte () * 0x100 + ms.ReadByte ()));
|
||||
if (ms.ReadByte () * 0x100 + ms.ReadByte () != 1)
|
||||
throw new Exception ("INTERNAL ERROR: unexpected ChangeCipherSpec length");
|
||||
ms.ReadByte (); // ChangeCipherSpec content (1 byte) ... anything is OK?
|
||||
}
|
||||
|
||||
protected byte [] ReadNextOperation (MemoryStream ms, HandshakeType expected)
|
||||
{
|
||||
if (ms.ReadByte () != (int) expected)
|
||||
throw new Exception ("INTERNAL ERROR: unexpected server response");
|
||||
int size = ms.ReadByte () * 0x10000 + ms.ReadByte () * 0x100 + ms.ReadByte ();
|
||||
// FIXME: use correct valid input range
|
||||
if (size > 0x100000)
|
||||
throw new Exception ("rejected massive input size.");
|
||||
byte [] bytes = new byte [size];
|
||||
ms.Read (bytes, 0, size);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
protected void WriteOperations (MemoryStream ms, params HandshakeMessage [] msgs)
|
||||
{
|
||||
List<byte []> rawbufs = new List<byte []> ();
|
||||
int total = 0;
|
||||
for (int i = 0; i < msgs.Length; i++) {
|
||||
HandshakeMessage msg = msgs [i];
|
||||
msg.Process ();
|
||||
rawbufs.Add (msg.EncodeMessage ());
|
||||
total += rawbufs [i].Length;
|
||||
msg.Update ();
|
||||
}
|
||||
// FIXME: split packets when the size exceeded 0x10000 (or so)
|
||||
ms.WriteByte ((byte) (total / 0x100));
|
||||
ms.WriteByte ((byte) (total % 0x100));
|
||||
foreach (byte [] bytes in rawbufs)
|
||||
ms.Write (bytes, 0, bytes.Length);
|
||||
}
|
||||
|
||||
protected void VerifyEndOfTransmit (MemoryStream ms)
|
||||
{
|
||||
if (ms.Position == ms.Length)
|
||||
return;
|
||||
|
||||
/*
|
||||
byte [] bytes = new byte [ms.Length - ms.Position];
|
||||
ms.Read (bytes, 0, bytes.Length);
|
||||
foreach (byte b in bytes)
|
||||
Console.Write ("{0:X02} ", b);
|
||||
Console.WriteLine (" - total {0} bytes remained.", bytes.Length);
|
||||
*/
|
||||
|
||||
throw new Exception ("INTERNAL ERROR: unexpected server response");
|
||||
}
|
||||
}
|
||||
|
||||
internal class TlsClientSession : TlsSession
|
||||
{
|
||||
SslClientStream ssl;
|
||||
MemoryStream stream;
|
||||
bool mutual;
|
||||
|
||||
public TlsClientSession (string host, X509Certificate2 clientCert, X509ServiceCertificateAuthentication auth)
|
||||
{
|
||||
stream = new MemoryStream ();
|
||||
if (clientCert == null)
|
||||
ssl = new SslClientStream (stream, host, true, SecurityProtocolType.Tls);
|
||||
else {
|
||||
ssl = new SslClientStream (stream, host, true, SecurityProtocolType.Tls, new X509CertificateCollection (new X509Certificate [] {clientCert}));
|
||||
mutual = true;
|
||||
ssl.ClientCertSelection += delegate (
|
||||
X509CertificateCollection clientCertificates,
|
||||
X509Certificate serverCertificate,
|
||||
string targetHost,
|
||||
X509CertificateCollection serverRequestedCertificates) {
|
||||
return clientCertificates [0];
|
||||
};
|
||||
}
|
||||
X509CertificateValidator v = null;
|
||||
switch (auth.CertificateValidationMode) {
|
||||
case X509CertificateValidationMode.None:
|
||||
v = X509CertificateValidator.None;
|
||||
break;
|
||||
case X509CertificateValidationMode.PeerTrust:
|
||||
v = X509CertificateValidator.PeerTrust;
|
||||
break;
|
||||
case X509CertificateValidationMode.ChainTrust:
|
||||
v = X509CertificateValidator.ChainTrust;
|
||||
break;
|
||||
case X509CertificateValidationMode.PeerOrChainTrust:
|
||||
v = X509CertificateValidator.PeerOrChainTrust;
|
||||
break;
|
||||
case X509CertificateValidationMode.Custom:
|
||||
v = auth.CustomCertificateValidator;
|
||||
break;
|
||||
}
|
||||
ssl.ServerCertValidationDelegate = delegate (X509Certificate certificate, int [] certificateErrors) {
|
||||
v.Validate (new X509Certificate2 (certificate)); // will throw SecurityTokenvalidationException if invalid.
|
||||
return true;
|
||||
};
|
||||
}
|
||||
|
||||
protected override Context Context {
|
||||
get { return ssl.context; }
|
||||
}
|
||||
|
||||
protected override RecordProtocol Protocol {
|
||||
get { return ssl.protocol; }
|
||||
}
|
||||
|
||||
public byte [] ProcessClientHello ()
|
||||
{
|
||||
Context.SupportedCiphers = CipherSuiteFactory.GetSupportedCiphers (Context.SecurityProtocol);
|
||||
Context.HandshakeState = HandshakeState.Started;
|
||||
Protocol.SendRecord (HandshakeType.ClientHello);
|
||||
stream.Flush ();
|
||||
return stream.ToArray ();
|
||||
}
|
||||
|
||||
// ServerHello, ServerCertificate and ServerHelloDone
|
||||
public void ProcessServerHello (byte [] raw)
|
||||
{
|
||||
stream.SetLength (0);
|
||||
stream.Write (raw, 0, raw.Length);
|
||||
stream.Seek (0, SeekOrigin.Begin);
|
||||
|
||||
//foreach (var b in raw) Console.Write ("{0:X02} ", b); Console.WriteLine ();
|
||||
|
||||
#if false // FIXME: should be enabled, taking some right shape.
|
||||
ReadNextOperation (stream, HandshakeType.ServerHello);
|
||||
ReadNextOperation (stream, HandshakeType.Certificate);
|
||||
if (mutual)
|
||||
ReadNextOperation (stream, HandshakeType.CertificateRequest);
|
||||
ReadNextOperation (stream, HandshakeType.ServerHelloDone);
|
||||
#else
|
||||
Protocol.ReceiveRecord (stream); // ServerHello
|
||||
Protocol.ReceiveRecord (stream); // ServerCertificate
|
||||
if (mutual)
|
||||
Protocol.ReceiveRecord (stream); // CertificateRequest
|
||||
Protocol.ReceiveRecord (stream); // ServerHelloDone
|
||||
#endif
|
||||
if (stream.Position != stream.Length)
|
||||
throw new SecurityNegotiationException (String.Format ("Unexpected SSL negotiation binary: {0} bytes of excess in {1} bytes of the octets", stream.Length - stream.Position, stream.Length));
|
||||
}
|
||||
|
||||
public byte [] ProcessClientKeyExchange ()
|
||||
{
|
||||
stream.SetLength (0);
|
||||
if (mutual)
|
||||
Protocol.SendRecord (HandshakeType.Certificate);
|
||||
Protocol.SendRecord (HandshakeType.ClientKeyExchange);
|
||||
Context.Negotiating.Cipher.ComputeKeys ();
|
||||
Context.Negotiating.Cipher.InitializeCipher ();
|
||||
Protocol.SendChangeCipherSpec ();
|
||||
Context.SupportedCiphers = CipherSuiteFactory.GetSupportedCiphers (SecurityProtocolType.Tls);
|
||||
Protocol.SendRecord (HandshakeType.Finished);
|
||||
stream.Flush ();
|
||||
return stream.ToArray ();
|
||||
}
|
||||
|
||||
public void ProcessServerFinished (byte [] raw)
|
||||
{
|
||||
stream.SetLength (0);
|
||||
stream.Write (raw, 0, raw.Length);
|
||||
stream.Seek (0, SeekOrigin.Begin);
|
||||
|
||||
Protocol.ReceiveRecord (stream); // ChangeCipherSpec
|
||||
Protocol.ReceiveRecord (stream); // ServerFinished
|
||||
}
|
||||
|
||||
public byte [] ProcessApplicationData (byte [] raw)
|
||||
{
|
||||
stream.SetLength (0);
|
||||
stream.Write (raw, 0, raw.Length);
|
||||
stream.Seek (0, SeekOrigin.Begin);
|
||||
return Protocol.ReceiveRecord (stream); // ApplicationData
|
||||
}
|
||||
}
|
||||
}
|
@ -1,154 +0,0 @@
|
||||
//
|
||||
// TlsServerSession.cs
|
||||
//
|
||||
// Author:
|
||||
// Atsushi Enomoto <atsushi@ximian.com>
|
||||
//
|
||||
// Copyright (C) 2007 Novell, Inc. http://www.novell.com
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using Mono.Security.Protocol.Tls;
|
||||
using Mono.Security.Protocol.Tls.Handshake;
|
||||
using Mono.Security.Protocol.Tls.Handshake.Server;
|
||||
|
||||
namespace System.ServiceModel.Security.Tokens
|
||||
{
|
||||
internal class TlsServerSession : TlsSession
|
||||
{
|
||||
SslServerStream ssl;
|
||||
MemoryStream stream;
|
||||
bool mutual;
|
||||
|
||||
public TlsServerSession (X509Certificate2 cert, bool mutual)
|
||||
{
|
||||
this.mutual = mutual;
|
||||
stream = new MemoryStream ();
|
||||
ssl = new SslServerStream (stream, cert, mutual, true, SecurityProtocolType.Tls);
|
||||
ssl.PrivateKeyCertSelectionDelegate = delegate (X509Certificate c, string host) {
|
||||
if (c.GetCertHashString () == cert.GetCertHashString ())
|
||||
return cert.PrivateKey;
|
||||
return null;
|
||||
};
|
||||
ssl.ClientCertValidationDelegate = delegate (X509Certificate certificate, int[] certificateErrors) {
|
||||
// FIXME: use X509CertificateValidator
|
||||
return true;
|
||||
};
|
||||
}
|
||||
|
||||
protected override Context Context {
|
||||
get { return ssl.context; }
|
||||
}
|
||||
|
||||
protected override RecordProtocol Protocol {
|
||||
get { return ssl.protocol; }
|
||||
}
|
||||
|
||||
public void ProcessClientHello (byte [] raw)
|
||||
{
|
||||
Context.SupportedCiphers = CipherSuiteFactory.GetSupportedCiphers (Context.SecurityProtocol);
|
||||
Context.HandshakeState = HandshakeState.Started;
|
||||
|
||||
stream.Write (raw, 0, raw.Length);
|
||||
stream.Seek (0, SeekOrigin.Begin);
|
||||
|
||||
Protocol.ReceiveRecord (stream);
|
||||
}
|
||||
|
||||
// ServerHello, ServerCertificate and ServerHelloDone
|
||||
public byte [] ProcessServerHello ()
|
||||
{
|
||||
Context.SessionId = Context.GetSecureRandomBytes (32);
|
||||
|
||||
#if false
|
||||
// so, can I send handshake batch with RecordProtocol?
|
||||
stream.SetLength (0);
|
||||
Protocol.SendRecord (HandshakeType.ServerHello);
|
||||
Protocol.SendRecord (HandshakeType.Certificate);
|
||||
Protocol.SendRecord (HandshakeType.ServerHelloDone);
|
||||
stream.Flush ();
|
||||
return stream.ToArray ();
|
||||
|
||||
#else
|
||||
|
||||
MemoryStream ms = new MemoryStream ();
|
||||
|
||||
WriteHandshake (ms);
|
||||
|
||||
if (mutual)
|
||||
WriteOperations (ms,
|
||||
new TlsServerHello (ssl.context),
|
||||
new TlsServerCertificate (ssl.context),
|
||||
new TlsServerCertificateRequest (ssl.context),
|
||||
new TlsServerHelloDone (ssl.context));
|
||||
else
|
||||
WriteOperations (ms,
|
||||
new TlsServerHello (ssl.context),
|
||||
new TlsServerCertificate (ssl.context),
|
||||
new TlsServerHelloDone (ssl.context));
|
||||
|
||||
return ms.ToArray ();
|
||||
#endif
|
||||
}
|
||||
|
||||
public void ProcessClientKeyExchange (byte [] raw)
|
||||
{
|
||||
stream.SetLength (0);
|
||||
stream.Write (raw, 0, raw.Length);
|
||||
stream.Seek (0, SeekOrigin.Begin);
|
||||
|
||||
if (mutual)
|
||||
Protocol.ReceiveRecord (stream); // Certificate
|
||||
Protocol.ReceiveRecord (stream); // ClientKeyExchange
|
||||
Protocol.ReceiveRecord (stream); // ChangeCipherSpec
|
||||
Protocol.ReceiveRecord (stream); // ClientFinished
|
||||
|
||||
if (stream.Position != stream.Length)
|
||||
throw new SecurityNegotiationException (String.Format ("Unexpected SSL negotiation binary: {0} bytes of excess in {1} bytes of the octets", stream.Length - stream.Position, stream.Length));
|
||||
}
|
||||
|
||||
public byte [] ProcessServerFinished ()
|
||||
{
|
||||
stream.SetLength (0);
|
||||
Protocol.SendChangeCipherSpec ();
|
||||
#if false
|
||||
Protocol.SendRecord (HandshakeType.Finished);
|
||||
stream.Flush ();
|
||||
return stream.ToArray ();
|
||||
#else
|
||||
MemoryStream ms = new MemoryStream ();
|
||||
WriteOperations (ms, new TlsServerFinished (ssl.context));
|
||||
ms.Flush ();
|
||||
return ms.ToArray ();
|
||||
#endif
|
||||
}
|
||||
|
||||
public byte [] ProcessApplicationData (byte [] raw)
|
||||
{
|
||||
stream.SetLength (0);
|
||||
Protocol.SendRecord (ContentType.ApplicationData, raw);
|
||||
stream.Flush ();
|
||||
return stream.ToArray ();
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user