pgpool2.git / summary / log / commit / refs

commit    3c97bbdddaa11e0155f37ac335ce742b9276ea01
Author:   Tatsuo Ishii <ishii@postgresql.org>
Date:     Fri Aug 07 06:22:21 2026 +0000

    Fix pool_do_auth.
    
    From PostgreSQL 19, backend sends a notice message "authenticated with
    an MD5-encrypted password" if MD5 auth is used. Unfortunately it
    exercises an untested code path in pool_do_auth. It calls
    SimpleForwardToFrontend to forward the notice message to
    frontend. Unfortunately calling it in authentication phase is wrong,
    since "session contest" is not established yet. If the session context
    is not established, SimpleForwardToFrontend fails with FATAL.
    
    To fix this, create a new function "forward_message_to_frontend",
    which is basically a simple version of SimpleForwardToFrontend error,
    so that it does not raise the FATAL error.
    
    Also add 133.md5_warning test for this.
    
    Reported-by: harudini
    Author: Tatsuo Ishii <ishii@postgresql.org>
    Discussion: https://github.com/pgpool/pgpool2/issues/168
    Backpatch-through: v4.3
    
    Test.


src/auth/pool_auth.c | 86 ++++++++++++++++++----- src/test/regression/tests/133.md5_warning/test.sh | 70 ++++++++++++++++++ 2 files changed, 137 insertions(+), 19 deletions(-) diff --git a/src/auth/pool_auth.c b/src/auth/pool_auth.c index 675838d47..95d12d9e2 100644 --- a/src/auth/pool_auth.c +++ b/src/auth/pool_auth.c @@ -81,6 +81,8 @@ static void authenticate_frontend_clear_text(POOL_CONNECTION *frontend); static bool get_auth_password(POOL_CONNECTION *backend, POOL_CONNECTION *frontend, int reauth, char **password, PasswordType *passwordType); static void ProcessNegotiateProtocol(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *cp); +static void forward_message_to_frontend(char kind, POOL_CONNECTION *frontend, + POOL_CONNECTION_POOL *backend); /* * Do authentication. Assuming the only caller is @@ -665,34 +667,20 @@ read_kind: errdetail("BACKEND NOTICE: \"%s\"", message))); pfree(message); } - /* process notice message */ - if (SimpleForwardToFrontend(kind, frontend, cp)) - ereport(ERROR, - (errmsg("authentication failed"), - errdetail("failed to forward message to frontend"))); - pool_flush(frontend); + /* forward the notice message to frontend */ + forward_message_to_frontend(kind, frontend, cp); break; - /* process error message */ case 'E': - if (pool_extract_error_message(false, MAIN(cp), protoMajor, true, &message) == 1) { ereport(LOG, (errmsg("backend throws an error message"), errdetail("%s", message))); - } - - SimpleForwardToFrontend(kind, frontend, cp); - - pool_flush(frontend); - - ereport(ERROR, - (errmsg("authentication failed, backend node replied with an error"), - errdetail("SERVER ERROR:\"%s\"", message ? message : "could not extract backend message"))); - - if (message) pfree(message); + } + /* forward the error message to frontend */ + forward_message_to_frontend(kind, frontend, cp); break; default: @@ -2222,3 +2210,63 @@ ProcessNegotiateProtocol(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *cp) } } } + +/* + * forward_message_frontend + * + * Simple version of SimpleForwardToFrontend. Just forward backend message to + * frontend. + */ +static void +forward_message_to_frontend(char kind, POOL_CONNECTION *frontend, + POOL_CONNECTION_POOL *backend) +{ + uint32 len, + len1 = 0; + char *p = NULL; + char *p1 = NULL; + int sendlen; + int i; + + pool_read(MAIN(backend), &len, sizeof(len)); + + len = ntohl(len); + if (len < 4) + elog(ERROR, "unable to forward message to frontend due to too short message length"); + len -= 4; + len1 = len; + + p = pool_read2(MAIN(backend), len); + if (p == NULL) + elog(ERROR, "unable to forward message to frontend due to reading from backend failure"); + p1 = palloc(len); + memcpy(p1, p, len); + + for (i = 0; i < NUM_BACKENDS; i++) + { + if (VALID_BACKEND(i) && !IS_MAIN_NODE_ID(i)) + { + pool_read(CONNECTION(backend, i), &len, sizeof(len)); + + len = ntohl(len); + if (len < 4) + elog(ERROR, "unable to forward message to frontend due to too short message length"); + len -= 4; + p = pool_read2(CONNECTION(backend, i), len); + if (p == NULL) + elog(ERROR, "unable to forward message to frontend due to reading from backend failure"); + if (len != len1) + { + elog(DEBUG1, "length does not match between backends. main(%d) %d th backend(%d) kind:(%c)", + len, i, len1, kind); + } + } + } + + /* forward message to frontend */ + pool_write(frontend, &kind, 1); + sendlen = htonl(len1 + 4); + pool_write(frontend, &sendlen, sizeof(sendlen)); + pool_write_and_flush(frontend, p1, len1); + pfree(p1); +} diff --git a/src/test/regression/tests/133.md5_warning/test.sh b/src/test/regression/tests/133.md5_warning/test.sh new file mode 100755 index 000000000..370810bdd --- /dev/null +++ b/src/test/regression/tests/133.md5_warning/test.sh @@ -0,0 +1,70 @@ +#!/usr/bin/env bash +#------------------------------------------------------------------- +# test script for the message: +# WARNING: authenticated with an MD5-encrypted password +# DETAIL: MD5 password support is deprecated and will be removed in a future release of PostgreSQL. +# (PostgreSQL 19+) + +# check PostgreSQL version +if [ "$PGVERSION" -lt 19 ];then + echo "PostgreSQL $PGVERSION is not supported by the test". + exit 0 +fi + +source $TESTLIBS +TESTDIR=testdir +PSQL=$PGBIN/psql +PG_CTL=$PGBIN/pg_ctl +export PGDATABASE=test +PG_MD5=$PGPOOL_INSTALL_DIR/bin/pg_md5 +PGPOOL_CONF=etc/pgpool.conf + +rm -fr $TESTDIR +mkdir $TESTDIR +cd $TESTDIR + +# specify max protocol version to 3.0 to avoid protocol negotiation +# message which is only supported by Pgpool-II 4.7+ +export PGMAXPROTOCOLVERSION=3.0 + +# create test environment. Number of backend node 1 is enough. +echo -n "creating test environment..." +$PGPOOL_SETUP -m s -n 1 || exit 1 +echo "done." + +dir=`pwd` +echo "enable_pool_hba = on" >> $PGPOOL_CONF + +./startall + +source ./bashrc.ports +export PGPORT=$PGPOOL_PORT +wait_for_pgpool_startup +echo PGPORT: $PGPORT +echo create MD5 password for "md5_user" +$PSQL -p 11002 test <<EOF +CREATE ROLE md5_user WITH LOGIN; +SET password_encryption = md5; +ALTER USER md5_user WITH ENCRYPTED PASSWORD 'md5_password'; +EOF + +$PG_MD5 -m -f $PGPOOL_CONF -u md5_user 'md5_password' + +./pgpool_reload +sleep 1 + +echo "connection test with md5 user" +expected=$'WARNING: authenticated with an MD5-encrypted password\nDETAIL: MD5 password support is deprecated and will be removed in a future release of PostgreSQL.' + +result=$(PGPASSWORD="md5_password" $PSQL -U md5_user -c "SELECT 1" test 2>&1 > /dev/null) +if [ $? != 0 ];then + echo "psql failed" + ./shutdownall + exit 1 +fi +./shutdownall +if [ "$expected" != "$result" ];then + echo "result is not expected one: \"$result\"" + exit 1 +fi +exit 0 [parent: 787313fafcb9]