From 09edb5448ab6f3b35bb90493b44e7bb7f5e8489c Mon Sep 17 00:00:00 2001 From: Ansgar Becker Date: Sun, 16 Mar 2025 13:40:52 +0100 Subject: [PATCH] Issue #1986: do not set CLIENT_SSL flag with libmariadb, which seems to cause a "bad handshake" in mysql_real_connect() --- source/dbconnection.pas | 42 ++++++++++++++++++----------------- source/dbstructures.mysql.pas | 15 +++++++++---- 2 files changed, 33 insertions(+), 24 deletions(-) diff --git a/source/dbconnection.pas b/source/dbconnection.pas index 9d8e2883..254a949d 100644 --- a/source/dbconnection.pas +++ b/source/dbconnection.pas @@ -663,7 +663,7 @@ type FLastRawResults: TMySQLRawResults; FStatementNum: Cardinal; procedure SetActive(Value: Boolean); override; - procedure SetOption(Option: Integer; Arg: PAnsiChar); + procedure SetOption(Option: Integer; Arg: Pointer); procedure DoBeforeConnect; override; procedure DoAfterConnect; override; function GetThreadId: Int64; override; @@ -2434,7 +2434,7 @@ procedure TMySQLConnection.SetActive( Value: Boolean ); var Connected: PMYSQL; ClientFlags, FinalPort, SSLoption: Integer; - VerifyServerCert: Byte; + VerifyServerCert: Integer; Error, StatusName: String; FinalHost, FinalSocket, FinalUsername, FinalPassword: String; ErrorHint: String; @@ -2473,7 +2473,7 @@ begin SetOption(FLib.MYSQL_OPT_SSL_CA, PAnsiChar(AnsiString(FParameters.SSLCACertificate))); if FParameters.SSLCipher <> '' then SetOption(FLib.MYSQL_OPT_SSL_CIPHER, PAnsiChar(AnsiString(FParameters.SSLCipher))); - if FLib.MYSQL_OPT_SSL_MODE <> TMySQLLib.INVALID_OPT then begin + if not FLib.IsLibMariadb then begin // MySQL Log(lcInfo, 'SSL parameters for MySQL'); case FParameters.SSLVerification of @@ -2539,7 +2539,7 @@ begin or CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA; if Parameters.Compressed then ClientFlags := ClientFlags or CLIENT_COMPRESS; - if Parameters.WantSSL then + if Parameters.WantSSL and (not FLib.IsLibMariadb) then ClientFlags := ClientFlags or CLIENT_SSL; // Point libmysql to the folder with client plugins @@ -3206,7 +3206,7 @@ begin end; -procedure TMySQLConnection.SetOption(Option: Integer; Arg: PAnsiChar); +procedure TMySQLConnection.SetOption(Option: Integer; Arg: Pointer); var SetOptionResult: Integer; RttiContext: TRttiContext; @@ -3215,23 +3215,25 @@ var FieldName: String; begin // Set one of the MYSQL_* option and log a warning if that failed - SetOptionResult := FLib.mysql_options(FHandle, Option, Arg); - if SetOptionResult <> 0 then begin - FieldName := Option.ToString; - // Attempt to find readable name of option constant - RttiContext := TRttiContext.Create; - LibType := RttiContext.GetType(TypeInfo(TMySQLLib)); - for LibField in LibType.GetFields do begin - // Skip assigned procedures - if LibField.FieldType = nil then - Continue; - if LibField.DataType.TypeKind = tkInteger then begin - if LibField.GetValue(FLib).AsInteger = Option then begin - FieldName := LibField.Name; - end; + FieldName := Option.ToString; + // Attempt to find readable name of option constant + RttiContext := TRttiContext.Create; + LibType := RttiContext.GetType(TypeInfo(TMySQLLib)); + for LibField in LibType.GetFields do begin + // Skip assigned procedures + if LibField.FieldType = nil then + Continue; + if LibField.DataType.TypeKind = tkInteger then begin + if LibField.GetValue(FLib).AsInteger = Option then begin + FieldName := LibField.Name; end; end; - RttiContext.Free; + end; + RttiContext.Free; + + Log(lcDebug, Format('Calling mysql_options(%s, ...)', [FieldName])); + SetOptionResult := FLib.mysql_options(FHandle, Option, Arg); + if SetOptionResult <> 0 then begin Log(lcError, _(SLogPrefixWarning) + ': mysql_options(' + FieldName + ', ...) failed!'); end; end; diff --git a/source/dbstructures.mysql.pas b/source/dbstructures.mysql.pas index 615ed95d..84cb9067 100644 --- a/source/dbstructures.mysql.pas +++ b/source/dbstructures.mysql.pas @@ -277,7 +277,7 @@ type mysql_info: function(Handle: PMYSQL): PAnsiChar; stdcall; mysql_num_fields: function(Result: PMYSQL_RES): Integer; stdcall; mysql_num_rows: function(Result: PMYSQL_RES): Int64; stdcall; - mysql_options: function(Handle: PMYSQL; Option: Integer; arg: PAnsiChar): Integer; stdcall; + mysql_options: function(Handle: PMYSQL; Option: Integer; arg: Pointer): Integer; stdcall; mysql_optionsv: function(Handle: PMYSQL; Option: Integer; arg, val: PAnsiChar): Integer; stdcall; mysql_ping: function(Handle: PMYSQL): Integer; stdcall; mysql_real_connect: function(Handle: PMYSQL; const Host, User, Passwd, Db: PAnsiChar; Port: Cardinal; const UnixSocket: PAnsiChar; ClientFlag: Cardinal): PMYSQL; stdcall; @@ -292,8 +292,8 @@ type mysql_warning_count: function(Handle: PMYSQL): Cardinal; stdcall; const INVALID_OPT = -1; - MYBOOL_FALSE: Byte = 0; - MYBOOL_TRUE: Byte = 1; + MYBOOL_FALSE: Integer = 0; + MYBOOL_TRUE: Integer = 1; protected procedure AssignProcedures; override; public @@ -316,6 +316,7 @@ type SSL_MODE_VERIFY_CA, SSL_MODE_VERIFY_IDENTITY: Integer; constructor Create(DllFile, DefaultDll: String); override; + function IsLibMariadb: Boolean; end; var MySQLKeywords: TStringList; @@ -3154,7 +3155,7 @@ begin SSL_MODE_REQUIRED := 3; SSL_MODE_VERIFY_CA := 4; SSL_MODE_VERIFY_IDENTITY := 5; - if ExtractFileName(FDllFile).StartsWith('libmariadb', True) then begin + if IsLibMariadb then begin // Differences in libmariadb MYSQL_OPT_SSL_VERIFY_SERVER_CERT := 21; MARIADB_OPT_TLS_VERSION := 7005; @@ -3173,6 +3174,12 @@ begin end; end; +function TMySQLLib.IsLibMariadb: Boolean; +begin + // libmariadb used (not libmysql) ? + Result := ExtractFileName(FDllFile).StartsWith('libmariadb', True); +end; + procedure TMySQLLib.AssignProcedures; begin AssignProc(@mysql_affected_rows, 'mysql_affected_rows');