* 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: "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-8.4.0-64.dll"; DestDir: "{app}"; DestName: "libmysql-8.4.0.dll"; Check: Is64BitInstallMode; Flags: ignoreversion
; PostgreSQL:
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

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://mariadb.com/kb/en/library/mysql_optionsv/
// 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 +
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
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
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
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
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
Log(lcInfo, _('SSL parameters successfully set.'))
else
@ -2448,24 +2450,24 @@ begin
// Point libmysql to the folder with client 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
raise EDbError.Create(f_('Plugin directory %s could not be set.', [PluginDir]));
end;
// Enable cleartext plugin
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
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
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
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(
FHandle,

View File

@ -4,7 +4,7 @@
interface
uses
System.Classes, dbstructures;
System.Classes, System.SysUtils, dbstructures;
const
@ -259,88 +259,6 @@ type
end;
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)
mysql_affected_rows: function(Handle: PMYSQL): Int64; stdcall;
mysql_character_set_name: function(Handle: PMYSQL): PAnsiChar; stdcall;
@ -363,7 +281,6 @@ type
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_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_store_result: function(Handle: PMYSQL): PMYSQL_RES; stdcall;
mysql_thread_id: function(Handle: PMYSQL): Cardinal; stdcall;
@ -374,6 +291,19 @@ type
mysql_warning_count: function(Handle: PMYSQL): Cardinal; stdcall;
protected
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;
var
MySQLKeywords: TStringList;
@ -3142,6 +3072,35 @@ implementation
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;
begin
AssignProc(@mysql_affected_rows, 'mysql_affected_rows');
@ -3165,7 +3124,6 @@ begin
AssignProc(@mysql_optionsv, 'mysql_optionsv', False);
AssignProc(@mysql_real_connect, 'mysql_real_connect');
AssignProc(@mysql_real_query, 'mysql_real_query');
AssignProc(@mysql_ssl_set, 'mysql_ssl_set');
AssignProc(@mysql_stat, 'mysql_stat');
AssignProc(@mysql_store_result, 'mysql_store_result');
AssignProc(@mysql_thread_id, 'mysql_thread_id');

View File

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