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

Commitba005f1

Browse files
committed
Allow password file name to be specified as a libpq connection parameter.
Formerly an alternate password file could only be selected via theenvironment variable PGPASSFILE; now it can also be selected via anew connection parameter "passfile", corresponding to the conventionsfor most other connection parameters. There was some concern aboutthis creating a security weakness, but it was agreed that that argumentwas pretty thin, and there are clear use-cases for handling passwordfiles this way.Julian Markwort, reviewed by Fabien Coelho, some adjustments by meDiscussion:https://postgr.es/m/a4b4f4f1-7b58-a0e8-5268-5f7db8e8ccaa@uni-muenster.de
1 parentd1ecd53 commitba005f1

File tree

4 files changed

+81
-62
lines changed

4 files changed

+81
-62
lines changed

‎doc/src/sgml/libpq.sgml

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -943,7 +943,7 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname
943943
Note that authentication is likely to fail if <literal>host</>
944944
is not the name of the server at network address <literal>hostaddr</>.
945945
Also, note that <literal>host</> rather than <literal>hostaddr</>
946-
is used to identify the connection in<filename>~/.pgpass</> (see
946+
is used to identify the connection ina password file (see
947947
<xref linkend="libpq-pgpass">).
948948
</para>
949949

@@ -1002,6 +1002,19 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname
10021002
</listitem>
10031003
</varlistentry>
10041004

1005+
<varlistentry id="libpq-connect-passfile" xreflabel="passfile">
1006+
<term><literal>passfile</literal></term>
1007+
<listitem>
1008+
<para>
1009+
Specifies the name of the file used to store passwords
1010+
(see <xref linkend="libpq-pgpass">).
1011+
Defaults to <filename>~/.pgpass</filename>, or
1012+
<filename>%APPDATA%\postgresql\pgpass.conf</> on Microsoft Windows.
1013+
(No error is reported if this file does not exist.)
1014+
</para>
1015+
</listitem>
1016+
</varlistentry>
1017+
10051018
<varlistentry id="libpq-connect-connect-timeout" xreflabel="connect_timeout">
10061019
<term><literal>connect_timeout</literal></term>
10071020
<listitem>
@@ -6893,8 +6906,8 @@ myEventProc(PGEventId evtId, void *evtInfo, void *passThrough)
68936906
Use of this environment variable
68946907
is not recommended for security reasons, as some operating systems
68956908
allow non-root users to see process environment variables via
6896-
<application>ps</>; instead consider usingthe
6897-
<filename>~/.pgpass</> file(see <xref linkend="libpq-pgpass">).
6909+
<application>ps</>; instead consider usinga password file
6910+
(see <xref linkend="libpq-pgpass">).
68986911
</para>
68996912
</listitem>
69006913

@@ -6903,9 +6916,8 @@ myEventProc(PGEventId evtId, void *evtInfo, void *passThrough)
69036916
<indexterm>
69046917
<primary><envar>PGPASSFILE</envar></primary>
69056918
</indexterm>
6906-
<envar>PGPASSFILE</envar> specifies the name of the password file to
6907-
use for lookups. If not set, it defaults to <filename>~/.pgpass</>
6908-
(see <xref linkend="libpq-pgpass">).
6919+
<envar>PGPASSFILE</envar> behaves the same as the <xref
6920+
linkend="libpq-connect-passfile"> connection parameter.
69096921
</para>
69106922
</listitem>
69116923

@@ -7187,13 +7199,16 @@ myEventProc(PGEventId evtId, void *evtInfo, void *passThrough)
71877199
</indexterm>
71887200

71897201
<para>
7190-
The file <filename>.pgpass</filename> in a user's home directoryor the
7191-
file referenced by <envar>PGPASSFILE</envar> cancontain passwords to
7202+
The file <filename>.pgpass</filename> in a user's home directorycan
7203+
contain passwords to
71927204
be used if the connection requires a password (and no password has been
71937205
specified otherwise). On Microsoft Windows the file is named
71947206
<filename>%APPDATA%\postgresql\pgpass.conf</> (where
71957207
<filename>%APPDATA%</> refers to the Application Data subdirectory in
71967208
the user's profile).
7209+
Alternatively, a password file can be specified
7210+
using the connection parameter <xref linkend="libpq-connect-passfile">
7211+
or the environment variable <envar>PGPASSFILE</envar>.
71977212
</para>
71987213

71997214
<para>
@@ -7219,8 +7234,8 @@ myEventProc(PGEventId evtId, void *evtInfo, void *passThrough)
72197234
</para>
72207235

72217236
<para>
7222-
On Unix systems, the permissions on<filename>.pgpass</filename> must
7223-
disallow any access to world or group; achieve this bythe command
7237+
On Unix systems, the permissions ona password file must
7238+
disallow any access to world or group; achieve this bya command such as
72247239
<command>chmod 0600 ~/.pgpass</command>. If the permissions are less
72257240
strict than this, the file will be ignored. On Microsoft Windows, it
72267241
is assumed that the file is stored in a directory that is secure, so

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -686,11 +686,12 @@ pg_fe_sendauth(AuthRequest areq, PGconn *conn)
686686
caseAUTH_REQ_MD5:
687687
caseAUTH_REQ_PASSWORD:
688688
{
689-
char*password=conn->connhost[conn->whichhost].password;
689+
char*password;
690690

691+
conn->password_needed= true;
692+
password=conn->connhost[conn->whichhost].password;
691693
if (password==NULL)
692694
password=conn->pgpass;
693-
conn->password_needed= true;
694695
if (password==NULL||password[0]=='\0')
695696
{
696697
printfPQExpBuffer(&conn->errorMessage,

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

Lines changed: 51 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,6 @@ static int ldapServiceLookup(const char *purl, PQconninfoOption *options,
107107
#defineDefaultTty""
108108
#defineDefaultOption""
109109
#defineDefaultAuthtype ""
110-
#defineDefaultPassword ""
111110
#defineDefaultTargetSessionAttrs"any"
112111
#ifdefUSE_SSL
113112
#defineDefaultSSLMode "prefer"
@@ -185,6 +184,10 @@ static const internalPQconninfoOption PQconninfoOptions[] = {
185184
"Database-Password","*",20,
186185
offsetof(structpg_conn,pgpass)},
187186

187+
{"passfile","PGPASSFILE",NULL,NULL,
188+
"Database-Password-File","",64,
189+
offsetof(structpg_conn,pgpassfile)},
190+
188191
{"connect_timeout","PGCONNECT_TIMEOUT",NULL,NULL,
189192
"Connect-timeout","",10,/* strlen(INT32_MAX) == 10 */
190193
offsetof(structpg_conn,connect_timeout)},
@@ -382,10 +385,9 @@ static int parseServiceFile(const char *serviceFile,
382385
PQExpBuffererrorMessage,
383386
bool*group_found);
384387
staticchar*pwdfMatchesString(char*buf,char*token);
385-
staticchar*PasswordFromFile(char*hostname,char*port,char*dbname,
386-
char*username);
387-
staticboolgetPgPassFilename(char*pgpassfile);
388-
staticvoiddot_pg_pass_warning(PGconn*conn);
388+
staticchar*passwordFromFile(char*hostname,char*port,char*dbname,
389+
char*username,char*pgpassfile);
390+
staticvoidpgpassfileWarning(PGconn*conn);
389391
staticvoiddefault_threadlock(intacquire);
390392

391393

@@ -957,19 +959,40 @@ connectOptions2(PGconn *conn)
957959
{
958960
inti;
959961

960-
if (conn->pgpass)
961-
free(conn->pgpass);
962-
conn->pgpass=strdup(DefaultPassword);
963-
if (!conn->pgpass)
964-
gotooom_error;
965-
for (i=0;i<conn->nconnhost;++i)
962+
if (conn->pgpassfile==NULL||conn->pgpassfile[0]=='\0')
963+
{
964+
/* Identify password file to use; fail if we can't */
965+
charhomedir[MAXPGPATH];
966+
967+
if (!pqGetHomeDirectory(homedir,sizeof(homedir)))
968+
{
969+
conn->status=CONNECTION_BAD;
970+
printfPQExpBuffer(&conn->errorMessage,
971+
libpq_gettext("could not get home directory to locate password file\n"));
972+
return false;
973+
}
974+
975+
if (conn->pgpassfile)
976+
free(conn->pgpassfile);
977+
conn->pgpassfile=malloc(MAXPGPATH);
978+
if (!conn->pgpassfile)
979+
gotooom_error;
980+
981+
snprintf(conn->pgpassfile,MAXPGPATH,"%s/%s",homedir,PGPASSFILE);
982+
}
983+
984+
for (i=0;i<conn->nconnhost;i++)
966985
{
986+
/* Try to get a password for this host from pgpassfile */
967987
conn->connhost[i].password=
968-
PasswordFromFile(conn->connhost[i].host,
988+
passwordFromFile(conn->connhost[i].host,
969989
conn->connhost[i].port,
970-
conn->dbName,conn->pguser);
990+
conn->dbName,
991+
conn->pguser,
992+
conn->pgpassfile);
993+
/* If we got one, set pgpassfile_used */
971994
if (conn->connhost[i].password!=NULL)
972-
conn->dot_pgpass_used= true;
995+
conn->pgpassfile_used= true;
973996
}
974997
}
975998

@@ -3016,7 +3039,7 @@ PQconnectPoll(PGconn *conn)
30163039

30173040
error_return:
30183041

3019-
dot_pg_pass_warning(conn);
3042+
pgpassfileWarning(conn);
30203043

30213044
/*
30223045
* We used to close the socket at this point, but that makes it awkward
@@ -3147,7 +3170,7 @@ makeEmptyPGconn(void)
31473170
conn->sock=PGINVALID_SOCKET;
31483171
conn->auth_req_received= false;
31493172
conn->password_needed= false;
3150-
conn->dot_pgpass_used= false;
3173+
conn->pgpassfile_used= false;
31513174
#ifdefUSE_SSL
31523175
conn->allow_ssl_try= true;
31533176
conn->wait_ssl_try= false;
@@ -3256,6 +3279,8 @@ freePGconn(PGconn *conn)
32563279
free(conn->pguser);
32573280
if (conn->pgpass)
32583281
free(conn->pgpass);
3282+
if (conn->pgpassfile)
3283+
free(conn->pgpassfile);
32593284
if (conn->keepalives)
32603285
free(conn->keepalives);
32613286
if (conn->keepalives_idle)
@@ -5794,6 +5819,9 @@ PQpass(const PGconn *conn)
57945819
password=conn->connhost[conn->whichhost].password;
57955820
if (password==NULL)
57965821
password=conn->pgpass;
5822+
/* Historically we've returned "" not NULL for no password specified */
5823+
if (password==NULL)
5824+
password="";
57975825
returnpassword;
57985826
}
57995827

@@ -6160,10 +6188,10 @@ pwdfMatchesString(char *buf, char *token)
61606188

61616189
/* Get a password from the password file. Return value is malloc'd. */
61626190
staticchar*
6163-
PasswordFromFile(char*hostname,char*port,char*dbname,char*username)
6191+
passwordFromFile(char*hostname,char*port,char*dbname,
6192+
char*username,char*pgpassfile)
61646193
{
61656194
FILE*fp;
6166-
charpgpassfile[MAXPGPATH];
61676195
structstatstat_buf;
61686196

61696197
#defineLINELEN NAMEDATALEN*5
@@ -6190,9 +6218,6 @@ PasswordFromFile(char *hostname, char *port, char *dbname, char *username)
61906218
if (port==NULL)
61916219
port=DEF_PGPORT_STR;
61926220

6193-
if (!getPgPassFilename(pgpassfile))
6194-
returnNULL;
6195-
61966221
/* If password file cannot be opened, ignore it. */
61976222
if (stat(pgpassfile,&stat_buf)!=0)
61986223
returnNULL;
@@ -6286,46 +6311,23 @@ PasswordFromFile(char *hostname, char *port, char *dbname, char *username)
62866311
}
62876312

62886313

6289-
staticbool
6290-
getPgPassFilename(char*pgpassfile)
6291-
{
6292-
char*passfile_env;
6293-
6294-
if ((passfile_env=getenv("PGPASSFILE"))!=NULL)
6295-
/* use the literal path from the environment, if set */
6296-
strlcpy(pgpassfile,passfile_env,MAXPGPATH);
6297-
else
6298-
{
6299-
charhomedir[MAXPGPATH];
6300-
6301-
if (!pqGetHomeDirectory(homedir,sizeof(homedir)))
6302-
return false;
6303-
snprintf(pgpassfile,MAXPGPATH,"%s/%s",homedir,PGPASSFILE);
6304-
}
6305-
return true;
6306-
}
6307-
63086314
/*
63096315
*If the connection failed, we should mention if
6310-
*we got the password from.pgpass in case that
6316+
*we got the password fromthe pgpassfile in case that
63116317
*password is wrong.
63126318
*/
63136319
staticvoid
6314-
dot_pg_pass_warning(PGconn*conn)
6320+
pgpassfileWarning(PGconn*conn)
63156321
{
6316-
/* If it was 'invalid authorization', add.pgpass mention */
6322+
/* If it was 'invalid authorization', addpgpassfile mention */
63176323
/* only works with >= 9.0 servers */
6318-
if (conn->dot_pgpass_used&&conn->password_needed&&conn->result&&
6324+
if (conn->pgpassfile_used&&conn->password_needed&&conn->result&&
63196325
strcmp(PQresultErrorField(conn->result,PG_DIAG_SQLSTATE),
63206326
ERRCODE_INVALID_PASSWORD)==0)
63216327
{
6322-
charpgpassfile[MAXPGPATH];
6323-
6324-
if (!getPgPassFilename(pgpassfile))
6325-
return;
63266328
appendPQExpBuffer(&conn->errorMessage,
63276329
libpq_gettext("password retrieved from file \"%s\"\n"),
6328-
pgpassfile);
6330+
conn->pgpassfile);
63296331
}
63306332
}
63316333

‎src/interfaces/libpq/libpq-int.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,7 @@ struct pg_conn
343343
char*replication;/* connect as the replication standby? */
344344
char*pguser;/* Postgres username and password, if any */
345345
char*pgpass;
346+
char*pgpassfile;/* path to a file containing password(s) */
346347
char*keepalives;/* use TCP keepalives? */
347348
char*keepalives_idle;/* time between TCP keepalives */
348349
char*keepalives_interval;/* time between TCP keepalive
@@ -407,7 +408,7 @@ struct pg_conn
407408
boolauth_req_received;/* true if any type of auth req
408409
* received */
409410
boolpassword_needed;/* true if server demanded a password */
410-
booldot_pgpass_used;/* true ifused .pgpass */
411+
boolpgpassfile_used;/* true ifpassword is from pgpassfile */
411412
boolsigpipe_so;/* have we masked SIGPIPE via SO_NOSIGPIPE? */
412413
boolsigpipe_flag;/* can we mask SIGPIPE via MSG_NOSIGNAL? */
413414

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp