]> granicus.if.org Git - postgresql/blobdiff - src/include/utils/acl.h
Create a 'type cache' that keeps track of the data needed for any particular
[postgresql] / src / include / utils / acl.h
index 93c896320a19c51b3806fe846e36b16e5388042d..29a807744ca01d7bfcf7a92291e3a7966b46b10b 100644 (file)
 /*-------------------------------------------------------------------------
  *
- * 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 */