/*-------------------------------------------------------------------------
*
- * acl.h--
+ * acl.h
* Definition of (and support for) access control list data structures.
*
*
- * Copyright (c) 1994, Regents of the University of California
+ * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: acl.h,v 1.18 1998/09/01 04:38:48 momjian Exp $
+ * $Id: acl.h,v 1.62 2003/08/17 19:58:06 tgl Exp $
*
* NOTES
- * For backward-compatability purposes we have to allow there
+ * 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
* code wherever this is included.
- *
*-------------------------------------------------------------------------
*/
#ifndef ACL_H
#define ACL_H
-#include <nodes/parsenodes.h>
-#include <utils/array.h>
+#include "nodes/parsenodes.h"
+#include "utils/array.h"
-/*
- * AclId system identifier for the user, group, etc.
- * XXX currently UNIX uid for users...
- */
-typedef uint32 AclId;
-#define ACL_ID_WORLD 0 /* XXX only idtype should be checked */
+/* typedef AclId is declared in c.h */
+
+#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.
*/
-typedef uint8 AclIdType;
-
-#define ACL_IDTYPE_WORLD 0x00
+#define ACL_IDTYPE_WORLD 0x00 /* PUBLIC */
#define ACL_IDTYPE_UID 0x01 /* user id - from pg_shadow */
#define ACL_IDTYPE_GID 0x02 /* group id - from pg_group */
/*
- * AclMode the actual permissions
- * XXX should probably use bit.h routines.
- * XXX should probably also stuff the modechg cruft in the
- * high bits, too.
+ * AclMode a bitmask of privilege bits
*/
-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_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)
+typedef uint32 AclMode;
/*
* AclItem
+ *
+ * Note: must be same size on all platforms, because the size is hardcoded
+ * in the pg_type.h entry for aclitem.
*/
typedef struct AclItem
{
- AclId ai_id;
- AclIdType ai_idtype;
- AclMode ai_mode;
+ AclId ai_grantee; /* ID that this item applies to */
+ AclId ai_grantor;
+ AclMode ai_privs; /* AclIdType plus privilege bits */
} AclItem;
-/* Note: if the size of AclItem changes,
- change the aclitem typlen in pg_type.h */
+/*
+ * The AclIdType is stored in the top two bits of the ai_privs field
+ * of an AclItem. The middle 15 bits are the grant option markers,
+ * and the lower 15 bits are the actual privileges.
+ */
+#define ACLITEM_GET_PRIVS(item) ((item).ai_privs & 0x7FFF)
+#define ACLITEM_GET_GOPTIONS(item) (((item).ai_privs >> 15) & 0x7FFF)
+#define ACLITEM_GET_IDTYPE(item) ((item).ai_privs >> 30)
+
+#define ACL_GRANT_OPTION_FOR(privs) (((privs) & 0x7FFF) << 15)
+
+#define ACLITEM_SET_PRIVS(item,privs) \
+ ((item).ai_privs = (ACLITEM_GET_IDTYPE(item)<<30) | (ACLITEM_GET_GOPTIONS(item)<<15) | ((privs) & 0x7FFF))
+#define ACLITEM_SET_GOPTIONS(item,goptions) \
+ ((item).ai_privs = (ACLITEM_GET_IDTYPE(item)<<30) | (((goptions) & 0x7FFF) << 15) | ACLITEM_GET_PRIVS(item))
+#define ACLITEM_SET_IDTYPE(item,idtype) \
+ ((item).ai_privs = ((idtype)<<30) | (ACLITEM_GET_GOPTIONS(item)<<15) | ACLITEM_GET_PRIVS(item))
+
+#define ACLITEM_SET_PRIVS_IDTYPE(item,privs,goption,idtype) \
+ ((item).ai_privs = ((privs) & 0x7FFF) |(((goption) & 0x7FFF) << 15) | ((idtype) << 30))
+
/*
- * The value of the first dimension-array element. Since these arrays
- * always have a lower-bound of 0, this is the same as the number of
- * elements in the array.
+ * Definitions for convenient access to Acl (array of AclItem) and IdList
+ * (array of AclId). These are standard PostgreSQL arrays, but are restricted
+ * to have one dimension. We also ignore the lower bound when reading,
+ * and set it to zero when writing.
+ *
+ * CAUTION: as of PostgreSQL 7.1, these arrays are toastable (just like all
+ * other array types). Therefore, be careful to detoast them with the
+ * macros provided, unless you know for certain that a particular array
+ * can't have been toasted. Presently, we do not provide toast tables for
+ * pg_class or pg_group, so the entries in those tables won't have been
+ * stored externally --- but they could have been compressed!
*/
-#define ARR_DIM0(a) (((unsigned *) (((char *) a) + sizeof(ArrayType)))[0])
+
/*
- * Acl a one-dimensional POSTGRES array of AclItem
+ * Acl a one-dimensional array of AclItem
*/
typedef ArrayType Acl;
-#define ACL_NUM(ACL) ARR_DIM0(ACL)
+#define ACL_NUM(ACL) (ARR_DIMS(ACL)[0])
#define ACL_DAT(ACL) ((AclItem *) ARR_DATA_PTR(ACL))
-#define ACL_N_SIZE(N) \
- ((unsigned) (ARR_OVERHEAD(1) + ((N) * sizeof(AclItem))))
+#define ACL_N_SIZE(N) (ARR_OVERHEAD(1) + ((N) * sizeof(AclItem)))
#define ACL_SIZE(ACL) ARR_SIZE(ACL)
/*
- * IdList a one-dimensional POSTGRES array of AclId
+ * IdList a one-dimensional array of AclId
*/
typedef ArrayType IdList;
-#define IDLIST_NUM(IDL) ARR_DIM0(IDL)
+#define IDLIST_NUM(IDL) (ARR_DIMS(IDL)[0])
#define IDLIST_DAT(IDL) ((AclId *) ARR_DATA_PTR(IDL))
-#define IDLIST_N_SIZE(N) \
- ((unsigned) (ARR_OVERHEAD(1) + ((N) * sizeof(AclId))))
+#define IDLIST_N_SIZE(N) (ARR_OVERHEAD(1) + ((N) * sizeof(AclId)))
#define IDLIST_SIZE(IDL) ARR_SIZE(IDL)
-#define ACL_MODECHG_STR "+-=" /* list of valid characters */
-#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'
-
-/* result codes for pg_aclcheck */
-#define ACLCHECK_OK 0
-#define ACLCHECK_NO_PRIV 1
-#define ACLCHECK_NO_CLASS 2
-#define ACLCHECK_NOT_OWNER 3
-
-/* warning messages. set these in aclchk.c. */
-extern char *aclcheck_error_strings[];
+/*
+ * fmgr macros for these types
+ */
+#define DatumGetAclItemP(X) ((AclItem *) DatumGetPointer(X))
+#define PG_GETARG_ACLITEM_P(n) DatumGetAclItemP(PG_GETARG_DATUM(n))
+#define PG_RETURN_ACLITEM_P(x) PG_RETURN_POINTER(x)
+
+#define DatumGetAclP(X) ((Acl *) PG_DETOAST_DATUM(X))
+#define DatumGetAclPCopy(X) ((Acl *) PG_DETOAST_DATUM_COPY(X))
+#define PG_GETARG_ACL_P(n) DatumGetAclP(PG_GETARG_DATUM(n))
+#define PG_GETARG_ACL_P_COPY(n) DatumGetAclPCopy(PG_GETARG_DATUM(n))
+#define PG_RETURN_ACL_P(x) PG_RETURN_POINTER(x)
+
+#define DatumGetIdListP(X) ((IdList *) PG_DETOAST_DATUM(X))
+#define DatumGetIdListPCopy(X) ((IdList *) PG_DETOAST_DATUM_COPY(X))
+#define PG_GETARG_IDLIST_P(n) DatumGetIdListP(PG_GETARG_DATUM(n))
+#define PG_GETARG_IDLIST_P_COPY(n) DatumGetIdListPCopy(PG_GETARG_DATUM(n))
+#define PG_RETURN_IDLIST_P(x) PG_RETURN_POINTER(x)
+
/*
- * Enable ACL execution tracing and table dumps
+ * ACL modification opcodes
*/
-/*#define ACLDEBUG_TRACE*/
+#define ACL_MODECHG_ADD 1
+#define ACL_MODECHG_DEL 2
+#define ACL_MODECHG_EQL 3
/*
- * routines used internally (parser, etc.)
+ * External representations of the privilege bits --- aclitemin/aclitemout
+ * represent each possible privilege bit with a distinct 1-character code
*/
-extern Acl *aclownerdefault(char *relname, AclId ownerid);
-extern Acl *acldefault(char *relname);
-extern Acl *aclinsert3(Acl *old_acl, AclItem *mod_aip, unsigned modechg);
+#define ACL_INSERT_CHR 'a' /* formerly known as "append" */
+#define ACL_SELECT_CHR 'r' /* formerly known as "read" */
+#define ACL_UPDATE_CHR 'w' /* formerly known as "write" */
+#define ACL_DELETE_CHR 'd'
+#define ACL_RULE_CHR 'R'
+#define ACL_REFERENCES_CHR 'x'
+#define ACL_TRIGGER_CHR 't'
+#define ACL_EXECUTE_CHR 'X'
+#define ACL_USAGE_CHR 'U'
+#define ACL_CREATE_CHR 'C'
+#define ACL_CREATE_TEMP_CHR 'T'
+
+/* string holding all privilege code chars, in order by bitmask position */
+#define ACL_ALL_RIGHTS_STR "arwdRxtXUCT"
-extern char *aclmakepriv(char *old_privlist, char new_priv);
-extern char *aclmakeuser(char *user_type, char *user);
-extern ChangeACLStmt *makeAclStmt(char *privs, List *rel_list, char *grantee,
- char grant_or_revoke);
+/*
+ * Bitmasks defining "all rights" for each supported object type
+ */
+#define ACL_ALL_RIGHTS_RELATION (ACL_INSERT|ACL_SELECT|ACL_UPDATE|ACL_DELETE|ACL_RULE|ACL_REFERENCES|ACL_TRIGGER)
+#define ACL_ALL_RIGHTS_DATABASE (ACL_CREATE|ACL_CREATE_TEMP)
+#define ACL_ALL_RIGHTS_FUNCTION (ACL_EXECUTE)
+#define ACL_ALL_RIGHTS_LANGUAGE (ACL_USAGE)
+#define ACL_ALL_RIGHTS_NAMESPACE (ACL_USAGE|ACL_CREATE)
+
+
+/* result codes for pg_*_aclcheck */
+typedef enum
+{
+ ACLCHECK_OK = 0,
+ ACLCHECK_NO_PRIV,
+ ACLCHECK_NOT_OWNER
+} AclResult;
+
+/* this enum covers all object types that can have privilege errors */
+/* currently it's only used to tell aclcheck_error what to say */
+typedef enum AclObjectKind
+{
+ ACL_KIND_CLASS, /* pg_class */
+ ACL_KIND_DATABASE, /* pg_database */
+ ACL_KIND_PROC, /* pg_proc */
+ ACL_KIND_OPER, /* pg_operator */
+ ACL_KIND_TYPE, /* pg_type */
+ ACL_KIND_LANGUAGE, /* pg_language */
+ ACL_KIND_NAMESPACE, /* pg_namespace */
+ ACL_KIND_OPCLASS, /* pg_opclass */
+ ACL_KIND_CONVERSION, /* pg_conversion */
+ MAX_ACL_KIND /* MUST BE LAST */
+} AclObjectKind;
/*
- * exported routines (from acl.c)
+ * routines used internally
*/
-extern Acl *makeacl(int n);
-extern AclItem *aclitemin(char *s);
-extern char *aclitemout(AclItem *aip);
-extern Acl *aclinsert(Acl *old_acl, AclItem *mod_aip);
-extern Acl *aclremove(Acl *old_acl, AclItem *mod_aip);
-extern int32 aclcontains(Acl *acl, AclItem *aip);
+extern Acl *acldefault(GrantObjectType objtype, AclId ownerid);
+extern Acl *aclinsert3(const Acl *old_acl, const AclItem *mod_aip,
+ unsigned modechg, DropBehavior behavior);
+
+/*
+ * SQL functions (from acl.c)
+ */
+extern Datum aclitemin(PG_FUNCTION_ARGS);
+extern Datum aclitemout(PG_FUNCTION_ARGS);
+extern Datum aclinsert(PG_FUNCTION_ARGS);
+extern Datum aclremove(PG_FUNCTION_ARGS);
+extern Datum aclcontains(PG_FUNCTION_ARGS);
+extern Datum makeaclitem(PG_FUNCTION_ARGS);
+extern Datum aclitem_eq(PG_FUNCTION_ARGS);
+extern Datum hash_aclitem(PG_FUNCTION_ARGS);
/*
* prototypes for functions in aclchk.c
*/
-extern void ChangeAcl(char *relname, AclItem *mod_aip, unsigned modechg);
+extern void ExecuteGrantStmt(GrantStmt *stmt);
extern AclId get_grosysid(char *groname);
extern char *get_groname(AclId grosysid);
-extern int32 pg_aclcheck(char *relname, char *usename, AclMode mode);
-extern int32 pg_ownercheck(char *usename, char *value, int cacheid);
-extern int32 pg_func_ownercheck(char *usename, char *funcname,
- int nargs, Oid *arglist);
-extern int32 pg_aggr_ownercheck(char *usename, char *aggname,
- Oid basetypeID);
-
-#endif /* ACL_H */
+extern AclResult pg_class_aclcheck(Oid table_oid, AclId userid, AclMode mode);
+extern AclResult pg_database_aclcheck(Oid db_oid, AclId userid, AclMode mode);
+extern AclResult pg_proc_aclcheck(Oid proc_oid, AclId userid, AclMode mode);
+extern AclResult pg_language_aclcheck(Oid lang_oid, AclId userid, AclMode mode);
+extern AclResult pg_namespace_aclcheck(Oid nsp_oid, AclId userid, AclMode mode);
+
+extern void aclcheck_error(AclResult aclerr, AclObjectKind objectkind,
+ const char *objectname);
+
+/* ownercheck routines just return true (owner) or false (not) */
+extern bool pg_class_ownercheck(Oid class_oid, AclId userid);
+extern bool pg_type_ownercheck(Oid type_oid, AclId userid);
+extern bool pg_oper_ownercheck(Oid oper_oid, AclId userid);
+extern bool pg_proc_ownercheck(Oid proc_oid, AclId userid);
+extern bool pg_namespace_ownercheck(Oid nsp_oid, AclId userid);
+extern bool pg_opclass_ownercheck(Oid opc_oid, AclId userid);
+extern bool pg_database_ownercheck(Oid db_oid, AclId userid);
+
+#endif /* ACL_H */