On 29/12/2019 23:10, Vik Fearing wrote: > On 29/12/2019 17:31, Tom Lane wrote: >> Robert Haas <robertmh...@gmail.com> writes: >>> On Sat, Dec 28, 2019 at 2:02 PM Vik Fearing <vik.fear...@2ndquadrant.com> >>> wrote: >>>> I'm all for this (and even suggested it during the IRC conversation that >>>> prompted this patch). It's rife with bikeshedding, though. My original >>>> proposal was to use '&' and Andrew Gierth would have used ':'. >>> I think this is a good proposal regardless of which character we >>> decide to use. My order of preference from highest-to-lowest would >>> probably be :*&, but maybe that's just because I'm reading this on >>> Sunday rather than on Tuesday. >> I don't have any particular objection to '&' if people prefer that. > > I wrote the patch so I got to decide. :-) I will also volunteer to do > the grunt work of changing the symbol if consensus wants that, though. > > > It turns out that my original patch didn't really change, all the meat > is in the keywords patch. The superuser patch is to be applied on top > of the keywords patch. >
I missed a few places in the tap tests. New keywords patch attached, superuser patch unchanged. -- Vik Fearing
diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml index 55694c4368..add25b2b43 100644 --- a/doc/src/sgml/catalogs.sgml +++ b/doc/src/sgml/catalogs.sgml @@ -8953,8 +8953,8 @@ SCRAM-SHA-256$<replaceable><iteration count></replaceable>:<replaceable>&l <entry><structfield>text</structfield></entry> <entry> Host name or IP address, or one - of <literal>all</literal>, <literal>samehost</literal>, - or <literal>samenet</literal>, or null for local connections + of <literal>&all</literal>, <literal>&samehost</literal>, + or <literal>&samenet</literal>, or null for local connections </entry> </row> <row> diff --git a/doc/src/sgml/client-auth.sgml b/doc/src/sgml/client-auth.sgml index 5f1eec78fb..96fc4b01e9 100644 --- a/doc/src/sgml/client-auth.sgml +++ b/doc/src/sgml/client-auth.sgml @@ -81,11 +81,26 @@ A record is made up of a number of fields which are separated by spaces and/or tabs. Fields can contain white space if the field value is double-quoted. - Quoting one of the keywords in a database, user, or address field (e.g., - <literal>all</literal> or <literal>replication</literal>) makes the word lose its special - meaning, and just match a database, user, or host with that name. </para> + <note> + <para> + As of version 13, keywords are preceded by the character "&". + For compatibility, the following legacy keywords are still accepted + on their own: + <literal>all</literal>, <literal>replication</literal>, + <literal>samegroup</literal>, <literal>samehost</literal>, + <literal>samenet</literal>, <literal>samerole</literal>, + <literal>sameuser</literal>. + </para> + + <para> + Quoting one of these legacy keywords in a database, user, or address + field makes the word lose its special meaning, and just match a + database, user, or host with that name. + </para> + </note> + <para> Each record specifies a connection type, a client IP address range (if relevant for the connection type), a database name, a user name, @@ -221,18 +236,18 @@ hostnogssenc <replaceable>database</replaceable> <replaceable>user</replaceable <listitem> <para> Specifies which database name(s) this record matches. The value - <literal>all</literal> specifies that it matches all databases. - The value <literal>sameuser</literal> specifies that the record + <literal>&all</literal> specifies that it matches all databases. + The value <literal>&sameuser</literal> specifies that the record matches if the requested database has the same name as the - requested user. The value <literal>samerole</literal> specifies that + requested user. The value <literal>&samerole</literal> specifies that the requested user must be a member of the role with the same - name as the requested database. (<literal>samegroup</literal> is an - obsolete but still accepted spelling of <literal>samerole</literal>.) + name as the requested database. (<literal>&samegroup</literal> is an + obsolete but still accepted spelling of <literal>&samerole</literal>.) Superusers are not considered to be members of a role for the - purposes of <literal>samerole</literal> unless they are explicitly + purposes of <literal>&samerole</literal> unless they are explicitly members of the role, directly or indirectly, and not just by virtue of being a superuser. - The value <literal>replication</literal> specifies that the record + The value <literal>&replication</literal> specifies that the record matches if a physical replication connection is requested (note that replication connections do not specify any particular database). Otherwise, this is the name of @@ -249,7 +264,7 @@ hostnogssenc <replaceable>database</replaceable> <replaceable>user</replaceable <listitem> <para> Specifies which database user name(s) this record - matches. The value <literal>all</literal> specifies that it + matches. The value <literal>&all</literal> specifies that it matches all users. Otherwise, this is either the name of a specific database user, or a group name preceded by <literal>+</literal>. (Recall that there is no real distinction between users and groups @@ -312,9 +327,9 @@ hostnogssenc <replaceable>database</replaceable> <replaceable>user</replaceable </para> <para> - You can also write <literal>all</literal> to match any IP address, - <literal>samehost</literal> to match any of the server's own IP - addresses, or <literal>samenet</literal> to match any address in any + You can also write <literal>&all</literal> to match any IP address, + <literal>&samehost</literal> to match any of the server's own IP + addresses, or <literal>&samenet</literal> to match any address in any subnet that the server is directly connected to. </para> @@ -699,40 +714,40 @@ hostnogssenc <replaceable>database</replaceable> <replaceable>user</replaceable # connections). # # TYPE DATABASE USER ADDRESS METHOD -local all all trust +local &all &all trust # The same using local loopback TCP/IP connections. # # TYPE DATABASE USER ADDRESS METHOD -host all all 127.0.0.1/32 trust +host &all &all 127.0.0.1/32 trust # The same as the previous line, but using a separate netmask column # # TYPE DATABASE USER IP-ADDRESS IP-MASK METHOD -host all all 127.0.0.1 255.255.255.255 trust +host &all &all 127.0.0.1 255.255.255.255 trust # The same over IPv6. # # TYPE DATABASE USER ADDRESS METHOD -host all all ::1/128 trust +host &all &all ::1/128 trust # The same using a host name (would typically cover both IPv4 and IPv6). # # TYPE DATABASE USER ADDRESS METHOD -host all all localhost trust +host &all &all localhost trust # Allow any user from any host with IP address 192.168.93.x to connect # to database "postgres" as the same user name that ident reports for # the connection (typically the operating system user name). # # TYPE DATABASE USER ADDRESS METHOD -host postgres all 192.168.93.0/24 ident +host postgres &all 192.168.93.0/24 ident # Allow any user from host 192.168.12.10 to connect to database # "postgres" if the user's password is correctly supplied. # # TYPE DATABASE USER ADDRESS METHOD -host postgres all 192.168.12.10/32 scram-sha-256 +host postgres &all 192.168.12.10/32 scram-sha-256 # Allow any user from hosts in the example.com domain to connect to # any database if the user's password is correctly supplied. @@ -742,8 +757,8 @@ host postgres all 192.168.12.10/32 scram-sha-256 # authentication. # # TYPE DATABASE USER ADDRESS METHOD -host all mike .example.com md5 -host all all .example.com scram-sha-256 +host &all mike .example.com md5 +host &all &all .example.com scram-sha-256 # In the absence of preceding "host" lines, these three lines will # reject all connections from 192.168.54.1 (since that entry will be @@ -754,9 +769,9 @@ host all all .example.com scram-sha-256 # encrypted GSSAPI connections) are allowed, but only from 192.168.12.10. # # TYPE DATABASE USER ADDRESS METHOD -host all all 192.168.54.1/32 reject -hostgssenc all all 0.0.0.0/0 gss -host all all 192.168.12.10/32 gss +host &all &all 192.168.54.1/32 reject +hostgssenc &all &all 0.0.0.0/0 gss +host &all &all 192.168.12.10/32 gss # Allow users from 192.168.x.x hosts to connect to any database, if # they pass the ident check. If, for example, ident says the user is @@ -765,7 +780,7 @@ host all all 192.168.12.10/32 gss # "omicron" that says "bryanh" is allowed to connect as "guest1". # # TYPE DATABASE USER ADDRESS METHOD -host all all 192.168.0.0/16 ident map=omicron +host &all &all 192.168.0.0/16 ident map=omicron # If these are the only three lines for local connections, they will # allow local users to connect only to their own databases (databases @@ -775,15 +790,15 @@ host all all 192.168.0.0/16 ident map=omicro # are required in all cases. # # TYPE DATABASE USER ADDRESS METHOD -local sameuser all md5 -local all @admins md5 -local all +support md5 +local &sameuser &all md5 +local &all @admins md5 +local &all +support md5 # The last two lines above can be combined into a single line: -local all @admins,+support md5 +local &all @admins,+support md5 # The database column can also use lists and file names: -local db1,db2,@demodbs all md5 +local db1,db2,@demodbs &all md5 </programlisting> </example> </sect1> diff --git a/src/backend/libpq/hba.c b/src/backend/libpq/hba.c index b6de92783a..da18c389e5 100644 --- a/src/backend/libpq/hba.c +++ b/src/backend/libpq/hba.c @@ -64,8 +64,20 @@ typedef struct check_network_data bool result; /* set to true if match */ } check_network_data; +/* + * The following keywords are accepted without the keyword sigil for legacy + * reasons. They may become normal words at some point in the future. + */ +#define token_is_legacy_keyword(t, k) (!t->quoted && ( \ + strcmp(t->string, "all") == 0 || \ + strcmp(t->string, "replication") == 0 || \ + strcmp(t->string, "samegroup") == 0 || \ + strcmp(t->string, "samehost") == 0 || \ + strcmp(t->string, "samenet") == 0 || \ + strcmp(t->string, "samerole") == 0 || \ + strcmp(t->string, "sameuser") == 0)) -#define token_is_keyword(t, k) (!t->quoted && strcmp(t->string, k) == 0) +#define token_is_keyword(t, k) ((t->string[0] == '&' && strcmp(t->string+1, k) == 0) || token_is_legacy_keyword(t, k)) #define token_matches(t, k) (strcmp(t->string, k) == 0) /* @@ -2472,7 +2484,7 @@ fill_hba_line(Tuplestorestate *tuple_store, TupleDesc tupdesc, * Flatten HbaToken list to string list. It might seem that we * should re-quote any quoted tokens, but that has been rejected * on the grounds that it makes it harder to compare the array - * elements to other system catalogs. That makes entries like + * elements to other system catalogs. That makes entries with legacy keywords like * "all" or "samerole" formally ambiguous ... but users who name * databases/roles that way are inflicting their own pain. */ diff --git a/src/backend/libpq/pg_hba.conf.sample b/src/backend/libpq/pg_hba.conf.sample index c853e36232..d08aba497f 100644 --- a/src/backend/libpq/pg_hba.conf.sample +++ b/src/backend/libpq/pg_hba.conf.sample @@ -21,12 +21,12 @@ # "hostssl" is an SSL-encrypted TCP/IP socket, and "hostnossl" is a # plain TCP/IP socket. # -# DATABASE can be "all", "sameuser", "samerole", "replication", a -# database name, or a comma-separated list thereof. The "all" -# keyword does not match "replication". Access to replication +# DATABASE can be &all, &sameuser, &samerole, &replication, a +# database name, or a comma-separated list thereof. The &all +# keyword does not match &replication. Access to replication # must be enabled in a separate record (see example below). # -# USER can be "all", a user name, a group name prefixed with "+", or a +# USER can be &all, a user name, a group name prefixed with "+", or a # comma-separated list thereof. In both the DATABASE and USER fields # you can also write a file name prefixed with "@" to include names # from a separate file. @@ -53,11 +53,18 @@ # section in the documentation for a list of which options are # available for which authentication methods. # +# As of version 13, keywords are preceded by the character "&". +# For compatibility, the following legacy keywords are still accepted on +# their own: +# all, +# replication, +# sameuser, samegroup, samerole, +# samehost, samenet +# # Database and user names containing spaces, commas, quotes and other -# special characters must be quoted. Quoting one of the keywords -# "all", "sameuser", "samerole" or "replication" makes the name lose -# its special character, and just match a database or username with -# that name. +# special characters must be quoted. Quoting one of the legacy keywords +# from the previous paragraph makes the name lose its special character, +# and just match a database or username with that name. # # This file is read on server startup and when the server receives a # SIGHUP signal. If you edit the file on a running system, you have to @@ -77,13 +84,13 @@ # TYPE DATABASE USER ADDRESS METHOD @remove-line-for-nolocal@# "local" is for Unix domain socket connections only -@remove-line-for-nolocal@local all all @authmethodlocal@ +@remove-line-for-nolocal@local &all &all @authmethodlocal@ # IPv4 local connections: -host all all 127.0.0.1/32 @authmethodhost@ +host &all &all 127.0.0.1/32 @authmethodhost@ # IPv6 local connections: -host all all ::1/128 @authmethodhost@ +host &all &all ::1/128 @authmethodhost@ # Allow replication connections from localhost, by a user with the # replication privilege. -@remove-line-for-nolocal@local replication all @authmethodlocal@ -host replication all 127.0.0.1/32 @authmethodhost@ -host replication all ::1/128 @authmethodhost@ +@remove-line-for-nolocal@local &replication &all @authmethodlocal@ +host &replication &all 127.0.0.1/32 @authmethodhost@ +host &replication &all ::1/128 @authmethodhost@ diff --git a/src/test/authentication/t/001_password.pl b/src/test/authentication/t/001_password.pl index 5985130e3d..237a5ab53f 100644 --- a/src/test/authentication/t/001_password.pl +++ b/src/test/authentication/t/001_password.pl @@ -29,7 +29,7 @@ sub reset_pg_hba my $hba_method = shift; unlink($node->data_dir . '/pg_hba.conf'); - $node->append_conf('pg_hba.conf', "local all all $hba_method"); + $node->append_conf('pg_hba.conf', "local &all &all $hba_method"); $node->reload; return; } diff --git a/src/test/authentication/t/002_saslprep.pl b/src/test/authentication/t/002_saslprep.pl index c4b335c45f..8d54f60710 100644 --- a/src/test/authentication/t/002_saslprep.pl +++ b/src/test/authentication/t/002_saslprep.pl @@ -25,7 +25,7 @@ sub reset_pg_hba my $hba_method = shift; unlink($node->data_dir . '/pg_hba.conf'); - $node->append_conf('pg_hba.conf', "local all all $hba_method"); + $node->append_conf('pg_hba.conf', "local &all &all $hba_method"); $node->reload; return; } diff --git a/src/test/kerberos/t/001_auth.pl b/src/test/kerberos/t/001_auth.pl index e3eb052160..108fd70243 100644 --- a/src/test/kerberos/t/001_auth.pl +++ b/src/test/kerberos/t/001_auth.pl @@ -197,7 +197,7 @@ sub test_access unlink($node->data_dir . '/pg_hba.conf'); $node->append_conf('pg_hba.conf', - qq{host all all $hostaddr/32 gss map=mymap}); + qq{host &all &all $hostaddr/32 gss map=mymap}); $node->restart; test_access($node, 'test1', 'SELECT true', 2, '', 'fails without ticket'); @@ -233,7 +233,7 @@ test_access( unlink($node->data_dir . '/pg_hba.conf'); $node->append_conf('pg_hba.conf', - qq{hostgssenc all all $hostaddr/32 gss map=mymap}); + qq{hostgssenc &all &all $hostaddr/32 gss map=mymap}); $node->restart; test_access( @@ -255,7 +255,7 @@ test_access($node, "test1", 'SELECT true', 2, "gssencmode=disable", unlink($node->data_dir . '/pg_hba.conf'); $node->append_conf('pg_hba.conf', - qq{hostnogssenc all all $hostaddr/32 gss map=mymap}); + qq{hostnogssenc &all &all $hostaddr/32 gss map=mymap}); $node->restart; test_access( @@ -279,7 +279,7 @@ test_access( truncate($node->data_dir . '/pg_ident.conf', 0); unlink($node->data_dir . '/pg_hba.conf'); $node->append_conf('pg_hba.conf', - qq{host all all $hostaddr/32 gss include_realm=0}); + qq{host &all &all $hostaddr/32 gss include_realm=0}); $node->restart; test_access( diff --git a/src/test/ldap/t/001_auth.pl b/src/test/ldap/t/001_auth.pl index f8941144f5..f1eb2e8cfc 100644 --- a/src/test/ldap/t/001_auth.pl +++ b/src/test/ldap/t/001_auth.pl @@ -174,7 +174,7 @@ note "simple bind"; unlink($node->data_dir . '/pg_hba.conf'); $node->append_conf('pg_hba.conf', - qq{local all all ldap ldapserver=$ldap_server ldapport=$ldap_port ldapprefix="uid=" ldapsuffix=",dc=example,dc=net"} + qq{local &all &all ldap ldapserver=$ldap_server ldapport=$ldap_port ldapprefix="uid=" ldapsuffix=",dc=example,dc=net"} ); $node->restart; @@ -190,7 +190,7 @@ note "search+bind"; unlink($node->data_dir . '/pg_hba.conf'); $node->append_conf('pg_hba.conf', - qq{local all all ldap ldapserver=$ldap_server ldapport=$ldap_port ldapbasedn="$ldap_basedn"} + qq{local &all &all ldap ldapserver=$ldap_server ldapport=$ldap_port ldapbasedn="$ldap_basedn"} ); $node->restart; @@ -206,7 +206,7 @@ note "multiple servers"; unlink($node->data_dir . '/pg_hba.conf'); $node->append_conf('pg_hba.conf', - qq{local all all ldap ldapserver="$ldap_server $ldap_server" ldapport=$ldap_port ldapbasedn="$ldap_basedn"} + qq{local &all &all ldap ldapserver="$ldap_server $ldap_server" ldapport=$ldap_port ldapbasedn="$ldap_basedn"} ); $node->restart; @@ -222,7 +222,7 @@ note "LDAP URLs"; unlink($node->data_dir . '/pg_hba.conf'); $node->append_conf('pg_hba.conf', - qq{local all all ldap ldapurl="$ldap_url/$ldap_basedn?uid?sub"}); + qq{local &all &all ldap ldapurl="$ldap_url/$ldap_basedn?uid?sub"}); $node->restart; $ENV{"PGPASSWORD"} = 'wrong'; @@ -239,7 +239,7 @@ note "search filters"; unlink($node->data_dir . '/pg_hba.conf'); $node->append_conf('pg_hba.conf', - qq{local all all ldap ldapserver=$ldap_server ldapport=$ldap_port ldapbasedn="$ldap_basedn" ldapsearchfilter="(|(uid=\$username)(mail=\$username))"} + qq{local &all &all ldap ldapserver=$ldap_server ldapport=$ldap_port ldapbasedn="$ldap_basedn" ldapsearchfilter="(|(uid=\$username)(mail=\$username))"} ); $node->restart; @@ -252,7 +252,7 @@ note "search filters in LDAP URLs"; unlink($node->data_dir . '/pg_hba.conf'); $node->append_conf('pg_hba.conf', - qq{local all all ldap ldapurl="$ldap_url/$ldap_basedn??sub?(|(uid=\$username)(mail=\$username))"} + qq{local &all &all ldap ldapurl="$ldap_url/$ldap_basedn??sub?(|(uid=\$username)(mail=\$username))"} ); $node->restart; @@ -266,7 +266,7 @@ test_access($node, 'te...@example.net', 0, 'search filter finds by mail'); # override. It might be useful in a case like this. unlink($node->data_dir . '/pg_hba.conf'); $node->append_conf('pg_hba.conf', - qq{local all all ldap ldapurl="$ldap_url/$ldap_basedn??sub" ldapsearchfilter="(|(uid=\$username)(mail=\$username))"} + qq{local &all &all ldap ldapurl="$ldap_url/$ldap_basedn??sub" ldapsearchfilter="(|(uid=\$username)(mail=\$username))"} ); $node->restart; @@ -278,7 +278,7 @@ note "diagnostic message"; # note bad ldapprefix with a question mark that triggers a diagnostic message unlink($node->data_dir . '/pg_hba.conf'); $node->append_conf('pg_hba.conf', - qq{local all all ldap ldapserver=$ldap_server ldapport=$ldap_port ldapprefix="?uid=" ldapsuffix=""} + qq{local &all &all ldap ldapserver=$ldap_server ldapport=$ldap_port ldapprefix="?uid=" ldapsuffix=""} ); $node->restart; @@ -290,7 +290,7 @@ note "TLS"; # request StartTLS with ldaptls=1 unlink($node->data_dir . '/pg_hba.conf'); $node->append_conf('pg_hba.conf', - qq{local all all ldap ldapserver=$ldap_server ldapport=$ldap_port ldapbasedn="$ldap_basedn" ldapsearchfilter="(uid=\$username)" ldaptls=1} + qq{local &all &all ldap ldapserver=$ldap_server ldapport=$ldap_port ldapbasedn="$ldap_basedn" ldapsearchfilter="(uid=\$username)" ldaptls=1} ); $node->restart; @@ -300,7 +300,7 @@ test_access($node, 'test1', 0, 'StartTLS'); # request LDAPS with ldapscheme=ldaps unlink($node->data_dir . '/pg_hba.conf'); $node->append_conf('pg_hba.conf', - qq{local all all ldap ldapserver=$ldap_server ldapscheme=ldaps ldapport=$ldaps_port ldapbasedn="$ldap_basedn" ldapsearchfilter="(uid=\$username)"} + qq{local &all &all ldap ldapserver=$ldap_server ldapscheme=ldaps ldapport=$ldaps_port ldapbasedn="$ldap_basedn" ldapsearchfilter="(uid=\$username)"} ); $node->restart; @@ -310,7 +310,7 @@ test_access($node, 'test1', 0, 'LDAPS'); # request LDAPS with ldapurl=ldaps://... unlink($node->data_dir . '/pg_hba.conf'); $node->append_conf('pg_hba.conf', - qq{local all all ldap ldapurl="$ldaps_url/$ldap_basedn??sub?(uid=\$username)"} + qq{local &all &all ldap ldapurl="$ldaps_url/$ldap_basedn??sub?(uid=\$username)"} ); $node->restart; @@ -320,7 +320,7 @@ test_access($node, 'test1', 0, 'LDAPS with URL'); # bad combination of LDAPS and StartTLS unlink($node->data_dir . '/pg_hba.conf'); $node->append_conf('pg_hba.conf', - qq{local all all ldap ldapurl="$ldaps_url/$ldap_basedn??sub?(uid=\$username)" ldaptls=1} + qq{local &all &all ldap ldapurl="$ldaps_url/$ldap_basedn??sub?(uid=\$username)" ldaptls=1} ); $node->restart; diff --git a/src/test/perl/PostgresNode.pm b/src/test/perl/PostgresNode.pm index 270bd6c856..b39d8cf25a 100644 --- a/src/test/perl/PostgresNode.pm +++ b/src/test/perl/PostgresNode.pm @@ -390,7 +390,7 @@ sub set_replication_conf if ($TestLib::windows_os) { print $hba - "host replication all $test_localhost/32 sspi include_realm=1 map=regress\n"; + "host &replication &all $test_localhost/32 sspi include_realm=1 map=regress\n"; } close $hba; return; diff --git a/src/test/regress/pg_regress.c b/src/test/regress/pg_regress.c index 297b8fbd6f..650fe38767 100644 --- a/src/test/regress/pg_regress.c +++ b/src/test/regress/pg_regress.c @@ -1065,10 +1065,10 @@ config_sspi_auth(const char *pgdata, const char *superuser_name) exit(2); } CW(fputs("# Configuration written by config_sspi_auth()\n", hba) >= 0); - CW(fputs("host all all 127.0.0.1/32 sspi include_realm=1 map=regress\n", + CW(fputs("host &all &all 127.0.0.1/32 sspi include_realm=1 map=regress\n", hba) >= 0); if (have_ipv6) - CW(fputs("host all all ::1/128 sspi include_realm=1 map=regress\n", + CW(fputs("host &all &all ::1/128 sspi include_realm=1 map=regress\n", hba) >= 0); CW(fclose(hba) == 0);
diff --git a/doc/src/sgml/client-auth.sgml b/doc/src/sgml/client-auth.sgml index 96fc4b01e9..36cdf180c4 100644 --- a/doc/src/sgml/client-auth.sgml +++ b/doc/src/sgml/client-auth.sgml @@ -265,7 +265,11 @@ hostnogssenc <replaceable>database</replaceable> <replaceable>user</replaceable <para> Specifies which database user name(s) this record matches. The value <literal>&all</literal> specifies that it - matches all users. Otherwise, this is either the name of a specific + matches all users. + The value <literal>&superuser</literal> specifies that it matches all + superusers. The value <literal>&nonsuperuser</literal> specifies that it + matches no superusers. + Otherwise, this is either the name of a specific database user, or a group name preceded by <literal>+</literal>. (Recall that there is no real distinction between users and groups in <productname>PostgreSQL</productname>; a <literal>+</literal> mark really means diff --git a/src/backend/libpq/hba.c b/src/backend/libpq/hba.c index da18c389e5..087680be64 100644 --- a/src/backend/libpq/hba.c +++ b/src/backend/libpq/hba.c @@ -608,6 +608,16 @@ check_role(const char *role, Oid roleid, List *tokens) if (is_member(roleid, tok->string + 1)) return true; } + else if (token_is_keyword(tok, "superuser")) + { + if (superuser_arg(roleid)) + return true; + } + else if (token_is_keyword(tok, "nonsuperuser")) + { + if (!superuser_arg(roleid)) + return true; + } else if (token_matches(tok, role) || token_is_keyword(tok, "all")) return true;