aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/init/miscinit.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/utils/init/miscinit.c')
-rw-r--r--src/backend/utils/init/miscinit.c49
1 files changed, 43 insertions, 6 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);