Merge pull request #1312 from esdrubal/xmltext
[mono.git] / mcs / class / System / Test / System.Security.Cryptography.X509Certificates / X509ChainTest.cs
1 //
2 // X509ChainTest.cs - NUnit tests for X509Chain
3 //
4 // Author:
5 //      Sebastien Pouliot  <sebastien@ximian.com>
6 //
7 // (C) 2003 Motus Technologies Inc. (http://www.motus.com)
8 // Copyright (C) 2006 Novell, Inc (http://www.novell.com)
9 //
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
17 // 
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
20 // 
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 //
29
30 #if NET_2_0
31
32 using NUnit.Framework;
33
34 using System;
35 using System.Security.Cryptography;
36 using System.Security.Cryptography.X509Certificates;
37 using System.Text;
38
39 namespace MonoTests.System.Security.Cryptography.X509Certificates {
40
41         [TestFixture]
42         public class X509ChainTest {
43
44                 //private X509Certificate2Collection empty;
45                 private X509Certificate2Collection collection;
46
47                 private X509Certificate2 cert_empty;
48                 private X509Certificate2 cert1;
49                 private X509Certificate2 cert2;
50                 private X509Certificate2 cert3;
51
52                 [TestFixtureSetUp]
53                 public void FixtureSetUp ()
54                 {
55                         cert_empty = new X509Certificate2 ();
56                         cert1 = new X509Certificate2 (X509Certificate2Test.farscape_pfx, "farscape", X509KeyStorageFlags.Exportable);
57                         cert2 = new X509Certificate2 (Encoding.ASCII.GetBytes (X509Certificate2Test.base64_cert));
58
59                         //empty = new X509Certificate2Collection ();
60                         collection = new X509Certificate2Collection ();
61                         collection.Add (cert1);
62                         collection.Add (cert2);
63                 }
64
65                 // this method avoid having a dependance on the order of status
66                 public void CheckChainStatus (X509ChainStatusFlags expected, X509ChainStatus[] status, string msg)
67                 {
68                         if ((expected == X509ChainStatusFlags.NoError) && (status.Length == 0))
69                                 return;
70
71                         X509ChainStatusFlags actual = X509ChainStatusFlags.NoError;
72                         foreach (X509ChainStatus s in status) {
73                                 actual |= s.Status;
74                         }
75                         Assert.AreEqual (expected, actual, msg);
76                 }
77
78                 private void CheckDefaultChain (X509Chain c)
79                 {
80                         Assert.AreEqual (0, c.ChainElements.Count, "ChainElements");
81                         Assert.IsNotNull (c.ChainPolicy, "ChainPolicy");
82                         Assert.AreEqual (0, c.ChainStatus.Length, "ChainStatus");
83                         // check default policy
84                         CheckDefaultPolicy (c.ChainPolicy);
85                 }
86
87                 private void CheckDefaultPolicy (X509ChainPolicy p)
88                 {
89                         Assert.AreEqual (0, p.ApplicationPolicy.Count, "ApplicationPolicy");
90                         Assert.AreEqual (0, p.CertificatePolicy.Count, "CertificatePolicy");
91                         Assert.AreEqual (0, p.ExtraStore.Count, "ExtraStore");
92                         Assert.AreEqual (X509RevocationFlag.ExcludeRoot, p.RevocationFlag, "RevocationFlag");
93                         Assert.AreEqual (X509RevocationMode.Online, p.RevocationMode, "RevocationMode");
94                         Assert.AreEqual (0, p.UrlRetrievalTimeout.Ticks, "UrlRetrievalTimeout");
95                         Assert.AreEqual (X509VerificationFlags.NoFlag, p.VerificationFlags, "VerificationFlags");
96                         Assert.IsTrue (p.VerificationTime <= DateTime.Now, "VerificationTime");
97                 }
98
99                 [Test]
100                 public void ConstructorEmpty () 
101                 {
102                         X509Chain c = new X509Chain ();
103                         CheckDefaultChain (c);
104                 }
105
106                 [Test]
107                 public void ConstructorMachineContextFalse () 
108                 {
109                         X509Chain c = new X509Chain (false);
110                         CheckDefaultChain (c);
111                 }
112
113                 [Test]
114                 public void ConstructorMachineContextTrue () 
115                 {
116                         X509Chain c = new X509Chain (true);
117                         CheckDefaultChain (c);
118                 }
119
120                 [Test]
121                 [ExpectedException (typeof (ArgumentException))]
122                 public void Build_Null ()
123                 {
124                         X509Chain c = new X509Chain ();
125                         c.Build (null);
126                 }
127
128                 [Test]
129                 [ExpectedException (typeof (ArgumentException))]
130                 public void Build_Empty ()
131                 {
132                         X509Chain c = new X509Chain ();
133                         c.Build (cert_empty);
134                 }
135
136                 [Test]
137                 public void Build_Twice_SameCertificate ()
138                 {
139                         X509Chain c = new X509Chain ();
140                         Assert.IsFalse (c.Build (cert1), "Build-1a");
141                         Assert.IsFalse (c.Build (cert1), "Build-2a");
142                 }
143
144                 [Test]
145                 public void Build_Twice_DifferentCertificate ()
146                 {
147                         X509Chain c = new X509Chain ();
148                         Assert.IsFalse (c.Build (cert1), "Build-1");
149                         Assert.IsFalse (c.Build (cert2), "Build-2");
150                 }
151
152                 [Test]
153                 public void Build_Twice_WithReset ()
154                 {
155                         X509Chain c = new X509Chain ();
156                         Assert.IsFalse (c.Build (cert1), "Build-1");
157                         c.Reset ();
158                         Assert.IsFalse (c.Build (cert2), "Build-2");
159                         c.Reset ();
160                         CheckDefaultChain (c);
161                 }
162
163                 private void CheckCert1 (X509Chain c)
164                 {
165                         X509VerificationFlags success_mask;
166
167                         switch (c.ChainPolicy.RevocationMode) {
168                         case X509RevocationMode.Offline:
169                         case X509RevocationMode.Online:
170                                 success_mask = X509VerificationFlags.IgnoreNotTimeValid | X509VerificationFlags.AllowUnknownCertificateAuthority;
171                                 break;
172                         case X509RevocationMode.NoCheck:
173                         default:
174                                 success_mask = X509VerificationFlags.AllowUnknownCertificateAuthority;
175                                 break;
176                         }
177
178                         Assert.AreEqual (((c.ChainPolicy.VerificationFlags & success_mask) == success_mask), c.Build (cert1), "Build");
179                         Assert.AreEqual (1, c.ChainElements.Count, "ChainElements");
180                         Assert.AreEqual (String.Empty, c.ChainElements[0].Information, "ChainElements[0].Information");
181                         Assert.AreEqual (cert1, c.ChainElements[0].Certificate, "ChainElements[0].Certificate");
182
183                         switch (c.ChainPolicy.RevocationMode) {
184                         case X509RevocationMode.Offline:
185                         case X509RevocationMode.Online:
186                                 CheckChainStatus (X509ChainStatusFlags.PartialChain | X509ChainStatusFlags.RevocationStatusUnknown | X509ChainStatusFlags.OfflineRevocation, c.ChainStatus, "c.ChainStatus");
187                                 CheckChainStatus (X509ChainStatusFlags.RevocationStatusUnknown | X509ChainStatusFlags.OfflineRevocation, c.ChainElements[0].ChainElementStatus, "c.ChainElements[0].ChainElementStatus");
188                                 break;
189                         case X509RevocationMode.NoCheck:
190                                 CheckChainStatus (X509ChainStatusFlags.PartialChain, c.ChainStatus, "c.ChainStatus");
191                                 CheckChainStatus (X509ChainStatusFlags.NoError, c.ChainElements[0].ChainElementStatus, "c.ChainElements[0].ChainElementStatus");
192                                 break;
193                         }
194                 }
195
196                 [Test]
197                 public void Build_Cert1_X509RevocationMode_Offline ()
198                 {
199                         X509Chain c = new X509Chain ();
200                         c.ChainPolicy.RevocationMode = X509RevocationMode.Offline; // default
201                         foreach (X509VerificationFlags vf in Enum.GetValues (typeof (X509VerificationFlags))) {
202                                 c.ChainPolicy.VerificationFlags = vf;
203                                 CheckCert1 (c);
204                                 c.Reset ();
205                         }
206                 }
207
208                 [Test]
209                 [Category ("InetAccess")]
210                 public void Build_Cert1_X509RevocationMode_Online ()
211                 {
212                         X509Chain c = new X509Chain ();
213                         c.ChainPolicy.RevocationMode = X509RevocationMode.Online;
214                         foreach (X509VerificationFlags vf in Enum.GetValues (typeof (X509VerificationFlags))) {
215                                 c.ChainPolicy.VerificationFlags = vf;
216                                 CheckCert1 (c);
217                                 c.Reset ();
218                         }
219                 }
220
221                 [Test]
222                 public void Build_Cert1_X509RevocationMode_NoCheck ()
223                 {
224                         X509Chain c = new X509Chain ();
225                         c.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;
226                         foreach (X509VerificationFlags vf in Enum.GetValues (typeof (X509VerificationFlags))) {
227                                 c.ChainPolicy.VerificationFlags = vf;
228                                 CheckCert1 (c);
229                                 c.Reset ();
230                         }
231                 }
232
233                 private void CheckCert2 (X509Chain c)
234                 {
235                         X509VerificationFlags success_mask = X509VerificationFlags.IgnoreNotTimeValid | X509VerificationFlags.AllowUnknownCertificateAuthority;
236                         Assert.AreEqual (((c.ChainPolicy.VerificationFlags & success_mask) == success_mask), c.Build (cert2), "Build");
237                         Assert.AreEqual (1, c.ChainElements.Count, "ChainElements");
238                         Assert.AreEqual (String.Empty, c.ChainElements[0].Information, "ChainElements[0].Information");
239                         Assert.AreEqual (cert2, c.ChainElements[0].Certificate, "ChainElements[0].Certificate");
240
241                         CheckChainStatus (X509ChainStatusFlags.UntrustedRoot | X509ChainStatusFlags.NotTimeValid, c.ChainStatus, "c.ChainStatus");
242                         CheckChainStatus (X509ChainStatusFlags.UntrustedRoot | X509ChainStatusFlags.NotTimeValid, c.ChainElements[0].ChainElementStatus, "c.ChainElements[0].ChainElementStatus");
243                 }
244
245                 [Test]
246                 public void Build_Cert2 ()
247                 {
248                         X509Chain c = new X509Chain ();
249                         foreach (X509VerificationFlags vf in Enum.GetValues (typeof (X509VerificationFlags))) {
250                                 c.ChainPolicy.VerificationFlags = vf;
251                                 CheckCert2 (c);
252                                 c.Reset ();
253                         }
254                         // minimal criteria for success
255                         c.ChainPolicy.VerificationFlags = X509VerificationFlags.IgnoreNotTimeValid | X509VerificationFlags.AllowUnknownCertificateAuthority;
256                         CheckCert2 (c);
257                 }
258
259                 [Test]
260                 public void Reset ()
261                 {
262                         X509Chain c = new X509Chain ();
263                         c.ChainPolicy.ApplicationPolicy.Add (new Oid ("1.2.3"));
264                         c.ChainPolicy.CertificatePolicy.Add (new Oid ("1.2.4"));
265                         c.ChainPolicy.ExtraStore.AddRange (collection);
266                         c.ChainPolicy.RevocationFlag = X509RevocationFlag.EntireChain;
267                         c.ChainPolicy.RevocationMode = X509RevocationMode.Offline;
268                         c.ChainPolicy.UrlRetrievalTimeout = new TimeSpan (1000);
269                         c.ChainPolicy.VerificationFlags = X509VerificationFlags.IgnoreWrongUsage;
270                         c.ChainPolicy.VerificationTime = DateTime.MinValue;
271                         c.Reset ();
272                         // resetting the chain doesn't reset the policy
273                         Assert.AreEqual (1, c.ChainPolicy.ApplicationPolicy.Count, "ApplicationPolicy");
274                         Assert.AreEqual (1, c.ChainPolicy.CertificatePolicy.Count, "CertificatePolicy");
275                         Assert.AreEqual (2, c.ChainPolicy.ExtraStore.Count, "ExtraStore");
276                         Assert.AreEqual (X509RevocationFlag.EntireChain, c.ChainPolicy.RevocationFlag, "RevocationFlag");
277                         Assert.AreEqual (X509RevocationMode.Offline, c.ChainPolicy.RevocationMode, "RevocationMode");
278                         Assert.AreEqual (1000, c.ChainPolicy.UrlRetrievalTimeout.Ticks, "UrlRetrievalTimeout");
279                         Assert.AreEqual (X509VerificationFlags.IgnoreWrongUsage, c.ChainPolicy.VerificationFlags, "VerificationFlags");
280                         Assert.AreEqual (DateTime.MinValue, c.ChainPolicy.VerificationTime, "VerificationTime");
281                 }
282
283                 [Test]
284                 public void StaticCreation () 
285                 {
286                         X509Chain c = X509Chain.Create ();
287                         CheckDefaultChain (c);
288                 }
289
290                 [Test]
291                 public void CreateViaCryptoConfig ()
292                 {
293                         // X509Chain can be changed using CryptoConfig
294                         Assert.AreEqual (typeof (X509Chain), CryptoConfig.CreateFromName ("X509Chain").GetType (), "X509Chain");
295                         Assert.IsNull (CryptoConfig.CreateFromName ("System.Security.Cryptography.X509Certificates.X509Chain"), "System.Security.Cryptography.X509Certificates.X509Chain");
296                 }
297         }
298 }
299
300 #endif