mirror of
https://github.com/postgres/postgres.git
synced 2025-07-03 20:02:46 +03:00
Arrange for client authentication to occur before we select a specific
database to connect to. This is necessary for the walsender code to work properly (it was previously using an untenable assumption that template1 would always be available to connect to). This also gets rid of a small security shortcoming that was introduced in the original patch to eliminate the flat authentication files: before, you could find out whether or not the requested database existed even if you couldn't pass the authentication checks. The changes needed to support this are mainly just to treat pg_authid and pg_auth_members as nailed relations, so that we can read them without having to be able to locate real pg_class entries for them. This mechanism was already debugged for pg_database, but we hadn't recognized the value of applying it to those catalogs too. Since the current code doesn't have support for accessing toast tables before we've brought up all of the relcache, remove pg_authid's toast table to ensure that no one can store an out-of-line toasted value of rolpassword. The case seems quite unlikely to occur in practice, and was effectively unsupported anyway in the old "flatfiles" implementation. Update genbki.pl to actually implement the same rules as bootstrap.c does for not-nullability of catalog columns. The previous coding was a bit cheesy but worked all right for the previous set of bootstrap catalogs. It does not work for pg_authid, where rolvaliduntil needs to be nullable. Initdb forced due to minor catalog changes (mainly the toast table removal).
This commit is contained in:
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/utils/init/postinit.c,v 1.209 2010/04/20 01:38:52 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/init/postinit.c,v 1.210 2010/04/20 23:48:47 tgl Exp $
|
||||
*
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
@ -552,7 +552,7 @@ InitPostgres(const char *in_dbname, Oid dboid, const char *username,
|
||||
|
||||
/*
|
||||
* Load relcache entries for the shared system catalogs. This must create
|
||||
* at least an entry for pg_database.
|
||||
* at least entries for pg_database and catalogs used for authentication.
|
||||
*/
|
||||
RelationCacheInitializePhase2();
|
||||
|
||||
@ -585,14 +585,60 @@ InitPostgres(const char *in_dbname, Oid dboid, const char *username,
|
||||
(void) GetTransactionSnapshot();
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform client authentication if necessary, then figure out our
|
||||
* postgres user ID, and see if we are a superuser.
|
||||
*
|
||||
* In standalone mode and in autovacuum worker processes, we use a fixed
|
||||
* ID, otherwise we figure it out from the authenticated user name.
|
||||
*/
|
||||
if (bootstrap || IsAutoVacuumWorkerProcess())
|
||||
{
|
||||
InitializeSessionUserIdStandalone();
|
||||
am_superuser = true;
|
||||
}
|
||||
else if (!IsUnderPostmaster)
|
||||
{
|
||||
InitializeSessionUserIdStandalone();
|
||||
am_superuser = true;
|
||||
if (!ThereIsAtLeastOneRole())
|
||||
ereport(WARNING,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("no roles are defined in this database system"),
|
||||
errhint("You should immediately run CREATE USER \"%s\" SUPERUSER;.",
|
||||
username)));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* normal multiuser case */
|
||||
Assert(MyProcPort != NULL);
|
||||
PerformAuthentication(MyProcPort);
|
||||
InitializeSessionUserId(username);
|
||||
am_superuser = superuser();
|
||||
}
|
||||
|
||||
/*
|
||||
* If walsender, we're done here --- we don't want to connect to any
|
||||
* particular database.
|
||||
*/
|
||||
if (am_walsender)
|
||||
{
|
||||
Assert(!bootstrap);
|
||||
/* report this backend in the PgBackendStatus array */
|
||||
pgstat_bestart();
|
||||
/* close the transaction we started above */
|
||||
CommitTransactionCommand();
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set up the global variables holding database id and default tablespace.
|
||||
* But note we won't actually try to touch the database just yet.
|
||||
*
|
||||
* We take a shortcut in the bootstrap and walsender case, otherwise we
|
||||
* have to look up the db's entry in pg_database.
|
||||
* We take a shortcut in the bootstrap case, otherwise we have to look up
|
||||
* the db's entry in pg_database.
|
||||
*/
|
||||
if (bootstrap || am_walsender)
|
||||
if (bootstrap)
|
||||
{
|
||||
MyDatabaseId = TemplateDbOid;
|
||||
MyDatabaseTableSpace = DEFAULTTABLESPACE_OID;
|
||||
@ -655,7 +701,7 @@ InitPostgres(const char *in_dbname, Oid dboid, const char *username,
|
||||
* AccessShareLock for such sessions and thereby not conflict against
|
||||
* CREATE DATABASE.
|
||||
*/
|
||||
if (!bootstrap && !am_walsender)
|
||||
if (!bootstrap)
|
||||
LockSharedObject(DatabaseRelationId, MyDatabaseId, 0,
|
||||
RowExclusiveLock);
|
||||
|
||||
@ -664,7 +710,7 @@ InitPostgres(const char *in_dbname, Oid dboid, const char *username,
|
||||
* If there was a concurrent DROP DATABASE, this ensures we will die
|
||||
* cleanly without creating a mess.
|
||||
*/
|
||||
if (!bootstrap && !am_walsender)
|
||||
if (!bootstrap)
|
||||
{
|
||||
HeapTuple tuple;
|
||||
|
||||
@ -684,7 +730,7 @@ InitPostgres(const char *in_dbname, Oid dboid, const char *username,
|
||||
*/
|
||||
fullpath = GetDatabasePath(MyDatabaseId, MyDatabaseTableSpace);
|
||||
|
||||
if (!bootstrap && !am_walsender)
|
||||
if (!bootstrap)
|
||||
{
|
||||
if (access(fullpath, F_OK) == -1)
|
||||
{
|
||||
@ -715,51 +761,16 @@ InitPostgres(const char *in_dbname, Oid dboid, const char *username,
|
||||
*/
|
||||
RelationCacheInitializePhase3();
|
||||
|
||||
/*
|
||||
* Perform client authentication if necessary, then figure out our
|
||||
* postgres user ID, and see if we are a superuser.
|
||||
*
|
||||
* In standalone mode and in autovacuum worker processes, we use a fixed
|
||||
* ID, otherwise we figure it out from the authenticated user name.
|
||||
*/
|
||||
if (bootstrap || IsAutoVacuumWorkerProcess())
|
||||
{
|
||||
InitializeSessionUserIdStandalone();
|
||||
am_superuser = true;
|
||||
}
|
||||
else if (!IsUnderPostmaster)
|
||||
{
|
||||
InitializeSessionUserIdStandalone();
|
||||
am_superuser = true;
|
||||
if (!ThereIsAtLeastOneRole())
|
||||
ereport(WARNING,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("no roles are defined in this database system"),
|
||||
errhint("You should immediately run CREATE USER \"%s\" SUPERUSER;.",
|
||||
username)));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* normal multiuser case */
|
||||
Assert(MyProcPort != NULL);
|
||||
PerformAuthentication(MyProcPort);
|
||||
InitializeSessionUserId(username);
|
||||
am_superuser = superuser();
|
||||
}
|
||||
|
||||
/* set up ACL framework (so CheckMyDatabase can check permissions) */
|
||||
initialize_acl();
|
||||
|
||||
/* Process pg_db_role_setting options */
|
||||
process_settings(MyDatabaseId, GetSessionUserId());
|
||||
|
||||
/*
|
||||
* Re-read the pg_database row for our database, check permissions and set
|
||||
* up database-specific GUC settings. We can't do this until all the
|
||||
* database-access infrastructure is up. (Also, it wants to know if the
|
||||
* user is a superuser, so the above stuff has to happen first.)
|
||||
*/
|
||||
if (!bootstrap && !am_walsender)
|
||||
if (!bootstrap)
|
||||
CheckMyDatabase(dbname, am_superuser);
|
||||
|
||||
/*
|
||||
@ -841,6 +852,9 @@ InitPostgres(const char *in_dbname, Oid dboid, const char *username,
|
||||
}
|
||||
}
|
||||
|
||||
/* Process pg_db_role_setting options */
|
||||
process_settings(MyDatabaseId, GetSessionUserId());
|
||||
|
||||
/* Apply PostAuthDelay as soon as we've read all options */
|
||||
if (PostAuthDelay > 0)
|
||||
pg_usleep(PostAuthDelay * 1000000L);
|
||||
@ -856,10 +870,6 @@ InitPostgres(const char *in_dbname, Oid dboid, const char *username,
|
||||
/* initialize client encoding */
|
||||
InitializeClientEncoding();
|
||||
|
||||
/* reset the database for walsender */
|
||||
if (am_walsender)
|
||||
MyProc->databaseId = MyDatabaseId = InvalidOid;
|
||||
|
||||
/* report this backend in the PgBackendStatus array */
|
||||
if (!bootstrap)
|
||||
pgstat_bestart();
|
||||
|
Reference in New Issue
Block a user