* Dynamically set the used MYSQL_OPT_* constants for libmysql v8+, to fix the reported SEC_E_ALGORITHM_MISMATCH connection error on SSL-enabled sessions.
* add libmysql-8.4.0-64.dll to installer
* remove deprecated and no longer used mysql_ssl_set() function
This commit is contained in:
Ansgar Becker
2024-05-28 19:33:54 +02:00
parent d383089c3d
commit d549080cbd
5 changed files with 58 additions and 97 deletions

View File

@ -114,6 +114,7 @@ Source: "libmysql64.dll"; DestDir: "{app}"; DestName: "libmysql.dll"; Check: Is6
Source: "libmysql32.dll"; DestDir: "{app}"; DestName: "libmysql.dll"; Check: not Is64BitInstallMode; Flags: ignoreversion Source: "libmysql32.dll"; DestDir: "{app}"; DestName: "libmysql.dll"; Check: not Is64BitInstallMode; Flags: ignoreversion
Source: "libmysql-6.1-64.dll"; DestDir: "{app}"; DestName: "libmysql-6.1.dll"; Check: Is64BitInstallMode; Flags: ignoreversion Source: "libmysql-6.1-64.dll"; DestDir: "{app}"; DestName: "libmysql-6.1.dll"; Check: Is64BitInstallMode; Flags: ignoreversion
Source: "libmysql-6.1-32.dll"; DestDir: "{app}"; DestName: "libmysql-6.1.dll"; Check: not Is64BitInstallMode; Flags: ignoreversion Source: "libmysql-6.1-32.dll"; DestDir: "{app}"; DestName: "libmysql-6.1.dll"; Check: not Is64BitInstallMode; Flags: ignoreversion
Source: "libmysql-8.4.0-64.dll"; DestDir: "{app}"; DestName: "libmysql-8.4.0.dll"; Check: Is64BitInstallMode; Flags: ignoreversion
; PostgreSQL: ; PostgreSQL:
Source: "libpq-10-64.dll"; DestDir: "{app}"; DestName: "libpq-10.dll"; Check: Is64BitInstallMode; Flags: ignoreversion Source: "libpq-10-64.dll"; DestDir: "{app}"; DestName: "libpq-10.dll"; Check: Is64BitInstallMode; Flags: ignoreversion
Source: "libpq-10-32.dll"; DestDir: "{app}"; DestName: "libpq-10.dll"; Check: not Is64BitInstallMode; Flags: ignoreversion Source: "libpq-10-32.dll"; DestDir: "{app}"; DestName: "libpq-10.dll"; Check: not Is64BitInstallMode; Flags: ignoreversion

BIN
out/libmysql-8.4.0-64.dll Normal file

Binary file not shown.

View File

@ -2382,21 +2382,23 @@ begin
// See https://www.heidisql.com/forum.php?t=27158 // See https://www.heidisql.com/forum.php?t=27158
// See https://mariadb.com/kb/en/library/mysql_optionsv/ // See https://mariadb.com/kb/en/library/mysql_optionsv/
// See issue #1768 // See issue #1768
SetOptionResult := FLib.mysql_options(FHandle, Integer(MARIADB_OPT_TLS_VERSION), PAnsiChar('TLSv1,TLSv1.1,TLSv1.2,TLSv1.3')); var TlsVersions := 'TLSv1,TLSv1.1,TLSv1.2,TLSv1.3';
//TlsVersions := 'TLSv1.1';
SetOptionResult := FLib.mysql_options(FHandle, FLib.MARIADB_OPT_TLS_VERSION, PAnsiChar(AnsiString(TlsVersions)));
SetOptionResult := SetOptionResult + SetOptionResult := SetOptionResult +
FLib.mysql_options(FHandle, Integer(MYSQL_OPT_TLS_VERSION), PAnsiChar(AnsiString('TLSv1,TLSv1.1,TLSv1.2,TLSv1.3'))); FLib.mysql_options(FHandle, FLib.MYSQL_OPT_TLS_VERSION, PAnsiChar(AnsiString(TlsVersions)));
if FParameters.SSLPrivateKey <> '' then if FParameters.SSLPrivateKey <> '' then
SetOptionResult := SetOptionResult + SetOptionResult := SetOptionResult +
FLib.mysql_options(FHandle, Integer(MYSQL_OPT_SSL_KEY), PAnsiChar(AnsiString(FParameters.SSLPrivateKey))); FLib.mysql_options(FHandle, FLib.MYSQL_OPT_SSL_KEY, PAnsiChar(AnsiString(FParameters.SSLPrivateKey)));
if FParameters.SSLCertificate <> '' then if FParameters.SSLCertificate <> '' then
SetOptionResult := SetOptionResult + SetOptionResult := SetOptionResult +
FLib.mysql_options(FHandle, Integer(MYSQL_OPT_SSL_CERT), PAnsiChar(AnsiString(FParameters.SSLCertificate))); FLib.mysql_options(FHandle, FLib.MYSQL_OPT_SSL_CERT, PAnsiChar(AnsiString(FParameters.SSLCertificate)));
if FParameters.SSLCACertificate <> '' then if FParameters.SSLCACertificate <> '' then
SetOptionResult := SetOptionResult + SetOptionResult := SetOptionResult +
FLib.mysql_options(FHandle, Integer(MYSQL_OPT_SSL_CA), PAnsiChar(AnsiString(FParameters.SSLCACertificate))); FLib.mysql_options(FHandle, FLib.MYSQL_OPT_SSL_CA, PAnsiChar(AnsiString(FParameters.SSLCACertificate)));
if FParameters.SSLCipher <> '' then if FParameters.SSLCipher <> '' then
SetOptionResult := SetOptionResult + SetOptionResult := SetOptionResult +
FLib.mysql_options(FHandle, Integer(MYSQL_OPT_SSL_CIPHER), PAnsiChar(AnsiString(FParameters.SSLCipher))); FLib.mysql_options(FHandle, FLib.MYSQL_OPT_SSL_CIPHER, PAnsiChar(AnsiString(FParameters.SSLCipher)));
if SetOptionResult = 0 then if SetOptionResult = 0 then
Log(lcInfo, _('SSL parameters successfully set.')) Log(lcInfo, _('SSL parameters successfully set.'))
else else
@ -2448,24 +2450,24 @@ begin
// Point libmysql to the folder with client plugins // Point libmysql to the folder with client plugins
PluginDir := AnsiString(ExtractFilePath(ParamStr(0))+'plugins'); PluginDir := AnsiString(ExtractFilePath(ParamStr(0))+'plugins');
SetOptionResult := FLib.mysql_options(FHandle, Integer(MYSQL_PLUGIN_DIR), PAnsiChar(PluginDir)); SetOptionResult := FLib.mysql_options(FHandle, FLib.MYSQL_PLUGIN_DIR, PAnsiChar(PluginDir));
if SetOptionResult <> 0 then begin if SetOptionResult <> 0 then begin
raise EDbError.Create(f_('Plugin directory %s could not be set.', [PluginDir])); raise EDbError.Create(f_('Plugin directory %s could not be set.', [PluginDir]));
end; end;
// Enable cleartext plugin // Enable cleartext plugin
if Parameters.CleartextPluginEnabled then if Parameters.CleartextPluginEnabled then
FLib.mysql_options(FHandle, Integer(MYSQL_ENABLE_CLEARTEXT_PLUGIN), PAnsiChar('1')); FLib.mysql_options(FHandle, FLib.MYSQL_ENABLE_CLEARTEXT_PLUGIN, PAnsiChar('1'));
// Tell server who we are // Tell server who we are
if Assigned(FLib.mysql_optionsv) then if Assigned(FLib.mysql_optionsv) then
FLib.mysql_optionsv(FHandle, Integer(MYSQL_OPT_CONNECT_ATTR_ADD), 'program_name', APPNAME); FLib.mysql_optionsv(FHandle, FLib.MYSQL_OPT_CONNECT_ATTR_ADD, 'program_name', APPNAME);
// Seems to be still required on some systems, for importing CSV files // Seems to be still required on some systems, for importing CSV files
FLib.mysql_options(FHandle, Integer(MYSQL_OPT_LOCAL_INFILE), PAnsiChar('1')); FLib.mysql_options(FHandle, FLib.MYSQL_OPT_LOCAL_INFILE, PAnsiChar('1'));
// Ensure we have some connection timeout // Ensure we have some connection timeout
FLib.mysql_options(FHandle, Integer(MYSQL_OPT_CONNECT_TIMEOUT), @FParameters.QueryTimeout); FLib.mysql_options(FHandle, FLib.MYSQL_OPT_CONNECT_TIMEOUT, @FParameters.QueryTimeout);
Connected := FLib.mysql_real_connect( Connected := FLib.mysql_real_connect(
FHandle, FHandle,

View File

@ -4,7 +4,7 @@
interface interface
uses uses
System.Classes, dbstructures; System.Classes, System.SysUtils, dbstructures;
const const
@ -259,88 +259,6 @@ type
end; end;
PMYSQL_RES = ^MYSQL_RES; PMYSQL_RES = ^MYSQL_RES;
TMySQLOption = (
MYSQL_OPT_CONNECT_TIMEOUT,
MYSQL_OPT_COMPRESS,
MYSQL_OPT_NAMED_PIPE,
MYSQL_INIT_COMMAND,
MYSQL_READ_DEFAULT_FILE,
MYSQL_READ_DEFAULT_GROUP,
MYSQL_SET_CHARSET_DIR,
MYSQL_SET_CHARSET_NAME,
MYSQL_OPT_LOCAL_INFILE,
MYSQL_OPT_PROTOCOL,
MYSQL_SHARED_MEMORY_BASE_NAME,
MYSQL_OPT_READ_TIMEOUT,
MYSQL_OPT_WRITE_TIMEOUT,
MYSQL_OPT_USE_RESULT,
MYSQL_OPT_USE_REMOTE_CONNECTION,
MYSQL_OPT_USE_EMBEDDED_CONNECTION,
MYSQL_OPT_GUESS_CONNECTION,
MYSQL_SET_CLIENT_IP,
MYSQL_SECURE_AUTH,
MYSQL_REPORT_DATA_TRUNCATION,
MYSQL_OPT_RECONNECT,
MYSQL_OPT_SSL_VERIFY_SERVER_CERT,
MYSQL_PLUGIN_DIR,
MYSQL_DEFAULT_AUTH,
MYSQL_OPT_BIND,
MYSQL_OPT_SSL_KEY,
MYSQL_OPT_SSL_CERT,
MYSQL_OPT_SSL_CA,
MYSQL_OPT_SSL_CAPATH,
MYSQL_OPT_SSL_CIPHER,
MYSQL_OPT_SSL_CRL,
MYSQL_OPT_SSL_CRLPATH,
// Connection attribute options
MYSQL_OPT_CONNECT_ATTR_RESET,
MYSQL_OPT_CONNECT_ATTR_ADD,
MYSQL_OPT_CONNECT_ATTR_DELETE,
MYSQL_SERVER_PUBLIC_KEY,
MYSQL_ENABLE_CLEARTEXT_PLUGIN,
MYSQL_OPT_CAN_HANDLE_EXPIRED_PASSWORDS,
MYSQL_OPT_SSL_ENFORCE,
MYSQL_OPT_MAX_ALLOWED_PACKET,
MYSQL_OPT_NET_BUFFER_LENGTH,
MYSQL_OPT_TLS_VERSION,
// MariaDB specific
MYSQL_PROGRESS_CALLBACK=5999,
MYSQL_OPT_NONBLOCK,
// MariaDB Connector/C specific
MYSQL_DATABASE_DRIVER=7000,
MARIADB_OPT_SSL_FP, // deprecated, use MARIADB_OPT_TLS_PEER_FP instead
MARIADB_OPT_SSL_FP_LIST, // deprecated, use MARIADB_OPT_TLS_PEER_FP_LIST instead
MARIADB_OPT_TLS_PASSPHRASE, // passphrase for encrypted certificates
MARIADB_OPT_TLS_CIPHER_STRENGTH,
MARIADB_OPT_TLS_VERSION,
MARIADB_OPT_TLS_PEER_FP, // single finger print for server certificate verification
MARIADB_OPT_TLS_PEER_FP_LIST, // finger print white list for server certificate verification
MARIADB_OPT_CONNECTION_READ_ONLY,
MYSQL_OPT_CONNECT_ATTRS, // for mysql_get_optionv
MARIADB_OPT_USERDATA,
MARIADB_OPT_CONNECTION_HANDLER,
MARIADB_OPT_PORT,
MARIADB_OPT_UNIXSOCKET,
MARIADB_OPT_PASSWORD,
MARIADB_OPT_HOST,
MARIADB_OPT_USER,
MARIADB_OPT_SCHEMA,
MARIADB_OPT_DEBUG,
MARIADB_OPT_FOUND_ROWS,
MARIADB_OPT_MULTI_RESULTS,
MARIADB_OPT_MULTI_STATEMENTS,
MARIADB_OPT_INTERACTIVE,
MARIADB_OPT_PROXY_HEADER,
MARIADB_OPT_IO_WAIT,
MARIADB_OPT_SKIP_READ_RESPONSE,
MARIADB_OPT_RESTRICTED_AUTH,
MARIADB_OPT_RPL_REGISTER_REPLICA,
MARIADB_OPT_STATUS_CALLBACK,
MARIADB_OPT_SERVER_PLUGINS,
MARIADB_OPT_BULK_UNIT_RESULTS
);
TMySQLLib = class(TDbLib) TMySQLLib = class(TDbLib)
mysql_affected_rows: function(Handle: PMYSQL): Int64; stdcall; mysql_affected_rows: function(Handle: PMYSQL): Int64; stdcall;
mysql_character_set_name: function(Handle: PMYSQL): PAnsiChar; stdcall; mysql_character_set_name: function(Handle: PMYSQL): PAnsiChar; stdcall;
@ -363,7 +281,6 @@ type
mysql_ping: function(Handle: PMYSQL): 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; mysql_real_connect: function(Handle: PMYSQL; const Host, User, Passwd, Db: PAnsiChar; Port: Cardinal; const UnixSocket: PAnsiChar; ClientFlag: Cardinal): PMYSQL; stdcall;
mysql_real_query: function(Handle: PMYSQL; const Query: PAnsiChar; Length: Cardinal): Integer; stdcall; mysql_real_query: function(Handle: PMYSQL; const Query: PAnsiChar; Length: Cardinal): Integer; stdcall;
mysql_ssl_set: function(Handle: PMYSQL; const key, cert, CA, CApath, cipher: PAnsiChar): Integer; stdcall;
mysql_stat: function(Handle: PMYSQL): PAnsiChar; stdcall; mysql_stat: function(Handle: PMYSQL): PAnsiChar; stdcall;
mysql_store_result: function(Handle: PMYSQL): PMYSQL_RES; stdcall; mysql_store_result: function(Handle: PMYSQL): PMYSQL_RES; stdcall;
mysql_thread_id: function(Handle: PMYSQL): Cardinal; stdcall; mysql_thread_id: function(Handle: PMYSQL): Cardinal; stdcall;
@ -374,6 +291,19 @@ type
mysql_warning_count: function(Handle: PMYSQL): Cardinal; stdcall; mysql_warning_count: function(Handle: PMYSQL): Cardinal; stdcall;
protected protected
procedure AssignProcedures; override; procedure AssignProcedures; override;
public
MYSQL_OPT_LOCAL_INFILE,
MYSQL_OPT_CONNECT_TIMEOUT,
MARIADB_OPT_TLS_VERSION,
MYSQL_OPT_TLS_VERSION,
MYSQL_PLUGIN_DIR,
MYSQL_OPT_SSL_KEY,
MYSQL_OPT_SSL_CERT,
MYSQL_OPT_SSL_CA,
MYSQL_OPT_SSL_CIPHER,
MYSQL_OPT_CONNECT_ATTR_ADD,
MYSQL_ENABLE_CLEARTEXT_PLUGIN: Integer;
constructor Create(DllFile, DefaultDll: String); override;
end; end;
var var
MySQLKeywords: TStringList; MySQLKeywords: TStringList;
@ -3142,6 +3072,35 @@ implementation
uses apphelpers; uses apphelpers;
constructor TMySQLLib.Create(DllFile, DefaultDll: String);
begin
inherited;
// Some MYSQL_OPT_* constants were removed in MySQL 8.0, so the offsets differ between libmysql and libmariadb.
MYSQL_OPT_CONNECT_TIMEOUT := 0;
MYSQL_OPT_LOCAL_INFILE := 8;
MARIADB_OPT_TLS_VERSION := 7005;
if String(mysql_get_client_info).StartsWith('8.') then begin
MYSQL_PLUGIN_DIR := 16;
MYSQL_OPT_SSL_KEY := 19;
MYSQL_OPT_SSL_CERT := 20;
MYSQL_OPT_SSL_CA := 21;
MYSQL_OPT_SSL_CIPHER := 23;
MYSQL_OPT_CONNECT_ATTR_ADD := 27;
MYSQL_ENABLE_CLEARTEXT_PLUGIN := 30;
MYSQL_OPT_TLS_VERSION := 34;
end
else begin
MYSQL_PLUGIN_DIR := 22;
MYSQL_OPT_SSL_KEY := 25;
MYSQL_OPT_SSL_CERT := 26;
MYSQL_OPT_SSL_CA := 27;
MYSQL_OPT_SSL_CIPHER := 29;
MYSQL_OPT_CONNECT_ATTR_ADD := 33;
MYSQL_ENABLE_CLEARTEXT_PLUGIN := 36;
MYSQL_OPT_TLS_VERSION := 41;
end;
end;
procedure TMySQLLib.AssignProcedures; procedure TMySQLLib.AssignProcedures;
begin begin
AssignProc(@mysql_affected_rows, 'mysql_affected_rows'); AssignProc(@mysql_affected_rows, 'mysql_affected_rows');
@ -3165,7 +3124,6 @@ begin
AssignProc(@mysql_optionsv, 'mysql_optionsv', False); AssignProc(@mysql_optionsv, 'mysql_optionsv', False);
AssignProc(@mysql_real_connect, 'mysql_real_connect'); AssignProc(@mysql_real_connect, 'mysql_real_connect');
AssignProc(@mysql_real_query, 'mysql_real_query'); AssignProc(@mysql_real_query, 'mysql_real_query');
AssignProc(@mysql_ssl_set, 'mysql_ssl_set');
AssignProc(@mysql_stat, 'mysql_stat'); AssignProc(@mysql_stat, 'mysql_stat');
AssignProc(@mysql_store_result, 'mysql_store_result'); AssignProc(@mysql_store_result, 'mysql_store_result');
AssignProc(@mysql_thread_id, 'mysql_thread_id'); AssignProc(@mysql_thread_id, 'mysql_thread_id');

View File

@ -88,7 +88,7 @@ type
public public
property Handle: HMODULE read FHandle; property Handle: HMODULE read FHandle;
property DllFile: String read FDllFile; property DllFile: String read FDllFile;
constructor Create(DllFile, DefaultDll: String); constructor Create(DllFile, DefaultDll: String); virtual;
destructor Destroy; override; destructor Destroy; override;
end; end;