00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "postgres.h"
00016
00017 #include <ctype.h>
00018
00019 #include "access/htup_details.h"
00020 #include "catalog/namespace.h"
00021 #include "catalog/pg_authid.h"
00022 #include "catalog/pg_auth_members.h"
00023 #include "catalog/pg_type.h"
00024 #include "catalog/pg_class.h"
00025 #include "commands/dbcommands.h"
00026 #include "commands/proclang.h"
00027 #include "commands/tablespace.h"
00028 #include "foreign/foreign.h"
00029 #include "funcapi.h"
00030 #include "miscadmin.h"
00031 #include "utils/acl.h"
00032 #include "utils/builtins.h"
00033 #include "utils/catcache.h"
00034 #include "utils/inval.h"
00035 #include "utils/lsyscache.h"
00036 #include "utils/memutils.h"
00037 #include "utils/syscache.h"
00038
00039
00040 typedef struct
00041 {
00042 const char *name;
00043 AclMode value;
00044 } priv_map;
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072 static Oid cached_privs_role = InvalidOid;
00073 static List *cached_privs_roles = NIL;
00074 static Oid cached_member_role = InvalidOid;
00075 static List *cached_membership_roles = NIL;
00076
00077
00078 static const char *getid(const char *s, char *n);
00079 static void putid(char *p, const char *s);
00080 static Acl *allocacl(int n);
00081 static void check_acl(const Acl *acl);
00082 static const char *aclparse(const char *s, AclItem *aip);
00083 static bool aclitem_match(const AclItem *a1, const AclItem *a2);
00084 static int aclitemComparator(const void *arg1, const void *arg2);
00085 static void check_circularity(const Acl *old_acl, const AclItem *mod_aip,
00086 Oid ownerId);
00087 static Acl *recursive_revoke(Acl *acl, Oid grantee, AclMode revoke_privs,
00088 Oid ownerId, DropBehavior behavior);
00089 static int oidComparator(const void *arg1, const void *arg2);
00090
00091 static AclMode convert_priv_string(text *priv_type_text);
00092 static AclMode convert_any_priv_string(text *priv_type_text,
00093 const priv_map *privileges);
00094
00095 static Oid convert_table_name(text *tablename);
00096 static AclMode convert_table_priv_string(text *priv_type_text);
00097 static AclMode convert_sequence_priv_string(text *priv_type_text);
00098 static AttrNumber convert_column_name(Oid tableoid, text *column);
00099 static AclMode convert_column_priv_string(text *priv_type_text);
00100 static Oid convert_database_name(text *databasename);
00101 static AclMode convert_database_priv_string(text *priv_type_text);
00102 static Oid convert_foreign_data_wrapper_name(text *fdwname);
00103 static AclMode convert_foreign_data_wrapper_priv_string(text *priv_type_text);
00104 static Oid convert_function_name(text *functionname);
00105 static AclMode convert_function_priv_string(text *priv_type_text);
00106 static Oid convert_language_name(text *languagename);
00107 static AclMode convert_language_priv_string(text *priv_type_text);
00108 static Oid convert_schema_name(text *schemaname);
00109 static AclMode convert_schema_priv_string(text *priv_type_text);
00110 static Oid convert_server_name(text *servername);
00111 static AclMode convert_server_priv_string(text *priv_type_text);
00112 static Oid convert_tablespace_name(text *tablespacename);
00113 static AclMode convert_tablespace_priv_string(text *priv_type_text);
00114 static Oid convert_type_name(text *typename);
00115 static AclMode convert_type_priv_string(text *priv_type_text);
00116 static AclMode convert_role_priv_string(text *priv_type_text);
00117 static AclResult pg_role_aclcheck(Oid role_oid, Oid roleid, AclMode mode);
00118
00119 static void RoleMembershipCacheCallback(Datum arg, int cacheid, uint32 hashvalue);
00120 static Oid get_role_oid_or_public(const char *rolname);
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135 static const char *
00136 getid(const char *s, char *n)
00137 {
00138 int len = 0;
00139 bool in_quotes = false;
00140
00141 Assert(s && n);
00142
00143 while (isspace((unsigned char) *s))
00144 s++;
00145
00146 for (;
00147 *s != '\0' &&
00148 (isalnum((unsigned char) *s) ||
00149 *s == '_' ||
00150 *s == '"' ||
00151 in_quotes);
00152 s++)
00153 {
00154 if (*s == '"')
00155 {
00156
00157 if (*(s + 1) != '"')
00158 {
00159 in_quotes = !in_quotes;
00160 continue;
00161 }
00162
00163 s++;
00164 }
00165
00166
00167 if (len >= NAMEDATALEN - 1)
00168 ereport(ERROR,
00169 (errcode(ERRCODE_NAME_TOO_LONG),
00170 errmsg("identifier too long"),
00171 errdetail("Identifier must be less than %d characters.",
00172 NAMEDATALEN)));
00173
00174 n[len++] = *s;
00175 }
00176 n[len] = '\0';
00177 while (isspace((unsigned char) *s))
00178 s++;
00179 return s;
00180 }
00181
00182
00183
00184
00185
00186
00187 static void
00188 putid(char *p, const char *s)
00189 {
00190 const char *src;
00191 bool safe = true;
00192
00193 for (src = s; *src; src++)
00194 {
00195
00196 if (!isalnum((unsigned char) *src) && *src != '_')
00197 {
00198 safe = false;
00199 break;
00200 }
00201 }
00202 if (!safe)
00203 *p++ = '"';
00204 for (src = s; *src; src++)
00205 {
00206
00207 if (*src == '"')
00208 *p++ = '"';
00209 *p++ = *src;
00210 }
00211 if (!safe)
00212 *p++ = '"';
00213 *p = '\0';
00214 }
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236 static const char *
00237 aclparse(const char *s, AclItem *aip)
00238 {
00239 AclMode privs,
00240 goption,
00241 read;
00242 char name[NAMEDATALEN];
00243 char name2[NAMEDATALEN];
00244
00245 Assert(s && aip);
00246
00247 #ifdef ACLDEBUG
00248 elog(LOG, "aclparse: input = \"%s\"", s);
00249 #endif
00250 s = getid(s, name);
00251 if (*s != '=')
00252 {
00253
00254 if (strcmp(name, "group") != 0 && strcmp(name, "user") != 0)
00255 ereport(ERROR,
00256 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
00257 errmsg("unrecognized key word: \"%s\"", name),
00258 errhint("ACL key word must be \"group\" or \"user\".")));
00259 s = getid(s, name);
00260 if (name[0] == '\0')
00261 ereport(ERROR,
00262 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
00263 errmsg("missing name"),
00264 errhint("A name must follow the \"group\" or \"user\" key word.")));
00265 }
00266
00267 if (*s != '=')
00268 ereport(ERROR,
00269 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
00270 errmsg("missing \"=\" sign")));
00271
00272 privs = goption = ACL_NO_RIGHTS;
00273
00274 for (++s, read = 0; isalpha((unsigned char) *s) || *s == '*'; s++)
00275 {
00276 switch (*s)
00277 {
00278 case '*':
00279 goption |= read;
00280 break;
00281 case ACL_INSERT_CHR:
00282 read = ACL_INSERT;
00283 break;
00284 case ACL_SELECT_CHR:
00285 read = ACL_SELECT;
00286 break;
00287 case ACL_UPDATE_CHR:
00288 read = ACL_UPDATE;
00289 break;
00290 case ACL_DELETE_CHR:
00291 read = ACL_DELETE;
00292 break;
00293 case ACL_TRUNCATE_CHR:
00294 read = ACL_TRUNCATE;
00295 break;
00296 case ACL_REFERENCES_CHR:
00297 read = ACL_REFERENCES;
00298 break;
00299 case ACL_TRIGGER_CHR:
00300 read = ACL_TRIGGER;
00301 break;
00302 case ACL_EXECUTE_CHR:
00303 read = ACL_EXECUTE;
00304 break;
00305 case ACL_USAGE_CHR:
00306 read = ACL_USAGE;
00307 break;
00308 case ACL_CREATE_CHR:
00309 read = ACL_CREATE;
00310 break;
00311 case ACL_CREATE_TEMP_CHR:
00312 read = ACL_CREATE_TEMP;
00313 break;
00314 case ACL_CONNECT_CHR:
00315 read = ACL_CONNECT;
00316 break;
00317 case 'R':
00318 read = 0;
00319 break;
00320 default:
00321 ereport(ERROR,
00322 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
00323 errmsg("invalid mode character: must be one of \"%s\"",
00324 ACL_ALL_RIGHTS_STR)));
00325 }
00326
00327 privs |= read;
00328 }
00329
00330 if (name[0] == '\0')
00331 aip->ai_grantee = ACL_ID_PUBLIC;
00332 else
00333 aip->ai_grantee = get_role_oid(name, false);
00334
00335
00336
00337
00338
00339 if (*s == '/')
00340 {
00341 s = getid(s + 1, name2);
00342 if (name2[0] == '\0')
00343 ereport(ERROR,
00344 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
00345 errmsg("a name must follow the \"/\" sign")));
00346 aip->ai_grantor = get_role_oid(name2, false);
00347 }
00348 else
00349 {
00350 aip->ai_grantor = BOOTSTRAP_SUPERUSERID;
00351 ereport(WARNING,
00352 (errcode(ERRCODE_INVALID_GRANTOR),
00353 errmsg("defaulting grantor to user ID %u",
00354 BOOTSTRAP_SUPERUSERID)));
00355 }
00356
00357 ACLITEM_SET_PRIVS_GOPTIONS(*aip, privs, goption);
00358
00359 #ifdef ACLDEBUG
00360 elog(LOG, "aclparse: correctly read [%u %x %x]",
00361 aip->ai_grantee, privs, goption);
00362 #endif
00363
00364 return s;
00365 }
00366
00367
00368
00369
00370
00371
00372
00373
00374 static Acl *
00375 allocacl(int n)
00376 {
00377 Acl *new_acl;
00378 Size size;
00379
00380 if (n < 0)
00381 elog(ERROR, "invalid size: %d", n);
00382 size = ACL_N_SIZE(n);
00383 new_acl = (Acl *) palloc0(size);
00384 SET_VARSIZE(new_acl, size);
00385 new_acl->ndim = 1;
00386 new_acl->dataoffset = 0;
00387 new_acl->elemtype = ACLITEMOID;
00388 ARR_LBOUND(new_acl)[0] = 1;
00389 ARR_DIMS(new_acl)[0] = n;
00390 return new_acl;
00391 }
00392
00393
00394
00395
00396 Acl *
00397 make_empty_acl(void)
00398 {
00399 return allocacl(0);
00400 }
00401
00402
00403
00404
00405 Acl *
00406 aclcopy(const Acl *orig_acl)
00407 {
00408 Acl *result_acl;
00409
00410 result_acl = allocacl(ACL_NUM(orig_acl));
00411
00412 memcpy(ACL_DAT(result_acl),
00413 ACL_DAT(orig_acl),
00414 ACL_NUM(orig_acl) * sizeof(AclItem));
00415
00416 return result_acl;
00417 }
00418
00419
00420
00421
00422
00423
00424
00425 Acl *
00426 aclconcat(const Acl *left_acl, const Acl *right_acl)
00427 {
00428 Acl *result_acl;
00429
00430 result_acl = allocacl(ACL_NUM(left_acl) + ACL_NUM(right_acl));
00431
00432 memcpy(ACL_DAT(result_acl),
00433 ACL_DAT(left_acl),
00434 ACL_NUM(left_acl) * sizeof(AclItem));
00435
00436 memcpy(ACL_DAT(result_acl) + ACL_NUM(left_acl),
00437 ACL_DAT(right_acl),
00438 ACL_NUM(right_acl) * sizeof(AclItem));
00439
00440 return result_acl;
00441 }
00442
00443
00444
00445
00446
00447
00448
00449 Acl *
00450 aclmerge(const Acl *left_acl, const Acl *right_acl, Oid ownerId)
00451 {
00452 Acl *result_acl;
00453 AclItem *aip;
00454 int i,
00455 num;
00456
00457
00458 if (left_acl == NULL || ACL_NUM(left_acl) == 0)
00459 {
00460 if (right_acl == NULL || ACL_NUM(right_acl) == 0)
00461 return NULL;
00462 else
00463 return aclcopy(right_acl);
00464 }
00465 else
00466 {
00467 if (right_acl == NULL || ACL_NUM(right_acl) == 0)
00468 return aclcopy(left_acl);
00469 }
00470
00471
00472 result_acl = aclcopy(left_acl);
00473
00474 aip = ACL_DAT(right_acl);
00475 num = ACL_NUM(right_acl);
00476
00477 for (i = 0; i < num; i++, aip++)
00478 {
00479 Acl *tmp_acl;
00480
00481 tmp_acl = aclupdate(result_acl, aip, ACL_MODECHG_ADD,
00482 ownerId, DROP_RESTRICT);
00483 pfree(result_acl);
00484 result_acl = tmp_acl;
00485 }
00486
00487 return result_acl;
00488 }
00489
00490
00491
00492
00493 void
00494 aclitemsort(Acl *acl)
00495 {
00496 if (acl != NULL && ACL_NUM(acl) > 1)
00497 qsort(ACL_DAT(acl), ACL_NUM(acl), sizeof(AclItem), aclitemComparator);
00498 }
00499
00500
00501
00502
00503
00504
00505
00506
00507 bool
00508 aclequal(const Acl *left_acl, const Acl *right_acl)
00509 {
00510
00511 if (left_acl == NULL || ACL_NUM(left_acl) == 0)
00512 {
00513 if (right_acl == NULL || ACL_NUM(right_acl) == 0)
00514 return true;
00515 else
00516 return false;
00517 }
00518 else
00519 {
00520 if (right_acl == NULL || ACL_NUM(right_acl) == 0)
00521 return false;
00522 }
00523
00524 if (ACL_NUM(left_acl) != ACL_NUM(right_acl))
00525 return false;
00526
00527 if (memcmp(ACL_DAT(left_acl),
00528 ACL_DAT(right_acl),
00529 ACL_NUM(left_acl) * sizeof(AclItem)) == 0)
00530 return true;
00531
00532 return false;
00533 }
00534
00535
00536
00537
00538 static void
00539 check_acl(const Acl *acl)
00540 {
00541 if (ARR_ELEMTYPE(acl) != ACLITEMOID)
00542 ereport(ERROR,
00543 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
00544 errmsg("ACL array contains wrong data type")));
00545 if (ARR_NDIM(acl) != 1)
00546 ereport(ERROR,
00547 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
00548 errmsg("ACL arrays must be one-dimensional")));
00549 if (ARR_HASNULL(acl))
00550 ereport(ERROR,
00551 (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
00552 errmsg("ACL arrays must not contain null values")));
00553 }
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563 Datum
00564 aclitemin(PG_FUNCTION_ARGS)
00565 {
00566 const char *s = PG_GETARG_CSTRING(0);
00567 AclItem *aip;
00568
00569 aip = (AclItem *) palloc(sizeof(AclItem));
00570 s = aclparse(s, aip);
00571 while (isspace((unsigned char) *s))
00572 ++s;
00573 if (*s)
00574 ereport(ERROR,
00575 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
00576 errmsg("extra garbage at the end of the ACL specification")));
00577
00578 PG_RETURN_ACLITEM_P(aip);
00579 }
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589 Datum
00590 aclitemout(PG_FUNCTION_ARGS)
00591 {
00592 AclItem *aip = PG_GETARG_ACLITEM_P(0);
00593 char *p;
00594 char *out;
00595 HeapTuple htup;
00596 unsigned i;
00597
00598 out = palloc(strlen("=/") +
00599 2 * N_ACL_RIGHTS +
00600 2 * (2 * NAMEDATALEN + 2) +
00601 1);
00602
00603 p = out;
00604 *p = '\0';
00605
00606 if (aip->ai_grantee != ACL_ID_PUBLIC)
00607 {
00608 htup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(aip->ai_grantee));
00609 if (HeapTupleIsValid(htup))
00610 {
00611 putid(p, NameStr(((Form_pg_authid) GETSTRUCT(htup))->rolname));
00612 ReleaseSysCache(htup);
00613 }
00614 else
00615 {
00616
00617 sprintf(p, "%u", aip->ai_grantee);
00618 }
00619 }
00620 while (*p)
00621 ++p;
00622
00623 *p++ = '=';
00624
00625 for (i = 0; i < N_ACL_RIGHTS; ++i)
00626 {
00627 if (ACLITEM_GET_PRIVS(*aip) & (1 << i))
00628 *p++ = ACL_ALL_RIGHTS_STR[i];
00629 if (ACLITEM_GET_GOPTIONS(*aip) & (1 << i))
00630 *p++ = '*';
00631 }
00632
00633 *p++ = '/';
00634 *p = '\0';
00635
00636 htup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(aip->ai_grantor));
00637 if (HeapTupleIsValid(htup))
00638 {
00639 putid(p, NameStr(((Form_pg_authid) GETSTRUCT(htup))->rolname));
00640 ReleaseSysCache(htup);
00641 }
00642 else
00643 {
00644
00645 sprintf(p, "%u", aip->ai_grantor);
00646 }
00647
00648 PG_RETURN_CSTRING(out);
00649 }
00650
00651
00652
00653
00654
00655
00656 static bool
00657 aclitem_match(const AclItem *a1, const AclItem *a2)
00658 {
00659 return a1->ai_grantee == a2->ai_grantee &&
00660 a1->ai_grantor == a2->ai_grantor;
00661 }
00662
00663
00664
00665
00666
00667 static int
00668 aclitemComparator(const void *arg1, const void *arg2)
00669 {
00670 const AclItem *a1 = (const AclItem *) arg1;
00671 const AclItem *a2 = (const AclItem *) arg2;
00672
00673 if (a1->ai_grantee > a2->ai_grantee)
00674 return 1;
00675 if (a1->ai_grantee < a2->ai_grantee)
00676 return -1;
00677 if (a1->ai_grantor > a2->ai_grantor)
00678 return 1;
00679 if (a1->ai_grantor < a2->ai_grantor)
00680 return -1;
00681 if (a1->ai_privs > a2->ai_privs)
00682 return 1;
00683 if (a1->ai_privs < a2->ai_privs)
00684 return -1;
00685 return 0;
00686 }
00687
00688
00689
00690
00691 Datum
00692 aclitem_eq(PG_FUNCTION_ARGS)
00693 {
00694 AclItem *a1 = PG_GETARG_ACLITEM_P(0);
00695 AclItem *a2 = PG_GETARG_ACLITEM_P(1);
00696 bool result;
00697
00698 result = a1->ai_privs == a2->ai_privs &&
00699 a1->ai_grantee == a2->ai_grantee &&
00700 a1->ai_grantor == a2->ai_grantor;
00701 PG_RETURN_BOOL(result);
00702 }
00703
00704
00705
00706
00707
00708
00709
00710
00711 Datum
00712 hash_aclitem(PG_FUNCTION_ARGS)
00713 {
00714 AclItem *a = PG_GETARG_ACLITEM_P(0);
00715
00716
00717 PG_RETURN_UINT32((uint32) (a->ai_privs + a->ai_grantee + a->ai_grantor));
00718 }
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730 Acl *
00731 acldefault(GrantObjectType objtype, Oid ownerId)
00732 {
00733 AclMode world_default;
00734 AclMode owner_default;
00735 int nacl;
00736 Acl *acl;
00737 AclItem *aip;
00738
00739 switch (objtype)
00740 {
00741 case ACL_OBJECT_COLUMN:
00742
00743 world_default = ACL_NO_RIGHTS;
00744 owner_default = ACL_NO_RIGHTS;
00745 break;
00746 case ACL_OBJECT_RELATION:
00747 world_default = ACL_NO_RIGHTS;
00748 owner_default = ACL_ALL_RIGHTS_RELATION;
00749 break;
00750 case ACL_OBJECT_SEQUENCE:
00751 world_default = ACL_NO_RIGHTS;
00752 owner_default = ACL_ALL_RIGHTS_SEQUENCE;
00753 break;
00754 case ACL_OBJECT_DATABASE:
00755
00756 world_default = ACL_CREATE_TEMP | ACL_CONNECT;
00757 owner_default = ACL_ALL_RIGHTS_DATABASE;
00758 break;
00759 case ACL_OBJECT_FUNCTION:
00760
00761 world_default = ACL_EXECUTE;
00762 owner_default = ACL_ALL_RIGHTS_FUNCTION;
00763 break;
00764 case ACL_OBJECT_LANGUAGE:
00765
00766 world_default = ACL_USAGE;
00767 owner_default = ACL_ALL_RIGHTS_LANGUAGE;
00768 break;
00769 case ACL_OBJECT_LARGEOBJECT:
00770 world_default = ACL_NO_RIGHTS;
00771 owner_default = ACL_ALL_RIGHTS_LARGEOBJECT;
00772 break;
00773 case ACL_OBJECT_NAMESPACE:
00774 world_default = ACL_NO_RIGHTS;
00775 owner_default = ACL_ALL_RIGHTS_NAMESPACE;
00776 break;
00777 case ACL_OBJECT_TABLESPACE:
00778 world_default = ACL_NO_RIGHTS;
00779 owner_default = ACL_ALL_RIGHTS_TABLESPACE;
00780 break;
00781 case ACL_OBJECT_FDW:
00782 world_default = ACL_NO_RIGHTS;
00783 owner_default = ACL_ALL_RIGHTS_FDW;
00784 break;
00785 case ACL_OBJECT_FOREIGN_SERVER:
00786 world_default = ACL_NO_RIGHTS;
00787 owner_default = ACL_ALL_RIGHTS_FOREIGN_SERVER;
00788 break;
00789 case ACL_OBJECT_DOMAIN:
00790 case ACL_OBJECT_TYPE:
00791 world_default = ACL_USAGE;
00792 owner_default = ACL_ALL_RIGHTS_TYPE;
00793 break;
00794 default:
00795 elog(ERROR, "unrecognized objtype: %d", (int) objtype);
00796 world_default = ACL_NO_RIGHTS;
00797 owner_default = ACL_NO_RIGHTS;
00798 break;
00799 }
00800
00801 nacl = 0;
00802 if (world_default != ACL_NO_RIGHTS)
00803 nacl++;
00804 if (owner_default != ACL_NO_RIGHTS)
00805 nacl++;
00806
00807 acl = allocacl(nacl);
00808 aip = ACL_DAT(acl);
00809
00810 if (world_default != ACL_NO_RIGHTS)
00811 {
00812 aip->ai_grantee = ACL_ID_PUBLIC;
00813 aip->ai_grantor = ownerId;
00814 ACLITEM_SET_PRIVS_GOPTIONS(*aip, world_default, ACL_NO_RIGHTS);
00815 aip++;
00816 }
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828 if (owner_default != ACL_NO_RIGHTS)
00829 {
00830 aip->ai_grantee = ownerId;
00831 aip->ai_grantor = ownerId;
00832 ACLITEM_SET_PRIVS_GOPTIONS(*aip, owner_default, ACL_NO_RIGHTS);
00833 }
00834
00835 return acl;
00836 }
00837
00838
00839
00840
00841
00842
00843
00844 Datum
00845 acldefault_sql(PG_FUNCTION_ARGS)
00846 {
00847 char objtypec = PG_GETARG_CHAR(0);
00848 Oid owner = PG_GETARG_OID(1);
00849 GrantObjectType objtype = 0;
00850
00851 switch (objtypec)
00852 {
00853 case 'c':
00854 objtype = ACL_OBJECT_COLUMN;
00855 break;
00856 case 'r':
00857 objtype = ACL_OBJECT_RELATION;
00858 break;
00859 case 's':
00860 objtype = ACL_OBJECT_SEQUENCE;
00861 break;
00862 case 'd':
00863 objtype = ACL_OBJECT_DATABASE;
00864 break;
00865 case 'f':
00866 objtype = ACL_OBJECT_FUNCTION;
00867 break;
00868 case 'l':
00869 objtype = ACL_OBJECT_LANGUAGE;
00870 break;
00871 case 'L':
00872 objtype = ACL_OBJECT_LARGEOBJECT;
00873 break;
00874 case 'n':
00875 objtype = ACL_OBJECT_NAMESPACE;
00876 break;
00877 case 't':
00878 objtype = ACL_OBJECT_TABLESPACE;
00879 break;
00880 case 'F':
00881 objtype = ACL_OBJECT_FDW;
00882 break;
00883 case 'S':
00884 objtype = ACL_OBJECT_FOREIGN_SERVER;
00885 break;
00886 case 'T':
00887 objtype = ACL_OBJECT_TYPE;
00888 break;
00889 default:
00890 elog(ERROR, "unrecognized objtype abbreviation: %c", objtypec);
00891 }
00892
00893 PG_RETURN_ACL_P(acldefault(objtype, owner));
00894 }
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909
00910
00911
00912
00913 Acl *
00914 aclupdate(const Acl *old_acl, const AclItem *mod_aip,
00915 int modechg, Oid ownerId, DropBehavior behavior)
00916 {
00917 Acl *new_acl = NULL;
00918 AclItem *old_aip,
00919 *new_aip = NULL;
00920 AclMode old_rights,
00921 old_goptions,
00922 new_rights,
00923 new_goptions;
00924 int dst,
00925 num;
00926
00927
00928 check_acl(old_acl);
00929
00930
00931 if (modechg != ACL_MODECHG_DEL &&
00932 ACLITEM_GET_GOPTIONS(*mod_aip) != ACL_NO_RIGHTS)
00933 check_circularity(old_acl, mod_aip, ownerId);
00934
00935 num = ACL_NUM(old_acl);
00936 old_aip = ACL_DAT(old_acl);
00937
00938
00939
00940
00941
00942
00943
00944
00945 for (dst = 0; dst < num; ++dst)
00946 {
00947 if (aclitem_match(mod_aip, old_aip + dst))
00948 {
00949
00950 new_acl = allocacl(num);
00951 new_aip = ACL_DAT(new_acl);
00952 memcpy(new_acl, old_acl, ACL_SIZE(old_acl));
00953 break;
00954 }
00955 }
00956
00957 if (dst == num)
00958 {
00959
00960 new_acl = allocacl(num + 1);
00961 new_aip = ACL_DAT(new_acl);
00962 memcpy(new_aip, old_aip, num * sizeof(AclItem));
00963
00964
00965 new_aip[dst].ai_grantee = mod_aip->ai_grantee;
00966 new_aip[dst].ai_grantor = mod_aip->ai_grantor;
00967 ACLITEM_SET_PRIVS_GOPTIONS(new_aip[dst],
00968 ACL_NO_RIGHTS, ACL_NO_RIGHTS);
00969 num++;
00970 }
00971
00972 old_rights = ACLITEM_GET_RIGHTS(new_aip[dst]);
00973 old_goptions = ACLITEM_GET_GOPTIONS(new_aip[dst]);
00974
00975
00976 switch (modechg)
00977 {
00978 case ACL_MODECHG_ADD:
00979 ACLITEM_SET_RIGHTS(new_aip[dst],
00980 old_rights | ACLITEM_GET_RIGHTS(*mod_aip));
00981 break;
00982 case ACL_MODECHG_DEL:
00983 ACLITEM_SET_RIGHTS(new_aip[dst],
00984 old_rights & ~ACLITEM_GET_RIGHTS(*mod_aip));
00985 break;
00986 case ACL_MODECHG_EQL:
00987 ACLITEM_SET_RIGHTS(new_aip[dst],
00988 ACLITEM_GET_RIGHTS(*mod_aip));
00989 break;
00990 }
00991
00992 new_rights = ACLITEM_GET_RIGHTS(new_aip[dst]);
00993 new_goptions = ACLITEM_GET_GOPTIONS(new_aip[dst]);
00994
00995
00996
00997
00998 if (new_rights == ACL_NO_RIGHTS)
00999 {
01000 memmove(new_aip + dst,
01001 new_aip + dst + 1,
01002 (num - dst - 1) * sizeof(AclItem));
01003
01004 ARR_DIMS(new_acl)[0] = num - 1;
01005 SET_VARSIZE(new_acl, ACL_N_SIZE(num - 1));
01006 }
01007
01008
01009
01010
01011
01012 if ((old_goptions & ~new_goptions) != 0)
01013 {
01014 Assert(mod_aip->ai_grantee != ACL_ID_PUBLIC);
01015 new_acl = recursive_revoke(new_acl, mod_aip->ai_grantee,
01016 (old_goptions & ~new_goptions),
01017 ownerId, behavior);
01018 }
01019
01020 return new_acl;
01021 }
01022
01023
01024
01025
01026
01027
01028
01029
01030
01031
01032
01033
01034 Acl *
01035 aclnewowner(const Acl *old_acl, Oid oldOwnerId, Oid newOwnerId)
01036 {
01037 Acl *new_acl;
01038 AclItem *new_aip;
01039 AclItem *old_aip;
01040 AclItem *dst_aip;
01041 AclItem *src_aip;
01042 AclItem *targ_aip;
01043 bool newpresent = false;
01044 int dst,
01045 src,
01046 targ,
01047 num;
01048
01049 check_acl(old_acl);
01050
01051
01052
01053
01054
01055
01056 num = ACL_NUM(old_acl);
01057 old_aip = ACL_DAT(old_acl);
01058 new_acl = allocacl(num);
01059 new_aip = ACL_DAT(new_acl);
01060 memcpy(new_aip, old_aip, num * sizeof(AclItem));
01061 for (dst = 0, dst_aip = new_aip; dst < num; dst++, dst_aip++)
01062 {
01063 if (dst_aip->ai_grantor == oldOwnerId)
01064 dst_aip->ai_grantor = newOwnerId;
01065 else if (dst_aip->ai_grantor == newOwnerId)
01066 newpresent = true;
01067 if (dst_aip->ai_grantee == oldOwnerId)
01068 dst_aip->ai_grantee = newOwnerId;
01069 else if (dst_aip->ai_grantee == newOwnerId)
01070 newpresent = true;
01071 }
01072
01073
01074
01075
01076
01077
01078
01079
01080
01081
01082
01083
01084
01085
01086
01087
01088
01089 if (newpresent)
01090 {
01091 dst = 0;
01092 for (targ = 0, targ_aip = new_aip; targ < num; targ++, targ_aip++)
01093 {
01094
01095 if (ACLITEM_GET_RIGHTS(*targ_aip) == ACL_NO_RIGHTS)
01096 continue;
01097
01098 for (src = targ + 1, src_aip = targ_aip + 1; src < num;
01099 src++, src_aip++)
01100 {
01101 if (ACLITEM_GET_RIGHTS(*src_aip) == ACL_NO_RIGHTS)
01102 continue;
01103 if (aclitem_match(targ_aip, src_aip))
01104 {
01105 ACLITEM_SET_RIGHTS(*targ_aip,
01106 ACLITEM_GET_RIGHTS(*targ_aip) |
01107 ACLITEM_GET_RIGHTS(*src_aip));
01108
01109 ACLITEM_SET_RIGHTS(*src_aip, ACL_NO_RIGHTS);
01110 }
01111 }
01112
01113 new_aip[dst] = *targ_aip;
01114 dst++;
01115 }
01116
01117 ARR_DIMS(new_acl)[0] = dst;
01118 SET_VARSIZE(new_acl, ACL_N_SIZE(dst));
01119 }
01120
01121 return new_acl;
01122 }
01123
01124
01125
01126
01127
01128
01129
01130
01131
01132
01133
01134
01135
01136
01137 static void
01138 check_circularity(const Acl *old_acl, const AclItem *mod_aip,
01139 Oid ownerId)
01140 {
01141 Acl *acl;
01142 AclItem *aip;
01143 int i,
01144 num;
01145 AclMode own_privs;
01146
01147 check_acl(old_acl);
01148
01149
01150
01151
01152
01153 Assert(mod_aip->ai_grantee != ACL_ID_PUBLIC);
01154
01155
01156 if (mod_aip->ai_grantor == ownerId)
01157 return;
01158
01159
01160 acl = allocacl(ACL_NUM(old_acl));
01161 memcpy(acl, old_acl, ACL_SIZE(old_acl));
01162
01163
01164 cc_restart:
01165 num = ACL_NUM(acl);
01166 aip = ACL_DAT(acl);
01167 for (i = 0; i < num; i++)
01168 {
01169 if (aip[i].ai_grantee == mod_aip->ai_grantee &&
01170 ACLITEM_GET_GOPTIONS(aip[i]) != ACL_NO_RIGHTS)
01171 {
01172 Acl *new_acl;
01173
01174
01175 new_acl = aclupdate(acl, &aip[i], ACL_MODECHG_DEL,
01176 ownerId, DROP_CASCADE);
01177
01178 pfree(acl);
01179 acl = new_acl;
01180
01181 goto cc_restart;
01182 }
01183 }
01184
01185
01186 own_privs = aclmask(acl,
01187 mod_aip->ai_grantor,
01188 ownerId,
01189 ACL_GRANT_OPTION_FOR(ACLITEM_GET_GOPTIONS(*mod_aip)),
01190 ACLMASK_ALL);
01191 own_privs = ACL_OPTION_TO_PRIVS(own_privs);
01192
01193 if ((ACLITEM_GET_GOPTIONS(*mod_aip) & ~own_privs) != 0)
01194 ereport(ERROR,
01195 (errcode(ERRCODE_INVALID_GRANT_OPERATION),
01196 errmsg("grant options cannot be granted back to your own grantor")));
01197
01198 pfree(acl);
01199 }
01200
01201
01202
01203
01204
01205
01206
01207
01208
01209
01210
01211
01212
01213
01214
01215
01216
01217 static Acl *
01218 recursive_revoke(Acl *acl,
01219 Oid grantee,
01220 AclMode revoke_privs,
01221 Oid ownerId,
01222 DropBehavior behavior)
01223 {
01224 AclMode still_has;
01225 AclItem *aip;
01226 int i,
01227 num;
01228
01229 check_acl(acl);
01230
01231
01232 if (grantee == ownerId)
01233 return acl;
01234
01235
01236 still_has = aclmask(acl, grantee, ownerId,
01237 ACL_GRANT_OPTION_FOR(revoke_privs),
01238 ACLMASK_ALL);
01239 revoke_privs &= ~ACL_OPTION_TO_PRIVS(still_has);
01240 if (revoke_privs == ACL_NO_RIGHTS)
01241 return acl;
01242
01243 restart:
01244 num = ACL_NUM(acl);
01245 aip = ACL_DAT(acl);
01246 for (i = 0; i < num; i++)
01247 {
01248 if (aip[i].ai_grantor == grantee
01249 && (ACLITEM_GET_PRIVS(aip[i]) & revoke_privs) != 0)
01250 {
01251 AclItem mod_acl;
01252 Acl *new_acl;
01253
01254 if (behavior == DROP_RESTRICT)
01255 ereport(ERROR,
01256 (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
01257 errmsg("dependent privileges exist"),
01258 errhint("Use CASCADE to revoke them too.")));
01259
01260 mod_acl.ai_grantor = grantee;
01261 mod_acl.ai_grantee = aip[i].ai_grantee;
01262 ACLITEM_SET_PRIVS_GOPTIONS(mod_acl,
01263 revoke_privs,
01264 revoke_privs);
01265
01266 new_acl = aclupdate(acl, &mod_acl, ACL_MODECHG_DEL,
01267 ownerId, behavior);
01268
01269 pfree(acl);
01270 acl = new_acl;
01271
01272 goto restart;
01273 }
01274 }
01275
01276 return acl;
01277 }
01278
01279
01280
01281
01282
01283
01284
01285
01286
01287
01288
01289
01290
01291
01292
01293
01294
01295
01296
01297
01298
01299
01300
01301
01302
01303 AclMode
01304 aclmask(const Acl *acl, Oid roleid, Oid ownerId,
01305 AclMode mask, AclMaskHow how)
01306 {
01307 AclMode result;
01308 AclMode remaining;
01309 AclItem *aidat;
01310 int i,
01311 num;
01312
01313
01314
01315
01316
01317 if (acl == NULL)
01318 elog(ERROR, "null ACL");
01319
01320 check_acl(acl);
01321
01322
01323 if (mask == 0)
01324 return 0;
01325
01326 result = 0;
01327
01328
01329 if ((mask & ACLITEM_ALL_GOPTION_BITS) &&
01330 has_privs_of_role(roleid, ownerId))
01331 {
01332 result = mask & ACLITEM_ALL_GOPTION_BITS;
01333 if ((how == ACLMASK_ALL) ? (result == mask) : (result != 0))
01334 return result;
01335 }
01336
01337 num = ACL_NUM(acl);
01338 aidat = ACL_DAT(acl);
01339
01340
01341
01342
01343 for (i = 0; i < num; i++)
01344 {
01345 AclItem *aidata = &aidat[i];
01346
01347 if (aidata->ai_grantee == ACL_ID_PUBLIC ||
01348 aidata->ai_grantee == roleid)
01349 {
01350 result |= aidata->ai_privs & mask;
01351 if ((how == ACLMASK_ALL) ? (result == mask) : (result != 0))
01352 return result;
01353 }
01354 }
01355
01356
01357
01358
01359
01360
01361
01362
01363 remaining = mask & ~result;
01364 for (i = 0; i < num; i++)
01365 {
01366 AclItem *aidata = &aidat[i];
01367
01368 if (aidata->ai_grantee == ACL_ID_PUBLIC ||
01369 aidata->ai_grantee == roleid)
01370 continue;
01371
01372 if ((aidata->ai_privs & remaining) &&
01373 has_privs_of_role(roleid, aidata->ai_grantee))
01374 {
01375 result |= aidata->ai_privs & mask;
01376 if ((how == ACLMASK_ALL) ? (result == mask) : (result != 0))
01377 return result;
01378 remaining = mask & ~result;
01379 }
01380 }
01381
01382 return result;
01383 }
01384
01385
01386
01387
01388
01389
01390
01391
01392 static AclMode
01393 aclmask_direct(const Acl *acl, Oid roleid, Oid ownerId,
01394 AclMode mask, AclMaskHow how)
01395 {
01396 AclMode result;
01397 AclItem *aidat;
01398 int i,
01399 num;
01400
01401
01402
01403
01404
01405 if (acl == NULL)
01406 elog(ERROR, "null ACL");
01407
01408 check_acl(acl);
01409
01410
01411 if (mask == 0)
01412 return 0;
01413
01414 result = 0;
01415
01416
01417 if ((mask & ACLITEM_ALL_GOPTION_BITS) &&
01418 roleid == ownerId)
01419 {
01420 result = mask & ACLITEM_ALL_GOPTION_BITS;
01421 if ((how == ACLMASK_ALL) ? (result == mask) : (result != 0))
01422 return result;
01423 }
01424
01425 num = ACL_NUM(acl);
01426 aidat = ACL_DAT(acl);
01427
01428
01429
01430
01431 for (i = 0; i < num; i++)
01432 {
01433 AclItem *aidata = &aidat[i];
01434
01435 if (aidata->ai_grantee == roleid)
01436 {
01437 result |= aidata->ai_privs & mask;
01438 if ((how == ACLMASK_ALL) ? (result == mask) : (result != 0))
01439 return result;
01440 }
01441 }
01442
01443 return result;
01444 }
01445
01446
01447
01448
01449
01450
01451
01452
01453
01454
01455 int
01456 aclmembers(const Acl *acl, Oid **roleids)
01457 {
01458 Oid *list;
01459 const AclItem *acldat;
01460 int i,
01461 j,
01462 k;
01463
01464 if (acl == NULL || ACL_NUM(acl) == 0)
01465 {
01466 *roleids = NULL;
01467 return 0;
01468 }
01469
01470 check_acl(acl);
01471
01472
01473 list = palloc(ACL_NUM(acl) * 2 * sizeof(Oid));
01474 acldat = ACL_DAT(acl);
01475
01476
01477
01478
01479 j = 0;
01480 for (i = 0; i < ACL_NUM(acl); i++)
01481 {
01482 const AclItem *ai = &acldat[i];
01483
01484 if (ai->ai_grantee != ACL_ID_PUBLIC)
01485 list[j++] = ai->ai_grantee;
01486
01487 if (ai->ai_grantor != ACL_ID_PUBLIC)
01488 list[j++] = ai->ai_grantor;
01489 }
01490
01491
01492 qsort(list, j, sizeof(Oid), oidComparator);
01493
01494
01495 k = 0;
01496 for (i = 1; i < j; i++)
01497 {
01498 if (list[k] != list[i])
01499 list[++k] = list[i];
01500 }
01501
01502
01503
01504
01505
01506 *roleids = list;
01507
01508 return k + 1;
01509 }
01510
01511
01512
01513
01514
01515 static int
01516 oidComparator(const void *arg1, const void *arg2)
01517 {
01518 Oid oid1 = *(const Oid *) arg1;
01519 Oid oid2 = *(const Oid *) arg2;
01520
01521 if (oid1 > oid2)
01522 return 1;
01523 if (oid1 < oid2)
01524 return -1;
01525 return 0;
01526 }
01527
01528
01529
01530
01531
01532 Datum
01533 aclinsert(PG_FUNCTION_ARGS)
01534 {
01535 ereport(ERROR,
01536 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
01537 errmsg("aclinsert is no longer supported")));
01538
01539 PG_RETURN_NULL();
01540 }
01541
01542 Datum
01543 aclremove(PG_FUNCTION_ARGS)
01544 {
01545 ereport(ERROR,
01546 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
01547 errmsg("aclremove is no longer supported")));
01548
01549 PG_RETURN_NULL();
01550 }
01551
01552 Datum
01553 aclcontains(PG_FUNCTION_ARGS)
01554 {
01555 Acl *acl = PG_GETARG_ACL_P(0);
01556 AclItem *aip = PG_GETARG_ACLITEM_P(1);
01557 AclItem *aidat;
01558 int i,
01559 num;
01560
01561 check_acl(acl);
01562 num = ACL_NUM(acl);
01563 aidat = ACL_DAT(acl);
01564 for (i = 0; i < num; ++i)
01565 {
01566 if (aip->ai_grantee == aidat[i].ai_grantee &&
01567 aip->ai_grantor == aidat[i].ai_grantor &&
01568 (ACLITEM_GET_RIGHTS(*aip) & ACLITEM_GET_RIGHTS(aidat[i])) == ACLITEM_GET_RIGHTS(*aip))
01569 PG_RETURN_BOOL(true);
01570 }
01571 PG_RETURN_BOOL(false);
01572 }
01573
01574 Datum
01575 makeaclitem(PG_FUNCTION_ARGS)
01576 {
01577 Oid grantee = PG_GETARG_OID(0);
01578 Oid grantor = PG_GETARG_OID(1);
01579 text *privtext = PG_GETARG_TEXT_P(2);
01580 bool goption = PG_GETARG_BOOL(3);
01581 AclItem *result;
01582 AclMode priv;
01583
01584 priv = convert_priv_string(privtext);
01585
01586 result = (AclItem *) palloc(sizeof(AclItem));
01587
01588 result->ai_grantee = grantee;
01589 result->ai_grantor = grantor;
01590
01591 ACLITEM_SET_PRIVS_GOPTIONS(*result, priv,
01592 (goption ? priv : ACL_NO_RIGHTS));
01593
01594 PG_RETURN_ACLITEM_P(result);
01595 }
01596
01597 static AclMode
01598 convert_priv_string(text *priv_type_text)
01599 {
01600 char *priv_type = text_to_cstring(priv_type_text);
01601
01602 if (pg_strcasecmp(priv_type, "SELECT") == 0)
01603 return ACL_SELECT;
01604 if (pg_strcasecmp(priv_type, "INSERT") == 0)
01605 return ACL_INSERT;
01606 if (pg_strcasecmp(priv_type, "UPDATE") == 0)
01607 return ACL_UPDATE;
01608 if (pg_strcasecmp(priv_type, "DELETE") == 0)
01609 return ACL_DELETE;
01610 if (pg_strcasecmp(priv_type, "TRUNCATE") == 0)
01611 return ACL_TRUNCATE;
01612 if (pg_strcasecmp(priv_type, "REFERENCES") == 0)
01613 return ACL_REFERENCES;
01614 if (pg_strcasecmp(priv_type, "TRIGGER") == 0)
01615 return ACL_TRIGGER;
01616 if (pg_strcasecmp(priv_type, "EXECUTE") == 0)
01617 return ACL_EXECUTE;
01618 if (pg_strcasecmp(priv_type, "USAGE") == 0)
01619 return ACL_USAGE;
01620 if (pg_strcasecmp(priv_type, "CREATE") == 0)
01621 return ACL_CREATE;
01622 if (pg_strcasecmp(priv_type, "TEMP") == 0)
01623 return ACL_CREATE_TEMP;
01624 if (pg_strcasecmp(priv_type, "TEMPORARY") == 0)
01625 return ACL_CREATE_TEMP;
01626 if (pg_strcasecmp(priv_type, "CONNECT") == 0)
01627 return ACL_CONNECT;
01628 if (pg_strcasecmp(priv_type, "RULE") == 0)
01629 return 0;
01630
01631 ereport(ERROR,
01632 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
01633 errmsg("unrecognized privilege type: \"%s\"", priv_type)));
01634 return ACL_NO_RIGHTS;
01635 }
01636
01637
01638
01639
01640
01641
01642
01643
01644
01645
01646
01647 static AclMode
01648 convert_any_priv_string(text *priv_type_text,
01649 const priv_map *privileges)
01650 {
01651 AclMode result = 0;
01652 char *priv_type = text_to_cstring(priv_type_text);
01653 char *chunk;
01654 char *next_chunk;
01655
01656
01657 for (chunk = priv_type; chunk; chunk = next_chunk)
01658 {
01659 int chunk_len;
01660 const priv_map *this_priv;
01661
01662
01663 next_chunk = strchr(chunk, ',');
01664 if (next_chunk)
01665 *next_chunk++ = '\0';
01666
01667
01668 while (*chunk && isspace((unsigned char) *chunk))
01669 chunk++;
01670 chunk_len = strlen(chunk);
01671 while (chunk_len > 0 && isspace((unsigned char) chunk[chunk_len - 1]))
01672 chunk_len--;
01673 chunk[chunk_len] = '\0';
01674
01675
01676 for (this_priv = privileges; this_priv->name; this_priv++)
01677 {
01678 if (pg_strcasecmp(this_priv->name, chunk) == 0)
01679 {
01680 result |= this_priv->value;
01681 break;
01682 }
01683 }
01684 if (!this_priv->name)
01685 ereport(ERROR,
01686 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
01687 errmsg("unrecognized privilege type: \"%s\"", chunk)));
01688 }
01689
01690 pfree(priv_type);
01691 return result;
01692 }
01693
01694
01695 static const char *
01696 convert_aclright_to_string(int aclright)
01697 {
01698 switch (aclright)
01699 {
01700 case ACL_INSERT:
01701 return "INSERT";
01702 case ACL_SELECT:
01703 return "SELECT";
01704 case ACL_UPDATE:
01705 return "UPDATE";
01706 case ACL_DELETE:
01707 return "DELETE";
01708 case ACL_TRUNCATE:
01709 return "TRUNCATE";
01710 case ACL_REFERENCES:
01711 return "REFERENCES";
01712 case ACL_TRIGGER:
01713 return "TRIGGER";
01714 case ACL_EXECUTE:
01715 return "EXECUTE";
01716 case ACL_USAGE:
01717 return "USAGE";
01718 case ACL_CREATE:
01719 return "CREATE";
01720 case ACL_CREATE_TEMP:
01721 return "TEMPORARY";
01722 case ACL_CONNECT:
01723 return "CONNECT";
01724 default:
01725 elog(ERROR, "unrecognized aclright: %d", aclright);
01726 return NULL;
01727 }
01728 }
01729
01730
01731
01732
01733
01734
01735
01736
01737
01738
01739
01740
01741
01742
01743
01744
01745 Datum
01746 aclexplode(PG_FUNCTION_ARGS)
01747 {
01748 Acl *acl = PG_GETARG_ACL_P(0);
01749 FuncCallContext *funcctx;
01750 int *idx;
01751 AclItem *aidat;
01752
01753 if (SRF_IS_FIRSTCALL())
01754 {
01755 TupleDesc tupdesc;
01756 MemoryContext oldcontext;
01757
01758 check_acl(acl);
01759
01760 funcctx = SRF_FIRSTCALL_INIT();
01761 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
01762
01763
01764
01765
01766
01767 tupdesc = CreateTemplateTupleDesc(4, false);
01768 TupleDescInitEntry(tupdesc, (AttrNumber) 1, "grantor",
01769 OIDOID, -1, 0);
01770 TupleDescInitEntry(tupdesc, (AttrNumber) 2, "grantee",
01771 OIDOID, -1, 0);
01772 TupleDescInitEntry(tupdesc, (AttrNumber) 3, "privilege_type",
01773 TEXTOID, -1, 0);
01774 TupleDescInitEntry(tupdesc, (AttrNumber) 4, "is_grantable",
01775 BOOLOID, -1, 0);
01776
01777 funcctx->tuple_desc = BlessTupleDesc(tupdesc);
01778
01779
01780 idx = (int *) palloc(sizeof(int[2]));
01781 idx[0] = 0;
01782 idx[1] = -1;
01783 funcctx->user_fctx = (void *) idx;
01784
01785 MemoryContextSwitchTo(oldcontext);
01786 }
01787
01788 funcctx = SRF_PERCALL_SETUP();
01789 idx = (int *) funcctx->user_fctx;
01790 aidat = ACL_DAT(acl);
01791
01792
01793 while (idx[0] < ACL_NUM(acl))
01794 {
01795 AclItem *aidata;
01796 AclMode priv_bit;
01797
01798 idx[1]++;
01799 if (idx[1] == N_ACL_RIGHTS)
01800 {
01801 idx[1] = 0;
01802 idx[0]++;
01803 if (idx[0] >= ACL_NUM(acl))
01804 break;
01805 }
01806 aidata = &aidat[idx[0]];
01807 priv_bit = 1 << idx[1];
01808
01809 if (ACLITEM_GET_PRIVS(*aidata) & priv_bit)
01810 {
01811 Datum result;
01812 Datum values[4];
01813 bool nulls[4];
01814 HeapTuple tuple;
01815
01816 values[0] = ObjectIdGetDatum(aidata->ai_grantor);
01817 values[1] = ObjectIdGetDatum(aidata->ai_grantee);
01818 values[2] = CStringGetTextDatum(convert_aclright_to_string(priv_bit));
01819 values[3] = BoolGetDatum((ACLITEM_GET_GOPTIONS(*aidata) & priv_bit) != 0);
01820
01821 MemSet(nulls, 0, sizeof(nulls));
01822
01823 tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls);
01824 result = HeapTupleGetDatum(tuple);
01825
01826 SRF_RETURN_NEXT(funcctx, result);
01827 }
01828 }
01829
01830 SRF_RETURN_DONE(funcctx);
01831 }
01832
01833
01834
01835
01836
01837
01838
01839
01840
01841
01842
01843
01844
01845
01846
01847
01848
01849
01850
01851 Datum
01852 has_table_privilege_name_name(PG_FUNCTION_ARGS)
01853 {
01854 Name rolename = PG_GETARG_NAME(0);
01855 text *tablename = PG_GETARG_TEXT_P(1);
01856 text *priv_type_text = PG_GETARG_TEXT_P(2);
01857 Oid roleid;
01858 Oid tableoid;
01859 AclMode mode;
01860 AclResult aclresult;
01861
01862 roleid = get_role_oid_or_public(NameStr(*rolename));
01863 tableoid = convert_table_name(tablename);
01864 mode = convert_table_priv_string(priv_type_text);
01865
01866 aclresult = pg_class_aclcheck(tableoid, roleid, mode);
01867
01868 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
01869 }
01870
01871
01872
01873
01874
01875
01876
01877 Datum
01878 has_table_privilege_name(PG_FUNCTION_ARGS)
01879 {
01880 text *tablename = PG_GETARG_TEXT_P(0);
01881 text *priv_type_text = PG_GETARG_TEXT_P(1);
01882 Oid roleid;
01883 Oid tableoid;
01884 AclMode mode;
01885 AclResult aclresult;
01886
01887 roleid = GetUserId();
01888 tableoid = convert_table_name(tablename);
01889 mode = convert_table_priv_string(priv_type_text);
01890
01891 aclresult = pg_class_aclcheck(tableoid, roleid, mode);
01892
01893 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
01894 }
01895
01896
01897
01898
01899
01900
01901 Datum
01902 has_table_privilege_name_id(PG_FUNCTION_ARGS)
01903 {
01904 Name username = PG_GETARG_NAME(0);
01905 Oid tableoid = PG_GETARG_OID(1);
01906 text *priv_type_text = PG_GETARG_TEXT_P(2);
01907 Oid roleid;
01908 AclMode mode;
01909 AclResult aclresult;
01910
01911 roleid = get_role_oid_or_public(NameStr(*username));
01912 mode = convert_table_priv_string(priv_type_text);
01913
01914 if (!SearchSysCacheExists1(RELOID, ObjectIdGetDatum(tableoid)))
01915 PG_RETURN_NULL();
01916
01917 aclresult = pg_class_aclcheck(tableoid, roleid, mode);
01918
01919 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
01920 }
01921
01922
01923
01924
01925
01926
01927
01928 Datum
01929 has_table_privilege_id(PG_FUNCTION_ARGS)
01930 {
01931 Oid tableoid = PG_GETARG_OID(0);
01932 text *priv_type_text = PG_GETARG_TEXT_P(1);
01933 Oid roleid;
01934 AclMode mode;
01935 AclResult aclresult;
01936
01937 roleid = GetUserId();
01938 mode = convert_table_priv_string(priv_type_text);
01939
01940 if (!SearchSysCacheExists1(RELOID, ObjectIdGetDatum(tableoid)))
01941 PG_RETURN_NULL();
01942
01943 aclresult = pg_class_aclcheck(tableoid, roleid, mode);
01944
01945 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
01946 }
01947
01948
01949
01950
01951
01952
01953 Datum
01954 has_table_privilege_id_name(PG_FUNCTION_ARGS)
01955 {
01956 Oid roleid = PG_GETARG_OID(0);
01957 text *tablename = PG_GETARG_TEXT_P(1);
01958 text *priv_type_text = PG_GETARG_TEXT_P(2);
01959 Oid tableoid;
01960 AclMode mode;
01961 AclResult aclresult;
01962
01963 tableoid = convert_table_name(tablename);
01964 mode = convert_table_priv_string(priv_type_text);
01965
01966 aclresult = pg_class_aclcheck(tableoid, roleid, mode);
01967
01968 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
01969 }
01970
01971
01972
01973
01974
01975
01976 Datum
01977 has_table_privilege_id_id(PG_FUNCTION_ARGS)
01978 {
01979 Oid roleid = PG_GETARG_OID(0);
01980 Oid tableoid = PG_GETARG_OID(1);
01981 text *priv_type_text = PG_GETARG_TEXT_P(2);
01982 AclMode mode;
01983 AclResult aclresult;
01984
01985 mode = convert_table_priv_string(priv_type_text);
01986
01987 if (!SearchSysCacheExists1(RELOID, ObjectIdGetDatum(tableoid)))
01988 PG_RETURN_NULL();
01989
01990 aclresult = pg_class_aclcheck(tableoid, roleid, mode);
01991
01992 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
01993 }
01994
01995
01996
01997
01998
01999
02000
02001
02002 static Oid
02003 convert_table_name(text *tablename)
02004 {
02005 RangeVar *relrv;
02006
02007 relrv = makeRangeVarFromNameList(textToQualifiedNameList(tablename));
02008
02009
02010 return RangeVarGetRelid(relrv, NoLock, false);
02011 }
02012
02013
02014
02015
02016
02017 static AclMode
02018 convert_table_priv_string(text *priv_type_text)
02019 {
02020 static const priv_map table_priv_map[] = {
02021 {"SELECT", ACL_SELECT},
02022 {"SELECT WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_SELECT)},
02023 {"INSERT", ACL_INSERT},
02024 {"INSERT WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_INSERT)},
02025 {"UPDATE", ACL_UPDATE},
02026 {"UPDATE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_UPDATE)},
02027 {"DELETE", ACL_DELETE},
02028 {"DELETE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_DELETE)},
02029 {"TRUNCATE", ACL_TRUNCATE},
02030 {"TRUNCATE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_TRUNCATE)},
02031 {"REFERENCES", ACL_REFERENCES},
02032 {"REFERENCES WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_REFERENCES)},
02033 {"TRIGGER", ACL_TRIGGER},
02034 {"TRIGGER WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_TRIGGER)},
02035 {"RULE", 0},
02036 {"RULE WITH GRANT OPTION", 0},
02037 {NULL, 0}
02038 };
02039
02040 return convert_any_priv_string(priv_type_text, table_priv_map);
02041 }
02042
02043
02044
02045
02046
02047
02048
02049
02050
02051
02052
02053
02054
02055
02056
02057
02058
02059 Datum
02060 has_sequence_privilege_name_name(PG_FUNCTION_ARGS)
02061 {
02062 Name rolename = PG_GETARG_NAME(0);
02063 text *sequencename = PG_GETARG_TEXT_P(1);
02064 text *priv_type_text = PG_GETARG_TEXT_P(2);
02065 Oid roleid;
02066 Oid sequenceoid;
02067 AclMode mode;
02068 AclResult aclresult;
02069
02070 roleid = get_role_oid_or_public(NameStr(*rolename));
02071 mode = convert_sequence_priv_string(priv_type_text);
02072 sequenceoid = convert_table_name(sequencename);
02073 if (get_rel_relkind(sequenceoid) != RELKIND_SEQUENCE)
02074 ereport(ERROR,
02075 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
02076 errmsg("\"%s\" is not a sequence",
02077 text_to_cstring(sequencename))));
02078
02079 aclresult = pg_class_aclcheck(sequenceoid, roleid, mode);
02080
02081 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
02082 }
02083
02084
02085
02086
02087
02088
02089
02090 Datum
02091 has_sequence_privilege_name(PG_FUNCTION_ARGS)
02092 {
02093 text *sequencename = PG_GETARG_TEXT_P(0);
02094 text *priv_type_text = PG_GETARG_TEXT_P(1);
02095 Oid roleid;
02096 Oid sequenceoid;
02097 AclMode mode;
02098 AclResult aclresult;
02099
02100 roleid = GetUserId();
02101 mode = convert_sequence_priv_string(priv_type_text);
02102 sequenceoid = convert_table_name(sequencename);
02103 if (get_rel_relkind(sequenceoid) != RELKIND_SEQUENCE)
02104 ereport(ERROR,
02105 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
02106 errmsg("\"%s\" is not a sequence",
02107 text_to_cstring(sequencename))));
02108
02109 aclresult = pg_class_aclcheck(sequenceoid, roleid, mode);
02110
02111 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
02112 }
02113
02114
02115
02116
02117
02118
02119 Datum
02120 has_sequence_privilege_name_id(PG_FUNCTION_ARGS)
02121 {
02122 Name username = PG_GETARG_NAME(0);
02123 Oid sequenceoid = PG_GETARG_OID(1);
02124 text *priv_type_text = PG_GETARG_TEXT_P(2);
02125 Oid roleid;
02126 AclMode mode;
02127 AclResult aclresult;
02128 char relkind;
02129
02130 roleid = get_role_oid_or_public(NameStr(*username));
02131 mode = convert_sequence_priv_string(priv_type_text);
02132 relkind = get_rel_relkind(sequenceoid);
02133 if (relkind == '\0')
02134 PG_RETURN_NULL();
02135 else if (relkind != RELKIND_SEQUENCE)
02136 ereport(ERROR,
02137 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
02138 errmsg("\"%s\" is not a sequence",
02139 get_rel_name(sequenceoid))));
02140
02141 aclresult = pg_class_aclcheck(sequenceoid, roleid, mode);
02142
02143 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
02144 }
02145
02146
02147
02148
02149
02150
02151
02152 Datum
02153 has_sequence_privilege_id(PG_FUNCTION_ARGS)
02154 {
02155 Oid sequenceoid = PG_GETARG_OID(0);
02156 text *priv_type_text = PG_GETARG_TEXT_P(1);
02157 Oid roleid;
02158 AclMode mode;
02159 AclResult aclresult;
02160 char relkind;
02161
02162 roleid = GetUserId();
02163 mode = convert_sequence_priv_string(priv_type_text);
02164 relkind = get_rel_relkind(sequenceoid);
02165 if (relkind == '\0')
02166 PG_RETURN_NULL();
02167 else if (relkind != RELKIND_SEQUENCE)
02168 ereport(ERROR,
02169 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
02170 errmsg("\"%s\" is not a sequence",
02171 get_rel_name(sequenceoid))));
02172
02173 aclresult = pg_class_aclcheck(sequenceoid, roleid, mode);
02174
02175 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
02176 }
02177
02178
02179
02180
02181
02182
02183 Datum
02184 has_sequence_privilege_id_name(PG_FUNCTION_ARGS)
02185 {
02186 Oid roleid = PG_GETARG_OID(0);
02187 text *sequencename = PG_GETARG_TEXT_P(1);
02188 text *priv_type_text = PG_GETARG_TEXT_P(2);
02189 Oid sequenceoid;
02190 AclMode mode;
02191 AclResult aclresult;
02192
02193 mode = convert_sequence_priv_string(priv_type_text);
02194 sequenceoid = convert_table_name(sequencename);
02195 if (get_rel_relkind(sequenceoid) != RELKIND_SEQUENCE)
02196 ereport(ERROR,
02197 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
02198 errmsg("\"%s\" is not a sequence",
02199 text_to_cstring(sequencename))));
02200
02201 aclresult = pg_class_aclcheck(sequenceoid, roleid, mode);
02202
02203 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
02204 }
02205
02206
02207
02208
02209
02210
02211 Datum
02212 has_sequence_privilege_id_id(PG_FUNCTION_ARGS)
02213 {
02214 Oid roleid = PG_GETARG_OID(0);
02215 Oid sequenceoid = PG_GETARG_OID(1);
02216 text *priv_type_text = PG_GETARG_TEXT_P(2);
02217 AclMode mode;
02218 AclResult aclresult;
02219 char relkind;
02220
02221 mode = convert_sequence_priv_string(priv_type_text);
02222 relkind = get_rel_relkind(sequenceoid);
02223 if (relkind == '\0')
02224 PG_RETURN_NULL();
02225 else if (relkind != RELKIND_SEQUENCE)
02226 ereport(ERROR,
02227 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
02228 errmsg("\"%s\" is not a sequence",
02229 get_rel_name(sequenceoid))));
02230
02231 aclresult = pg_class_aclcheck(sequenceoid, roleid, mode);
02232
02233 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
02234 }
02235
02236
02237
02238
02239
02240 static AclMode
02241 convert_sequence_priv_string(text *priv_type_text)
02242 {
02243 static const priv_map sequence_priv_map[] = {
02244 {"USAGE", ACL_USAGE},
02245 {"SELECT", ACL_SELECT},
02246 {"UPDATE", ACL_UPDATE},
02247 {NULL, 0}
02248 };
02249
02250 return convert_any_priv_string(priv_type_text, sequence_priv_map);
02251 }
02252
02253
02254
02255
02256
02257
02258
02259
02260
02261
02262
02263
02264
02265
02266
02267
02268
02269
02270 Datum
02271 has_any_column_privilege_name_name(PG_FUNCTION_ARGS)
02272 {
02273 Name rolename = PG_GETARG_NAME(0);
02274 text *tablename = PG_GETARG_TEXT_P(1);
02275 text *priv_type_text = PG_GETARG_TEXT_P(2);
02276 Oid roleid;
02277 Oid tableoid;
02278 AclMode mode;
02279 AclResult aclresult;
02280
02281 roleid = get_role_oid_or_public(NameStr(*rolename));
02282 tableoid = convert_table_name(tablename);
02283 mode = convert_column_priv_string(priv_type_text);
02284
02285
02286 aclresult = pg_class_aclcheck(tableoid, roleid, mode);
02287 if (aclresult != ACLCHECK_OK)
02288 aclresult = pg_attribute_aclcheck_all(tableoid, roleid, mode,
02289 ACLMASK_ANY);
02290
02291 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
02292 }
02293
02294
02295
02296
02297
02298
02299
02300 Datum
02301 has_any_column_privilege_name(PG_FUNCTION_ARGS)
02302 {
02303 text *tablename = PG_GETARG_TEXT_P(0);
02304 text *priv_type_text = PG_GETARG_TEXT_P(1);
02305 Oid roleid;
02306 Oid tableoid;
02307 AclMode mode;
02308 AclResult aclresult;
02309
02310 roleid = GetUserId();
02311 tableoid = convert_table_name(tablename);
02312 mode = convert_column_priv_string(priv_type_text);
02313
02314
02315 aclresult = pg_class_aclcheck(tableoid, roleid, mode);
02316 if (aclresult != ACLCHECK_OK)
02317 aclresult = pg_attribute_aclcheck_all(tableoid, roleid, mode,
02318 ACLMASK_ANY);
02319
02320 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
02321 }
02322
02323
02324
02325
02326
02327
02328 Datum
02329 has_any_column_privilege_name_id(PG_FUNCTION_ARGS)
02330 {
02331 Name username = PG_GETARG_NAME(0);
02332 Oid tableoid = PG_GETARG_OID(1);
02333 text *priv_type_text = PG_GETARG_TEXT_P(2);
02334 Oid roleid;
02335 AclMode mode;
02336 AclResult aclresult;
02337
02338 roleid = get_role_oid_or_public(NameStr(*username));
02339 mode = convert_column_priv_string(priv_type_text);
02340
02341 if (!SearchSysCacheExists1(RELOID, ObjectIdGetDatum(tableoid)))
02342 PG_RETURN_NULL();
02343
02344
02345 aclresult = pg_class_aclcheck(tableoid, roleid, mode);
02346 if (aclresult != ACLCHECK_OK)
02347 aclresult = pg_attribute_aclcheck_all(tableoid, roleid, mode,
02348 ACLMASK_ANY);
02349
02350 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
02351 }
02352
02353
02354
02355
02356
02357
02358
02359 Datum
02360 has_any_column_privilege_id(PG_FUNCTION_ARGS)
02361 {
02362 Oid tableoid = PG_GETARG_OID(0);
02363 text *priv_type_text = PG_GETARG_TEXT_P(1);
02364 Oid roleid;
02365 AclMode mode;
02366 AclResult aclresult;
02367
02368 roleid = GetUserId();
02369 mode = convert_column_priv_string(priv_type_text);
02370
02371 if (!SearchSysCacheExists1(RELOID, ObjectIdGetDatum(tableoid)))
02372 PG_RETURN_NULL();
02373
02374
02375 aclresult = pg_class_aclcheck(tableoid, roleid, mode);
02376 if (aclresult != ACLCHECK_OK)
02377 aclresult = pg_attribute_aclcheck_all(tableoid, roleid, mode,
02378 ACLMASK_ANY);
02379
02380 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
02381 }
02382
02383
02384
02385
02386
02387
02388 Datum
02389 has_any_column_privilege_id_name(PG_FUNCTION_ARGS)
02390 {
02391 Oid roleid = PG_GETARG_OID(0);
02392 text *tablename = PG_GETARG_TEXT_P(1);
02393 text *priv_type_text = PG_GETARG_TEXT_P(2);
02394 Oid tableoid;
02395 AclMode mode;
02396 AclResult aclresult;
02397
02398 tableoid = convert_table_name(tablename);
02399 mode = convert_column_priv_string(priv_type_text);
02400
02401
02402 aclresult = pg_class_aclcheck(tableoid, roleid, mode);
02403 if (aclresult != ACLCHECK_OK)
02404 aclresult = pg_attribute_aclcheck_all(tableoid, roleid, mode,
02405 ACLMASK_ANY);
02406
02407 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
02408 }
02409
02410
02411
02412
02413
02414
02415 Datum
02416 has_any_column_privilege_id_id(PG_FUNCTION_ARGS)
02417 {
02418 Oid roleid = PG_GETARG_OID(0);
02419 Oid tableoid = PG_GETARG_OID(1);
02420 text *priv_type_text = PG_GETARG_TEXT_P(2);
02421 AclMode mode;
02422 AclResult aclresult;
02423
02424 mode = convert_column_priv_string(priv_type_text);
02425
02426 if (!SearchSysCacheExists1(RELOID, ObjectIdGetDatum(tableoid)))
02427 PG_RETURN_NULL();
02428
02429
02430 aclresult = pg_class_aclcheck(tableoid, roleid, mode);
02431 if (aclresult != ACLCHECK_OK)
02432 aclresult = pg_attribute_aclcheck_all(tableoid, roleid, mode,
02433 ACLMASK_ANY);
02434
02435 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
02436 }
02437
02438
02439
02440
02441
02442
02443
02444
02445
02446
02447
02448
02449
02450
02451
02452
02453
02454
02455
02456
02457
02458 static int
02459 column_privilege_check(Oid tableoid, AttrNumber attnum,
02460 Oid roleid, AclMode mode)
02461 {
02462 AclResult aclresult;
02463 HeapTuple attTuple;
02464 Form_pg_attribute attributeForm;
02465
02466
02467
02468
02469
02470
02471
02472
02473
02474 if (!SearchSysCacheExists1(RELOID, ObjectIdGetDatum(tableoid)))
02475 return -1;
02476
02477 aclresult = pg_class_aclcheck(tableoid, roleid, mode);
02478
02479 if (aclresult == ACLCHECK_OK)
02480 return true;
02481
02482
02483
02484
02485
02486
02487 attTuple = SearchSysCache2(ATTNUM,
02488 ObjectIdGetDatum(tableoid),
02489 Int16GetDatum(attnum));
02490 if (!HeapTupleIsValid(attTuple))
02491 return -1;
02492 attributeForm = (Form_pg_attribute) GETSTRUCT(attTuple);
02493 if (attributeForm->attisdropped)
02494 {
02495 ReleaseSysCache(attTuple);
02496 return -1;
02497 }
02498 ReleaseSysCache(attTuple);
02499
02500 aclresult = pg_attribute_aclcheck(tableoid, attnum, roleid, mode);
02501
02502 return (aclresult == ACLCHECK_OK);
02503 }
02504
02505
02506
02507
02508
02509
02510 Datum
02511 has_column_privilege_name_name_name(PG_FUNCTION_ARGS)
02512 {
02513 Name rolename = PG_GETARG_NAME(0);
02514 text *tablename = PG_GETARG_TEXT_P(1);
02515 text *column = PG_GETARG_TEXT_P(2);
02516 text *priv_type_text = PG_GETARG_TEXT_P(3);
02517 Oid roleid;
02518 Oid tableoid;
02519 AttrNumber colattnum;
02520 AclMode mode;
02521 int privresult;
02522
02523 roleid = get_role_oid_or_public(NameStr(*rolename));
02524 tableoid = convert_table_name(tablename);
02525 colattnum = convert_column_name(tableoid, column);
02526 mode = convert_column_priv_string(priv_type_text);
02527
02528 privresult = column_privilege_check(tableoid, colattnum, roleid, mode);
02529 if (privresult < 0)
02530 PG_RETURN_NULL();
02531 PG_RETURN_BOOL(privresult);
02532 }
02533
02534
02535
02536
02537
02538
02539 Datum
02540 has_column_privilege_name_name_attnum(PG_FUNCTION_ARGS)
02541 {
02542 Name rolename = PG_GETARG_NAME(0);
02543 text *tablename = PG_GETARG_TEXT_P(1);
02544 AttrNumber colattnum = PG_GETARG_INT16(2);
02545 text *priv_type_text = PG_GETARG_TEXT_P(3);
02546 Oid roleid;
02547 Oid tableoid;
02548 AclMode mode;
02549 int privresult;
02550
02551 roleid = get_role_oid_or_public(NameStr(*rolename));
02552 tableoid = convert_table_name(tablename);
02553 mode = convert_column_priv_string(priv_type_text);
02554
02555 privresult = column_privilege_check(tableoid, colattnum, roleid, mode);
02556 if (privresult < 0)
02557 PG_RETURN_NULL();
02558 PG_RETURN_BOOL(privresult);
02559 }
02560
02561
02562
02563
02564
02565
02566 Datum
02567 has_column_privilege_name_id_name(PG_FUNCTION_ARGS)
02568 {
02569 Name username = PG_GETARG_NAME(0);
02570 Oid tableoid = PG_GETARG_OID(1);
02571 text *column = PG_GETARG_TEXT_P(2);
02572 text *priv_type_text = PG_GETARG_TEXT_P(3);
02573 Oid roleid;
02574 AttrNumber colattnum;
02575 AclMode mode;
02576 int privresult;
02577
02578 roleid = get_role_oid_or_public(NameStr(*username));
02579 colattnum = convert_column_name(tableoid, column);
02580 mode = convert_column_priv_string(priv_type_text);
02581
02582 privresult = column_privilege_check(tableoid, colattnum, roleid, mode);
02583 if (privresult < 0)
02584 PG_RETURN_NULL();
02585 PG_RETURN_BOOL(privresult);
02586 }
02587
02588
02589
02590
02591
02592
02593 Datum
02594 has_column_privilege_name_id_attnum(PG_FUNCTION_ARGS)
02595 {
02596 Name username = PG_GETARG_NAME(0);
02597 Oid tableoid = PG_GETARG_OID(1);
02598 AttrNumber colattnum = PG_GETARG_INT16(2);
02599 text *priv_type_text = PG_GETARG_TEXT_P(3);
02600 Oid roleid;
02601 AclMode mode;
02602 int privresult;
02603
02604 roleid = get_role_oid_or_public(NameStr(*username));
02605 mode = convert_column_priv_string(priv_type_text);
02606
02607 privresult = column_privilege_check(tableoid, colattnum, roleid, mode);
02608 if (privresult < 0)
02609 PG_RETURN_NULL();
02610 PG_RETURN_BOOL(privresult);
02611 }
02612
02613
02614
02615
02616
02617
02618 Datum
02619 has_column_privilege_id_name_name(PG_FUNCTION_ARGS)
02620 {
02621 Oid roleid = PG_GETARG_OID(0);
02622 text *tablename = PG_GETARG_TEXT_P(1);
02623 text *column = PG_GETARG_TEXT_P(2);
02624 text *priv_type_text = PG_GETARG_TEXT_P(3);
02625 Oid tableoid;
02626 AttrNumber colattnum;
02627 AclMode mode;
02628 int privresult;
02629
02630 tableoid = convert_table_name(tablename);
02631 colattnum = convert_column_name(tableoid, column);
02632 mode = convert_column_priv_string(priv_type_text);
02633
02634 privresult = column_privilege_check(tableoid, colattnum, roleid, mode);
02635 if (privresult < 0)
02636 PG_RETURN_NULL();
02637 PG_RETURN_BOOL(privresult);
02638 }
02639
02640
02641
02642
02643
02644
02645 Datum
02646 has_column_privilege_id_name_attnum(PG_FUNCTION_ARGS)
02647 {
02648 Oid roleid = PG_GETARG_OID(0);
02649 text *tablename = PG_GETARG_TEXT_P(1);
02650 AttrNumber colattnum = PG_GETARG_INT16(2);
02651 text *priv_type_text = PG_GETARG_TEXT_P(3);
02652 Oid tableoid;
02653 AclMode mode;
02654 int privresult;
02655
02656 tableoid = convert_table_name(tablename);
02657 mode = convert_column_priv_string(priv_type_text);
02658
02659 privresult = column_privilege_check(tableoid, colattnum, roleid, mode);
02660 if (privresult < 0)
02661 PG_RETURN_NULL();
02662 PG_RETURN_BOOL(privresult);
02663 }
02664
02665
02666
02667
02668
02669
02670 Datum
02671 has_column_privilege_id_id_name(PG_FUNCTION_ARGS)
02672 {
02673 Oid roleid = PG_GETARG_OID(0);
02674 Oid tableoid = PG_GETARG_OID(1);
02675 text *column = PG_GETARG_TEXT_P(2);
02676 text *priv_type_text = PG_GETARG_TEXT_P(3);
02677 AttrNumber colattnum;
02678 AclMode mode;
02679 int privresult;
02680
02681 colattnum = convert_column_name(tableoid, column);
02682 mode = convert_column_priv_string(priv_type_text);
02683
02684 privresult = column_privilege_check(tableoid, colattnum, roleid, mode);
02685 if (privresult < 0)
02686 PG_RETURN_NULL();
02687 PG_RETURN_BOOL(privresult);
02688 }
02689
02690
02691
02692
02693
02694
02695 Datum
02696 has_column_privilege_id_id_attnum(PG_FUNCTION_ARGS)
02697 {
02698 Oid roleid = PG_GETARG_OID(0);
02699 Oid tableoid = PG_GETARG_OID(1);
02700 AttrNumber colattnum = PG_GETARG_INT16(2);
02701 text *priv_type_text = PG_GETARG_TEXT_P(3);
02702 AclMode mode;
02703 int privresult;
02704
02705 mode = convert_column_priv_string(priv_type_text);
02706
02707 privresult = column_privilege_check(tableoid, colattnum, roleid, mode);
02708 if (privresult < 0)
02709 PG_RETURN_NULL();
02710 PG_RETURN_BOOL(privresult);
02711 }
02712
02713
02714
02715
02716
02717
02718
02719 Datum
02720 has_column_privilege_name_name(PG_FUNCTION_ARGS)
02721 {
02722 text *tablename = PG_GETARG_TEXT_P(0);
02723 text *column = PG_GETARG_TEXT_P(1);
02724 text *priv_type_text = PG_GETARG_TEXT_P(2);
02725 Oid roleid;
02726 Oid tableoid;
02727 AttrNumber colattnum;
02728 AclMode mode;
02729 int privresult;
02730
02731 roleid = GetUserId();
02732 tableoid = convert_table_name(tablename);
02733 colattnum = convert_column_name(tableoid, column);
02734 mode = convert_column_priv_string(priv_type_text);
02735
02736 privresult = column_privilege_check(tableoid, colattnum, roleid, mode);
02737 if (privresult < 0)
02738 PG_RETURN_NULL();
02739 PG_RETURN_BOOL(privresult);
02740 }
02741
02742
02743
02744
02745
02746
02747
02748 Datum
02749 has_column_privilege_name_attnum(PG_FUNCTION_ARGS)
02750 {
02751 text *tablename = PG_GETARG_TEXT_P(0);
02752 AttrNumber colattnum = PG_GETARG_INT16(1);
02753 text *priv_type_text = PG_GETARG_TEXT_P(2);
02754 Oid roleid;
02755 Oid tableoid;
02756 AclMode mode;
02757 int privresult;
02758
02759 roleid = GetUserId();
02760 tableoid = convert_table_name(tablename);
02761 mode = convert_column_priv_string(priv_type_text);
02762
02763 privresult = column_privilege_check(tableoid, colattnum, roleid, mode);
02764 if (privresult < 0)
02765 PG_RETURN_NULL();
02766 PG_RETURN_BOOL(privresult);
02767 }
02768
02769
02770
02771
02772
02773
02774
02775 Datum
02776 has_column_privilege_id_name(PG_FUNCTION_ARGS)
02777 {
02778 Oid tableoid = PG_GETARG_OID(0);
02779 text *column = PG_GETARG_TEXT_P(1);
02780 text *priv_type_text = PG_GETARG_TEXT_P(2);
02781 Oid roleid;
02782 AttrNumber colattnum;
02783 AclMode mode;
02784 int privresult;
02785
02786 roleid = GetUserId();
02787 colattnum = convert_column_name(tableoid, column);
02788 mode = convert_column_priv_string(priv_type_text);
02789
02790 privresult = column_privilege_check(tableoid, colattnum, roleid, mode);
02791 if (privresult < 0)
02792 PG_RETURN_NULL();
02793 PG_RETURN_BOOL(privresult);
02794 }
02795
02796
02797
02798
02799
02800
02801
02802 Datum
02803 has_column_privilege_id_attnum(PG_FUNCTION_ARGS)
02804 {
02805 Oid tableoid = PG_GETARG_OID(0);
02806 AttrNumber colattnum = PG_GETARG_INT16(1);
02807 text *priv_type_text = PG_GETARG_TEXT_P(2);
02808 Oid roleid;
02809 AclMode mode;
02810 int privresult;
02811
02812 roleid = GetUserId();
02813 mode = convert_column_priv_string(priv_type_text);
02814
02815 privresult = column_privilege_check(tableoid, colattnum, roleid, mode);
02816 if (privresult < 0)
02817 PG_RETURN_NULL();
02818 PG_RETURN_BOOL(privresult);
02819 }
02820
02821
02822
02823
02824
02825
02826
02827
02828
02829 static AttrNumber
02830 convert_column_name(Oid tableoid, text *column)
02831 {
02832 AttrNumber attnum;
02833 char *colname;
02834
02835 colname = text_to_cstring(column);
02836 attnum = get_attnum(tableoid, colname);
02837 if (attnum == InvalidAttrNumber)
02838 ereport(ERROR,
02839 (errcode(ERRCODE_UNDEFINED_COLUMN),
02840 errmsg("column \"%s\" of relation \"%s\" does not exist",
02841 colname, get_rel_name(tableoid))));
02842 pfree(colname);
02843 return attnum;
02844 }
02845
02846
02847
02848
02849
02850 static AclMode
02851 convert_column_priv_string(text *priv_type_text)
02852 {
02853 static const priv_map column_priv_map[] = {
02854 {"SELECT", ACL_SELECT},
02855 {"SELECT WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_SELECT)},
02856 {"INSERT", ACL_INSERT},
02857 {"INSERT WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_INSERT)},
02858 {"UPDATE", ACL_UPDATE},
02859 {"UPDATE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_UPDATE)},
02860 {"REFERENCES", ACL_REFERENCES},
02861 {"REFERENCES WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_REFERENCES)},
02862 {NULL, 0}
02863 };
02864
02865 return convert_any_priv_string(priv_type_text, column_priv_map);
02866 }
02867
02868
02869
02870
02871
02872
02873
02874
02875
02876
02877
02878
02879
02880
02881
02882
02883
02884 Datum
02885 has_database_privilege_name_name(PG_FUNCTION_ARGS)
02886 {
02887 Name username = PG_GETARG_NAME(0);
02888 text *databasename = PG_GETARG_TEXT_P(1);
02889 text *priv_type_text = PG_GETARG_TEXT_P(2);
02890 Oid roleid;
02891 Oid databaseoid;
02892 AclMode mode;
02893 AclResult aclresult;
02894
02895 roleid = get_role_oid_or_public(NameStr(*username));
02896 databaseoid = convert_database_name(databasename);
02897 mode = convert_database_priv_string(priv_type_text);
02898
02899 aclresult = pg_database_aclcheck(databaseoid, roleid, mode);
02900
02901 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
02902 }
02903
02904
02905
02906
02907
02908
02909
02910 Datum
02911 has_database_privilege_name(PG_FUNCTION_ARGS)
02912 {
02913 text *databasename = PG_GETARG_TEXT_P(0);
02914 text *priv_type_text = PG_GETARG_TEXT_P(1);
02915 Oid roleid;
02916 Oid databaseoid;
02917 AclMode mode;
02918 AclResult aclresult;
02919
02920 roleid = GetUserId();
02921 databaseoid = convert_database_name(databasename);
02922 mode = convert_database_priv_string(priv_type_text);
02923
02924 aclresult = pg_database_aclcheck(databaseoid, roleid, mode);
02925
02926 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
02927 }
02928
02929
02930
02931
02932
02933
02934 Datum
02935 has_database_privilege_name_id(PG_FUNCTION_ARGS)
02936 {
02937 Name username = PG_GETARG_NAME(0);
02938 Oid databaseoid = PG_GETARG_OID(1);
02939 text *priv_type_text = PG_GETARG_TEXT_P(2);
02940 Oid roleid;
02941 AclMode mode;
02942 AclResult aclresult;
02943
02944 roleid = get_role_oid_or_public(NameStr(*username));
02945 mode = convert_database_priv_string(priv_type_text);
02946
02947 if (!SearchSysCacheExists1(DATABASEOID, ObjectIdGetDatum(databaseoid)))
02948 PG_RETURN_NULL();
02949
02950 aclresult = pg_database_aclcheck(databaseoid, roleid, mode);
02951
02952 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
02953 }
02954
02955
02956
02957
02958
02959
02960
02961 Datum
02962 has_database_privilege_id(PG_FUNCTION_ARGS)
02963 {
02964 Oid databaseoid = PG_GETARG_OID(0);
02965 text *priv_type_text = PG_GETARG_TEXT_P(1);
02966 Oid roleid;
02967 AclMode mode;
02968 AclResult aclresult;
02969
02970 roleid = GetUserId();
02971 mode = convert_database_priv_string(priv_type_text);
02972
02973 if (!SearchSysCacheExists1(DATABASEOID, ObjectIdGetDatum(databaseoid)))
02974 PG_RETURN_NULL();
02975
02976 aclresult = pg_database_aclcheck(databaseoid, roleid, mode);
02977
02978 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
02979 }
02980
02981
02982
02983
02984
02985
02986 Datum
02987 has_database_privilege_id_name(PG_FUNCTION_ARGS)
02988 {
02989 Oid roleid = PG_GETARG_OID(0);
02990 text *databasename = PG_GETARG_TEXT_P(1);
02991 text *priv_type_text = PG_GETARG_TEXT_P(2);
02992 Oid databaseoid;
02993 AclMode mode;
02994 AclResult aclresult;
02995
02996 databaseoid = convert_database_name(databasename);
02997 mode = convert_database_priv_string(priv_type_text);
02998
02999 aclresult = pg_database_aclcheck(databaseoid, roleid, mode);
03000
03001 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
03002 }
03003
03004
03005
03006
03007
03008
03009 Datum
03010 has_database_privilege_id_id(PG_FUNCTION_ARGS)
03011 {
03012 Oid roleid = PG_GETARG_OID(0);
03013 Oid databaseoid = PG_GETARG_OID(1);
03014 text *priv_type_text = PG_GETARG_TEXT_P(2);
03015 AclMode mode;
03016 AclResult aclresult;
03017
03018 mode = convert_database_priv_string(priv_type_text);
03019
03020 if (!SearchSysCacheExists1(DATABASEOID, ObjectIdGetDatum(databaseoid)))
03021 PG_RETURN_NULL();
03022
03023 aclresult = pg_database_aclcheck(databaseoid, roleid, mode);
03024
03025 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
03026 }
03027
03028
03029
03030
03031
03032
03033
03034
03035 static Oid
03036 convert_database_name(text *databasename)
03037 {
03038 char *dbname = text_to_cstring(databasename);
03039
03040 return get_database_oid(dbname, false);
03041 }
03042
03043
03044
03045
03046
03047 static AclMode
03048 convert_database_priv_string(text *priv_type_text)
03049 {
03050 static const priv_map database_priv_map[] = {
03051 {"CREATE", ACL_CREATE},
03052 {"CREATE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_CREATE)},
03053 {"TEMPORARY", ACL_CREATE_TEMP},
03054 {"TEMPORARY WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_CREATE_TEMP)},
03055 {"TEMP", ACL_CREATE_TEMP},
03056 {"TEMP WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_CREATE_TEMP)},
03057 {"CONNECT", ACL_CONNECT},
03058 {"CONNECT WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_CONNECT)},
03059 {NULL, 0}
03060 };
03061
03062 return convert_any_priv_string(priv_type_text, database_priv_map);
03063
03064 }
03065
03066
03067
03068
03069
03070
03071
03072
03073
03074
03075
03076
03077
03078
03079
03080
03081
03082 Datum
03083 has_foreign_data_wrapper_privilege_name_name(PG_FUNCTION_ARGS)
03084 {
03085 Name username = PG_GETARG_NAME(0);
03086 text *fdwname = PG_GETARG_TEXT_P(1);
03087 text *priv_type_text = PG_GETARG_TEXT_P(2);
03088 Oid roleid;
03089 Oid fdwid;
03090 AclMode mode;
03091 AclResult aclresult;
03092
03093 roleid = get_role_oid_or_public(NameStr(*username));
03094 fdwid = convert_foreign_data_wrapper_name(fdwname);
03095 mode = convert_foreign_data_wrapper_priv_string(priv_type_text);
03096
03097 aclresult = pg_foreign_data_wrapper_aclcheck(fdwid, roleid, mode);
03098
03099 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
03100 }
03101
03102
03103
03104
03105
03106
03107
03108 Datum
03109 has_foreign_data_wrapper_privilege_name(PG_FUNCTION_ARGS)
03110 {
03111 text *fdwname = PG_GETARG_TEXT_P(0);
03112 text *priv_type_text = PG_GETARG_TEXT_P(1);
03113 Oid roleid;
03114 Oid fdwid;
03115 AclMode mode;
03116 AclResult aclresult;
03117
03118 roleid = GetUserId();
03119 fdwid = convert_foreign_data_wrapper_name(fdwname);
03120 mode = convert_foreign_data_wrapper_priv_string(priv_type_text);
03121
03122 aclresult = pg_foreign_data_wrapper_aclcheck(fdwid, roleid, mode);
03123
03124 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
03125 }
03126
03127
03128
03129
03130
03131
03132 Datum
03133 has_foreign_data_wrapper_privilege_name_id(PG_FUNCTION_ARGS)
03134 {
03135 Name username = PG_GETARG_NAME(0);
03136 Oid fdwid = PG_GETARG_OID(1);
03137 text *priv_type_text = PG_GETARG_TEXT_P(2);
03138 Oid roleid;
03139 AclMode mode;
03140 AclResult aclresult;
03141
03142 roleid = get_role_oid_or_public(NameStr(*username));
03143 mode = convert_foreign_data_wrapper_priv_string(priv_type_text);
03144
03145 aclresult = pg_foreign_data_wrapper_aclcheck(fdwid, roleid, mode);
03146
03147 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
03148 }
03149
03150
03151
03152
03153
03154
03155
03156 Datum
03157 has_foreign_data_wrapper_privilege_id(PG_FUNCTION_ARGS)
03158 {
03159 Oid fdwid = PG_GETARG_OID(0);
03160 text *priv_type_text = PG_GETARG_TEXT_P(1);
03161 Oid roleid;
03162 AclMode mode;
03163 AclResult aclresult;
03164
03165 roleid = GetUserId();
03166 mode = convert_foreign_data_wrapper_priv_string(priv_type_text);
03167
03168 aclresult = pg_foreign_data_wrapper_aclcheck(fdwid, roleid, mode);
03169
03170 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
03171 }
03172
03173
03174
03175
03176
03177
03178 Datum
03179 has_foreign_data_wrapper_privilege_id_name(PG_FUNCTION_ARGS)
03180 {
03181 Oid roleid = PG_GETARG_OID(0);
03182 text *fdwname = PG_GETARG_TEXT_P(1);
03183 text *priv_type_text = PG_GETARG_TEXT_P(2);
03184 Oid fdwid;
03185 AclMode mode;
03186 AclResult aclresult;
03187
03188 fdwid = convert_foreign_data_wrapper_name(fdwname);
03189 mode = convert_foreign_data_wrapper_priv_string(priv_type_text);
03190
03191 aclresult = pg_foreign_data_wrapper_aclcheck(fdwid, roleid, mode);
03192
03193 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
03194 }
03195
03196
03197
03198
03199
03200
03201 Datum
03202 has_foreign_data_wrapper_privilege_id_id(PG_FUNCTION_ARGS)
03203 {
03204 Oid roleid = PG_GETARG_OID(0);
03205 Oid fdwid = PG_GETARG_OID(1);
03206 text *priv_type_text = PG_GETARG_TEXT_P(2);
03207 AclMode mode;
03208 AclResult aclresult;
03209
03210 mode = convert_foreign_data_wrapper_priv_string(priv_type_text);
03211
03212 aclresult = pg_foreign_data_wrapper_aclcheck(fdwid, roleid, mode);
03213
03214 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
03215 }
03216
03217
03218
03219
03220
03221
03222
03223
03224 static Oid
03225 convert_foreign_data_wrapper_name(text *fdwname)
03226 {
03227 char *fdwstr = text_to_cstring(fdwname);
03228
03229 return get_foreign_data_wrapper_oid(fdwstr, false);
03230 }
03231
03232
03233
03234
03235
03236 static AclMode
03237 convert_foreign_data_wrapper_priv_string(text *priv_type_text)
03238 {
03239 static const priv_map foreign_data_wrapper_priv_map[] = {
03240 {"USAGE", ACL_USAGE},
03241 {"USAGE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_USAGE)},
03242 {NULL, 0}
03243 };
03244
03245 return convert_any_priv_string(priv_type_text, foreign_data_wrapper_priv_map);
03246 }
03247
03248
03249
03250
03251
03252
03253
03254
03255
03256
03257
03258
03259
03260
03261
03262
03263
03264 Datum
03265 has_function_privilege_name_name(PG_FUNCTION_ARGS)
03266 {
03267 Name username = PG_GETARG_NAME(0);
03268 text *functionname = PG_GETARG_TEXT_P(1);
03269 text *priv_type_text = PG_GETARG_TEXT_P(2);
03270 Oid roleid;
03271 Oid functionoid;
03272 AclMode mode;
03273 AclResult aclresult;
03274
03275 roleid = get_role_oid_or_public(NameStr(*username));
03276 functionoid = convert_function_name(functionname);
03277 mode = convert_function_priv_string(priv_type_text);
03278
03279 aclresult = pg_proc_aclcheck(functionoid, roleid, mode);
03280
03281 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
03282 }
03283
03284
03285
03286
03287
03288
03289
03290 Datum
03291 has_function_privilege_name(PG_FUNCTION_ARGS)
03292 {
03293 text *functionname = PG_GETARG_TEXT_P(0);
03294 text *priv_type_text = PG_GETARG_TEXT_P(1);
03295 Oid roleid;
03296 Oid functionoid;
03297 AclMode mode;
03298 AclResult aclresult;
03299
03300 roleid = GetUserId();
03301 functionoid = convert_function_name(functionname);
03302 mode = convert_function_priv_string(priv_type_text);
03303
03304 aclresult = pg_proc_aclcheck(functionoid, roleid, mode);
03305
03306 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
03307 }
03308
03309
03310
03311
03312
03313
03314 Datum
03315 has_function_privilege_name_id(PG_FUNCTION_ARGS)
03316 {
03317 Name username = PG_GETARG_NAME(0);
03318 Oid functionoid = PG_GETARG_OID(1);
03319 text *priv_type_text = PG_GETARG_TEXT_P(2);
03320 Oid roleid;
03321 AclMode mode;
03322 AclResult aclresult;
03323
03324 roleid = get_role_oid_or_public(NameStr(*username));
03325 mode = convert_function_priv_string(priv_type_text);
03326
03327 if (!SearchSysCacheExists1(PROCOID, ObjectIdGetDatum(functionoid)))
03328 PG_RETURN_NULL();
03329
03330 aclresult = pg_proc_aclcheck(functionoid, roleid, mode);
03331
03332 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
03333 }
03334
03335
03336
03337
03338
03339
03340
03341 Datum
03342 has_function_privilege_id(PG_FUNCTION_ARGS)
03343 {
03344 Oid functionoid = PG_GETARG_OID(0);
03345 text *priv_type_text = PG_GETARG_TEXT_P(1);
03346 Oid roleid;
03347 AclMode mode;
03348 AclResult aclresult;
03349
03350 roleid = GetUserId();
03351 mode = convert_function_priv_string(priv_type_text);
03352
03353 if (!SearchSysCacheExists1(PROCOID, ObjectIdGetDatum(functionoid)))
03354 PG_RETURN_NULL();
03355
03356 aclresult = pg_proc_aclcheck(functionoid, roleid, mode);
03357
03358 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
03359 }
03360
03361
03362
03363
03364
03365
03366 Datum
03367 has_function_privilege_id_name(PG_FUNCTION_ARGS)
03368 {
03369 Oid roleid = PG_GETARG_OID(0);
03370 text *functionname = PG_GETARG_TEXT_P(1);
03371 text *priv_type_text = PG_GETARG_TEXT_P(2);
03372 Oid functionoid;
03373 AclMode mode;
03374 AclResult aclresult;
03375
03376 functionoid = convert_function_name(functionname);
03377 mode = convert_function_priv_string(priv_type_text);
03378
03379 aclresult = pg_proc_aclcheck(functionoid, roleid, mode);
03380
03381 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
03382 }
03383
03384
03385
03386
03387
03388
03389 Datum
03390 has_function_privilege_id_id(PG_FUNCTION_ARGS)
03391 {
03392 Oid roleid = PG_GETARG_OID(0);
03393 Oid functionoid = PG_GETARG_OID(1);
03394 text *priv_type_text = PG_GETARG_TEXT_P(2);
03395 AclMode mode;
03396 AclResult aclresult;
03397
03398 mode = convert_function_priv_string(priv_type_text);
03399
03400 if (!SearchSysCacheExists1(PROCOID, ObjectIdGetDatum(functionoid)))
03401 PG_RETURN_NULL();
03402
03403 aclresult = pg_proc_aclcheck(functionoid, roleid, mode);
03404
03405 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
03406 }
03407
03408
03409
03410
03411
03412
03413
03414
03415 static Oid
03416 convert_function_name(text *functionname)
03417 {
03418 char *funcname = text_to_cstring(functionname);
03419 Oid oid;
03420
03421 oid = DatumGetObjectId(DirectFunctionCall1(regprocedurein,
03422 CStringGetDatum(funcname)));
03423
03424 if (!OidIsValid(oid))
03425 ereport(ERROR,
03426 (errcode(ERRCODE_UNDEFINED_FUNCTION),
03427 errmsg("function \"%s\" does not exist", funcname)));
03428
03429 return oid;
03430 }
03431
03432
03433
03434
03435
03436 static AclMode
03437 convert_function_priv_string(text *priv_type_text)
03438 {
03439 static const priv_map function_priv_map[] = {
03440 {"EXECUTE", ACL_EXECUTE},
03441 {"EXECUTE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_EXECUTE)},
03442 {NULL, 0}
03443 };
03444
03445 return convert_any_priv_string(priv_type_text, function_priv_map);
03446 }
03447
03448
03449
03450
03451
03452
03453
03454
03455
03456
03457
03458
03459
03460
03461
03462
03463
03464 Datum
03465 has_language_privilege_name_name(PG_FUNCTION_ARGS)
03466 {
03467 Name username = PG_GETARG_NAME(0);
03468 text *languagename = PG_GETARG_TEXT_P(1);
03469 text *priv_type_text = PG_GETARG_TEXT_P(2);
03470 Oid roleid;
03471 Oid languageoid;
03472 AclMode mode;
03473 AclResult aclresult;
03474
03475 roleid = get_role_oid_or_public(NameStr(*username));
03476 languageoid = convert_language_name(languagename);
03477 mode = convert_language_priv_string(priv_type_text);
03478
03479 aclresult = pg_language_aclcheck(languageoid, roleid, mode);
03480
03481 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
03482 }
03483
03484
03485
03486
03487
03488
03489
03490 Datum
03491 has_language_privilege_name(PG_FUNCTION_ARGS)
03492 {
03493 text *languagename = PG_GETARG_TEXT_P(0);
03494 text *priv_type_text = PG_GETARG_TEXT_P(1);
03495 Oid roleid;
03496 Oid languageoid;
03497 AclMode mode;
03498 AclResult aclresult;
03499
03500 roleid = GetUserId();
03501 languageoid = convert_language_name(languagename);
03502 mode = convert_language_priv_string(priv_type_text);
03503
03504 aclresult = pg_language_aclcheck(languageoid, roleid, mode);
03505
03506 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
03507 }
03508
03509
03510
03511
03512
03513
03514 Datum
03515 has_language_privilege_name_id(PG_FUNCTION_ARGS)
03516 {
03517 Name username = PG_GETARG_NAME(0);
03518 Oid languageoid = PG_GETARG_OID(1);
03519 text *priv_type_text = PG_GETARG_TEXT_P(2);
03520 Oid roleid;
03521 AclMode mode;
03522 AclResult aclresult;
03523
03524 roleid = get_role_oid_or_public(NameStr(*username));
03525 mode = convert_language_priv_string(priv_type_text);
03526
03527 if (!SearchSysCacheExists1(LANGOID, ObjectIdGetDatum(languageoid)))
03528 PG_RETURN_NULL();
03529
03530 aclresult = pg_language_aclcheck(languageoid, roleid, mode);
03531
03532 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
03533 }
03534
03535
03536
03537
03538
03539
03540
03541 Datum
03542 has_language_privilege_id(PG_FUNCTION_ARGS)
03543 {
03544 Oid languageoid = PG_GETARG_OID(0);
03545 text *priv_type_text = PG_GETARG_TEXT_P(1);
03546 Oid roleid;
03547 AclMode mode;
03548 AclResult aclresult;
03549
03550 roleid = GetUserId();
03551 mode = convert_language_priv_string(priv_type_text);
03552
03553 if (!SearchSysCacheExists1(LANGOID, ObjectIdGetDatum(languageoid)))
03554 PG_RETURN_NULL();
03555
03556 aclresult = pg_language_aclcheck(languageoid, roleid, mode);
03557
03558 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
03559 }
03560
03561
03562
03563
03564
03565
03566 Datum
03567 has_language_privilege_id_name(PG_FUNCTION_ARGS)
03568 {
03569 Oid roleid = PG_GETARG_OID(0);
03570 text *languagename = PG_GETARG_TEXT_P(1);
03571 text *priv_type_text = PG_GETARG_TEXT_P(2);
03572 Oid languageoid;
03573 AclMode mode;
03574 AclResult aclresult;
03575
03576 languageoid = convert_language_name(languagename);
03577 mode = convert_language_priv_string(priv_type_text);
03578
03579 aclresult = pg_language_aclcheck(languageoid, roleid, mode);
03580
03581 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
03582 }
03583
03584
03585
03586
03587
03588
03589 Datum
03590 has_language_privilege_id_id(PG_FUNCTION_ARGS)
03591 {
03592 Oid roleid = PG_GETARG_OID(0);
03593 Oid languageoid = PG_GETARG_OID(1);
03594 text *priv_type_text = PG_GETARG_TEXT_P(2);
03595 AclMode mode;
03596 AclResult aclresult;
03597
03598 mode = convert_language_priv_string(priv_type_text);
03599
03600 if (!SearchSysCacheExists1(LANGOID, ObjectIdGetDatum(languageoid)))
03601 PG_RETURN_NULL();
03602
03603 aclresult = pg_language_aclcheck(languageoid, roleid, mode);
03604
03605 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
03606 }
03607
03608
03609
03610
03611
03612
03613
03614
03615 static Oid
03616 convert_language_name(text *languagename)
03617 {
03618 char *langname = text_to_cstring(languagename);
03619
03620 return get_language_oid(langname, false);
03621 }
03622
03623
03624
03625
03626
03627 static AclMode
03628 convert_language_priv_string(text *priv_type_text)
03629 {
03630 static const priv_map language_priv_map[] = {
03631 {"USAGE", ACL_USAGE},
03632 {"USAGE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_USAGE)},
03633 {NULL, 0}
03634 };
03635
03636 return convert_any_priv_string(priv_type_text, language_priv_map);
03637 }
03638
03639
03640
03641
03642
03643
03644
03645
03646
03647
03648
03649
03650
03651
03652
03653
03654
03655 Datum
03656 has_schema_privilege_name_name(PG_FUNCTION_ARGS)
03657 {
03658 Name username = PG_GETARG_NAME(0);
03659 text *schemaname = PG_GETARG_TEXT_P(1);
03660 text *priv_type_text = PG_GETARG_TEXT_P(2);
03661 Oid roleid;
03662 Oid schemaoid;
03663 AclMode mode;
03664 AclResult aclresult;
03665
03666 roleid = get_role_oid_or_public(NameStr(*username));
03667 schemaoid = convert_schema_name(schemaname);
03668 mode = convert_schema_priv_string(priv_type_text);
03669
03670 aclresult = pg_namespace_aclcheck(schemaoid, roleid, mode);
03671
03672 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
03673 }
03674
03675
03676
03677
03678
03679
03680
03681 Datum
03682 has_schema_privilege_name(PG_FUNCTION_ARGS)
03683 {
03684 text *schemaname = PG_GETARG_TEXT_P(0);
03685 text *priv_type_text = PG_GETARG_TEXT_P(1);
03686 Oid roleid;
03687 Oid schemaoid;
03688 AclMode mode;
03689 AclResult aclresult;
03690
03691 roleid = GetUserId();
03692 schemaoid = convert_schema_name(schemaname);
03693 mode = convert_schema_priv_string(priv_type_text);
03694
03695 aclresult = pg_namespace_aclcheck(schemaoid, roleid, mode);
03696
03697 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
03698 }
03699
03700
03701
03702
03703
03704
03705 Datum
03706 has_schema_privilege_name_id(PG_FUNCTION_ARGS)
03707 {
03708 Name username = PG_GETARG_NAME(0);
03709 Oid schemaoid = PG_GETARG_OID(1);
03710 text *priv_type_text = PG_GETARG_TEXT_P(2);
03711 Oid roleid;
03712 AclMode mode;
03713 AclResult aclresult;
03714
03715 roleid = get_role_oid_or_public(NameStr(*username));
03716 mode = convert_schema_priv_string(priv_type_text);
03717
03718 if (!SearchSysCacheExists1(NAMESPACEOID, ObjectIdGetDatum(schemaoid)))
03719 PG_RETURN_NULL();
03720
03721 aclresult = pg_namespace_aclcheck(schemaoid, roleid, mode);
03722
03723 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
03724 }
03725
03726
03727
03728
03729
03730
03731
03732 Datum
03733 has_schema_privilege_id(PG_FUNCTION_ARGS)
03734 {
03735 Oid schemaoid = PG_GETARG_OID(0);
03736 text *priv_type_text = PG_GETARG_TEXT_P(1);
03737 Oid roleid;
03738 AclMode mode;
03739 AclResult aclresult;
03740
03741 roleid = GetUserId();
03742 mode = convert_schema_priv_string(priv_type_text);
03743
03744 if (!SearchSysCacheExists1(NAMESPACEOID, ObjectIdGetDatum(schemaoid)))
03745 PG_RETURN_NULL();
03746
03747 aclresult = pg_namespace_aclcheck(schemaoid, roleid, mode);
03748
03749 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
03750 }
03751
03752
03753
03754
03755
03756
03757 Datum
03758 has_schema_privilege_id_name(PG_FUNCTION_ARGS)
03759 {
03760 Oid roleid = PG_GETARG_OID(0);
03761 text *schemaname = PG_GETARG_TEXT_P(1);
03762 text *priv_type_text = PG_GETARG_TEXT_P(2);
03763 Oid schemaoid;
03764 AclMode mode;
03765 AclResult aclresult;
03766
03767 schemaoid = convert_schema_name(schemaname);
03768 mode = convert_schema_priv_string(priv_type_text);
03769
03770 aclresult = pg_namespace_aclcheck(schemaoid, roleid, mode);
03771
03772 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
03773 }
03774
03775
03776
03777
03778
03779
03780 Datum
03781 has_schema_privilege_id_id(PG_FUNCTION_ARGS)
03782 {
03783 Oid roleid = PG_GETARG_OID(0);
03784 Oid schemaoid = PG_GETARG_OID(1);
03785 text *priv_type_text = PG_GETARG_TEXT_P(2);
03786 AclMode mode;
03787 AclResult aclresult;
03788
03789 mode = convert_schema_priv_string(priv_type_text);
03790
03791 if (!SearchSysCacheExists1(NAMESPACEOID, ObjectIdGetDatum(schemaoid)))
03792 PG_RETURN_NULL();
03793
03794 aclresult = pg_namespace_aclcheck(schemaoid, roleid, mode);
03795
03796 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
03797 }
03798
03799
03800
03801
03802
03803
03804
03805
03806 static Oid
03807 convert_schema_name(text *schemaname)
03808 {
03809 char *nspname = text_to_cstring(schemaname);
03810
03811 return get_namespace_oid(nspname, false);
03812 }
03813
03814
03815
03816
03817
03818 static AclMode
03819 convert_schema_priv_string(text *priv_type_text)
03820 {
03821 static const priv_map schema_priv_map[] = {
03822 {"CREATE", ACL_CREATE},
03823 {"CREATE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_CREATE)},
03824 {"USAGE", ACL_USAGE},
03825 {"USAGE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_USAGE)},
03826 {NULL, 0}
03827 };
03828
03829 return convert_any_priv_string(priv_type_text, schema_priv_map);
03830 }
03831
03832
03833
03834
03835
03836
03837
03838
03839
03840
03841
03842
03843
03844
03845
03846
03847
03848 Datum
03849 has_server_privilege_name_name(PG_FUNCTION_ARGS)
03850 {
03851 Name username = PG_GETARG_NAME(0);
03852 text *servername = PG_GETARG_TEXT_P(1);
03853 text *priv_type_text = PG_GETARG_TEXT_P(2);
03854 Oid roleid;
03855 Oid serverid;
03856 AclMode mode;
03857 AclResult aclresult;
03858
03859 roleid = get_role_oid_or_public(NameStr(*username));
03860 serverid = convert_server_name(servername);
03861 mode = convert_server_priv_string(priv_type_text);
03862
03863 aclresult = pg_foreign_server_aclcheck(serverid, roleid, mode);
03864
03865 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
03866 }
03867
03868
03869
03870
03871
03872
03873
03874 Datum
03875 has_server_privilege_name(PG_FUNCTION_ARGS)
03876 {
03877 text *servername = PG_GETARG_TEXT_P(0);
03878 text *priv_type_text = PG_GETARG_TEXT_P(1);
03879 Oid roleid;
03880 Oid serverid;
03881 AclMode mode;
03882 AclResult aclresult;
03883
03884 roleid = GetUserId();
03885 serverid = convert_server_name(servername);
03886 mode = convert_server_priv_string(priv_type_text);
03887
03888 aclresult = pg_foreign_server_aclcheck(serverid, roleid, mode);
03889
03890 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
03891 }
03892
03893
03894
03895
03896
03897
03898 Datum
03899 has_server_privilege_name_id(PG_FUNCTION_ARGS)
03900 {
03901 Name username = PG_GETARG_NAME(0);
03902 Oid serverid = PG_GETARG_OID(1);
03903 text *priv_type_text = PG_GETARG_TEXT_P(2);
03904 Oid roleid;
03905 AclMode mode;
03906 AclResult aclresult;
03907
03908 roleid = get_role_oid_or_public(NameStr(*username));
03909 mode = convert_server_priv_string(priv_type_text);
03910
03911 aclresult = pg_foreign_server_aclcheck(serverid, roleid, mode);
03912
03913 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
03914 }
03915
03916
03917
03918
03919
03920
03921
03922 Datum
03923 has_server_privilege_id(PG_FUNCTION_ARGS)
03924 {
03925 Oid serverid = PG_GETARG_OID(0);
03926 text *priv_type_text = PG_GETARG_TEXT_P(1);
03927 Oid roleid;
03928 AclMode mode;
03929 AclResult aclresult;
03930
03931 roleid = GetUserId();
03932 mode = convert_server_priv_string(priv_type_text);
03933
03934 aclresult = pg_foreign_server_aclcheck(serverid, roleid, mode);
03935
03936 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
03937 }
03938
03939
03940
03941
03942
03943
03944 Datum
03945 has_server_privilege_id_name(PG_FUNCTION_ARGS)
03946 {
03947 Oid roleid = PG_GETARG_OID(0);
03948 text *servername = PG_GETARG_TEXT_P(1);
03949 text *priv_type_text = PG_GETARG_TEXT_P(2);
03950 Oid serverid;
03951 AclMode mode;
03952 AclResult aclresult;
03953
03954 serverid = convert_server_name(servername);
03955 mode = convert_server_priv_string(priv_type_text);
03956
03957 aclresult = pg_foreign_server_aclcheck(serverid, roleid, mode);
03958
03959 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
03960 }
03961
03962
03963
03964
03965
03966
03967 Datum
03968 has_server_privilege_id_id(PG_FUNCTION_ARGS)
03969 {
03970 Oid roleid = PG_GETARG_OID(0);
03971 Oid serverid = PG_GETARG_OID(1);
03972 text *priv_type_text = PG_GETARG_TEXT_P(2);
03973 AclMode mode;
03974 AclResult aclresult;
03975
03976 mode = convert_server_priv_string(priv_type_text);
03977
03978 aclresult = pg_foreign_server_aclcheck(serverid, roleid, mode);
03979
03980 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
03981 }
03982
03983
03984
03985
03986
03987
03988
03989
03990 static Oid
03991 convert_server_name(text *servername)
03992 {
03993 char *serverstr = text_to_cstring(servername);
03994
03995 return get_foreign_server_oid(serverstr, false);
03996 }
03997
03998
03999
04000
04001
04002 static AclMode
04003 convert_server_priv_string(text *priv_type_text)
04004 {
04005 static const priv_map server_priv_map[] = {
04006 {"USAGE", ACL_USAGE},
04007 {"USAGE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_USAGE)},
04008 {NULL, 0}
04009 };
04010
04011 return convert_any_priv_string(priv_type_text, server_priv_map);
04012 }
04013
04014
04015
04016
04017
04018
04019
04020
04021
04022
04023
04024
04025
04026
04027
04028
04029
04030 Datum
04031 has_tablespace_privilege_name_name(PG_FUNCTION_ARGS)
04032 {
04033 Name username = PG_GETARG_NAME(0);
04034 text *tablespacename = PG_GETARG_TEXT_P(1);
04035 text *priv_type_text = PG_GETARG_TEXT_P(2);
04036 Oid roleid;
04037 Oid tablespaceoid;
04038 AclMode mode;
04039 AclResult aclresult;
04040
04041 roleid = get_role_oid_or_public(NameStr(*username));
04042 tablespaceoid = convert_tablespace_name(tablespacename);
04043 mode = convert_tablespace_priv_string(priv_type_text);
04044
04045 aclresult = pg_tablespace_aclcheck(tablespaceoid, roleid, mode);
04046
04047 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
04048 }
04049
04050
04051
04052
04053
04054
04055
04056 Datum
04057 has_tablespace_privilege_name(PG_FUNCTION_ARGS)
04058 {
04059 text *tablespacename = PG_GETARG_TEXT_P(0);
04060 text *priv_type_text = PG_GETARG_TEXT_P(1);
04061 Oid roleid;
04062 Oid tablespaceoid;
04063 AclMode mode;
04064 AclResult aclresult;
04065
04066 roleid = GetUserId();
04067 tablespaceoid = convert_tablespace_name(tablespacename);
04068 mode = convert_tablespace_priv_string(priv_type_text);
04069
04070 aclresult = pg_tablespace_aclcheck(tablespaceoid, roleid, mode);
04071
04072 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
04073 }
04074
04075
04076
04077
04078
04079
04080 Datum
04081 has_tablespace_privilege_name_id(PG_FUNCTION_ARGS)
04082 {
04083 Name username = PG_GETARG_NAME(0);
04084 Oid tablespaceoid = PG_GETARG_OID(1);
04085 text *priv_type_text = PG_GETARG_TEXT_P(2);
04086 Oid roleid;
04087 AclMode mode;
04088 AclResult aclresult;
04089
04090 roleid = get_role_oid_or_public(NameStr(*username));
04091 mode = convert_tablespace_priv_string(priv_type_text);
04092
04093 aclresult = pg_tablespace_aclcheck(tablespaceoid, roleid, mode);
04094
04095 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
04096 }
04097
04098
04099
04100
04101
04102
04103
04104 Datum
04105 has_tablespace_privilege_id(PG_FUNCTION_ARGS)
04106 {
04107 Oid tablespaceoid = PG_GETARG_OID(0);
04108 text *priv_type_text = PG_GETARG_TEXT_P(1);
04109 Oid roleid;
04110 AclMode mode;
04111 AclResult aclresult;
04112
04113 roleid = GetUserId();
04114 mode = convert_tablespace_priv_string(priv_type_text);
04115
04116 aclresult = pg_tablespace_aclcheck(tablespaceoid, roleid, mode);
04117
04118 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
04119 }
04120
04121
04122
04123
04124
04125
04126 Datum
04127 has_tablespace_privilege_id_name(PG_FUNCTION_ARGS)
04128 {
04129 Oid roleid = PG_GETARG_OID(0);
04130 text *tablespacename = PG_GETARG_TEXT_P(1);
04131 text *priv_type_text = PG_GETARG_TEXT_P(2);
04132 Oid tablespaceoid;
04133 AclMode mode;
04134 AclResult aclresult;
04135
04136 tablespaceoid = convert_tablespace_name(tablespacename);
04137 mode = convert_tablespace_priv_string(priv_type_text);
04138
04139 aclresult = pg_tablespace_aclcheck(tablespaceoid, roleid, mode);
04140
04141 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
04142 }
04143
04144
04145
04146
04147
04148
04149 Datum
04150 has_tablespace_privilege_id_id(PG_FUNCTION_ARGS)
04151 {
04152 Oid roleid = PG_GETARG_OID(0);
04153 Oid tablespaceoid = PG_GETARG_OID(1);
04154 text *priv_type_text = PG_GETARG_TEXT_P(2);
04155 AclMode mode;
04156 AclResult aclresult;
04157
04158 mode = convert_tablespace_priv_string(priv_type_text);
04159
04160 aclresult = pg_tablespace_aclcheck(tablespaceoid, roleid, mode);
04161
04162 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
04163 }
04164
04165
04166
04167
04168
04169
04170
04171
04172 static Oid
04173 convert_tablespace_name(text *tablespacename)
04174 {
04175 char *spcname = text_to_cstring(tablespacename);
04176
04177 return get_tablespace_oid(spcname, false);
04178 }
04179
04180
04181
04182
04183
04184 static AclMode
04185 convert_tablespace_priv_string(text *priv_type_text)
04186 {
04187 static const priv_map tablespace_priv_map[] = {
04188 {"CREATE", ACL_CREATE},
04189 {"CREATE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_CREATE)},
04190 {NULL, 0}
04191 };
04192
04193 return convert_any_priv_string(priv_type_text, tablespace_priv_map);
04194 }
04195
04196
04197
04198
04199
04200
04201
04202
04203
04204
04205
04206
04207
04208
04209
04210
04211 Datum
04212 has_type_privilege_name_name(PG_FUNCTION_ARGS)
04213 {
04214 Name username = PG_GETARG_NAME(0);
04215 text *typename = PG_GETARG_TEXT_P(1);
04216 text *priv_type_text = PG_GETARG_TEXT_P(2);
04217 Oid roleid;
04218 Oid typeoid;
04219 AclMode mode;
04220 AclResult aclresult;
04221
04222 roleid = get_role_oid_or_public(NameStr(*username));
04223 typeoid = convert_type_name(typename);
04224 mode = convert_type_priv_string(priv_type_text);
04225
04226 aclresult = pg_type_aclcheck(typeoid, roleid, mode);
04227
04228 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
04229 }
04230
04231
04232
04233
04234
04235
04236
04237 Datum
04238 has_type_privilege_name(PG_FUNCTION_ARGS)
04239 {
04240 text *typename = PG_GETARG_TEXT_P(0);
04241 text *priv_type_text = PG_GETARG_TEXT_P(1);
04242 Oid roleid;
04243 Oid typeoid;
04244 AclMode mode;
04245 AclResult aclresult;
04246
04247 roleid = GetUserId();
04248 typeoid = convert_type_name(typename);
04249 mode = convert_type_priv_string(priv_type_text);
04250
04251 aclresult = pg_type_aclcheck(typeoid, roleid, mode);
04252
04253 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
04254 }
04255
04256
04257
04258
04259
04260
04261 Datum
04262 has_type_privilege_name_id(PG_FUNCTION_ARGS)
04263 {
04264 Name username = PG_GETARG_NAME(0);
04265 Oid typeoid = PG_GETARG_OID(1);
04266 text *priv_type_text = PG_GETARG_TEXT_P(2);
04267 Oid roleid;
04268 AclMode mode;
04269 AclResult aclresult;
04270
04271 roleid = get_role_oid_or_public(NameStr(*username));
04272 mode = convert_type_priv_string(priv_type_text);
04273
04274 if (!SearchSysCacheExists1(TYPEOID, ObjectIdGetDatum(typeoid)))
04275 PG_RETURN_NULL();
04276
04277 aclresult = pg_type_aclcheck(typeoid, roleid, mode);
04278
04279 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
04280 }
04281
04282
04283
04284
04285
04286
04287
04288 Datum
04289 has_type_privilege_id(PG_FUNCTION_ARGS)
04290 {
04291 Oid typeoid = PG_GETARG_OID(0);
04292 text *priv_type_text = PG_GETARG_TEXT_P(1);
04293 Oid roleid;
04294 AclMode mode;
04295 AclResult aclresult;
04296
04297 roleid = GetUserId();
04298 mode = convert_type_priv_string(priv_type_text);
04299
04300 if (!SearchSysCacheExists1(TYPEOID, ObjectIdGetDatum(typeoid)))
04301 PG_RETURN_NULL();
04302
04303 aclresult = pg_type_aclcheck(typeoid, roleid, mode);
04304
04305 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
04306 }
04307
04308
04309
04310
04311
04312
04313 Datum
04314 has_type_privilege_id_name(PG_FUNCTION_ARGS)
04315 {
04316 Oid roleid = PG_GETARG_OID(0);
04317 text *typename = PG_GETARG_TEXT_P(1);
04318 text *priv_type_text = PG_GETARG_TEXT_P(2);
04319 Oid typeoid;
04320 AclMode mode;
04321 AclResult aclresult;
04322
04323 typeoid = convert_type_name(typename);
04324 mode = convert_type_priv_string(priv_type_text);
04325
04326 aclresult = pg_type_aclcheck(typeoid, roleid, mode);
04327
04328 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
04329 }
04330
04331
04332
04333
04334
04335
04336 Datum
04337 has_type_privilege_id_id(PG_FUNCTION_ARGS)
04338 {
04339 Oid roleid = PG_GETARG_OID(0);
04340 Oid typeoid = PG_GETARG_OID(1);
04341 text *priv_type_text = PG_GETARG_TEXT_P(2);
04342 AclMode mode;
04343 AclResult aclresult;
04344
04345 mode = convert_type_priv_string(priv_type_text);
04346
04347 if (!SearchSysCacheExists1(TYPEOID, ObjectIdGetDatum(typeoid)))
04348 PG_RETURN_NULL();
04349
04350 aclresult = pg_type_aclcheck(typeoid, roleid, mode);
04351
04352 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
04353 }
04354
04355
04356
04357
04358
04359
04360
04361
04362 static Oid
04363 convert_type_name(text *typename)
04364 {
04365 char *typname = text_to_cstring(typename);
04366 Oid oid;
04367
04368 oid = DatumGetObjectId(DirectFunctionCall1(regtypein,
04369 CStringGetDatum(typname)));
04370
04371 if (!OidIsValid(oid))
04372 ereport(ERROR,
04373 (errcode(ERRCODE_UNDEFINED_OBJECT),
04374 errmsg("type \"%s\" does not exist", typname)));
04375
04376 return oid;
04377 }
04378
04379
04380
04381
04382
04383 static AclMode
04384 convert_type_priv_string(text *priv_type_text)
04385 {
04386 static const priv_map type_priv_map[] = {
04387 {"USAGE", ACL_USAGE},
04388 {"USAGE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_USAGE)},
04389 {NULL, 0}
04390 };
04391
04392 return convert_any_priv_string(priv_type_text, type_priv_map);
04393 }
04394
04395
04396
04397
04398
04399
04400
04401
04402
04403
04404
04405
04406
04407
04408
04409
04410
04411 Datum
04412 pg_has_role_name_name(PG_FUNCTION_ARGS)
04413 {
04414 Name username = PG_GETARG_NAME(0);
04415 Name rolename = PG_GETARG_NAME(1);
04416 text *priv_type_text = PG_GETARG_TEXT_P(2);
04417 Oid roleid;
04418 Oid roleoid;
04419 AclMode mode;
04420 AclResult aclresult;
04421
04422 roleid = get_role_oid(NameStr(*username), false);
04423 roleoid = get_role_oid(NameStr(*rolename), false);
04424 mode = convert_role_priv_string(priv_type_text);
04425
04426 aclresult = pg_role_aclcheck(roleoid, roleid, mode);
04427
04428 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
04429 }
04430
04431
04432
04433
04434
04435
04436
04437 Datum
04438 pg_has_role_name(PG_FUNCTION_ARGS)
04439 {
04440 Name rolename = PG_GETARG_NAME(0);
04441 text *priv_type_text = PG_GETARG_TEXT_P(1);
04442 Oid roleid;
04443 Oid roleoid;
04444 AclMode mode;
04445 AclResult aclresult;
04446
04447 roleid = GetUserId();
04448 roleoid = get_role_oid(NameStr(*rolename), false);
04449 mode = convert_role_priv_string(priv_type_text);
04450
04451 aclresult = pg_role_aclcheck(roleoid, roleid, mode);
04452
04453 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
04454 }
04455
04456
04457
04458
04459
04460
04461 Datum
04462 pg_has_role_name_id(PG_FUNCTION_ARGS)
04463 {
04464 Name username = PG_GETARG_NAME(0);
04465 Oid roleoid = PG_GETARG_OID(1);
04466 text *priv_type_text = PG_GETARG_TEXT_P(2);
04467 Oid roleid;
04468 AclMode mode;
04469 AclResult aclresult;
04470
04471 roleid = get_role_oid(NameStr(*username), false);
04472 mode = convert_role_priv_string(priv_type_text);
04473
04474 aclresult = pg_role_aclcheck(roleoid, roleid, mode);
04475
04476 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
04477 }
04478
04479
04480
04481
04482
04483
04484
04485 Datum
04486 pg_has_role_id(PG_FUNCTION_ARGS)
04487 {
04488 Oid roleoid = PG_GETARG_OID(0);
04489 text *priv_type_text = PG_GETARG_TEXT_P(1);
04490 Oid roleid;
04491 AclMode mode;
04492 AclResult aclresult;
04493
04494 roleid = GetUserId();
04495 mode = convert_role_priv_string(priv_type_text);
04496
04497 aclresult = pg_role_aclcheck(roleoid, roleid, mode);
04498
04499 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
04500 }
04501
04502
04503
04504
04505
04506
04507 Datum
04508 pg_has_role_id_name(PG_FUNCTION_ARGS)
04509 {
04510 Oid roleid = PG_GETARG_OID(0);
04511 Name rolename = PG_GETARG_NAME(1);
04512 text *priv_type_text = PG_GETARG_TEXT_P(2);
04513 Oid roleoid;
04514 AclMode mode;
04515 AclResult aclresult;
04516
04517 roleoid = get_role_oid(NameStr(*rolename), false);
04518 mode = convert_role_priv_string(priv_type_text);
04519
04520 aclresult = pg_role_aclcheck(roleoid, roleid, mode);
04521
04522 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
04523 }
04524
04525
04526
04527
04528
04529
04530 Datum
04531 pg_has_role_id_id(PG_FUNCTION_ARGS)
04532 {
04533 Oid roleid = PG_GETARG_OID(0);
04534 Oid roleoid = PG_GETARG_OID(1);
04535 text *priv_type_text = PG_GETARG_TEXT_P(2);
04536 AclMode mode;
04537 AclResult aclresult;
04538
04539 mode = convert_role_priv_string(priv_type_text);
04540
04541 aclresult = pg_role_aclcheck(roleoid, roleid, mode);
04542
04543 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
04544 }
04545
04546
04547
04548
04549
04550
04551
04552
04553
04554
04555
04556
04557
04558
04559
04560 static AclMode
04561 convert_role_priv_string(text *priv_type_text)
04562 {
04563 static const priv_map role_priv_map[] = {
04564 {"USAGE", ACL_USAGE},
04565 {"MEMBER", ACL_CREATE},
04566 {"USAGE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_CREATE)},
04567 {"USAGE WITH ADMIN OPTION", ACL_GRANT_OPTION_FOR(ACL_CREATE)},
04568 {"MEMBER WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_CREATE)},
04569 {"MEMBER WITH ADMIN OPTION", ACL_GRANT_OPTION_FOR(ACL_CREATE)},
04570 {NULL, 0}
04571 };
04572
04573 return convert_any_priv_string(priv_type_text, role_priv_map);
04574 }
04575
04576
04577
04578
04579
04580 static AclResult
04581 pg_role_aclcheck(Oid role_oid, Oid roleid, AclMode mode)
04582 {
04583 if (mode & ACL_GRANT_OPTION_FOR(ACL_CREATE))
04584 {
04585 if (is_admin_of_role(roleid, role_oid))
04586 return ACLCHECK_OK;
04587 }
04588 if (mode & ACL_CREATE)
04589 {
04590 if (is_member_of_role(roleid, role_oid))
04591 return ACLCHECK_OK;
04592 }
04593 if (mode & ACL_USAGE)
04594 {
04595 if (has_privs_of_role(roleid, role_oid))
04596 return ACLCHECK_OK;
04597 }
04598 return ACLCHECK_NO_PRIV;
04599 }
04600
04601
04602
04603
04604
04605 void
04606 initialize_acl(void)
04607 {
04608 if (!IsBootstrapProcessingMode())
04609 {
04610
04611
04612
04613
04614 CacheRegisterSyscacheCallback(AUTHMEMROLEMEM,
04615 RoleMembershipCacheCallback,
04616 (Datum) 0);
04617 }
04618 }
04619
04620
04621
04622
04623
04624 static void
04625 RoleMembershipCacheCallback(Datum arg, int cacheid, uint32 hashvalue)
04626 {
04627
04628 cached_privs_role = InvalidOid;
04629 cached_member_role = InvalidOid;
04630 }
04631
04632
04633
04634 static bool
04635 has_rolinherit(Oid roleid)
04636 {
04637 bool result = false;
04638 HeapTuple utup;
04639
04640 utup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
04641 if (HeapTupleIsValid(utup))
04642 {
04643 result = ((Form_pg_authid) GETSTRUCT(utup))->rolinherit;
04644 ReleaseSysCache(utup);
04645 }
04646 return result;
04647 }
04648
04649
04650
04651
04652
04653
04654
04655
04656
04657
04658
04659
04660
04661
04662
04663
04664 static List *
04665 roles_has_privs_of(Oid roleid)
04666 {
04667 List *roles_list;
04668 ListCell *l;
04669 List *new_cached_privs_roles;
04670 MemoryContext oldctx;
04671
04672
04673 if (OidIsValid(cached_privs_role) && cached_privs_role == roleid)
04674 return cached_privs_roles;
04675
04676
04677
04678
04679
04680
04681
04682
04683
04684
04685
04686
04687 roles_list = list_make1_oid(roleid);
04688
04689 foreach(l, roles_list)
04690 {
04691 Oid memberid = lfirst_oid(l);
04692 CatCList *memlist;
04693 int i;
04694
04695
04696 if (!has_rolinherit(memberid))
04697 continue;
04698
04699
04700 memlist = SearchSysCacheList1(AUTHMEMMEMROLE,
04701 ObjectIdGetDatum(memberid));
04702 for (i = 0; i < memlist->n_members; i++)
04703 {
04704 HeapTuple tup = &memlist->members[i]->tuple;
04705 Oid otherid = ((Form_pg_auth_members) GETSTRUCT(tup))->roleid;
04706
04707
04708
04709
04710
04711
04712 roles_list = list_append_unique_oid(roles_list, otherid);
04713 }
04714 ReleaseSysCacheList(memlist);
04715 }
04716
04717
04718
04719
04720 oldctx = MemoryContextSwitchTo(TopMemoryContext);
04721 new_cached_privs_roles = list_copy(roles_list);
04722 MemoryContextSwitchTo(oldctx);
04723 list_free(roles_list);
04724
04725
04726
04727
04728 cached_privs_role = InvalidOid;
04729 list_free(cached_privs_roles);
04730 cached_privs_roles = new_cached_privs_roles;
04731 cached_privs_role = roleid;
04732
04733
04734 return cached_privs_roles;
04735 }
04736
04737
04738
04739
04740
04741
04742
04743
04744
04745
04746
04747 static List *
04748 roles_is_member_of(Oid roleid)
04749 {
04750 List *roles_list;
04751 ListCell *l;
04752 List *new_cached_membership_roles;
04753 MemoryContext oldctx;
04754
04755
04756 if (OidIsValid(cached_member_role) && cached_member_role == roleid)
04757 return cached_membership_roles;
04758
04759
04760
04761
04762
04763
04764
04765
04766
04767
04768
04769
04770 roles_list = list_make1_oid(roleid);
04771
04772 foreach(l, roles_list)
04773 {
04774 Oid memberid = lfirst_oid(l);
04775 CatCList *memlist;
04776 int i;
04777
04778
04779 memlist = SearchSysCacheList1(AUTHMEMMEMROLE,
04780 ObjectIdGetDatum(memberid));
04781 for (i = 0; i < memlist->n_members; i++)
04782 {
04783 HeapTuple tup = &memlist->members[i]->tuple;
04784 Oid otherid = ((Form_pg_auth_members) GETSTRUCT(tup))->roleid;
04785
04786
04787
04788
04789
04790
04791 roles_list = list_append_unique_oid(roles_list, otherid);
04792 }
04793 ReleaseSysCacheList(memlist);
04794 }
04795
04796
04797
04798
04799 oldctx = MemoryContextSwitchTo(TopMemoryContext);
04800 new_cached_membership_roles = list_copy(roles_list);
04801 MemoryContextSwitchTo(oldctx);
04802 list_free(roles_list);
04803
04804
04805
04806
04807 cached_member_role = InvalidOid;
04808 list_free(cached_membership_roles);
04809 cached_membership_roles = new_cached_membership_roles;
04810 cached_member_role = roleid;
04811
04812
04813 return cached_membership_roles;
04814 }
04815
04816
04817
04818
04819
04820
04821
04822
04823
04824 bool
04825 has_privs_of_role(Oid member, Oid role)
04826 {
04827
04828 if (member == role)
04829 return true;
04830
04831
04832 if (superuser_arg(member))
04833 return true;
04834
04835
04836
04837
04838
04839 return list_member_oid(roles_has_privs_of(member), role);
04840 }
04841
04842
04843
04844
04845
04846
04847
04848 bool
04849 is_member_of_role(Oid member, Oid role)
04850 {
04851
04852 if (member == role)
04853 return true;
04854
04855
04856 if (superuser_arg(member))
04857 return true;
04858
04859
04860
04861
04862
04863 return list_member_oid(roles_is_member_of(member), role);
04864 }
04865
04866
04867
04868
04869
04870 void
04871 check_is_member_of_role(Oid member, Oid role)
04872 {
04873 if (!is_member_of_role(member, role))
04874 ereport(ERROR,
04875 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
04876 errmsg("must be member of role \"%s\"",
04877 GetUserNameFromId(role))));
04878 }
04879
04880
04881
04882
04883
04884
04885
04886 bool
04887 is_member_of_role_nosuper(Oid member, Oid role)
04888 {
04889
04890 if (member == role)
04891 return true;
04892
04893
04894
04895
04896
04897 return list_member_oid(roles_is_member_of(member), role);
04898 }
04899
04900
04901
04902
04903
04904
04905
04906
04907
04908 bool
04909 is_admin_of_role(Oid member, Oid role)
04910 {
04911 bool result = false;
04912 List *roles_list;
04913 ListCell *l;
04914
04915
04916 if (member == role)
04917 return true;
04918
04919
04920 if (superuser_arg(member))
04921 return true;
04922
04923
04924
04925
04926
04927
04928 roles_list = list_make1_oid(member);
04929
04930 foreach(l, roles_list)
04931 {
04932 Oid memberid = lfirst_oid(l);
04933 CatCList *memlist;
04934 int i;
04935
04936
04937 memlist = SearchSysCacheList1(AUTHMEMMEMROLE,
04938 ObjectIdGetDatum(memberid));
04939 for (i = 0; i < memlist->n_members; i++)
04940 {
04941 HeapTuple tup = &memlist->members[i]->tuple;
04942 Oid otherid = ((Form_pg_auth_members) GETSTRUCT(tup))->roleid;
04943
04944 if (otherid == role &&
04945 ((Form_pg_auth_members) GETSTRUCT(tup))->admin_option)
04946 {
04947
04948 result = true;
04949 break;
04950 }
04951
04952 roles_list = list_append_unique_oid(roles_list, otherid);
04953 }
04954 ReleaseSysCacheList(memlist);
04955 if (result)
04956 break;
04957 }
04958
04959 list_free(roles_list);
04960
04961 return result;
04962 }
04963
04964
04965
04966 static int
04967 count_one_bits(AclMode mask)
04968 {
04969 int nbits = 0;
04970
04971
04972 while (mask)
04973 {
04974 if (mask & 1)
04975 nbits++;
04976 mask >>= 1;
04977 }
04978 return nbits;
04979 }
04980
04981
04982
04983
04984
04985
04986
04987
04988
04989
04990
04991
04992
04993
04994
04995
04996
04997
04998
04999
05000
05001
05002
05003
05004
05005
05006 void
05007 select_best_grantor(Oid roleId, AclMode privileges,
05008 const Acl *acl, Oid ownerId,
05009 Oid *grantorId, AclMode *grantOptions)
05010 {
05011 AclMode needed_goptions = ACL_GRANT_OPTION_FOR(privileges);
05012 List *roles_list;
05013 int nrights;
05014 ListCell *l;
05015
05016
05017
05018
05019
05020
05021
05022 if (roleId == ownerId || superuser_arg(roleId))
05023 {
05024 *grantorId = ownerId;
05025 *grantOptions = needed_goptions;
05026 return;
05027 }
05028
05029
05030
05031
05032
05033
05034
05035 roles_list = roles_has_privs_of(roleId);
05036
05037
05038 *grantorId = roleId;
05039 *grantOptions = ACL_NO_RIGHTS;
05040 nrights = 0;
05041
05042 foreach(l, roles_list)
05043 {
05044 Oid otherrole = lfirst_oid(l);
05045 AclMode otherprivs;
05046
05047 otherprivs = aclmask_direct(acl, otherrole, ownerId,
05048 needed_goptions, ACLMASK_ALL);
05049 if (otherprivs == needed_goptions)
05050 {
05051
05052 *grantorId = otherrole;
05053 *grantOptions = otherprivs;
05054 return;
05055 }
05056
05057
05058
05059
05060
05061 if (otherprivs != ACL_NO_RIGHTS)
05062 {
05063 int nnewrights = count_one_bits(otherprivs);
05064
05065 if (nnewrights > nrights)
05066 {
05067 *grantorId = otherrole;
05068 *grantOptions = otherprivs;
05069 nrights = nnewrights;
05070 }
05071 }
05072 }
05073 }
05074
05075
05076
05077
05078
05079
05080
05081 Oid
05082 get_role_oid(const char *rolname, bool missing_ok)
05083 {
05084 Oid oid;
05085
05086 oid = GetSysCacheOid1(AUTHNAME, CStringGetDatum(rolname));
05087 if (!OidIsValid(oid) && !missing_ok)
05088 ereport(ERROR,
05089 (errcode(ERRCODE_UNDEFINED_OBJECT),
05090 errmsg("role \"%s\" does not exist", rolname)));
05091 return oid;
05092 }
05093
05094
05095
05096
05097
05098 static Oid
05099 get_role_oid_or_public(const char *rolname)
05100 {
05101 if (strcmp(rolname, "public") == 0)
05102 return ACL_ID_PUBLIC;
05103
05104 return get_role_oid(rolname, false);
05105 }