diff --git a/out/locale/en/LC_MESSAGES/default.po b/out/locale/en/LC_MESSAGES/default.po index 2b5aa560..8042915e 100644 --- a/out/locale/en/LC_MESSAGES/default.po +++ b/out/locale/en/LC_MESSAGES/default.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: HeidiSQL\n" "POT-Creation-Date: 2012-11-05 21:40\n" -"PO-Revision-Date: 2024-06-05 16:41+0200\n" +"PO-Revision-Date: 2024-06-28 15:35+0200\n" "Last-Translator: Ansgar Becker \n" "Language-Team: English (http://www.transifex.com/projects/p/heidisql/language/en/)\n" "Language: en\n" @@ -439,6 +439,21 @@ msgstr "SSL certificate:" msgid "SSL cipher:" msgstr "SSL cipher:" +msgid "Certificate verification" +msgstr "Certificate verification" + +msgid "No verification (insecure)" +msgstr "No verification (insecure)" + +msgid "Verify CA" +msgstr "Verify CA" + +msgid "Verify CA and host name identity" +msgstr "Verify CA and host name identity" + +msgid "You might need to lower the certificate verification in the SSL settings." +msgstr "You might need to lower the certificate verification in the SSL settings." + msgid "Path to key file" msgstr "Path to key file" diff --git a/source/apphelpers.pas b/source/apphelpers.pas index f848bcc7..f4ad26d3 100644 --- a/source/apphelpers.pas +++ b/source/apphelpers.pas @@ -187,7 +187,7 @@ type asUser, asPassword, asCleartextPluginEnabled, asWindowsAuth, asLoginPrompt, asPort, asLibrary, asAllProviders, asSSHtunnelActive, asPlinkExecutable, asSshExecutable, asSSHtunnelHost, asSSHtunnelHostPort, asSSHtunnelPort, asSSHtunnelUser, asSSHtunnelPassword, asSSHtunnelTimeout, asSSHtunnelPrivateKey, asSSLActive, asSSLKey, - asSSLCert, asSSLCA, asSSLCipher, asSSLWarnUnused, asNetType, asCompressed, asLocalTimeZone, asQueryTimeout, asKeepAlive, + asSSLCert, asSSLCA, asSSLCipher, asSSLVerification, asSSLWarnUnused, asNetType, asCompressed, asLocalTimeZone, asQueryTimeout, asKeepAlive, asStartupScriptFilename, asDatabases, asComment, asDatabaseFilter, asTableFilter, asFilterVT, asExportSQLCreateDatabases, asExportSQLCreateTables, asExportSQLDataHow, asExportSQLDataInsertSize, asExportSQLFilenames, asExportZIPFilenames, asExportSQLDirectories, asExportSQLDatabase, asExportSQLServerDatabase, asExportSQLOutput, asExportSQLAddComments, asExportSQLRemoveAutoIncrement, asExportSQLRemoveDefiner, @@ -2539,7 +2539,7 @@ var rx: TRegExpr; ExeName, SessName, Host, Lib, Port, User, Pass, Socket, AllDatabases, SSLPrivateKey, SSLCACertificate, SSLCertificate, SSLCipher: String; - NetType, WindowsAuth, WantSSL, CleartextPluginEnabled: Integer; + NetType, WindowsAuth, WantSSL, CleartextPluginEnabled, SSLVerification: Integer; AbsentFiles: TStringList; function GetParamValue(ShortName, LongName: String): String; @@ -2618,6 +2618,7 @@ begin SSLCACertificate := GetParamValue('sslca', 'sslcacertificate'); SSLCertificate := GetParamValue('sslcert', 'sslcertificate'); SSLCipher := GetParamValue('sslcip', 'sslcipher'); + SSLVerification := StrToIntDef(GetParamValue('sslvrf', 'sslverification'), -1); // Leave out support for startup script, seems reasonable for command line connecting if (Host <> '') or (User <> '') or (Pass <> '') or (Port <> '') or (Socket <> '') or (AllDatabases <> '') then begin @@ -2654,6 +2655,8 @@ begin ConnectionParams.SSLCertificate := SSLCertificate; if SSLCipher <> '' then ConnectionParams.SSLCipher := SSLCipher; + if SSLVerification >= 0 then + ConnectionParams.SSLVerification := SSLVerification; if WindowsAuth in [0,1] then ConnectionParams.WindowsAuth := Boolean(WindowsAuth); @@ -3724,6 +3727,7 @@ begin InitSetting(asSSLCert, 'SSL_Cert', 0, False, '', True); InitSetting(asSSLCA, 'SSL_CA', 0, False, '', True); InitSetting(asSSLCipher, 'SSL_Cipher', 0, False, '', True); + InitSetting(asSSLVerification, 'SSL_Verification', 2, False, '', True); InitSetting(asSSLWarnUnused, 'SSL_WarnUnused', 0, True); InitSetting(asNetType, 'NetType', Integer(ntMySQL_TCPIP), False, '', True); InitSetting(asCompressed, 'Compressed', 0, False, '', True); diff --git a/source/connections.dfm b/source/connections.dfm index e669370f..a3c691f7 100644 --- a/source/connections.dfm +++ b/source/connections.dfm @@ -763,6 +763,13 @@ object connform: Tconnform Height = 14 Caption = 'SSL cipher:' end + object lblSSLVerification: TLabel + Left = 3 + Top = 148 + Width = 131 + Height = 14 + Caption = 'Certificate verification:' + end object chkWantSSL: TCheckBox Left = 190 Top = 13 @@ -776,7 +783,7 @@ object connform: Tconnform object editSSLcipher: TEdit Left = 190 Top = 117 - Width = 320 + Width = 324 Height = 22 Anchors = [akLeft, akTop, akRight] TabOrder = 4 @@ -787,7 +794,7 @@ object connform: Tconnform object editSSLCertificate: TButtonedEdit Left = 190 Top = 90 - Width = 320 + Width = 324 Height = 22 Anchors = [akLeft, akTop, akRight] Images = MainForm.VirtualImageListMain @@ -803,7 +810,7 @@ object connform: Tconnform object editSSLCACertificate: TButtonedEdit Left = 190 Top = 63 - Width = 320 + Width = 324 Height = 22 Anchors = [akLeft, akTop, akRight] Images = MainForm.VirtualImageListMain @@ -819,7 +826,7 @@ object connform: Tconnform object editSSLPrivateKey: TButtonedEdit Left = 190 Top = 36 - Width = 320 + Width = 324 Height = 22 Anchors = [akLeft, akTop, akRight] Images = MainForm.VirtualImageListMain @@ -832,6 +839,20 @@ object connform: Tconnform OnExit = editTrim OnRightButtonClick = PickFile end + object comboSSLVerification: TComboBox + Left = 190 + Top = 145 + Width = 324 + Height = 22 + Style = csDropDownList + Anchors = [akLeft, akTop, akRight] + TabOrder = 5 + OnChange = Modification + Items.Strings = ( + 'No verification (insecure)' + 'Verify CA' + 'Verify CA and host name identity') + end end object tabStatistics: TTabSheet Caption = 'Statistics' diff --git a/source/connections.pas b/source/connections.pas index 91abfe11..6286cacb 100644 --- a/source/connections.pas +++ b/source/connections.pas @@ -138,6 +138,8 @@ type timerEditFilterDelay: TTimer; comboSSHExe: TComboBox; chkSSHActive: TCheckBox; + comboSSLVerification: TComboBox; + lblSSLVerification: TLabel; procedure FormCreate(Sender: TObject); procedure btnOpenClick(Sender: TObject); procedure FormShow(Sender: TObject); @@ -510,6 +512,7 @@ begin Sess.SSLCertificate := editSSLCertificate.Text; Sess.SSLCACertificate := editSSLCACertificate.Text; Sess.SSLCipher := editSSLCipher.Text; + Sess.SSLVerification := comboSSLVerification.ItemIndex; Sess.IgnoreDatabasePattern := editIgnoreDatabasePattern.Text; Sess.LogFileDdl := chkLogFileDdl.Checked; Sess.LogFileDml := chkLogFileDml.Checked; @@ -733,6 +736,7 @@ begin Result.SSLCertificate := editSSLCertificate.Text; Result.SSLCACertificate := editSSLCACertificate.Text; Result.SSLCipher := editSSLCipher.Text; + Result.SSLVerification := comboSSLVerification.ItemIndex; Result.StartupScriptFilename := editStartupScript.Text; Result.Compressed := chkCompressed.Checked; Result.QueryTimeout := updownQueryTimeout.Position; @@ -1033,6 +1037,7 @@ begin editSSLCertificate.Text := Sess.SSLCertificate; editSSLCACertificate.Text := Sess.SSLCACertificate; editSSLCipher.Text := Sess.SSLCipher; + comboSSLVerification.ItemIndex := Sess.SSLVerification; editIgnoreDatabasePattern.Text := Sess.IgnoreDatabasePattern; chkLogFileDdl.Checked := Sess.LogFileDdl; chkLogFileDml.Checked := Sess.LogFileDml; @@ -1439,6 +1444,7 @@ begin or (Sess.SSLCertificate <> editSSLCertificate.Text) or (Sess.SSLCACertificate <> editSSLCACertificate.Text) or (Sess.SSLCipher <> editSSLCipher.Text) + or (Sess.SSLVerification <> comboSSLVerification.ItemIndex) or (Sess.IgnoreDatabasePattern <> editIgnoreDatabasePattern.Text) or (Sess.LogFileDdl <> chkLogFileDdl.Checked) or (Sess.LogFileDml <> chkLogFileDml.Checked) @@ -1575,6 +1581,8 @@ begin editSSLCertificate.Enabled := Params.WantSSL; lblSSLcipher.Enabled := Params.WantSSL; editSSLcipher.Enabled := Params.WantSSL; + lblSSLVerification.Enabled := Params.WantSSL; + comboSSLVerification.Enabled := Params.WantSSL; lblQueryTimeout.Enabled := True; editQueryTimeout.Enabled := lblQueryTimeout.Enabled; updownQueryTimeout.Enabled := lblQueryTimeout.Enabled; diff --git a/source/dbconnection.pas b/source/dbconnection.pas index 568f2445..68c8bd16 100644 --- a/source/dbconnection.pas +++ b/source/dbconnection.pas @@ -314,7 +314,7 @@ type FSessionPath, FSSLPrivateKey, FSSLCertificate, FSSLCACertificate, FSSLCipher, FServerVersion, FSSHHost, FSSHUser, FSSHPassword, FSSHExe, FSSHPrivateKey, FIgnoreDatabasePattern: String; - FPort, FSSHPort, FSSHLocalPort, FSSHTimeout, FCounter, FQueryTimeout, FKeepAlive: Integer; + FPort, FSSHPort, FSSHLocalPort, FSSHTimeout, FCounter, FQueryTimeout, FKeepAlive, FSSLVerification: Integer; FSSHActive, FLoginPrompt, FCompressed, FLocalTimeZone, FFullTableStatus, FWindowsAuth, FWantSSL, FIsFolder, FCleartextPluginEnabled: Boolean; FSessionColor: TColor; @@ -403,6 +403,7 @@ type property SSLCertificate: String read FSSLCertificate write FSSLCertificate; property SSLCACertificate: String read FSSLCACertificate write FSSLCACertificate; property SSLCipher: String read FSSLCipher write FSSLCipher; + property SSLVerification: Integer read FSSLVerification write FSSLVerification; property IgnoreDatabasePattern: String read FIgnoreDatabasePattern write FIgnoreDatabasePattern; property LogFileDdl: Boolean read FLogFileDdl write FLogFileDdl; property LogFileDml: Boolean read FLogFileDml write FLogFileDml; @@ -1421,6 +1422,7 @@ begin FSSLCertificate := AppSettings.GetDefaultString(asSSLCert); FSSLCACertificate := AppSettings.GetDefaultString(asSSLCA); FSSLCipher := AppSettings.GetDefaultString(asSSLCipher); + FSSLVerification := AppSettings.GetDefaultInt(asSSLVerification); FStartupScriptFilename := AppSettings.GetDefaultString(asStartupScriptFilename); FQueryTimeout := AppSettings.GetDefaultInt(asQueryTimeout); FKeepAlive := AppSettings.GetDefaultInt(asKeepAlive); @@ -1495,6 +1497,7 @@ begin FSSLCertificate := AppSettings.ReadString(asSSLCert); FSSLCACertificate := AppSettings.ReadString(asSSLCA); FSSLCipher := AppSettings.ReadString(asSSLCipher); + FSSLVerification := AppSettings.ReadInt(asSSLVerification); FStartupScriptFilename := AppSettings.ReadString(asStartupScriptFilename); FQueryTimeout := AppSettings.ReadInt(asQueryTimeout); FKeepAlive := AppSettings.ReadInt(asKeepAlive); @@ -1564,6 +1567,7 @@ begin AppSettings.WriteString(asSSLCert, FSSLCertificate); AppSettings.WriteString(asSSLCA, FSSLCACertificate); AppSettings.WriteString(asSSLCipher, FSSLCipher); + AppSettings.WriteInt(asSSLVerification, FSSLVerification); AppSettings.WriteString(asIgnoreDatabasePattern, FIgnoreDatabasePattern); AppSettings.WriteBool(asLogFileDdl, FLogFileDdl); AppSettings.WriteBool(asLogFileDml, FLogFileDml); @@ -2406,7 +2410,7 @@ end; procedure TMySQLConnection.SetActive( Value: Boolean ); var Connected: PMYSQL; - ClientFlags, FinalPort: Integer; + ClientFlags, FinalPort, SSLoption: Integer; Error, StatusName: String; FinalHost, FinalSocket, FinalUsername, FinalPassword: String; ErrorHint: String; @@ -2450,6 +2454,22 @@ begin if FParameters.SSLCipher <> '' then SetOptionResult := SetOptionResult + FLib.mysql_options(FHandle, FLib.MYSQL_OPT_SSL_CIPHER, PAnsiChar(AnsiString(FParameters.SSLCipher))); + if FParameters.SSLVerification in [1,2] then begin + // MySQL and MariaDB have different options for this + if FLib.MYSQL_OPT_SSL_MODE > TMySQLLib.INVALID_OPT then begin + if FParameters.SSLVerification = 1 then + SSLoption := FLib.SSL_MODE_VERIFY_CA + else + SSLoption := FLib.SSL_MODE_VERIFY_IDENTITY; + SetOptionResult := SetOptionResult + + FLib.mysql_options(FHandle, FLib.MYSQL_OPT_SSL_MODE, @SSLoption); + end + else begin + SSLoption := 1; + SetOptionResult := SetOptionResult + + FLib.mysql_options(FHandle, FLib.MYSQL_OPT_SSL_VERIFY_SERVER_CERT, @SSLoption); + end; + end; if SetOptionResult = 0 then Log(lcInfo, _('SSL parameters successfully set.')) else @@ -2540,6 +2560,9 @@ begin ['libmysql'] ); end + else if Error.Contains('certificate verif') then begin + ErrorHint := _('You might need to lower the certificate verification in the SSL settings.'); + end else if (FParameters.DefaultLibrary <> '') and (FParameters.LibraryOrProvider <> FParameters.DefaultLibrary) then begin ErrorHint := f_('You could try the default library %s in your session settings. (Current: %s)', [FParameters.DefaultLibrary, FParameters.LibraryOrProvider] diff --git a/source/dbstructures.mysql.pas b/source/dbstructures.mysql.pas index 8ca5457e..b46f7c12 100644 --- a/source/dbstructures.mysql.pas +++ b/source/dbstructures.mysql.pas @@ -290,6 +290,8 @@ type mysql_thread_init: function: Byte; stdcall; mysql_thread_end: procedure; stdcall; mysql_warning_count: function(Handle: PMYSQL): Cardinal; stdcall; + const + INVALID_OPT = -1; protected procedure AssignProcedures; override; public @@ -303,7 +305,11 @@ type MYSQL_OPT_SSL_CA, MYSQL_OPT_SSL_CIPHER, MYSQL_OPT_CONNECT_ATTR_ADD, - MYSQL_ENABLE_CLEARTEXT_PLUGIN: Integer; + MYSQL_ENABLE_CLEARTEXT_PLUGIN, + MYSQL_OPT_SSL_MODE, + MYSQL_OPT_SSL_VERIFY_SERVER_CERT: Integer; + SSL_MODE_VERIFY_CA, + SSL_MODE_VERIFY_IDENTITY: Integer; constructor Create(DllFile, DefaultDll: String); override; end; var @@ -3113,6 +3119,10 @@ begin MYSQL_OPT_CONNECT_TIMEOUT := 0; MYSQL_OPT_LOCAL_INFILE := 8; MARIADB_OPT_TLS_VERSION := 7005; + MYSQL_OPT_SSL_MODE := INVALID_OPT; + MYSQL_OPT_SSL_VERIFY_SERVER_CERT := INVALID_OPT; + SSL_MODE_VERIFY_CA := 4; + SSL_MODE_VERIFY_IDENTITY := 5; if String(mysql_get_client_info).StartsWith('8.') then begin MYSQL_PLUGIN_DIR := 16; MYSQL_OPT_SSL_KEY := 19; @@ -3122,8 +3132,10 @@ begin MYSQL_OPT_CONNECT_ATTR_ADD := 27; MYSQL_ENABLE_CLEARTEXT_PLUGIN := 30; MYSQL_OPT_TLS_VERSION := 34; + MYSQL_OPT_SSL_MODE := 35; end else begin + MYSQL_OPT_SSL_VERIFY_SERVER_CERT := 15; MYSQL_PLUGIN_DIR := 22; MYSQL_OPT_SSL_KEY := 25; MYSQL_OPT_SSL_CERT := 26;