1 // Transport Security Layer (TLS)
2 // Copyright (c) 2003-2004 Carlos Guzman Alvarez
3 
4 //
5 // Permission is hereby granted, free of charge, to any person obtaining
6 // a copy of this software and associated documentation files (the
7 // "Software"), to deal in the Software without restriction, including
8 // without limitation the rights to use, copy, modify, merge, publish,
9 // distribute, sublicense, and/or sell copies of the Software, and to
10 // permit persons to whom the Software is furnished to do so, subject to
11 // the following conditions:
12 //
13 // The above copyright notice and this permission notice shall be
14 // included in all copies or substantial portions of the Software.
15 //
16 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 //
24 
25 using System;
26 using System.Collections;
27 using System.IO;
28 using System.Net;
29 using System.Net.Sockets;
30 using System.Security.Cryptography;
31 using System.Security.Cryptography.X509Certificates;
32 
33 using Mono.Security.Protocol.Tls.Handshake;
34 using Mono.Security.Interface;
35 
36 namespace Mono.Security.Protocol.Tls
37 {
38 #if INSIDE_SYSTEM
39 	internal
40 #else
41 	public
42 #endif
43 	class SslServerStream : SslStreamBase
44 	{
45 		#region Internal Events
46 
47 		internal event CertificateValidationCallback	ClientCertValidation;
48 		internal event PrivateKeySelectionCallback		PrivateKeySelection;
49 
50 		#endregion
51 
52 		#region Properties
53 
54 		public X509Certificate ClientCertificate
55 		{
56 			get
57 			{
58 				if (this.context.HandshakeState == HandshakeState.Finished)
59 				{
60 					return this.context.ClientSettings.ClientCertificate;
61 				}
62 
63 				return null;
64 			}
65 		}
66 
67 		#endregion
68 
69 		#region Callback Properties
70 
71 		public CertificateValidationCallback ClientCertValidationDelegate
72 		{
73 			get { return this.ClientCertValidation; }
74 			set { this.ClientCertValidation = value; }
75 		}
76 
77 		public PrivateKeySelectionCallback PrivateKeyCertSelectionDelegate
78 		{
79 			get { return this.PrivateKeySelection; }
80 			set { this.PrivateKeySelection = value; }
81 		}
82 
83 		#endregion
84 
85 		public event CertificateValidationCallback2 ClientCertValidation2;
86 		#region Constructors
87 
SslServerStream( Stream stream, X509Certificate serverCertificate)88 		public SslServerStream(
89 			Stream			stream,
90 			X509Certificate serverCertificate) : this(
91 			stream,
92 			serverCertificate,
93 			false,
94 			false,
95 			SecurityProtocolType.Default)
96 		{
97 		}
98 
SslServerStream( Stream stream, X509Certificate serverCertificate, bool clientCertificateRequired, bool ownsStream)99 		public SslServerStream(
100 			Stream			stream,
101 			X509Certificate serverCertificate,
102 			bool			clientCertificateRequired,
103 			bool			ownsStream): this(
104 			stream,
105 			serverCertificate,
106 			clientCertificateRequired,
107 			ownsStream,
108 			SecurityProtocolType.Default)
109 		{
110 		}
111 
SslServerStream( Stream stream, X509Certificate serverCertificate, bool clientCertificateRequired, bool requestClientCertificate, bool ownsStream)112 		public SslServerStream(
113 			Stream			stream,
114 			X509Certificate serverCertificate,
115 			bool			clientCertificateRequired,
116 			bool			requestClientCertificate,
117 			bool			ownsStream)
118 				: this (stream, serverCertificate, clientCertificateRequired, requestClientCertificate, ownsStream, SecurityProtocolType.Default)
119 		{
120 		}
121 
SslServerStream( Stream stream, X509Certificate serverCertificate, bool clientCertificateRequired, bool ownsStream, SecurityProtocolType securityProtocolType)122 		public SslServerStream(
123 			Stream					stream,
124 			X509Certificate			serverCertificate,
125 			bool					clientCertificateRequired,
126 			bool					ownsStream,
127 			SecurityProtocolType	securityProtocolType)
128 			: this (stream, serverCertificate, clientCertificateRequired, false, ownsStream, securityProtocolType)
129 		{
130 		}
131 
SslServerStream( Stream stream, X509Certificate serverCertificate, bool clientCertificateRequired, bool requestClientCertificate, bool ownsStream, SecurityProtocolType securityProtocolType)132 		public SslServerStream(
133 			Stream					stream,
134 			X509Certificate			serverCertificate,
135 			bool					clientCertificateRequired,
136 			bool					requestClientCertificate,
137 			bool					ownsStream,
138 			SecurityProtocolType	securityProtocolType)
139 			: base(stream, ownsStream)
140 		{
141 			this.context = new ServerContext(
142 				this,
143 				securityProtocolType,
144 				serverCertificate,
145 				clientCertificateRequired,
146 				requestClientCertificate);
147 
148 			this.protocol = new ServerRecordProtocol(innerStream, (ServerContext)this.context);
149 		}
150 
151 		#endregion
152 
153 		#region Finalizer
154 
~SslServerStream()155 		~SslServerStream()
156 		{
157 			this.Dispose(false);
158 		}
159 
160 		#endregion
161 
162 		#region IDisposable Methods
163 
Dispose(bool disposing)164 		protected override void Dispose(bool disposing)
165 		{
166 			base.Dispose(disposing);
167 
168 			if (disposing)
169 			{
170 				this.ClientCertValidation = null;
171 				this.PrivateKeySelection = null;
172 			}
173 		}
174 
175 		#endregion
176 
177 		#region Handsake Methods
178 
179 		/*
180 			Client											Server
181 
182 			ClientHello                 -------->
183 															ServerHello
184 															Certificate*
185 															ServerKeyExchange*
186 															CertificateRequest*
187 										<--------			ServerHelloDone
188 			Certificate*
189 			ClientKeyExchange
190 			CertificateVerify*
191 			[ChangeCipherSpec]
192 			Finished                    -------->
193 															[ChangeCipherSpec]
194 										<--------           Finished
195 			Application Data            <------->			Application Data
196 
197 					Fig. 1 - Message flow for a full handshake
198 		*/
199 
BeginNegotiateHandshake(AsyncCallback callback, object state)200 		internal override IAsyncResult BeginNegotiateHandshake(AsyncCallback callback, object state)
201 		{
202 			// Reset the context if needed
203 			if (this.context.HandshakeState != HandshakeState.None)
204 			{
205 				this.context.Clear();
206 			}
207 
208 			// Obtain supported cipher suites
209 			this.context.SupportedCiphers = CipherSuiteFactory.GetSupportedCiphers (true, context.SecurityProtocol);
210 
211 			// Set handshake state
212 			this.context.HandshakeState = HandshakeState.Started;
213 
214 			// Receive Client Hello message
215 			return this.protocol.BeginReceiveRecord(this.innerStream, callback, state);
216 
217 		}
218 
EndNegotiateHandshake(IAsyncResult asyncResult)219 		internal override void EndNegotiateHandshake(IAsyncResult asyncResult)
220 		{
221 			// Receive Client Hello message and ignore it
222 			this.protocol.EndReceiveRecord(asyncResult);
223 
224 			// If received message is not an ClientHello send a
225 			// Fatal Alert
226 			if (this.context.LastHandshakeMsg != HandshakeType.ClientHello)
227 			{
228 				this.protocol.SendAlert(AlertDescription.UnexpectedMessage);
229 			}
230 
231 			// Send ServerHello message
232 			this.protocol.SendRecord(HandshakeType.ServerHello);
233 
234 			// Send ServerCertificate message
235 			this.protocol.SendRecord(HandshakeType.Certificate);
236 
237 			// If the client certificate is required send the CertificateRequest message
238 			if (((ServerContext)this.context).ClientCertificateRequired ||
239 				((ServerContext)this.context).RequestClientCertificate)
240 			{
241 				this.protocol.SendRecord(HandshakeType.CertificateRequest);
242 			}
243 
244 			// Send ServerHelloDone message
245 			this.protocol.SendRecord(HandshakeType.ServerHelloDone);
246 
247 			// Receive client response, until the Client Finished message
248 			// is received. IE can be interrupted at this stage and never
249 			// complete the handshake
250 			while (this.context.LastHandshakeMsg != HandshakeType.Finished)
251 			{
252 				byte[] record = this.protocol.ReceiveRecord(this.innerStream);
253 				if ((record == null) || (record.Length == 0))
254 				{
255 					throw new TlsException(
256 						AlertDescription.HandshakeFailiure,
257 						"The client stopped the handshake.");
258 				}
259 			}
260 
261 			// Send ChangeCipherSpec and ServerFinished messages
262 			this.protocol.SendChangeCipherSpec();
263 			this.protocol.SendRecord (HandshakeType.Finished);
264 
265 			// The handshake is finished
266 			this.context.HandshakeState = HandshakeState.Finished;
267 
268 			// Reset Handshake messages information
269 			this.context.HandshakeMessages.Reset ();
270 
271 			// Clear Key Info
272 			this.context.ClearKeyInfo();
273 		}
274 
275 		#endregion
276 
277 		#region Event Methods
278 
OnLocalCertificateSelection(X509CertificateCollection clientCertificates, X509Certificate serverCertificate, string targetHost, X509CertificateCollection serverRequestedCertificates)279 		internal override X509Certificate OnLocalCertificateSelection(X509CertificateCollection clientCertificates, X509Certificate serverCertificate, string targetHost, X509CertificateCollection serverRequestedCertificates)
280 		{
281 			throw new NotSupportedException();
282 		}
283 
OnRemoteCertificateValidation(X509Certificate certificate, int[] errors)284 		internal override bool OnRemoteCertificateValidation(X509Certificate certificate, int[] errors)
285 		{
286 			if (this.ClientCertValidation != null)
287 			{
288 				return this.ClientCertValidation(certificate, errors);
289 			}
290 
291 			return (errors != null && errors.Length == 0);
292 		}
293 
294 		internal override bool HaveRemoteValidation2Callback {
295 			get { return ClientCertValidation2 != null; }
296 		}
297 
OnRemoteCertificateValidation2(Mono.Security.X509.X509CertificateCollection collection)298 		internal override ValidationResult OnRemoteCertificateValidation2 (Mono.Security.X509.X509CertificateCollection collection)
299 		{
300 			CertificateValidationCallback2 cb = ClientCertValidation2;
301 			if (cb != null)
302 				return cb (collection);
303 			return null;
304 		}
305 
RaiseClientCertificateValidation( X509Certificate certificate, int[] certificateErrors)306 		internal bool RaiseClientCertificateValidation(
307 			X509Certificate certificate,
308 			int[]			certificateErrors)
309 		{
310 			return base.RaiseRemoteCertificateValidation(certificate, certificateErrors);
311 		}
312 
OnLocalPrivateKeySelection(X509Certificate certificate, string targetHost)313 		internal override AsymmetricAlgorithm OnLocalPrivateKeySelection(X509Certificate certificate, string targetHost)
314 		{
315 			if (this.PrivateKeySelection != null)
316 			{
317 				return this.PrivateKeySelection(certificate, targetHost);
318 			}
319 
320 			return null;
321 		}
322 
RaisePrivateKeySelection( X509Certificate certificate, string targetHost)323 		internal AsymmetricAlgorithm RaisePrivateKeySelection(
324 			X509Certificate certificate,
325 			string targetHost)
326 		{
327 			return base.RaiseLocalPrivateKeySelection(certificate, targetHost);
328 		}
329 
330 		#endregion
331 	}
332 }
333