2010-06-03 Jb Evain <jbevain@novell.com>
[mcs.git] / class / System.ServiceModel / System.ServiceModel.Security.Tokens / TlsServerSession.cs
blob0355e9f6949c4f45e52fd186b68c3b1fbac4c433
1 //
2 // TlsServerSession.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.IO;
30 using System.Security.Cryptography.X509Certificates;
31 using Mono.Security.Protocol.Tls;
32 using Mono.Security.Protocol.Tls.Handshake;
33 using Mono.Security.Protocol.Tls.Handshake.Server;
35 namespace System.ServiceModel.Security.Tokens
37 internal class TlsServerSession : TlsSession
39 SslServerStream ssl;
40 MemoryStream stream;
41 bool mutual;
43 public TlsServerSession (X509Certificate2 cert, bool mutual)
45 this.mutual = mutual;
46 stream = new MemoryStream ();
47 ssl = new SslServerStream (stream, cert, mutual, true, SecurityProtocolType.Tls);
48 ssl.PrivateKeyCertSelectionDelegate = delegate (X509Certificate c, string host) {
49 if (c.GetCertHashString () == cert.GetCertHashString ())
50 return cert.PrivateKey;
51 return null;
53 ssl.ClientCertValidationDelegate = delegate (X509Certificate certificate, int[] certificateErrors) {
54 // FIXME: use X509CertificateValidator
55 return true;
59 protected override Context Context {
60 get { return ssl.context; }
63 protected override RecordProtocol Protocol {
64 get { return ssl.protocol; }
67 public void ProcessClientHello (byte [] raw)
69 Context.SupportedCiphers = CipherSuiteFactory.GetSupportedCiphers (Context.SecurityProtocol);
70 Context.HandshakeState = HandshakeState.Started;
72 stream.Write (raw, 0, raw.Length);
73 stream.Seek (0, SeekOrigin.Begin);
75 Protocol.ReceiveRecord (stream);
78 // ServerHello, ServerCertificate and ServerHelloDone
79 public byte [] ProcessServerHello ()
81 Context.SessionId = Context.GetSecureRandomBytes (32);
83 #if false
84 // so, can I send handshake batch with RecordProtocol?
85 stream.SetLength (0);
86 Protocol.SendRecord (HandshakeType.ServerHello);
87 Protocol.SendRecord (HandshakeType.Certificate);
88 Protocol.SendRecord (HandshakeType.ServerHelloDone);
89 stream.Flush ();
90 return stream.ToArray ();
92 #else
94 MemoryStream ms = new MemoryStream ();
96 WriteHandshake (ms);
98 if (mutual)
99 WriteOperations (ms,
100 new TlsServerHello (ssl.context),
101 new TlsServerCertificate (ssl.context),
102 new TlsServerCertificateRequest (ssl.context),
103 new TlsServerHelloDone (ssl.context));
104 else
105 WriteOperations (ms,
106 new TlsServerHello (ssl.context),
107 new TlsServerCertificate (ssl.context),
108 new TlsServerHelloDone (ssl.context));
110 return ms.ToArray ();
111 #endif
114 public void ProcessClientKeyExchange (byte [] raw)
116 stream.SetLength (0);
117 stream.Write (raw, 0, raw.Length);
118 stream.Seek (0, SeekOrigin.Begin);
120 if (mutual)
121 Protocol.ReceiveRecord (stream); // Certificate
122 Protocol.ReceiveRecord (stream); // ClientKeyExchange
123 Protocol.ReceiveRecord (stream); // ChangeCipherSpec
124 Protocol.ReceiveRecord (stream); // ClientFinished
126 if (stream.Position != stream.Length)
127 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));
130 public byte [] ProcessServerFinished ()
132 stream.SetLength (0);
133 Protocol.SendChangeCipherSpec ();
134 Protocol.SendRecord (HandshakeType.Finished);
135 stream.Flush ();
136 return stream.ToArray ();
139 public byte [] ProcessApplicationData (byte [] raw)
141 stream.SetLength (0);
142 Protocol.SendRecord (ContentType.ApplicationData, raw);
143 stream.Flush ();
144 return stream.ToArray ();