Index: src/interfaces/libpq/fe-connect.c =================================================================== RCS file: /projects/cvsroot/pgsql-server/src/interfaces/libpq/fe-connect.c,v retrieving revision 1.190 diff -c -r1.190 fe-connect.c *** src/interfaces/libpq/fe-connect.c 2002/07/20 05:43:31 1.190 --- src/interfaces/libpq/fe-connect.c 2002/08/11 23:40:42 *************** *** 182,187 **** --- 182,190 ---- 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,393 **** --- 391,400 ---- * * 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 * argument is NULL or a null string * *************** *** 476,488 **** 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) --- 483,488 ---- *************** *** 493,498 **** --- 493,509 ---- 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) *************** *** 2809,2812 **** --- 2820,2912 ---- (void) arg; /* not used */ /* 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 } Index: src/interfaces/perl5/Pg.pm =================================================================== RCS file: /projects/cvsroot/pgsql-server/src/interfaces/perl5/Pg.pm,v retrieving revision 1.10 diff -c -r1.10 Pg.pm *** src/interfaces/perl5/Pg.pm 2001/09/10 04:19:19 1.10 --- src/interfaces/perl5/Pg.pm 2002/08/11 23:40:50 *************** *** 260,274 **** 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 "" Using appropriate methods you can access almost all fields of the returned PGconn structure. --- 260,275 ---- 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 "" ! passwordfile PGPASSWORDFILE "" Using appropriate methods you can access almost all fields of the returned PGconn structure. Index: doc/src/sgml/libpq.sgml =================================================================== RCS file: /projects/cvsroot/pgsql-server/doc/src/sgml/libpq.sgml,v retrieving revision 1.90 diff -c -r1.90 libpq.sgml *** doc/src/sgml/libpq.sgml 2002/03/22 19:20:13 1.90 --- doc/src/sgml/libpq.sgml 2002/08/11 23:40:56 *************** *** 2038,2046 **** PGPASSWORD sets the password used if the backend demands password ! authentication. This is not recommended because the password can ! be read by others using the ps command with special options ! on some platforms. --- 2038,2062 ---- PGPASSWORD sets the password used if the backend demands password ! authentication. This functionality is deprecated for security ! reasons; consider migrating to PGPASSWORDFILE. ! ! ! ! ! ! PGPASSWORDFILE ! ! PGPASSWORDFILE ! sets the password file used if the backend demands password authentication. ! This file should have the format ! ! hostname:port:database:username:password ! ! Any of these may be a literal name, or a * that matches ! anything. The first match will be the one used, so put more specific entries first. ! Entries with : or \ should be escaped ! with \. Index: doc/src/sgml/libpq++.sgml =================================================================== RCS file: /projects/cvsroot/pgsql-server/doc/src/sgml/libpq++.sgml,v retrieving revision 1.41 diff -c -r1.41 libpq++.sgml *** doc/src/sgml/libpq++.sgml 2002/03/22 19:20:12 1.41 --- doc/src/sgml/libpq++.sgml 2002/08/11 23:40:58 *************** *** 117,127 **** ! PGPASSWORD ! sets the password used if the backend demands password ! authentication. This is not recommended because the password can ! be read by others using the ps command with special options ! on some platforms. --- 117,130 ---- ! PGPASSWORD ! sets the password used if the backend demands password ! authentication. This is deprecated; use PGPASSWORDFILE instead. ! ! ! PGPASSWORDFILE ! sets the password file used if the backend demands password ! authentication. Refer to the libpq documentation for more details.