Add an officially exported libpq function to encrypt passwords, and

modify the previous \password patch to use it instead of depending
on a not-officially-exported function.  Per discussion.
This commit is contained in:
Tom Lane 2005-12-23 01:16:38 +00:00
parent e80f9dfa80
commit ea9b028dc7
6 changed files with 93 additions and 14 deletions

View File

@ -1,5 +1,5 @@
<!--
$PostgreSQL: pgsql/doc/src/sgml/libpq.sgml,v 1.199 2005/11/04 23:14:00 petere Exp $
$PostgreSQL: pgsql/doc/src/sgml/libpq.sgml,v 1.200 2005/12/23 01:16:37 tgl Exp $
-->
<chapter id="libpq">
@ -3565,6 +3565,40 @@ void PQuntrace(PGconn *conn);
</sect1>
<sect1 id="libpq-misc">
<title>Miscellaneous Functions</title>
<para>
As always, there are some functions that just don't fit anywhere.
</para>
<variablelist>
<varlistentry>
<term><function>pg_make_encrypted_password</function><indexterm><primary>pg_make_encrypted_password</></></term>
<listitem>
<para>
Prepares the encrypted form of a <productname>PostgreSQL</> password.
<synopsis>
char *pg_make_encrypted_password(const char *passwd, const char *user);
</synopsis>
<function>pg_make_encrypted_password</> is intended to be used by client
applications that wish to send commands like
<literal>ALTER USER joe PASSWORD 'pwd'</>.
It is good practice not to send the original cleartext password in such a
command, because it might be exposed in command logs, activity displays,
and so on. Instead, use this function to convert the password to encrypted
form before it is sent. The arguments are the cleartext password, and the SQL
name of the user it is for. The return value is a malloc'd string, or NULL if
out-of-memory. The caller may assume the string doesn't contain any weird
characters that would require escaping. Use <function>PQfreemem</> to free
the result when done with it.
</para>
</listitem>
</varlistentry>
</variablelist>
</sect1>
<sect1 id="libpq-notice-processing">
<title>Notice Processing</title>

View File

@ -3,7 +3,7 @@
*
* Copyright (c) 2000-2005, PostgreSQL Global Development Group
*
* $PostgreSQL: pgsql/src/bin/psql/command.c,v 1.156 2005/12/18 02:17:16 petere Exp $
* $PostgreSQL: pgsql/src/bin/psql/command.c,v 1.157 2005/12/23 01:16:38 tgl Exp $
*/
#include "postgres_fe.h"
#include "command.h"
@ -12,7 +12,6 @@
#undef mkdir
#endif
#include <errno.h>
#include <ctype.h>
#ifdef HAVE_PWD_H
#include <pwd.h>
@ -35,7 +34,6 @@
#include "libpq-fe.h"
#include "pqexpbuffer.h"
#include "libpq/crypt.h"
#include "dumputils.h"
#include "common.h"
@ -638,14 +636,16 @@ exec_command(const char *cmd,
{
char *opt0 = psql_scan_slash_option(scan_state, OT_SQLID, NULL, true);
char *user;
char encrypted_password[MD5_PASSWD_LEN + 1];
char *encrypted_password;
if (opt0)
user = opt0;
else
user = PQuser(pset.db);
if (!pg_md5_encrypt(pw1, user, strlen(user), encrypted_password))
encrypted_password = pg_make_encrypted_password(pw1, user);
if (!encrypted_password)
{
fprintf(stderr, _("Password encryption failed.\n"));
success = false;
@ -656,7 +656,7 @@ exec_command(const char *cmd,
PGresult *res;
initPQExpBuffer(&buf);
printfPQExpBuffer(&buf, "ALTER ROLE %s PASSWORD '%s';",
printfPQExpBuffer(&buf, "ALTER USER %s PASSWORD '%s';",
fmtId(user), encrypted_password);
res = PSQLexec(buf.data, false);
termPQExpBuffer(&buf);
@ -664,6 +664,7 @@ exec_command(const char *cmd,
success = false;
else
PQclear(res);
PQfreemem(encrypted_password);
}
}

View File

@ -5,7 +5,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/bin/scripts/createuser.c,v 1.24 2005/12/18 02:17:16 petere Exp $
* $PostgreSQL: pgsql/src/bin/scripts/createuser.c,v 1.25 2005/12/23 01:16:38 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -13,7 +13,6 @@
#include "postgres_fe.h"
#include "common.h"
#include "dumputils.h"
#include "libpq/crypt.h"
static void help(const char *progname);
@ -250,14 +249,17 @@ main(int argc, char *argv[])
if (encrypted != TRI_NO)
{
char encrypted_password[MD5_PASSWD_LEN + 1];
char *encrypted_password;
if (!pg_md5_encrypt(newpassword, newuser, strlen(newuser), encrypted_password))
encrypted_password = pg_make_encrypted_password(newpassword,
newuser);
if (!encrypted_password)
{
fprintf(stderr, _("Password encryption failed.\n"));
exit(1);
}
appendStringLiteral(&sql, encrypted_password, false);
PQfreemem(encrypted_password);
}
else
appendStringLiteral(&sql, newpassword, false);

View File

@ -1,4 +1,4 @@
# $PostgreSQL: pgsql/src/interfaces/libpq/exports.txt,v 1.5 2005/10/21 15:21:21 tgl Exp $
# $PostgreSQL: pgsql/src/interfaces/libpq/exports.txt,v 1.6 2005/12/23 01:16:38 tgl Exp $
# Functions to be exported by libpq DLLs
PQconnectdb 1
PQsetdbLogin 2
@ -125,3 +125,4 @@ PQcancel 122
lo_create 123
PQinitSSL 124
PQregisterThreadLock 125
pg_make_encrypted_password 126

View File

@ -10,7 +10,7 @@
* exceed INITIAL_EXPBUFFER_SIZE (currently 256 bytes).
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/interfaces/libpq/fe-auth.c,v 1.108 2005/11/22 18:17:32 momjian Exp $
* $PostgreSQL: pgsql/src/interfaces/libpq/fe-auth.c,v 1.109 2005/12/23 01:16:38 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -531,3 +531,40 @@ pg_fe_getauthname(char *PQerrormsg)
return authn;
}
/*
* pg_make_encrypted_password -- exported routine to encrypt a password
*
* This is intended to be used by client applications that wish to send
* commands like ALTER USER joe PASSWORD 'pwd'. The password need not
* be sent in cleartext if it is encrypted on the client side. This is
* good because it ensures the cleartext password won't end up in logs,
* pg_stat displays, etc. We export the function so that clients won't
* be dependent on low-level details like whether the enceyption is MD5
* or something else.
*
* Arguments are the cleartext password, and the SQL name of the user it
* is for.
*
* Return value is a malloc'd string, or NULL if out-of-memory. The client
* may assume the string doesn't contain any weird characters that would
* require escaping.
*/
char *
pg_make_encrypted_password(const char *passwd, const char *user)
{
char *crypt_pwd;
crypt_pwd = malloc(MD5_PASSWD_LEN + 1);
if (!crypt_pwd)
return NULL;
if (!pg_md5_encrypt(passwd, user, strlen(user), crypt_pwd))
{
free(crypt_pwd);
return NULL;
}
return crypt_pwd;
}

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/interfaces/libpq/libpq-fe.h,v 1.122 2005/11/23 04:23:28 momjian Exp $
* $PostgreSQL: pgsql/src/interfaces/libpq/libpq-fe.h,v 1.123 2005/12/23 01:16:38 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -495,6 +495,10 @@ extern int PQdsplen(const char *s, int encoding);
/* Get encoding id from environment variable PGCLIENTENCODING */
extern int PQenv2encoding(void);
/* === in fe-auth.c === */
extern char *pg_make_encrypted_password(const char *passwd, const char *user);
#ifdef __cplusplus
}
#endif