diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index dde4bc25b1..8e00327a5d 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -567,6 +567,9 @@ int postmaster_alive_fds[2] = {-1, -1}; HANDLE PostmasterHandle; #endif +StartupPacketTimeout_hook_type StartupPacketTimeout_hook = NULL; +BadConnPacket_hook_type BadConnPacket_hook = NULL; + /* * Postmaster main entry point */ @@ -4462,8 +4465,11 @@ BackendInitialize(Port *port) * Stop here if it was bad or a cancel packet. ProcessStartupPacket * already did any appropriate error reporting. */ - if (status != STATUS_OK) + if (status != STATUS_OK) { + if (BadConnPacket_hook) + (*BadConnPacket_hook) (port); proc_exit(0); + } /* * Now that we have the user and database name, we can set the process @@ -5323,6 +5329,11 @@ dummy_handler(SIGNAL_ARGS) static void StartupPacketTimeoutHandler(void) { + if (StartupPacketTimeout_hook) + (*StartupPacketTimeout_hook) (MyProcPort); + ereport(COMMERROR, + (errcode(ERRCODE_PROTOCOL_VIOLATION), + errmsg("timeout while processing startup packet"))); _exit(1); } diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c index 6b9082604f..562ed331bf 100644 --- a/src/backend/utils/init/postinit.c +++ b/src/backend/utils/init/postinit.c @@ -67,6 +67,14 @@ #include "utils/syscache.h" #include "utils/timeout.h" +/* + * Hooks to be used when a connection has been refused in case of bad + * database name, bad database oid or bad permissions. + */ +BadDb_hook_type baddbname_hook = NULL; +BadDb_hook_type baddboid_hook = NULL; +BadDb_hook_type baddbperm_hook = NULL; + static HeapTuple GetDatabaseTuple(const char *dbname); static HeapTuple GetDatabaseTupleByOid(Oid dboid); static void PerformAuthentication(Port *port); @@ -360,10 +368,14 @@ CheckMyDatabase(const char *name, bool am_superuser, bool override_allow_connect if (!am_superuser && pg_database_aclcheck(MyDatabaseId, GetUserId(), ACL_CONNECT) != ACLCHECK_OK) + { + if (baddbperm_hook) + (*baddbperm_hook) (MyProcPort); ereport(FATAL, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), errmsg("permission denied for database \"%s\"", name), errdetail("User does not have CONNECT privilege."))); + } /* * Check connection limit for this database. @@ -918,9 +930,13 @@ InitPostgres(const char *in_dbname, Oid dboid, const char *username, tuple = GetDatabaseTuple(in_dbname); if (!HeapTupleIsValid(tuple)) + { + if (baddbname_hook) + (*baddbname_hook) (MyProcPort); ereport(FATAL, (errcode(ERRCODE_UNDEFINED_DATABASE), errmsg("database \"%s\" does not exist", in_dbname))); + } dbform = (Form_pg_database) GETSTRUCT(tuple); MyDatabaseId = dbform->oid; MyDatabaseTableSpace = dbform->dattablespace; @@ -935,9 +951,13 @@ InitPostgres(const char *in_dbname, Oid dboid, const char *username, tuple = GetDatabaseTupleByOid(dboid); if (!HeapTupleIsValid(tuple)) + { + if (baddboid_hook) + (*baddboid_hook) (MyProcPort); ereport(FATAL, (errcode(ERRCODE_UNDEFINED_DATABASE), errmsg("database %u does not exist", dboid))); + } dbform = (Form_pg_database) GETSTRUCT(tuple); MyDatabaseId = dbform->oid; MyDatabaseTableSpace = dbform->dattablespace; diff --git a/src/include/postmaster/postmaster.h b/src/include/postmaster/postmaster.h index 90e333ccd2..f42c19a4d1 100644 --- a/src/include/postmaster/postmaster.h +++ b/src/include/postmaster/postmaster.h @@ -63,6 +63,19 @@ extern Size ShmemBackendArraySize(void); extern void ShmemBackendArrayAllocation(void); #endif +/* kluge to avoid including libpq/libpq-be.h here */ +struct Port; +typedef void (*BadDb_hook_type) (const struct Port *); +extern PGDLLIMPORT BadDb_hook_type baddbname_hook; +extern PGDLLIMPORT BadDb_hook_type baddboid_hook; +extern PGDLLIMPORT BadDb_hook_type baddbperm_hook; + +typedef void (*BadConnPacket_hook_type) (const struct Port *); +extern PGDLLIMPORT BadConnPacket_hook_type BadConnPacket_hook; + +typedef void (*StartupPacketTimeout_hook_type) (const struct Port *); +extern PGDLLIMPORT StartupPacketTimeout_hook_type StartupPacketTimeout_hook; + /* * Note: MAX_BACKENDS is limited to 2^18-1 because that's the width reserved * for buffer references in buf_internals.h. This limitation could be lifted