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">
@ -117,11 +117,14 @@ $Header: /cvsroot/pgsql/doc/src/sgml/Attic/libpq++.sgml,v 1.41 2002/03/22 19:20:
</listitem>
<listitem>
<para>
<envar>PGPASSWORD</envar>
sets the password used if the backend demands password
authentication. This is not recommended because the password can
be read by others using the <command>ps</command> command with special options
on some platforms.
<envar>PGPASSWORD</envar>
sets the password used if the backend demands password
authentication. This is deprecated; use <envar>PGPASSWORDFILE</envar> instead.
<listitem>
<para>
<envar>PGPASSWORDFILE</envar>
sets the password file used if the backend demands password
authentication. Refer to the libpq documentation for more details.
</para>
</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">
@ -2038,9 +2038,25 @@ sets the user name used to connect to the database and for authentication.
</indexterm>
<envar>PGPASSWORD</envar>
sets the password used if the backend demands password
authentication. This is not recommended because the password can
be read by others using the <command>ps</command> command with special options
on some platforms.
authentication. This functionality is deprecated for security
reasons; consider migrating to <envar>PGPASSWORDFILE</envar>.
</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>
</listitem>
<listitem>

View File

@ -8,7 +8,7 @@
*
*
* 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 int parseServiceInfo(PQconninfoOption *options,
PQExpBuffer errorMessage);
char *pwdfMatchesString(char *buf, char *token);
char *PasswordFromFile(char *hostname, char *port, char *dbname,
char *username, char *pwdfile);
/*
* Connecting to a Database
@ -388,6 +391,10 @@ PQconndefaults(void)
*
* 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>
* 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"));
}
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 ((tmp = getenv("PGDATABASE")) != NULL)
@ -493,6 +493,17 @@ PQsetdbLogin(const char *pghost, const char *pgport, const char *pgoptions,
else
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
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. */
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
#
@ -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
parameters are replaced by environment variables or by hard coded defaults:
parameter environment variable hard coded default
--------------------------------------------------
host PGHOST localhost
port PGPORT 5432
options PGOPTIONS ""
tty PGTTY ""
dbname PGDATABASE current userid
user PGUSER current userid
password PGPASSWORD ""
parameter environment variable hard coded default
------------------------------------------------------
host PGHOST localhost
port PGPORT 5432
options PGOPTIONS ""
tty PGTTY ""
dbname PGDATABASE current userid
user PGUSER current userid
password PGPASSWORD ""
passwordfile PGPASSWORDFILE ""
Using appropriate methods you can access almost all fields of the
returned PGconn structure.