aws / aws/amazon-redshift-odbc-driver
`SQLDriverConnect` truncates long IAM temporary passwords to 1024 chars (`MAX_IDEN_LEN`), causing `28000` authentication failure
- Dominant language
- C
- Stars
- 25
- Forks
- 17
- PR merge metrics
- No merged PRs in 30d
Description
### Summary
When connecting with a long IAM temporary password (e.g. from
`aws redshift-serverless get-credentials`, which can return 1000+ character
passwords) via **`SQLDriverConnect`** — i.e. a connection string, whether it
references a DSN (`;DSN=foo;UID=...;PWD=...`) or not (`Driver={...};UID=...;PWD=...`)
— the driver silently truncates the password to 1024 characters before
sending it to the server. The server then rejects the truncated password,
and the client sees:
```
[Redshift][ODBC Driver][Server]28000:FATAL: IAM authentication failed for user "IAMR:"
```
**`SQLConnect`** (DSN name + UID + PWD passed as three separate arguments,
*not* a connection string) is **not** affected — the same password works
correctly through that path, because it does not apply the same
1024-character limit. Whether a DSN name is involved is not the deciding
factor; which ODBC connect API is used (`SQLConnect` vs `SQLDriverConnect`)
is. This inconsistency between the two standard ODBC connect APIs is the
root cause.
This affects any client that connects using a connection string, including
**Tableau Desktop**, which (per Tableau's own documentation) always builds and
passes a connection string to the driver manager.
### Root cause
- `parseConnectString()` (used by `SQLDriverConnect`) in `rsconnect.cpp`:
```c
strncpy(pConnectProps->szPassword, pval, MAX_IDEN_LEN - 1);
pConnectProps->szPassword[MAX_IDEN_LEN - 1] = '\0';
```
This is confirmed (by driver log inspection, see below) to be the code path
that actually truncates the password in this bug.
- `readMoreConnectPropsFromRegistry()` (used to read `PWD`/`Password` directly
from a DSN section in `odbc.ini`, i.e. when the password itself — not just
the DSN name — is stored in `odbc.ini`) has the same `MAX_IDEN_LEN` limit via
`RS_SQLGetPrivateProfileString(..., MAX_IDEN_LEN, ODBC_INI)`. This code path
was **not** exercised in our reproduction/verification (our DSN never stored
the password itself; the password was always supplied by the caller), but it
shares the same `MAX_IDEN_LEN` limit and the same bug pattern, so we include
it as a fix target on code-inspection grounds.
- `MAX_IDEN_LEN` is `1024 + 1` (`rsiam.h`), sized for identifier-like fields
(host, port, DSN, user), not for long IAM temporary credentials.
- By contrast, `RS_SQLConnect()` (the `SQLConnect` code path, i.e. DSN name +
UID + PWD passed as three separate arguments) copies the password with
`sizeof(pConnectProps->szPassword)` as the limit, which is
`PADB_MAX_PARAMETERS` (32767) — the real size of the `szPassword` buffer.
So `SQLConnect` never truncates, while `SQLDriverConnect` (with or without a
`DSN=` keyword in the connection string) does.
### Steps to reproduce
Using `isql` (unixODBC) against a Redshift Serverless workgroup with IAM
authentication:
```bash
# Get a long IAM temporary password (typically 1000+ chars)
export RSPASSWORD=$(aws redshift-serverless get-credentials \
--region --workgroup-name --db-name dev \
--duration-seconds 3600 --query 'dbPassword' --output text)
echo "PWD length: ${#RSPASSWORD}"
# SQLDriverConnect path (connection string) -> fails
isql -v -k "Driver={Amazon Redshift ODBC Driver (x64)};Server=;Port=5439;Database=dev;UID=IAMR:;PWD=$RSPASSWORD;SSLMode=require"
# [28000][Redshift][ODBC Driver][Server]28000:FATAL: IAM authentication failed for user "IAMR:"
# SQLConnect path (DSN name + UID + PWD as arguments) -> succeeds with the same password
isql -v "IAMR:" "$RSPASSWORD"
# Connected!
```
With `LogLevel=6` driver tracing enabled, the actual bytes written to the
backend (`fe-misc.c:232`, `"To backend[S]> ... N bytes"`) confirm the
truncation:
| Path | Password length | Bytes sent to server | Truncated? |
|---|---|---|---|
| `SQLConnect` (DSN + UID/PWD args) | 1905 | 1906 | No |
| `SQLDriverConnect` (connection string) | 1905 | 1025 | **Yes** (cut to `MAX_IDEN_LEN - 1`) |
### Verified environments
This was reproduced and the fix (see linked PR) was verified on:
- Linux (Amazon Linux 2023, x86_64), source build, `isql` (unixODBC) via both
`SQLConnect` and `SQLDriverConnect`.
- macOS (Apple Silicon, arm64), source build, `isql` (unixODBC) via
`SQLDriverConnect`.
- macOS (Apple Silicon, arm64), **Tableau Desktop** (actual application),
which uses the `SQLDriverConnect` path — confirmed both the original bug
(`28000` failure with a long IAM password) and the fix (successful
connection) on the real client.
In all cases, driver logs (`fe-misc.c:232`) confirmed the exact byte count
sent to the backend matched the full password length (+1 for the NUL
terminator) once the fix was applied, with no truncation.
### Impact
Any ODBC client that connects via a connection string (`SQLDriverConnect`) —
including Tableau Desktop — is affected when using IAM authentication with a
temporary password longer than 1024 characters. Clients that use `SQLConnect`
(DSN name + UID + PWD as separate arguments) are not affected. Native
(non-IAM) database users are typically unaffected regardless of the code
path, because their passwords are short enough to stay under the limit,
which is why this can look like an IAM-specific regression.
### Suggested fix
Use `sizeof(pConnectProps->szPassword)` instead of `MAX_IDEN_LEN` for the
password field in both `parseConnectString()` and
`readMoreConnectPropsFromRegistry()`, matching the limit already used by the
`SQLConnect` path. See the accompanying PR for the implementation.
Contributor guide
Research direction
Start in rsconnect.cpp at parseConnectString() and readMoreConnectPropsFromRegistry(), then inspect MAX_IDEN_LEN in rsiam.h and compare the existing RS_SQLConnect() path. Reproduce with isql using a long IAM password through SQLDriverConnect and SQLConnect. Done means SQLDriverConnect preserves the full password without authentication failure while SQLConnect behavior remains unchanged.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- aws, c, sql
- Domain
- authentication, databases
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 72/100