Skip to content

Commit a2c3931

Browse files
committed
Fix pg_hba.conf matching so that replication connections only match records
with database = replication. The previous coding would allow them to match ordinary records too, but that seems like a recipe for security breaches. Improve the messages associated with no-such-pg_hba.conf entry to report replication connections as such, since that's now a critical aspect of whether the connection matches. Make some cursory improvements in the related documentation, too.
1 parent a3c6d10 commit a2c3931

File tree

6 files changed

+146
-88
lines changed

6 files changed

+146
-88
lines changed

doc/src/sgml/client-auth.sgml

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<!-- $PostgreSQL: pgsql/doc/src/sgml/client-auth.sgml,v 1.136 2010/04/03 07:22:53 petere Exp $ -->
1+
<!-- $PostgreSQL: pgsql/doc/src/sgml/client-auth.sgml,v 1.137 2010/04/21 03:32:53 tgl Exp $ -->
22

33
<chapter id="client-authentication">
44
<title>Client Authentication</title>
@@ -75,13 +75,14 @@
7575
<para>
7676
The general format of the <filename>pg_hba.conf</filename> file is
7777
a set of records, one per line. Blank lines are ignored, as is any
78-
text after the <literal>#</literal> comment character. A record is made
78+
text after the <literal>#</literal> comment character.
79+
Records cannot be continued across lines.
80+
A record is made
7981
up of a number of fields which are separated by spaces and/or tabs.
8082
Fields can contain white space if the field value is quoted.
81-
Quoting one of the keywords in database or username field (e.g "all"
82-
or "replication") makes the name lose its special character, and just
83-
match a database or username with that name. Records cannot be
84-
continued across lines.
83+
Quoting one of the keywords in a database or username field (e.g.,
84+
<literal>all</> or <literal>replication</>) makes the word lose its special
85+
character, and just match a database or user with that name.
8586
</para>
8687

8788
<para>
@@ -185,7 +186,8 @@ hostnossl <replaceable>database</replaceable> <replaceable>user</replaceable>
185186
name as the requested database. (<literal>samegroup</> is an
186187
obsolete but still accepted spelling of <literal>samerole</>.)
187188
The value <literal>replication</> specifies that the record
188-
matches if streaming replication is requested.
189+
matches if a replication connection is requested (note that
190+
replication connections do not specify any particular database).
189191
Otherwise, this is the name of
190192
a specific <productname>PostgreSQL</productname> database.
191193
Multiple database names can be supplied by separating them with
@@ -241,7 +243,7 @@ hostnossl <replaceable>database</replaceable> <replaceable>user</replaceable>
241243
Typical examples of a <replaceable>CIDR-address</replaceable> are
242244
<literal>172.20.143.89/32</literal> for a single host, or
243245
<literal>172.20.143.0/24</literal> for a small network, or
244-
<literal>10.6.0.0/16</literal> for a larger one.
246+
<literal>10.6.0.0/16</literal> for a larger one.
245247
<literal>0.0.0.0/0</literal> (<quote>all balls</>) represents all addresses.
246248
To specify a single host, use a CIDR mask of 32 for IPv4 or
247249
128 for IPv6. In a network address, do not omit trailing zeroes.

doc/src/sgml/high-availability.sgml

Lines changed: 21 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<!-- $PostgreSQL: pgsql/doc/src/sgml/high-availability.sgml,v 1.61 2010/04/20 11:15:06 rhaas Exp $ -->
1+
<!-- $PostgreSQL: pgsql/doc/src/sgml/high-availability.sgml,v 1.62 2010/04/21 03:32:53 tgl Exp $ -->
22

33
<chapter id="high-availability">
44
<title>High Availability, Load Balancing, and Replication</title>
@@ -617,7 +617,7 @@ protocol to make nodes agree on a serializable transactional order.
617617
</sect2>
618618

619619
<sect2 id="preparing-master-for-standby">
620-
<title>Preparing Master for Standby Servers</title>
620+
<title>Preparing the Master for Standby Servers</title>
621621

622622
<para>
623623
Set up continuous archiving on the primary to an archive directory
@@ -629,9 +629,13 @@ protocol to make nodes agree on a serializable transactional order.
629629
</para>
630630

631631
<para>
632-
If you want to use streaming replication, set up authentication to allow
633-
streaming replication connections and set <varname>max_wal_senders</> in
634-
the configuration file of the primary server.
632+
If you want to use streaming replication, set up authentication on the
633+
primary server to allow replication connections from the standby
634+
server(s); that is, provide a suitable entry or entries in
635+
<filename>pg_hba.conf</> with the database field set to
636+
<literal>replication</>. Also ensure <varname>max_wal_senders</> is set
637+
to a sufficiently large value in the configuration file of the primary
638+
server.
635639
</para>
636640

637641
<para>
@@ -641,7 +645,7 @@ protocol to make nodes agree on a serializable transactional order.
641645
</sect2>
642646

643647
<sect2 id="standby-server-setup">
644-
<title>Setting up the standby server</title>
648+
<title>Setting Up a Standby Server</title>
645649

646650
<para>
647651
To set up the standby server, restore the base backup taken from primary
@@ -656,7 +660,7 @@ protocol to make nodes agree on a serializable transactional order.
656660
<para>
657661
Do not use pg_standby or similar tools with the built-in standby mode
658662
described here. <varname>restore_command</> should return immediately
659-
if the file does not exist, the server will retry the command again if
663+
if the file does not exist; the server will retry the command again if
660664
necessary. See <xref linkend="log-shipping-alternative">
661665
for using tools like pg_standby.
662666
</para>
@@ -776,22 +780,20 @@ trigger_file = '/path/to/trigger_file'
776780
<sect3 id="streaming-replication-authentication">
777781
<title>Authentication</title>
778782
<para>
779-
It is very important that the access privilege for replication be setup
780-
properly so that only trusted users can read the WAL stream, because it is
781-
easy to extract privileged information from it.
783+
It is very important that the access privileges for replication be set up
784+
so that only trusted users can read the WAL stream, because it is
785+
easy to extract privileged information from it. Standby servers must
786+
authenticate to the primary as a superuser account.
787+
So a role with the <literal>SUPERUSER</> and <literal>LOGIN</>
788+
privileges needs to be created on the primary.
782789
</para>
783790
<para>
784-
Only the superuser is allowed to connect to the primary as the replication
785-
standby. So a role with the <literal>SUPERUSER</> and <literal>LOGIN</>
786-
privileges needs to be created in the primary.
787-
</para>
788-
<para>
789-
Client authentication for replication is controlled by the
791+
Client authentication for replication is controlled by a
790792
<filename>pg_hba.conf</> record specifying <literal>replication</> in the
791793
<replaceable>database</> field. For example, if the standby is running on
792794
host IP <literal>192.168.1.100</> and the superuser's name for replication
793795
is <literal>foo</>, the administrator can add the following line to the
794-
<filename>pg_hba.conf</> file on the primary.
796+
<filename>pg_hba.conf</> file on the primary:
795797

796798
<programlisting>
797799
# Allow the user "foo" from host 192.168.1.100 to connect to the primary
@@ -809,18 +811,13 @@ host replication foo 192.168.1.100/32 md5
809811
port <literal>5432</literal>, the superuser's name for replication is
810812
<literal>foo</>, and the password is <literal>foopass</>, the administrator
811813
can add the following line to the <filename>recovery.conf</> file on the
812-
standby.
814+
standby:
813815

814816
<programlisting>
815817
# The standby connects to the primary that is running on host 192.168.1.50
816818
# and port 5432 as the user "foo" whose password is "foopass".
817819
primary_conninfo = 'host=192.168.1.50 port=5432 user=foo password=foopass'
818820
</programlisting>
819-
820-
You do not need to specify <literal>database=replication</> in the
821-
<varname>primary_conninfo</varname>. The required option will be added
822-
automatically. If you mention the database parameter at all within
823-
<varname>primary_conninfo</varname> then a FATAL error will be raised.
824821
</para>
825822
</sect3>
826823

@@ -1959,7 +1956,7 @@ mv /tmp/pg_control /path/to/backup/data/global
19591956
<filename>pg_control</> contains the location where WAL replay will
19601957
begin after restoring from the backup; backing it up first ensures
19611958
that it points to the last restartpoint when the backup started, not
1962-
some later restartpoint that happened while files were copied to the
1959+
some later restartpoint that happened while files were copied to the
19631960
backup.
19641961
</para>
19651962
</listitem>

doc/src/sgml/recovery-config.sgml

Lines changed: 27 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<!-- $PostgreSQL: pgsql/doc/src/sgml/recovery-config.sgml,v 2.4 2010/04/07 10:58:49 heikki Exp $ -->
1+
<!-- $PostgreSQL: pgsql/doc/src/sgml/recovery-config.sgml,v 2.5 2010/04/21 03:32:53 tgl Exp $ -->
22

33
<chapter Id="recovery-config">
44
<title>Recovery Configuration</title>
@@ -10,12 +10,10 @@
1010
</indexterm>
1111

1212
<para>
13-
This chapter describes the settings available in
14-
<filename>recovery.conf</> file. They apply only for the duration of
15-
the recovery. (A sample file, <filename>share/recovery.conf.sample</>,
16-
exists in the installation's <filename>share/</> directory.) They must
17-
be reset for any subsequent recovery you wish to perform. They cannot
18-
be changed once recovery has begun.
13+
This chapter describes the settings available in the
14+
<filename>recovery.conf</> file. They apply only for the duration of the
15+
recovery. They must be reset for any subsequent recovery you wish to
16+
perform. They cannot be changed once recovery has begun.
1917
</para>
2018

2119
<para>
@@ -26,6 +24,11 @@
2624
value, write two quotes (<literal>''</>).
2725
</para>
2826

27+
<para>
28+
A sample file, <filename>share/recovery.conf.sample</>,
29+
is provided in the installation's <filename>share/</> directory.
30+
</para>
31+
2932
<sect1 id="archive-recovery-settings">
3033

3134
<title>Archive recovery settings</title>
@@ -208,9 +211,10 @@ restore_command = 'copy "C:\\server\\archivedir\\%f" "%p"' # Windows
208211
<para>
209212
Specifies whether to start the <productname>PostgreSQL</> server as
210213
a standby. If this parameter is <literal>on</>, the server will
211-
not end recovery when the end of archived WAL is reached, but
212-
will keep trying to continue recovery using <varname>restore_command</>
213-
and by connecting to the primary server as specified by the
214+
not stop recovery when the end of archived WAL is reached, but
215+
will keep trying to continue recovery by fetching new WAL segments
216+
using <varname>restore_command</>
217+
and/or by connecting to the primary server as specified by the
214218
<varname>primary_conninfo</> setting.
215219
</para>
216220
</listitem>
@@ -229,14 +233,19 @@ restore_command = 'copy "C:\\server\\archivedir\\%f" "%p"' # Windows
229233
defaults are used.
230234
</para>
231235
<para>
232-
The built-in replication requires that a host name (or host address)
233-
or port number which the primary server listens on be
234-
specified in this string. Also ensure that a role with
235-
the <literal>SUPERUSER</> and <literal>LOGIN</> privileges on the
236-
primary is set (see
237-
<xref linkend="streaming-replication-authentication">). Note that
238-
the password needs to be set if the primary demands password
239-
authentication.
236+
The connection string should specify the host name (or address)
237+
of the primary server, as well as the port number if it is not
238+
the same as the standby server's default.
239+
Also specify a user name corresponding to a role that has the
240+
<literal>SUPERUSER</> and <literal>LOGIN</> privileges on the
241+
primary (see
242+
<xref linkend="streaming-replication-authentication">).
243+
A password needs to be provided too, if the primary demands password
244+
authentication. (The password can be provided either in
245+
the <varname>primary_conninfo</varname> string or in a separate
246+
<filename>~/.pgpass</> file on the standby server.)
247+
Do not specify a database name in the
248+
<varname>primary_conninfo</varname> string.
240249
</para>
241250
<para>
242251
This setting has no effect if <varname>standby_mode</> is <literal>off</>.

src/backend/libpq/auth.c

Lines changed: 75 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/libpq/auth.c,v 1.199 2010/04/19 19:02:18 sriggs Exp $
11+
* $PostgreSQL: pgsql/src/backend/libpq/auth.c,v 1.200 2010/04/21 03:32:53 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -36,6 +36,7 @@
3636
#include "libpq/pqformat.h"
3737
#include "libpq/md5.h"
3838
#include "miscadmin.h"
39+
#include "replication/walsender.h"
3940
#include "storage/ipc.h"
4041

4142

@@ -250,6 +251,7 @@ auth_failed(Port *port, int status)
250251
switch (port->hba->auth_method)
251252
{
252253
case uaReject:
254+
case uaImplicitReject:
253255
errstr = gettext_noop("authentication failed for user \"%s\": host rejected");
254256
break;
255257
case uaKrb5:
@@ -363,12 +365,14 @@ ClientAuthentication(Port *port)
363365
case uaReject:
364366

365367
/*
366-
* An explicit "reject" entry in pg_hba.conf. Take pity on the poor
367-
* user and issue a helpful error message.
368-
* NOTE: this is not a security breach, because all the info
369-
* reported here is known at the frontend and must be assumed
370-
* known to bad guys. We're merely helping out the less clueful
371-
* good guys.
368+
* An explicit "reject" entry in pg_hba.conf. This report exposes
369+
* the fact that there's an explicit reject entry, which is perhaps
370+
* not so desirable from a security standpoint; but the message
371+
* for an implicit reject could confuse the DBA a lot when the
372+
* true situation is a match to an explicit reject. And we don't
373+
* want to change the message for an implicit reject. As noted
374+
* below, the additional information shown here doesn't expose
375+
* anything not known to an attacker.
372376
*/
373377
{
374378
char hostinfo[NI_MAXHOST];
@@ -378,29 +382,50 @@ ClientAuthentication(Port *port)
378382
NULL, 0,
379383
NI_NUMERICHOST);
380384

385+
if (am_walsender)
386+
{
381387
#ifdef USE_SSL
382-
ereport(FATAL,
383-
(errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
384-
errmsg("pg_hba.conf rejects host \"%s\", user \"%s\", database \"%s\", %s",
385-
hostinfo, port->user_name, port->database_name,
386-
port->ssl ? _("SSL on") : _("SSL off"))));
388+
ereport(FATAL,
389+
(errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
390+
errmsg("pg_hba.conf rejects replication connection for host \"%s\", user \"%s\", %s",
391+
hostinfo, port->user_name,
392+
port->ssl ? _("SSL on") : _("SSL off"))));
387393
#else
388-
ereport(FATAL,
389-
(errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
390-
errmsg("pg_hba.conf rejects host \"%s\", user \"%s\", database \"%s\"",
391-
hostinfo, port->user_name, port->database_name)));
394+
ereport(FATAL,
395+
(errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
396+
errmsg("pg_hba.conf rejects replication connection for host \"%s\", user \"%s\"",
397+
hostinfo, port->user_name)));
392398
#endif
399+
}
400+
else
401+
{
402+
#ifdef USE_SSL
403+
ereport(FATAL,
404+
(errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
405+
errmsg("pg_hba.conf rejects connection for host \"%s\", user \"%s\", database \"%s\", %s",
406+
hostinfo, port->user_name,
407+
port->database_name,
408+
port->ssl ? _("SSL on") : _("SSL off"))));
409+
#else
410+
ereport(FATAL,
411+
(errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
412+
errmsg("pg_hba.conf rejects connection for host \"%s\", user \"%s\", database \"%s\"",
413+
hostinfo, port->user_name,
414+
port->database_name)));
415+
#endif
416+
}
393417
break;
394418
}
395419

396420
case uaImplicitReject:
397421

398422
/*
399-
* No matching entry so tell the user we fell through.
400-
* NOTE: this is not a security breach, because all the info
401-
* reported here is known at the frontend and must be assumed
402-
* known to bad guys. We're merely helping out the less clueful
403-
* good guys.
423+
* No matching entry, so tell the user we fell through.
424+
*
425+
* NOTE: the extra info reported here is not a security breach,
426+
* because all that info is known at the frontend and must be
427+
* assumed known to bad guys. We're merely helping out the less
428+
* clueful good guys.
404429
*/
405430
{
406431
char hostinfo[NI_MAXHOST];
@@ -410,18 +435,38 @@ ClientAuthentication(Port *port)
410435
NULL, 0,
411436
NI_NUMERICHOST);
412437

438+
if (am_walsender)
439+
{
413440
#ifdef USE_SSL
414-
ereport(FATAL,
415-
(errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
416-
errmsg("no pg_hba.conf entry for host \"%s\", user \"%s\", database \"%s\", %s",
417-
hostinfo, port->user_name, port->database_name,
418-
port->ssl ? _("SSL on") : _("SSL off"))));
441+
ereport(FATAL,
442+
(errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
443+
errmsg("no pg_hba.conf entry for replication connection from host \"%s\", user \"%s\", %s",
444+
hostinfo, port->user_name,
445+
port->ssl ? _("SSL on") : _("SSL off"))));
419446
#else
420-
ereport(FATAL,
421-
(errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
422-
errmsg("no pg_hba.conf entry for host \"%s\", user \"%s\", database \"%s\"",
423-
hostinfo, port->user_name, port->database_name)));
447+
ereport(FATAL,
448+
(errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
449+
errmsg("no pg_hba.conf entry for replication connection from host \"%s\", user \"%s\"",
450+
hostinfo, port->user_name)));
451+
#endif
452+
}
453+
else
454+
{
455+
#ifdef USE_SSL
456+
ereport(FATAL,
457+
(errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
458+
errmsg("no pg_hba.conf entry for host \"%s\", user \"%s\", database \"%s\", %s",
459+
hostinfo, port->user_name,
460+
port->database_name,
461+
port->ssl ? _("SSL on") : _("SSL off"))));
462+
#else
463+
ereport(FATAL,
464+
(errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
465+
errmsg("no pg_hba.conf entry for host \"%s\", user \"%s\", database \"%s\"",
466+
hostinfo, port->user_name,
467+
port->database_name)));
424468
#endif
469+
}
425470
break;
426471
}
427472

0 commit comments

Comments
 (0)