2006-11-24 Sebastien Pouliot <sebastien@ximian.com>
authorSebastien Pouliot <sebastien@ximian.com>
Fri, 24 Nov 2006 21:06:53 +0000 (21:06 -0000)
committerSebastien Pouliot <sebastien@ximian.com>
Fri, 24 Nov 2006 21:06:53 +0000 (21:06 -0000)
* X509Certificate2.cs: Modified Verify to use CryptoConfig to create
the X509Chain used to verify the certificate. This makes it possible
to change the default chaining (certificate path creation and
validation) algorithm.
* X509Chain.cs: Started implementation based on the options and error
codes defined. Work in progress (incomplete and needs a lot more test
cases).
* X509ChainElementCollection.cs: Added internal methods to Add and
Clear the collection.
* X509ChainElement.cs: Implemented, MonoTODO removed.
* X509ChainPolicy.cs: Add missing checks on enum-based properties.
Renamed fields to match guidelines.
* X509ChainStatus.cs: Provide a default StatusInformation value based
on the Status.

svn path=/trunk/mcs/; revision=68441

mcs/class/System/System.Security.Cryptography.X509Certificates/ChangeLog
mcs/class/System/System.Security.Cryptography.X509Certificates/X509Certificate2.cs
mcs/class/System/System.Security.Cryptography.X509Certificates/X509Chain.cs
mcs/class/System/System.Security.Cryptography.X509Certificates/X509ChainElement.cs
mcs/class/System/System.Security.Cryptography.X509Certificates/X509ChainElementCollection.cs
mcs/class/System/System.Security.Cryptography.X509Certificates/X509ChainPolicy.cs
mcs/class/System/System.Security.Cryptography.X509Certificates/X509ChainStatus.cs

index a5b2a0cedb59c36669868cd47390d9bf84a2b201..e9ff6713f7b86abab8dbd3e5d14d9d74a5eb88c7 100644 (file)
@@ -1,3 +1,20 @@
+2006-11-24  Sebastien Pouliot  <sebastien@ximian.com>
+
+       * X509Certificate2.cs: Modified Verify to use CryptoConfig to create
+       the X509Chain used to verify the certificate. This makes it possible
+       to change the default chaining (certificate path creation and 
+       validation) algorithm.
+       * X509Chain.cs: Started implementation based on the options and error 
+       codes defined. Work in progress (incomplete and needs a lot more test
+       cases).
+       * X509ChainElementCollection.cs: Added internal methods to Add and
+       Clear the collection.
+       * X509ChainElement.cs: Implemented, MonoTODO removed.
+       * X509ChainPolicy.cs: Add missing checks on enum-based properties. 
+       Renamed fields to match guidelines.
+       * X509ChainStatus.cs: Provide a default StatusInformation value based 
+       on the Status.
+
 2006-11-22  Sebastien Pouliot  <sebastien@ximian.com>
 
        * X509Certificate2Collection.cs: Remove comment that proved to be 
index 6c5eac9acf034d5ec537c92f8094e181cdf20eb2..ebc1423f3c455bed7f00331934a22b2cad0413c9 100644 (file)
@@ -558,13 +558,13 @@ namespace System.Security.Cryptography.X509Certificates {
                        }
                }
 
-               [MonoTODO ("depends on incomplete X509Chain")]
+               [MonoTODO ("by default this depends on the incomplete X509Chain")]
                public bool Verify ()
                {
                        if (_cert == null)
                                throw new CryptographicException (empty_error);
 
-                       X509Chain chain = new X509Chain ();
+                       X509Chain chain = (X509Chain) CryptoConfig.CreateFromName ("X509Chain");
                        if (!chain.Build (this))
                                return false;
                        // TODO - check chain and other stuff ???
index 8ec41a21e524881a31dbb5fb1c75e771f8346227..4676e927278513c27ebb937f251537cdb7ab1ea5 100644 (file)
@@ -5,7 +5,7 @@
 //     Sebastien Pouliot  <sebastien@ximian.com>
 //
 // (C) 2003 Motus Technologies Inc. (http://www.motus.com)
-// Copyright (C) 2004-2005 Novell Inc. (http://www.novell.com)
+// Copyright (C) 2004-2006 Novell Inc. (http://www.novell.com)
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the
 
 #if NET_2_0 && SECURITY_DEP
 
+using System.Collections;
+
 namespace System.Security.Cryptography.X509Certificates {
 
        public class X509Chain {
 
                // Set to internal to remove a warning
-               internal bool _machineContext;
-               private X509ChainElementCollection _elements;
-               private X509ChainPolicy _policy;
-               private X509ChainStatus[] _status;
+               private StoreLocation location;
+               private X509ChainElementCollection elements;
+               private X509ChainPolicy policy;
+               private X509ChainStatus[] status;
+
+               static X509ChainStatus[] Empty = new X509ChainStatus [0];
 
                // constructors
 
-               public X509Chain () : this (false)
+               public X509Chain ()
+                       : this (false)
                {
                }
 
                public X509Chain (bool useMachineContext) 
                {
-                       _machineContext = useMachineContext;
-                       _elements = new X509ChainElementCollection ();
-                       _policy = new X509ChainPolicy ();
+                       location = useMachineContext ? StoreLocation.LocalMachine : StoreLocation.CurrentUser;
+                       elements = new X509ChainElementCollection ();
+                       policy = new X509ChainPolicy ();
                }
 
+               [MonoTODO ("Mono's X509Chain is fully managed. All handles are invalid.")]
                public X509Chain (IntPtr chainContext)
                {
                        // CryptoAPI compatibility (unmanaged handle)
@@ -60,45 +66,289 @@ namespace System.Security.Cryptography.X509Certificates {
 
                // properties
 
+               [MonoTODO ("Mono's X509Chain is fully managed. Always returns IntPtr.Zero.")]
                public IntPtr ChainContext {
                        get { return IntPtr.Zero; }
                }
 
                public X509ChainElementCollection ChainElements {
-                       get { return _elements; }
+                       get { return elements; }
                }
 
                public X509ChainPolicy ChainPolicy {
-                       get { return _policy; }
-                       set { _policy = value; }
+                       get { return policy; }
+                       set { policy = value; }
                }
 
                public X509ChainStatus[] ChainStatus {
                        get { 
-                               if (_status == null)
-                                       _status = new X509ChainStatus [0]; 
-                               return _status;
+                               if (status == null)
+                                       return Empty;
+                               return status;
                        }
                } 
 
                // methods
 
-               [MonoTODO]
+               [MonoTODO ("Work in progress")]
                public bool Build (X509Certificate2 certificate)
                {
-                       return false;
+                       if (certificate == null)
+                               throw new ArgumentException ("certificate");
+
+                       Reset ();
+
+                       X509ChainStatusFlags flag;
+                       try {
+                               flag = BuildFrom (certificate);
+                       }
+                       catch (CryptographicException ce) {
+                               throw new ArgumentException ("certificate", ce);
+                       }
+
+                       ArrayList list = new ArrayList ();
+                       // build "global" ChainStatus from the ChainStatus of every ChainElements\r
+                       foreach (X509ChainElement ce in elements) {\r
+                               foreach (X509ChainStatus cs in ce.ChainElementStatus) {\r
+                                       // FIXME - avoid duplicates ?\r
+                                       list.Add (cs);\r
+                               }\r
+                       }
+                       // and if required add some
+                       if (flag != X509ChainStatusFlags.NoError) {
+                               list.Insert (0, new X509ChainStatus (flag));
+                       }
+                       status = (X509ChainStatus[]) list.ToArray (typeof (X509ChainStatus));
+
+                       // (fast path) this ignore everything we have checked\r
+                       if (ChainPolicy.VerificationFlags == X509VerificationFlags.AllFlags)\r
+                               return true;\r
+\r
+                       bool result = true;
+                       // now check if exclude some verification for the "end result" (boolean)\r
+                       foreach (X509ChainStatus cs in status) {\r
+                               switch (cs.Status) {\r
+                               case X509ChainStatusFlags.UntrustedRoot:\r
+                               case X509ChainStatusFlags.PartialChain:\r
+                                       result &= ((ChainPolicy.VerificationFlags & X509VerificationFlags.AllowUnknownCertificateAuthority) != 0);\r
+                                       break;\r
+                               case X509ChainStatusFlags.NotTimeValid:\r
+                                       result &= ((ChainPolicy.VerificationFlags & X509VerificationFlags.IgnoreNotTimeValid) != 0);
+                                       break;\r
+                               // FIXME - from here we needs new test cases for all cases\r
+                               case X509ChainStatusFlags.NotTimeNested:\r
+                                       result &= ((ChainPolicy.VerificationFlags & X509VerificationFlags.IgnoreNotTimeNested) != 0);\r
+                                       break;\r
+                               case X509ChainStatusFlags.InvalidBasicConstraints:\r
+                                       result &= ((ChainPolicy.VerificationFlags & X509VerificationFlags.IgnoreInvalidBasicConstraints) != 0);\r
+                                       break;\r
+                               case X509ChainStatusFlags.InvalidPolicyConstraints:\r
+                               case X509ChainStatusFlags.NoIssuanceChainPolicy:\r
+                                       result &= ((ChainPolicy.VerificationFlags & X509VerificationFlags.IgnoreInvalidPolicy) != 0);\r
+                                       break;\r
+                               case X509ChainStatusFlags.InvalidNameConstraints:\r
+                               case X509ChainStatusFlags.HasNotSupportedNameConstraint:\r
+                               case X509ChainStatusFlags.HasNotPermittedNameConstraint:\r
+                               case X509ChainStatusFlags.HasExcludedNameConstraint:\r
+                                       result &= ((ChainPolicy.VerificationFlags & X509VerificationFlags.IgnoreInvalidName) != 0);\r
+                                       break;\r
+                               case X509ChainStatusFlags.InvalidExtension:\r
+                                       // not sure ?!?\r
+                                       result &= ((ChainPolicy.VerificationFlags & X509VerificationFlags.IgnoreWrongUsage) != 0);\r
+                                       break;\r
+                               //\r
+                               //      ((ChainPolicy.VerificationFlags & X509VerificationFlags.IgnoreRootRevocationUnknown) != 0)\r
+                               //      ((ChainPolicy.VerificationFlags & X509VerificationFlags.IgnoreEndRevocationUnknown) != 0)\r
+                               case X509ChainStatusFlags.CtlNotTimeValid:\r
+                                       result &= ((ChainPolicy.VerificationFlags & X509VerificationFlags.IgnoreCtlNotTimeValid) != 0);\r
+                                       break;\r
+                               case X509ChainStatusFlags.CtlNotSignatureValid:\r
+                                       // ?\r
+                                       break;\r
+                               //      ((ChainPolicy.VerificationFlags & X509VerificationFlags.IgnoreCtlSignerRevocationUnknown) != 0);\r
+                               case X509ChainStatusFlags.CtlNotValidForUsage:\r
+                                       // FIXME - does IgnoreWrongUsage apply to CTL (it doesn't have Ctl in it's name like the others)\r
+                                       result &= ((ChainPolicy.VerificationFlags & X509VerificationFlags.IgnoreWrongUsage) != 0);\r
+                                       break;\r
+                               default:\r
+                                       result = false;\r
+                                       break;\r
+                               }\r
+                               // once we have one failure there's no need to check further\r
+                               if (!result)\r
+                                       return false;\r
+                       }
+
+                       // every "problem" was excluded
+                       return true;
                }
 
-               [MonoTODO]
                public void Reset () 
                {
+                       if ((status != null) && (status.Length != 0))
+                               status = null;
+                       if (elements.Count > 0)
+                               elements.Clear ();
+                       // note: this call doesn't Reset the X509ChainPolicy
                }
 
                // static methods
 
                public static X509Chain Create ()
                {
-                       return new X509Chain ();
+                       return (X509Chain) CryptoConfig.CreateFromName ("X509Chain");
+               }
+
+               // private stuff
+
+               private X509ChainStatusFlags BuildFrom (X509Certificate2 certificate)
+               {\r
+                       X509ChainStatusFlags result = X509ChainStatusFlags.NoError;
+                       X509ChainStatusFlags flags = X509ChainStatusFlags.NoError;
+
+                       // check certificate
+                       Process (certificate, ref flags);
+
+                       // check if certificate is self-signed
+                       if (IsSelfSigned (certificate)) {
+                               // FIXME - add support for cross-certificate, bridges
+                               ProcessRoot (certificate, ref flags);
+                       } else {\r
+                               CheckRevocation (certificate, ref flags);\r
+
+                               X509Certificate2 parent = FindParent (certificate, ref flags);
+                               if (parent != null) {
+                                       // recurse
+                                       result = BuildFrom (parent);
+                                       if (result != X509ChainStatusFlags.NoError)
+                                               return result;
+                               } else {
+                                       // we didn't end with a root, nor could we find one (stores)
+                                       result = X509ChainStatusFlags.PartialChain;
+                               }
+                       }
+                       elements.Add (certificate, flags);
+                       return result;
+               }
+
+               private void Process (X509Certificate2 certificate, ref X509ChainStatusFlags flags)
+               {
+                       // is it the end-entity ?
+                       if (elements.Count == 0) {
+                       }\r
+\r
+                       if ((ChainPolicy.VerificationTime < certificate.NotBefore) ||\r
+                               (ChainPolicy.VerificationTime > certificate.NotAfter)) {\r
+                               flags |= X509ChainStatusFlags.NotTimeValid;\r
+                       }
+
+                       // TODO - for X509ChainStatusFlags.NotTimeNested (needs global structure)\r
+\r
+                       // TODO - for X509ChainStatusFlags.InvalidExtension
+
+                       // TODO - check for X509ChainStatusFlags.InvalidBasicConstraint
+
+                       // TODO - for X509ChainStatusFlags.InvalidPolicyConstraints
+                       //      using X509ChainPolicy.ApplicationPolicy and X509ChainPolicy.CertificatePolicy
+
+                       // TODO - check for X509ChainStatusFlags.NoIssuanceChainPolicy
+
+                       // TODO - check for X509ChainStatusFlags.InvalidNameConstraint
+                       // TODO - check for X509ChainStatusFlags.HasNotSupportedNameConstraint
+                       // TODO - check for X509ChainStatusFlags.HasNotPermittedNameConstraint
+                       // TODO - check for X509ChainStatusFlags.HasExcludedNameConstraint
+               }
+
+               private void ProcessEndEntity (X509Certificate2 certificate, ref X509ChainStatusFlags flags)
+               {
+               }
+
+               private void ProcessCertificateAuthority (X509Certificate2 certificate, ref X509ChainStatusFlags flags)
+               {
+               }
+
+               // CTL == Certificate Trust List / not sure how/if they apply here
+               private void ProcessCTL (X509Certificate2 certificate, ref X509ChainStatusFlags flags)
+               {
+                       // TODO - check for X509ChainStatusFlags.CtlNotTimeValid
+                       // TODO - check for X509ChainStatusFlags.CtlNotSignatureValid
+                       // TODO - check for X509ChainStatusFlags.CtlNotValidForUsage
+               }
+
+               private void ProcessRoot (X509Certificate2 certificate, ref X509ChainStatusFlags flags)
+               {
+                       X509Store trust = new X509Store (StoreName.Root, location);
+                       trust.Open (OpenFlags.ReadOnly);
+                       if (!trust.Certificates.Contains (certificate)) {
+                               flags |= X509ChainStatusFlags.UntrustedRoot;
+                       }
+                       trust.Close ();
+
+                       if (!IsSignedBy (certificate, certificate)) {
+                               flags |= X509ChainStatusFlags.NotSignatureValid;
+                       }
+               }
+
+               // we search local user (default) or machine certificate store 
+               // and in the extra certificate supplied in ChainPolicy.ExtraStore
+               private X509Certificate2 FindParent (X509Certificate2 certificate, ref X509ChainStatusFlags flags)
+               {
+                       X509Certificate2 parent = null;
+
+                       // TODO - check for X509ChainStatusFlags.Cyclic
+
+                       if ((parent != null) && !IsSignedBy (certificate, parent)) {
+                               flags |= X509ChainStatusFlags.NotSignatureValid;
+                       }
+                       return null;
+               }
+
+               // check for "self-signed" certificate - without verifying the signature
+               private bool IsSelfSigned (X509Certificate2 certificate)
+               {\r
+                       // FIXME - very incomplete\r
+                       return (certificate.Issuer == certificate.Subject);\r
+               }
+
+               // this method verify the signature
+               private bool IsSignedBy (X509Certificate2 signed, X509Certificate2 signer)
+               {\r
+                       // FIXME
+                       return true;
+               }\r
+\r
+               private void CheckRevocation (X509Certificate2 certificate, ref X509ChainStatusFlags flags)\r
+               {\r
+                       switch (ChainPolicy.RevocationMode) {\r
+                       case X509RevocationMode.Online:\r
+                               // local?/download CRL and OCSP\r
+                               CheckOnlineRevocation (certificate, ref flags);\r
+                               break;\r
+                       case X509RevocationMode.Offline:\r
+                               // only local CRL ?\r
+                               CheckOfflineRevocation (certificate, ref flags);\r
+                               break;\r
+                       case X509RevocationMode.NoCheck:\r
+                               break;\r
+                       default:\r
+                               throw new InvalidOperationException ();\r
+                       }\r
+               }\r
+\r
+               private void CheckOfflineRevocation (X509Certificate2 certificate, ref X509ChainStatusFlags flags)\r
+               {\r
+                       // TODO - check for X509ChainStatusFlags.Revoked\r
+                       // TODO - check for X509ChainStatusFlags.RevocationStatusUnknown\r
+                       // TODO - check for X509ChainStatusFlags.OfflineRevocation\r
+                       //       (using X509ChainPolicy.RevocationFlag and X509ChainPolicy.RevocationMode)\r
+               }\r
+\r
+               private void CheckOnlineRevocation (X509Certificate2 certificate, ref X509ChainStatusFlags flags)
+               {
+                       // TODO - check for X509ChainStatusFlags.Revoked
+                       // TODO - check for X509ChainStatusFlags.RevocationStatusUnknown
+                       // TODO - check for X509ChainStatusFlags.OfflineRevocation
+                       //       (using X509ChainPolicy.RevocationFlag and X509ChainPolicy.RevocationMode)
                }
        }
 }
index 086ce7c8a6c2c9454e7bd17293e6f98fd50819fd..103f2a119922e38fdc4f246cee7bef4307fa4b55 100644 (file)
@@ -5,7 +5,7 @@
 //     Sebastien Pouliot  <sebastien@ximian.com>
 //
 // (C) 2003 Motus Technologies Inc. (http://www.motus.com)
-// Copyright (C) 2005 Novell Inc. (http://www.novell.com)
+// Copyright (C) 2005-2006 Novell Inc. (http://www.novell.com)
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the
@@ -33,28 +33,91 @@ namespace System.Security.Cryptography.X509Certificates {
 
        public class X509ChainElement {
 
+               private X509Certificate2 certificate;
+               private X509ChainStatus[] status;
+               private string info;
+
                // constructors
 
                // only accessible from X509Chain.ChainElements
-               internal X509ChainElement ()
+               internal X509ChainElement (X509Certificate2 certificate, X509ChainStatusFlags flags)
                {
+                       this.certificate = certificate;
+
+                       if (flags == X509ChainStatusFlags.NoError) {
+                               status = new X509ChainStatus [0];
+                       } else {
+                               int size = Count (flags);
+                               status = new X509ChainStatus [size];
+
+                               int n = 0;
+                               // process every possible error\r
+                               Set (status, ref n, flags, X509ChainStatusFlags.UntrustedRoot);\r
+                               Set (status, ref n, flags, X509ChainStatusFlags.NotTimeValid);
+                               // not yet sorted after this...
+                               Set (status, ref n, flags, X509ChainStatusFlags.NotTimeNested);
+                               Set (status, ref n, flags, X509ChainStatusFlags.Revoked);
+                               Set (status, ref n, flags, X509ChainStatusFlags.NotSignatureValid);
+                               Set (status, ref n, flags, X509ChainStatusFlags.NotValidForUsage);
+                               Set (status, ref n, flags, X509ChainStatusFlags.RevocationStatusUnknown);
+                               Set (status, ref n, flags, X509ChainStatusFlags.Cyclic);
+                               Set (status, ref n, flags, X509ChainStatusFlags.InvalidExtension);
+                               Set (status, ref n, flags, X509ChainStatusFlags.InvalidPolicyConstraints);
+                               Set (status, ref n, flags, X509ChainStatusFlags.InvalidBasicConstraints);
+                               Set (status, ref n, flags, X509ChainStatusFlags.InvalidNameConstraints);
+                               Set (status, ref n, flags, X509ChainStatusFlags.HasNotSupportedNameConstraint);
+                               Set (status, ref n, flags, X509ChainStatusFlags.HasNotDefinedNameConstraint);
+                               Set (status, ref n, flags, X509ChainStatusFlags.HasNotPermittedNameConstraint);
+                               Set (status, ref n, flags, X509ChainStatusFlags.HasExcludedNameConstraint);
+                               Set (status, ref n, flags, X509ChainStatusFlags.PartialChain);
+                               Set (status, ref n, flags, X509ChainStatusFlags.CtlNotTimeValid);
+                               Set (status, ref n, flags, X509ChainStatusFlags.CtlNotSignatureValid);
+                               Set (status, ref n, flags, X509ChainStatusFlags.CtlNotValidForUsage);
+                               Set (status, ref n, flags, X509ChainStatusFlags.OfflineRevocation);
+                               Set (status, ref n, flags, X509ChainStatusFlags.NoIssuanceChainPolicy);
+                       }
+                       // so far String.Empty is the only thing I've seen. 
+                       // The interesting stuff is inside X509ChainStatus.Information
+                       info = String.Empty;
                }
 
                // properties
 
-               [MonoTODO]
                public X509Certificate2 Certificate {
-                       get { return null; }
+                       get { return certificate; }
                }
 
-               [MonoTODO]
                public X509ChainStatus[] ChainElementStatus {
-                       get { return null; }
+                       get { return status; }
                }
 
-               [MonoTODO]
                public string Information {
-                       get { return null; }
+                       get { return info; }
+               }
+
+               // private stuff
+
+               private int Count (X509ChainStatusFlags flags)
+               {
+                       int size = 0;
+                       int n = 0;
+                       int f = (int) flags;
+                       int m = 0x1;
+                       while (n++ < 32) {
+                               if ((f & m) == m)
+                                       size++;
+                               m <<= 1;
+                       }
+                       return size;
+               }
+
+               private void Set (X509ChainStatus[] status, ref int position, X509ChainStatusFlags flags, X509ChainStatusFlags mask)
+               {
+                       if ((flags & mask) != 0) {
+                               status [position].Status = mask;
+                               status [position].StatusInformation = X509ChainStatus.GetInformation (mask);
+                               position++;
+                       }
                }
        }
 }
index 12f904ba502194eb0d8e5d8142e168526503d97d..f47e4c859e98589f1fe063bf47ba55c7c41f4486 100644 (file)
@@ -34,8 +34,6 @@ using System.Collections;
 
 namespace System.Security.Cryptography.X509Certificates {
 
-       // Note: Match the definition of framework version 1.2.3400.0 on http://longhorn.msdn.microsoft.com
-
        public sealed class X509ChainElementCollection : ICollection, IEnumerable {
 
                private ArrayList _list;
@@ -87,6 +85,18 @@ namespace System.Security.Cryptography.X509Certificates {
                {
                        return new X509ChainElementEnumerator (_list);
                }
+
+               // private stuff
+
+               internal void Add (X509Certificate2 certificate, X509ChainStatusFlags flags)
+               {
+                       _list.Add (new X509ChainElement (certificate, flags));
+               }
+
+               internal void Clear ()
+               {
+                       _list.Clear ();
+               }
        }
 }
 
index 5bd0b10a883328638acb0c0369bd5a397264f53b..4a828a8b8f5fae85355449dc12b266d14bd94440 100644 (file)
@@ -5,7 +5,7 @@
 //     Sebastien Pouliot  <sebastien@ximian.com>
 //
 // (C) 2003 Motus Technologies Inc. (http://www.motus.com)
-// Copyright (C) 2005 Novell Inc. (http://www.novell.com)
+// Copyright (C) 2005-2006 Novell Inc. (http://www.novell.com)
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the
@@ -33,14 +33,14 @@ namespace System.Security.Cryptography.X509Certificates {
 
        public sealed class X509ChainPolicy {
 
-               private OidCollection _apps;
-               private OidCollection _cert;
-               private X509Certificate2Collection _store;
-               private X509RevocationFlag _rflag;
-               private X509RevocationMode _mode;
-               private TimeSpan _timeout;
-               private X509VerificationFlags _vflags;
-               private DateTime _vtime;
+               private OidCollection apps;
+               private OidCollection cert;
+               private X509Certificate2Collection store;
+               private X509RevocationFlag rflag;
+               private X509RevocationMode mode;
+               private TimeSpan timeout;
+               private X509VerificationFlags vflags;
+               private DateTime vtime;
 
                // constructors
 
@@ -52,54 +52,66 @@ namespace System.Security.Cryptography.X509Certificates {
                // properties
 
                public OidCollection ApplicationPolicy {
-                       get { return _apps; }
+                       get { return apps; }
                }
 
                public OidCollection CertificatePolicy {
-                       get { return _cert; }
+                       get { return cert; }
                }
 
                public X509Certificate2Collection ExtraStore {
-                       get { return _store; }
+                       get { return store; }
                }
 
                public X509RevocationFlag RevocationFlag {
-                       get { return _rflag; }
-                       set { _rflag = value; }
+                       get { return rflag; }
+                       set {
+                               if ((value < X509RevocationFlag.EndCertificateOnly) || (value > X509RevocationFlag.ExcludeRoot))
+                                       throw new ArgumentException ("RevocationFlag");
+                               rflag = value;
+                       }
                }
 
                public X509RevocationMode RevocationMode {
-                       get { return _mode; }
-                       set { _mode = value; }
+                       get { return mode; }
+                       set {
+                               if ((value < X509RevocationMode.NoCheck) || (value > X509RevocationMode.Offline))
+                                       throw new ArgumentException ("RevocationMode");
+                               mode = value;
+                       }
                }
 
                public TimeSpan UrlRetrievalTimeout {
-                       get { return _timeout; }
-                       set { _timeout = value; }
+                       get { return timeout; }
+                       set { timeout = value; }
                }
 
                public X509VerificationFlags VerificationFlags {
-                       get { return _vflags; }
-                       set { _vflags = value; }
+                       get { return vflags; }
+                       set {
+                               if ((value | X509VerificationFlags.AllFlags) != X509VerificationFlags.AllFlags)
+                                       throw new ArgumentException ("VerificationFlags");
+                               vflags = value;
+                       }
                }
 
                public DateTime VerificationTime {
-                       get { return _vtime; }
-                       set { _vtime = value; }
+                       get { return vtime; }
+                       set { vtime = value; }
                }
 
                // methods
 
                public void Reset ()
                {
-                       _apps = new OidCollection ();
-                       _cert = new OidCollection ();
-                       _store = new X509Certificate2Collection ();
-                       _rflag = X509RevocationFlag.ExcludeRoot;
-                       _mode = X509RevocationMode.Online;
-                       _timeout = new TimeSpan (0);
-                       _vflags = X509VerificationFlags.NoFlag;
-                       _vtime = DateTime.Now;
+                       apps = new OidCollection ();
+                       cert = new OidCollection ();
+                       store = new X509Certificate2Collection ();
+                       rflag = X509RevocationFlag.ExcludeRoot;
+                       mode = X509RevocationMode.Online;
+                       timeout = TimeSpan.Zero;
+                       vflags = X509VerificationFlags.NoFlag;
+                       vtime = DateTime.Now;
                }
        }
 }
index 7f4d67013000e35fbbc42d5a18e26a45dbbaab8c..78d68c178981fcde2f95baa02310eae0d2a4448b 100644 (file)
@@ -2,11 +2,10 @@
 // X509ChainStatus.cs - System.Security.Cryptography.X509Certificates.X509ChainStatus
 //
 // Author:
-//     Sebastien Pouliot (spouliot@motus.com)
+//     Sebastien Pouliot  <sebastien@ximian.com>
 //
 // (C) 2003 Motus Technologies Inc. (http://www.motus.com)
-//
-
+// Copyright (C) 2006 Novell Inc. (http://www.novell.com)
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the
 
 namespace System.Security.Cryptography.X509Certificates {
 
-       // Note: Match the definition of framework version 1.2.3400.0 on http://longhorn.msdn.microsoft.com
-
        public struct X509ChainStatus {
 
-               private X509ChainStatusFlags _status;
-               private string _info;
+               private X509ChainStatusFlags status;
+               private string info;
+
+               internal X509ChainStatus (X509ChainStatusFlags flag)
+               {
+                       status = flag;
+                       info = GetInformation (flag);
+               }
 
                // properties
 
                public X509ChainStatusFlags Status {
-                       get { return _status; }
-                       set { _status = value; }
+                       get { return status; }
+                       set { status = value; }
                }
 
                public string StatusInformation {
-                       get { return _info; }
-                       set { _info = value; }
+                       get { return info; }
+                       set { info = value; }
+               }
+
+               // private stuff
+
+               // note: flags isn't a flag (i.e. multiple values) when used here
+               static internal string GetInformation (X509ChainStatusFlags flags)
+               {
+                       switch (flags) {
+                       case X509ChainStatusFlags.NotTimeValid:
+                       case X509ChainStatusFlags.NotTimeNested:
+                       case X509ChainStatusFlags.Revoked:
+                       case X509ChainStatusFlags.NotSignatureValid:
+                       case X509ChainStatusFlags.NotValidForUsage:
+                       case X509ChainStatusFlags.UntrustedRoot:
+                       case X509ChainStatusFlags.RevocationStatusUnknown:
+                       case X509ChainStatusFlags.Cyclic:
+                       case X509ChainStatusFlags.InvalidExtension:
+                       case X509ChainStatusFlags.InvalidPolicyConstraints:
+                       case X509ChainStatusFlags.InvalidBasicConstraints:
+                       case X509ChainStatusFlags.InvalidNameConstraints:
+                       case X509ChainStatusFlags.HasNotSupportedNameConstraint:
+                       case X509ChainStatusFlags.HasNotDefinedNameConstraint:
+                       case X509ChainStatusFlags.HasNotPermittedNameConstraint:
+                       case X509ChainStatusFlags.HasExcludedNameConstraint:
+                       case X509ChainStatusFlags.PartialChain:
+                       case X509ChainStatusFlags.CtlNotTimeValid:
+                       case X509ChainStatusFlags.CtlNotSignatureValid:
+                       case X509ChainStatusFlags.CtlNotValidForUsage:
+                       case X509ChainStatusFlags.OfflineRevocation:
+                       case X509ChainStatusFlags.NoIssuanceChainPolicy:
+                               return Locale.GetText (flags.ToString ()); // FIXME - add a better description
+                       case X509ChainStatusFlags.NoError:
+                       default:
+                               // should never happen
+                               return String.Empty;
+                       }
                }
        }
 }