diff options
Diffstat (limited to 'src/backend/utils/adt/acl.c')
-rw-r--r-- | src/backend/utils/adt/acl.c | 757 |
1 files changed, 756 insertions, 1 deletions
diff --git a/src/backend/utils/adt/acl.c b/src/backend/utils/adt/acl.c index eeb95430271..14bf6e3c801 100644 --- a/src/backend/utils/adt/acl.c +++ b/src/backend/utils/adt/acl.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/acl.c,v 1.61 2001/06/09 23:21:55 petere Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/acl.c,v 1.62 2001/06/12 15:58:34 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -31,6 +31,12 @@ static const char *getid(const char *s, char *n); static bool aclitemeq(const AclItem *a1, const AclItem *a2); static bool aclitemgt(const AclItem *a1, const AclItem *a2); +AclMode convert_priv_string(text *priv_type_text); +bool has_table_privilege_cname_cname(char *username, char *relname, text *priv_type_text); +bool has_table_privilege_id_cname(Oid usesysid, char *relname, text *priv_type_text); +bool has_table_privilege_cname_id(char *username, Oid reloid, text *priv_type_text); +static char *get_Name(text *relin); + #define ACL_IDTYPE_GID_KEYWORD "group" #define ACL_IDTYPE_UID_KEYWORD "user" @@ -710,3 +716,752 @@ makeAclString(const char *privileges, const char *grantee, char grant_or_revoke) pfree(str.data); return ret; } + + +/* + * has_table_privilege_tname_tname + * Check user privileges on a relation given + * text usename, text relname, and text priv name. + * + * RETURNS + * a boolean value + * 't' indicating user has the privilege + * 'f' indicating user does not have the privilege + */ +Datum +has_table_privilege_tname_tname(PG_FUNCTION_ARGS) +{ + text *username_text; + char *username; + text *relname_text; + char *relname; + text *priv_type_text; + bool result; + + username_text = PG_GETARG_TEXT_P(0); + relname_text = PG_GETARG_TEXT_P(1); + priv_type_text = PG_GETARG_TEXT_P(2); + + /* + * Convert username and relname 'text' pattern to null-terminated string + */ + username = get_Name(username_text); + relname = get_Name(relname_text); + + /* + * Make use of has_table_privilege_cname_cname. + * It accepts the arguments we now have. + */ + result = has_table_privilege_cname_cname(username, relname, priv_type_text); + + PG_RETURN_BOOL(result); + +} + + +/* + * has_table_privilege_tname_name + * Check user privileges on a relation given + * text usename, name relname, and text priv name. + * + * RETURNS + * a boolean value + * 't' indicating user has the privilege + * 'f' indicating user does not have the privilege + */ +Datum +has_table_privilege_tname_name(PG_FUNCTION_ARGS) +{ + text *username_text; + char *username; + Name relname_name; + char *relname; + text *priv_type_text; + bool result; + + username_text = PG_GETARG_TEXT_P(0); + relname_name = PG_GETARG_NAME(1); + priv_type_text = PG_GETARG_TEXT_P(2); + + /* + * Convert username 'text' pattern to null-terminated string + */ + username = get_Name(username_text); + + /* + * Convert relname 'name' pattern to null-terminated string + */ + relname = DatumGetCString(DirectFunctionCall1(nameout, PointerGetDatum(relname_name))); + + /* + * Make use of has_table_privilege_cname_cname. + * It accepts the arguments we now have. + */ + result = has_table_privilege_cname_cname(username, relname, priv_type_text); + + PG_RETURN_BOOL(result); + +} + + +/* + * has_table_privilege_name_tname + * Check user privileges on a relation given + * name usename, text relname, and text priv name. + * + * RETURNS + * a boolean value + * 't' indicating user has the privilege + * 'f' indicating user does not have the privilege + */ +Datum +has_table_privilege_name_tname(PG_FUNCTION_ARGS) +{ + Name username_name; + char *username; + text *relname_text; + char *relname; + text *priv_type_text; + bool result; + + username_name = PG_GETARG_NAME(0); + relname_text = PG_GETARG_TEXT_P(1); + priv_type_text = PG_GETARG_TEXT_P(2); + + /* + * Convert username 'name' pattern to null-terminated string + */ + username = DatumGetCString(DirectFunctionCall1(nameout, PointerGetDatum(username_name))); + + /* + * Convert relname 'text' pattern to null-terminated string + */ + relname = get_Name(relname_text); + + /* + * Make use of has_table_privilege_cname_cname. + * It accepts the arguments we now have. + */ + result = has_table_privilege_cname_cname(username, relname, priv_type_text); + + PG_RETURN_BOOL(result); + +} + + +/* + * has_table_privilege_name_name + * Check user privileges on a relation given + * name usename, name relname, and text priv name. + * + * RETURNS + * a boolean value + * 't' indicating user has the privilege + * 'f' indicating user does not have the privilege + */ +Datum +has_table_privilege_name_name(PG_FUNCTION_ARGS) +{ + Name username_name; + char *username; + Name relname_name; + char *relname; + text *priv_type_text; + bool result; + + username_name = PG_GETARG_NAME(0); + relname_name = PG_GETARG_NAME(1); + priv_type_text = PG_GETARG_TEXT_P(2); + + /* + * Convert username and relname 'name' pattern to null-terminated string + */ + username = DatumGetCString(DirectFunctionCall1(nameout, PointerGetDatum(username_name))); + relname = DatumGetCString(DirectFunctionCall1(nameout, PointerGetDatum(relname_name))); + + /* + * Make use of has_table_privilege_cname_cname. + * It accepts the arguments we now have. + */ + result = has_table_privilege_cname_cname(username, relname, priv_type_text); + + PG_RETURN_BOOL(result); + +} + + +/* + * has_table_privilege_tname + * Check user privileges on a relation given + * text relname and text priv name. + * current_user is assumed + * + * RETURNS + * a boolean value + * 't' indicating user has the privilege + * 'f' indicating user does not have the privilege + */ +Datum +has_table_privilege_tname(PG_FUNCTION_ARGS) +{ + Oid usesysid = (Oid) -1; + text *relname_text; + char *relname; + text *priv_type_text; + bool result; + + relname_text = PG_GETARG_TEXT_P(0); + priv_type_text = PG_GETARG_TEXT_P(1); + + usesysid = GetUserId(); + + /* + * Convert relname 'text' pattern to null-terminated string + */ + relname = get_Name(relname_text); + + /* + * Make use of has_table_privilege_id_cname. + * It accepts the arguments we now have. + */ + result = has_table_privilege_id_cname(usesysid, relname, priv_type_text); + + PG_RETURN_BOOL(result); + +} + +/* + * has_table_privilege_name + * Check user privileges on a relation given + * name relname and text priv name. + * current_user is assumed + * + * RETURNS + * a boolean value + * 't' indicating user has the privilege + * 'f' indicating user does not have the privilege + */ +Datum +has_table_privilege_name(PG_FUNCTION_ARGS) +{ + Oid usesysid = (Oid) -1; + Name relname_name; + char *relname; + text *priv_type_text; + bool result; + + relname_name = PG_GETARG_NAME(0); + priv_type_text = PG_GETARG_TEXT_P(1); + + usesysid = GetUserId(); + + /* + * Convert relname 'Name' pattern to null-terminated string + */ + relname = DatumGetCString(DirectFunctionCall1(nameout, PointerGetDatum(relname_name))); + + /* + * Make use of has_table_privilege_id_cname. + * It accepts the arguments we now have. + */ + result = has_table_privilege_id_cname(usesysid, relname, priv_type_text); + + PG_RETURN_BOOL(result); + +} + + +/* + * has_table_privilege_tname_id + * Check user privileges on a relation given + * text usename, rel oid, and text priv name. + * + * RETURNS + * a boolean value + * 't' indicating user has the privilege + * 'f' indicating user does not have the privilege + */ +Datum +has_table_privilege_tname_id(PG_FUNCTION_ARGS) +{ + text *username_text; + char *username; + Oid reloid = 0; + text *priv_type_text; + bool result; + + username_text = PG_GETARG_TEXT_P(0); + reloid = PG_GETARG_OID(1); + priv_type_text = PG_GETARG_TEXT_P(2); + + /* + * Convert username 'text' pattern to null-terminated string + */ + username = get_Name(username_text); + + /* + * Make use of has_table_privilege_cname_id. + * It accepts the arguments we now have. + */ + result = has_table_privilege_cname_id(username, reloid, priv_type_text); + + PG_RETURN_BOOL(result); + +} + + +/* + * has_table_privilege_name_id + * Check user privileges on a relation given + * name usename, rel oid, and text priv name. + * + * RETURNS + * a boolean value + * 't' indicating user has the privilege + * 'f' indicating user does not have the privilege + */ +Datum +has_table_privilege_name_id(PG_FUNCTION_ARGS) +{ + Name username_name; + char *username; + Oid reloid = 0; + text *priv_type_text = NULL; + bool result; + + username_name = PG_GETARG_NAME(0); + reloid = PG_GETARG_OID(1); + priv_type_text = PG_GETARG_TEXT_P(2); + + /* + * Convert username 'name' pattern to null-terminated string + */ + username = DatumGetCString(DirectFunctionCall1(nameout, PointerGetDatum(username_name))); + + /* + * Make use of has_table_privilege_cname_id. + * It accepts the arguments we now have. + */ + result = has_table_privilege_cname_id(username, reloid, priv_type_text); + + PG_RETURN_BOOL(result); + +} + + +/* + * has_table_privilege_id + * Check user privileges on a relation given + * rel oid, and text priv name. + * current_user is assumed + * + * RETURNS + * a boolean value + * 't' indicating user has the privilege + * 'f' indicating user does not have the privilege + */ +Datum +has_table_privilege_id(PG_FUNCTION_ARGS) +{ + char *username; + Oid reloid = 0; + text *priv_type_text; + bool result; + + reloid = PG_GETARG_OID(0); + priv_type_text = PG_GETARG_TEXT_P(1); + username = GetUserName(GetUserId()); + + /* + * Make use of has_table_privilege_cname_id. + * It accepts the arguments we now have. + */ + result = has_table_privilege_cname_id(username, reloid, priv_type_text); + + PG_RETURN_BOOL(result); + +} + + +/* + * has_table_privilege_id_tname + * Check user privileges on a relation given + * usesysid, text relname, and priv name. + * + * RETURNS + * a boolean value + * 't' indicating user has the privilege + * 'f' indicating user does not have the privilege + */ +Datum +has_table_privilege_id_tname(PG_FUNCTION_ARGS) +{ + Oid usesysid; + text *relname_text; + char *relname; + text *priv_type_text; + bool result; + + usesysid = PG_GETARG_OID(0); + relname_text = PG_GETARG_TEXT_P(1); + priv_type_text = PG_GETARG_TEXT_P(2); + + /* + * Convert relname 'text' pattern to null-terminated string + */ + relname = get_Name(relname_text); + + /* + * Make use of has_table_privilege_id_cname. + * It accepts the arguments we now have. + */ + result = has_table_privilege_id_cname(usesysid, relname, priv_type_text); + + PG_RETURN_BOOL(result); + +} + + +/* + * has_table_privilege_id_name + * Check user privileges on a relation given + * usesysid, name relname, and priv name. + * + * RETURNS + * a boolean value + * 't' indicating user has the privilege + * 'f' indicating user does not have the privilege + */ +Datum +has_table_privilege_id_name(PG_FUNCTION_ARGS) +{ + Oid usesysid; + Name relname_name; + char *relname; + text *priv_type_text; + bool result; + + usesysid = PG_GETARG_OID(0); + relname_name = PG_GETARG_NAME(1); + priv_type_text = PG_GETARG_TEXT_P(2); + + /* + * Convert relname 'name' pattern to null-terminated string + */ + relname = DatumGetCString(DirectFunctionCall1(nameout, PointerGetDatum(relname_name))); + + /* + * Make use of has_table_privilege_id_cname. + * It accepts the arguments we now have. + */ + result = has_table_privilege_id_cname(usesysid, relname, priv_type_text); + + PG_RETURN_BOOL(result); + +} + + +/* + * has_table_privilege_id_id + * Check user privileges on a relation given + * usesysid, rel oid, and priv name. + * + * RETURNS + * a boolean value + * 't' indicating user has the privilege + * 'f' indicating user does not have the privilege + */ +Datum +has_table_privilege_id_id(PG_FUNCTION_ARGS) +{ + Oid usesysid; + Oid reloid; + char *relname; + text *priv_type_text; + HeapTuple tuple; + AclMode mode; + int32 result; + + + usesysid = PG_GETARG_OID(0); + reloid = PG_GETARG_OID(1); + priv_type_text = PG_GETARG_TEXT_P(2); + + /* + * Lookup relname based on rel oid + */ + tuple = SearchSysCache(RELOID, ObjectIdGetDatum(reloid), 0, 0, 0); + if (!HeapTupleIsValid(tuple)) { + elog(ERROR, "has_table_privilege: invalid relation oid %d", (int) reloid); + } + + relname = NameStr(((Form_pg_class) GETSTRUCT(tuple))->relname); + + ReleaseSysCache(tuple); + + /* + * Convert priv_type_text to an AclMode + */ + mode = convert_priv_string(priv_type_text); + + /* + * Finally, check for the privilege + */ + result = pg_aclcheck(relname, usesysid, mode); + + if (result == ACLCHECK_OK) { + PG_RETURN_BOOL(TRUE); + } else { + PG_RETURN_BOOL(FALSE); + } + +} + +/* + * Internal functions. + */ + +/* + * convert_priv_string + * Internal function. + * Return mode from priv_type string + * + * RETURNS + * AclMode + */ + +AclMode +convert_priv_string(text *priv_type_text) +{ + char *priv_type = DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(priv_type_text))); + + /* + * Return mode from priv_type string + */ + if (strcasecmp(priv_type, "SELECT") == 0) + return ACL_SELECT; + + if (strcasecmp(priv_type, "INSERT") == 0) + return ACL_INSERT; + + if (strcasecmp(priv_type, "UPDATE") == 0) + return ACL_UPDATE; + + if (strcasecmp(priv_type, "DELETE") == 0) + return ACL_DELETE; + + if (strcasecmp(priv_type, "RULE") == 0) + return ACL_RULE; + + if (strcasecmp(priv_type, "REFERENCES") == 0) + return ACL_REFERENCES; + + if (strcasecmp(priv_type, "TRIGGER") == 0) + return ACL_TRIGGER; + + elog(ERROR, "has_table_privilege: invalid privilege type %s", priv_type); + /* + * We should never get here, but stop the compiler from complaining + */ + return ACL_NO; + +} + +/* + * has_table_privilege_cname_cname + * Check user privileges on a relation given + * char *usename, char *relname, and text priv name. + * + * RETURNS + * a boolean value + * 't' indicating user has the privilege + * 'f' indicating user does not have the privilege + */ +bool +has_table_privilege_cname_cname(char *username, char *relname, text *priv_type_text) +{ + + Oid usesysid = (Oid) -1; + HeapTuple tuple; + bool result; + + /* + * Lookup userid based on username + */ + + tuple = SearchSysCache(SHADOWNAME, NameGetDatum(username), 0, 0, 0); + if (!HeapTupleIsValid(tuple)) { + elog(ERROR, "has_table_privilege: invalid user name %s", (char *) username); + } + + usesysid = (Oid) ((Form_pg_shadow) GETSTRUCT(tuple))->usesysid; + ReleaseSysCache(tuple); + + /* + * Make use of has_table_privilege_id_cname. + * It accepts the arguments we now have. + */ + result = has_table_privilege_id_cname(usesysid, relname, priv_type_text); + + return result; + +} + + +/* + * has_table_privilege_cname_id + * Check user privileges on a relation given + * char *usename, rel oid, and text priv name. + * + * RETURNS + * a boolean value + * 't' indicating user has the privilege + * 'f' indicating user does not have the privilege + */ +bool +has_table_privilege_cname_id(char *username, Oid reloid, text *priv_type_text) +{ + Oid usesysid = (Oid) -1; + char *relname = NULL; + HeapTuple tuple; + bool result; + + /* + * Lookup userid based on username + */ + + tuple = SearchSysCache(SHADOWNAME, NameGetDatum(username), 0, 0, 0); + if (!HeapTupleIsValid(tuple)) { + elog(ERROR, "has_table_privilege: invalid user name %s", (char *) username); + } + + usesysid = (Oid) ((Form_pg_shadow) GETSTRUCT(tuple))->usesysid; + + ReleaseSysCache(tuple); + + /* + * Lookup relname based on rel oid + */ + tuple = SearchSysCache(RELOID, ObjectIdGetDatum(reloid), 0, 0, 0); + if (!HeapTupleIsValid(tuple)) { + elog(ERROR, "has_table_privilege: invalid relation oid %d", (int) reloid); + } + + relname = NameStr(((Form_pg_class) GETSTRUCT(tuple))->relname); + + ReleaseSysCache(tuple); + + /* + * Make use of has_table_privilege_id_cname. + * It accepts the arguments we now have. + */ + result = has_table_privilege_id_cname(usesysid, relname, priv_type_text); + + return result; + +} + + +/* + * has_table_privilege_id_cname + * Check user privileges on a relation given + * usesysid, char *relname, and text priv name. + * + * RETURNS + * a boolean value + * 't' indicating user has the privilege + * 'f' indicating user does not have the privilege + */ +bool +has_table_privilege_id_cname(Oid usesysid, char *relname, text *priv_type_text) +{ + + HeapTuple tuple; + AclMode mode; + int32 result; + + /* + * Check relname is valid. + * This is needed to deal with the case when usename is a superuser + * in which case pg_aclcheck simply returns ACLCHECK_OK + * without validating relname + */ + tuple = SearchSysCache(RELNAME, PointerGetDatum(relname), 0, 0, 0); + + if (!HeapTupleIsValid(tuple)) { + elog(ERROR, "has_table_privilege: invalid relname %s", relname); + } + ReleaseSysCache(tuple); + + /* + * Convert priv_type_text to an AclMode + */ + mode = convert_priv_string(priv_type_text); + + /* + * Finally, check for the privilege + */ + result = pg_aclcheck(relname, usesysid, mode); + + if (result == ACLCHECK_OK) { + return TRUE; + } else { + return FALSE; + } + +} + + +/* + * Given a 'text' relname parameter to a function, extract the actual + * relname. We downcase the name if it's not double-quoted, + * and truncate it if it's too long. + * + * This is a kluge, really --- should be able to write, e.g. nextval(seqrel). + */ +static char * +get_Name(text *relin) +{ + char *rawname = DatumGetCString(DirectFunctionCall1(textout, + PointerGetDatum(relin))); + int rawlen = strlen(rawname); + char *relname; + + if (rawlen >= 2 && + rawname[0] == '\"' && rawname[rawlen - 1] == '\"') + { + /* strip off quotes, keep case */ + rawname[rawlen - 1] = '\0'; + relname = pstrdup(rawname + 1); + pfree(rawname); + } + else + { + relname = rawname; + + /* + * It's important that this match the identifier downcasing code + * used by backend/parser/scan.l. + */ + for (; *rawname; rawname++) + { + if (isupper((unsigned char) *rawname)) + *rawname = tolower((unsigned char) *rawname); + } + } + + /* Truncate name if it's overlength; again, should match scan.l */ + if (strlen(relname) >= NAMEDATALEN) + { +#ifdef MULTIBYTE + int len; + + len = pg_mbcliplen(relname, i, NAMEDATALEN-1); + relname[len] = '\0'; +#else + relname[NAMEDATALEN-1] = '\0'; +#endif + } + + return relname; +} |