X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fclass%2Fcorlib%2FSystem.Security.Cryptography.X509Certificates%2FX509Certificate.cs;h=7830a6b91131af330a332282279f1174bcffa6fd;hb=0717f141b92db56481cc09af70c026d7ffad8921;hp=b61fd6e0da365263ca60a05f143955cc57b35a2a;hpb=0e3361865d53648229b8700c8d76e6af93f1e062;p=mono.git diff --git a/mcs/class/corlib/System.Security.Cryptography.X509Certificates/X509Certificate.cs b/mcs/class/corlib/System.Security.Cryptography.X509Certificates/X509Certificate.cs index b61fd6e0da3..7830a6b9113 100644 --- a/mcs/class/corlib/System.Security.Cryptography.X509Certificates/X509Certificate.cs +++ b/mcs/class/corlib/System.Security.Cryptography.X509Certificates/X509Certificate.cs @@ -1,11 +1,11 @@ // -// X509Certificates.cs: Handles X.509 certificates. +// X509Certificate.cs: Handles X.509 certificates. // // Author: // Sebastien Pouliot // // (C) 2002, 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 @@ -33,11 +33,11 @@ using System.Security.Permissions; using System.Text; using Mono.Security; -using Mono.Security.Authenticode; using Mono.Security.X509; -#if NET_2_0 using System.Runtime.Serialization; +#if !MOONLIGHT +using Mono.Security.Authenticode; #endif namespace System.Security.Cryptography.X509Certificates { @@ -50,11 +50,10 @@ namespace System.Security.Cryptography.X509Certificates { // and/or Authenticode certs. However this class works with older // X509v1 certificates and non-authenticode (code signing) certs. [Serializable] -#if NET_2_0 - [ComVisible (true)] - public class X509Certificate : IDeserializationCallback, ISerializable { +#if NET_2_1 + public partial class X509Certificate { #else - public class X509Certificate { + public partial class X509Certificate : IDeserializationCallback, ISerializable { #endif // typedef struct _CERT_CONTEXT { // DWORD dwCertEncodingType; @@ -97,44 +96,33 @@ namespace System.Security.Cryptography.X509Certificates { public static X509Certificate CreateFromCertFile (string filename) { - byte[] data = null; - using (FileStream fs = new FileStream (filename, FileMode.Open)) { - data = new byte [fs.Length]; - fs.Read (data, 0, data.Length); - fs.Close (); - } + byte[] data = Load (filename); return new X509Certificate (data); } - + +#if !MOONLIGHT [MonoTODO ("Incomplete - minimal validation in this version")] public static X509Certificate CreateFromSignedFile (string filename) { try { AuthenticodeDeformatter a = new AuthenticodeDeformatter (filename); if (a.SigningCertificate != null) { - if (a.Reason != 0) { - string msg = String.Format (Locale.GetText ( - "Invalid digital signature on {0}, reason #{1}."), - filename, a.Reason); - throw new COMException (msg); - } return new X509Certificate (a.SigningCertificate.RawData); } - - // if no signature is present return an empty certificate - byte[] cert = null; // must not confuse compiler about null ;) - return new X509Certificate (cert); } catch (SecurityException) { // don't wrap SecurityException into a COMException throw; } catch (Exception e) { - string msg = String.Format (Locale.GetText ("Couldn't extract digital signature from {0}."), filename); + string msg = Locale.GetText ("Couldn't extract digital signature from {0}.", filename); throw new COMException (msg, e); } + throw new CryptographicException (Locale.GetText ("{0} isn't signed.", filename)); } - + +#endif // NET_2_1 + // constructors // special constructor for Publisher (and related classes). @@ -142,7 +130,7 @@ namespace System.Security.Cryptography.X509Certificates { internal X509Certificate (byte[] data, bool dates) { if (data != null) { - x509 = new Mono.Security.X509.X509Certificate (data); + Import (data, (string)null, X509KeyStorageFlags.DefaultKeySet); hideDates = !dates; } } @@ -151,20 +139,39 @@ namespace System.Security.Cryptography.X509Certificates { { } - [SecurityPermission (SecurityAction.Demand, UnmanagedCode = true)] public X509Certificate (IntPtr handle) + { + if (handle == IntPtr.Zero) + throw new ArgumentException ("Invalid handle."); +#if NET_2_1 + // this works on Windows-only so it's of no use for Moonlight + // even more since this ctor is [SecurityCritical] + throw new NotSupportedException (); +#else + InitFromHandle (handle); +#endif + } + +#if !MOONLIGHT + [SecurityPermission (SecurityAction.Demand, UnmanagedCode = true)] + private void InitFromHandle (IntPtr handle) { if (handle != IntPtr.Zero) { + // both Marshal.PtrToStructure and Marshal.Copy use LinkDemand (so they will always success from here) CertificateContext cc = (CertificateContext) Marshal.PtrToStructure (handle, typeof (CertificateContext)); byte[] data = new byte [cc.cbCertEncoded]; Marshal.Copy (cc.pbCertEncoded, data, 0, (int)cc.cbCertEncoded); x509 = new Mono.Security.X509.X509Certificate (data); } - // IntPtr.Zero results in an "empty" certificate instance + // for 1.x IntPtr.Zero results in an "empty" certificate instance } +#endif public X509Certificate (System.Security.Cryptography.X509Certificates.X509Certificate cert) { + if (cert == null) + throw new ArgumentNullException ("cert"); + if (cert != null) { byte[] data = cert.GetRawCertData (); if (data != null) @@ -173,78 +180,21 @@ namespace System.Security.Cryptography.X509Certificates { } } -#if NET_2_0 - [MonoTODO] - public X509Certificate () - { - } - - [MonoTODO] - public X509Certificate (byte[] rawData, string password) - { - Import (rawData, password, X509KeyStorageFlags.DefaultKeySet); - } - - [MonoTODO] - public X509Certificate (byte[] rawData, SecureString password) - { - Import (rawData, password, X509KeyStorageFlags.DefaultKeySet); - } - - [MonoTODO] - public X509Certificate (byte[] rawData, string password, X509KeyStorageFlags keyStorageFlags) - { - Import (rawData, password, keyStorageFlags); - } - - [MonoTODO] - public X509Certificate (byte[] rawData, SecureString password, X509KeyStorageFlags keyStorageFlags) - { - Import (rawData, password, keyStorageFlags); - } - - [MonoTODO] - public X509Certificate (string fileName) - { - Import (fileName, (string)null, X509KeyStorageFlags.DefaultKeySet); - } - - [MonoTODO] - public X509Certificate (string fileName, string password) - { - Import (fileName, password, X509KeyStorageFlags.DefaultKeySet); - } - - [MonoTODO] - public X509Certificate (string fileName, SecureString password) - { - Import (fileName, password, X509KeyStorageFlags.DefaultKeySet); - } - - [MonoTODO] - public X509Certificate (string fileName, string password, X509KeyStorageFlags keyStorageFlags) - { - Import (fileName, password, keyStorageFlags); - } - - [MonoTODO] - public X509Certificate (string fileName, SecureString password, X509KeyStorageFlags keyStorageFlags) - { - Import (fileName, password, keyStorageFlags); - } - - [MonoTODO] - public X509Certificate (SerializationInfo info, StreamingContext context) - { - } -#endif // public methods - public virtual bool Equals (System.Security.Cryptography.X509Certificates.X509Certificate cert) + public virtual bool Equals (System.Security.Cryptography.X509Certificates.X509Certificate other) { - if (cert != null) { - byte[] raw = cert.GetRawCertData (); + if (other == null) { + return false; + } else { + if (other.x509 == null) { + if (x509 == null) + return true; + throw new CryptographicException (Locale.GetText ("Certificate instance is empty.")); + } + + byte[] raw = other.x509.RawData; if (raw != null) { if (x509 == null) return false; @@ -262,7 +212,7 @@ namespace System.Security.Cryptography.X509Certificates { return false; } } - return (x509.RawData == null); + return ((x509 == null) || (x509.RawData == null)); } // LAMESPEC: This is the equivalent of the "thumbprint" that can be seen @@ -271,6 +221,8 @@ namespace System.Security.Cryptography.X509Certificates { // algorithm used to sign the certificate). public virtual byte[] GetCertHash () { + if (x509 == null) + throw new CryptographicException (Locale.GetText ("Certificate instance is empty.")); // we'll hash the cert only once and only if required if ((cachedCertificateHash == null) && (x509 != null)) { SHA1 sha = SHA1.Create (); @@ -286,25 +238,25 @@ namespace System.Security.Cryptography.X509Certificates { } // strangly there are no DateTime returning function - // LAMESPEC: Microsoft returns the local time from Pacific Time (GMT-8) - // BUG: This will not be corrected in Framework 1.1 and also affect WSE 1.0 public virtual string GetEffectiveDateString () { if (hideDates) return null; - DateTime dt = x509.ValidFrom.ToUniversalTime().AddHours (-8); - return dt.ToString (); //"yyyy-MM-dd HH:mm:ss"); + if (x509 == null) + throw new CryptographicException (Locale.GetText ("Certificate instance is empty.")); + + return x509.ValidFrom.ToLocalTime ().ToString (); } // strangly there are no DateTime returning function - // LAMESPEC: Microsoft returns the local time from Pacific Time (GMT-8) - // BUG: This will not be corrected in Framework 1.1 and also affect WSE 1.0 public virtual string GetExpirationDateString () { if (hideDates) return null; - DateTime dt = x509.ValidUntil.ToUniversalTime().AddHours (-8); - return dt.ToString (); //"yyyy-MM-dd HH:mm:ss"); + if (x509 == null) + throw new CryptographicException (Locale.GetText ("Certificate instance is empty.")); + + return x509.ValidUntil.ToLocalTime ().ToString (); } // well maybe someday there'll be support for PGP or SPKI ? @@ -315,6 +267,8 @@ namespace System.Security.Cryptography.X509Certificates { public override int GetHashCode () { + if (x509 == null) + return 0; // the cert hash may not be (yet) calculated if (cachedCertificateHash == null) GetCertHash(); @@ -327,65 +281,84 @@ namespace System.Security.Cryptography.X509Certificates { return 0; } -#if NET_2_0 [Obsolete ("Use the Issuer property.")] -#endif public virtual string GetIssuerName () { + if (x509 == null) + throw new CryptographicException (Locale.GetText ("Certificate instance is empty.")); return x509.IssuerName; } public virtual string GetKeyAlgorithm () { + if (x509 == null) + throw new CryptographicException (Locale.GetText ("Certificate instance is empty.")); return x509.KeyAlgorithm; } public virtual byte[] GetKeyAlgorithmParameters () { - return x509.KeyAlgorithmParameters; + if (x509 == null) + throw new CryptographicException (Locale.GetText ("Certificate instance is empty.")); + + byte[] kap = x509.KeyAlgorithmParameters; + if (kap == null) + throw new CryptographicException (Locale.GetText ("Parameters not part of the certificate")); + + return kap; } public virtual string GetKeyAlgorithmParametersString () { - return tostr (x509.KeyAlgorithmParameters); + return tostr (GetKeyAlgorithmParameters ()); } -#if NET_2_0 [Obsolete ("Use the Subject property.")] -#endif public virtual string GetName () { + if (x509 == null) + throw new CryptographicException (Locale.GetText ("Certificate instance is empty.")); return x509.SubjectName; } public virtual byte[] GetPublicKey () { + if (x509 == null) + throw new CryptographicException (Locale.GetText ("Certificate instance is empty.")); return x509.PublicKey; } public virtual string GetPublicKeyString () { - return tostr (x509.PublicKey); + return tostr (GetPublicKey ()); } public virtual byte[] GetRawCertData () { - return ((x509 != null) ? x509.RawData : null); + if (x509 == null) + throw new CryptographicException (Locale.GetText ("Certificate instance is empty.")); + return x509.RawData; } public virtual string GetRawCertDataString () { - return ((x509 != null) ? tostr (x509.RawData) : null); + if (x509 == null) + throw new CryptographicException (Locale.GetText ("Certificate instance is empty.")); + return tostr (x509.RawData); } public virtual byte[] GetSerialNumber () { + if (x509 == null) + throw new CryptographicException (Locale.GetText ("Certificate instance is empty.")); return x509.SerialNumber; } public virtual string GetSerialNumberString () { - return tostr (x509.SerialNumber); + byte[] sn = GetSerialNumber (); + Array.Reverse (sn); + return tostr (sn); } // to please corcompare ;-) @@ -394,197 +367,31 @@ namespace System.Security.Cryptography.X509Certificates { return base.ToString (); } - public virtual string ToString (bool details) + public virtual string ToString (bool fVerbose) { - if (details) { - string nl = Environment.NewLine; - StringBuilder sb = new StringBuilder (); - sb.Append ("CERTIFICATE:"); - sb.Append (nl); - sb.Append ("\tFormat: "); - sb.Append (GetFormat ()); - if (x509.SubjectName != null) { - sb.Append (nl); - sb.Append ("\tName: "); - sb.Append (GetName ()); - } - if (x509.IssuerName != null) { - sb.Append (nl); - sb.Append ("\tIssuing CA: "); - sb.Append (GetIssuerName ()); - } - if (x509.SignatureAlgorithm != null) { - sb.Append (nl); - sb.Append ("\tKey Algorithm: "); - sb.Append (GetKeyAlgorithm ()); - } - if (x509.SerialNumber != null) { - sb.Append (nl); - sb.Append ("\tSerial Number: "); - sb.Append (GetSerialNumberString ()); - } - // Note: Algorithm is not spelled right as the actual - // MS implementation (we do exactly the same for the - // comparison in the unit tests) - if (x509.KeyAlgorithmParameters != null) { - sb.Append (nl); - sb.Append ("\tKey Alogrithm Parameters: "); - sb.Append (GetKeyAlgorithmParametersString ()); - } - if (x509.PublicKey != null) { - sb.Append (nl); - sb.Append ("\tPublic Key: "); - sb.Append (GetPublicKeyString ()); - } - sb.Append (nl); - sb.Append (nl); - return sb.ToString (); - } - else + if (!fVerbose || (x509 == null)) return base.ToString (); - } - -#if NET_2_0 - public string Issuer { - get { return x509.IssuerName; } - } - - public string Subject { - get { return x509.SubjectName; } - } - - [ComVisible (false)] - public override bool Equals (object obj) - { - X509Certificate x = (obj as X509Certificate); - if (x != null) - return this.Equals (x); - return false; - } - - [MonoTODO ("incomplete")] - [ComVisible (false)] - public virtual byte[] Export (X509ContentType contentType) - { - return Export (contentType, (byte[])null); - } - - [MonoTODO ("incomplete")] - [ComVisible (false)] - public virtual byte[] Export (X509ContentType contentType, string password) - { - return Export (contentType, Encoding.UTF8.GetBytes (password)); - } - - [MonoTODO ("incomplete")] - public virtual byte[] Export (X509ContentType contentType, SecureString password) - { - return Export (contentType, password.GetBuffer ()); - } - - [MonoTODO ("export!")] - internal byte[] Export (X509ContentType contentType, byte[] password) - { - try { - switch (contentType) { - case X509ContentType.Cert: - return x509.RawData; - default: - throw new NotSupportedException (); - } - } - finally { - // protect password - if (password != null) - Array.Clear (password, 0, password.Length); - } - } - - [MonoTODO] - void IDeserializationCallback.OnDeserialization (object sender) - { - } - - [ComVisible (false)] - public virtual void Import (byte[] rawData) - { - Import (rawData, (string)null, X509KeyStorageFlags.DefaultKeySet); - } - - [MonoTODO ("missing KeyStorageFlags support")] - [ComVisible (false)] - public virtual void Import (byte[] rawData, string password, X509KeyStorageFlags keyStorageFlags) - { - if (password == null) { - x509 = new Mono.Security.X509.X509Certificate (rawData); - // TODO - PKCS12 without password - } else { - // try PKCS#12 - PKCS12 pfx = new PKCS12 (rawData, password); - if (pfx.Certificates.Count > 0) { - x509 = pfx.Certificates [0]; - } else { - x509 = null; - } - } - } - - [MonoTODO ("SecureString is incomplete")] - public virtual void Import (byte[] rawData, SecureString password, X509KeyStorageFlags keyStorageFlags) - { - Import (rawData, (string)null, keyStorageFlags); - } - [ComVisible (false)] - public virtual void Import (string fileName) - { - byte[] rawData = Load (fileName); - Import (rawData, (string)null, X509KeyStorageFlags.DefaultKeySet); + string nl = Environment.NewLine; + StringBuilder sb = new StringBuilder (); + sb.AppendFormat ("[Subject]{0} {1}{0}{0}", nl, Subject); + sb.AppendFormat ("[Issuer]{0} {1}{0}{0}", nl, Issuer); + sb.AppendFormat ("[Not Before]{0} {1}{0}{0}", nl, GetEffectiveDateString ()); + sb.AppendFormat ("[Not After]{0} {1}{0}{0}", nl, GetExpirationDateString ()); + sb.AppendFormat ("[Thumbprint]{0} {1}{0}", nl, GetCertHashString ()); + sb.Append (nl); + return sb.ToString (); } - [MonoTODO ("missing KeyStorageFlags support")] - [ComVisible (false)] - public virtual void Import (string fileName, string password, X509KeyStorageFlags keyStorageFlags) - { - byte[] rawData = Load (fileName); - Import (rawData, password, keyStorageFlags); - } - - [MonoTODO ("SecureString is incomplete")] - public virtual void Import (string fileName, SecureString password, X509KeyStorageFlags keyStorageFlags) - { - byte[] rawData = Load (fileName); - Import (rawData, (string)null, keyStorageFlags); - } - - private byte[] Load (string fileName) + private static byte[] Load (string fileName) { byte[] data = null; - using (FileStream fs = new FileStream (fileName, FileMode.Open)) { + using (FileStream fs = File.OpenRead (fileName)) { data = new byte [fs.Length]; fs.Read (data, 0, data.Length); fs.Close (); } return data; } - - [MonoTODO] - void ISerializable.GetObjectData (SerializationInfo info, StreamingContext context) - { - } - - [MonoTODO] - [ComVisible (false)] - public virtual void Reset () - { - } - - // properties - - [ComVisible (false)] - public IntPtr Handle { - get { return (IntPtr) 0; } - } -#endif } }