From: Vladislav Vaintroub Date: October 19 2009 3:49pm Subject: bzr commit into connector-net-trunk branch (vvaintroub:786) List-Archive: http://lists.mysql.com/commits/87353 Message-Id: <0KRR001BLQM0LH30@fe-emea-09.sun.com> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="Boundary_(ID_1sZOYR8vE8SY+louFRgP/Q)" --Boundary_(ID_1sZOYR8vE8SY+louFRgP/Q) MIME-version: 1.0 Content-type: text/plain; CHARSET=US-ASCII Content-transfer-encoding: 7BIT Content-disposition: inline #At file:///H:/connector_net/trunk/ based on revid:vvaintroub@stripped 786 Vladislav Vaintroub 2009-10-19 Implement support for client SSL certificates modified: MySql.Data/Provider/Source/MySqlConnectionStringBuilder.cs MySql.Data/Provider/Source/NativeDriver.cs === modified file 'MySql.Data/Provider/Source/MySqlConnectionStringBuilder.cs' --- a/MySql.Data/Provider/Source/MySqlConnectionStringBuilder.cs 2009-10-09 21:44:54 +0000 +++ b/MySql.Data/Provider/Source/MySqlConnectionStringBuilder.cs 2009-10-19 15:49:09 +0000 @@ -28,6 +28,7 @@ using System.Text; using MySql.Data.MySqlClient.Properties; using System.Collections; using System.Globalization; +using System.Security.Cryptography.X509Certificates; namespace MySql.Data.MySqlClient { @@ -321,8 +322,75 @@ namespace MySql.Data.MySqlClient } } + [Category("Authentication")] + [DisplayName("Certificate File")] + [Description("Certificate file in PKCS#12 format (.pfx)")] + [DefaultValue(null)] + public string CertificateFile + { + get { return (string) values["Certificate File"];} + set + { + SetValue("Certificate File", value); + } + } + + [Category("Authentication")] + [DisplayName("Certificate Password")] + [Description("Password for certificate file")] + [DefaultValue(null)] + public string CertificatePassword + { + get { return (string)values["Certificate Password"];} + set + { + SetValue("Certificate Password", value); + } + } + + [Category("Authentication")] + [DisplayName("Certificate Store Location")] + [Description("Certificate Store Location (CurrentUser or LocalMachine)")] + [DefaultValue(null)] + public string CertificateStoreLocation + { + get { return (string)values["Certificate Store Location"]; } + set + { + if (value != null) + { + try + { + Enum.Parse(typeof(StoreLocation), value); + } + catch (ArgumentException) + { + throw new InvalidOperationException(String.Format( + Resources.InvalidConnectionStringValue, value, + "Certificate Store Location")); + } + } + SetValue("Certificate Store Location", value); + } + } + + [Category("Authentication")] + [DisplayName("Certificate Thumbprint")] + [Description("Certificate thumbprint. Can be used together with Certificate "+ + "Store Location parameter to uniquely identify certificate to be used "+ + "for SSL authentication.")] + [DefaultValue(null)] + public string CertificateThumbprint + { + get { return (string)values["Certificate Store Location"]; } + set + { + SetValue("Certificate Store Location", value); + } + } #endregion + #region Other Properties /// === modified file 'MySql.Data/Provider/Source/NativeDriver.cs' --- a/MySql.Data/Provider/Source/NativeDriver.cs 2009-10-09 21:44:54 +0000 +++ b/MySql.Data/Provider/Source/NativeDriver.cs 2009-10-19 15:49:09 +0000 @@ -259,12 +259,59 @@ namespace MySql.Data.MySqlClient #region SSL + /// + /// Retrieve client SSL certificates. Dependent on connection string + /// settings we use either file or store based certificates. + /// + private X509CertificateCollection GetClientCertificates() + { + X509CertificateCollection certs = new X509CertificateCollection(); + + // Check for file-based certificate + if (Settings.CertificateFile != null) + { + X509Certificate2 clientCert = new X509Certificate2(Settings.CertificateFile, + Settings.CertificatePassword); + certs.Add(clientCert); + return certs; + } + + if (Settings.CertificateStoreLocation != null) + return certs; + + // Check for store-based certificate + StoreLocation location = (StoreLocation) + Enum.Parse(typeof(StoreLocation), Settings.CertificateStoreLocation); + X509Store store = new X509Store(StoreName.My, location); + store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly); + + + if (Settings.CertificateThumbprint == null) + { + // Return all certificates from the store. + certs.AddRange(store.Certificates); + return certs; + } + + // Find certificate with given thumbprint + certs.AddRange(store.Certificates.Find(X509FindType.FindByThumbprint, + Settings.CertificateThumbprint, true)); + + if (certs.Count == 0) + { + throw new MySqlException("Certificate with Thumbprint " + + Settings.CertificateThumbprint + " not found"); + } + return certs; + } + + private void StartSSL() { RemoteCertificateValidationCallback sslValidateCallback = new RemoteCertificateValidationCallback(ServerCheckValidation); SslStream ss = new SslStream(baseStream, true, sslValidateCallback, null); - X509CertificateCollection certs = new X509CertificateCollection(); + X509CertificateCollection certs = GetClientCertificates(); ss.AuthenticateAsClient(Settings.Server, certs, SslProtocols.Default, false); baseStream = ss; stream = new MySqlStream(ss, Encoding, false); --Boundary_(ID_1sZOYR8vE8SY+louFRgP/Q) MIME-version: 1.0 Content-type: text/bzr-bundle; CHARSET=US-ASCII; name="bzr/vvaintroub@stripped" Content-transfer-encoding: 7BIT Content-disposition: inline; filename="bzr/vvaintroub@stripped" # Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: vvaintroub@stripped # target_branch: file:///H:/connector_net/trunk/ # testament_sha1: 00fe0216c889c440333c14314b5360ed678299d9 # timestamp: 2009-10-19 17:49:10 +0200 # source_branch: file:///H:/connector_net/6.1/ # base_revision_id: vvaintroub@stripped\ # u8r6mvnkqa5579mm # # Begin bundle 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 --Boundary_(ID_1sZOYR8vE8SY+louFRgP/Q)--