Merge pull request #3823 from mono/fix-btls-managed
[mono.git] / mcs / class / System / Mono.Btls / X509ChainImplBtls.cs
1 //
2 // X509ChainImplBtls.cs
3 //
4 // Author:
5 //       Martin Baulig <martin.baulig@xamarin.com>
6 //
7 // Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com)
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining a copy
10 // of this software and associated documentation files (the "Software"), to deal
11 // in the Software without restriction, including without limitation the rights
12 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 // copies of the Software, and to permit persons to whom the Software is
14 // furnished to do so, subject to the following conditions:
15 //
16 // The above copyright notice and this permission notice shall be included in
17 // all copies or substantial portions of the Software.
18 //
19 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 // THE SOFTWARE.
26 #if SECURITY_DEP && MONO_FEATURE_BTLS
27 using System;
28 using System.Text;
29 using System.Security;
30 using System.Security.Cryptography;
31 using System.Security.Cryptography.X509Certificates;
32 using MX = Mono.Security.X509;
33
34 namespace Mono.Btls
35 {
36         class X509ChainImplBtls : X509ChainImpl
37         {
38                 MonoBtlsX509StoreCtx storeCtx;
39                 MonoBtlsX509Chain chain;
40                 MonoBtlsX509Chain untrustedChain;
41                 X509ChainElementCollection elements;
42                 X509Certificate2Collection untrusted;
43                 X509Certificate2[] certificates;
44                 X509ChainPolicy policy;
45
46                 internal X509ChainImplBtls (MonoBtlsX509Chain chain)
47                 {
48                         this.chain = chain.Copy ();
49                         policy = new X509ChainPolicy ();
50                 }
51
52                 internal X509ChainImplBtls (MonoBtlsX509StoreCtx storeCtx)
53                 {
54                         this.storeCtx = storeCtx.Copy ();
55                         this.chain = storeCtx.GetChain ();
56
57                         policy = new X509ChainPolicy ();
58
59                         untrustedChain = storeCtx.GetUntrusted ();
60
61                         if (untrustedChain != null) {
62                                 untrusted = new X509Certificate2Collection ();
63                                 policy.ExtraStore = untrusted;
64                                 for (int i = 0; i < untrustedChain.Count; i++) {
65                                         var cert = untrustedChain.GetCertificate (i);
66                                         using (var impl = new X509CertificateImplBtls (cert))
67                                                 untrusted.Add (new X509Certificate2 (impl));
68                                 }
69                         }
70                 }
71
72                 internal X509ChainImplBtls ()
73                 {
74                         chain = new MonoBtlsX509Chain ();
75                         elements = new X509ChainElementCollection ();
76                         policy = new X509ChainPolicy ();
77                 }
78
79                 public override bool IsValid {
80                         get { return chain != null && chain.IsValid; }
81                 }
82
83                 public override IntPtr Handle {
84                         get { return chain.Handle.DangerousGetHandle (); }
85                 }
86
87                 internal MonoBtlsX509Chain Chain {
88                         get {
89                                 ThrowIfContextInvalid ();
90                                 return chain;
91                         }
92                 }
93
94                 internal MonoBtlsX509StoreCtx StoreCtx {
95                         get {
96                                 ThrowIfContextInvalid ();
97                                 return storeCtx;
98                         }
99                 }
100
101                 public override X509ChainElementCollection ChainElements {
102                         get {
103                                 ThrowIfContextInvalid ();
104                                 if (elements != null)
105                                         return elements;
106
107                                 elements = new X509ChainElementCollection ();
108                                 certificates = new X509Certificate2 [chain.Count];
109
110                                 for (int i = 0; i < certificates.Length; i++) {
111                                         var cert = chain.GetCertificate (i);
112                                         using (var impl = new X509CertificateImplBtls (cert))
113                                                 certificates [i] = new X509Certificate2 (impl);
114                                         elements.Add (certificates [i]);
115                                 }
116
117                                 return elements;
118                         }
119                 }
120
121                 public override X509ChainPolicy ChainPolicy {
122                         get { return policy; }
123                         set { policy = value; }
124                 }
125
126                 public override X509ChainStatus[] ChainStatus {
127                         get { throw new NotImplementedException (); }
128                 }
129
130                 public override bool Build (X509Certificate2 certificate)
131                 {
132                         return false;
133                 }
134
135                 public override void Reset ()
136                 {
137                         if (certificates != null) {
138                                 foreach (var certificate in certificates)
139                                         certificate.Dispose ();
140                                 certificates = null;
141                         }
142                         if (elements != null) {
143                                 elements.Clear ();
144                                 elements = null;
145                         }
146                 }
147
148                 protected override void Dispose (bool disposing)
149                 {
150                         if (disposing) {
151                                 if (chain != null) {
152                                         chain.Dispose ();
153                                         chain = null;
154                                 }
155                                 if (storeCtx != null) {
156                                         storeCtx.Dispose ();
157                                         storeCtx = null;
158                                 }
159                                 if (untrustedChain != null) {
160                                         untrustedChain.Dispose ();
161                                         untrustedChain = null;
162                                 }
163                                 if (untrusted != null) {
164                                         foreach (var cert in untrusted)
165                                                 cert.Dispose ();
166                                         untrusted = null;
167                                 }
168                                 if (certificates != null) {
169                                         foreach (var cert in certificates)
170                                                 cert.Dispose ();
171                                         certificates = null;
172                                 }
173                         }
174                         base.Dispose (disposing);
175                 }
176         }
177 }
178 #endif