disable broken tests on net_4_0
[mcs.git] / class / System.ServiceModel / System.ServiceModel.Security.Tokens / SslSecurityTokenAuthenticator.cs
blobae6cb82da386dbb0d22a0e18c52063488c7c64bf
1 //
2 // SslSecurityTokenAuthenticator.cs
3 //
4 // Author:
5 // Atsushi Enomoto <atsushi@ximian.com>
6 //
7 // Copyright (C) 2007 Novell, Inc. http://www.novell.com
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 //
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 //
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 using System;
29 using System.Collections.Generic;
30 using System.Collections.ObjectModel;
31 using System.IO;
32 using System.Net.Security;
33 using System.IdentityModel.Policy;
34 using System.IdentityModel.Selectors;
35 using System.IdentityModel.Tokens;
36 using System.Security.Cryptography;
37 using System.Security.Cryptography.X509Certificates;
38 using System.Security.Cryptography.Xml;
39 using System.ServiceModel.Channels;
40 using System.ServiceModel.Description;
41 using System.ServiceModel.Security;
42 using System.ServiceModel.Security.Tokens;
43 using System.Xml;
45 using ReqType = System.ServiceModel.Security.Tokens.ServiceModelSecurityTokenRequirement;
47 namespace System.ServiceModel.Security.Tokens
49 // FIXME: implement all
50 class SslSecurityTokenAuthenticator : CommunicationSecurityTokenAuthenticator
52 ServiceCredentialsSecurityTokenManager manager;
53 SslAuthenticatorCommunicationObject comm;
54 bool mutual;
56 public SslSecurityTokenAuthenticator (
57 ServiceCredentialsSecurityTokenManager manager,
58 SecurityTokenRequirement r)
60 this.manager = manager;
61 mutual = (r.TokenType == ServiceModelSecurityTokenTypes.MutualSslnego);
62 comm = new SslAuthenticatorCommunicationObject (this);
65 public bool IsMutual {
66 get { return mutual; }
69 public ServiceCredentialsSecurityTokenManager Manager {
70 get { return manager; }
73 public override AuthenticatorCommunicationObject Communication {
74 get { return comm; }
77 protected override bool CanValidateTokenCore (SecurityToken token)
79 throw new NotImplementedException ();
82 protected override ReadOnlyCollection<IAuthorizationPolicy>
83 ValidateTokenCore (SecurityToken token)
85 throw new NotImplementedException ();
89 class SslAuthenticatorCommunicationObject : AuthenticatorCommunicationObject
91 SslSecurityTokenAuthenticator owner;
93 public SslAuthenticatorCommunicationObject (SslSecurityTokenAuthenticator owner)
95 this.owner = owner;
98 WSTrustSecurityTokenServiceProxy proxy;
100 protected internal override TimeSpan DefaultCloseTimeout {
101 get { throw new NotImplementedException (); }
104 protected internal override TimeSpan DefaultOpenTimeout {
105 get { throw new NotImplementedException (); }
108 public override Message ProcessNegotiation (Message request)
110 if (request.Headers.Action == Constants.WstIssueAction)
111 return ProcessClientHello (request);
112 else
113 return ProcessClientKeyExchange (request);
116 class TlsServerSessionInfo
118 public TlsServerSessionInfo (string context, TlsServerSession tls)
120 ContextId = context;
121 Tls = tls;
124 public string ContextId;
125 public TlsServerSession Tls;
126 public MemoryStream Messages = new MemoryStream ();
129 Dictionary<string,TlsServerSessionInfo> sessions =
130 new Dictionary<string,TlsServerSessionInfo> ();
132 void AppendNegotiationMessageXml (XmlReader reader, TlsServerSessionInfo tlsInfo)
134 XmlDsigExcC14NTransform t = new XmlDsigExcC14NTransform ();
135 XmlDocument doc = new XmlDocument ();
136 doc.PreserveWhitespace = true;
137 reader.MoveToContent ();
138 doc.AppendChild (doc.ReadNode (reader));
139 t.LoadInput (doc);
140 MemoryStream stream = (MemoryStream) t.GetOutput ();
141 byte [] bytes = stream.ToArray ();
142 tlsInfo.Messages.Write (bytes, 0, bytes.Length);
145 Message ProcessClientHello (Message request)
147 // FIXME: use correct buffer size
148 MessageBuffer buffer = request.CreateBufferedCopy (0x10000);
149 WSTrustRequestSecurityTokenReader reader =
150 new WSTrustRequestSecurityTokenReader (buffer.CreateMessage ().GetReaderAtBodyContents (), SecurityTokenSerializer);
151 reader.Read ();
153 if (sessions.ContainsKey (reader.Value.Context))
154 throw new SecurityNegotiationException (String.Format ("The context '{0}' already exists in this SSL negotiation manager", reader.Value.Context));
156 TlsServerSession tls = new TlsServerSession (owner.Manager.ServiceCredentials.ServiceCertificate.Certificate, owner.IsMutual);
157 TlsServerSessionInfo tlsInfo = new TlsServerSessionInfo (
158 reader.Value.Context, tls);
160 AppendNegotiationMessageXml (buffer.CreateMessage ().GetReaderAtBodyContents (), tlsInfo);
162 tls.ProcessClientHello (reader.Value.BinaryExchange.Value);
163 WstRequestSecurityTokenResponse rstr =
164 new WstRequestSecurityTokenResponse (SecurityTokenSerializer);
165 rstr.Context = reader.Value.Context;
166 rstr.BinaryExchange = new WstBinaryExchange (Constants.WstBinaryExchangeValueTls);
167 rstr.BinaryExchange.Value = tls.ProcessServerHello ();
169 Message reply = Message.CreateMessage (request.Version, Constants.WstIssueReplyAction, rstr);
170 reply.Headers.RelatesTo = request.Headers.MessageId;
172 // FIXME: use correct buffer size
173 buffer = reply.CreateBufferedCopy (0x10000);
174 AppendNegotiationMessageXml (buffer.CreateMessage ().GetReaderAtBodyContents (), tlsInfo);
176 sessions [reader.Value.Context] = tlsInfo;
178 return buffer.CreateMessage ();
181 Message ProcessClientKeyExchange (Message request)
183 // FIXME: use correct buffer size
184 MessageBuffer buffer = request.CreateBufferedCopy (0x10000);
185 WSTrustRequestSecurityTokenResponseReader reader =
186 new WSTrustRequestSecurityTokenResponseReader (Constants.WstTlsnegoProofTokenType, buffer.CreateMessage ().GetReaderAtBodyContents (), SecurityTokenSerializer, null);
187 reader.Read ();
189 TlsServerSessionInfo tlsInfo;
190 if (!sessions.TryGetValue (reader.Value.Context, out tlsInfo))
191 throw new SecurityNegotiationException (String.Format ("The context '{0}' does not exist in this SSL negotiation manager", reader.Value.Context));
192 TlsServerSession tls = tlsInfo.Tls;
194 AppendNegotiationMessageXml (buffer.CreateMessage ().GetReaderAtBodyContents (), tlsInfo);
195 //Console.WriteLine (System.Text.Encoding.UTF8.GetString (tlsInfo.Messages.ToArray ()));
197 tls.ProcessClientKeyExchange (reader.Value.BinaryExchange.Value);
199 byte [] serverFinished = tls.ProcessServerFinished ();
201 // The shared key is computed as recommended in WS-Trust:
202 // P_SHA1(encrypted_key,SHA1(exc14n(RST..RSTRs))+"CK-HASH")
203 byte [] hash = SHA1.Create ().ComputeHash (tlsInfo.Messages.ToArray ());
204 byte [] key = tls.CreateHash (tls.MasterSecret, hash, "CK-HASH");
205 byte [] keyTlsApplied = tls.ProcessApplicationData (key);
206 foreach (byte b in hash) Console.Write ("{0:X02} ", b); Console.WriteLine ();
207 foreach (byte b in key) Console.Write ("{0:X02} ", b); Console.WriteLine ();
209 WstRequestSecurityTokenResponseCollection col =
210 new WstRequestSecurityTokenResponseCollection ();
211 WstRequestSecurityTokenResponse rstr =
212 new WstRequestSecurityTokenResponse (SecurityTokenSerializer);
213 rstr.Context = reader.Value.Context;
214 rstr.TokenType = Constants.WsscContextToken;
215 DateTime from = DateTime.Now;
216 // FIXME: not sure if arbitrary key is used here.
217 SecurityContextSecurityToken sct = SecurityContextSecurityToken.CreateCookieSecurityContextToken (
218 // Create a new context.
219 // (do not use sslnego context here.)
220 new UniqueId (),
221 "uuid-" + Guid.NewGuid (),
222 key,
223 from,
224 // FIXME: use LocalServiceSecuritySettings.NegotiationTimeout
225 from.AddHours (8),
226 null,
227 owner.Manager.ServiceCredentials.SecureConversationAuthentication.SecurityStateEncoder);
228 rstr.RequestedSecurityToken = sct;
229 // without this ProcessApplicationData(), .NET seems
230 // to fail recovering the key.
231 rstr.RequestedProofToken = keyTlsApplied;
232 rstr.RequestedAttachedReference = new LocalIdKeyIdentifierClause (sct.Id);
233 rstr.RequestedUnattachedReference = new SecurityContextKeyIdentifierClause (sct.ContextId, null);
234 WstLifetime lt = new WstLifetime ();
235 lt.Created = from;
236 lt.Expires = from.Add (SecurityBindingElement.LocalServiceSettings.IssuedCookieLifetime);
237 rstr.Lifetime = lt;
238 rstr.BinaryExchange = new WstBinaryExchange (Constants.WstBinaryExchangeValueTls);
239 rstr.BinaryExchange.Value = serverFinished;
241 col.Responses.Add (rstr);
243 // Authenticator is mandatory for MS sslnego.
244 rstr = new WstRequestSecurityTokenResponse (SecurityTokenSerializer);
245 rstr.Context = reader.Value.Context;
246 rstr.Authenticator = tls.CreateHash (key, hash, "AUTH-HASH");
247 col.Responses.Add (rstr);
249 sessions.Remove (reader.Value.Context);
251 // FIXME: get correct tokenRequestor address (probably identity authorized?)
252 if (owner.IssuedSecurityTokenHandler != null)
253 owner.IssuedSecurityTokenHandler (sct, request.Headers.ReplyTo);
255 return Message.CreateMessage (request.Version, Constants.WstIssueReplyAction, col);
258 protected override void OnAbort ()
260 throw new NotImplementedException ();
263 protected override void OnOpen (TimeSpan timeout)
265 if (State == CommunicationState.Opened)
266 throw new InvalidOperationException ("Already opened.");
268 EnsureProperties ();
270 proxy = new WSTrustSecurityTokenServiceProxy (
271 IssuerBinding, IssuerAddress);
274 protected override IAsyncResult OnBeginOpen (TimeSpan timeout, AsyncCallback callback, object state)
276 throw new NotImplementedException ();
279 protected override void OnEndOpen (IAsyncResult result)
281 throw new NotImplementedException ();
284 protected override void OnClose (TimeSpan timeout)
286 if (proxy != null)
287 proxy.Close ();
290 protected override IAsyncResult OnBeginClose (TimeSpan timeout, AsyncCallback callback, object state)
292 throw new NotImplementedException ();
295 protected override void OnEndClose (IAsyncResult result)
297 throw new NotImplementedException ();