Merge pull request #5014 from vkargov/vk-kasha
[mono.git] / mcs / class / System / Mono.Net.Security / MobileTlsContext.cs
1 //
2 // MobileTlsContext.cs
3 //
4 // Author:
5 //       Martin Baulig <martin.baulig@xamarin.com>
6 //
7 // Copyright (c) 2015 Xamarin, Inc.
8 //
9
10 #if SECURITY_DEP
11 #if MONO_SECURITY_ALIAS
12 extern alias MonoSecurity;
13 #endif
14
15 #if MONO_SECURITY_ALIAS
16 using MonoSecurity::Mono.Security.Interface;
17 #else
18 using Mono.Security.Interface;
19 #endif
20
21 using System;
22 using System.IO;
23 using SD = System.Diagnostics;
24 using System.Collections;
25 using System.Collections.Generic;
26 using System.Threading;
27 using System.Threading.Tasks;
28 using System.Security.Authentication;
29 using System.Security.Cryptography.X509Certificates;
30
31 namespace Mono.Net.Security
32 {
33         abstract class MobileTlsContext : IDisposable
34         {
35                 MobileAuthenticatedStream parent;
36                 bool serverMode;
37                 string targetHost;
38                 string serverName;
39                 SslProtocols enabledProtocols;
40                 X509Certificate serverCertificate;
41                 X509CertificateCollection clientCertificates;
42                 bool askForClientCert;
43                 ICertificateValidator2 certificateValidator;
44
45                 public MobileTlsContext (
46                         MobileAuthenticatedStream parent, bool serverMode, string targetHost,
47                         SslProtocols enabledProtocols, X509Certificate serverCertificate,
48                         X509CertificateCollection clientCertificates, bool askForClientCert)
49                 {
50                         this.parent = parent;
51                         this.serverMode = serverMode;
52                         this.targetHost = targetHost;
53                         this.enabledProtocols = enabledProtocols;
54                         this.serverCertificate = serverCertificate;
55                         this.clientCertificates = clientCertificates;
56                         this.askForClientCert = askForClientCert;
57
58                         serverName = targetHost;
59                         if (!string.IsNullOrEmpty (serverName)) {
60                                 var pos = serverName.IndexOf (':');
61                                 if (pos > 0)
62                                         serverName = serverName.Substring (0, pos);
63                         }
64
65                         certificateValidator = CertificateValidationHelper.GetInternalValidator (
66                                 parent.Settings, parent.Provider);
67                 }
68
69                 internal MobileAuthenticatedStream Parent {
70                         get { return parent; }
71                 }
72
73                 public MonoTlsSettings Settings {
74                         get { return parent.Settings; }
75                 }
76
77                 public MonoTlsProvider Provider {
78                         get { return parent.Provider; }
79                 }
80
81                 [SD.Conditional ("MARTIN_DEBUG")]
82                 protected void Debug (string message, params object[] args)
83                 {
84                         Console.Error.WriteLine ("{0}: {1}", GetType ().Name, string.Format (message, args));
85                 }
86
87                 public abstract bool HasContext {
88                         get;
89                 }
90
91                 public abstract bool IsAuthenticated {
92                         get;
93                 }
94
95                 public bool IsServer {
96                         get { return serverMode; }
97                 }
98
99                 protected string TargetHost {
100                         get { return targetHost; }
101                 }
102
103                 protected string ServerName {
104                         get { return serverName; }
105                 }
106
107                 protected bool AskForClientCertificate {
108                         get { return askForClientCert; }
109                 }
110
111                 protected SslProtocols EnabledProtocols {
112                         get { return enabledProtocols; }
113                 }
114
115                 protected X509CertificateCollection ClientCertificates {
116                         get { return clientCertificates; }
117                 }
118
119                 protected void GetProtocolVersions (out TlsProtocolCode min, out TlsProtocolCode max)
120                 {
121                         if ((enabledProtocols & SslProtocols.Tls) != 0)
122                                 min = TlsProtocolCode.Tls10;
123                         else if ((enabledProtocols & SslProtocols.Tls11) != 0)
124                                 min = TlsProtocolCode.Tls11;
125                         else
126                                 min = TlsProtocolCode.Tls12;
127
128                         if ((enabledProtocols & SslProtocols.Tls12) != 0)
129                                 max = TlsProtocolCode.Tls12;
130                         else if ((enabledProtocols & SslProtocols.Tls11) != 0)
131                                 max = TlsProtocolCode.Tls11;
132                         else
133                                 max = TlsProtocolCode.Tls10;
134                 }
135
136                 public abstract void StartHandshake ();
137
138                 public abstract bool ProcessHandshake ();
139
140                 public abstract void FinishHandshake ();
141
142                 public abstract MonoTlsConnectionInfo ConnectionInfo {
143                         get;
144                 }
145
146                 internal X509Certificate LocalServerCertificate {
147                         get { return serverCertificate; }
148                 }
149
150                 internal abstract bool IsRemoteCertificateAvailable {
151                         get;
152                 }
153
154                 internal abstract X509Certificate LocalClientCertificate {
155                         get;
156                 }
157
158                 public abstract X509Certificate RemoteCertificate {
159                         get;
160                 }
161
162                 public abstract TlsProtocols NegotiatedProtocol {
163                         get;
164                 }
165
166                 public abstract void Flush ();
167
168                 public abstract int Read (byte[] buffer, int offset, int count, out bool wantMore);
169
170                 public abstract int Write (byte[] buffer, int offset, int count, out bool wantMore);
171
172                 public abstract void Shutdown ();
173
174                 protected bool ValidateCertificate (X509Certificate leaf, X509Chain chain)
175                 {
176                         var result = certificateValidator.ValidateCertificate (TargetHost, IsServer, leaf, chain);
177                         return result != null && result.Trusted && !result.UserDenied;
178                 }
179
180                 protected bool ValidateCertificate (X509CertificateCollection certificates)
181                 {
182                         var result = certificateValidator.ValidateCertificate (TargetHost, IsServer, certificates);
183                         return result != null && result.Trusted && !result.UserDenied;
184                 }
185
186                 protected X509Certificate SelectClientCertificate (X509Certificate serverCertificate, string[] acceptableIssuers)
187                 {
188                         X509Certificate certificate;
189                         var selected = certificateValidator.SelectClientCertificate (
190                                 TargetHost, ClientCertificates, serverCertificate, acceptableIssuers, out certificate);
191                         if (selected)
192                                 return certificate;
193
194                         if (clientCertificates == null || clientCertificates.Count == 0)
195                                 return null;
196
197                         if (clientCertificates.Count == 1)
198                                 return clientCertificates [0];
199
200                         // FIXME: select onne.
201                         throw new NotImplementedException ();
202                 }
203
204                 public void Dispose ()
205                 {
206                         Dispose (true);
207                         GC.SuppressFinalize (this);
208                 }
209
210                 protected virtual void Dispose (bool disposing)
211                 {
212                 }
213
214                 ~MobileTlsContext ()
215                 {
216                         Dispose (false);
217                 }
218         }
219 }
220
221 #endif