Skip to content

Commit

Permalink
Add new parameter for SIGv4 auth. (#42)
Browse files Browse the repository at this point in the history
Add new optional parameter for use with AWS_SIGv4 authentication to connect to a cluster via SSH tunnel (for example - OpenSearch cluster is a VPC endpoint).
This parameter is required to fix request header to comply SIGv4 requirements. [Ref: link](https://stackoverflow.com/a/67683064).
---------

Signed-off-by: Yury-Fridlyand <yury.fridlyand@improving.com>
  • Loading branch information
Yury-Fridlyand committed May 30, 2023
1 parent 9b8d366 commit 701d1cd
Show file tree
Hide file tree
Showing 27 changed files with 204 additions and 55 deletions.
3 changes: 0 additions & 3 deletions .github/workflows/sql-odbc-main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,6 @@ on:
push:
branches-ignore:
- 'dependabot/**'
paths:
- '.'
- '.github/workflows/sql-odbc-main.yml'

env:
CI_OUTPUT_PATH: "./ci-output"
Expand Down
46 changes: 24 additions & 22 deletions docs/user/configuration_options.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,37 +4,39 @@
#### Basic Options

| Option | Description | Type | Default |
|--------|-------------|------|---------------|
| `DSN` | **D**ata **S**ource **N**ame used for configuring the connection. | string | |
| `Host` / `Server` | Hostname or IP address for the target cluster. | string | |
| `Port` | Port number on which the cluster's REST interface is listening. | string | |
| Option | Description | Type |
|-------------------|-------------------------------------------------------------------|--------|
| `DSN` | **D**ata **S**ource **N**ame used for configuring the connection. | string |
| `Host` / `Server` | Hostname or IP address for the target cluster. | string |
| `Port` | Port number on which the cluster's REST interface is listening. | string |

#### Authentication Options

| Option | Description | Type | Default |
|--------|-------------|------|---------------|
| `Auth` | Authentication mechanism to use. | one of `BASIC` (basic HTTP), `AWS_SIGV4` (AWS auth), `NONE` | `NONE`
| `User` / `UID` | [`Auth=BASIC`] Username for the connection. | string | |
| `Password` / `PWD` | [`Auth=BASIC`] Password for the connection. | string | |
| `Region` | [`Auth=AWS_SIGV4`] Region used for signing requests | AWS region (eg. `us-west-1`) | |
| Option | Description | Type | Acceptable Values | Default |
|--------------------|-------------------------------------------------------------------------------|--------|------------------------------------------------------|---------|
| `Auth` | Authentication mechanism to use. | string | `BASIC` (basic HTTP), `AWS_SIGV4` (AWS auth), `NONE` | `NONE` |
| `User` / `UID` | [`Auth=BASIC`] Username for the connection. | string | | |
| `Password` / `PWD` | [`Auth=BASIC`] Password for the connection. | string | | |
| `Region` | [`Auth=AWS_SIGV4`] Region used for signing requests | string | AWS region (eg. `us-west-1`) | |
| `TunnelHost` | [`Auth=AWS_SIGV4`] VPC endpoint hostname if connected through tunnel or proxy | string | | |

**NOTE:** To use `AWS_SIGV4` authentication you need to create `~/.aws/credentials` and add `opensearchodbc` profile with aws access key id and secret key.
**NOTE:** To use `AWS_SIGV4` authentication you need to create `~/.aws/credentials` and add `opensearchodbc` profile with aws access key id, secret key and session token (if used).

#### Advanced Options

| Option | Description | Type | Default |
|--------|-------------|------|---------------|
| `UseSSL` | Whether to establish the connection over SSL/TLS | boolean (`0` or `1`) | false (`0`) |
| `HostnameVerification` | Indicate whether certificate hostname verification should be performed for an SSL/TLS connection. | boolean (`0` or `1`) | true (`1`) |
| `ResponseTimeout` | The maximum time to wait for responses from the `Host`, in seconds. | integer | `10` |
| `FetchSize` | The page size for all cursor requests. The default value (-1) uses server-defined page size. Set FetchSize to 0 for non-cursor behavior. | integer | `-1` |
| Option | Description | Type | Acceptable Values | Default |
|------------------------|------------------------------------------------------------------------------------------------------------------------------------------|---------|---------------------------------|-------------|
| `UseSSL` | Whether to establish the connection over SSL/TLS | boolean | `0` or `1` | `0` (false) |
| `HostnameVerification` | Indicate whether certificate hostname verification should be performed for an SSL/TLS connection. | boolean | `0` or `1` | `1` (true) |
| `ResponseTimeout` | The maximum time to wait for responses from the `Host`, in seconds. | integer | | `10` |
| `FetchSize` | The page size for all cursor requests. The default value (-1) uses server-defined page size. Set FetchSize to 0 for non-cursor behavior. | integer | `-1`, `0` or any positive value | `-1` |

#### Logging Options

| Option | Description | Type | Default |
|--------|-------------|------|---------------|
| `LogLevel` | Severity level for driver logs. | one of `OPENSEARCH_OFF`, `OPENSEARCH_FATAL`, `OPENSEARCH_ERROR`, `OPENSEARCH_INFO`, `OPENSEARCH_DEBUG`, `OPENSEARCH_TRACE`, `OPENSEARCH_ALL` | `OPENSEARCH_WARNING` |
| `LogOutput` | Location for storing driver logs. | string | WIN: `C:\`, MAC: `/tmp` |
| Option | Description | Type | Acceptable Values | Default |
|-------------|-----------------------------------|---------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------|
| `LogLevel` | Severity level for driver logs. | integer | `0` -- `OFF` <br /> `1` -- `FATAL` <br /> `2` -- `ERROR` <br /> `3` -- `WARNING` <br /> `4` -- `INFO` <br /> `5` -- `DEBUG` <br /> `6` -- `TRACE` <br /> `7` -- `ALL` | `3` |
| `LogOutput` | Location for storing driver logs. | string | | WIN: `C:\` <br /> MAC: `/Library/ODBC/opensearch-sql-odbc` |


**NOTE:** Administrative privileges are required to change the value of logging options on Windows.
Binary file added docs/user/img/mac_dsn_config_aws_sigv4_auth.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/user/img/mac_dsn_config_basic_auth.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/user/img/win_configure_dsn.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/user/img/win_configure_dsn_values.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/user/img/win_configure_with_tunnel.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/user/img/win_system_dsn.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/user/img/win_user_dsn_configure_options.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/user/img/win_user_dsn_list.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/user/img/win_user_dsn_select_driver.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
93 changes: 91 additions & 2 deletions docs/user/mac_configure_dsn.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ Note: In order to use the OpenSearch SQL ODBC driver with the [Tableau Connector
* **Description of the Driver**: The driver name used for ODBC connections (ex. `OpenSearch SQL ODBC Driver`)
* **Driver File Name**: The path to the driver file (default installed path: `/Library/ODBC/opensearch-sql-odbc/bin/libsqlodbc.dylib`)
* **Setup File Name**: The path to the driver file (default installed path: `/Library/ODBC/opensearch-sql-odbc/bin/libsqlodbc.dylib`)
* Set as a **User** driver
* Set as a **System** driver
* Below is a screenshot of how the final screen should look.
3. Click **OK** to save the options.

Expand Down Expand Up @@ -68,4 +68,93 @@ Try the following:
Port = 9200
Username = admin
Password = admin
```
```

## Configuration examples

### `BASIC` Authentication

```ini
[ODBC Data Sources]
OpenSearch SQL ODBC DSN = OpenSearch SQL ODBC Driver

[ODBC]
TraceLibrary =
Trace = 1
TraceAutoStop = 0
TraceFile = /Library/ODBC/opensearch-sql-odbc/odbc.log
TraceDLL =

[OpenSearch SQL ODBC DSN]
Driver = /Library/ODBC/opensearch-sql-odbc/bin/libsqlodbc.dylib
Host = https://localhost
Port = 9200
UseSSL = 1
ResponseTimeout = 6
HostnameVerification = 0
LogOutput = /Library/ODBC/opensearch-sql-odbc
Auth = BASIC
```

<p align="center">
<img src="img/mac_dsn_config_basic_auth.png" width="80%"/>
</p>

### `AWS_SIGv4` Authentication

```ini
[ODBC Data Sources]
OpenSearch SQL ODBC DSN = OpenSearch SQL ODBC Driver

[ODBC]
TraceLibrary =
Trace = 1
TraceAutoStop = 0
TraceFile = /Library/ODBC/opensearch-sql-odbc/odbc.log
TraceDLL =

[OpenSearch SQL ODBC DSN]
Driver = /Library/ODBC/opensearch-sql-odbc/bin/libsqlodbc.dylib
Host = https://search-*.us-east-1.es.amazonaws.com/
Port = 443
UseSSL = 1
ResponseTimeout = 6
HostnameVerification = 1
Region = us-east-1
LogOutput = /Library/ODBC/opensearch-sql-odbc
Auth = AWS_SIGV4
```

<p align="center">
<img src="img/mac_dsn_config_aws_sigv4_auth.png" width="80%"/>
</p>

### `AWS_SIGv4` Authentication with connecting to a VPC endpoint behind SSH tunnel

```ini
[ODBC Data Sources]
OpenSearch SQL ODBC DSN = OpenSearch SQL ODBC Driver

[ODBC]
TraceLibrary =
Trace = 1
TraceAutoStop = 0
TraceFile = /Library/ODBC/opensearch-sql-odbc/odbc.log
TraceDLL =

[OpenSearch SQL ODBC DSN]
Driver = /Library/ODBC/opensearch-sql-odbc/bin/libsqlodbc.dylib
Host = https://localhost
Port = 9200
UseSSL = 1
ResponseTimeout = 6
HostnameVerification = 0
Region = us-east-1
LogOutput = /Library/ODBC/opensearch-sql-odbc
Auth = AWS_SIGV4
TunnelHost = vpc-*.us-east-1.es.amazonaws.com
```

<p align="center">
<img src="img/mac_dsn_config_aws_sigv4_auth_with_ssh_tunnel.png" width="80%"/>
</p>
9 changes: 8 additions & 1 deletion docs/user/windows_configure_dsn.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

<img src="img/win_odbc_data_sources.png" width="30%">

**NOTE**: Use 32 bit application to configure 32 bit driver and 64 bit app for 64 bit driver.

2. Click on the `System DSN` tab. Select `OpenSearch SQL ODBC DSN` and click on `Configure`.

<img src="img/win_system_dsn.png" width="60%">
Expand Down Expand Up @@ -53,4 +55,9 @@ For example, if you can connect to server using following curl command
7. You will find this newly added DSN in User DSN list.

<img src="img/win_user_dsn_list.png" width="60%">


## Connecting to an OpenSearch cluster created as an AWS VPC endpoint over a tunnel

In case if you use a tunnel or a proxy to connect to an OpenSearch cluster located into a VPC, `Host` doesn't represent a real OpenSearch hostname. To properly sign requests with AWS signature, real OpenSearch cluster hostname is required. It could be set in `Tunnel Host` field.

<img src="img/win_configure_with_tunnel.png" width="50%">
2 changes: 2 additions & 0 deletions src/PerformanceTests/PTODBCInfo/performance_odbc_info.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ runtime_options rt_opts = []() {
temp_opts.auth.password = wstring_to_string(it.second);
else if (tmp == L"region")
temp_opts.auth.region = wstring_to_string(it.second);
else if (tmp == L"tunnelhost")
temp_opts.auth.tunnel_host = wstring_to_string(it.second);
else if (tmp == L"usessl")
temp_opts.crypt.use_ssl =
(std::stoul(it.second, nullptr, 10) ? true : false);
Expand Down
7 changes: 4 additions & 3 deletions src/UnitTests/UTConn/test_conn.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,21 @@ const std::string valid_port = "9200";
const std::string valid_user = "admin";
const std::string valid_pw = "admin";
const std::string valid_region = "us-west-3";
const std::string valid_tunnel_host = "";
const std::string invalid_host = "10.1.1.189";
const std::string invalid_port = "920";
const std::string invalid_user = "amin";
const std::string invalid_pw = "amin";
const std::string invalid_region = "bad-region";
runtime_options valid_opt_val = {{valid_host, valid_port, "1", "0"},
{"BASIC", valid_user, valid_pw, valid_region},
{"BASIC", valid_user, valid_pw, valid_region, valid_tunnel_host},
{use_ssl, false, "", "", "", ""}};
runtime_options invalid_opt_val = {
{invalid_host, invalid_port, "1", "0"},
{"BASIC", invalid_user, invalid_pw, valid_region},
{"BASIC", invalid_user, invalid_pw, valid_region, valid_tunnel_host},
{use_ssl, false, "", "", "", ""}};
runtime_options missing_opt_val = {{"", "", "1", "0"},
{"BASIC", "", invalid_pw, valid_region},
{"BASIC", "", invalid_pw, valid_region, valid_tunnel_host},
{use_ssl, false, "", "", "", ""}};

TEST(TestOpenSearchConnConnectionOptions, ValidParameters) {
Expand Down
3 changes: 2 additions & 1 deletion src/UnitTests/UTConn/test_query_execution.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const std::string valid_port = "9200";
const std::string valid_user = "admin";
const std::string valid_pw = "admin";
const std::string valid_region = "us-west-3";
const std::string valid_tunnel_host = "";
const std::string query =
"SELECT Origin FROM opensearch_dashboards_sample_data_flights LIMIT 5";
const std::string all_columns_flights_query =
Expand All @@ -24,7 +25,7 @@ const int all_columns_flights_count = 25;
const int some_columns_flights_count = 2;
runtime_options valid_conn_opt_val = {
{valid_host, valid_port, "1", "0"},
{"BASIC", valid_user, valid_pw, valid_region},
{"BASIC", valid_user, valid_pw, valid_region, valid_tunnel_host},
{use_ssl, false, "", "", "", ""}};

TEST(TestOpenSearchExecDirect, ValidQuery) {
Expand Down
17 changes: 14 additions & 3 deletions src/sqlodbc/dlg_specific.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,12 @@ void makeConnectString(char *connect_string, const ConnInfo *ci, UWORD len) {
"=%s;"
"database=OpenSearch;" INI_PORT "=%s;" INI_USERNAME_ABBR
"=%s;" INI_PASSWORD_ABBR "=%s;" INI_AUTH_MODE "=%s;" INI_REGION
"=%s;" INI_SSL_USE "=%d;" INI_SSL_HOST_VERIFY "=%d;" INI_LOG_LEVEL
"=%d;" INI_LOG_OUTPUT "=%s;" INI_TIMEOUT "=%s;" INI_FETCH_SIZE "=%s;",
"=%s;" INI_TUNNEL_HOST "=%s;" INI_SSL_USE "=%d;" INI_SSL_HOST_VERIFY
"=%d;" INI_LOG_LEVEL "=%d;" INI_LOG_OUTPUT "=%s;" INI_TIMEOUT "=%s;"
INI_FETCH_SIZE "=%s;",
got_dsn ? "DSN" : "DRIVER", got_dsn ? ci->dsn : ci->drivername,
ci->server, ci->port, ci->username, encoded_item, ci->authtype,
ci->region, (int)ci->use_ssl, (int)ci->verify_server,
ci->region, ci->tunnel_host, (int)ci->use_ssl, (int)ci->verify_server,
(int)ci->drivers.loglevel, ci->drivers.output_dir,
ci->response_timeout, ci->fetch_size);
if (olen < 0 || olen >= nlen) {
Expand Down Expand Up @@ -109,6 +110,8 @@ BOOL copyConnAttributes(ConnInfo *ci, const char *attribute,
STRCPY_FIXED(ci->authtype, value);
else if (stricmp(attribute, INI_REGION) == 0)
STRCPY_FIXED(ci->region, value);
else if (stricmp(attribute, INI_TUNNEL_HOST) == 0)
STRCPY_FIXED(ci->tunnel_host, value);
else if (stricmp(attribute, INI_SSL_USE) == 0)
ci->use_ssl = (char)atoi(value);
else if (stricmp(attribute, INI_SSL_HOST_VERIFY) == 0)
Expand Down Expand Up @@ -146,6 +149,7 @@ static void getCiDefaults(ConnInfo *ci) {
ci->password.name = NULL;
strncpy(ci->username, DEFAULT_USERNAME, MEDIUM_REGISTRY_LEN);
strncpy(ci->region, DEFAULT_REGION, MEDIUM_REGISTRY_LEN);
strncpy(ci->tunnel_host, DEFAULT_TUNNEL_HOST, MEDIUM_REGISTRY_LEN);
ci->use_ssl = DEFAULT_USE_SSL;
ci->verify_server = DEFAULT_VERIFY_SERVER;
strcpy(ci->drivers.output_dir, "C:\\");
Expand Down Expand Up @@ -250,6 +254,10 @@ void getDSNinfo(ConnInfo *ci, const char *configDrvrname) {
sizeof(temp), ODBC_INI)
> 0)
STRCPY_FIXED(ci->region, temp);
if (SQLGetPrivateProfileString(DSN, INI_TUNNEL_HOST, NULL_STRING, temp,
sizeof(temp), ODBC_INI)
> 0)
STRCPY_FIXED(ci->tunnel_host, temp);
if (SQLGetPrivateProfileString(DSN, INI_SSL_USE, NULL_STRING, temp,
sizeof(temp), ODBC_INI)
> 0)
Expand Down Expand Up @@ -304,6 +312,7 @@ void writeDSNinfo(const ConnInfo *ci) {
SQLWritePrivateProfileString(DSN, INI_PASSWORD, encoded_item, ODBC_INI);
SQLWritePrivateProfileString(DSN, INI_AUTH_MODE, ci->authtype, ODBC_INI);
SQLWritePrivateProfileString(DSN, INI_REGION, ci->region, ODBC_INI);
SQLWritePrivateProfileString(DSN, INI_TUNNEL_HOST, ci->tunnel_host, ODBC_INI);
ITOA_FIXED(temp, ci->use_ssl);
SQLWritePrivateProfileString(DSN, INI_SSL_USE, temp, ODBC_INI);
ITOA_FIXED(temp, ci->verify_server);
Expand Down Expand Up @@ -454,6 +463,7 @@ void CC_conninfo_init(ConnInfo *conninfo, UInt4 option) {
conninfo->password.name = NULL;
strncpy(conninfo->username, DEFAULT_USERNAME, MEDIUM_REGISTRY_LEN);
strncpy(conninfo->region, DEFAULT_REGION, MEDIUM_REGISTRY_LEN);
strncpy(conninfo->tunnel_host, DEFAULT_TUNNEL_HOST, MEDIUM_REGISTRY_LEN);
conninfo->use_ssl = DEFAULT_USE_SSL;
conninfo->verify_server = DEFAULT_VERIFY_SERVER;

Expand Down Expand Up @@ -494,6 +504,7 @@ void CC_copy_conninfo(ConnInfo *ci, const ConnInfo *sci) {
CORR_STRCPY(username);
CORR_STRCPY(authtype);
CORR_STRCPY(region);
CORR_STRCPY(tunnel_host);
NAME_TO_NAME(ci->password, sci->password);
CORR_VALCPY(use_ssl);
CORR_VALCPY(verify_server);
Expand Down
5 changes: 3 additions & 2 deletions src/sqlodbc/dlg_specific.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ extern "C" {
#define INI_PASSWORD "password"
#define INI_PASSWORD_ABBR "PWD"
#define INI_AUTH_MODE "auth"
#define INI_REGION "region"
#define INI_REGION "region"
#define INI_TUNNEL_HOST "TunnelHost"
#define INI_SSL_USE "useSSL"
#define INI_SSL_HOST_VERIFY "hostnameVerification"
#define INI_LOG_LEVEL "logLevel"
Expand All @@ -63,7 +64,6 @@ extern "C" {
#define DEFAULT_DRIVERNAME "opensearchodbc"
#define DEFAULT_DESC ""
#define DEFAULT_DSN ""
#define DEFAULT_REGION ""
#define DEFAULT_VERIFY_SERVER 1

#define AUTHTYPE_NONE "NONE"
Expand Down Expand Up @@ -124,6 +124,7 @@ extern "C" {
#define DEFAULT_TRUST_SELF_SIGNED 0
#define DEFAULT_AUTH_MODE "NONE"
#define DEFAULT_REGION ""
#define DEFAULT_TUNNEL_HOST ""
#define DEFAULT_CERTIFICATE ""
#define DEFAULT_KEY ""
#define DEFAULT_UNKNOWNSIZES UNKNOWNS_AS_MAX
Expand Down
6 changes: 6 additions & 0 deletions src/sqlodbc/dlg_wingui.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,14 +63,17 @@ void SetAuthenticationVisibility(HWND hdlg, const struct authmode *am) {
EnableWindow(GetDlgItem(hdlg, IDC_USER), TRUE);
EnableWindow(GetDlgItem(hdlg, IDC_PASSWORD), TRUE);
EnableWindow(GetDlgItem(hdlg, IDC_REGION), FALSE);
EnableWindow(GetDlgItem(hdlg, IDC_TUNNEL_HOST), FALSE);
} else if (strcmp(am->authtype_str, AUTHTYPE_IAM) == 0) {
EnableWindow(GetDlgItem(hdlg, IDC_USER), FALSE);
EnableWindow(GetDlgItem(hdlg, IDC_PASSWORD), FALSE);
EnableWindow(GetDlgItem(hdlg, IDC_REGION), TRUE);
EnableWindow(GetDlgItem(hdlg, IDC_TUNNEL_HOST), TRUE);
} else {
EnableWindow(GetDlgItem(hdlg, IDC_USER), FALSE);
EnableWindow(GetDlgItem(hdlg, IDC_PASSWORD), FALSE);
EnableWindow(GetDlgItem(hdlg, IDC_REGION), FALSE);
EnableWindow(GetDlgItem(hdlg, IDC_TUNNEL_HOST), FALSE);
}
}

Expand Down Expand Up @@ -99,6 +102,7 @@ void SetDlgStuff(HWND hdlg, const ConnInfo *ci) {
SetDlgItemText(hdlg, IDC_USER, ci->username);
SetDlgItemText(hdlg, IDC_PASSWORD, SAFE_NAME(ci->password));
SetDlgItemText(hdlg, IDC_REGION, ci->region);
SetDlgItemText(hdlg, IDC_TUNNEL_HOST, ci->tunnel_host);
}

static void GetNameField(HWND hdlg, int item, opensearchNAME *name) {
Expand All @@ -117,6 +121,8 @@ void GetDlgStuff(HWND hdlg, ConnInfo *ci) {
GetDlgItemText(hdlg, IDC_USER, ci->username, sizeof(ci->username));
GetNameField(hdlg, IDC_PASSWORD, &ci->password);
GetDlgItemText(hdlg, IDC_REGION, ci->region, sizeof(ci->region));
GetDlgItemText(hdlg, IDC_TUNNEL_HOST, ci->tunnel_host,
sizeof(ci->tunnel_host));
const struct authmode *am = GetCurrentAuthMode(hdlg);
SetAuthenticationVisibility(hdlg, am);
STRCPY_FIXED(ci->authtype, am->authtype_str);
Expand Down
2 changes: 2 additions & 0 deletions src/sqlodbc/drvconn.c
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,8 @@ INT_PTR CALLBACK dconn_FDriverConnectProc(HWND hdlg, UINT wMsg, WPARAM wParam,
SetFocus(GetDlgItem(hdlg, IDC_USER));
else if (ci->region[0] == '\0')
SetFocus(GetDlgItem(hdlg, IDC_REGION));
else if (ci->tunnel_host[0] == '\0')
SetFocus(GetDlgItem(hdlg, IDC_TUNNEL_HOST));

SendDlgItemMessage(hdlg, IDC_AUTHTYPE, CB_SETCURSEL, 2, (WPARAM)0);

Expand Down
Loading

0 comments on commit 701d1cd

Please sign in to comment.