util/installer.h (380 lines of code) (raw):
// Modifications Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
//
// Copyright (c) 2007, 2024, Oracle and/or its affiliates.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License, version 2.0, as
// published by the Free Software Foundation.
//
// This program is designed to work with certain software (including
// but not limited to OpenSSL) that is licensed under separate terms, as
// designated in a particular file or component or in included license
// documentation. The authors of MySQL hereby grant you an additional
// permission to link the program and your derivative works with the
// separately licensed software that they have either included with
// the program or referenced in the documentation.
//
// Without limiting anything contained in the foregoing, this file,
// which is part of Connector/ODBC, is also subject to the
// Universal FOSS Exception, version 1.0, a copy of which can be found at
// https://oss.oracle.com/licenses/universal-foss-exception.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU General Public License, version 2.0, for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
/*
* Function prototypes and structures for installer-wrapper functionality.
*/
#ifndef _INSTALLER_H
#define _INSTALLER_H
#include "../MYODBC_CONF.h"
#include "../MYODBC_ODBC.h"
#include <map>
#include <vector>
#include <string>
#define UNDEFINED_PORT -1
/* the different modes used when calling MYODBCSetupDataSourceConfig */
#define CONFIG_ADD 1
#define CONFIG_EDIT 2
#define CONFIG_VIEW 3
#define CONFIG_DRIVER_CONNECT 4
UWORD config_get();
UWORD config_set(UWORD mode);
#ifdef __cplusplus
extern "C" {
#endif
// Some forward declarations to avoid including stringutil.h
void sqlwcharfromul(SQLWCHAR *wstr, unsigned long v);
unsigned long sqlwchartoul(const SQLWCHAR *wstr);
#ifdef __cplusplus
}
#endif
using SQLWSTRING = std::basic_string<SQLWCHAR, std::char_traits<SQLWCHAR>,
std::allocator<SQLWCHAR>>;
#ifdef BOOL
// Prevent error in enum opt_type
#undef BOOL
typedef int BOOL;
#endif // BOOL
class optionBase {
public:
enum class opt_type { STRING, INT, BOOL };
protected:
// Flag that the value is set
bool m_is_set = false;
// Flag that the value is set to default.
// Used when writing options to INI. Default values are omitted.
bool m_is_default = false;
opt_type m_type;
const char *err_msg_not_set = "Option is used without being set";
public:
optionBase() {}
optionBase(opt_type t) : m_type(t) {}
bool is_set() { return m_is_set; }
bool is_default() { return m_is_default; }
opt_type get_type() { return m_type; }
virtual operator SQLWSTRING() const = 0;
virtual const optionBase &operator=(const SQLWSTRING &val) {
m_is_set = true;
m_is_default = false;
return *this;
};
};
template<typename T>
class optionVal : public optionBase {
T m_val;
public:
constexpr optionVal() {
m_type = std::is_same<T, int>::value ? opt_type::INT : opt_type::BOOL;
m_val = (T)0;
}
virtual operator SQLWSTRING() const {
SQLWCHAR numbuf[64];
if (!m_is_set)
throw err_msg_not_set;
sqlwcharfromul(numbuf, (unsigned long)m_val);
return SQLWSTRING(numbuf);
}
virtual operator T() const {
if (m_is_set)
return m_val;
throw err_msg_not_set;
}
const optionBase &operator=(const T &val) {
m_val = val;
m_is_set = true;
m_is_default = false;
return *this;
}
virtual const optionBase &operator=(const SQLWSTRING &val) {
m_val = (T)sqlwchartoul(val.c_str());
return optionBase::operator=(val);
}
void set_default(T val) {
m_val = val;
m_is_set = true;
m_is_default = true;
}
};
using optionBool = optionVal<bool>;
using optionInt = optionVal<int>;
class optionStr : public optionBase {
const char *err_msg_null = "Option value is nullptr";
SQLWSTRING m_wstr;
std::string m_str;
bool m_is_null = false;
void set(const SQLWSTRING &val, bool is_default);
void set(const std::string &val, bool is_default);
const SQLCHAR *get() const {
if (m_is_set)
return (const SQLCHAR *)(m_is_null ? nullptr : m_str.c_str());
throw err_msg_not_set;
}
const SQLWCHAR *getw() const {
if (m_is_set)
return (const SQLWCHAR *)(m_is_null ? nullptr : m_wstr.c_str());
throw err_msg_not_set;
}
virtual void set_null() {
m_is_set = true;
m_is_null = true;
m_is_default = false;
m_wstr.clear();
m_str.clear();
}
public:
optionStr() : optionBase(opt_type::STRING) { }
void set_default(std::nullptr_t) {
set_null();
m_is_default = true;
}
void set_default(const SQLWCHAR *val) {
if (val)
set(val, true);
else
set_default(nullptr);
}
void set_default(const SQLCHAR *val) {
if (val)
set((const char*)val, true);
else
set_default(nullptr);
}
virtual const optionBase& operator=(const SQLWSTRING &val);
const optionBase& operator=(const SQLWCHAR *val);
// Assigning nullptr is equivalent to clearing the option
const optionStr &operator=(std::nullptr_t) { set_null(); return *this; }
const optionStr &operator=(const std::string &val);
operator const SQLCHAR *() const { return get(); }
operator SQLCHAR *() const { return (SQLCHAR *)get(); }
operator const char *() const { return (const char*)get(); }
operator const SQLWCHAR *() const { return getw(); }
virtual operator bool() const { return (m_is_set && !m_is_null && !m_wstr.empty()); }
virtual operator SQLWSTRING() const {
if (m_is_null)
throw err_msg_null;
return m_wstr;
}
virtual operator const SQLWSTRING&() const {
if (m_is_null)
throw err_msg_null;
return m_wstr;
}
void set_remove_brackets(const SQLWCHAR *val_str, SQLINTEGER len);
};
#define DECLARE_OPTIONS(X) optionStr X;
#define DRIVER_OPTIONS_LIST(X) \
X(name) X(lib) X(setup_lib)
class Driver {
public:
DRIVER_OPTIONS_LIST(DECLARE_OPTIONS)
/*
* Lookup a driver given only the filename of the driver. This is used:
*
* 1. When prompting for additional DSN info upon connect when the
* driver uses an external setup library.
*
* 2. When testing a connection when adding/editing a DSN.
*/
int lookup_name();
/*
* Lookup a driver in the system. The driver name is read from the given
* object. If greater-than zero is returned, additional information
* can be obtained from SQLInstallerError(). A less-than zero return code
* indicates that the driver could not be found.
*/
int lookup();
/*
* Read the semi-colon delimited key-value pairs the attributes
* necessary to popular the driver object.
*/
int from_kvpair_semicolon(const SQLWCHAR *attrs);
/*
* Write the attributes of the driver object into key-value pairs
* separated by single NULL chars.
*/
int to_kvpair_null(SQLWCHAR *attrs, size_t attrslen);
Driver();
~Driver();
};
/* SQL_MAX_OPTION_STRING_LENGTH = 256, should be ok */
#define ODBCDRIVER_STRLEN SQL_MAX_OPTION_STRING_LENGTH
#define ODBCDATASOURCE_STRLEN SQL_MAX_OPTION_STRING_LENGTH
// Failover default settings
#define TOPOLOGY_REFRESH_RATE_MS 30000
#define FAILOVER_TOPOLOGY_REFRESH_RATE_MS 5000
#define FAILOVER_TIMEOUT_MS 60000
#define FAILOVER_READER_CONNECT_TIMEOUT_MS 30000
#define FAILOVER_WRITER_RECONNECT_INTERVAL_MS 5000
// Monitoring default settings
#define FAILURE_DETECTION_TIME_MS 30000
#define FAILURE_DETECTION_INTERVAL_MS 5000
#define DEFAULT_FAILURE_DETECTION_COUNT 3
#define MONITOR_DISPOSAL_TIME_MS 60000
#define FAILURE_DETECTION_TIMEOUT_SECS 5
// Default timeout settings
#define DEFAULT_CONNECT_TIMEOUT_SECS 30
#define DEFAULT_NETWORK_TIMEOUT_SECS 30
unsigned int get_connect_timeout(unsigned int seconds);
unsigned int get_network_timeout(unsigned int seconds);
#if MFA_ENABLED
#define MFA_OPTS(X) X(PWD1) X(PWD2) X(PWD3)
#else
#define MFA_OPTS(X)
#endif
#define AWS_AUTH_STR_OPTIONS_LIST(X) \
X(AUTH_MODE) \
X(AUTH_REGION) \
X(AUTH_HOST) \
X(AUTH_SECRET_ID)
#define AWS_AUTH_INT_OPTIONS_LIST(X) \
X(AUTH_PORT) \
X(AUTH_EXPIRATION)
#define FED_AUTH_STR_OPTIONS_LIST(X) \
X(FED_AUTH_MODE) \
X(IDP_USERNAME) \
X(IDP_PASSWORD) \
X(IDP_ENDPOINT) \
X(IAM_ROLE_ARN) \
X(IAM_IDP_ARN) \
X(APP_ID) \
X(FED_AUTH_HOST) \
X(FED_AUTH_REGION)
#define FED_AUTH_INT_OPTIONS_LIST(X) \
X(IDP_PORT) \
X(CLIENT_SOCKET_TIMEOUT) \
X(CLIENT_CONNECT_TIMEOUT) \
X(FED_AUTH_PORT) \
X(FED_AUTH_EXPIRATION)
#define FED_AUTH_BOOL_OPTIONS_LIST(X) \
X(ENABLE_SSL)
#define FAILOVER_BOOL_OPTIONS_LIST(X) \
X(ENABLE_CLUSTER_FAILOVER) \
X(GATHER_PERF_METRICS) \
X(GATHER_PERF_METRICS_PER_INSTANCE) \
#define FAILOVER_STR_OPTIONS_LIST(X) \
X(HOST_PATTERN) \
X(CLUSTER_ID) \
X(FAILOVER_MODE)
#define FAILOVER_INT_OPTIONS_LIST(X) \
X(TOPOLOGY_REFRESH_RATE) \
X(FAILOVER_TIMEOUT) \
X(FAILOVER_TOPOLOGY_REFRESH_RATE) \
X(FAILOVER_WRITER_RECONNECT_INTERVAL) \
X(FAILOVER_READER_CONNECT_TIMEOUT) \
X(CONNECT_TIMEOUT) \
X(NETWORK_TIMEOUT)
#define MONITORING_BOOL_OPTIONS_LIST(X) X(ENABLE_FAILURE_DETECTION)
#define MONITORING_INT_OPTIONS_LIST(X) \
X(FAILURE_DETECTION_TIME) \
X(FAILURE_DETECTION_INTERVAL) \
X(FAILURE_DETECTION_COUNT) \
X(FAILURE_DETECTION_TIMEOUT) \
X(MONITOR_DISPOSAL_TIME)
#define CUSTOM_ENDPOINT_BOOL_OPTIONS_LIST(X) X(WAIT_FOR_CUSTOM_ENDPOINT_INFO) \
X(ENABLE_CUSTOM_ENDPOINT_MONITORING)
#define CUSTOM_ENDPOINT_INT_OPTIONS_LIST(X) \
X(CUSTOM_ENDPOINT_INFO_REFRESH_RATE_MS) \
X(WAIT_FOR_CUSTOM_ENDPOINT_INFO_TIMEOUT_MS) \
X(CUSTOM_ENDPOINT_MONITOR_EXPIRATION_MS)
#define CUSTOM_ENDPOINT_STR_OPTIONS_LIST(X) X(CUSTOM_ENDPOINT_REGION)
#define STR_OPTIONS_LIST(X) \
X(DSN) \
X(DRIVER) \
X(DESCRIPTION) \
X(SERVER) \
X(UID) \
X(PWD) \
MFA_OPTS(X) X(DATABASE) X(SOCKET) X(INITSTMT) X(CHARSET) X(SSL_KEY) X(SSL_CERT) X(SSL_CA) X(SSL_CAPATH) \
X(SSL_CIPHER) X(SSL_MODE) X(RSAKEY) X(SAVEFILE) X(PLUGIN_DIR) X(DEFAULT_AUTH) X(LOAD_DATA_LOCAL_DIR) \
X(OCI_CONFIG_FILE) X(OCI_CONFIG_PROFILE) X(AUTHENTICATION_KERBEROS_MODE) X(TLS_VERSIONS) X(SSL_CRL) \
X(SSL_CRLPATH) X(SSLVERIFY) X(OPENTELEMETRY) AWS_AUTH_STR_OPTIONS_LIST(X) FAILOVER_STR_OPTIONS_LIST(X) \
CUSTOM_ENDPOINT_STR_OPTIONS_LIST(X) FED_AUTH_STR_OPTIONS_LIST(X)
#define INT_OPTIONS_LIST(X) \
X(PORT) \
X(READTIMEOUT) \
X(WRITETIMEOUT) \
X(CLIENT_INTERACTIVE) \
X(PREFETCH) FAILOVER_INT_OPTIONS_LIST(X) AWS_AUTH_INT_OPTIONS_LIST(X) MONITORING_INT_OPTIONS_LIST(X) \
CUSTOM_ENDPOINT_INT_OPTIONS_LIST(X) FED_AUTH_INT_OPTIONS_LIST(X)
// TODO: remove AUTO_RECONNECT when special handling (warning)
// is not needed anymore.
#define BOOL_OPTIONS_LIST(X) \
X(FOUND_ROWS) \
X(BIG_PACKETS) \
X(COMPRESSED_PROTO) \
X(NO_BIGINT) \
X(SAFE) \
X(AUTO_RECONNECT) \
X(AUTO_IS_NULL) X(NO_BINARY_RESULT) X(CAN_HANDLE_EXP_PWD) X(ENABLE_CLEARTEXT_PLUGIN) X(GET_SERVER_PUBLIC_KEY) \
X(NO_PROMPT) X(DYNAMIC_CURSOR) X(NO_DEFAULT_CURSOR) X(NO_LOCALE) X(PAD_SPACE) X(NO_CACHE) X(FULL_COLUMN_NAMES) \
X(IGNORE_SPACE) X(NAMED_PIPE) X(NO_CATALOG) X(NO_SCHEMA) X(USE_MYCNF) X(NO_TRANSACTIONS) X(FORWARD_CURSOR) \
X(MULTI_STATEMENTS) X(COLUMN_SIZE_S32) X(MIN_DATE_TO_ZERO) X(ZERO_DATE_TO_MIN) X(DFLT_BIGINT_BIND_STR) \
X(LOG_QUERY) X(NO_SSPS) X(NO_TLS_1_2) X(NO_TLS_1_3) X(NO_DATE_OVERFLOW) X(ENABLE_LOCAL_INFILE) \
X(ENABLE_DNS_SRV) X(MULTI_HOST) FAILOVER_BOOL_OPTIONS_LIST(X) MONITORING_BOOL_OPTIONS_LIST(X) \
CUSTOM_ENDPOINT_BOOL_OPTIONS_LIST(X) FED_AUTH_BOOL_OPTIONS_LIST(X)
#define FULL_OPTIONS_LIST(X) \
STR_OPTIONS_LIST(X) INT_OPTIONS_LIST(X) BOOL_OPTIONS_LIST(X)
// List of options that are represented as bits in numeric OPTION value
#define BIT_OPTIONS_LIST(X) \
X(FOUND_ROWS) \
X(BIG_PACKETS) \
X(NO_PROMPT) \
X(DYNAMIC_CURSOR) X(NO_DEFAULT_CURSOR) X(NO_LOCALE) X(PAD_SPACE) \
X(FULL_COLUMN_NAMES) X(COMPRESSED_PROTO) X(IGNORE_SPACE) X(NAMED_PIPE) \
X(NO_BIGINT) X(NO_CATALOG) X(USE_MYCNF) X(SAFE) X(NO_TRANSACTIONS) \
X(LOG_QUERY) X(NO_CACHE) X(FORWARD_CURSOR) X(AUTO_RECONNECT) \
X(AUTO_IS_NULL) X(ZERO_DATE_TO_MIN) X(MIN_DATE_TO_ZERO) \
X(MULTI_STATEMENTS) X(COLUMN_SIZE_S32) \
X(NO_BINARY_RESULT) X(DFLT_BIGINT_BIND_STR)
#if MFA_ENABLED
#define MFA_ALIASES(X) X(PWD1, PASSWORD1) X(PWD2, PASSWORD2) X(PWD3, PASSWORD3)
#else
#define MFA_ALIASES(X)
#endif
// Pairs of option names that have to be treated as the same
#define ALIAS_OPTIONS_LIST(X) \
X(UID, USER) X(PWD, PASSWORD) MFA_ALIASES(X) X(DATABASE, DB) \
X(SSL_KEY, SSLKEY) X(SSL_CERT, SSLCERT) X(SSL_CA, SSLCA) \
X(SSL_CAPATH, SSLCAPATH) X(SSL_CIPHER, SSLCIPHER) X(SSL_MODE, SSLMODE)
// Options that are not directly written to DSN
#define SKIP_OPTIONS_LIST(X) \
X(DRIVER) X(DSN)
class DataSource {
private:
// Map containing options, the key is SQLWSTRING for easier search
std::map<SQLWSTRING, optionBase &> m_opt_map;
// List of option aliases, they will not be written in INI files
std::vector<SQLWSTRING> m_alias_list;
public:
#define DECLARE_STR_OPT(X) optionStr opt_##X;
STR_OPTIONS_LIST(DECLARE_STR_OPT);
#define DECLARE_INT_OPT(X) optionInt opt_##X;
INT_OPTIONS_LIST(DECLARE_INT_OPT);
#define DECLARE_BOOL_OPT(X) optionBool opt_##X;
BOOL_OPTIONS_LIST(DECLARE_BOOL_OPT);
DataSource();
SQLWSTRING to_kvpair(SQLWCHAR delim);
void reset();
int add();
bool write_opt(const SQLWCHAR *name, const SQLWCHAR *val);
bool exists();
void set_numeric_options(unsigned long options);
void set_val(SQLWCHAR *name, SQLWCHAR *val);
optionBase *get_opt(SQLWCHAR *name);
unsigned long get_numeric_options();
int lookup();
int from_kvpair(const SQLWCHAR *str, SQLWCHAR delim);
void copy(DataSource* ds_source);
};
/* perhaps that is a good idea to have const ds object with defaults */
extern const unsigned int default_cursor_prefetch;
typedef struct{
SQLCHAR *type_name;
SQLINTEGER name_length;
SQLSMALLINT sql_type;
SQLSMALLINT mysql_type;
SQLUINTEGER type_length;
BOOL binary;
}SQLTypeMap;
#define TYPE_MAP_SIZE 32
extern const SQLWCHAR W_DRIVER_PARAM[];
extern const SQLWCHAR W_DRIVER_NAME[];
extern const SQLWCHAR W_INVALID_ATTR_STR[];
#define AUTH_MODE_IAM "IAM"
#define AUTH_MODE_SECRETS_MANAGER "SECRETS MANAGER"
#define FED_AUTH_MODE_ADFS "ADFS"
#define FED_AUTH_MODE_OKTA "OKTA"
#define FAILOVER_MODE_STRICT_WRITER "STRICT WRITER"
#define FAILOVER_MODE_STRICT_READER "STRICT READER"
#define FAILOVER_MODE_READER_OR_WRITER "READER OR WRITER"
/*
* Deprecated connection parameters
*/
#define FLAG_FOUND_ROWS 2 /* Access can't handle affected_rows */
#define FLAG_BIG_PACKETS 8 /* Allow BIG packets. */
#define FLAG_NO_PROMPT 16 /* Don't prompt on connection */
#define FLAG_DYNAMIC_CURSOR 32 /* Enables the dynamic cursor */
#define FLAG_NO_DEFAULT_CURSOR 128 /* No default cursor */
#define FLAG_NO_LOCALE 256 /* No locale specification */
#define FLAG_PAD_SPACE 512 /* Pad CHAR:s with space to max length */
#define FLAG_FULL_COLUMN_NAMES 1024 /* Extends SQLDescribeCol */
#define FLAG_COMPRESSED_PROTO 2048 /* Use compressed protocol */
#define FLAG_IGNORE_SPACE 4096 /* Ignore spaces after function names */
#define FLAG_NAMED_PIPE 8192 /* Force use of named pipes */
#define FLAG_NO_BIGINT 16384 /* Change BIGINT to INT */
#define FLAG_NO_CATALOG 32768 /* No catalog support */
#define FLAG_USE_MYCNF 65536L /* Read my.cnf at start */
#define FLAG_SAFE 131072L /* Try to be as safe as possible */
#define FLAG_NO_TRANSACTIONS (FLAG_SAFE << 1) /* Disable transactions */
#define FLAG_LOG_QUERY (FLAG_SAFE << 2) /* Query logging, debug */
#define FLAG_NO_CACHE (FLAG_SAFE << 3) /* Don't cache the resultset */
/* Force use of forward-only cursors */
#define FLAG_FORWARD_CURSOR (FLAG_SAFE << 4)
/* Force auto-reconnect */
#define FLAG_AUTO_RECONNECT (FLAG_SAFE << 5)
#define FLAG_AUTO_IS_NULL (FLAG_SAFE << 6) /* 8388608 Enables SQL_AUTO_IS_NULL */
#define FLAG_ZERO_DATE_TO_MIN (1 << 24) /* Convert XXXX-00-00 date to ODBC min date on results */
#define FLAG_MIN_DATE_TO_ZERO (1 << 25) /* Convert ODBC min date to 0000-00-00 on query */
#define FLAG_MULTI_STATEMENTS (1 << 26) /* Allow multiple statements in a query */
#define FLAG_COLUMN_SIZE_S32 (1 << 27) /* Limit column size to a signed 32-bit value (automatically set for ADO) */
#define FLAG_NO_BINARY_RESULT (1 << 28) /* Disables charset 63 for columns with empty org_table */
/*
When binding SQL_BIGINT as SQL_C_DEFAULT, treat it as a string
(automatically set for MS Access) see bug#24535
*/
#define FLAG_DFLT_BIGINT_BIND_STR (1 << 29)
/*
Use SHOW TABLE STATUS instead Information_Schema DB for table metadata
*/
#define ODBC_SSL_MODE_DISABLED "DISABLED"
#define ODBC_SSL_MODE_PREFERRED "PREFERRED"
#define ODBC_SSL_MODE_REQUIRED "REQUIRED"
#define ODBC_SSL_MODE_VERIFY_CA "VERIFY_CA"
#define ODBC_SSL_MODE_VERIFY_IDENTITY "VERIFY_IDENTITY"
// Possible values of OPENTELEMETRY option.
#define ODBC_OTEL_MODE(X) \
X(DISABLED,0) \
X(PREFERRED,1)
#define LPASTE(X) L ## X
#define LSTR(X) LPASTE(X)
#endif /* _INSTALLER_H */