1 /* Transport Security Layer (TLS)
2 * Copyright (c) 2003 Carlos Guzmán Álvarez
4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation
6 * files (the "Software"), to deal in the Software without restriction,
7 * including without limitation the rights to use, copy, modify, merge,
8 * publish, distribute, sublicense, and/or sell copies of the Software,
9 * and to permit persons to whom the Software is furnished to do so,
10 * subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included
13 * in all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
27 using System.Collections;
30 using System.Net.Sockets;
31 using System.Security.Cryptography;
33 using Mono.Security.Protocol.Tls.Alerts;
35 namespace Mono.Security.Protocol.Tls
37 public sealed class TlsSession
41 public event TlsWarningAlertEventHandler WarningAlert;
47 private byte[] sessionId;
48 private TlsSessionContext context;
49 private bool helloDone;
50 private bool handshakeFinished;
51 private TlsSessionSettings settings;
52 private TlsCipherSuiteCollection supportedCiphers;
53 private TlsSocket socket;
54 private TlsNetworkStream networkStream;
55 private bool isSecure;
56 private TlsSessionState state;
62 public byte[] SessionId
64 get { return sessionId; }
67 public TlsNetworkStream NetworkStream
69 get { return networkStream; }
72 public TlsSessionState State
79 #region INTERNAL_PROPERTIES
81 internal TlsSessionContext Context
83 get { return context; }
86 internal TlsCipherSuiteCollection SupportedCiphers
88 get { return supportedCiphers; }
91 internal bool HelloDone
93 get { return helloDone; }
94 set { helloDone = value; }
97 internal bool HandshakeFinished
99 get { return handshakeFinished; }
100 set { handshakeFinished = value; }
103 internal bool IsSecure
105 get { return isSecure; }
106 set { isSecure = value; }
109 internal TlsSessionSettings Settings
111 get { return settings; }
114 internal short MaxFragmentSize
116 get { return (short)System.Math.Pow(2, 14); }
123 public TlsSession(TlsSessionSettings settings)
125 this.settings = settings;
126 this.context = new TlsSessionContext();
127 this.sessionId = new byte[0];
129 // Initialize socket for connection
130 this.initializeSocket();
135 #region EXCEPTION_METHODS
137 internal TlsException CreateException(TlsAlertLevel alertLevel, TlsAlertDescription alertDesc)
139 return CreateException(TlsAlert.GetAlertMessage(alertDesc));
142 internal TlsException CreateException(string format, params object[] args)
144 StringBuilder message = new StringBuilder();
145 message.AppendFormat(format, args);
147 return CreateException(message.ToString());
150 internal TlsException CreateException(string message)
152 this.state = TlsSessionState.Broken;
154 // Throw an exception will made the connection unavailable
155 // for this both streams will be closed
158 return new TlsException(message);
169 this.context.Protocol = settings.Protocol;
170 this.context.CompressionMethod = settings.CompressionMethod;
171 this.state = TlsSessionState.OpeningSecure;
172 this.supportedCiphers = TlsCipherSuiteFactory.GetSupportedCiphers(context.Protocol);
173 this.socket.DoHandshake();
174 this.state = TlsSessionState.OpenSecure;
176 catch (TlsException ex)
178 this.state = TlsSessionState.Broken;
183 this.state = TlsSessionState.Broken;
193 this.state = TlsSessionState.Closing;
197 TlsCloseNotifyAlert alert = new TlsCloseNotifyAlert(this);
199 // Write close notify
200 this.socket.SendAlert(alert);
202 // Check that the session is finished by the client and by server
203 if (!this.context.ConnectionEnd)
205 throw new TlsException("Invalid session termination");
211 this.state = TlsSessionState.Broken;
219 this.state = TlsSessionState.Closed;
225 #region INTERNAL_METHODS
227 internal void RaiseWarningAlert(TlsAlertLevel level, TlsAlertDescription description)
229 if (WarningAlert != null)
231 WarningAlert(this, new TlsWarningAlertEventArgs(level, description));
235 internal void SetSessionId(byte[] sessionId)
237 this.sessionId = sessionId;
242 #region PRIVATE_METHODS
244 private void initializeSocket()
248 this.state = TlsSessionState.Opening;
251 IPAddress hostadd = Dns.Resolve(settings.ServerName).AddressList[0];
252 IPEndPoint EPhost = new IPEndPoint(hostadd, settings.ServerPort);
255 socket = new TlsSocket(
257 AddressFamily.InterNetwork,
261 // Make the socket to connect to the Server
262 socket.Connect(EPhost);
263 networkStream = new TlsNetworkStream(socket, true);
265 this.state = TlsSessionState.Open;
269 this.state = TlsSessionState.Broken;
274 private void closeStreams()
276 // Reset session state
277 this.context.IsActual = false;
279 // Close the socket and the networkStream
280 this.networkStream.Close();
282 // Reset session information
283 this.isSecure = false;
284 this.helloDone = false;
285 this.handshakeFinished = false;
286 this.context = new TlsSessionContext();
287 this.sessionId = new byte[0];