2010-02-27 Miguel de Icaza <miguel@novell.com>
authorMiguel de Icaza <miguel@gnome.org>
Sat, 27 Feb 2010 23:16:29 +0000 (23:16 -0000)
committerMiguel de Icaza <miguel@gnome.org>
Sat, 27 Feb 2010 23:16:29 +0000 (23:16 -0000)
* OSX509Certificates.cs: Add support to validate X509 certificate
chains using the OSX certificates API.

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

mcs/class/Mono.Security/Mono.Security.Protocol.Tls.Handshake.Client/TlsServerCertificate.cs
mcs/class/Mono.Security/Mono.Security.X509/ChangeLog
mcs/class/Mono.Security/Mono.Security.X509/OSX509Certificates.cs [new file with mode: 0644]
mcs/class/Mono.Security/Mono.Security.dll.sources

index f5bf2e72db0694cfdb588c89b4321c4fcff69890..468ed90b043022d7676c19fa48ddf19edae61c47 100644 (file)
@@ -1,6 +1,6 @@
 // Transport Security Layer (TLS)
 // Copyright (c) 2003-2004 Carlos Guzman Alvarez
-// Copyright (C) 2004, 2006-2007 Novell, Inc (http://www.novell.com)
+// Copyright (C) 2004, 2006-2010 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
@@ -182,6 +182,12 @@ namespace Mono.Security.Protocol.Tls.Handshake.Client
                        return true;
                }
 
+               
+               static private void VerifyOSX (X509CertificateCollection certificates)
+               {
+                       
+               }
+               
                private void validateCertificates(X509CertificateCollection certificates)
                {
                        ClientContext           context                 = (ClientContext)this.Context;
@@ -238,6 +244,18 @@ namespace Mono.Security.Protocol.Tls.Handshake.Client
                                result = false;
                        }
 
+                       // Attempt to use OSX certificates
+                       //
+                       // Ideally we should return the SecTrustResult
+                       if (System.IO.File.Exists (OSX509Certificates.SecurityLibrary)){
+                               OSX509Certificates.SecTrustResult trustResult =  OSX509Certificates.TrustEvaluateSsl (certificates);
+
+                               // We could use the other values of trustResult to pass this extra information to the .NET 2 callback
+                               // for values like SecTrustResult.Confirm
+                               result = (trustResult == OSX509Certificates.SecTrustResult.Proceed ||
+                                         trustResult == OSX509Certificates.SecTrustResult.Unspecified);
+                       }
+                       
                        if (!result) 
                        {
                                switch (verify.Status) 
index 71f0cc3defb857d9c28f1f8427a43a9d4d44fcab..b20c91c63e11270dbb1b786833d87ba358613c5b 100644 (file)
@@ -1,3 +1,8 @@
+2010-02-27  Miguel de Icaza  <miguel@novell.com>
+
+       * OSX509Certificates.cs: Add support to validate X509 certificate
+       chains using the OSX certificates API.
+
 2008-09-12  Sebastien Pouliot  <sebastien@ximian.com>
 
        * PKCS12.cs, X509Store.cs: Use File.Create instead of OpenWrite to
diff --git a/mcs/class/Mono.Security/Mono.Security.X509/OSX509Certificates.cs b/mcs/class/Mono.Security/Mono.Security.X509/OSX509Certificates.cs
new file mode 100644 (file)
index 0000000..c032f9b
--- /dev/null
@@ -0,0 +1,142 @@
+// Copyright (C) 2010 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
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+using System;
+using System.Runtime.InteropServices;
+using Mono.Security.X509;
+using Mono.Security.X509.Extensions;
+
+namespace Mono.Security.X509 {
+
+       internal class OSX509Certificates {
+               public const string SecurityLibrary = "/System/Library/Frameworks/Security.framework/Security";
+               public const string CoreFoundationLibrary = "/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation";
+       
+               [DllImport (SecurityLibrary)]
+               extern static IntPtr SecCertificateCreateWithData (IntPtr allocator, IntPtr nsdataRef);
+               
+               [DllImport (SecurityLibrary)]
+               extern static int SecTrustCreateWithCertificates (IntPtr certOrCertArray, IntPtr policies, out IntPtr sectrustref);
+               
+               [DllImport (SecurityLibrary)]
+               extern static IntPtr SecPolicyCreateSSL (int server, IntPtr cfStringHostname);
+               
+               [DllImport (SecurityLibrary)]
+               extern static int SecTrustEvaluate (IntPtr secTrustRef, out SecTrustResult secTrustResultTime);
+
+               [DllImport (CoreFoundationLibrary)]
+               unsafe extern static IntPtr CFDataCreate (IntPtr allocator, byte *bytes, IntPtr length);
+
+               [DllImport (CoreFoundationLibrary)]
+               unsafe extern static void CFRelease (IntPtr handle);
+
+               [DllImport (CoreFoundationLibrary)]
+               extern static IntPtr CFArrayCreate (IntPtr allocator, IntPtr values, IntPtr numValues, IntPtr callbacks);
+               
+               public enum SecTrustResult {
+                       Invalid,
+                       Proceed,
+                       Confirm,
+                       Deny,
+                       Unspecified,
+                       RecoverableTrustFailure,
+                       FatalTrustFailure,
+                       ResultOtherError,
+               }
+
+               static IntPtr sslsecpolicy = SecPolicyCreateSSL (0, IntPtr.Zero);
+
+               static IntPtr MakeCFData (byte [] data)
+               {
+                       unsafe {
+                               fixed (byte *ptr = &data [0])
+                                       return CFDataCreate (IntPtr.Zero, ptr, (IntPtr) data.Length);
+                       }
+               }
+
+               static unsafe IntPtr FromIntPtrs (IntPtr [] values)
+               {
+                       fixed (IntPtr* pv = values) {
+                               return CFArrayCreate (
+                                       IntPtr.Zero, 
+                                       (IntPtr) pv,
+                                       (IntPtr) values.Length,
+                                       IntPtr.Zero);
+                       }
+               }
+               
+               public static SecTrustResult TrustEvaluateSsl (X509CertificateCollection certificates)
+               {
+                       try {
+                               return _TrustEvaluateSsl (certificates);
+                       } catch {
+                               return SecTrustResult.Deny;
+                       }
+               }
+               
+               static SecTrustResult _TrustEvaluateSsl (X509CertificateCollection certificates)
+               {
+                       if (certificates == null)
+                               throw new ArgumentNullException ("certificates");
+
+                       int certCount = certificates.Count;
+                       IntPtr [] cfDataPtrs = new IntPtr [certCount];
+                       IntPtr [] secCerts = new IntPtr [certCount];
+                       IntPtr certArray = IntPtr.Zero;
+                       
+                       try {
+                               for (int i = 0; i < certCount; i++)
+                                       cfDataPtrs [i] = MakeCFData (certificates [i].RawData);
+                               
+                               for (int i = 0; i < certCount; i++){
+                                       secCerts [i] = SecCertificateCreateWithData (IntPtr.Zero, cfDataPtrs [i]);
+                                       if (secCerts [i] == IntPtr.Zero){
+                                               CFRelease (cfDataPtrs [i]);
+                                               return SecTrustResult.Deny;
+                                       }
+                               }
+                               certArray = FromIntPtrs (secCerts);
+                               IntPtr sectrust;
+                               int code = SecTrustCreateWithCertificates (certArray, sslsecpolicy, out sectrust);
+                               if (code == 0){
+                                       SecTrustResult result;
+                                       code = SecTrustEvaluate (sectrust, out result);
+                                       if (code != 0)
+                                               return SecTrustResult.Deny;
+
+                                       CFRelease (sectrust);
+                                       CFRelease (sslsecpolicy);
+                                       
+                                       return result;
+                               }
+                               return SecTrustResult.Deny;
+                       } finally {
+                               for (int i = 0; i < certCount; i++)
+                                       if (secCerts [i] != IntPtr.Zero)
+                                               CFRelease (cfDataPtrs [i]);
+
+                               if (certArray != IntPtr.Zero)
+                                       CFRelease (certArray);
+                       }
+               }
+       }
+}
+               
\ No newline at end of file
index f38e35e06aba5223770483a2a9ab2304b37a5a84..44c2cc6de3861589b1c0a187876eee671f9187ec 100644 (file)
@@ -36,6 +36,7 @@
 ./Mono.Security.Cryptography/SHA224.cs
 ./Mono.Security.Cryptography/SHA224Managed.cs
 ./Mono.Security.Cryptography/SymmetricTransform.cs
+./Mono.Security.X509/OSX509Certificates.cs
 ./Mono.Security.X509/PKCS12.cs
 ./Mono.Security.X509/X501Name.cs
 ./Mono.Security.X509/X509Builder.cs