Skip to content

Commit 8a2922d

Browse files
committed
Represent grant options in the information schema.
1 parent 65fb311 commit 8a2922d

File tree

4 files changed

+139
-38
lines changed

4 files changed

+139
-38
lines changed

src/backend/catalog/information_schema.sql

Lines changed: 29 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
*
55
* Copyright 2002, PostgreSQL Global Development Group
66
*
7-
* $Id: information_schema.sql,v 1.7 2003/06/05 16:08:47 petere Exp $
7+
* $Id: information_schema.sql,v 1.8 2003/06/11 09:23:55 petere Exp $
88
*/
99

1010

@@ -604,7 +604,7 @@ GRANT SELECT ON referential_constraints TO PUBLIC;
604604
*/
605605

606606
CREATE VIEW routine_privileges AS
607-
SELECT CAST(u_owner.usename AS sql_identifier) AS grantor,
607+
SELECT CAST(u_grantor.usename AS sql_identifier) AS grantor,
608608
CAST(u_grantee.usename AS sql_identifier) AS grantee,
609609
CAST(current_database() AS sql_identifier) AS specific_catalog,
610610
CAST(n.nspname AS sql_identifier) AS specific_schema,
@@ -613,17 +613,22 @@ CREATE VIEW routine_privileges AS
613613
CAST(n.nspname AS sql_identifier) AS routine_schema,
614614
CAST(p.proname AS sql_identifier) AS routine_name,
615615
CAST('EXECUTE' AS character_data) AS privilege_type,
616-
CAST('NO' AS character_data) AS is_grantable
616+
CAST(
617+
CASE WHEN aclcontains(p.proacl,
618+
makeaclitem(u_grantee.usesysid, 0, u_grantor.usesysid, 'EXECUTE', true))
619+
THEN 'YES' ELSE 'NO' END AS character_data) AS is_grantable
617620

618-
FROM pg_user u_owner,
619-
pg_user u_grantee,
621+
FROM pg_proc p,
620622
pg_namespace n,
621-
pg_proc p
623+
pg_user u_grantor,
624+
(SELECT usesysid, usename FROM pg_user UNION SELECT 0, 'PUBLIC') AS u_grantee
622625

623-
WHERE u_owner.usesysid = p.proowner
624-
AND p.pronamespace = n.oid
625-
AND has_function_privilege(u_grantee.usename, p.oid, 'EXECUTE')
626-
AND (u_owner.usename = current_user OR u_grantee.usename = current_user);
626+
WHERE p.pronamespace = n.oid
627+
AND aclcontains(p.proacl,
628+
makeaclitem(u_grantee.usesysid, 0, u_grantor.usesysid, 'EXECUTE', false))
629+
AND (u_grantor.usename = current_user
630+
OR u_grantee.usename = current_user
631+
OR u_grantee.usename = 'PUBLIC');
627632

628633
GRANT SELECT ON routine_privileges TO PUBLIC;
629634

@@ -940,27 +945,31 @@ GRANT SELECT ON table_constraints TO PUBLIC;
940945
*/
941946

942947
CREATE VIEW table_privileges AS
943-
SELECT CAST(u_owner.usename AS sql_identifier) AS grantor,
948+
SELECT CAST(u_grantor.usename AS sql_identifier) AS grantor,
944949
CAST(u_grantee.usename AS sql_identifier) AS grantee,
945950
CAST(current_database() AS sql_identifier) AS table_catalog,
946951
CAST(nc.nspname AS sql_identifier) AS table_schema,
947952
CAST(c.relname AS sql_identifier) AS table_name,
948953
CAST(pr.type AS character_data) AS privilege_type,
949-
CAST('NO' AS character_data) AS is_grantable,
954+
CAST(
955+
CASE WHEN aclcontains(c.relacl,
956+
makeaclitem(u_grantee.usesysid, 0, u_grantor.usesysid, pr.type, true))
957+
THEN 'YES' ELSE 'NO' END AS character_data) AS is_grantable,
950958
CAST('NO' AS character_data) AS with_hierarchy
951959

952-
FROM pg_user u_owner,
953-
pg_user u_grantee,
960+
FROM pg_class c,
954961
pg_namespace nc,
955-
pg_class c,
962+
pg_user u_grantor,
963+
(SELECT usesysid, usename FROM pg_user UNION SELECT 0, 'PUBLIC') AS u_grantee,
956964
(SELECT 'SELECT' UNION SELECT 'DELETE' UNION SELECT 'INSERT' UNION SELECT 'UPDATE'
957965
UNION SELECT 'REFERENCES' UNION SELECT 'TRIGGER') AS pr (type)
958966

959-
WHERE u_owner.usesysid = c.relowner
960-
AND c.relnamespace = nc.oid
961-
AND has_table_privilege(u_grantee.usename, c.oid, pr.type)
962-
963-
AND (u_owner.usename = current_user OR u_grantee.usename = current_user);
967+
WHERE c.relnamespace = nc.oid
968+
AND aclcontains(c.relacl,
969+
makeaclitem(u_grantee.usesysid, 0, u_grantor.usesysid, pr.type, false))
970+
AND (u_grantor.usename = current_user
971+
OR u_grantee.usename = current_user
972+
OR u_grantee.usename = 'PUBLIC');
964973

965974
GRANT SELECT ON table_privileges TO PUBLIC;
966975

src/backend/utils/adt/acl.c

Lines changed: 102 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/utils/adt/acl.c,v 1.87 2003/06/02 19:00:29 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/utils/adt/acl.c,v 1.88 2003/06/11 09:23:55 petere Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -32,12 +32,14 @@
3232

3333
static const char *getid(const char *s, char *n);
3434
static void putid(char *p, const char *s);
35-
static Acl *makeacl(int n);
35+
static Acl *allocacl(int n);
3636
static const char *aclparse(const char *s, AclItem *aip);
3737
static bool aclitemeq(const AclItem *a1, const AclItem *a2);
3838
static Acl *recursive_revoke(Acl *acl, AclId grantee,
3939
AclMode revoke_privs, DropBehavior behavior);
4040

41+
static AclMode convert_priv_string(text *priv_type_text);
42+
4143
static Oid convert_table_name(text *tablename);
4244
static AclMode convert_table_priv_string(text *priv_type_text);
4345
static Oid convert_database_name(text *databasename);
@@ -265,20 +267,20 @@ aclparse(const char *s, AclItem *aip)
265267
}
266268

267269
/*
268-
* makeacl
270+
* allocacl
269271
* Allocates storage for a new Acl with 'n' entries.
270272
*
271273
* RETURNS:
272274
* the new Acl
273275
*/
274276
static Acl *
275-
makeacl(int n)
277+
allocacl(int n)
276278
{
277279
Acl *new_acl;
278280
Size size;
279281

280282
if (n < 0)
281-
elog(ERROR, "makeacl: invalid size: %d", n);
283+
elog(ERROR, "allocacl: invalid size: %d", n);
282284
size = ACL_N_SIZE(n);
283285
new_acl = (Acl *) palloc0(size);
284286
new_acl->size = size;
@@ -471,7 +473,7 @@ acldefault(GrantObjectType objtype, AclId ownerid)
471473
break;
472474
}
473475

474-
acl = makeacl((world_default != ACL_NO_RIGHTS ? 1 : 0)
476+
acl = allocacl((world_default != ACL_NO_RIGHTS ? 1 : 0)
475477
+ (ownerid ? 1 : 0));
476478
aip = ACL_DAT(acl);
477479

@@ -513,10 +515,10 @@ aclinsert3(const Acl *old_acl, const AclItem *mod_aip, unsigned modechg, DropBeh
513515

514516
/* These checks for null input are probably dead code, but... */
515517
if (!old_acl || ACL_NUM(old_acl) < 1)
516-
old_acl = makeacl(1);
518+
old_acl = allocacl(1);
517519
if (!mod_aip)
518520
{
519-
new_acl = makeacl(ACL_NUM(old_acl));
521+
new_acl = allocacl(ACL_NUM(old_acl));
520522
memcpy((char *) new_acl, (char *) old_acl, ACL_SIZE(old_acl));
521523
return new_acl;
522524
}
@@ -536,7 +538,7 @@ aclinsert3(const Acl *old_acl, const AclItem *mod_aip, unsigned modechg, DropBeh
536538
if (aclitemeq(mod_aip, old_aip + dst))
537539
{
538540
/* found a match, so modify existing item */
539-
new_acl = makeacl(num);
541+
new_acl = allocacl(num);
540542
new_aip = ACL_DAT(new_acl);
541543
memcpy(new_acl, old_acl, ACL_SIZE(old_acl));
542544
break;
@@ -546,7 +548,7 @@ aclinsert3(const Acl *old_acl, const AclItem *mod_aip, unsigned modechg, DropBeh
546548
if (dst == num)
547549
{
548550
/* need to append a new item */
549-
new_acl = makeacl(num + 1);
551+
new_acl = allocacl(num + 1);
550552
new_aip = ACL_DAT(new_acl);
551553
memcpy(new_aip, old_aip, num * sizeof(AclItem));
552554

@@ -671,10 +673,10 @@ aclremove(PG_FUNCTION_ARGS)
671673

672674
/* These checks for null input should be dead code, but... */
673675
if (!old_acl || ACL_NUM(old_acl) < 1)
674-
old_acl = makeacl(1);
676+
old_acl = allocacl(1);
675677
if (!mod_aip)
676678
{
677-
new_acl = makeacl(ACL_NUM(old_acl));
679+
new_acl = allocacl(ACL_NUM(old_acl));
678680
memcpy((char *) new_acl, (char *) old_acl, ACL_SIZE(old_acl));
679681
PG_RETURN_ACL_P(new_acl);
680682
}
@@ -689,13 +691,13 @@ aclremove(PG_FUNCTION_ARGS)
689691
if (dst >= old_num)
690692
{
691693
/* Not found, so return copy of source ACL */
692-
new_acl = makeacl(old_num);
694+
new_acl = allocacl(old_num);
693695
memcpy((char *) new_acl, (char *) old_acl, ACL_SIZE(old_acl));
694696
}
695697
else
696698
{
697699
new_num = old_num - 1;
698-
new_acl = makeacl(new_num);
700+
new_acl = allocacl(new_num);
699701
new_aip = ACL_DAT(new_acl);
700702
if (dst == 0)
701703
{ /* start */
@@ -734,13 +736,97 @@ aclcontains(PG_FUNCTION_ARGS)
734736
aidat = ACL_DAT(acl);
735737
for (i = 0; i < num; ++i)
736738
{
737-
if (aip->ai_grantee == aidat[i].ai_grantee &&
738-
aip->ai_privs == aidat[i].ai_privs)
739+
if (aip->ai_grantee == aidat[i].ai_grantee
740+
&& ACLITEM_GET_IDTYPE(*aip) == ACLITEM_GET_IDTYPE(aidat[i])
741+
&& aip->ai_grantor == aidat[i].ai_grantor
742+
&& (ACLITEM_GET_PRIVS(*aip) & ACLITEM_GET_PRIVS(aidat[i])) == ACLITEM_GET_PRIVS(*aip)
743+
&& (ACLITEM_GET_GOPTIONS(*aip) & ACLITEM_GET_GOPTIONS(aidat[i])) == ACLITEM_GET_GOPTIONS(*aip))
739744
PG_RETURN_BOOL(true);
740745
}
741746
PG_RETURN_BOOL(false);
742747
}
743748

749+
Datum
750+
makeaclitem(PG_FUNCTION_ARGS)
751+
{
752+
int32 u_grantee = PG_GETARG_INT32(0);
753+
int32 g_grantee = PG_GETARG_INT32(1);
754+
int32 grantor = PG_GETARG_INT32(2);
755+
text *privtext = PG_GETARG_TEXT_P(3);
756+
bool goption = PG_GETARG_BOOL(4);
757+
AclItem *aclitem;
758+
AclMode priv;
759+
760+
priv = convert_priv_string(privtext);
761+
762+
aclitem = (AclItem *) palloc(sizeof(*aclitem));
763+
if (u_grantee == 0 && g_grantee == 0)
764+
{
765+
aclitem->ai_grantee = 0;
766+
ACLITEM_SET_IDTYPE(*aclitem, ACL_IDTYPE_WORLD);
767+
}
768+
else if (u_grantee != 0 && g_grantee != 0)
769+
{
770+
elog(ERROR, "cannot specify both user and group");
771+
}
772+
else if (u_grantee != 0)
773+
{
774+
aclitem->ai_grantee = u_grantee;
775+
ACLITEM_SET_IDTYPE(*aclitem, ACL_IDTYPE_UID);
776+
}
777+
else if (g_grantee != 0)
778+
{
779+
aclitem->ai_grantee = g_grantee;
780+
ACLITEM_SET_IDTYPE(*aclitem, ACL_IDTYPE_GID);
781+
}
782+
783+
aclitem->ai_grantor = grantor;
784+
ACLITEM_SET_PRIVS(*aclitem, priv);
785+
if (goption)
786+
ACLITEM_SET_GOPTIONS(*aclitem, priv);
787+
else
788+
ACLITEM_SET_GOPTIONS(*aclitem, ACL_NO_RIGHTS);
789+
790+
PG_RETURN_ACLITEM_P(aclitem);
791+
}
792+
793+
static AclMode
794+
convert_priv_string(text *priv_type_text)
795+
{
796+
char *priv_type;
797+
798+
priv_type = DatumGetCString(DirectFunctionCall1(textout,
799+
PointerGetDatum(priv_type_text)));
800+
801+
if (strcasecmp(priv_type, "SELECT") == 0)
802+
return ACL_SELECT;
803+
if (strcasecmp(priv_type, "INSERT") == 0)
804+
return ACL_INSERT;
805+
if (strcasecmp(priv_type, "UPDATE") == 0)
806+
return ACL_UPDATE;
807+
if (strcasecmp(priv_type, "DELETE") == 0)
808+
return ACL_DELETE;
809+
if (strcasecmp(priv_type, "RULE") == 0)
810+
return ACL_RULE;
811+
if (strcasecmp(priv_type, "REFERENCES") == 0)
812+
return ACL_REFERENCES;
813+
if (strcasecmp(priv_type, "TRIGGER") == 0)
814+
return ACL_TRIGGER;
815+
if (strcasecmp(priv_type, "EXECUTE") == 0)
816+
return ACL_EXECUTE;
817+
if (strcasecmp(priv_type, "USAGE") == 0)
818+
return ACL_USAGE;
819+
if (strcasecmp(priv_type, "CREATE") == 0)
820+
return ACL_CREATE;
821+
if (strcasecmp(priv_type, "TEMP") == 0)
822+
return ACL_CREATE_TEMP;
823+
if (strcasecmp(priv_type, "TEMPORARY") == 0)
824+
return ACL_CREATE_TEMP;
825+
826+
elog(ERROR, "invalid privilege type %s", priv_type);
827+
return ACL_NO_RIGHTS; /* keep compiler quiet */
828+
}
829+
744830

745831
/*
746832
* has_table_privilege variants

src/include/catalog/pg_proc.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $Id: pg_proc.h,v 1.302 2003/05/26 00:11:27 tgl Exp $
10+
* $Id: pg_proc.h,v 1.303 2003/06/11 09:23:55 petere Exp $
1111
*
1212
* NOTES
1313
* The script catalog/genbki.sh reads this file and generates .bki
@@ -1318,6 +1318,8 @@ DATA(insert OID = 1036 ( aclremove PGNSP PGUID 12 f f t f s 2 1034 "1034 10
13181318
DESCR("remove ACL item");
13191319
DATA(insert OID = 1037 ( aclcontains PGNSP PGUID 12 f f t f s 2 16 "1034 1033" aclcontains - _null_ ));
13201320
DESCR("does ACL contain item?");
1321+
DATA(insert OID = 1365 ( makeaclitem PGNSP PGUID 12 f f t f s 5 1033 "23 23 23 25 16" makeaclitem - _null_ ));
1322+
DESCR("make ACL item");
13211323
DATA(insert OID = 1038 ( seteval PGNSP PGUID 12 f f t t v 1 23 "26" seteval - _null_ ));
13221324
DESCR("internal function supporting PostQuel-style sets");
13231325
DATA(insert OID = 1044 ( bpcharin PGNSP PGUID 12 f f t f i 3 1042 "2275 26 23" bpcharin - _null_ ));

src/include/utils/acl.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $Id: acl.h,v 1.51 2003/01/23 23:39:07 petere Exp $
10+
* $Id: acl.h,v 1.52 2003/06/11 09:23:55 petere Exp $
1111
*
1212
* NOTES
1313
* For backward-compatibility purposes we have to allow there
@@ -70,6 +70,9 @@ typedef struct AclItem
7070
((item).ai_privs = (ACLITEM_GET_IDTYPE(item)<<30) | (ACLITEM_GET_GOPTIONS(item)<<15) | ((privs) & 0x7FFF))
7171
#define ACLITEM_SET_GOPTIONS(item,goptions) \
7272
((item).ai_privs = (ACLITEM_GET_IDTYPE(item)<<30) | (((goptions) & 0x7FFF) << 15) | ACLITEM_GET_PRIVS(item))
73+
#define ACLITEM_SET_IDTYPE(item,idtype) \
74+
((item).ai_privs = ((idtype)<<30) | (ACLITEM_GET_GOPTIONS(item)<<15) | ACLITEM_GET_PRIVS(item))
75+
7376
#define ACLITEM_SET_PRIVS_IDTYPE(item,privs,goption,idtype) \
7477
((item).ai_privs = ((privs) & 0x7FFF) |(((goption) & 0x7FFF) << 15) | ((idtype) << 30))
7578

@@ -188,6 +191,7 @@ extern Datum aclitemout(PG_FUNCTION_ARGS);
188191
extern Datum aclinsert(PG_FUNCTION_ARGS);
189192
extern Datum aclremove(PG_FUNCTION_ARGS);
190193
extern Datum aclcontains(PG_FUNCTION_ARGS);
194+
extern Datum makeaclitem(PG_FUNCTION_ARGS);
191195

192196
/*
193197
* prototypes for functions in aclchk.c

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy