Commit 7663e6bb authored by Tom Lane's avatar Tom Lane

Reject tabs and linefeeds in usernames and passwords that are being

stored in pg_pwd, to guard against failures of the sort observed by
Tom Yackel.  Note: in the case of encrypted passwords this is no
restriction, since the string we are interested in is the MD5 hash.
parent bdea97ea
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Header: /cvsroot/pgsql/src/backend/commands/user.c,v 1.86 2001/10/28 06:25:42 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/user.c,v 1.87 2001/11/01 18:09:58 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -44,6 +44,10 @@ extern bool Password_encryption; ...@@ -44,6 +44,10 @@ extern bool Password_encryption;
* *
* This function set is both a trigger function for direct updates to pg_shadow * This function set is both a trigger function for direct updates to pg_shadow
* as well as being called directly from create/alter/drop user. * as well as being called directly from create/alter/drop user.
*
* We raise an error to force transaction rollback if we detect an illegal
* username or password --- illegal being defined as values that would
* mess up the pg_pwd parser.
*--------------------------------------------------------------------- *---------------------------------------------------------------------
*/ */
static void static void
...@@ -85,26 +89,51 @@ write_password_file(Relation rel) ...@@ -85,26 +89,51 @@ write_password_file(Relation rel)
bool null_n, bool null_n,
null_p, null_p,
null_v; null_v;
char *str_n,
*str_p,
*str_v;
int i;
datum_n = heap_getattr(tuple, Anum_pg_shadow_usename, dsc, &null_n); datum_n = heap_getattr(tuple, Anum_pg_shadow_usename, dsc, &null_n);
if (null_n) if (null_n)
continue; /* don't allow empty users */ continue; /* ignore NULL usernames */
datum_p = heap_getattr(tuple, Anum_pg_shadow_passwd, dsc, &null_p); str_n = DatumGetCString(DirectFunctionCall1(nameout, datum_n));
datum_p = heap_getattr(tuple, Anum_pg_shadow_passwd, dsc, &null_p);
/* /*
* It could be argued that people having a null password shouldn't * It can be argued that people having a null password shouldn't
* be allowed to connect, because they need to have a password set * be allowed to connect under password authentication, because
* up first. If you think assuming an empty password in that case * they need to have a password set up first. If you think assuming an
* is better, erase the following line. * empty password in that case is better, change this logic to look
* something like the code for valuntil.
*/ */
if (null_p) if (null_p)
{
pfree(str_n);
continue; continue;
}
str_p = DatumGetCString(DirectFunctionCall1(textout, datum_p));
datum_v = heap_getattr(tuple, Anum_pg_shadow_valuntil, dsc, &null_v); datum_v = heap_getattr(tuple, Anum_pg_shadow_valuntil, dsc, &null_v);
if (null_v)
str_v = pstrdup("\\N");
else
str_v = DatumGetCString(DirectFunctionCall1(nabstimeout, datum_v));
/*
* Check for illegal characters in the username and password.
*/
i = strcspn(str_n, CRYPT_PWD_FILE_SEPSTR "\n");
if (str_n[i] != '\0')
elog(ERROR, "Invalid user name '%s'", str_n);
i = strcspn(str_p, CRYPT_PWD_FILE_SEPSTR "\n");
if (str_p[i] != '\0')
elog(ERROR, "Invalid user password '%s'", str_p);
/* /*
* These fake entries are not really necessary. To remove them, * The extra columns we emit here are not really necessary. To remove
* the parser in backend/libpq/crypt.c would need to be adjusted. * them, the parser in backend/libpq/crypt.c would need to be
* Initdb might also need adjustments. * adjusted. Initdb might also need adjustments.
*/ */
fprintf(fp, fprintf(fp,
"%s" "%s"
...@@ -122,12 +151,13 @@ write_password_file(Relation rel) ...@@ -122,12 +151,13 @@ write_password_file(Relation rel)
"%s" "%s"
CRYPT_PWD_FILE_SEPSTR CRYPT_PWD_FILE_SEPSTR
"%s\n", "%s\n",
DatumGetCString(DirectFunctionCall1(nameout, datum_n)), str_n,
null_p ? "" : str_p,
DatumGetCString(DirectFunctionCall1(textout, datum_p)), str_v);
null_v ? "\\N" :
DatumGetCString(DirectFunctionCall1(nabstimeout, datum_v)) pfree(str_n);
); pfree(str_p);
pfree(str_v);
} }
heap_endscan(scan); heap_endscan(scan);
...@@ -137,8 +167,7 @@ write_password_file(Relation rel) ...@@ -137,8 +167,7 @@ write_password_file(Relation rel)
FreeFile(fp); FreeFile(fp);
/* /*
* And rename the temp file to its final name, deleting the old * Rename the temp file to its final name, deleting the old pg_pwd.
* pg_pwd.
*/ */
if (rename(tempname, filename)) if (rename(tempname, filename))
elog(ERROR, "rename %s to %s: %m", tempname, filename); elog(ERROR, "rename %s to %s: %m", tempname, filename);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment