static int32 aclcheck(char *relname, Acl *acl, AclId id,
AclIdType idtype, AclMode mode);
-/*
- * Enable use of user relations in place of real system catalogs.
- */
-/*#define ACLDEBUG*/
-
-#ifdef ACLDEBUG
-/*
- * Fool the code below into thinking that "pgacls" is pg_class.
- * relname and relowner are in the same place, happily.
- */
-#undef Anum_pg_class_relacl
-#define Anum_pg_class_relacl 3
-#undef Natts_pg_class
-#define Natts_pg_class 3
-#undef Name_pg_class
-#define Name_pg_class "pgacls"
-#undef Name_pg_group
-#define Name_pg_group "pggroup"
-#endif
-
/* warning messages, now more explicit. */
-/* should correspond to the order of the ACLCHK_* result codes above. */
+/* MUST correspond to the order of the ACLCHK_* result codes in acl.h. */
char *aclcheck_error_strings[] = {
"No error.",
"Permission denied.",
"Must be table owner."
};
+
#ifdef ACLDEBUG_TRACE
static
dumpacl(Acl *acl)
#endif
/*
- *
+ * ChangeAcl
*/
void
ChangeAcl(char *relname,
*new_acl;
Relation relation;
HeapTuple tuple;
+ Datum aclDatum;
Datum values[Natts_pg_class];
char nulls[Natts_pg_class];
char replaces[Natts_pg_class];
Relation idescs[Num_pg_class_indices];
bool isNull;
- bool free_old_acl = false;
/*
* Find the pg_class tuple matching 'relname' and extract the ACL. If
relname);
}
- old_acl = (Acl *) heap_getattr(tuple,
- Anum_pg_class_relacl,
- RelationGetDescr(relation),
- &isNull);
+ aclDatum = SysCacheGetAttr(RELNAME, tuple, Anum_pg_class_relacl,
+ &isNull);
if (isNull)
{
-#ifdef ACLDEBUG_TRACE
- elog(DEBUG, "ChangeAcl: using default ACL");
-#endif
- old_acl = acldefault(relname);
- free_old_acl = true;
- }
-
- /* Need to detoast the old ACL for modification */
- old_acl = DatumGetAclP(PointerGetDatum(old_acl));
+ /* No ACL, so build default ACL for rel */
+ AclId ownerId;
- if (ACL_NUM(old_acl) < 1)
+ ownerId = ((Form_pg_class) GETSTRUCT(tuple))->relowner;
+ old_acl = acldefault(relname, ownerId);
+ }
+ else
{
-#ifdef ACLDEBUG_TRACE
- elog(DEBUG, "ChangeAcl: old ACL has zero length");
-#endif
- old_acl = acldefault(relname);
- free_old_acl = true;
+ /* get a detoasted copy of the rel's ACL */
+ old_acl = DatumGetAclPCopy(aclDatum);
}
#ifdef ACLDEBUG_TRACE
CatalogCloseIndices(Num_pg_class_indices, idescs);
heap_close(relation, RowExclusiveLock);
- if (free_old_acl)
- pfree(old_acl);
+
+ pfree(old_acl);
pfree(new_acl);
}
unsigned num,
found_group;
- /* if no acl is found, use world default */
+ /*
+ * If ACL is null, default to "OK" --- this should not happen,
+ * since caller should have inserted appropriate default
+ */
if (!acl)
- acl = acldefault(relname);
+ {
+ elog(DEBUG, "aclcheck: null ACL, returning 1");
+ return ACLCHECK_OK;
+ }
num = ACL_NUM(acl);
aidat = ACL_DAT(acl);
*/
if (num < 1)
{
-#if defined(ACLDEBUG_TRACE) || 1
elog(DEBUG, "aclcheck: zero-length ACL, returning 1");
-#endif
return ACLCHECK_OK;
}
int32
pg_aclcheck(char *relname, Oid userid, AclMode mode)
{
- HeapTuple tuple;
- Acl *acl = (Acl *) NULL;
int32 result;
+ HeapTuple tuple;
char *usename;
- Relation relation;
+ Datum aclDatum;
+ bool isNull;
+ Acl *acl;
tuple = SearchSysCacheTuple(SHADOWSYSID,
ObjectIdGetDatum(userid),
return ACLCHECK_OK;
}
-#ifndef ACLDEBUG
- relation = heap_openr(RelationRelationName, RowExclusiveLock);
+ /*
+ * Normal case: get the relation's ACL from pg_class
+ */
tuple = SearchSysCacheTuple(RELNAME,
PointerGetDatum(relname),
0, 0, 0);
if (!HeapTupleIsValid(tuple))
- {
- elog(ERROR, "pg_aclcheck: class \"%s\" not found",
- relname);
- }
- if (!heap_attisnull(tuple, Anum_pg_class_relacl))
- {
- /* get a detoasted copy of the ACL */
- acl = DatumGetAclPCopy(heap_getattr(tuple,
- Anum_pg_class_relacl,
- RelationGetDescr(relation),
- (bool *) NULL));
- }
- else
- {
+ elog(ERROR, "pg_aclcheck: class \"%s\" not found", relname);
- /*
- * if the acl is null, by default the owner can do whatever he
- * wants to with it
- */
+ aclDatum = SysCacheGetAttr(RELNAME, tuple, Anum_pg_class_relacl,
+ &isNull);
+ if (isNull)
+ {
+ /* No ACL, so build default ACL for rel */
AclId ownerId;
ownerId = ((Form_pg_class) GETSTRUCT(tuple))->relowner;
- acl = aclownerdefault(relname, ownerId);
+ acl = acldefault(relname, ownerId);
}
- heap_close(relation, RowExclusiveLock);
-#else
- relation = heap_openr(RelationRelationName, RowExclusiveLock);
- tuple = SearchSysCacheTuple(RELNAME,
- PointerGetDatum(relname),
- 0, 0, 0);
- if (HeapTupleIsValid(tuple) &&
- !heap_attisnull(tuple, Anum_pg_class_relacl))
+ else
{
- /* get a detoasted copy of the ACL */
- acl = DatumGetAclPCopy(heap_getattr(tuple,
- Anum_pg_class_relacl,
- RelationGetDescr(relation),
- (bool *) NULL));
+ /* get a detoasted copy of the rel's ACL */
+ acl = DatumGetAclPCopy(aclDatum);
}
- heap_close(relation, RowExclusiveLock);
-#endif
+
result = aclcheck(relname, acl, userid, (AclIdType) ACL_IDTYPE_UID, mode);
if (acl)
pfree(acl);
* NOTES
* For backward-compatibility purposes we have to allow there
* to be a null ACL in a pg_class tuple. This will be defined as
- * meaning "no protection" (i.e., old catalogs get old semantics).
+ * meaning "default protection" (i.e., whatever acldefault() returns).
*
* The AclItems in an ACL array are currently kept in sorted order.
* Things will break hard if you change that without changing the
*/
typedef uint32 AclId;
-#define ACL_ID_WORLD 0 /* XXX only idtype should be checked */
+#define ACL_ID_WORLD 0 /* placeholder for id in a WORLD acl item */
/*
* AclIdType tag that describes if the AclId is a user, group, etc.
#define ACL_RU (1<<3) /* place rules */
#define N_ACL_MODES 4
-#define ACL_MODECHG_ADD 1
-#define ACL_MODECHG_DEL 2
-#define ACL_MODECHG_EQL 3
-
-/* change this line if you want to set the default acl permission */
-#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)
-
/*
* AclItem
*/
#define PG_RETURN_IDLIST_P(x) PG_RETURN_POINTER(x)
+/*
+ * ACL modification opcodes
+ */
+#define ACL_MODECHG_ADD 1
+#define ACL_MODECHG_DEL 2
+#define ACL_MODECHG_EQL 3
+
/* mode indicators for I/O */
#define ACL_MODECHG_STR "+-=" /* list of valid characters */
#define ACL_MODECHG_ADD_CHR '+'
/*
* routines used internally (parser, etc.)
*/
-extern Acl *aclownerdefault(char *relname, AclId ownerid);
-extern Acl *acldefault(char *relname);
+extern Acl *acldefault(char *relname, AclId ownerid);
+
extern Acl *aclinsert3(Acl *old_acl, AclItem *mod_aip, unsigned modechg);
extern char *aclmakepriv(char *old_privlist, char new_priv);