<!--
-$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">
</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>
<!--
-$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">
</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>
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
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
*
* 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
*
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)
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)
/* 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
+}
#-------------------------------------------------------
#
-# $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
#
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.