Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commite3f99e0

Browse files
committed
Fix libpq's code for searching .pgpass; rationalize empty-list-item cases.
Before v10, we always searched ~/.pgpass using the host parameter,and nothing else, to match to the "hostname" field of ~/.pgpass.(However, null host or host matching DEFAULT_PGSOCKET_DIR was replaced by"localhost".) In v10, this got broken by commit274bb2b, repaired bycommitbdac983, and broken again by commit7b02ba6; in the codeactually shipped, we'd search with hostaddr if both that and host werespecified --- though oddly, *not* if only hostaddr were specified.Since this is directly contrary to the documentation, and notbackwards-compatible, it's clearly a bug.However, the change wasn't totally without justification, even though itwasn't done quite right, because the pre-v10 behavior has arguably beenbuggy since we added hostaddr. If hostaddr is specified and host isn't,the pre-v10 code will search ~/.pgpass for "localhost", and ship thatpassword off to a server that most likely isn't local at all. That'sunhelpful at best, and could be a security breach at worst.Therefore, rather than just revert to that old behavior, let's definethe behavior as "search with host if provided, else with hostaddr ifprovided, else search for localhost". (As before, a host name matchingDEFAULT_PGSOCKET_DIR is replaced by localhost.) This matches thebehavior of the actual connection code, so that we don't pick up aninappropriate password; and it allows useful searches to happen whenonly hostaddr is given.While we're messing around here, ensure that empty elements within ahost or hostaddr list select the same behavior as a totally-emptyfield would; for instance "host=a,,b" is equivalent to "host=a,/tmp,b"if DEFAULT_PGSOCKET_DIR is /tmp. Things worked that way in some casesalready, but not consistently so, which contributed to the confusionabout what key ~/.pgpass would get searched with.Update documentation accordingly, and also clarify some nearby text.Back-patch to v10 where the host/hostaddr list functionality wasintroduced.Discussion:https://postgr.es/m/30805.1532749137@sss.pgh.pa.us
1 parente80f2b3 commite3f99e0

File tree

2 files changed

+84
-56
lines changed

2 files changed

+84
-56
lines changed

‎doc/src/sgml/libpq.sgml

Lines changed: 38 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -938,8 +938,8 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname
938938
<para>
939939
If a password file is used, you can have different passwords for
940940
different hosts. All the other connection options are the same for every
941-
host,it is not possible to e.g. specifyadifferent username for
942-
different hosts.
941+
host in the list;it is not possible to e.g. specify different
942+
usernames fordifferent hosts.
943943
</para>
944944
</sect3>
945945
</sect2>
@@ -961,15 +961,16 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname
961961
name of the directory in which the socket file is stored. If
962962
multiple host names are specified, each will be tried in turn in
963963
the order given. The default behavior when <literal>host</literal> is
964-
not specified is to connect to a Unix-domain
964+
not specified, or is empty, is to connect to a Unix-domain
965965
socket<indexterm><primary>Unix domain socket</primary></indexterm> in
966966
<filename>/tmp</filename> (or whatever socket directory was specified
967967
when <productname>PostgreSQL</productname> was built). On machines without
968968
Unix-domain sockets, the default is to connect to <literal>localhost</literal>.
969969
</para>
970970
<para>
971971
A comma-separated list of host names is also accepted, in which case
972-
each host name in the list is tried in order. See
972+
each host name in the list is tried in order; an empty item in the
973+
list selects the default behavior as explained above. See
973974
<xref linkend="libpq-multiple-hosts"/> for details.
974975
</para>
975976
</listitem>
@@ -1020,14 +1021,17 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname
10201021
</itemizedlist>
10211022
Note that authentication is likely to fail if <literal>host</literal>
10221023
is not the name of the server at network address <literal>hostaddr</literal>.
1023-
Also, note that <literal>host</literal> rather than <literal>hostaddr</literal>
1024+
Also, when both <literal>host</literal> and <literal>hostaddr</literal>
1025+
are specified, <literal>host</literal>
10241026
is used to identify the connection in a password file (see
10251027
<xref linkend="libpq-pgpass"/>).
10261028
</para>
10271029

10281030
<para>
10291031
A comma-separated list of <literal>hostaddr</literal> values is also
1030-
accepted, in which case each host in the list is tried in order. See
1032+
accepted, in which case each host in the list is tried in order.
1033+
An empty item in the list causes the corresponding host name to be
1034+
used, or the default host name if that is empty as well. See
10311035
<xref linkend="libpq-multiple-hosts"/> for details.
10321036
</para>
10331037
<para>
@@ -1047,9 +1051,12 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname
10471051
name extension for Unix-domain
10481052
connections.<indexterm><primary>port</primary></indexterm>
10491053
If multiple hosts were given in the <literal>host</literal> or
1050-
<literal>hostaddr</literal> parameters, this parameter may specify a list
1051-
of ports of equal length, or it may specify a single port number to
1052-
be used for all hosts.
1054+
<literal>hostaddr</literal> parameters, this parameter may specify a
1055+
comma-separated list of ports of the same length as the host list, or
1056+
it may specify a single port number to be used for all hosts.
1057+
An empty string, or an empty item in a comma-separated list,
1058+
specifies the default port number established
1059+
when <productname>PostgreSQL</productname> was built.
10531060
</para>
10541061
</listitem>
10551062
</varlistentry>
@@ -1683,6 +1690,17 @@ char *PQuser(const PGconn *conn);
16831690
char *PQpass(const PGconn *conn);
16841691
</synopsis>
16851692
</para>
1693+
1694+
<para>
1695+
<function>PQpass</function> will return either the password specified
1696+
in the connection parameters, or if there was none and the password
1697+
was obtained from the <link linkend="libpq-pgpass">password
1698+
file</link>, it will return that. In the latter case,
1699+
if multiple hosts were specified in the connection parameters, it is
1700+
not possible to rely on the result of <function>PQpass</function> until
1701+
the connection is established. The status of the connection can be
1702+
checked using the function <function>PQstatus</function>.
1703+
</para>
16861704
</listitem>
16871705
</varlistentry>
16881706

@@ -7521,13 +7539,18 @@ myEventProc(PGEventId evtId, void *evtInfo, void *passThrough)
75217539
used. (Therefore, put more-specific entries first when you are using
75227540
wildcards.) If an entry needs to contain <literal>:</literal> or
75237541
<literal>\</literal>, escape this character with <literal>\</literal>.
7524-
A host name of <literal>localhost</literal> matches both TCP (host name
7525-
<literal>localhost</literal>) and Unix domain socket (<literal>pghost</literal> empty
7526-
or the default socket directory) connections coming from the local
7527-
machine. In a standby server, a database name of <literal>replication</literal>
7542+
The host name field is matched to the <literal>host</literal> connection
7543+
parameter if that is specified, otherwise to
7544+
the <literal>hostaddr</literal> parameter if that is specified; if neither
7545+
are given then the host name <literal>localhost</literal> is searched for.
7546+
The host name <literal>localhost</literal> is also searched for when
7547+
the connection is a Unix-domain socket connection and
7548+
the <literal>host</literal> parameter
7549+
matches <application>libpq</application>'s default socket directory path.
7550+
In a standby server, a database field of <literal>replication</literal>
75287551
matches streaming replication connections made to the master server.
7529-
The<literal>database</literal> field is of limited usefulness because
7530-
users havethe same password for all databases in the same cluster.
7552+
The database field is of limited usefulnessotherwise,because users have
7553+
the same password for all databases in the same cluster.
75317554
</para>
75327555

75337556
<para>

‎src/interfaces/libpq/fe-connect.c

Lines changed: 46 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -901,6 +901,8 @@ parse_comma_separated_list(char **startptr, bool *more)
901901
staticbool
902902
connectOptions2(PGconn*conn)
903903
{
904+
inti;
905+
904906
/*
905907
* Allocate memory for details about each host to which we might possibly
906908
* try to connect. For that, count the number of elements in the hostaddr
@@ -920,11 +922,10 @@ connectOptions2(PGconn *conn)
920922

921923
/*
922924
* We now have one pg_conn_host structure per possible host. Fill in the
923-
* hostdetailsfor each one.
925+
* hostand hostaddr fieldsfor each, by splitting the parameter strings.
924926
*/
925927
if (conn->pghostaddr!=NULL&&conn->pghostaddr[0]!='\0')
926928
{
927-
inti;
928929
char*s=conn->pghostaddr;
929930
boolmore= true;
930931

@@ -933,8 +934,6 @@ connectOptions2(PGconn *conn)
933934
conn->connhost[i].hostaddr=parse_comma_separated_list(&s,&more);
934935
if (conn->connhost[i].hostaddr==NULL)
935936
gotooom_error;
936-
937-
conn->connhost[i].type=CHT_HOST_ADDRESS;
938937
}
939938

940939
/*
@@ -948,7 +947,6 @@ connectOptions2(PGconn *conn)
948947

949948
if (conn->pghost!=NULL&&conn->pghost[0]!='\0')
950949
{
951-
inti;
952950
char*s=conn->pghost;
953951
boolmore= true;
954952

@@ -957,17 +955,9 @@ connectOptions2(PGconn *conn)
957955
conn->connhost[i].host=parse_comma_separated_list(&s,&more);
958956
if (conn->connhost[i].host==NULL)
959957
gotooom_error;
960-
961-
/* Identify the type of host. */
962-
if (conn->pghostaddr==NULL||conn->pghostaddr[0]=='\0')
963-
{
964-
conn->connhost[i].type=CHT_HOST_NAME;
965-
#ifdefHAVE_UNIX_SOCKETS
966-
if (is_absolute_path(conn->connhost[i].host))
967-
conn->connhost[i].type=CHT_UNIX_SOCKET;
968-
#endif
969-
}
970958
}
959+
960+
/* Check for wrong number of host items. */
971961
if (more||i!=conn->nconnhost)
972962
{
973963
conn->status=CONNECTION_BAD;
@@ -979,29 +969,48 @@ connectOptions2(PGconn *conn)
979969
}
980970

981971
/*
982-
* If neither host or hostaddr options was given, connect to default host.
972+
* Now, for each host slot, identify the type of address spec, and fill in
973+
* the default address if nothing was given.
983974
*/
984-
if ((conn->pghostaddr==NULL||conn->pghostaddr[0]=='\0')&&
985-
(conn->pghost==NULL||conn->pghost[0]=='\0'))
975+
for (i=0;i<conn->nconnhost;i++)
986976
{
987-
Assert(conn->nconnhost==1);
977+
pg_conn_host*ch=&conn->connhost[i];
978+
979+
if (ch->hostaddr!=NULL&&ch->hostaddr[0]!='\0')
980+
ch->type=CHT_HOST_ADDRESS;
981+
elseif (ch->host!=NULL&&ch->host[0]!='\0')
982+
{
983+
ch->type=CHT_HOST_NAME;
988984
#ifdefHAVE_UNIX_SOCKETS
989-
conn->connhost[0].host=strdup(DEFAULT_PGSOCKET_DIR);
990-
conn->connhost[0].type=CHT_UNIX_SOCKET;
985+
if (is_absolute_path(ch->host))
986+
ch->type=CHT_UNIX_SOCKET;
987+
#endif
988+
}
989+
else
990+
{
991+
if (ch->host)
992+
free(ch->host);
993+
#ifdefHAVE_UNIX_SOCKETS
994+
ch->host=strdup(DEFAULT_PGSOCKET_DIR);
995+
ch->type=CHT_UNIX_SOCKET;
991996
#else
992-
conn->connhost[0].host=strdup(DefaultHost);
993-
conn->connhost[0].type=CHT_HOST_NAME;
997+
ch->host=strdup(DefaultHost);
998+
ch->type=CHT_HOST_NAME;
994999
#endif
995-
if (conn->connhost[0].host==NULL)
996-
gotooom_error;
1000+
if (ch->host==NULL)
1001+
gotooom_error;
1002+
}
9971003
}
9981004

9991005
/*
10001006
* Next, work out the port number corresponding to each host name.
1007+
*
1008+
* Note: unlike the above for host names, this could leave the port fields
1009+
* as null or empty strings. We will substitute DEF_PGPORT whenever we
1010+
* read such a port field.
10011011
*/
10021012
if (conn->pgport!=NULL&&conn->pgport[0]!='\0')
10031013
{
1004-
inti;
10051014
char*s=conn->pgport;
10061015
boolmore= true;
10071016

@@ -1065,8 +1074,8 @@ connectOptions2(PGconn *conn)
10651074
}
10661075

10671076
/*
1068-
*Supply defaultpasswordif none given. Note that thepasswordmight be
1069-
* different for each host/port pair.
1077+
*Ifpasswordwas not given, try to look it up inpasswordfile. Note
1078+
*that the result might bedifferent for each host/port pair.
10701079
*/
10711080
if (conn->pgpass==NULL||conn->pgpass[0]=='\0')
10721081
{
@@ -1089,20 +1098,16 @@ connectOptions2(PGconn *conn)
10891098

10901099
if (conn->pgpassfile!=NULL&&conn->pgpassfile[0]!='\0')
10911100
{
1092-
inti;
1093-
10941101
for (i=0;i<conn->nconnhost;i++)
10951102
{
10961103
/*
1097-
* Try to get a password for this host frompgpassfile.We use
1098-
*host name rather than host address in the same manner as
1099-
*PQhost().
1104+
* Try to get a password for this host fromfile.We use host
1105+
*for the hostname search key if given, else hostaddr (at
1106+
*least one of them is guaranteed nonempty by now).
11001107
*/
1101-
char*pwhost=conn->connhost[i].host;
1108+
constchar*pwhost=conn->connhost[i].host;
11021109

1103-
if (conn->connhost[i].type==CHT_HOST_ADDRESS&&
1104-
conn->connhost[i].host!=NULL&&
1105-
conn->connhost[i].host[0]!='\0')
1110+
if (pwhost==NULL||pwhost[0]=='\0')
11061111
pwhost=conn->connhost[i].hostaddr;
11071112

11081113
conn->connhost[i].password=
@@ -6385,14 +6390,14 @@ passwordFromFile(const char *hostname, const char *port, const char *dbname,
63856390
#defineLINELEN NAMEDATALEN*5
63866391
charbuf[LINELEN];
63876392

6388-
if (dbname==NULL||strlen(dbname)==0)
6393+
if (dbname==NULL||dbname[0]=='\0')
63896394
returnNULL;
63906395

6391-
if (username==NULL||strlen(username)==0)
6396+
if (username==NULL||username[0]=='\0')
63926397
returnNULL;
63936398

63946399
/* 'localhost' matches pghost of '' or the default socket directory */
6395-
if (hostname==NULL)
6400+
if (hostname==NULL||hostname[0]=='\0')
63966401
hostname=DefaultHost;
63976402
elseif (is_absolute_path(hostname))
63986403

@@ -6403,7 +6408,7 @@ passwordFromFile(const char *hostname, const char *port, const char *dbname,
64036408
if (strcmp(hostname,DEFAULT_PGSOCKET_DIR)==0)
64046409
hostname=DefaultHost;
64056410

6406-
if (port==NULL)
6411+
if (port==NULL||port[0]=='\0')
64076412
port=DEF_PGPORT_STR;
64086413

64096414
/* If password file cannot be opened, ignore it. */

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp