]> granicus.if.org Git - postgresql/commitdiff
Allow a non-superuser database owner to vacuum all tables in his
authorTom Lane <tgl@sss.pgh.pa.us>
Wed, 13 Jun 2001 21:44:41 +0000 (21:44 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Wed, 13 Jun 2001 21:44:41 +0000 (21:44 +0000)
database, including system catalogs (but not the shared catalogs,
since they don't really belong to his database).  This is per recent
mailing list discussion.  Clean up some other code that also checks
for database ownerness by introducing a test function is_dbadmin().

src/backend/commands/analyze.c
src/backend/commands/comment.c
src/backend/commands/define.c
src/backend/commands/indexcmds.c
src/backend/commands/proclang.c
src/backend/commands/vacuum.c
src/backend/libpq/be-fsstubs.c
src/backend/utils/misc/superuser.c
src/include/catalog/pg_shadow.h
src/include/miscadmin.h

index 28ec8d648ef9579db987582745fe88b91ec148f7..c650ff88a1a27dad25b955b03064aad24b09aae9 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/commands/analyze.c,v 1.19 2001/06/06 21:29:17 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/commands/analyze.c,v 1.20 2001/06/13 21:44:40 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -193,16 +193,18 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt)
        ReleaseSysCache(tuple);
 
        /*
-        * Open the class, getting only a read lock on it, and check permissions
+        * Open the class, getting only a read lock on it, and check permissions.
+        * Permissions check should match vacuum's check!
         */
        onerel = heap_open(relid, AccessShareLock);
 
-       if (!pg_ownercheck(GetUserId(), RelationGetRelationName(onerel),
-                                          RELNAME))
+       if (! (pg_ownercheck(GetUserId(), RelationGetRelationName(onerel),
+                                                RELNAME) ||
+                  (is_dbadmin(MyDatabaseId) && !onerel->rd_rel->relisshared)))
        {
                /* No need for a notice if we already complained during VACUUM */
                if (!vacstmt->vacuum)
-                       elog(NOTICE, "Skipping \"%s\" --- only table owner can ANALYZE it",
+                       elog(NOTICE, "Skipping \"%s\" --- only table or database owner can ANALYZE it",
                                 RelationGetRelationName(onerel));
                heap_close(onerel, NoLock);
                CommitTransactionCommand();
index 695c7401e719cdf499ab2e475d375b99080b7dbb..39668f867e068b7ac9288df21ea205f6d6edba17 100644 (file)
@@ -4,10 +4,10 @@
  *
  * PostgreSQL object comments utility code.
  *
- * Copyright (c) 1999, PostgreSQL Global Development Group
+ * Copyright (c) 1999-2001, PostgreSQL Global Development Group
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.29 2001/06/05 19:34:56 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.30 2001/06/13 21:44:40 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -21,7 +21,6 @@
 #include "catalog/pg_database.h"
 #include "catalog/pg_description.h"
 #include "catalog/pg_operator.h"
-#include "catalog/pg_shadow.h"
 #include "catalog/pg_trigger.h"
 #include "catalog/pg_type.h"
 #include "catalog/pg_class.h"
@@ -389,16 +388,11 @@ CommentAttribute(char *relname, char *attrname, char *comment)
 static void
 CommentDatabase(char *database, char *comment)
 {
-
        Relation        pg_database;
-       HeapTuple       dbtuple,
-                               usertuple;
        ScanKeyData entry;
        HeapScanDesc scan;
+       HeapTuple       dbtuple;
        Oid                     oid;
-       bool            superuser;
-       int32           dba;
-       Oid                     userid;
 
        /*** First find the tuple in pg_database for the database ***/
 
@@ -408,33 +402,17 @@ CommentDatabase(char *database, char *comment)
        scan = heap_beginscan(pg_database, 0, SnapshotNow, 1, &entry);
        dbtuple = heap_getnext(scan, 0);
 
-       /*** Validate database exists, and fetch the dba id and oid ***/
+       /*** Validate database exists, and fetch the db oid ***/
 
        if (!HeapTupleIsValid(dbtuple))
                elog(ERROR, "database '%s' does not exist", database);
-       dba = ((Form_pg_database) GETSTRUCT(dbtuple))->datdba;
        oid = dbtuple->t_data->t_oid;
 
-       /*** Now, fetch user information ***/
-
-       userid = GetUserId();
-       usertuple = SearchSysCache(SHADOWSYSID,
-                                                          ObjectIdGetDatum(userid),
-                                                          0, 0, 0);
-       if (!HeapTupleIsValid(usertuple))
-               elog(ERROR, "invalid user id %u", (unsigned) userid);
-       superuser = ((Form_pg_shadow) GETSTRUCT(usertuple))->usesuper;
-       ReleaseSysCache(usertuple);
+       /*** Allow if the user matches the database dba or is a superuser ***/
 
-       /*** Allow if the userid matches the database dba or is a superuser ***/
-
-#ifndef NO_SECURITY
-       if (!(superuser || (userid == dba)))
-       {
+       if (!(superuser() || is_dbadmin(oid)))
                elog(ERROR, "you are not permitted to comment on database '%s'",
                         database);
-       }
-#endif
 
        /*** Create the comments with the pg_database oid ***/
 
@@ -444,7 +422,6 @@ CommentDatabase(char *database, char *comment)
 
        heap_endscan(scan);
        heap_close(pg_database, AccessShareLock);
-
 }
 
 /*------------------------------------------------------------------
index 98a6e351476f06e917c8fcdf2c717c794ffc2727..b5852b6fffaea6398695d03009a835ac155b4128 100644 (file)
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/commands/define.c,v 1.55 2001/05/18 21:24:18 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/commands/define.c,v 1.56 2001/06/13 21:44:40 tgl Exp $
  *
  * DESCRIPTION
  *       The "DefineFoo" routines take the parse tree and pick out the
  *
  *-------------------------------------------------------------------------
  */
+#include "postgres.h"
+
 #include <ctype.h>
 #include <math.h>
 
-#include "postgres.h"
-
 #include "access/heapam.h"
 #include "catalog/catname.h"
 #include "catalog/pg_aggregate.h"
 #include "catalog/pg_language.h"
 #include "catalog/pg_operator.h"
 #include "catalog/pg_proc.h"
-#include "catalog/pg_shadow.h"
 #include "catalog/pg_type.h"
 #include "commands/defrem.h"
 #include "fmgr.h"
+#include "miscadmin.h"
 #include "optimizer/cost.h"
 #include "parser/parse_expr.h"
 #include "tcop/dest.h"
index 373a68fbf30e2b02bacc2ca10a1b3ca1ea120001..108c4ea3780863db0782614d49df7eaac1c74a4f 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.49 2001/05/31 18:16:55 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.50 2001/06/13 21:44:40 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -28,7 +28,6 @@
 #include "catalog/pg_opclass.h"
 #include "catalog/pg_operator.h"
 #include "catalog/pg_proc.h"
-#include "catalog/pg_shadow.h"
 #include "commands/defrem.h"
 #include "miscadmin.h"
 #include "optimizer/clauses.h"
@@ -712,14 +711,9 @@ ReindexTable(const char *name, bool force)
 void
 ReindexDatabase(const char *dbname, bool force, bool all)
 {
-       Relation        relation,
-                               relationRelation;
-       HeapTuple       dbtuple,
-                               tuple;
+       Relation        relationRelation;
        HeapScanDesc scan;
-       int4            db_owner;
-       Oid                     db_id;
-       ScanKeyData scankey;
+       HeapTuple       tuple;
        MemoryContext private_context;
        MemoryContext old;
        int                     relcnt,
@@ -730,24 +724,12 @@ ReindexDatabase(const char *dbname, bool force, bool all)
 
        AssertArg(dbname);
 
-       relation = heap_openr(DatabaseRelationName, AccessShareLock);
-       ScanKeyEntryInitialize(&scankey, 0, Anum_pg_database_datname,
-                                                  F_NAMEEQ, NameGetDatum(dbname));
-       scan = heap_beginscan(relation, 0, SnapshotNow, 1, &scankey);
-       dbtuple = heap_getnext(scan, 0);
-       if (!HeapTupleIsValid(dbtuple))
-               elog(ERROR, "Database \"%s\" does not exist", dbname);
-       db_id = dbtuple->t_data->t_oid;
-       db_owner = ((Form_pg_database) GETSTRUCT(dbtuple))->datdba;
-       heap_endscan(scan);
-       heap_close(relation, NoLock);
+       if (strcmp(dbname, DatabaseName) != 0)
+               elog(ERROR, "REINDEX DATABASE: Can be executed only on the currently open database.");
 
-       if (GetUserId() != db_owner && !superuser())
+       if (! (superuser() || is_dbadmin(MyDatabaseId)))
                elog(ERROR, "REINDEX DATABASE: Permission denied.");
 
-       if (db_id != MyDatabaseId)
-               elog(ERROR, "REINDEX DATABASE: Can be executed only on the currently open database.");
-
        /*
         * We cannot run inside a user transaction block; if we were inside a
         * transaction, then our commit- and start-transaction-command calls
index 43327c7a65ac1a21618174d66399aaf5be89196f..120c5d8b008c8f0865c74c0fd4b0c6b2871f3258 100644 (file)
@@ -3,20 +3,26 @@
  * proclang.c
  *       PostgreSQL PROCEDURAL LANGUAGE support code.
  *
+ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ *       $Header: /cvsroot/pgsql/src/backend/commands/proclang.c,v 1.28 2001/06/13 21:44:40 tgl Exp $
+ *
  *-------------------------------------------------------------------------
  */
-#include <ctype.h>
-
 #include "postgres.h"
 
+#include <ctype.h>
+
 #include "access/heapam.h"
 #include "catalog/catname.h"
 #include "catalog/indexing.h"
 #include "catalog/pg_language.h"
 #include "catalog/pg_proc.h"
-#include "catalog/pg_shadow.h"
 #include "commands/proclang.h"
 #include "fmgr.h"
+#include "miscadmin.h"
 #include "utils/builtins.h"
 #include "utils/syscache.h"
 
@@ -63,10 +69,8 @@ CreateProceduralLanguage(CreatePLangStmt *stmt)
         * Check permission
         */
        if (!superuser())
-       {
                elog(ERROR, "Only users with Postgres superuser privilege are "
                         "permitted to create procedural languages");
-       }
 
        /*
         * Translate the language name and check that this language doesn't
@@ -150,10 +154,8 @@ DropProceduralLanguage(DropPLangStmt *stmt)
         * Check permission
         */
        if (!superuser())
-       {
                elog(ERROR, "Only users with Postgres superuser privilege are "
                         "permitted to drop procedural languages");
-       }
 
        /*
         * Translate the language name, check that this language exist and is
index 3cba03952015fa4cf681973bbe9e7dd058ee83bb..33d5409364ac9166376c83d4c0867f9ba17aca47 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.195 2001/05/25 15:45:32 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.196 2001/06/13 21:44:40 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -437,15 +437,20 @@ vacuum_rel(Oid relid)
        /*
         * Open the class, get an exclusive lock on it, and check permissions.
         *
+        * We allow the user to vacuum a table if he is superuser, the table
+        * owner, or the database owner (but in the latter case, only if it's
+        * not a shared relation).  pg_ownercheck includes the superuser case.
+        *
         * Note we choose to treat permissions failure as a NOTICE and keep
         * trying to vacuum the rest of the DB --- is this appropriate?
         */
        onerel = heap_open(relid, AccessExclusiveLock);
 
-       if (!pg_ownercheck(GetUserId(), RelationGetRelationName(onerel),
-                                          RELNAME))
+       if (! (pg_ownercheck(GetUserId(), RelationGetRelationName(onerel),
+                                                RELNAME) ||
+                  (is_dbadmin(MyDatabaseId) && !onerel->rd_rel->relisshared)))
        {
-               elog(NOTICE, "Skipping \"%s\" --- only table owner can VACUUM it",
+               elog(NOTICE, "Skipping \"%s\" --- only table or database owner can VACUUM it",
                         RelationGetRelationName(onerel));
                heap_close(onerel, AccessExclusiveLock);
                CommitTransactionCommand();
index 4d50ee1ae12d907d744f603d1440570a2d824d48..b0a759bc0080fbaf17009679bb305ad925a87010 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/libpq/be-fsstubs.c,v 1.58 2001/03/22 03:59:30 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/libpq/be-fsstubs.c,v 1.59 2001/06/13 21:44:41 tgl Exp $
  *
  * NOTES
  *       This should be moved to a more appropriate place.  It is here
@@ -39,9 +39,9 @@
 #include <sys/stat.h>
 #include <unistd.h>
 
-#include "catalog/pg_shadow.h"
 #include "libpq/be-fsstubs.h"
 #include "libpq/libpq-fs.h"
+#include "miscadmin.h"
 #include "storage/large_object.h"
 #include "utils/memutils.h"
 
index e539d57347bc647377f05adbaf81a1406a89dc16..73cfe8cb9799b9bad3750abc8719fca43ae3bdc5 100644 (file)
@@ -1,35 +1,38 @@
 /*-------------------------------------------------------------------------
  *
  * superuser.c
- *
  *       The superuser() function.  Determines if user has superuser privilege.
+ *       Also, a function to check for the owner (datdba) of a database.
+ *
  *
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/utils/misc/superuser.c,v 1.17 2001/01/24 19:43:16 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/utils/misc/superuser.c,v 1.18 2001/06/13 21:44:41 tgl Exp $
  *
- * DESCRIPTION
- *       See superuser().
  *-------------------------------------------------------------------------
  */
-
 #include "postgres.h"
+
+#include "access/heapam.h"
+#include "catalog/catname.h"
+#include "catalog/pg_database.h"
 #include "catalog/pg_shadow.h"
 #include "utils/syscache.h"
 #include "miscadmin.h"
+#include "utils/fmgroids.h"
 
+
+/*
+ * The Postgres user running this command has Postgres superuser privileges
+ */
 bool
 superuser(void)
 {
-/*--------------------------------------------------------------------------
-       The Postgres user running this command has Postgres superuser
-       privileges.
---------------------------------------------------------------------------*/
+       bool            result = false;
        HeapTuple       utup;
-       bool            result;
 
        utup = SearchSysCache(SHADOWSYSID,
                                                  ObjectIdGetDatum(GetUserId()),
@@ -38,7 +41,36 @@ superuser(void)
        {
                result = ((Form_pg_shadow) GETSTRUCT(utup))->usesuper;
                ReleaseSysCache(utup);
-               return result;
        }
-       return false;
+       return result;
+}
+
+/*
+ * The Postgres user running this command is the owner of the specified
+ * database.
+ */
+bool
+is_dbadmin(Oid dbid)
+{
+       Relation        pg_database;
+       ScanKeyData entry[1];
+       HeapScanDesc scan;
+       HeapTuple       dbtuple;
+       int32           dba;
+
+       /* There's no syscache for pg_database, so must look the hard way */
+       pg_database = heap_openr(DatabaseRelationName, AccessShareLock);
+       ScanKeyEntryInitialize(&entry[0], 0x0,
+                                                  ObjectIdAttributeNumber, F_OIDEQ,
+                                                  ObjectIdGetDatum(dbid));
+       scan = heap_beginscan(pg_database, 0, SnapshotNow, 1, entry);
+       dbtuple = heap_getnext(scan, 0);
+       if (!HeapTupleIsValid(dbtuple))
+               elog(ERROR, "database %u does not exist", dbid);
+       dba = ((Form_pg_database) GETSTRUCT(dbtuple))->datdba;
+       heap_endscan(scan);
+       heap_close(pg_database, AccessShareLock);
+
+       /* XXX some confusion about whether userids are OID or int4 ... */
+       return (GetUserId() == (Oid) dba);
 }
index e0b087a9d913f54c95487285ff3cd6bccde57398..fdec3fa82cace5a60c96eeb7121bb49952cbcd0e 100644 (file)
@@ -9,7 +9,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pg_shadow.h,v 1.11 2001/03/09 22:10:13 tgl Exp $
+ * $Id: pg_shadow.h,v 1.12 2001/06/13 21:44:41 tgl Exp $
  *
  * NOTES
  *       the genbki.sh script reads this file and generates .bki
 #define PG_SHADOW_H
 
 
-/* Prototype required for superuser() from superuser.c */
-
-bool           superuser(void);
-
 /* ----------------
  *             pg_shadow definition.  cpp turns this into
  *             typedef struct FormData_pg_shadow
index 742f58137c5e9fcc90581ee1e6e0cb8c8e5a969f..588c2f99dea2990d690a7a3f6024feff183ef6cc 100644 (file)
@@ -12,7 +12,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: miscadmin.h,v 1.85 2001/05/12 01:48:49 petere Exp $
+ * $Id: miscadmin.h,v 1.86 2001/06/13 21:44:41 tgl Exp $
  *
  * NOTES
  *       some of the information in this file should be moved to
@@ -220,9 +220,13 @@ extern int CheckPathAccess(char *path, char *name, int open_mode);
 extern void GetCharSetByHost(char *TableName, int host, const char *DataDir);
 extern void SetCharSet(void);
 extern char *convertstr(unsigned char *buff, int len, int dest);
-
 #endif
 
+/* in utils/misc/superuser.c */
+extern bool superuser(void);   /* current user is superuser */
+extern bool is_dbadmin(Oid dbid); /* current user is owner of database */
+
+
 /*****************************************************************************
  *       pmod.h --                                                                                                                              *
  *                     POSTGRES processing mode definitions.                                                    *