diff options
author | Peter Eisentraut <peter_e@gmx.net> | 2001-05-27 09:59:30 +0000 |
---|---|---|
committer | Peter Eisentraut <peter_e@gmx.net> | 2001-05-27 09:59:30 +0000 |
commit | 96147a6d1c15b7604838dcd5de5ebd771f551d96 (patch) | |
tree | 54ad7d06fff6c8d331194285bf3a7718630f5976 /src | |
parent | 52350c7ad965d856da74514f89b88ce4ffbd18e7 (diff) | |
download | postgresql-96147a6d1c15b7604838dcd5de5ebd771f551d96.tar.gz postgresql-96147a6d1c15b7604838dcd5de5ebd771f551d96.zip |
Make UPDATE and DELETE privileges distinct. Add REFERENCES and TRIGGER
privileges. INSERT and COPY FROM now require INSERT (only). Add
privileges regression test.
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/catalog/aclchk.c | 28 | ||||
-rw-r--r-- | src/backend/commands/command.c | 7 | ||||
-rw-r--r-- | src/backend/commands/comment.c | 4 | ||||
-rw-r--r-- | src/backend/commands/copy.c | 4 | ||||
-rw-r--r-- | src/backend/commands/sequence.c | 8 | ||||
-rw-r--r-- | src/backend/commands/trigger.c | 8 | ||||
-rw-r--r-- | src/backend/executor/execMain.c | 15 | ||||
-rw-r--r-- | src/backend/parser/gram.y | 32 | ||||
-rw-r--r-- | src/backend/tcop/utility.c | 6 | ||||
-rw-r--r-- | src/backend/utils/adt/acl.c | 46 | ||||
-rw-r--r-- | src/include/utils/acl.h | 33 | ||||
-rw-r--r-- | src/test/regress/expected/privileges.out | 198 | ||||
-rw-r--r-- | src/test/regress/parallel_schedule | 1 | ||||
-rw-r--r-- | src/test/regress/pg_regress.sh | 14 | ||||
-rw-r--r-- | src/test/regress/serial_schedule | 3 | ||||
-rw-r--r-- | src/test/regress/sql/privileges.sql | 146 |
16 files changed, 465 insertions, 88 deletions
diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c index bfc4cc2a454..5ef74cb1d55 100644 --- a/src/backend/catalog/aclchk.c +++ b/src/backend/catalog/aclchk.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/aclchk.c,v 1.47 2001/03/22 03:59:18 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/aclchk.c,v 1.48 2001/05/27 09:59:28 petere Exp $ * * NOTES * See acl.h. @@ -46,7 +46,7 @@ char *aclcheck_error_strings[] = { }; -#ifdef ACLDEBUG_TRACE +#ifdef ACLDEBUG static dumpacl(Acl *acl) { @@ -62,7 +62,7 @@ dumpacl(Acl *acl) PointerGetDatum(aip + i)))); } -#endif +#endif /* ACLDEBUG */ /* * ChangeAcl @@ -116,13 +116,13 @@ ChangeAcl(char *relname, old_acl = DatumGetAclPCopy(aclDatum); } -#ifdef ACLDEBUG_TRACE +#ifdef ACLDEBUG dumpacl(old_acl); #endif new_acl = aclinsert3(old_acl, mod_aip, modechg); -#ifdef ACLDEBUG_TRACE +#ifdef ACLDEBUG dumpacl(new_acl); #endif @@ -285,7 +285,7 @@ aclcheck(char *relname, Acl *acl, AclId id, AclIdType idtype, AclMode mode) { if (aip->ai_id == id) { -#ifdef ACLDEBUG_TRACE +#ifdef ACLDEBUG elog(DEBUG, "aclcheck: found user %u/%d", aip->ai_id, aip->ai_mode); #endif @@ -301,7 +301,7 @@ aclcheck(char *relname, Acl *acl, AclId id, AclIdType idtype, AclMode mode) { if (in_group(id, aip->ai_id)) { -#ifdef ACLDEBUG_TRACE +#ifdef ACLDEBUG elog(DEBUG, "aclcheck: found group %u/%d", aip->ai_id, aip->ai_mode); #endif @@ -324,7 +324,7 @@ aclcheck(char *relname, Acl *acl, AclId id, AclIdType idtype, AclMode mode) { if (aip->ai_id == id) { -#ifdef ACLDEBUG_TRACE +#ifdef ACLDEBUG elog(DEBUG, "aclcheck: found group %u/%d", aip->ai_id, aip->ai_mode); #endif @@ -341,7 +341,7 @@ aclcheck(char *relname, Acl *acl, AclId id, AclIdType idtype, AclMode mode) break; } -#ifdef ACLDEBUG_TRACE +#ifdef ACLDEBUG elog(DEBUG, "aclcheck: using world=%d", aidat->ai_mode); #endif return (aidat->ai_mode & mode) ? ACLCHECK_OK : ACLCHECK_NO_PRIV; @@ -371,7 +371,7 @@ pg_aclcheck(char *relname, Oid userid, AclMode mode) * pg_shadow.usecatupd is set. (This is to let superusers protect * themselves from themselves.) */ - if (((mode & ACL_WR) || (mode & ACL_AP)) && + if (((mode & ACL_UPDATE) || (mode & ACL_INSERT) || (mode & ACL_DELETE)) && !allowSystemTableMods && IsSystemRelationName(relname) && strncmp(relname, "pg_temp.", strlen("pg_temp.")) != 0 && !((Form_pg_shadow) GETSTRUCT(tuple))->usecatupd) @@ -387,7 +387,7 @@ pg_aclcheck(char *relname, Oid userid, AclMode mode) */ if (((Form_pg_shadow) GETSTRUCT(tuple))->usesuper) { -#ifdef ACLDEBUG_TRACE +#ifdef ACLDEBUG elog(DEBUG, "pg_aclcheck: \"%s\" is superuser", usename); #endif @@ -454,7 +454,7 @@ pg_ownercheck(Oid userid, */ if (((Form_pg_shadow) GETSTRUCT(tuple))->usesuper) { -#ifdef ACLDEBUG_TRACE +#ifdef ACLDEBUG elog(DEBUG, "pg_ownercheck: user \"%s\" is superuser", usename); #endif @@ -528,7 +528,7 @@ pg_func_ownercheck(Oid userid, */ if (((Form_pg_shadow) GETSTRUCT(tuple))->usesuper) { -#ifdef ACLDEBUG_TRACE +#ifdef ACLDEBUG elog(DEBUG, "pg_ownercheck: user \"%s\" is superuser", usename); #endif @@ -576,7 +576,7 @@ pg_aggr_ownercheck(Oid userid, */ if (((Form_pg_shadow) GETSTRUCT(tuple))->usesuper) { -#ifdef ACLDEBUG_TRACE +#ifdef ACLDEBUG elog(DEBUG, "pg_aggr_ownercheck: user \"%s\" is superuser", usename); #endif diff --git a/src/backend/commands/command.c b/src/backend/commands/command.c index bc5153b8005..90cfba50be5 100644 --- a/src/backend/commands/command.c +++ b/src/backend/commands/command.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.128 2001/05/21 14:22:11 wieck Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.129 2001/05/27 09:59:28 petere Exp $ * * NOTES * The PerformAddAttribute() code, like most of the relation @@ -1939,9 +1939,10 @@ LockTableCommand(LockStmt *lockstmt) elog(ERROR, "LOCK TABLE: %s is not a table", lockstmt->relname); if (lockstmt->mode == AccessShareLock) - aclresult = pg_aclcheck(lockstmt->relname, GetUserId(), ACL_RD); + aclresult = pg_aclcheck(lockstmt->relname, GetUserId(), ACL_SELECT); else - aclresult = pg_aclcheck(lockstmt->relname, GetUserId(), ACL_WR); + aclresult = pg_aclcheck(lockstmt->relname, GetUserId(), + ACL_UPDATE | ACL_DELETE); if (aclresult != ACLCHECK_OK) elog(ERROR, "LOCK TABLE: permission denied"); diff --git a/src/backend/commands/comment.c b/src/backend/commands/comment.c index 06397ab323f..7d3ba9b5618 100644 --- a/src/backend/commands/comment.c +++ b/src/backend/commands/comment.c @@ -7,7 +7,7 @@ * Copyright (c) 1999, PostgreSQL Global Development Group * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.27 2001/03/22 03:59:21 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.28 2001/05/27 09:59:29 petere Exp $ * *------------------------------------------------------------------------- */ @@ -468,7 +468,7 @@ CommentRewrite(char *rule, char *comment) #ifndef NO_SECURITY relation = RewriteGetRuleEventRel(rule); - aclcheck = pg_aclcheck(relation, GetUserId(), ACL_RU); + aclcheck = pg_aclcheck(relation, GetUserId(), ACL_RULE); if (aclcheck != ACLCHECK_OK) { elog(ERROR, "you are not permitted to comment on rule '%s'", diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c index 0f249fa385c..fbbade10331 100644 --- a/src/backend/commands/copy.c +++ b/src/backend/commands/copy.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.136 2001/03/22 06:16:11 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.137 2001/05/27 09:59:29 petere Exp $ * *------------------------------------------------------------------------- */ @@ -271,7 +271,7 @@ DoCopy(char *relname, bool binary, bool oids, bool from, bool pipe, FILE *fp; Relation rel; - const AclMode required_access = from ? ACL_WR : ACL_RD; + const AclMode required_access = from ? ACL_INSERT : ACL_SELECT; int result; /* diff --git a/src/backend/commands/sequence.c b/src/backend/commands/sequence.c index f1dbbf6d251..f37b6199b24 100644 --- a/src/backend/commands/sequence.c +++ b/src/backend/commands/sequence.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/sequence.c,v 1.55 2001/05/10 20:38:49 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/sequence.c,v 1.56 2001/05/27 09:59:29 petere Exp $ * *------------------------------------------------------------------------- */ @@ -243,7 +243,7 @@ nextval(PG_FUNCTION_ARGS) rescnt = 0; bool logit = false; - if (pg_aclcheck(seqname, GetUserId(), ACL_WR) != ACLCHECK_OK) + if (pg_aclcheck(seqname, GetUserId(), ACL_UPDATE) != ACLCHECK_OK) elog(ERROR, "%s.nextval: you don't have permissions to set sequence %s", seqname, seqname); @@ -390,7 +390,7 @@ currval(PG_FUNCTION_ARGS) SeqTable elm; int32 result; - if (pg_aclcheck(seqname, GetUserId(), ACL_RD) != ACLCHECK_OK) + if (pg_aclcheck(seqname, GetUserId(), ACL_SELECT) != ACLCHECK_OK) elog(ERROR, "%s.currval: you don't have permissions to read sequence %s", seqname, seqname); @@ -428,7 +428,7 @@ do_setval(char *seqname, int32 next, bool iscalled) Buffer buf; Form_pg_sequence seq; - if (pg_aclcheck(seqname, GetUserId(), ACL_WR) != ACLCHECK_OK) + if (pg_aclcheck(seqname, GetUserId(), ACL_UPDATE) != ACLCHECK_OK) elog(ERROR, "%s.setval: you don't have permissions to set sequence %s", seqname, seqname); diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c index 70f2e1b2957..70c146530f1 100644 --- a/src/backend/commands/trigger.c +++ b/src/backend/commands/trigger.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.90 2001/03/22 06:16:11 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.91 2001/05/27 09:59:29 petere Exp $ * *------------------------------------------------------------------------- */ @@ -69,8 +69,10 @@ CreateTrigger(CreateTrigStmt *stmt) if (!allowSystemTableMods && IsSystemRelationName(stmt->relname)) elog(ERROR, "CreateTrigger: can't create trigger for system relation %s", stmt->relname); - if (!pg_ownercheck(GetUserId(), stmt->relname, RELNAME)) - elog(ERROR, "%s: %s", stmt->relname, aclcheck_error_strings[ACLCHECK_NOT_OWNER]); + if (pg_aclcheck(stmt->relname, GetUserId(), + stmt->isconstraint ? ACL_REFERENCES : ACL_TRIGGER) + != ACLCHECK_OK) + elog(ERROR, "permission denied"); /* * If trigger is a constraint, user trigger name as constraint name diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c index eda6ce518d2..f87b674b074 100644 --- a/src/backend/executor/execMain.c +++ b/src/backend/executor/execMain.c @@ -27,7 +27,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.140 2001/05/15 00:33:36 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.141 2001/05/27 09:59:29 petere Exp $ * *------------------------------------------------------------------------- */ @@ -420,7 +420,7 @@ ExecCheckRTEPerms(RangeTblEntry *rte, CmdType operation) if (rte->checkForRead) { - aclcheck_result = CHECK(ACL_RD); + aclcheck_result = CHECK(ACL_SELECT); if (aclcheck_result != ACLCHECK_OK) elog(ERROR, "%s: %s", relName, aclcheck_error_strings[aclcheck_result]); @@ -437,15 +437,14 @@ ExecCheckRTEPerms(RangeTblEntry *rte, CmdType operation) switch (operation) { case CMD_INSERT: - /* Accept either APPEND or WRITE access for this */ - aclcheck_result = CHECK(ACL_AP); - if (aclcheck_result != ACLCHECK_OK) - aclcheck_result = CHECK(ACL_WR); + aclcheck_result = CHECK(ACL_INSERT); break; case CMD_SELECT: - case CMD_DELETE: case CMD_UPDATE: - aclcheck_result = CHECK(ACL_WR); + aclcheck_result = CHECK(ACL_UPDATE); + break; + case CMD_DELETE: + aclcheck_result = CHECK(ACL_DELETE); break; default: elog(ERROR, "ExecCheckRTEPerms: bogus operation %d", diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 5857f6ee642..37c28495e54 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -11,7 +11,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.226 2001/05/14 20:30:20 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.227 2001/05/27 09:59:29 petere Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT @@ -2234,19 +2234,19 @@ from_in: IN * *****************************************************************************/ -GrantStmt: GRANT privileges ON relation_name_list TO grantee opt_with_grant +GrantStmt: GRANT privileges ON opt_table relation_name_list TO grantee opt_with_grant { - $$ = (Node*)makeAclStmt($2,$4,$6,'+'); + $$ = (Node*)makeAclStmt($2,$5,$7,'+'); } ; privileges: ALL PRIVILEGES { - $$ = aclmakepriv("rwaR",0); + $$ = aclmakepriv(ACL_MODE_STR,0); } | ALL { - $$ = aclmakepriv("rwaR",0); + $$ = aclmakepriv(ACL_MODE_STR,0); } | operation_commalist { @@ -2266,23 +2266,31 @@ operation_commalist: operation operation: SELECT { - $$ = ACL_MODE_RD_CHR; + $$ = ACL_MODE_SELECT_CHR; } | INSERT { - $$ = ACL_MODE_AP_CHR; + $$ = ACL_MODE_INSERT_CHR; } | UPDATE { - $$ = ACL_MODE_WR_CHR; + $$ = ACL_MODE_UPDATE_CHR; } | DELETE { - $$ = ACL_MODE_WR_CHR; + $$ = ACL_MODE_DELETE_CHR; } | RULE { - $$ = ACL_MODE_RU_CHR; + $$ = ACL_MODE_RULE_CHR; + } + | REFERENCES + { + $$ = ACL_MODE_REFERENCES_CHR; + } + | TRIGGER + { + $$ = ACL_MODE_TRIGGER_CHR; } ; @@ -2315,9 +2323,9 @@ opt_with_grant: WITH GRANT OPTION * *****************************************************************************/ -RevokeStmt: REVOKE privileges ON relation_name_list FROM grantee +RevokeStmt: REVOKE privileges ON opt_table relation_name_list FROM grantee { - $$ = (Node*)makeAclStmt($2,$4,$6,'-'); + $$ = (Node*)makeAclStmt($2,$5,$7,'-'); } ; diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c index b616f7e68ef..dc569455b26 100644 --- a/src/backend/tcop/utility.c +++ b/src/backend/tcop/utility.c @@ -10,7 +10,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.110 2001/05/07 00:43:23 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.111 2001/05/27 09:59:29 petere Exp $ * *------------------------------------------------------------------------- */ @@ -267,7 +267,7 @@ ProcessUtility(Node *parsetree, int aclcheck_result; relationName = RewriteGetRuleEventRel(rulename); - aclcheck_result = pg_aclcheck(relationName, GetUserId(), ACL_RU); + aclcheck_result = pg_aclcheck(relationName, GetUserId(), ACL_RULE); if (aclcheck_result != ACLCHECK_OK) elog(ERROR, "%s: %s", relationName, aclcheck_error_strings[aclcheck_result]); @@ -550,7 +550,7 @@ ProcessUtility(Node *parsetree, int aclcheck_result; relname = stmt->object->relname; - aclcheck_result = pg_aclcheck(relname, GetUserId(), ACL_RU); + aclcheck_result = pg_aclcheck(relname, GetUserId(), ACL_RULE); if (aclcheck_result != ACLCHECK_OK) elog(ERROR, "%s: %s", relname, aclcheck_error_strings[aclcheck_result]); set_ps_display(commandTag = "CREATE"); diff --git a/src/backend/utils/adt/acl.c b/src/backend/utils/adt/acl.c index 10e2f13bc32..f4e3fe9986d 100644 --- a/src/backend/utils/adt/acl.c +++ b/src/backend/utils/adt/acl.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/acl.c,v 1.58 2001/03/22 03:59:48 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/acl.c,v 1.59 2001/05/27 09:59:30 petere Exp $ * *------------------------------------------------------------------------- */ @@ -113,8 +113,8 @@ aclparse(char *s, AclItem *aip, unsigned *modechg) Assert(s && aip && modechg); -#ifdef ACLDEBUG_TRACE - printf("aclparse: input = '%s'\n", s); +#ifdef ACLDEBUG + elog(DEBUG, "aclparse: input = '%s'", s); #endif aip->ai_idtype = ACL_IDTYPE_UID; s = getid(s, name); @@ -155,17 +155,26 @@ aclparse(char *s, AclItem *aip, unsigned *modechg) { switch (*s) { - case ACL_MODE_AP_CHR: - aip->ai_mode |= ACL_AP; + case ACL_MODE_INSERT_CHR: + aip->ai_mode |= ACL_INSERT; break; - case ACL_MODE_RD_CHR: - aip->ai_mode |= ACL_RD; + case ACL_MODE_SELECT_CHR: + aip->ai_mode |= ACL_SELECT; break; - case ACL_MODE_WR_CHR: - aip->ai_mode |= ACL_WR; + case ACL_MODE_UPDATE_CHR: + aip->ai_mode |= ACL_UPDATE; break; - case ACL_MODE_RU_CHR: - aip->ai_mode |= ACL_RU; + case ACL_MODE_DELETE_CHR: + aip->ai_mode |= ACL_DELETE; + break; + case ACL_MODE_RULE_CHR: + aip->ai_mode |= ACL_RULE; + break; + case ACL_MODE_REFERENCES_CHR: + aip->ai_mode |= ACL_REFERENCES; + break; + case ACL_MODE_TRIGGER_CHR: + aip->ai_mode |= ACL_TRIGGER; break; default: elog(ERROR, "aclparse: mode flags must use \"%s\"", @@ -192,7 +201,7 @@ aclparse(char *s, AclItem *aip, unsigned *modechg) break; } -#ifdef ACLDEBUG_TRACE +#ifdef ACLDEBUG elog(DEBUG, "aclparse: correctly read [%x %d %x], modechg=%x", aip->ai_idtype, aip->ai_id, aip->ai_mode, *modechg); #endif @@ -269,7 +278,7 @@ aclitemout(PG_FUNCTION_ARGS) unsigned i; char *tmpname; - p = out = palloc(strlen("group =arwR ") + 1 + NAMEDATALEN); + p = out = palloc(strlen("group =" ACL_MODE_STR " ") + 1 + NAMEDATALEN); *p = '\0'; switch (aip->ai_idtype) @@ -368,14 +377,13 @@ acldefault(char *relname, AclId ownerid) AclItem *aip; #define ACL_WORLD_DEFAULT (ACL_NO) -/* #define ACL_WORLD_DEFAULT (ACL_RD|ACL_WR|ACL_AP|ACL_RU) */ -#define ACL_OWNER_DEFAULT (ACL_RD|ACL_WR|ACL_AP|ACL_RU) +#define ACL_OWNER_DEFAULT (ACL_INSERT|ACL_SELECT|ACL_UPDATE|ACL_DELETE|ACL_RULE|ACL_REFERENCES|ACL_TRIGGER) acl = makeacl(2); aip = ACL_DAT(acl); aip[0].ai_idtype = ACL_IDTYPE_WORLD; aip[0].ai_id = ACL_ID_WORLD; - aip[0].ai_mode = IsSystemRelationName(relname) ? ACL_RD : ACL_WORLD_DEFAULT; + aip[0].ai_mode = IsSystemRelationName(relname) ? ACL_SELECT : ACL_WORLD_DEFAULT; aip[1].ai_idtype = ACL_IDTYPE_UID; aip[1].ai_id = ownerid; aip[1].ai_mode = ACL_OWNER_DEFAULT; @@ -651,8 +659,8 @@ aclmakepriv(char *old_privlist, char new_priv) int i; int l; - Assert(strlen(old_privlist) < 5); - priv = palloc(5); /* at most "rwaR" */ ; + Assert(strlen(old_privlist) <= strlen(ACL_MODE_STR)); + priv = palloc(strlen(ACL_MODE_STR)+1); if (old_privlist == NULL || old_privlist[0] == '\0') { @@ -665,7 +673,7 @@ aclmakepriv(char *old_privlist, char new_priv) l = strlen(old_privlist); - if (l == 4) + if (l == strlen(ACL_MODE_STR)) { /* can't add any more privileges */ return priv; } diff --git a/src/include/utils/acl.h b/src/include/utils/acl.h index 7e09390c3ca..02e6094c51e 100644 --- a/src/include/utils/acl.h +++ b/src/include/utils/acl.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: acl.h,v 1.31 2001/03/22 04:01:10 momjian Exp $ + * $Id: acl.h,v 1.32 2001/05/27 09:59:30 petere Exp $ * * NOTES * For backward-compatibility purposes we have to allow there @@ -52,11 +52,14 @@ typedef uint8 AclIdType; typedef uint8 AclMode; #define ACL_NO 0 /* no permissions */ -#define ACL_AP (1<<0) /* append */ -#define ACL_RD (1<<1) /* read */ -#define ACL_WR (1<<2) /* write (append/delete/replace) */ -#define ACL_RU (1<<3) /* place rules */ -#define N_ACL_MODES 4 +#define ACL_INSERT (1<<0) +#define ACL_SELECT (1<<1) +#define ACL_UPDATE (1<<2) +#define ACL_DELETE (1<<3) +#define ACL_RULE (1<<4) +#define ACL_REFERENCES (1<<5) +#define ACL_TRIGGER (1<<6) +#define N_ACL_MODES 7 /* 1 plus the last 1<<x */ /* * AclItem @@ -146,11 +149,14 @@ typedef ArrayType IdList; #define ACL_MODECHG_ADD_CHR '+' #define ACL_MODECHG_DEL_CHR '-' #define ACL_MODECHG_EQL_CHR '=' -#define ACL_MODE_STR "arwR" /* list of valid characters */ -#define ACL_MODE_AP_CHR 'a' -#define ACL_MODE_RD_CHR 'r' -#define ACL_MODE_WR_CHR 'w' -#define ACL_MODE_RU_CHR 'R' +#define ACL_MODE_STR "arwdRxt" /* list of valid characters */ +#define ACL_MODE_INSERT_CHR 'a' /* formerly known as "append" */ +#define ACL_MODE_SELECT_CHR 'r' /* formerly known as "read" */ +#define ACL_MODE_UPDATE_CHR 'w' /* formerly known as "write" */ +#define ACL_MODE_DELETE_CHR 'd' +#define ACL_MODE_RULE_CHR 'R' +#define ACL_MODE_REFERENCES_CHR 'x' +#define ACL_MODE_TRIGGER_CHR 't' /* result codes for pg_aclcheck */ #define ACLCHECK_OK 0 @@ -162,11 +168,6 @@ typedef ArrayType IdList; extern char *aclcheck_error_strings[]; /* - * Enable ACL execution tracing and table dumps - */ -/*#define ACLDEBUG_TRACE*/ - -/* * routines used internally */ extern Acl *acldefault(char *relname, AclId ownerid); diff --git a/src/test/regress/expected/privileges.out b/src/test/regress/expected/privileges.out new file mode 100644 index 00000000000..cb376e0bbc8 --- /dev/null +++ b/src/test/regress/expected/privileges.out @@ -0,0 +1,198 @@ +-- +-- Test access privileges +-- +CREATE USER regressuser1; +CREATE USER regressuser2; +CREATE USER regressuser3; +CREATE USER regressuser4; +CREATE USER regressuser4; -- duplicate +ERROR: CREATE USER: user name "regressuser4" already exists +CREATE GROUP regressgroup1; +CREATE GROUP regressgroup2 WITH USER regressuser1, regressuser2; +ALTER GROUP regressgroup1 ADD USER regressuser4; +ALTER GROUP regressgroup2 ADD USER regressuser2; -- duplicate +NOTICE: ALTER GROUP: user "regressuser2" is already in group "regressgroup2" +ALTER GROUP regressgroup2 DROP USER regressuser2; +ALTER GROUP regressgroup2 ADD USER regressuser4; +-- test owner privileges +SET SESSION AUTHORIZATION regressuser1; +SELECT session_user, current_user; + session_user | current_user +--------------+-------------- + regressuser1 | regressuser1 +(1 row) + +CREATE TABLE atest1 ( a int, b text ); +SELECT * FROM atest1; + a | b +---+--- +(0 rows) + +INSERT INTO atest1 VALUES (1, 'one'); +DELETE FROM atest1; +UPDATE atest1 SET a = 1 WHERE b = 'blech'; +LOCK atest1 IN ACCESS EXCLUSIVE MODE; +REVOKE ALL ON atest1 FROM PUBLIC; +SELECT * FROM atest1; + a | b +---+--- +(0 rows) + +GRANT ALL ON atest1 TO regressuser2; +GRANT SELECT ON atest1 TO regressuser3; +SELECT * FROM atest1; + a | b +---+--- +(0 rows) + +CREATE TABLE atest2 (col1 varchar(10), col2 boolean); +GRANT SELECT ON atest2 TO regressuser2; +GRANT UPDATE ON atest2 TO regressuser3; +GRANT INSERT ON atest2 TO regressuser4; +SET SESSION AUTHORIZATION regressuser2; +SELECT session_user, current_user; + session_user | current_user +--------------+-------------- + regressuser2 | regressuser2 +(1 row) + +-- try various combinations of queries on atest1 and atest2 +SELECT * FROM atest1; -- ok + a | b +---+--- +(0 rows) + +SELECT * FROM atest2; -- ok + col1 | col2 +------+------ +(0 rows) + +INSERT INTO atest1 VALUES (2, 'two'); -- ok +INSERT INTO atest2 VALUES ('foo', true); -- fail +ERROR: atest2: Permission denied. +INSERT INTO atest1 SELECT 1, b FROM atest1; -- ok +UPDATE atest1 SET a = 1 WHERE a = 2; -- ok +UPDATE atest2 SET col2 = NOT col2; -- fail +ERROR: atest2: Permission denied. +SELECT * FROM atest1 FOR UPDATE; -- ok + a | b +---+----- + 1 | two + 1 | two +(2 rows) + +SELECT * FROM atest2 FOR UPDATE; -- fail +ERROR: atest2: Permission denied. +DELETE FROM atest2; -- fail +ERROR: atest2: Permission denied. +LOCK atest2 IN ACCESS EXCLUSIVE MODE; -- fail +ERROR: LOCK TABLE: permission denied +COPY atest2 FROM stdin; -- fail +ERROR: atest2: Permission denied. +GRANT ALL ON atest1 TO PUBLIC; -- fail +ERROR: you do not own class "atest1" +-- checks in subquery, both ok +SELECT * FROM atest1 WHERE ( b IN ( SELECT col1 FROM atest2 ) ); + a | b +---+--- +(0 rows) + +SELECT * FROM atest2 WHERE ( col1 IN ( SELECT b FROM atest1 ) ); + col1 | col2 +------+------ +(0 rows) + +SET SESSION AUTHORIZATION regressuser3; +SELECT session_user, current_user; + session_user | current_user +--------------+-------------- + regressuser3 | regressuser3 +(1 row) + +SELECT * FROM atest1; -- ok + a | b +---+----- + 1 | two + 1 | two +(2 rows) + +SELECT * FROM atest2; -- fail +ERROR: atest2: Permission denied. +INSERT INTO atest1 VALUES (2, 'two'); -- fail +ERROR: atest1: Permission denied. +INSERT INTO atest2 VALUES ('foo', true); -- fail +ERROR: atest2: Permission denied. +INSERT INTO atest1 SELECT 1, b FROM atest1; -- fail +ERROR: atest1: Permission denied. +UPDATE atest1 SET a = 1 WHERE a = 2; -- fail +ERROR: atest1: Permission denied. +UPDATE atest2 SET col2 = NULL; -- ok +UPDATE atest2 SET col2 = NOT col2; -- fails; requires SELECT on atest2 +ERROR: atest2: Permission denied. +UPDATE atest2 SET col2 = true WHERE atest1.a = 5; -- ok +SELECT * FROM atest1 FOR UPDATE; -- fail +ERROR: atest1: Permission denied. +SELECT * FROM atest2 FOR UPDATE; -- fail +ERROR: atest2: Permission denied. +DELETE FROM atest2; -- fail +ERROR: atest2: Permission denied. +LOCK atest2 IN ACCESS EXCLUSIVE MODE; -- ok +COPY atest2 FROM stdin; -- fail +ERROR: atest2: Permission denied. +-- checks in subquery, both fail +SELECT * FROM atest1 WHERE ( b IN ( SELECT col1 FROM atest2 ) ); +ERROR: atest2: Permission denied. +SELECT * FROM atest2 WHERE ( col1 IN ( SELECT b FROM atest1 ) ); +ERROR: atest2: Permission denied. +SET SESSION AUTHORIZATION regressuser4; +COPY atest2 FROM stdin; -- ok +-- groups +SET SESSION AUTHORIZATION regressuser3; +CREATE TABLE atest3 (one int, two int, three int); +GRANT DELETE ON atest3 TO GROUP regressgroup2; +SET SESSION AUTHORIZATION regressuser1; +SELECT * FROM atest3; -- fail +ERROR: atest3: Permission denied. +DELETE FROM atest3; -- ok +-- views +SET SESSION AUTHORIZATION regressuser3; +CREATE VIEW atestv1 AS SELECT * FROM atest1; -- ok +/* The next *should* fail, but it's not implemented that way yet. */ +CREATE VIEW atestv2 AS SELECT * FROM atest2; +CREATE VIEW atestv3 AS SELECT * FROM atest3; -- ok +SELECT * FROM atestv1; -- ok + a | b +---+----- + 1 | two + 1 | two +(2 rows) + +GRANT SELECT ON atestv1 TO regressuser4; +GRANT SELECT ON atestv3 TO regressuser4; +SET SESSION AUTHORIZATION regressuser4; +SELECT * FROM atestv1; -- ok + a | b +---+----- + 1 | two + 1 | two +(2 rows) + +SELECT * FROM atestv3; -- ok + one | two | three +-----+-----+------- +(0 rows) + +-- clean up +\c regression +DROP TABLE atest1; +DROP TABLE atest2; +DROP TABLE atest3; +DROP VIEW atestv1; +DROP VIEW atestv2; +DROP VIEW atestv3; +DROP GROUP regressgroup1; +DROP GROUP regressgroup2; +DROP USER regressuser1; +DROP USER regressuser2; +DROP USER regressuser3; +DROP USER regressuser4; diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index f37b2054e40..08e97511ac9 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -61,6 +61,7 @@ test: select ignore: random test: select_into select_distinct select_distinct_on select_implicit select_having subselect union case join aggregates transactions random portals arrays btree_index hash_index +test: privileges test: misc # ---------- diff --git a/src/test/regress/pg_regress.sh b/src/test/regress/pg_regress.sh index 8eb74b28010..552724a10f1 100644 --- a/src/test/regress/pg_regress.sh +++ b/src/test/regress/pg_regress.sh @@ -1,5 +1,5 @@ #! /bin/sh -# $Header: /cvsroot/pgsql/src/test/regress/Attic/pg_regress.sh,v 1.20 2001/03/24 23:32:25 petere Exp $ +# $Header: /cvsroot/pgsql/src/test/regress/Attic/pg_regress.sh,v 1.21 2001/05/27 09:59:30 petere Exp $ me=`basename $0` : ${TMPDIR=/tmp} @@ -433,6 +433,18 @@ fi # ---------- +# Remove regressuser* and regressgroup* user accounts. +# ---------- + +message "dropping regression test user accounts" +"$bindir/psql" $psql_options -c 'drop group regressgroup1; drop group regressgroup2; drop user regressuser1, regressuser2, regressuser3, regressuser4;' $dbname 2>/dev/null +if [ $? -eq 2 ]; then + echo "$me: could not drop user accounts" + (exit 2); exit +fi + + +# ---------- # Install the PL/pgSQL language in it # ---------- diff --git a/src/test/regress/serial_schedule b/src/test/regress/serial_schedule index 14ad6f505e0..afb0090cdad 100644 --- a/src/test/regress/serial_schedule +++ b/src/test/regress/serial_schedule @@ -1,4 +1,4 @@ -# $Header: /cvsroot/pgsql/src/test/regress/serial_schedule,v 1.3 2000/11/22 13:37:44 petere Exp $ +# $Header: /cvsroot/pgsql/src/test/regress/serial_schedule,v 1.4 2001/05/27 09:59:30 petere Exp $ # This should probably be in an order similar to parallel_schedule. test: boolean test: char @@ -68,6 +68,7 @@ test: portals test: arrays test: btree_index test: hash_index +test: privileges test: misc test: select_views test: alter_table diff --git a/src/test/regress/sql/privileges.sql b/src/test/regress/sql/privileges.sql new file mode 100644 index 00000000000..1558273f7b2 --- /dev/null +++ b/src/test/regress/sql/privileges.sql @@ -0,0 +1,146 @@ +-- +-- Test access privileges +-- + +CREATE USER regressuser1; +CREATE USER regressuser2; +CREATE USER regressuser3; +CREATE USER regressuser4; +CREATE USER regressuser4; -- duplicate + +CREATE GROUP regressgroup1; +CREATE GROUP regressgroup2 WITH USER regressuser1, regressuser2; + +ALTER GROUP regressgroup1 ADD USER regressuser4; + +ALTER GROUP regressgroup2 ADD USER regressuser2; -- duplicate +ALTER GROUP regressgroup2 DROP USER regressuser2; +ALTER GROUP regressgroup2 ADD USER regressuser4; + + +-- test owner privileges + +SET SESSION AUTHORIZATION regressuser1; +SELECT session_user, current_user; + +CREATE TABLE atest1 ( a int, b text ); +SELECT * FROM atest1; +INSERT INTO atest1 VALUES (1, 'one'); +DELETE FROM atest1; +UPDATE atest1 SET a = 1 WHERE b = 'blech'; +LOCK atest1 IN ACCESS EXCLUSIVE MODE; + +REVOKE ALL ON atest1 FROM PUBLIC; +SELECT * FROM atest1; + +GRANT ALL ON atest1 TO regressuser2; +GRANT SELECT ON atest1 TO regressuser3; +SELECT * FROM atest1; + +CREATE TABLE atest2 (col1 varchar(10), col2 boolean); +GRANT SELECT ON atest2 TO regressuser2; +GRANT UPDATE ON atest2 TO regressuser3; +GRANT INSERT ON atest2 TO regressuser4; + + +SET SESSION AUTHORIZATION regressuser2; +SELECT session_user, current_user; + +-- try various combinations of queries on atest1 and atest2 + +SELECT * FROM atest1; -- ok +SELECT * FROM atest2; -- ok +INSERT INTO atest1 VALUES (2, 'two'); -- ok +INSERT INTO atest2 VALUES ('foo', true); -- fail +INSERT INTO atest1 SELECT 1, b FROM atest1; -- ok +UPDATE atest1 SET a = 1 WHERE a = 2; -- ok +UPDATE atest2 SET col2 = NOT col2; -- fail +SELECT * FROM atest1 FOR UPDATE; -- ok +SELECT * FROM atest2 FOR UPDATE; -- fail +DELETE FROM atest2; -- fail +LOCK atest2 IN ACCESS EXCLUSIVE MODE; -- fail +COPY atest2 FROM stdin; -- fail +GRANT ALL ON atest1 TO PUBLIC; -- fail + +-- checks in subquery, both ok +SELECT * FROM atest1 WHERE ( b IN ( SELECT col1 FROM atest2 ) ); +SELECT * FROM atest2 WHERE ( col1 IN ( SELECT b FROM atest1 ) ); + + +SET SESSION AUTHORIZATION regressuser3; +SELECT session_user, current_user; + +SELECT * FROM atest1; -- ok +SELECT * FROM atest2; -- fail +INSERT INTO atest1 VALUES (2, 'two'); -- fail +INSERT INTO atest2 VALUES ('foo', true); -- fail +INSERT INTO atest1 SELECT 1, b FROM atest1; -- fail +UPDATE atest1 SET a = 1 WHERE a = 2; -- fail +UPDATE atest2 SET col2 = NULL; -- ok +UPDATE atest2 SET col2 = NOT col2; -- fails; requires SELECT on atest2 +UPDATE atest2 SET col2 = true WHERE atest1.a = 5; -- ok +SELECT * FROM atest1 FOR UPDATE; -- fail +SELECT * FROM atest2 FOR UPDATE; -- fail +DELETE FROM atest2; -- fail +LOCK atest2 IN ACCESS EXCLUSIVE MODE; -- ok +COPY atest2 FROM stdin; -- fail + +-- checks in subquery, both fail +SELECT * FROM atest1 WHERE ( b IN ( SELECT col1 FROM atest2 ) ); +SELECT * FROM atest2 WHERE ( col1 IN ( SELECT b FROM atest1 ) ); + +SET SESSION AUTHORIZATION regressuser4; +COPY atest2 FROM stdin; -- ok +bar true +\. + + +-- groups + +SET SESSION AUTHORIZATION regressuser3; +CREATE TABLE atest3 (one int, two int, three int); +GRANT DELETE ON atest3 TO GROUP regressgroup2; + +SET SESSION AUTHORIZATION regressuser1; + +SELECT * FROM atest3; -- fail +DELETE FROM atest3; -- ok + + +-- views + +SET SESSION AUTHORIZATION regressuser3; + +CREATE VIEW atestv1 AS SELECT * FROM atest1; -- ok +/* The next *should* fail, but it's not implemented that way yet. */ +CREATE VIEW atestv2 AS SELECT * FROM atest2; +CREATE VIEW atestv3 AS SELECT * FROM atest3; -- ok + +SELECT * FROM atestv1; -- ok +GRANT SELECT ON atestv1 TO regressuser4; +GRANT SELECT ON atestv3 TO regressuser4; + +SET SESSION AUTHORIZATION regressuser4; + +SELECT * FROM atestv1; -- ok +SELECT * FROM atestv3; -- ok + + +-- clean up + +\c regression +DROP TABLE atest1; +DROP TABLE atest2; +DROP TABLE atest3; + +DROP VIEW atestv1; +DROP VIEW atestv2; +DROP VIEW atestv3; + +DROP GROUP regressgroup1; +DROP GROUP regressgroup2; + +DROP USER regressuser1; +DROP USER regressuser2; +DROP USER regressuser3; +DROP USER regressuser4; |