Details
-
Bug
-
Status: Open (View Workflow)
-
Major
-
Resolution: Unresolved
-
10.6.24
-
None
-
None
-
- MariaDB Server 10.6.24 Docker
- MariaDB Connector/C 3.3.8 through 3.4.x
- Native `mariadb` CLI client (from mariadb-client package)
Description
When using any MySQL/MariaDB client with `--default-auth=mysql_clear_password` to trigger an auth switch, connections with long passwords (>250 bytes) and a database name fail with `ERROR 1049: Unknown database 'X'` where `X` is a character from the server's scramble buffer, not from the actual database name.
Can be reproduced by both MariaDB Connector/C and the native `mariadb` CLI client, so likely a server-side bug.
# Create test user with long password
|
mysql -u root -e "
|
SET @longpass = REPEAT('A', 1000); |
SET @sql = CONCAT('CREATE USER IF NOT EXISTS testuser@\"%\" IDENTIFIED BY \"', @longpass, 'XYZ\"'); |
PREPARE stmt FROM @sql;
|
EXECUTE stmt;
|
GRANT ALL ON *.* TO testuser@'%'; |
"
|
|
|
# Generate the same long password
|
LONG_PASSWORD=$(python3 -c "print('A' * 1000 + 'XYZ')") |
|
|
# This FAILS - triggers auth switch with long password + database
|
mariadb -h 127.0.0.1 -u testuser -p"$LONG_PASSWORD" \ |
--default-auth=mysql_clear_password \
|
information_schema \
|
-e "SELECT 1" |
# Result: ERROR 1049 (42000): Unknown database 'Z'
|
|
|
# This WORKS - no database specified
|
mariadb -h 127.0.0.1 -u testuser -p"$LONG_PASSWORD" \ |
--default-auth=mysql_clear_password \
|
-e "SELECT 1" |
# Result: Success
|
|
|
# This WORKS - no auth switch (using server's default auth plugin)
|
mariadb -h 127.0.0.1 -u testuser -p"$LONG_PASSWORD" \ |
information_schema \
|
-e "SELECT 1" |
# Result: Success |
Bug Analysis
Conditions Required
The bug occurs when ALL of these conditions are true:
1. Client requests a different auth plugin than server's default (triggers AuthSwitchRequest)
2. Password length > 250 bytes (requires LENENC 3-byte encoding)
3. A database name is specified in the initial connection
What Happens (based on packet capture analysis)
1. Client sends HandshakeResponse with:
- `CLIENT_CONNECT_WITH_DB` flag SET
- `CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA` flag SET
- Username
- Password length: LENENC encoded (e.g., `fc ec 03` for 1004 bytes)
- Password data (correctly placed)
- Database name (correctly placed after password)
- Auth plugin name (`mysql_clear_password`)
2. *Packet is correctly formed* - verified via tcpdump
3. Server sends AuthSwitchRequest (0xFE packet) with scramble data
4. Client sends AuthSwitchResponse with scrambled password (20 bytes for mysql_native_password)
5. *BUG*: Server returns `ERROR 1049: Unknown database 'Z'`
- The 'Z' character (0x5a) appears in the *scramble buffer* from step 3
- Server is reading database name from wrong memory location after auth switch
Evidence from Packet Capture
Server scramble in AuthSwitchRequest:
|
38 52 74 71 5a 50 5f 6e 2d 33 58 40 78 5e 4e 4a 67 4a 7a 4a 00
|
^^ = 0x5a = 'Z'
|
|
|
Error message: "Unknown database 'Z'"
|
The error character matches byte 4 of the scramble, NOT the password ending.
Root Cause
The MariaDB Server has a bug in its auth switch handling code path. When processing a HandshakeResponse with LENENC-encoded auth data (>250 bytes), the server correctly parses the initial packet but loses track of the database name location during the auth switch process. It later reads from the wrong memory location (the scramble buffer).
Workaround
Connect without specifying a database, then switch after authentication:
/* Step 1: Connect WITHOUT database */
|
result = mysql_real_connect(mysql, host, user, password, NULL, port, NULL, 0);
|
|
|
/* Step 2: Switch database after auth succeeds */
|
mysql_query(mysql, "USE testdb"); |
Or avoid triggering auth switch by not setting `--default-auth` / `MYSQL_DEFAULT_AUTH`.
Environment
- OS: Ubuntu 24.04
- MariaDB Server: 10.6.24
- Tested clients:
- MariaDB Connector/C 3.3.8
- Native `mariadb` CLI from mariadb-client package