diff --git a/doc/src/sgml/client-auth.sgml b/doc/src/sgml/client-auth.sgml index 38b13954ea..d2f30a47c4 100644 --- a/doc/src/sgml/client-auth.sgml +++ b/doc/src/sgml/client-auth.sgml @@ -1,4 +1,4 @@ - + Client Authentication @@ -75,13 +75,14 @@ The general format of the pg_hba.conf file is a set of records, one per line. Blank lines are ignored, as is any - text after the # comment character. A record is made + text after the # comment character. + Records cannot be continued across lines. + 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 quoted. - Quoting one of the keywords in database or username field (e.g "all" - or "replication") makes the name lose its special character, and just - match a database or username with that name. Records cannot be - continued across lines. + Quoting one of the keywords in a database or username field (e.g., + all or replication) makes the word lose its special + character, and just match a database or user with that name. @@ -185,7 +186,8 @@ hostnossl database user name as the requested database. (samegroup is an obsolete but still accepted spelling of samerole.) The value replication specifies that the record - matches if streaming replication is requested. + matches if a replication connection is requested (note that + replication connections do not specify any particular database). Otherwise, this is the name of a specific PostgreSQL database. Multiple database names can be supplied by separating them with @@ -241,7 +243,7 @@ hostnossl database user Typical examples of a CIDR-address are 172.20.143.89/32 for a single host, or 172.20.143.0/24 for a small network, or - 10.6.0.0/16 for a larger one. + 10.6.0.0/16 for a larger one. 0.0.0.0/0 (all balls) represents all addresses. To specify a single host, use a CIDR mask of 32 for IPv4 or 128 for IPv6. In a network address, do not omit trailing zeroes. diff --git a/doc/src/sgml/high-availability.sgml b/doc/src/sgml/high-availability.sgml index d2a8ea7799..766d223bd2 100644 --- a/doc/src/sgml/high-availability.sgml +++ b/doc/src/sgml/high-availability.sgml @@ -1,4 +1,4 @@ - + High Availability, Load Balancing, and Replication @@ -617,7 +617,7 @@ protocol to make nodes agree on a serializable transactional order. - Preparing Master for Standby Servers + Preparing the Master for Standby Servers 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. - If you want to use streaming replication, set up authentication to allow - streaming replication connections and set max_wal_senders in - the configuration file of the primary server. + If you want to use streaming replication, set up authentication on the + primary server to allow replication connections from the standby + server(s); that is, provide a suitable entry or entries in + pg_hba.conf with the database field set to + replication. Also ensure max_wal_senders is set + to a sufficiently large value in the configuration file of the primary + server. @@ -641,7 +645,7 @@ protocol to make nodes agree on a serializable transactional order. - Setting up the standby server + Setting Up a Standby Server 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. Do not use pg_standby or similar tools with the built-in standby mode described here. restore_command should return immediately - if the file does not exist, the server will retry the command again if + if the file does not exist; the server will retry the command again if necessary. See for using tools like pg_standby. @@ -776,22 +780,20 @@ trigger_file = '/path/to/trigger_file' Authentication - It is very important that the access privilege for replication be setup - properly so that only trusted users can read the WAL stream, because it is - easy to extract privileged information from it. + It is very important that the access privileges for replication be set up + so that only trusted users can read the WAL stream, because it is + easy to extract privileged information from it. Standby servers must + authenticate to the primary as a superuser account. + So a role with the SUPERUSER and LOGIN + privileges needs to be created on the primary. - Only the superuser is allowed to connect to the primary as the replication - standby. So a role with the SUPERUSER and LOGIN - privileges needs to be created in the primary. - - - Client authentication for replication is controlled by the + Client authentication for replication is controlled by a pg_hba.conf record specifying replication in the database field. For example, if the standby is running on host IP 192.168.1.100 and the superuser's name for replication is foo, the administrator can add the following line to the - pg_hba.conf file on the primary. + pg_hba.conf file on the primary: # 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 port 5432, the superuser's name for replication is foo, and the password is foopass, the administrator can add the following line to the recovery.conf file on the - standby. + standby: # The standby connects to the primary that is running on host 192.168.1.50 # and port 5432 as the user "foo" whose password is "foopass". primary_conninfo = 'host=192.168.1.50 port=5432 user=foo password=foopass' - - You do not need to specify database=replication in the - primary_conninfo. The required option will be added - automatically. If you mention the database parameter at all within - primary_conninfo then a FATAL error will be raised. @@ -1959,7 +1956,7 @@ mv /tmp/pg_control /path/to/backup/data/global pg_control contains the location where WAL replay will begin after restoring from the backup; backing it up first ensures that it points to the last restartpoint when the backup started, not - some later restartpoint that happened while files were copied to the + some later restartpoint that happened while files were copied to the backup. diff --git a/doc/src/sgml/recovery-config.sgml b/doc/src/sgml/recovery-config.sgml index 85d3b7eb3f..58fa5b0b10 100644 --- a/doc/src/sgml/recovery-config.sgml +++ b/doc/src/sgml/recovery-config.sgml @@ -1,4 +1,4 @@ - + Recovery Configuration @@ -10,12 +10,10 @@ - This chapter describes the settings available in - recovery.conf file. They apply only for the duration of - the recovery. (A sample file, share/recovery.conf.sample, - exists in the installation's share/ directory.) They must - be reset for any subsequent recovery you wish to perform. They cannot - be changed once recovery has begun. + This chapter describes the settings available in the + recovery.conf file. They apply only for the duration of the + recovery. They must be reset for any subsequent recovery you wish to + perform. They cannot be changed once recovery has begun. @@ -26,6 +24,11 @@ value, write two quotes (''). + + A sample file, share/recovery.conf.sample, + is provided in the installation's share/ directory. + + Archive recovery settings @@ -208,9 +211,10 @@ restore_command = 'copy "C:\\server\\archivedir\\%f" "%p"' # Windows Specifies whether to start the PostgreSQL server as a standby. If this parameter is on, the server will - not end recovery when the end of archived WAL is reached, but - will keep trying to continue recovery using restore_command - and by connecting to the primary server as specified by the + not stop recovery when the end of archived WAL is reached, but + will keep trying to continue recovery by fetching new WAL segments + using restore_command + and/or by connecting to the primary server as specified by the primary_conninfo setting. @@ -229,14 +233,19 @@ restore_command = 'copy "C:\\server\\archivedir\\%f" "%p"' # Windows defaults are used. - The built-in replication requires that a host name (or host address) - or port number which the primary server listens on be - specified in this string. Also ensure that a role with - the SUPERUSER and LOGIN privileges on the - primary is set (see - ). Note that - the password needs to be set if the primary demands password - authentication. + The connection string should specify the host name (or address) + of the primary server, as well as the port number if it is not + the same as the standby server's default. + Also specify a user name corresponding to a role that has the + SUPERUSER and LOGIN privileges on the + primary (see + ). + A password needs to be provided too, if the primary demands password + authentication. (The password can be provided either in + the primary_conninfo string or in a separate + ~/.pgpass file on the standby server.) + Do not specify a database name in the + primary_conninfo string. This setting has no effect if standby_mode is off. diff --git a/src/backend/libpq/auth.c b/src/backend/libpq/auth.c index ac26317d26..c4e234186e 100644 --- a/src/backend/libpq/auth.c +++ b/src/backend/libpq/auth.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/libpq/auth.c,v 1.199 2010/04/19 19:02:18 sriggs Exp $ + * $PostgreSQL: pgsql/src/backend/libpq/auth.c,v 1.200 2010/04/21 03:32:53 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -36,6 +36,7 @@ #include "libpq/pqformat.h" #include "libpq/md5.h" #include "miscadmin.h" +#include "replication/walsender.h" #include "storage/ipc.h" @@ -250,6 +251,7 @@ auth_failed(Port *port, int status) switch (port->hba->auth_method) { case uaReject: + case uaImplicitReject: errstr = gettext_noop("authentication failed for user \"%s\": host rejected"); break; case uaKrb5: @@ -363,12 +365,14 @@ ClientAuthentication(Port *port) case uaReject: /* - * An explicit "reject" entry in pg_hba.conf. Take pity on the poor - * user and issue a helpful error message. - * NOTE: this is not a security breach, because all the info - * reported here is known at the frontend and must be assumed - * known to bad guys. We're merely helping out the less clueful - * good guys. + * An explicit "reject" entry in pg_hba.conf. This report exposes + * the fact that there's an explicit reject entry, which is perhaps + * not so desirable from a security standpoint; but the message + * for an implicit reject could confuse the DBA a lot when the + * true situation is a match to an explicit reject. And we don't + * want to change the message for an implicit reject. As noted + * below, the additional information shown here doesn't expose + * anything not known to an attacker. */ { char hostinfo[NI_MAXHOST]; @@ -378,29 +382,50 @@ ClientAuthentication(Port *port) NULL, 0, NI_NUMERICHOST); + if (am_walsender) + { #ifdef USE_SSL - ereport(FATAL, - (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION), - errmsg("pg_hba.conf rejects host \"%s\", user \"%s\", database \"%s\", %s", - hostinfo, port->user_name, port->database_name, - port->ssl ? _("SSL on") : _("SSL off")))); + ereport(FATAL, + (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION), + errmsg("pg_hba.conf rejects replication connection for host \"%s\", user \"%s\", %s", + hostinfo, port->user_name, + port->ssl ? _("SSL on") : _("SSL off")))); #else - ereport(FATAL, - (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION), - errmsg("pg_hba.conf rejects host \"%s\", user \"%s\", database \"%s\"", - hostinfo, port->user_name, port->database_name))); + ereport(FATAL, + (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION), + errmsg("pg_hba.conf rejects replication connection for host \"%s\", user \"%s\"", + hostinfo, port->user_name))); #endif + } + else + { +#ifdef USE_SSL + ereport(FATAL, + (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION), + errmsg("pg_hba.conf rejects connection for host \"%s\", user \"%s\", database \"%s\", %s", + hostinfo, port->user_name, + port->database_name, + port->ssl ? _("SSL on") : _("SSL off")))); +#else + ereport(FATAL, + (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION), + errmsg("pg_hba.conf rejects connection for host \"%s\", user \"%s\", database \"%s\"", + hostinfo, port->user_name, + port->database_name))); +#endif + } break; } case uaImplicitReject: /* - * No matching entry so tell the user we fell through. - * NOTE: this is not a security breach, because all the info - * reported here is known at the frontend and must be assumed - * known to bad guys. We're merely helping out the less clueful - * good guys. + * No matching entry, so tell the user we fell through. + * + * NOTE: the extra info reported here is not a security breach, + * because all that info is known at the frontend and must be + * assumed known to bad guys. We're merely helping out the less + * clueful good guys. */ { char hostinfo[NI_MAXHOST]; @@ -410,18 +435,38 @@ ClientAuthentication(Port *port) NULL, 0, NI_NUMERICHOST); + if (am_walsender) + { #ifdef USE_SSL - ereport(FATAL, - (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION), - errmsg("no pg_hba.conf entry for host \"%s\", user \"%s\", database \"%s\", %s", - hostinfo, port->user_name, port->database_name, - port->ssl ? _("SSL on") : _("SSL off")))); + ereport(FATAL, + (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION), + errmsg("no pg_hba.conf entry for replication connection from host \"%s\", user \"%s\", %s", + hostinfo, port->user_name, + port->ssl ? _("SSL on") : _("SSL off")))); #else - ereport(FATAL, - (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION), - errmsg("no pg_hba.conf entry for host \"%s\", user \"%s\", database \"%s\"", - hostinfo, port->user_name, port->database_name))); + ereport(FATAL, + (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION), + errmsg("no pg_hba.conf entry for replication connection from host \"%s\", user \"%s\"", + hostinfo, port->user_name))); #endif + } + else + { +#ifdef USE_SSL + ereport(FATAL, + (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION), + errmsg("no pg_hba.conf entry for host \"%s\", user \"%s\", database \"%s\", %s", + hostinfo, port->user_name, + port->database_name, + port->ssl ? _("SSL on") : _("SSL off")))); +#else + ereport(FATAL, + (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION), + errmsg("no pg_hba.conf entry for host \"%s\", user \"%s\", database \"%s\"", + hostinfo, port->user_name, + port->database_name))); +#endif + } break; } diff --git a/src/backend/libpq/hba.c b/src/backend/libpq/hba.c index 11443f76e2..e5fb65f75d 100644 --- a/src/backend/libpq/hba.c +++ b/src/backend/libpq/hba.c @@ -10,7 +10,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/libpq/hba.c,v 1.205 2010/04/19 19:02:18 sriggs Exp $ + * $PostgreSQL: pgsql/src/backend/libpq/hba.c,v 1.206 2010/04/21 03:32:53 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -513,7 +513,13 @@ check_db(const char *dbname, const char *role, Oid roleid, char *param_str) tok != NULL; tok = strtok(NULL, MULTI_VALUE_SEP)) { - if (strcmp(tok, "all\n") == 0) + if (am_walsender) + { + /* walsender connections can only match replication keyword */ + if (strcmp(tok, "replication\n") == 0) + return true; + } + else if (strcmp(tok, "all\n") == 0) return true; else if (strcmp(tok, "sameuser\n") == 0) { @@ -526,9 +532,8 @@ check_db(const char *dbname, const char *role, Oid roleid, char *param_str) if (is_member(roleid, dbname)) return true; } - else if (strcmp(tok, "replication\n") == 0 && - am_walsender) - return true; + else if (strcmp(tok, "replication\n") == 0) + continue; /* never match this if not walsender */ else if (strcmp(tok, dbname) == 0) return true; } @@ -1812,7 +1817,7 @@ load_ident(void) * * Note that STATUS_ERROR indicates a problem with the hba config file. * If the file is OK but does not contain any entry matching the request, - * we return STATUS_OK and method = uaReject. + * we return STATUS_OK and method = uaImplicitReject. */ int hba_getauthmethod(hbaPort *port) diff --git a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c index d41858e49a..1807fde9e4 100644 --- a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c +++ b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c @@ -10,7 +10,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c,v 1.9 2010/04/19 14:10:45 mha Exp $ + * $PostgreSQL: pgsql/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c,v 1.10 2010/04/21 03:32:53 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -91,7 +91,7 @@ libpqrcv_connect(char *conninfo, XLogRecPtr startpoint) streamConn = PQconnectdb(conninfo_repl); if (PQstatus(streamConn) != CONNECTION_OK) ereport(ERROR, - (errmsg("could not connect to the primary server : %s", + (errmsg("could not connect to the primary server: %s", PQerrorMessage(streamConn)))); /*