Uploaded image for project: 'MariaDB Server'
  1. MariaDB Server
  2. MDEV-38431

Auth Switch with Long Password Corrupts Database Name

    XMLWordPrintable

Details

    • Bug
    • Status: Open (View Workflow)
    • Major
    • Resolution: Unresolved
    • 10.6.24
    • None
    • Protocol
    • 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

      Attachments

        Activity

          People

            Unassigned Unassigned
            rophy Rophy Tsai
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

              Created:
              Updated:

              Git Integration

                Error rendering 'com.xiplink.jira.git.jira_git_plugin:git-issue-webpanel'. Please contact your Jira administrators.