I'm giving a try at some TODO items. Currently it's the turn of the

PGPASSWORDFILE environment variable.  I have modified libpq to make use
of this variable.  I present the first cut here.

Currently the format for the file should be

host:port:database:user:password

Alvaro Herrera
This commit is contained in:
Bruce Momjian 2002-08-15 02:56:19 +00:00
parent 46aaa5dda3
commit 7f4981f4af
4 changed files with 148 additions and 28 deletions

View File

@ -1,5 +1,5 @@
<!-- <!--
$Header: /cvsroot/pgsql/doc/src/sgml/Attic/libpq++.sgml,v 1.41 2002/03/22 19:20:12 petere Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/Attic/libpq++.sgml,v 1.42 2002/08/15 02:56:19 momjian Exp $
--> -->
<chapter id="libpqplusplus"> <chapter id="libpqplusplus">
@ -117,11 +117,14 @@ $Header: /cvsroot/pgsql/doc/src/sgml/Attic/libpq++.sgml,v 1.41 2002/03/22 19:20:
</listitem> </listitem>
<listitem> <listitem>
<para> <para>
<envar>PGPASSWORD</envar> <envar>PGPASSWORD</envar>
sets the password used if the backend demands password sets the password used if the backend demands password
authentication. This is not recommended because the password can authentication. This is deprecated; use <envar>PGPASSWORDFILE</envar> instead.
be read by others using the <command>ps</command> command with special options <listitem>
on some platforms. <para>
<envar>PGPASSWORDFILE</envar>
sets the password file used if the backend demands password
authentication. Refer to the libpq documentation for more details.
</para> </para>
</listitem> </listitem>
<listitem> <listitem>

View File

@ -1,5 +1,5 @@
<!-- <!--
$Header: /cvsroot/pgsql/doc/src/sgml/libpq.sgml,v 1.90 2002/03/22 19:20:13 petere Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/libpq.sgml,v 1.91 2002/08/15 02:56:19 momjian Exp $
--> -->
<chapter id="libpq"> <chapter id="libpq">
@ -2038,9 +2038,25 @@ sets the user name used to connect to the database and for authentication.
</indexterm> </indexterm>
<envar>PGPASSWORD</envar> <envar>PGPASSWORD</envar>
sets the password used if the backend demands password sets the password used if the backend demands password
authentication. This is not recommended because the password can authentication. This functionality is deprecated for security
be read by others using the <command>ps</command> command with special options reasons; consider migrating to <envar>PGPASSWORDFILE</envar>.
on some platforms. </para>
</listitem>
<listitem>
<para>
<indexterm>
<primary><envar>PGPASSWORDFILE</envar></primary>
</indexterm>
<envar>PGPASSWORDFILE</envar>
sets the password file used if the backend demands password authentication.
This file should have the format
<screen>
<replaceable>hostname</replaceable>:<replaceable>port</replaceable>:<replaceable>database</replaceable>:<replaceable>username</replaceable>:<replaceable>password</replaceable>
</screen>
Any of these may be a literal name, or a <literal>*</literal> that matches
anything. The first match will be the one used, so put more specific entries first.
Entries with <literal>:</literal> or <literal>\</literal> should be escaped
with <literal>\</literal>.
</para> </para>
</listitem> </listitem>
<listitem> <listitem>

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.190 2002/07/20 05:43:31 momjian Exp $ * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.191 2002/08/15 02:56:19 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -182,6 +182,9 @@ static char *conninfo_getval(PQconninfoOption *connOptions,
static void defaultNoticeProcessor(void *arg, const char *message); static void defaultNoticeProcessor(void *arg, const char *message);
static int parseServiceInfo(PQconninfoOption *options, static int parseServiceInfo(PQconninfoOption *options,
PQExpBuffer errorMessage); PQExpBuffer errorMessage);
char *pwdfMatchesString(char *buf, char *token);
char *PasswordFromFile(char *hostname, char *port, char *dbname,
char *username, char *pwdfile);
/* /*
* Connecting to a Database * Connecting to a Database
@ -388,6 +391,10 @@ PQconndefaults(void)
* *
* PGPASSWORD The user's password. * PGPASSWORD The user's password.
* *
* PGPASSWORDFILE
* A file that contains host:port:database:user:password
* for authentication
*
* PGDATABASE name of database to which to connect if <pgdatabase> * PGDATABASE name of database to which to connect if <pgdatabase>
* argument is NULL or a null string * argument is NULL or a null string
* *
@ -476,13 +483,6 @@ PQsetdbLogin(const char *pghost, const char *pgport, const char *pgoptions,
libpq_gettext("could not determine the PostgreSQL user name to use\n")); libpq_gettext("could not determine the PostgreSQL user name to use\n"));
} }
if (pwd)
conn->pgpass = strdup(pwd);
else if ((tmp = getenv("PGPASSWORD")) != NULL)
conn->pgpass = strdup(tmp);
else
conn->pgpass = strdup(DefaultPassword);
if (dbName == NULL) if (dbName == NULL)
{ {
if ((tmp = getenv("PGDATABASE")) != NULL) if ((tmp = getenv("PGDATABASE")) != NULL)
@ -493,6 +493,17 @@ PQsetdbLogin(const char *pghost, const char *pgport, const char *pgoptions,
else else
conn->dbName = strdup(dbName); conn->dbName = strdup(dbName);
/* getPasswordFromFile mallocs its result, so we don't need strdup here */
if (pwd)
conn->pgpass = strdup(pwd);
else if ((tmp = getenv("PGPASSWORD")) != NULL)
conn->pgpass = strdup(tmp);
else if ((tmp = PasswordFromFile(conn->pghost, conn->pgport,
conn->dbName, conn->pguser,
getenv("PGPASSWORDFILE"))) != NULL)
conn->pgpass = tmp;
else
conn->pgpass = strdup(DefaultPassword);
#ifdef USE_SSL #ifdef USE_SSL
if ((tmp = getenv("PGREQUIRESSL")) != NULL) if ((tmp = getenv("PGREQUIRESSL")) != NULL)
@ -2810,3 +2821,92 @@ defaultNoticeProcessor(void *arg, const char *message)
/* Note: we expect the supplied string to end with a newline already. */ /* Note: we expect the supplied string to end with a newline already. */
fprintf(stderr, "%s", message); fprintf(stderr, "%s", message);
} }
/* returns a pointer to the next token or NULL if the current
* token doesn't match */
char *
pwdfMatchesString(char *buf, char *token)
{
char *tbuf,
*ttok;
bool bslash = false;
if (buf == NULL || token == NULL)
return NULL;
tbuf = buf;
ttok = token;
if (*tbuf == '*')
return tbuf + 2;
while (*tbuf != 0)
{
if (*tbuf == '\\' && !bslash)
{
tbuf++;
bslash = true;
}
if (*tbuf == ':' && *ttok == 0 && !bslash)
return tbuf+1;
bslash = false;
if (*ttok == 0)
return NULL;
if (*tbuf == *ttok)
{
tbuf++;
ttok++;
}
else
return NULL;
}
return NULL;
}
/* get a password from the password file. */
char *
PasswordFromFile(char *hostname, char *port, char *dbname,
char *username, char *pwdfile)
{
FILE *fp;
#define LINELEN NAMEDATALEN*5
char buf[LINELEN];
if (pwdfile == NULL || strcmp(pwdfile, "") == 0)
return NULL;
if (dbname == NULL || strcmp(dbname, "") == 0)
return NULL;
if (username == NULL || strcmp(username, "") == 0)
return NULL;
if (hostname == NULL)
hostname = DefaultHost;
if (port == NULL)
port = DEF_PGPORT_STR;
fp = fopen(pwdfile, "r");
if (fp == NULL)
return NULL;
while (!feof(fp)) {
char *t = buf,
*ret;
fgets(buf, LINELEN - 1, fp);
if (strlen(buf) == 0)
continue;
buf[strlen(buf) - 1] = 0;
if ((t = pwdfMatchesString(t, hostname)) == NULL ||
(t = pwdfMatchesString(t, port)) == NULL ||
(t = pwdfMatchesString(t, dbname)) == NULL ||
(t = pwdfMatchesString(t, username)) == NULL)
continue;
ret=(char *)malloc(sizeof(char)*strlen(t));
strncpy(ret, t, strlen(t));
fclose(fp);
return ret;
}
fclose(fp);
return NULL;
#undef LINELEN
}

View File

@ -1,6 +1,6 @@
#------------------------------------------------------- #-------------------------------------------------------
# #
# $Id: Pg.pm,v 1.10 2001/09/10 04:19:19 momjian Exp $ # $Id: Pg.pm,v 1.11 2002/08/15 02:56:19 momjian Exp $
# #
# Copyright (c) 1997, 1998 Edmund Mergl # Copyright (c) 1997, 1998 Edmund Mergl
# #
@ -260,15 +260,16 @@ When opening a connection a given database name is always converted to
lower-case, unless it is surrounded by double quotes. All unspecified lower-case, unless it is surrounded by double quotes. All unspecified
parameters are replaced by environment variables or by hard coded defaults: parameters are replaced by environment variables or by hard coded defaults:
parameter environment variable hard coded default parameter environment variable hard coded default
-------------------------------------------------- ------------------------------------------------------
host PGHOST localhost host PGHOST localhost
port PGPORT 5432 port PGPORT 5432
options PGOPTIONS "" options PGOPTIONS ""
tty PGTTY "" tty PGTTY ""
dbname PGDATABASE current userid dbname PGDATABASE current userid
user PGUSER current userid user PGUSER current userid
password PGPASSWORD "" password PGPASSWORD ""
passwordfile PGPASSWORDFILE ""
Using appropriate methods you can access almost all fields of the Using appropriate methods you can access almost all fields of the
returned PGconn structure. returned PGconn structure.