1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-09 06:21:09 +03:00

Code review for GRANT CONNECT patch. Spell the privilege as CONNECT not

CONNECTION, fix a number of places that were missed (eg pg_dump support),
avoid executing an extra search of pg_database during startup.
This commit is contained in:
Tom Lane
2006-04-30 21:15:33 +00:00
parent 986085a7f0
commit 82a2881c5b
12 changed files with 118 additions and 81 deletions

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/catalog/aclchk.c,v 1.126 2006/04/30 02:09:07 momjian Exp $
* $PostgreSQL: pgsql/src/backend/catalog/aclchk.c,v 1.127 2006/04/30 21:15:33 tgl Exp $
*
* NOTES
* See acl.h.
@@ -1368,7 +1368,7 @@ string_to_privilege(const char *privname)
return ACL_CREATE_TEMP;
if (strcmp(privname, "temp") == 0)
return ACL_CREATE_TEMP;
if (strcmp(privname, "connection") == 0)
if (strcmp(privname, "connect") == 0)
return ACL_CONNECT;
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
@@ -1404,7 +1404,7 @@ privilege_to_string(AclMode privilege)
case ACL_CREATE_TEMP:
return "TEMP";
case ACL_CONNECT:
return "CONNECTION";
return "CONNECT";
default:
elog(ERROR, "unrecognized privilege: %d", (int) privilege);
}
@@ -1661,10 +1661,6 @@ pg_database_aclmask(Oid db_oid, Oid roleid,
ScanKeyData entry[1];
SysScanDesc scan;
HeapTuple tuple;
Datum aclDatum;
bool isNull;
Acl *acl;
Oid ownerId;
/* Superusers bypass all permission checking. */
if (superuser_arg(roleid))
@@ -1688,10 +1684,33 @@ pg_database_aclmask(Oid db_oid, Oid roleid,
(errcode(ERRCODE_UNDEFINED_DATABASE),
errmsg("database with OID %u does not exist", db_oid)));
ownerId = ((Form_pg_database) GETSTRUCT(tuple))->datdba;
result = pg_database_tuple_aclmask(tuple, RelationGetDescr(pg_database),
roleid, mask, how);
aclDatum = heap_getattr(tuple, Anum_pg_database_datacl,
RelationGetDescr(pg_database), &isNull);
systable_endscan(scan);
heap_close(pg_database, AccessShareLock);
return result;
}
/*
* This is split out so that ReverifyMyDatabase can perform an ACL check
* without a whole extra search of pg_database
*/
AclMode
pg_database_tuple_aclmask(HeapTuple db_tuple, TupleDesc tupdesc,
Oid roleid, AclMode mask, AclMaskHow how)
{
AclMode result;
Datum aclDatum;
bool isNull;
Acl *acl;
Oid ownerId;
ownerId = ((Form_pg_database) GETSTRUCT(db_tuple))->datdba;
aclDatum = heap_getattr(db_tuple, Anum_pg_database_datacl,
tupdesc, &isNull);
if (isNull)
{
@@ -1711,9 +1730,6 @@ pg_database_aclmask(Oid db_oid, Oid roleid,
if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
pfree(acl);
systable_endscan(scan);
heap_close(pg_database, AccessShareLock);
return result;
}

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/adt/acl.c,v 1.132 2006/04/30 02:09:07 momjian Exp $
* $PostgreSQL: pgsql/src/backend/utils/adt/acl.c,v 1.133 2006/04/30 21:15:33 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -553,7 +553,8 @@ acldefault(GrantObjectType objtype, Oid ownerId)
owner_default = ACL_ALL_RIGHTS_SEQUENCE;
break;
case ACL_OBJECT_DATABASE:
world_default = ACL_CREATE_TEMP | ACL_CONNECT; /* not NO_RIGHTS! */
/* for backwards compatibility, grant some rights by default */
world_default = ACL_CREATE_TEMP | ACL_CONNECT;
owner_default = ACL_ALL_RIGHTS_DATABASE;
break;
case ACL_OBJECT_FUNCTION:
@@ -1341,6 +1342,8 @@ convert_priv_string(text *priv_type_text)
return ACL_CREATE_TEMP;
if (pg_strcasecmp(priv_type, "TEMPORARY") == 0)
return ACL_CREATE_TEMP;
if (pg_strcasecmp(priv_type, "CONNECT") == 0)
return ACL_CONNECT;
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
@@ -1778,6 +1781,11 @@ convert_database_priv_string(text *priv_type_text)
if (pg_strcasecmp(priv_type, "TEMP WITH GRANT OPTION") == 0)
return ACL_GRANT_OPTION_FOR(ACL_CREATE_TEMP);
if (pg_strcasecmp(priv_type, "CONNECT") == 0)
return ACL_CONNECT;
if (pg_strcasecmp(priv_type, "CONNECT WITH GRANT OPTION") == 0)
return ACL_GRANT_OPTION_FOR(ACL_CONNECT);
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("unrecognized privilege type: \"%s\"", priv_type)));

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/init/postinit.c,v 1.163 2006/04/30 02:09:07 momjian Exp $
* $PostgreSQL: pgsql/src/backend/utils/init/postinit.c,v 1.164 2006/04/30 21:15:33 tgl Exp $
*
*
*-------------------------------------------------------------------------
@@ -51,7 +51,7 @@
static bool FindMyDatabase(const char *name, Oid *db_id, Oid *db_tablespace);
static void ReverifyMyDatabase(const char *name, const char *user_name);
static void ReverifyMyDatabase(const char *name, bool am_superuser);
static void InitCommunication(void);
static void ShutdownPostgres(int code, Datum arg);
static bool ThereIsAtLeastOneRole(void);
@@ -127,12 +127,11 @@ FindMyDatabase(const char *name, Oid *db_id, Oid *db_tablespace)
* of pg_database.
*
* To avoid having to read pg_database more times than necessary
* during session startup, this place is also fitting to set up any
* database-specific configuration variables.
* during session startup, this place is also fitting to check CONNECT
* privilege and set up any database-specific configuration variables.
*/
static void
ReverifyMyDatabase(const char *name, const char *user_name)
ReverifyMyDatabase(const char *name, bool am_superuser)
{
Relation pgdbrel;
SysScanDesc pgdbscan;
@@ -195,6 +194,22 @@ ReverifyMyDatabase(const char *name, const char *user_name)
errmsg("database \"%s\" is not currently accepting connections",
name)));
/*
* Check privilege to connect to the database. To avoid making
* a whole extra search of pg_database here, we don't go through
* pg_database_aclcheck, but instead use a lower-level routine
* that we can pass the pg_database tuple to.
*/
if (!am_superuser &&
pg_database_tuple_aclmask(tup, RelationGetDescr(pgdbrel),
GetUserId(),
ACL_CONNECT, ACLMASK_ANY) == 0)
ereport(FATAL,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("permission denied for database %s",
NameStr(dbform->datname)),
errdetail("User does not have CONNECT privilege.")));
/*
* Check connection limit for this database.
*
@@ -206,29 +221,12 @@ ReverifyMyDatabase(const char *name, const char *user_name)
* just document that the connection limit is approximate.
*/
if (dbform->datconnlimit >= 0 &&
!superuser() &&
!am_superuser &&
CountDBBackends(MyDatabaseId) > dbform->datconnlimit)
ereport(FATAL,
(errcode(ERRCODE_TOO_MANY_CONNECTIONS),
errmsg("too many connections for database \"%s\"",
name)));
/*
* Checking for privilege to connect to the database
* We want to bypass the test if we are running in bootstrap mode
*/
if (!IsBootstrapProcessingMode())
{
if(pg_database_aclcheck(MyDatabaseId,GetUserId()
,ACL_CONNECT) != ACLCHECK_OK )
{
ereport(FATAL,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("couldn't connect to database %s", NameStr(dbform->datname)),
errdetail("User %s doesn't have the CONNECTION privilege for database %s.",
user_name, NameStr(dbform->datname))));
}
}
}
/*
@@ -476,15 +474,20 @@ InitPostgres(const char *dbname, const char *username)
RelationCacheInitializePhase2();
/*
* Figure out our postgres user id. In standalone mode and in the
* autovacuum process, we use a fixed id, otherwise we figure it out from
* the authenticated user name.
* Figure out our postgres user id, and see if we are a superuser.
*
* In standalone mode and in the autovacuum process, we use a fixed id,
* otherwise we figure it out from the authenticated user name.
*/
if (bootstrap || autovacuum)
{
InitializeSessionUserIdStandalone();
am_superuser = true;
}
else if (!IsUnderPostmaster)
{
InitializeSessionUserIdStandalone();
am_superuser = true;
if (!ThereIsAtLeastOneRole())
ereport(WARNING,
(errcode(ERRCODE_UNDEFINED_OBJECT),
@@ -496,8 +499,12 @@ InitPostgres(const char *dbname, const char *username)
{
/* normal multiuser case */
InitializeSessionUserId(username);
am_superuser = superuser();
}
/* set up ACL framework (so ReverifyMyDatabase can check permissions) */
initialize_acl();
/*
* Unless we are bootstrapping, double-check that InitMyDatabaseInfo() got
* a correct result. We can't do this until all the database-access
@@ -505,7 +512,7 @@ InitPostgres(const char *dbname, const char *username)
* superuser, so the above stuff has to happen first.)
*/
if (!bootstrap)
ReverifyMyDatabase(dbname,username);
ReverifyMyDatabase(dbname, am_superuser);
/*
* Final phase of relation cache startup: write a new cache file if
@@ -514,14 +521,6 @@ InitPostgres(const char *dbname, const char *username)
*/
RelationCacheInitializePhase3();
/*
* Check if user is a superuser.
*/
if (bootstrap || autovacuum)
am_superuser = true;
else
am_superuser = superuser();
/*
* Check a normal user hasn't connected to a superuser reserved slot.
*/
@@ -540,9 +539,6 @@ InitPostgres(const char *dbname, const char *username)
/* set default namespace search path */
InitializeSearchPath();
/* set up ACL framework (currently just sets RolMemCache callback) */
initialize_acl();
/* initialize client encoding */
InitializeClientEncoding();