diff options
Diffstat (limited to 'src/backend/utils')
-rw-r--r-- | src/backend/utils/init/miscinit.c | 49 | ||||
-rw-r--r-- | src/backend/utils/init/postinit.c | 47 |
2 files changed, 79 insertions, 17 deletions
diff --git a/src/backend/utils/init/miscinit.c b/src/backend/utils/init/miscinit.c index 66d6d1725e0..f6c50438e03 100644 --- a/src/backend/utils/init/miscinit.c +++ b/src/backend/utils/init/miscinit.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/init/miscinit.c,v 1.147 2005/07/25 22:12:33 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/init/miscinit.c,v 1.148 2005/07/31 17:19:19 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -36,6 +36,8 @@ #include "storage/fd.h" #include "storage/ipc.h" #include "storage/pg_shmem.h" +#include "storage/proc.h" +#include "storage/procarray.h" #include "utils/builtins.h" #include "utils/guc.h" #include "utils/lsyscache.h" @@ -404,17 +406,52 @@ InitializeSessionUserId(const char *rolename) rform = (Form_pg_authid) GETSTRUCT(roleTup); roleid = HeapTupleGetOid(roleTup); - if (!rform->rolcanlogin) - ereport(FATAL, - (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION), - errmsg("role \"%s\" is not permitted to log in", rolename))); - AuthenticatedUserId = roleid; AuthenticatedUserIsSuperuser = rform->rolsuper; /* This sets OuterUserId/CurrentUserId too */ SetSessionUserId(roleid, AuthenticatedUserIsSuperuser); + /* Also mark our PGPROC entry with the authenticated user id */ + /* (We assume this is an atomic store so no lock is needed) */ + MyProc->roleId = roleid; + + /* + * These next checks are not enforced when in standalone mode, so that + * there is a way to recover from sillinesses like + * "UPDATE pg_authid SET rolcanlogin = false;". + * + * We do not enforce them for the autovacuum process either. + */ + if (IsUnderPostmaster && !IsAutoVacuumProcess()) + { + /* + * Is role allowed to login at all? + */ + if (!rform->rolcanlogin) + ereport(FATAL, + (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION), + errmsg("role \"%s\" is not permitted to log in", + rolename))); + /* + * Check connection limit for this role. + * + * There is a race condition here --- we create our PGPROC before + * checking for other PGPROCs. If two backends did this at about the + * same time, they might both think they were over the limit, while + * ideally one should succeed and one fail. Getting that to work + * exactly seems more trouble than it is worth, however; instead + * we just document that the connection limit is approximate. + */ + if (rform->rolconnlimit >= 0 && + !AuthenticatedUserIsSuperuser && + CountUserBackends(roleid) > rform->rolconnlimit) + ereport(FATAL, + (errcode(ERRCODE_TOO_MANY_CONNECTIONS), + errmsg("too many connections for role \"%s\"", + rolename))); + } + /* Record username and superuser status as GUC settings too */ SetConfigOption("session_authorization", rolename, PGC_BACKEND, PGC_S_OVERRIDE); diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c index b013eca86cf..d06fa5db369 100644 --- a/src/backend/utils/init/postinit.c +++ b/src/backend/utils/init/postinit.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/init/postinit.c,v 1.154 2005/07/29 19:30:05 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/init/postinit.c,v 1.155 2005/07/31 17:19:19 tgl Exp $ * * *------------------------------------------------------------------------- @@ -169,18 +169,43 @@ ReverifyMyDatabase(const char *name) name, MyDatabaseId))); } + dbform = (Form_pg_database) GETSTRUCT(tup); + /* - * Also check that the database is currently allowing connections. - * (We do not enforce this in standalone mode, however, so that there is - * a way to recover from "UPDATE pg_database SET datallowconn = false;". - * We do not enforce it for the autovacuum process either.) + * These next checks are not enforced when in standalone mode, so that + * there is a way to recover from disabling all access to all databases, + * for example "UPDATE pg_database SET datallowconn = false;". + * + * We do not enforce them for the autovacuum process either. */ - dbform = (Form_pg_database) GETSTRUCT(tup); - if (IsUnderPostmaster && !IsAutoVacuumProcess() && !dbform->datallowconn) - ereport(FATAL, - (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), - errmsg("database \"%s\" is not currently accepting connections", - name))); + if (IsUnderPostmaster && !IsAutoVacuumProcess()) + { + /* + * Check that the database is currently allowing connections. + */ + if (!dbform->datallowconn) + ereport(FATAL, + (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), + errmsg("database \"%s\" is not currently accepting connections", + name))); + /* + * Check connection limit for this database. + * + * There is a race condition here --- we create our PGPROC before + * checking for other PGPROCs. If two backends did this at about the + * same time, they might both think they were over the limit, while + * ideally one should succeed and one fail. Getting that to work + * exactly seems more trouble than it is worth, however; instead + * we just document that the connection limit is approximate. + */ + if (dbform->datconnlimit >= 0 && + !superuser() && + CountDBBackends(MyDatabaseId) > dbform->datconnlimit) + ereport(FATAL, + (errcode(ERRCODE_TOO_MANY_CONNECTIONS), + errmsg("too many connections for database \"%s\"", + name))); + } /* * OK, we're golden. Next to-do item is to save the encoding |