From: Vladislav Vaintroub Date: October 19 2009 8:34pm Subject: bzr commit into connector-net-trunk branch (vvaintroub:786) List-Archive: http://lists.mysql.com/commits/87374 Message-Id: <0KRS00FJG3TXUS60@fe-emea-10.sun.com> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="Boundary_(ID_tV+n6ufDbh1UqjX1yKaqOA)" --Boundary_(ID_tV+n6ufDbh1UqjX1yKaqOA) 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/MysqlDefs.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 20:34:41 +0000 @@ -321,6 +321,59 @@ 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 for client certificates")] + [DefaultValue(MySqlCertificateStoreLocation.None)] + public MySqlCertificateStoreLocation CertificateStoreLocation + { + get { return (MySqlCertificateStoreLocation)values["Certificate Store Location"]; } + set + { + 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 Thumbprint"]; } + set + { + SetValue("Certificate Thumbprint", value); + } + } #endregion #region Other Properties === modified file 'MySql.Data/Provider/Source/MysqlDefs.cs' --- a/MySql.Data/Provider/Source/MysqlDefs.cs 2009-10-09 21:44:54 +0000 +++ b/MySql.Data/Provider/Source/MysqlDefs.cs 2009-10-19 20:34:41 +0000 @@ -390,4 +390,20 @@ namespace MySql.Data.MySqlClient /// Embedded } + + public enum MySqlCertificateStoreLocation + { + /// + /// Do not use certificate store + /// + None, + /// + /// Use certificate store for the current user + /// + CurrentUser, + /// + /// User certificate store for the machine + /// + LocalMachine + } } \ No newline at end of file === 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 20:34:41 +0000 @@ -259,12 +259,61 @@ 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 == MySqlCertificateStoreLocation.None) + return certs; + + StoreLocation location = + (Settings.CertificateStoreLocation == MySqlCertificateStoreLocation.CurrentUser) ? + StoreLocation.CurrentUser : StoreLocation.LocalMachine; + + // Check for store-based certificate + 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_tV+n6ufDbh1UqjX1yKaqOA) 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: 2c64657d4fe379734ddd4ad151eab2fa60e1ddbc # timestamp: 2009-10-19 22:34:42 +0200 # source_branch: file:///H:/connector_net/6.1/ # base_revision_id: vvaintroub@stripped\ # u8r6mvnkqa5579mm # # Begin bundle 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 hQkHUXBv0A== --Boundary_(ID_tV+n6ufDbh1UqjX1yKaqOA)--