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

Commit71e3b28

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 parentd8dd8d2 commit71e3b28

File tree

2 files changed

+83
-55
lines changed

2 files changed

+83
-55
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</></> in
966966
<filename>/tmp</filename> (or whatever socket directory was specified
967967
when <productname>PostgreSQL</> was built). On machines without
968968
Unix-domain sockets, the default is to connect to <literal>localhost</>.
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</>
10221023
is not the name of the server at network address <literal>hostaddr</>.
1023-
Also, note that <literal>host</> rather than <literal>hostaddr</>
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</></>
10491053
If multiple hosts were given in the <literal>host</literal> or
1050-
<literal>hostaddr</> 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>
@@ -1588,6 +1595,17 @@ char *PQuser(const PGconn *conn);
15881595
char *PQpass(const PGconn *conn);
15891596
</synopsis>
15901597
</para>
1598+
1599+
<para>
1600+
<function>PQpass</function> will return either the password specified
1601+
in the connection parameters, or if there was none and the password
1602+
was obtained from the <link linkend="libpq-pgpass">password
1603+
file</link>, it will return that. In the latter case,
1604+
if multiple hosts were specified in the connection parameters, it is
1605+
not possible to rely on the result of <function>PQpass</function> until
1606+
the connection is established. The status of the connection can be
1607+
checked using the function <function>PQstatus</function>.
1608+
</para>
15911609
</listitem>
15921610
</varlistentry>
15931611

@@ -7380,13 +7398,18 @@ myEventProc(PGEventId evtId, void *evtInfo, void *passThrough)
73807398
used. (Therefore, put more-specific entries first when you are using
73817399
wildcards.) If an entry needs to contain <literal>:</literal> or
73827400
<literal>\</literal>, escape this character with <literal>\</literal>.
7383-
A host name of <literal>localhost</> matches both TCP (host name
7384-
<literal>localhost</>) and Unix domain socket (<literal>pghost</> empty
7385-
or the default socket directory) connections coming from the local
7386-
machine. In a standby server, a database name of <literal>replication</>
7401+
The host name field is matched to the <literal>host</literal> connection
7402+
parameter if that is specified, otherwise to
7403+
the <literal>hostaddr</literal> parameter if that is specified; if neither
7404+
are given then the host name <literal>localhost</literal> is searched for.
7405+
The host name <literal>localhost</literal> is also searched for when
7406+
the connection is a Unix-domain socket connection and
7407+
the <literal>host</literal> parameter
7408+
matches <application>libpq</application>'s default socket directory path.
7409+
In a standby server, a database field of <literal>replication</literal>
73877410
matches streaming replication connections made to the master server.
7388-
The<literal>database</> field is of limited usefulness because
7389-
users havethe same password for all databases in the same cluster.
7411+
The database field is of limited usefulnessotherwise,because users have
7412+
the same password for all databases in the same cluster.
73907413
</para>
73917414

73927415
<para>

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

Lines changed: 45 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -894,6 +894,8 @@ parse_comma_separated_list(char **startptr, bool *more)
894894
staticbool
895895
connectOptions2(PGconn*conn)
896896
{
897+
inti;
898+
897899
/*
898900
* Allocate memory for details about each host to which we might possibly
899901
* try to connect. For that, count the number of elements in the hostaddr
@@ -913,11 +915,10 @@ connectOptions2(PGconn *conn)
913915

914916
/*
915917
* We now have one pg_conn_host structure per possible host. Fill in the
916-
* hostdetailsfor each one.
918+
* hostand hostaddr fieldsfor each, by splitting the parameter strings.
917919
*/
918920
if (conn->pghostaddr!=NULL&&conn->pghostaddr[0]!='\0')
919921
{
920-
inti;
921922
char*s=conn->pghostaddr;
922923
boolmore= true;
923924

@@ -926,8 +927,6 @@ connectOptions2(PGconn *conn)
926927
conn->connhost[i].hostaddr=parse_comma_separated_list(&s,&more);
927928
if (conn->connhost[i].hostaddr==NULL)
928929
gotooom_error;
929-
930-
conn->connhost[i].type=CHT_HOST_ADDRESS;
931930
}
932931

933932
/*
@@ -941,7 +940,6 @@ connectOptions2(PGconn *conn)
941940

942941
if (conn->pghost!=NULL&&conn->pghost[0]!='\0')
943942
{
944-
inti;
945943
char*s=conn->pghost;
946944
boolmore= true;
947945

@@ -950,17 +948,9 @@ connectOptions2(PGconn *conn)
950948
conn->connhost[i].host=parse_comma_separated_list(&s,&more);
951949
if (conn->connhost[i].host==NULL)
952950
gotooom_error;
953-
954-
/* Identify the type of host. */
955-
if (conn->pghostaddr==NULL||conn->pghostaddr[0]=='\0')
956-
{
957-
conn->connhost[i].type=CHT_HOST_NAME;
958-
#ifdefHAVE_UNIX_SOCKETS
959-
if (is_absolute_path(conn->connhost[i].host))
960-
conn->connhost[i].type=CHT_UNIX_SOCKET;
961-
#endif
962-
}
963951
}
952+
953+
/* Check for wrong number of host items. */
964954
if (more||i!=conn->nconnhost)
965955
{
966956
conn->status=CONNECTION_BAD;
@@ -972,29 +962,48 @@ connectOptions2(PGconn *conn)
972962
}
973963

974964
/*
975-
* If neither host or hostaddr options was given, connect to default host.
965+
* Now, for each host slot, identify the type of address spec, and fill in
966+
* the default address if nothing was given.
976967
*/
977-
if ((conn->pghostaddr==NULL||conn->pghostaddr[0]=='\0')&&
978-
(conn->pghost==NULL||conn->pghost[0]=='\0'))
968+
for (i=0;i<conn->nconnhost;i++)
979969
{
980-
Assert(conn->nconnhost==1);
970+
pg_conn_host*ch=&conn->connhost[i];
971+
972+
if (ch->hostaddr!=NULL&&ch->hostaddr[0]!='\0')
973+
ch->type=CHT_HOST_ADDRESS;
974+
elseif (ch->host!=NULL&&ch->host[0]!='\0')
975+
{
976+
ch->type=CHT_HOST_NAME;
981977
#ifdefHAVE_UNIX_SOCKETS
982-
conn->connhost[0].host=strdup(DEFAULT_PGSOCKET_DIR);
983-
conn->connhost[0].type=CHT_UNIX_SOCKET;
978+
if (is_absolute_path(ch->host))
979+
ch->type=CHT_UNIX_SOCKET;
980+
#endif
981+
}
982+
else
983+
{
984+
if (ch->host)
985+
free(ch->host);
986+
#ifdefHAVE_UNIX_SOCKETS
987+
ch->host=strdup(DEFAULT_PGSOCKET_DIR);
988+
ch->type=CHT_UNIX_SOCKET;
984989
#else
985-
conn->connhost[0].host=strdup(DefaultHost);
986-
conn->connhost[0].type=CHT_HOST_NAME;
990+
ch->host=strdup(DefaultHost);
991+
ch->type=CHT_HOST_NAME;
987992
#endif
988-
if (conn->connhost[0].host==NULL)
989-
gotooom_error;
993+
if (ch->host==NULL)
994+
gotooom_error;
995+
}
990996
}
991997

992998
/*
993999
* Next, work out the port number corresponding to each host name.
1000+
*
1001+
* Note: unlike the above for host names, this could leave the port fields
1002+
* as null or empty strings. We will substitute DEF_PGPORT whenever we
1003+
* read such a port field.
9941004
*/
9951005
if (conn->pgport!=NULL&&conn->pgport[0]!='\0')
9961006
{
997-
inti;
9981007
char*s=conn->pgport;
9991008
boolmore= true;
10001009

@@ -1058,8 +1067,8 @@ connectOptions2(PGconn *conn)
10581067
}
10591068

10601069
/*
1061-
*Supply defaultpasswordif none given. Note that thepasswordmight be
1062-
* different for each host/port pair.
1070+
*Ifpasswordwas not given, try to look it up inpasswordfile. Note
1071+
*that the result might bedifferent for each host/port pair.
10631072
*/
10641073
if (conn->pgpass==NULL||conn->pgpass[0]=='\0')
10651074
{
@@ -1082,20 +1091,16 @@ connectOptions2(PGconn *conn)
10821091

10831092
if (conn->pgpassfile!=NULL&&conn->pgpassfile[0]!='\0')
10841093
{
1085-
inti;
1086-
10871094
for (i=0;i<conn->nconnhost;i++)
10881095
{
10891096
/*
1090-
* Try to get a password for this host frompgpassfile.We use
1091-
*host name rather than host address in the same manner as
1092-
*PQhost().
1097+
* Try to get a password for this host fromfile.We use host
1098+
*for the hostname search key if given, else hostaddr (at
1099+
*least one of them is guaranteed nonempty by now).
10931100
*/
10941101
char*pwhost=conn->connhost[i].host;
10951102

1096-
if (conn->connhost[i].type==CHT_HOST_ADDRESS&&
1097-
conn->connhost[i].host!=NULL&&
1098-
conn->connhost[i].host[0]!='\0')
1103+
if (pwhost==NULL||pwhost[0]=='\0')
10991104
pwhost=conn->connhost[i].hostaddr;
11001105

11011106
conn->connhost[i].password=
@@ -6375,14 +6380,14 @@ passwordFromFile(char *hostname, char *port, char *dbname,
63756380
#defineLINELEN NAMEDATALEN*5
63766381
charbuf[LINELEN];
63776382

6378-
if (dbname==NULL||strlen(dbname)==0)
6383+
if (dbname==NULL||dbname[0]=='\0')
63796384
returnNULL;
63806385

6381-
if (username==NULL||strlen(username)==0)
6386+
if (username==NULL||username[0]=='\0')
63826387
returnNULL;
63836388

63846389
/* 'localhost' matches pghost of '' or the default socket directory */
6385-
if (hostname==NULL)
6390+
if (hostname==NULL||hostname[0]=='\0')
63866391
hostname=DefaultHost;
63876392
elseif (is_absolute_path(hostname))
63886393

@@ -6393,7 +6398,7 @@ passwordFromFile(char *hostname, char *port, char *dbname,
63936398
if (strcmp(hostname,DEFAULT_PGSOCKET_DIR)==0)
63946399
hostname=DefaultHost;
63956400

6396-
if (port==NULL)
6401+
if (port==NULL||port[0]=='\0')
63976402
port=DEF_PGPORT_STR;
63986403

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

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp