1 // Transport Security Layer (TLS)
2 // Copyright (c) 2003-2004 Carlos Guzman Alvarez
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:
13 // The above copyright notice and this permission notice shall be
14 // included in all copies or substantial portions of the Software.
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.
26 using System
.Security
.Cryptography
.X509Certificates
;
28 using Mono
.Security
.Protocol
.Tls
;
30 namespace Mono
.Security
.Protocol
.Tls
.Handshake
.Client
32 internal class TlsClientCertificate
: HandshakeMessage
34 private bool clientCertSelected
;
35 private X509Certificate clientCert
;
39 public TlsClientCertificate(Context context
)
40 : base(context
, HandshakeType
.Certificate
)
48 public X509Certificate ClientCertificate
{
50 if (!clientCertSelected
)
52 GetClientCertificate ();
53 clientCertSelected
= true;
63 public override void Update()
71 #region Protected Methods
73 private void GetClientCertificate ()
75 // TODO: Client certificate selection is unfinished
76 ClientContext context
= (ClientContext
)this.Context
;
78 // note: the server may ask for mutual authentication
79 // but may not require it (i.e. it can be optional).
80 if (context
.ClientSettings
.Certificates
!= null &&
81 context
.ClientSettings
.Certificates
.Count
> 0)
83 clientCert
= context
.SslStream
.RaiseClientCertificateSelection(
84 this.Context
.ClientSettings
.Certificates
,
85 new X509Certificate(this.Context
.ServerSettings
.Certificates
[0].RawData
),
86 this.Context
.ClientSettings
.TargetHost
,
88 // Note: the application code can raise it's
89 // own exception to stop the connection too.
92 // Update the selected client certificate
93 context
.ClientSettings
.ClientCertificate
= clientCert
;
96 private void SendCertificates ()
98 TlsStream chain
= new TlsStream ();
100 X509Certificate currentCert
= this.ClientCertificate
;
101 while (currentCert
!= null) {
102 byte[] rawCert
= currentCert
.GetRawCertData ();
103 chain
.WriteInt24 (rawCert
.Length
);
104 chain
.Write(rawCert
);
105 currentCert
= FindParentCertificate (currentCert
);
107 this.WriteInt24 ((int)chain
.Length
);
108 this.Write (chain
.ToArray ());
111 protected override void ProcessAsSsl3()
113 if (this.ClientCertificate
!= null) {
116 // an Alert warning for NoCertificate (41)
117 // should be sent from here - but that would
118 // break the current message handling
122 protected override void ProcessAsTls1()
124 if (this.ClientCertificate
!= null) {
127 // return message with empty certificate (see 7.4.6 in RFC2246)
132 private X509Certificate
FindParentCertificate (X509Certificate cert
)
134 #pragma warning disable 618
135 // This certificate is the root certificate
136 if (cert
.GetName () == cert
.GetIssuerName ())
139 foreach (X509Certificate certificate
in this.Context
.ClientSettings
.Certificates
) {
140 if (certificate
.GetName () == cert
.GetIssuerName ())
144 #pragma warning restore 618