Imported Upstream version 5.18.0.142

Former-commit-id: 7467d4b717762eeaf652d77f1486dd11ffb1ff1f
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2018-10-09 08:20:59 +00:00
parent e52655b4dc
commit 0abdbe5a7d
1547 changed files with 93792 additions and 47893 deletions

View File

@ -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 ();
}
}
}

View File

@ -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 ();
}
}
}

View File

@ -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 ();
}
}
}

View File

@ -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 ();
}
}
}

View File

@ -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
}
}
}

View File

@ -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 ();
}
}
}