* X509Chain.cs: Fixed build for net_1_0 profile.
[mono.git] / mcs / class / Mono.Security / Mono.Security.Protocol.Tls / ClientRecordProtocol.cs
1 /* Transport Security Layer (TLS)
2  * Copyright (c) 2003-2004 Carlos Guzman Alvarez
3  * 
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:
11  * 
12  * The above copyright notice and this permission notice shall be included 
13  * in all copies or substantial portions of the Software.
14  * 
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.
23  */
24
25 using System;
26 using System.IO;
27
28 using Mono.Security.Protocol.Tls.Handshake;
29 using Mono.Security.Protocol.Tls.Handshake.Client;
30
31 namespace Mono.Security.Protocol.Tls
32 {
33         internal class ClientRecordProtocol : RecordProtocol
34         {
35                 #region Constructors
36
37                 public ClientRecordProtocol(
38                         Stream                  innerStream, 
39                         ClientContext   context) : base(innerStream, context)
40                 {
41                 }
42
43                 #endregion
44
45                 #region Send Messages
46
47                 public override void SendRecord(HandshakeType type)
48                 {
49                         // Create the record message
50                         HandshakeMessage msg = this.createClientHandshakeMessage(type);
51                         
52                         // Write record
53                         this.SendRecord(msg.ContentType, msg.EncodeMessage());
54
55                         // Update session
56                         msg.Update();
57
58                         // Reset message contents
59                         msg.Reset();
60                 }
61
62                 #endregion
63
64                 #region Handshake Processing Methods
65
66                 protected override void ProcessChangeCipherSpec()
67                 {
68                         // Reset sequence numbers
69                         this.context.ReadSequenceNumber = 0;
70                 }
71
72                 protected override void ProcessHandshakeMessage(TlsStream handMsg)
73                 {
74                         HandshakeType           handshakeType   = (HandshakeType)handMsg.ReadByte();
75                         HandshakeMessage        message                 = null;
76
77                         // Read message length
78                         int length = handMsg.ReadInt24();
79
80                         // Read message data
81                         byte[] data = new byte[length];
82                         handMsg.Read(data, 0, length);
83
84                         // Create and process the server message
85                         message = this.createServerHandshakeMessage(handshakeType, data);
86
87                         // Update the last handshake message
88                         this.Context.LastHandshakeMsg = handshakeType;
89
90                         // Update session
91                         if (message != null)
92                         {
93                                 message.Update();
94                         }
95                 }
96
97                 #endregion
98
99                 #region Client Handshake Message Factories
100
101                 private HandshakeMessage createClientHandshakeMessage(
102                         HandshakeType type)
103                 {
104                         switch (type)
105                         {
106                                 case HandshakeType.ClientHello:
107                                         return new TlsClientHello(this.context);
108
109                                 case HandshakeType.Certificate:
110                                         return new TlsClientCertificate(this.context);
111
112                                 case HandshakeType.ClientKeyExchange:
113                                         return new TlsClientKeyExchange(this.context);
114
115                                 case HandshakeType.CertificateVerify:
116                                         return new TlsClientCertificateVerify(this.context);
117
118                                 case HandshakeType.Finished:
119                                         return new TlsClientFinished(this.context);
120
121                                 default:
122                                         throw new InvalidOperationException("Unknown client handshake message type: " + type.ToString() );
123                         }
124                 }
125
126                 private HandshakeMessage createServerHandshakeMessage(
127                         HandshakeType type, byte[] buffer)
128                 {
129                         ClientContext context = (ClientContext)this.context;
130
131                         switch (type)
132                         {
133                                 case HandshakeType.HelloRequest:
134                                         if (context.HandshakeState != HandshakeState.Started)
135                                         {
136                                                 context.SslStream.NegotiateHandshake();
137                                         }
138                                         else
139                                         {
140                                                 this.SendAlert(
141                                                         AlertLevel.Warning,
142                                                         AlertDescription.NoRenegotiation);
143                                         }
144                                         return null;
145
146                                 case HandshakeType.ServerHello:
147                                         return new TlsServerHello(this.context, buffer);
148
149                                 case HandshakeType.Certificate:
150                                         return new TlsServerCertificate(this.context, buffer);
151
152                                 case HandshakeType.ServerKeyExchange:
153                                         return new TlsServerKeyExchange(this.context, buffer);
154
155                                 case HandshakeType.CertificateRequest:
156                                         return new TlsServerCertificateRequest(this.context, buffer);
157
158                                 case HandshakeType.ServerHelloDone:
159                                         return new TlsServerHelloDone(this.context, buffer);
160
161                                 case HandshakeType.Finished:
162                                         return new TlsServerFinished(this.context, buffer);
163
164                                 default:
165                                         throw this.context.CreateException("Unknown server handshake message received ({0})", type.ToString());
166                         }
167                 }
168
169                 #endregion
170         }
171 }