From fb3ca78b2d86567bb6572549c99f18fd61209390 Mon Sep 17 00:00:00 2001 From: Jelte Fennema Date: Wed, 11 Jan 2023 11:55:08 +0100 Subject: [PATCH v3 3/4] Only expand \1 in pg_ident.conf when not quoted While unlikely, it's possible for usernames to contain the literal character sequence '\1'. This allows quoting the database-username in a pg_ident.conf file such that it's possible to match against a literal '\1' character sequence. This also adds tests for \1 substitution. --- doc/src/sgml/client-auth.sgml | 3 +++ src/backend/libpq/hba.c | 3 ++- src/test/authentication/t/003_peer.pl | 37 +++++++++++++++++++++++++++ 3 files changed, 42 insertions(+), 1 deletion(-) diff --git a/doc/src/sgml/client-auth.sgml b/doc/src/sgml/client-auth.sgml index cc8c59206c9..08a25a5e002 100644 --- a/doc/src/sgml/client-auth.sgml +++ b/doc/src/sgml/client-auth.sgml @@ -960,6 +960,9 @@ mymap /^(.*)@otherdomain\.com$ guest will remove the domain part for users with system user names that end with @mydomain.com, and allow any user whose system name ends with @otherdomain.com to log in as guest. + Quoting a database-username containing + \1 makes the \1 + lose its special meaning. diff --git a/src/backend/libpq/hba.c b/src/backend/libpq/hba.c index 029b8e44838..0c00580dff0 100644 --- a/src/backend/libpq/hba.c +++ b/src/backend/libpq/hba.c @@ -2865,7 +2865,8 @@ check_ident_usermap(IdentLine *identLine, const char *usermap_name, return; } - if ((ofs = strstr(identLine->pg_user->string, "\\1")) != NULL) + if (!identLine->pg_user->quoted && + (ofs = strstr(identLine->pg_user->string, "\\1")) != NULL) { int offset; diff --git a/src/test/authentication/t/003_peer.pl b/src/test/authentication/t/003_peer.pl index 24cefd14e0a..968f4a319d8 100644 --- a/src/test/authentication/t/003_peer.pl +++ b/src/test/authentication/t/003_peer.pl @@ -141,6 +141,43 @@ test_role( [qr/connection authenticated: identity="$system_user" method=peer/]); +# Success as the regular expression matches and \1 is replaced +reset_pg_ident($node, 'mypeermap', qq{/^$system_user(.*)\$}, + 'test\1mapuser'); +test_role( + $node, + qq{testmapuser}, + 'peer', + 0, + 'with regular expression in user name map with \1', + log_like => + [qr/connection authenticated: identity="$system_user" method=peer/]); + +# Failure since the \1 is part of a quoted string +reset_pg_ident($node, 'mypeermap', qq{/^$system_user(.*)\$}, + '"test\1mapuser"'); +test_role( + $node, + qq{testmapuser}, + 'peer', + 2, + 'with regular expression in user name map with a quoted \1', + log_like => + [qr/connection authenticated: identity="$system_user" method=peer/]); + + +# Failure as the regular expression doesn't contain a group, but the database +# user contains \1 +reset_pg_ident($node, 'mypeermap', qq{/^$system_user\$}, + '\1testmapuser'); +test_role( + $node, + qq{testmapuser}, + 'peer', + 2, + 'with regular expression in user name map with \1 without a matching group', + log_like => [qr/regular expression "\^$system_user\$" has no subexpressions as requested by backreference in "\\1testmapuser"/]); + # Concatenate system_user to system_user. $regex_test_string = $system_user . $system_user; -- 2.34.1