]> granicus.if.org Git - postgresql/commitdiff
Support SECURITY LABEL on databases, tablespaces, and roles.
authorRobert Haas <rhaas@postgresql.org>
Wed, 20 Jul 2011 17:18:24 +0000 (13:18 -0400)
committerRobert Haas <rhaas@postgresql.org>
Wed, 20 Jul 2011 17:18:24 +0000 (13:18 -0400)
This requires a new shared catalog, pg_shseclabel.

Along the way, fix the security_label regression tests so that they
don't monkey with the labels of any pre-existing objects.  This is
unlikely to matter in practice, since only the label for the "dummy"
provider was being manipulated.  But this way still seems cleaner.

KaiGai Kohei, with fairly extensive hacking by me.

22 files changed:
doc/src/sgml/catalogs.sgml
doc/src/sgml/ref/security_label.sgml
src/backend/catalog/Makefile
src/backend/catalog/catalog.c
src/backend/catalog/system_views.sql
src/backend/commands/dbcommands.c
src/backend/commands/seclabel.c
src/backend/commands/tablespace.c
src/backend/commands/user.c
src/backend/parser/gram.y
src/bin/pg_dump/dumputils.c
src/bin/pg_dump/dumputils.h
src/bin/pg_dump/pg_dump.c
src/bin/pg_dump/pg_dumpall.c
src/include/catalog/catversion.h
src/include/catalog/indexing.h
src/include/catalog/pg_shseclabel.h [new file with mode: 0644]
src/include/commands/seclabel.h
src/test/regress/expected/rules.out
src/test/regress/expected/sanity_check.out
src/test/regress/input/security_label.source
src/test/regress/output/security_label.source

index a5ae7c9e91c50a568f2a0aa6bd5f021f6a5be6d1..5e5f8a7554755d6948ab1b3276cf02b5daffe615 100644 (file)
       <entry>comments on shared objects</entry>
      </row>
 
+     <row>
+      <entry><link linkend="catalog-pg-shseclabel"><structname>pg_shseclabel</structname></link></entry>
+      <entry>security labels on shared database objects</entry>
+     </row>
+
      <row>
       <entry><link linkend="catalog-pg-statistic"><structname>pg_statistic</structname></link></entry>
       <entry>planner statistics</entry>
    way to view security labels, see <xref linkend="view-pg-seclabels">.
   </para>
 
+  <para>
+   See also <link linkend="catalog-pg-shseclabel"><structname>pg_shseclabel</structname></link>,
+   which performs a similar function for security labels of database objects
+   that are shared across a database cluster.
+  </para>
+
   <table>
    <title><structname>pg_seclabel</structname> Columns</title>
 
 
  </sect1>
 
+ <sect1 id="catalog-pg-shseclabel">
+  <title><structname>pg_shseclabel</structname></title>
+
+  <indexterm zone="catalog-pg-shseclabel">
+   <primary>pg_shseclabel</primary>
+  </indexterm>
+
+  <para>
+   The catalog <structname>pg_shseclabel</structname> stores security
+   lables on shared database objects.  Security labels can be manipulated
+   with the <xref linkend="sql-security-label"> command.  For an easier
+   way to view security labels, see <xref linkend="view-pg-seclabels">.
+  </para>
+
+  <para>
+   See also <link linkend="catalog-pg-seclabel"><structname>pg_seclabel</structname></link>,
+   which performs a similar function for security labels involving objects
+   within a single database.
+  </para>
+
+  <para>
+   Unlike most system catalogs, <structname>pg_shseclabel</structname>
+   is shared across all databases of a cluster: there is only one
+   copy of <structname>pg_shseclabel</structname> per cluster, not
+   one per database.
+  </para>
+
+  <table>
+   <title><structname>pg_shseclabel</structname> Columns</title>
+   <tgroup cols="4">
+    <thead>
+     <row>
+      <entry>Name</entry>
+      <entry>Type</entry>
+      <entry>References</entry>
+      <entry>Description</entry>
+     </row>
+    </thead>
+    <tbody>
+     <row>
+      <entry><structfield>objoid</structfield></entry>
+      <entry><type>oid</type></entry>
+      <entry>any OID column</entry>
+      <entry>The OID of the object this security label pertains to</entry>
+     </row>
+     <row>
+      <entry><structfield>classoid</structfield></entry>
+      <entry><type>oid</type></entry>
+      <entry><literal><link linkend="catalog-pg-class"><structname>pg_class</structname></link>.oid</literal></entry>
+      <entry>The OID of the system catalog this object appears in</entry>
+     </row>
+     <row>
+      <entry><structfield>provider</structfield></entry>
+      <entry><type>name</type></entry>
+      <entry></entry>
+      <entry>The label provider associated with this label.</entry>
+     </row>
+     <row>
+      <entry><structfield>label</structfield></entry>
+      <entry><type>text</type></entry>
+      <entry></entry>
+      <entry>The security label applied to this object.</entry>
+     </row>
+    </tbody>
+   </tgroup>
+  </table>
+ </sect1>
 
  <sect1 id="catalog-pg-statistic">
   <title><structname>pg_statistic</structname></title>
index 13b62e22aa18e00f920128bec46a614a60b7a257..a9eda21b72abb0ea709aa0a49c2ef84bbf056130 100644 (file)
@@ -26,13 +26,16 @@ SECURITY LABEL [ FOR <replaceable class="PARAMETER">provider</replaceable> ] ON
   TABLE <replaceable class="PARAMETER">object_name</replaceable> |
   COLUMN <replaceable class="PARAMETER">table_name</replaceable>.<replaceable class="PARAMETER">column_name</replaceable> |
   AGGREGATE <replaceable class="PARAMETER">agg_name</replaceable> (<replaceable class="PARAMETER">agg_type</replaceable> [, ...] ) |
+  DATABASE <replaceable class="PARAMETER">object_name</replaceable> |
   DOMAIN <replaceable class="PARAMETER">object_name</replaceable> |
   FOREIGN TABLE <replaceable class="PARAMETER">object_name</replaceable>
   FUNCTION <replaceable class="PARAMETER">function_name</replaceable> ( [ [ <replaceable class="parameter">argmode</replaceable> ] [ <replaceable class="parameter">argname</replaceable> ] <replaceable class="parameter">argtype</replaceable> [, ...] ] ) |
   LARGE OBJECT <replaceable class="PARAMETER">large_object_oid</replaceable> |
   [ PROCEDURAL ] LANGUAGE <replaceable class="PARAMETER">object_name</replaceable> |
+  ROLE <replaceable class="PARAMETER">object_name</replaceable> |
   SCHEMA <replaceable class="PARAMETER">object_name</replaceable> |
   SEQUENCE <replaceable class="PARAMETER">object_name</replaceable> |
+  TABLESPACE <replaceable class="PARAMETER">object_name</replaceable> |
   TYPE <replaceable class="PARAMETER">object_name</replaceable> |
   VIEW <replaceable class="PARAMETER">object_name</replaceable>
 } IS '<replaceable class="PARAMETER">label</replaceable>'
index 3a834618d28510131e0d1db95ec1d1da958a40f7..7e0b7d65a8749815475a0d625f508fbb5ccc2a3c 100644 (file)
@@ -39,7 +39,7 @@ POSTGRES_BKI_SRCS = $(addprefix $(top_srcdir)/src/include/catalog/,\
        pg_ts_parser.h pg_ts_template.h pg_extension.h \
        pg_foreign_data_wrapper.h pg_foreign_server.h pg_user_mapping.h \
        pg_foreign_table.h \
-       pg_default_acl.h pg_seclabel.h pg_collation.h \
+       pg_default_acl.h pg_seclabel.h pg_shseclabel.h pg_collation.h \
        toasting.h indexing.h \
     )
 
index cbce0072de190e5c79d101cd1f1b1995b9ee2220..9d568b5273a2f51ef2a410e7de6d887d845d7353 100644 (file)
@@ -34,6 +34,7 @@
 #include "catalog/pg_db_role_setting.h"
 #include "catalog/pg_shdepend.h"
 #include "catalog/pg_shdescription.h"
+#include "catalog/pg_shseclabel.h"
 #include "catalog/pg_tablespace.h"
 #include "catalog/toasting.h"
 #include "miscadmin.h"
@@ -380,6 +381,7 @@ IsSharedRelation(Oid relationId)
                relationId == PLTemplateRelationId ||
                relationId == SharedDescriptionRelationId ||
                relationId == SharedDependRelationId ||
+               relationId == SharedSecLabelRelationId ||
                relationId == TableSpaceRelationId ||
                relationId == DbRoleSettingRelationId)
                return true;
@@ -394,6 +396,7 @@ IsSharedRelation(Oid relationId)
                relationId == SharedDescriptionObjIndexId ||
                relationId == SharedDependDependerIndexId ||
                relationId == SharedDependReferenceIndexId ||
+               relationId == SharedSecLabelObjectIndexId ||
                relationId == TablespaceOidIndexId ||
                relationId == TablespaceNameIndexId ||
                relationId == DbRoleSettingDatidRolidIndexId)
index 325d4523e6b7d6053fadd9ba0ec5a34363deed44..2253ca83a744c261c1170edf6277f0e4aae66599 100644 (file)
@@ -283,7 +283,37 @@ FROM
        pg_seclabel l
        JOIN pg_namespace nsp ON l.classoid = nsp.tableoid AND l.objoid = nsp.oid
 WHERE
-       l.objsubid = 0;
+       l.objsubid = 0
+UNION ALL
+SELECT
+       l.objoid, l.classoid, 0::int4 AS objsubid,
+       'database'::text AS objtype,
+       NULL::oid AS objnamespace,
+       quote_ident(dat.datname) AS objname,
+       l.provider, l.label
+FROM
+       pg_shseclabel l
+       JOIN pg_database dat ON l.classoid = dat.tableoid AND l.objoid = dat.oid
+UNION ALL
+SELECT
+       l.objoid, l.classoid, 0::int4 AS objsubid,
+       'tablespace'::text AS objtype,
+       NULL::oid AS objnamespace,
+       quote_ident(spc.spcname) AS objname,
+       l.provider, l.label
+FROM
+       pg_shseclabel l
+       JOIN pg_tablespace spc ON l.classoid = spc.tableoid AND l.objoid = spc.oid
+UNION ALL
+SELECT
+       l.objoid, l.classoid, 0::int4 AS objsubid,
+       'role'::text AS objtype,
+       NULL::oid AS objnamespace,
+       quote_ident(rol.rolname) AS objname,
+       l.provider, l.label
+FROM
+       pg_shseclabel l
+       JOIN pg_authid rol ON l.classoid = rol.tableoid AND l.objoid = rol.oid;
 
 CREATE VIEW pg_settings AS
     SELECT * FROM pg_show_all_settings() AS A;
index f319eb539c319a386f589b370b6a8d9ccbfe216d..93240efbd715399b97ee1b73c3f2267fab9852a9 100644 (file)
@@ -39,6 +39,7 @@
 #include "catalog/pg_tablespace.h"
 #include "commands/comment.h"
 #include "commands/dbcommands.h"
+#include "commands/seclabel.h"
 #include "commands/tablespace.h"
 #include "mb/pg_wchar.h"
 #include "miscadmin.h"
@@ -822,9 +823,11 @@ dropdb(const char *dbname, bool missing_ok)
        ReleaseSysCache(tup);
 
        /*
-        * Delete any comments associated with the database.
+        * Delete any comments or security labels associated with
+        * the database.
         */
        DeleteSharedComments(db_id, DatabaseRelationId);
+       DeleteSharedSecurityLabel(db_id, DatabaseRelationId);
 
        /*
         * Remove settings associated with this database
index 6e7e9c2976164c1986c5eabf60e18cdfcea9ceb5..0041734b62b960a8823c024ba6414c64f14d2722 100644 (file)
@@ -16,6 +16,7 @@
 #include "catalog/indexing.h"
 #include "catalog/namespace.h"
 #include "catalog/pg_seclabel.h"
+#include "catalog/pg_shseclabel.h"
 #include "commands/seclabel.h"
 #include "miscadmin.h"
 #include "utils/acl.h"
@@ -24,6 +25,7 @@
 #include "utils/lsyscache.h"
 #include "utils/memutils.h"
 #include "utils/rel.h"
+#include "utils/syscache.h"
 #include "utils/tqual.h"
 
 typedef struct
@@ -135,8 +137,56 @@ ExecSecLabelStmt(SecLabelStmt *stmt)
 }
 
 /*
- * GetSecurityLabel returns the security label for a database object for a
- * given provider, or NULL if there is no such label.
+ * GetSharedSecurityLabel returns the security label for a shared object for
+ * a given provider, or NULL if there is no such label.
+ */
+static char *
+GetSharedSecurityLabel(const ObjectAddress *object, const char *provider)
+{
+       Relation        pg_shseclabel;
+       ScanKeyData keys[3];
+       SysScanDesc scan;
+       HeapTuple       tuple;
+       Datum           datum;
+       bool            isnull;
+       char       *seclabel = NULL;
+
+       ScanKeyInit(&keys[0],
+                               Anum_pg_shseclabel_objoid,
+                               BTEqualStrategyNumber, F_OIDEQ,
+                               ObjectIdGetDatum(object->objectId));
+       ScanKeyInit(&keys[1],
+                               Anum_pg_shseclabel_classoid,
+                               BTEqualStrategyNumber, F_OIDEQ,
+                               ObjectIdGetDatum(object->classId));
+       ScanKeyInit(&keys[2],
+                               Anum_pg_shseclabel_provider,
+                               BTEqualStrategyNumber, F_TEXTEQ,
+                               CStringGetTextDatum(provider));
+
+       pg_shseclabel = heap_open(SharedSecLabelRelationId, AccessShareLock);
+
+       scan = systable_beginscan(pg_shseclabel, SharedSecLabelObjectIndexId, true,
+                                                         SnapshotNow, 3, keys);
+
+       tuple = systable_getnext(scan);
+       if (HeapTupleIsValid(tuple))
+       {
+               datum = heap_getattr(tuple, Anum_pg_shseclabel_label,
+                                                        RelationGetDescr(pg_shseclabel), &isnull);
+               if (!isnull)
+                       seclabel = TextDatumGetCString(datum);
+       }
+       systable_endscan(scan);
+
+       heap_close(pg_shseclabel, AccessShareLock);
+
+       return seclabel;
+}
+
+/*
+ * GetSecurityLabel returns the security label for a shared or database object
+ * for a given provider, or NULL if there is no such label.
  */
 char *
 GetSecurityLabel(const ObjectAddress *object, const char *provider)
@@ -149,8 +199,11 @@ GetSecurityLabel(const ObjectAddress *object, const char *provider)
        bool            isnull;
        char       *seclabel = NULL;
 
-       Assert(!IsSharedRelation(object->classId));
+       /* Shared objects have their own security label catalog. */
+       if (IsSharedRelation(object->classId))
+               return GetSharedSecurityLabel(object, provider);
 
+       /* Must be an unshared object, so examine pg_seclabel. */
        ScanKeyInit(&keys[0],
                                Anum_pg_seclabel_objoid,
                                BTEqualStrategyNumber, F_OIDEQ,
@@ -188,6 +241,84 @@ GetSecurityLabel(const ObjectAddress *object, const char *provider)
        return seclabel;
 }
 
+/* 
+ * SetSharedSecurityLabel is a helper function of SetSecurityLabel to
+ * handle shared database objects.
+ */
+static void
+SetSharedSecurityLabel(const ObjectAddress *object,
+                                          const char *provider, const char *label)
+{
+       Relation        pg_shseclabel;
+       ScanKeyData     keys[4];
+       SysScanDesc     scan;
+       HeapTuple       oldtup;
+       HeapTuple       newtup = NULL;
+       Datum           values[Natts_pg_shseclabel];
+       bool            nulls[Natts_pg_shseclabel];
+       bool            replaces[Natts_pg_shseclabel];
+
+       /* Prepare to form or update a tuple, if necessary. */
+       memset(nulls, false, sizeof(nulls));
+       memset(replaces, false, sizeof(replaces));
+       values[Anum_pg_shseclabel_objoid - 1] = ObjectIdGetDatum(object->objectId);
+       values[Anum_pg_shseclabel_classoid - 1] = ObjectIdGetDatum(object->classId);
+       values[Anum_pg_shseclabel_provider - 1] = CStringGetTextDatum(provider);
+       if (label != NULL)
+               values[Anum_pg_shseclabel_label - 1] = CStringGetTextDatum(label);
+
+       /* Use the index to search for a matching old tuple */
+       ScanKeyInit(&keys[0],
+                               Anum_pg_shseclabel_objoid,
+                               BTEqualStrategyNumber, F_OIDEQ,
+                               ObjectIdGetDatum(object->objectId));
+       ScanKeyInit(&keys[1],
+                               Anum_pg_shseclabel_classoid,
+                               BTEqualStrategyNumber, F_OIDEQ,
+                               ObjectIdGetDatum(object->classId));
+       ScanKeyInit(&keys[2],
+                               Anum_pg_shseclabel_provider,
+                               BTEqualStrategyNumber, F_TEXTEQ,
+                               CStringGetTextDatum(provider));
+
+       pg_shseclabel = heap_open(SharedSecLabelRelationId, RowExclusiveLock);
+
+       scan = systable_beginscan(pg_shseclabel, SharedSecLabelObjectIndexId, true,
+                                                         SnapshotNow, 3, keys);
+
+       oldtup = systable_getnext(scan);
+       if (HeapTupleIsValid(oldtup))
+       {
+               if (label == NULL)
+                       simple_heap_delete(pg_shseclabel, &oldtup->t_self);
+               else
+               {
+                       replaces[Anum_pg_shseclabel_label - 1] = true;
+                       newtup = heap_modify_tuple(oldtup, RelationGetDescr(pg_shseclabel),
+                                                                          values, nulls, replaces);
+                       simple_heap_update(pg_shseclabel, &oldtup->t_self, newtup);
+               }
+       }
+       systable_endscan(scan);
+
+       /* If we didn't find an old tuple, insert a new one */
+       if (newtup == NULL && label != NULL)
+       {
+               newtup = heap_form_tuple(RelationGetDescr(pg_shseclabel),
+                                                                values, nulls);
+               simple_heap_insert(pg_shseclabel, newtup);
+       }
+
+       /* Update indexes, if necessary */
+       if (newtup != NULL)
+       {
+               CatalogUpdateIndexes(pg_shseclabel, newtup);
+               heap_freetuple(newtup);
+       }
+
+       heap_close(pg_shseclabel, RowExclusiveLock);
+}
+
 /*
  * SetSecurityLabel attempts to set the security label for the specified
  * provider on the specified object to the given value.  NULL means that any
@@ -206,8 +337,12 @@ SetSecurityLabel(const ObjectAddress *object,
        bool            nulls[Natts_pg_seclabel];
        bool            replaces[Natts_pg_seclabel];
 
-       /* Security labels on shared objects are not supported. */
-       Assert(!IsSharedRelation(object->classId));
+       /* Shared objects have their own security label catalog. */
+       if (IsSharedRelation(object->classId))
+       {
+               SetSharedSecurityLabel(object, provider, label);
+               return;
+       }
 
        /* Prepare to form or update a tuple, if necessary. */
        memset(nulls, false, sizeof(nulls));
@@ -275,6 +410,38 @@ SetSecurityLabel(const ObjectAddress *object,
        heap_close(pg_seclabel, RowExclusiveLock);
 }
 
+/*
+ * DeleteSharedSecurityLabel is a helper function of DeleteSecurityLabel
+ * to handle shared database objects.
+ */
+void
+DeleteSharedSecurityLabel(Oid objectId, Oid classId)
+{
+       Relation        pg_shseclabel;
+       ScanKeyData     skey[2];
+       SysScanDesc     scan;
+       HeapTuple       oldtup;
+
+       ScanKeyInit(&skey[0],
+                               Anum_pg_shseclabel_objoid,
+                               BTEqualStrategyNumber, F_OIDEQ,
+                               ObjectIdGetDatum(objectId));
+       ScanKeyInit(&skey[1],
+                               Anum_pg_shseclabel_classoid,
+                               BTEqualStrategyNumber, F_OIDEQ,
+                               ObjectIdGetDatum(classId));
+
+       pg_shseclabel = heap_open(SharedSecLabelRelationId, RowExclusiveLock);
+
+       scan = systable_beginscan(pg_shseclabel, SharedSecLabelObjectIndexId, true,
+                                                         SnapshotNow, 2, skey);
+       while (HeapTupleIsValid(oldtup = systable_getnext(scan)))
+               simple_heap_delete(pg_shseclabel, &oldtup->t_self);
+       systable_endscan(scan);
+
+       heap_close(pg_shseclabel, RowExclusiveLock);
+}
+
 /*
  * DeleteSecurityLabel removes all security labels for an object (and any
  * sub-objects, if applicable).
@@ -288,9 +455,13 @@ DeleteSecurityLabel(const ObjectAddress *object)
        HeapTuple       oldtup;
        int                     nkeys;
 
-       /* Security labels on shared objects are not supported. */
+       /* Shared objects have their own security label catalog. */
        if (IsSharedRelation(object->classId))
+       {
+               Assert(object->objectSubId == 0);
+               DeleteSharedSecurityLabel(object->objectId, object->classId);
                return;
+       }
 
        ScanKeyInit(&skey[0],
                                Anum_pg_seclabel_objoid,
index 3024dc4b6468ebf0c4b3eac1152f10550ab5bda7..09ecabb7723db392806504f6f2532127e7d5e0cc 100644 (file)
@@ -63,6 +63,7 @@
 #include "catalog/pg_tablespace.h"
 #include "commands/comment.h"
 #include "commands/defrem.h"
+#include "commands/seclabel.h"
 #include "commands/tablespace.h"
 #include "miscadmin.h"
 #include "postmaster/bgwriter.h"
@@ -448,9 +449,10 @@ DropTableSpace(DropTableSpaceStmt *stmt)
        heap_endscan(scandesc);
 
        /*
-        * Remove any comments on this tablespace.
+        * Remove any comments or security labels on this tablespace.
         */
        DeleteSharedComments(tablespaceoid, TableSpaceRelationId);
+       DeleteSharedSecurityLabel(tablespaceoid, TableSpaceRelationId);
 
        /*
         * Remove dependency on owner.
index 871bda7cc59a8e14d2cb721bf001121c7d51f965..0367b200fefbd65268325359dc01f708bd5dc3b4 100644 (file)
@@ -24,6 +24,7 @@
 #include "catalog/pg_db_role_setting.h"
 #include "commands/comment.h"
 #include "commands/dbcommands.h"
+#include "commands/seclabel.h"
 #include "commands/user.h"
 #include "libpq/md5.h"
 #include "miscadmin.h"
@@ -1000,9 +1001,10 @@ DropRole(DropRoleStmt *stmt)
                systable_endscan(sscan);
 
                /*
-                * Remove any comments on this role.
+                * Remove any comments or security labels on this role.
                 */
                DeleteSharedComments(roleid, AuthIdRelationId);
+               DeleteSharedSecurityLabel(roleid, AuthIdRelationId);
 
                /*
                 * Remove settings for this role.
index 72260320c384667e91808369ba749c6b6918384d..ac094aa5f3af93383c103d66246f45e5e9fdef73 100644 (file)
@@ -5068,11 +5068,14 @@ opt_provider:   FOR ColId_or_Sconst     { $$ = $2; }
 
 security_label_type:
                        COLUMN                                                          { $$ = OBJECT_COLUMN; }
+                       | DATABASE                                                      { $$ = OBJECT_DATABASE; }
                        | FOREIGN TABLE                                         { $$ = OBJECT_FOREIGN_TABLE; }
                        | SCHEMA                                                        { $$ = OBJECT_SCHEMA; }
                        | SEQUENCE                                                      { $$ = OBJECT_SEQUENCE; }
                        | TABLE                                                         { $$ = OBJECT_TABLE; }
                        | DOMAIN_P                                                      { $$ = OBJECT_TYPE; }
+                       | ROLE                                                          { $$ = OBJECT_ROLE; }
+                       | TABLESPACE                                            { $$ = OBJECT_TABLESPACE; }
                        | TYPE_P                                                        { $$ = OBJECT_TYPE; }
                        | VIEW                                                          { $$ = OBJECT_VIEW; }
                ;
index 6e5e625e6d0c27d9ce8f19e9e6fb36ba3d479f4f..acce7f82fa448a52987e2ea31598a0c3a91fb83e 100644 (file)
@@ -1166,3 +1166,47 @@ processSQLNamePattern(PGconn *conn, PQExpBuffer buf, const char *pattern,
        return added_clause;
 #undef WHEREAND
 }
+
+/*
+ * buildShSecLabelQuery
+ *
+ * Build a query to retrieve security labels for a shared object.
+ */
+void
+buildShSecLabelQuery(PGconn *conn, const char *catalog_name, uint32 objectId,
+                                        PQExpBuffer sql)
+{
+       appendPQExpBuffer(sql,
+                                         "SELECT provider, label FROM pg_catalog.pg_shseclabel "
+                                         "WHERE classoid = '%s'::pg_catalog.regclass AND "
+                                         "objoid = %u", catalog_name, objectId);
+}
+
+/*
+ * emitShSecLabels
+ *
+ * Format security label data retrieved by the query generated in
+ * buildShSecLabelQuery.
+ */
+void
+emitShSecLabels(PGconn *conn, PGresult *res, PQExpBuffer buffer,
+                               const char *target, const char *objname)
+{
+       int                     i;
+
+       for (i = 0; i < PQntuples(res); i++)
+    {
+               char   *provider = PQgetvalue(res, i, 0);
+               char   *label = PQgetvalue(res, i, 1);
+
+               /* must use fmtId result before calling it again */
+               appendPQExpBuffer(buffer,
+                                                 "SECURITY LABEL FOR %s ON %s",
+                                                 fmtId(provider), target);
+               appendPQExpBuffer(buffer,
+                                                 " %s IS ",
+                                                 fmtId(objname));
+               appendStringLiteralConn(buffer, label, conn);
+        appendPQExpBuffer(buffer, ";\n");
+       }
+}
index 44d90669b61655c51f44f363d33e057d2c1f088c..40bbc81ae8d8be606e68487593222f4aa1737ecc 100644 (file)
@@ -47,5 +47,9 @@ extern bool processSQLNamePattern(PGconn *conn, PQExpBuffer buf,
                                          bool have_where, bool force_escape,
                                          const char *schemavar, const char *namevar,
                                          const char *altnamevar, const char *visibilityrule);
+extern void buildShSecLabelQuery(PGconn *conn, const char *catalog_name,
+                                        uint32 objectId, PQExpBuffer sql);
+extern void emitShSecLabels(PGconn *conn, PGresult *res,
+                               PQExpBuffer buffer, const char *target, const char *objname);
 
 #endif   /* DUMPUTILS_H */
index 9e69b0fc5241e0ceedb304a9f62b9f56095f76da..f2ee57cabd373913fe9e5083275eab808087779d 100644 (file)
@@ -2048,6 +2048,24 @@ dumpDatabase(Archive *AH)
 
        PQclear(res);
 
+       /* Dump shared security label. */
+       if (!no_security_labels && g_fout->remoteVersion >= 90200)
+       {
+               PQExpBuffer seclabelQry = createPQExpBuffer();
+
+               buildShSecLabelQuery(g_conn, "pg_database", dbCatId.oid, seclabelQry);
+               res = PQexec(g_conn, seclabelQry->data);
+               check_sql_result(res, g_conn, seclabelQry->data, PGRES_TUPLES_OK);
+               resetPQExpBuffer(seclabelQry);
+               emitShSecLabels(g_conn, res, seclabelQry, "DATABASE", datname);
+               if (strlen(seclabelQry->data))
+                       ArchiveEntry(AH, dbCatId, createDumpId(), datname, NULL, NULL,
+                                                dba, false, "SECURITY LABEL", SECTION_NONE,
+                                                seclabelQry->data, "", NULL,
+                                                &dbDumpId, 1, NULL, NULL);
+               destroyPQExpBuffer(seclabelQry);
+       }
+
        destroyPQExpBuffer(dbQry);
        destroyPQExpBuffer(delQry);
        destroyPQExpBuffer(creaQry);
index b3ad2eac29b1b384ddaf6fb0b0947b35db3cce09..b5f64e8d68e0ef9a7585c20be85804581148bfd5 100644 (file)
@@ -52,6 +52,9 @@ static void dumpTimestamp(char *msg);
 static void doShellQuoting(PQExpBuffer buf, const char *str);
 
 static int     runPgDump(const char *dbname);
+static void buildShSecLabels(PGconn *conn, const char *catalog_name,
+                                                        uint32 objectId, PQExpBuffer buffer,
+                                                        const char *target, const char *objname);
 static PGconn *connectDatabase(const char *dbname, const char *pghost, const char *pgport,
          const char *pguser, enum trivalue prompt_password, bool fail_on_error);
 static PGresult *executeQuery(PGconn *conn, const char *query);
@@ -718,15 +721,15 @@ dumpRoles(PGconn *conn)
        for (i = 0; i < PQntuples(res); i++)
        {
                const char *rolename;
+               Oid                     auth_oid;
 
+               auth_oid = atooid(PQgetvalue(res, i, i_oid));
                rolename = PQgetvalue(res, i, i_rolname);
 
                resetPQExpBuffer(buf);
 
                if (binary_upgrade)
                {
-                       Oid                     auth_oid = atooid(PQgetvalue(res, i, i_oid));
-
                        appendPQExpBuffer(buf, "\n-- For binary upgrade, must preserve pg_authid.oid\n");
                        appendPQExpBuffer(buf,
                                                          "SELECT binary_upgrade.set_next_pg_authid_oid('%u'::pg_catalog.oid);\n\n",
@@ -796,6 +799,10 @@ dumpRoles(PGconn *conn)
                        appendPQExpBuffer(buf, ";\n");
                }
 
+               if (!no_security_labels && server_version >= 90200)
+                       buildShSecLabels(conn, "pg_authid", auth_oid,
+                                                        buf, "ROLE", rolename);
+
                fprintf(OPF, "%s", buf->data);
 
                if (server_version >= 70300)
@@ -981,7 +988,7 @@ dumpTablespaces(PGconn *conn)
         * pg_xxx)
         */
        if (server_version >= 90000)
-               res = executeQuery(conn, "SELECT spcname, "
+               res = executeQuery(conn, "SELECT oid, spcname, "
                                                 "pg_catalog.pg_get_userbyid(spcowner) AS spcowner, "
                                                   "spclocation, spcacl, "
                                                   "array_to_string(spcoptions, ', '),"
@@ -990,7 +997,7 @@ dumpTablespaces(PGconn *conn)
                                                   "WHERE spcname !~ '^pg_' "
                                                   "ORDER BY 1");
        else if (server_version >= 80200)
-               res = executeQuery(conn, "SELECT spcname, "
+               res = executeQuery(conn, "SELECT oid, spcname, "
                                                 "pg_catalog.pg_get_userbyid(spcowner) AS spcowner, "
                                                   "spclocation, spcacl, null, "
                                                "pg_catalog.shobj_description(oid, 'pg_tablespace') "
@@ -998,7 +1005,7 @@ dumpTablespaces(PGconn *conn)
                                                   "WHERE spcname !~ '^pg_' "
                                                   "ORDER BY 1");
        else
-               res = executeQuery(conn, "SELECT spcname, "
+               res = executeQuery(conn, "SELECT oid, spcname, "
                                                 "pg_catalog.pg_get_userbyid(spcowner) AS spcowner, "
                                                   "spclocation, spcacl, "
                                                   "null, null "
@@ -1012,12 +1019,13 @@ dumpTablespaces(PGconn *conn)
        for (i = 0; i < PQntuples(res); i++)
        {
                PQExpBuffer buf = createPQExpBuffer();
-               char       *spcname = PQgetvalue(res, i, 0);
-               char       *spcowner = PQgetvalue(res, i, 1);
-               char       *spclocation = PQgetvalue(res, i, 2);
-               char       *spcacl = PQgetvalue(res, i, 3);
-               char       *spcoptions = PQgetvalue(res, i, 4);
-               char       *spccomment = PQgetvalue(res, i, 5);
+               uint32          spcoid = atooid(PQgetvalue(res, i, 0));
+               char       *spcname = PQgetvalue(res, i, 1);
+               char       *spcowner = PQgetvalue(res, i, 2);
+               char       *spclocation = PQgetvalue(res, i, 3);
+               char       *spcacl = PQgetvalue(res, i, 4);
+               char       *spcoptions = PQgetvalue(res, i, 5);
+               char       *spccomment = PQgetvalue(res, i, 6);
                char       *fspcname;
 
                /* needed for buildACLCommands() */
@@ -1051,6 +1059,10 @@ dumpTablespaces(PGconn *conn)
                        appendPQExpBuffer(buf, ";\n");
                }
 
+               if (!no_security_labels && server_version >= 90200)
+                       buildShSecLabels(conn, "pg_tablespace", spcoid,
+                                                        buf, "TABLESPACE", fspcname);
+
                fprintf(OPF, "%s", buf->data);
 
                free(fspcname);
@@ -1615,6 +1627,28 @@ runPgDump(const char *dbname)
        return ret;
 }
 
+/*
+ * buildShSecLabels
+ *
+ * Build SECURITY LABEL command(s) for an shared object
+ *
+ * The caller has to provide object type and identifier to select security
+ * labels from pg_seclabels system view.
+ */
+static void
+buildShSecLabels(PGconn *conn, const char *catalog_name, uint32 objectId,
+                                PQExpBuffer buffer, const char *target, const char *objname)
+{
+       PQExpBuffer     sql = createPQExpBuffer();
+       PGresult   *res;
+
+       buildShSecLabelQuery(conn, catalog_name, objectId, sql);
+       res = executeQuery(conn, sql->data);
+       emitShSecLabels(conn, res, buffer, target, objname);
+
+       PQclear(res);
+       destroyPQExpBuffer(sql);
+}
 
 /*
  * Make a database connection with the given parameters.  An
index 57becb4fe5fb3443a249faa639fbcfeca16bf287..2fadf30792f0e5b1a13c564195a64e668c4b165d 100644 (file)
@@ -53,6 +53,6 @@
  */
 
 /*                                                     yyyymmddN */
-#define CATALOG_VERSION_NO     201107171
+#define CATALOG_VERSION_NO     201107201
 
 #endif
index 4118e64542430ee47788d30fb2914baf41910583..9a8e6ffc8a549ed405bea969f7e08f3984f0f24d 100644 (file)
@@ -294,6 +294,9 @@ DECLARE_UNIQUE_INDEX(pg_db_role_setting_databaseid_rol_index, 2965, on pg_db_rol
 DECLARE_UNIQUE_INDEX(pg_seclabel_object_index, 3597, on pg_seclabel using btree(objoid oid_ops, classoid oid_ops, objsubid int4_ops, provider text_ops));
 #define SecLabelObjectIndexId                          3597
 
+DECLARE_UNIQUE_INDEX(pg_shseclabel_object_index, 3593, on pg_shseclabel using btree(objoid oid_ops, classoid oid_ops, provider text_ops));
+#define SharedSecLabelObjectIndexId                    3593
+
 DECLARE_UNIQUE_INDEX(pg_extension_oid_index, 3080, on pg_extension using btree(oid oid_ops));
 #define ExtensionOidIndexId 3080
 
diff --git a/src/include/catalog/pg_shseclabel.h b/src/include/catalog/pg_shseclabel.h
new file mode 100644 (file)
index 0000000..8533eac
--- /dev/null
@@ -0,0 +1,41 @@
+/* -------------------------------------------------------------------------
+ *
+ * pg_shseclabel.h
+ *    definition of the system "security label" relation (pg_shseclabel)
+ *
+ * Portions Copyright (c) 1996-2011, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * -------------------------------------------------------------------------
+ */
+#ifndef PG_SHSECLABEL_H
+#define PG_SHSECLABEL_H
+
+#include "catalog/genbki.h"
+
+/* ----------------
+ *             pg_shseclabel definition. cpp turns this into
+ *             typedef struct FormData_pg_shseclabel
+ * ----------------
+ */
+#define SharedSecLabelRelationId               3592
+
+CATALOG(pg_shseclabel,3592) BKI_SHARED_RELATION BKI_WITHOUT_OIDS
+{
+       Oid                     objoid;         /* OID of the shared object itself */
+       Oid                     classoid;       /* OID of table containing the shared object */
+       text            provider;       /* name of label provider */
+       text            label;          /* security label of the object */
+} FormData_pg_shseclabel;
+
+/* ----------------
+ *             compiler constants for pg_shseclabel
+ * ----------------
+ */
+#define Natts_pg_shseclabel                            4
+#define Anum_pg_shseclabel_objoid              1
+#define Anum_pg_shseclabel_classoid            2
+#define Anum_pg_shseclabel_provider            3
+#define Anum_pg_shseclabel_label               4
+
+#endif /* PG_SHSECLABEL_H */
index 06ce602d7dcefa72246ef9c61d4621c2b2604e45..1a0282c8ca7c37b988974d1591e9ad23e79ee3e0 100644 (file)
@@ -21,6 +21,7 @@ extern char *GetSecurityLabel(const ObjectAddress *object,
 extern void SetSecurityLabel(const ObjectAddress *object,
                                 const char *provider, const char *label);
 extern void DeleteSecurityLabel(const ObjectAddress *object);
+extern void DeleteSharedSecurityLabel(Oid objectId, Oid classId);
 
 /*
  * Statement and ESP hook support
index 336df52db8cf33b5daae4372ca5d9c4fd8d64f2d..454e1f98e45e77a331adbc054007a1c502d6a519 100644 (file)
@@ -1276,8 +1276,8 @@ drop table cchild;
 -- Check that ruleutils are working
 --
 SELECT viewname, definition FROM pg_views WHERE schemaname <> 'information_schema' ORDER BY viewname;
-            viewname             |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              definition                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               
----------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+            viewname             |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   definition                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   
+---------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  iexit                           | SELECT ih.name, ih.thepath, interpt_pp(ih.thepath, r.thepath) AS exit FROM ihighway ih, ramp r WHERE (ih.thepath ## r.thepath);
  pg_available_extension_versions | SELECT e.name, e.version, (x.extname IS NOT NULL) AS installed, e.superuser, e.relocatable, e.schema, e.requires, e.comment FROM (pg_available_extension_versions() e(name, version, superuser, relocatable, schema, requires, comment) LEFT JOIN pg_extension x ON (((e.name = x.extname) AND (e.version = x.extversion))));
  pg_available_extensions         | SELECT e.name, e.default_version, x.extversion AS installed_version, e.comment FROM (pg_available_extensions() e(name, default_version, comment) LEFT JOIN pg_extension x ON ((e.name = x.extname)));
@@ -1289,7 +1289,7 @@ SELECT viewname, definition FROM pg_views WHERE schemaname <> 'information_schem
  pg_prepared_xacts               | SELECT p.transaction, p.gid, p.prepared, u.rolname AS owner, d.datname AS database FROM ((pg_prepared_xact() p(transaction, gid, prepared, ownerid, dbid) LEFT JOIN pg_authid u ON ((p.ownerid = u.oid))) LEFT JOIN pg_database d ON ((p.dbid = d.oid)));
  pg_roles                        | SELECT pg_authid.rolname, pg_authid.rolsuper, pg_authid.rolinherit, pg_authid.rolcreaterole, pg_authid.rolcreatedb, pg_authid.rolcatupdate, pg_authid.rolcanlogin, pg_authid.rolreplication, pg_authid.rolconnlimit, '********'::text AS rolpassword, pg_authid.rolvaliduntil, s.setconfig AS rolconfig, pg_authid.oid FROM (pg_authid LEFT JOIN pg_db_role_setting s ON (((pg_authid.oid = s.setrole) AND (s.setdatabase = (0)::oid))));
  pg_rules                        | SELECT n.nspname AS schemaname, c.relname AS tablename, r.rulename, pg_get_ruledef(r.oid) AS definition FROM ((pg_rewrite r JOIN pg_class c ON ((c.oid = r.ev_class))) LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) WHERE (r.rulename <> '_RETURN'::name);
- pg_seclabels                    | (((((SELECT l.objoid, l.classoid, l.objsubid, CASE WHEN (rel.relkind = 'r'::"char") THEN 'table'::text WHEN (rel.relkind = 'v'::"char") THEN 'view'::text WHEN (rel.relkind = 'S'::"char") THEN 'sequence'::text WHEN (rel.relkind = 'f'::"char") THEN 'foreign table'::text ELSE NULL::text END AS objtype, rel.relnamespace AS objnamespace, CASE WHEN pg_table_is_visible(rel.oid) THEN quote_ident((rel.relname)::text) ELSE ((quote_ident((nsp.nspname)::text) || '.'::text) || quote_ident((rel.relname)::text)) END AS objname, l.provider, l.label FROM ((pg_seclabel l JOIN pg_class rel ON (((l.classoid = rel.tableoid) AND (l.objoid = rel.oid)))) JOIN pg_namespace nsp ON ((rel.relnamespace = nsp.oid))) WHERE (l.objsubid = 0) UNION ALL SELECT l.objoid, l.classoid, l.objsubid, 'column'::text AS objtype, rel.relnamespace AS objnamespace, ((CASE WHEN pg_table_is_visible(rel.oid) THEN quote_ident((rel.relname)::text) ELSE ((quote_ident((nsp.nspname)::text) || '.'::text) || quote_ident((rel.relname)::text)) END || '.'::text) || (att.attname)::text) AS objname, l.provider, l.label FROM (((pg_seclabel l JOIN pg_class rel ON (((l.classoid = rel.tableoid) AND (l.objoid = rel.oid)))) JOIN pg_attribute att ON (((rel.oid = att.attrelid) AND (l.objsubid = att.attnum)))) JOIN pg_namespace nsp ON ((rel.relnamespace = nsp.oid))) WHERE (l.objsubid <> 0)) UNION ALL SELECT l.objoid, l.classoid, l.objsubid, CASE WHEN (pro.proisagg = true) THEN 'aggregate'::text WHEN (pro.proisagg = false) THEN 'function'::text ELSE NULL::text END AS objtype, pro.pronamespace AS objnamespace, (((CASE WHEN pg_function_is_visible(pro.oid) THEN quote_ident((pro.proname)::text) ELSE ((quote_ident((nsp.nspname)::text) || '.'::text) || quote_ident((pro.proname)::text)) END || '('::text) || pg_get_function_arguments(pro.oid)) || ')'::text) AS objname, l.provider, l.label FROM ((pg_seclabel l JOIN pg_proc pro ON (((l.classoid = pro.tableoid) AND (l.objoid = pro.oid)))) JOIN pg_namespace nsp ON ((pro.pronamespace = nsp.oid))) WHERE (l.objsubid = 0)) UNION ALL SELECT l.objoid, l.classoid, l.objsubid, CASE WHEN (typ.typtype = 'd'::"char") THEN 'domain'::text ELSE 'type'::text END AS objtype, typ.typnamespace AS objnamespace, CASE WHEN pg_type_is_visible(typ.oid) THEN quote_ident((typ.typname)::text) ELSE ((quote_ident((nsp.nspname)::text) || '.'::text) || quote_ident((typ.typname)::text)) END AS objname, l.provider, l.label FROM ((pg_seclabel l JOIN pg_type typ ON (((l.classoid = typ.tableoid) AND (l.objoid = typ.oid)))) JOIN pg_namespace nsp ON ((typ.typnamespace = nsp.oid))) WHERE (l.objsubid = 0)) UNION ALL SELECT l.objoid, l.classoid, l.objsubid, 'large object'::text AS objtype, NULL::oid AS objnamespace, (l.objoid)::text AS objname, l.provider, l.label FROM (pg_seclabel l JOIN pg_largeobject_metadata lom ON ((l.objoid = lom.oid))) WHERE ((l.classoid = ('pg_largeobject'::regclass)::oid) AND (l.objsubid = 0))) UNION ALL SELECT l.objoid, l.classoid, l.objsubid, 'language'::text AS objtype, NULL::oid AS objnamespace, quote_ident((lan.lanname)::text) AS objname, l.provider, l.label FROM (pg_seclabel l JOIN pg_language lan ON (((l.classoid = lan.tableoid) AND (l.objoid = lan.oid)))) WHERE (l.objsubid = 0)) UNION ALL SELECT l.objoid, l.classoid, l.objsubid, 'schema'::text AS objtype, nsp.oid AS objnamespace, quote_ident((nsp.nspname)::text) AS objname, l.provider, l.label FROM (pg_seclabel l JOIN pg_namespace nsp ON (((l.classoid = nsp.tableoid) AND (l.objoid = nsp.oid)))) WHERE (l.objsubid = 0);
+ pg_seclabels                    | ((((((((SELECT l.objoid, l.classoid, l.objsubid, CASE WHEN (rel.relkind = 'r'::"char") THEN 'table'::text WHEN (rel.relkind = 'v'::"char") THEN 'view'::text WHEN (rel.relkind = 'S'::"char") THEN 'sequence'::text WHEN (rel.relkind = 'f'::"char") THEN 'foreign table'::text ELSE NULL::text END AS objtype, rel.relnamespace AS objnamespace, CASE WHEN pg_table_is_visible(rel.oid) THEN quote_ident((rel.relname)::text) ELSE ((quote_ident((nsp.nspname)::text) || '.'::text) || quote_ident((rel.relname)::text)) END AS objname, l.provider, l.label FROM ((pg_seclabel l JOIN pg_class rel ON (((l.classoid = rel.tableoid) AND (l.objoid = rel.oid)))) JOIN pg_namespace nsp ON ((rel.relnamespace = nsp.oid))) WHERE (l.objsubid = 0) UNION ALL SELECT l.objoid, l.classoid, l.objsubid, 'column'::text AS objtype, rel.relnamespace AS objnamespace, ((CASE WHEN pg_table_is_visible(rel.oid) THEN quote_ident((rel.relname)::text) ELSE ((quote_ident((nsp.nspname)::text) || '.'::text) || quote_ident((rel.relname)::text)) END || '.'::text) || (att.attname)::text) AS objname, l.provider, l.label FROM (((pg_seclabel l JOIN pg_class rel ON (((l.classoid = rel.tableoid) AND (l.objoid = rel.oid)))) JOIN pg_attribute att ON (((rel.oid = att.attrelid) AND (l.objsubid = att.attnum)))) JOIN pg_namespace nsp ON ((rel.relnamespace = nsp.oid))) WHERE (l.objsubid <> 0)) UNION ALL SELECT l.objoid, l.classoid, l.objsubid, CASE WHEN (pro.proisagg = true) THEN 'aggregate'::text WHEN (pro.proisagg = false) THEN 'function'::text ELSE NULL::text END AS objtype, pro.pronamespace AS objnamespace, (((CASE WHEN pg_function_is_visible(pro.oid) THEN quote_ident((pro.proname)::text) ELSE ((quote_ident((nsp.nspname)::text) || '.'::text) || quote_ident((pro.proname)::text)) END || '('::text) || pg_get_function_arguments(pro.oid)) || ')'::text) AS objname, l.provider, l.label FROM ((pg_seclabel l JOIN pg_proc pro ON (((l.classoid = pro.tableoid) AND (l.objoid = pro.oid)))) JOIN pg_namespace nsp ON ((pro.pronamespace = nsp.oid))) WHERE (l.objsubid = 0)) UNION ALL SELECT l.objoid, l.classoid, l.objsubid, CASE WHEN (typ.typtype = 'd'::"char") THEN 'domain'::text ELSE 'type'::text END AS objtype, typ.typnamespace AS objnamespace, CASE WHEN pg_type_is_visible(typ.oid) THEN quote_ident((typ.typname)::text) ELSE ((quote_ident((nsp.nspname)::text) || '.'::text) || quote_ident((typ.typname)::text)) END AS objname, l.provider, l.label FROM ((pg_seclabel l JOIN pg_type typ ON (((l.classoid = typ.tableoid) AND (l.objoid = typ.oid)))) JOIN pg_namespace nsp ON ((typ.typnamespace = nsp.oid))) WHERE (l.objsubid = 0)) UNION ALL SELECT l.objoid, l.classoid, l.objsubid, 'large object'::text AS objtype, NULL::oid AS objnamespace, (l.objoid)::text AS objname, l.provider, l.label FROM (pg_seclabel l JOIN pg_largeobject_metadata lom ON ((l.objoid = lom.oid))) WHERE ((l.classoid = ('pg_largeobject'::regclass)::oid) AND (l.objsubid = 0))) UNION ALL SELECT l.objoid, l.classoid, l.objsubid, 'language'::text AS objtype, NULL::oid AS objnamespace, quote_ident((lan.lanname)::text) AS objname, l.provider, l.label FROM (pg_seclabel l JOIN pg_language lan ON (((l.classoid = lan.tableoid) AND (l.objoid = lan.oid)))) WHERE (l.objsubid = 0)) UNION ALL SELECT l.objoid, l.classoid, l.objsubid, 'schema'::text AS objtype, nsp.oid AS objnamespace, quote_ident((nsp.nspname)::text) AS objname, l.provider, l.label FROM (pg_seclabel l JOIN pg_namespace nsp ON (((l.classoid = nsp.tableoid) AND (l.objoid = nsp.oid)))) WHERE (l.objsubid = 0)) UNION ALL SELECT l.objoid, l.classoid, 0 AS objsubid, 'database'::text AS objtype, NULL::oid AS objnamespace, quote_ident((dat.datname)::text) AS objname, l.provider, l.label FROM (pg_shseclabel l JOIN pg_database dat ON (((l.classoid = dat.tableoid) AND (l.objoid = dat.oid))))) UNION ALL SELECT l.objoid, l.classoid, 0 AS objsubid, 'tablespace'::text AS objtype, NULL::oid AS objnamespace, quote_ident((spc.spcname)::text) AS objname, l.provider, l.label FROM (pg_shseclabel l JOIN pg_tablespace spc ON (((l.classoid = spc.tableoid) AND (l.objoid = spc.oid))))) UNION ALL SELECT l.objoid, l.classoid, 0 AS objsubid, 'role'::text AS objtype, NULL::oid AS objnamespace, quote_ident((rol.rolname)::text) AS objname, l.provider, l.label FROM (pg_shseclabel l JOIN pg_authid rol ON (((l.classoid = rol.tableoid) AND (l.objoid = rol.oid))));
  pg_settings                     | SELECT a.name, a.setting, a.unit, a.category, a.short_desc, a.extra_desc, a.context, a.vartype, a.source, a.min_val, a.max_val, a.enumvals, a.boot_val, a.reset_val, a.sourcefile, a.sourceline FROM pg_show_all_settings() a(name, setting, unit, category, short_desc, extra_desc, context, vartype, source, min_val, max_val, enumvals, boot_val, reset_val, sourcefile, sourceline);
  pg_shadow                       | SELECT pg_authid.rolname AS usename, pg_authid.oid AS usesysid, pg_authid.rolcreatedb AS usecreatedb, pg_authid.rolsuper AS usesuper, pg_authid.rolcatupdate AS usecatupd, pg_authid.rolreplication AS userepl, pg_authid.rolpassword AS passwd, (pg_authid.rolvaliduntil)::abstime AS valuntil, s.setconfig AS useconfig FROM (pg_authid LEFT JOIN pg_db_role_setting s ON (((pg_authid.oid = s.setrole) AND (s.setdatabase = (0)::oid)))) WHERE pg_authid.rolcanlogin;
  pg_stat_activity                | SELECT s.datid, d.datname, s.procpid, s.usesysid, u.rolname AS usename, s.application_name, s.client_addr, s.client_hostname, s.client_port, s.backend_start, s.xact_start, s.query_start, s.waiting, s.current_query FROM pg_database d, pg_stat_get_activity(NULL::integer) s(datid, procpid, usesysid, application_name, current_query, waiting, xact_start, query_start, backend_start, client_addr, client_hostname, client_port), pg_authid u WHERE ((s.datid = d.oid) AND (s.usesysid = u.oid));
index ab9e89178878d2925e7498bcaefe591afe2309fb..d42b0ea045bf89b7b8a4c56eded03d7a4848682b 100644 (file)
@@ -120,6 +120,7 @@ SELECT relname, relhasindex
  pg_seclabel             | t
  pg_shdepend             | t
  pg_shdescription        | t
+ pg_shseclabel           | t
  pg_statistic            | t
  pg_tablespace           | t
  pg_trigger              | t
@@ -157,7 +158,7 @@ SELECT relname, relhasindex
  timetz_tbl              | f
  tinterval_tbl           | f
  varchar_tbl             | f
-(146 rows)
+(147 rows)
 
 --
 -- another sanity check: every system catalog that has OIDs should have
index 810a721ca8f37dce04045f4a97011b3e25aaef1f..70771d75967e7a95ced5309c4766fe1c0b9cc92d 100644 (file)
@@ -12,7 +12,7 @@ DROP TABLE IF EXISTS seclabel_tbl1;
 DROP TABLE IF EXISTS seclabel_tbl2;
 DROP TABLE IF EXISTS seclabel_tbl3;
 
-CREATE USER seclabel_user1;
+CREATE USER seclabel_user1 WITH CREATEROLE;
 CREATE USER seclabel_user2;
 
 CREATE TABLE seclabel_tbl1 (a int, b text);
@@ -34,6 +34,11 @@ SECURITY LABEL FOR 'dummy' ON TABLE seclabel_tbl1 IS 'classified';           -- fail
 SECURITY LABEL ON TABLE seclabel_tbl1 IS '...invalid label...';                -- fail
 SECURITY LABEL ON TABLE seclabel_tbl3 IS 'unclassified';                       -- fail
 
+SECURITY LABEL ON ROLE seclabel_user1 IS 'classified';                 -- fail
+SECURITY LABEL FOR 'dummy' ON ROLE seclabel_user1 IS 'classified';             -- fail
+SECURITY LABEL ON ROLE seclabel_user1 IS '...invalid label...';                -- fail
+SECURITY LABEL ON ROLE seclabel_user3 IS 'unclassified';                       -- fail
+
 -- Load dummy external security provider
 LOAD '@libdir@/dummy_seclabel@DLSUFFIX@';
 
@@ -55,21 +60,38 @@ SET SESSION AUTHORIZATION seclabel_user2;
 SECURITY LABEL ON TABLE seclabel_tbl1 IS 'unclassified';               -- fail
 SECURITY LABEL ON TABLE seclabel_tbl2 IS 'classified';                 -- OK
 
+--
+-- Test for shared database object
+--
+SET SESSION AUTHORIZATION seclabel_user1;
+
+SECURITY LABEL ON ROLE seclabel_user1 IS 'classified';                 -- OK
+SECURITY LABEL ON ROLE seclabel_user1 IS '...invalid label...';        -- fail
+SECURITY LABEL FOR 'dummy' ON ROLE seclabel_user2 IS 'unclassified';   -- OK
+SECURITY LABEL FOR 'unknown_seclabel' ON ROLE seclabel_user1 IS 'unclassified';        -- fail
+SECURITY LABEL ON ROLE seclabel_user1 IS 'secret';     -- fail (not superuser)
+SECURITY LABEL ON ROLE seclabel_user3 IS 'unclassified';       -- fail (not found)
+
+SET SESSION AUTHORIZATION seclabel_user2;
+SECURITY LABEL ON ROLE seclabel_user2 IS 'unclassified';       -- fail (not privileged)
+
+RESET SESSION AUTHORIZATION;
+
+--
+-- Test for various types of object
+--
 RESET SESSION AUTHORIZATION;
 
 SECURITY LABEL ON TABLE seclabel_tbl1 IS 'top secret';                 -- OK
 SECURITY LABEL ON VIEW seclabel_view1 IS 'classified';                 -- OK
 SECURITY LABEL ON FUNCTION seclabel_four() IS 'classified';            -- OK
 SECURITY LABEL ON DOMAIN seclabel_domain IS 'classified';              -- OK
-SECURITY LABEL ON LANGUAGE plpgsql IS 'unclassified';                  -- OK
-SECURITY LABEL ON SCHEMA public IS 'unclassified';                             -- OK
+CREATE SCHEMA seclabel_test;
+SECURITY LABEL ON SCHEMA seclabel_test IS 'unclassified';              -- OK
 
 SELECT objtype, objname, provider, label FROM pg_seclabels
        ORDER BY objtype, objname;
 
-SECURITY LABEL ON LANGUAGE plpgsql IS NULL;                                            -- OK
-SECURITY LABEL ON SCHEMA public IS NULL;                                               -- OK
-
 -- clean up objects
 DROP FUNCTION seclabel_four();
 DROP DOMAIN seclabel_domain;
@@ -78,6 +100,7 @@ DROP TABLE seclabel_tbl1;
 DROP TABLE seclabel_tbl2;
 DROP USER seclabel_user1;
 DROP USER seclabel_user2;
+DROP SCHEMA seclabel_test;
 
 -- make sure we don't have any leftovers
 SELECT objtype, objname, provider, label FROM pg_seclabels
index 4bc803d694fae0f2971f5b5ce0b3e050b949402c..6994d19c2e8788a59324d5a9b32d0a703903b6ac 100644 (file)
@@ -8,7 +8,7 @@ DROP ROLE IF EXISTS seclabel_user2;
 DROP TABLE IF EXISTS seclabel_tbl1;
 DROP TABLE IF EXISTS seclabel_tbl2;
 DROP TABLE IF EXISTS seclabel_tbl3;
-CREATE USER seclabel_user1;
+CREATE USER seclabel_user1 WITH CREATEROLE;
 CREATE USER seclabel_user2;
 CREATE TABLE seclabel_tbl1 (a int, b text);
 CREATE TABLE seclabel_tbl2 (x int, y text);
@@ -29,6 +29,14 @@ SECURITY LABEL ON TABLE seclabel_tbl1 IS '...invalid label...';              -- fail
 ERROR:  no security label providers have been loaded
 SECURITY LABEL ON TABLE seclabel_tbl3 IS 'unclassified';                       -- fail
 ERROR:  no security label providers have been loaded
+SECURITY LABEL ON ROLE seclabel_user1 IS 'classified';                 -- fail
+ERROR:  no security label providers have been loaded
+SECURITY LABEL FOR 'dummy' ON ROLE seclabel_user1 IS 'classified';             -- fail
+ERROR:  security label provider "dummy" is not loaded
+SECURITY LABEL ON ROLE seclabel_user1 IS '...invalid label...';                -- fail
+ERROR:  no security label providers have been loaded
+SECURITY LABEL ON ROLE seclabel_user3 IS 'unclassified';                       -- fail
+ERROR:  no security label providers have been loaded
 -- Load dummy external security provider
 LOAD '@abs_builddir@/dummy_seclabel@DLSUFFIX@';
 --
@@ -52,13 +60,34 @@ SET SESSION AUTHORIZATION seclabel_user2;
 SECURITY LABEL ON TABLE seclabel_tbl1 IS 'unclassified';               -- fail
 ERROR:  must be owner of relation seclabel_tbl1
 SECURITY LABEL ON TABLE seclabel_tbl2 IS 'classified';                 -- OK
+--
+-- Test for shared database object
+--
+SET SESSION AUTHORIZATION seclabel_user1;
+SECURITY LABEL ON ROLE seclabel_user1 IS 'classified';                 -- OK
+SECURITY LABEL ON ROLE seclabel_user1 IS '...invalid label...';        -- fail
+ERROR:  '...invalid label...' is not a valid security label
+SECURITY LABEL FOR 'dummy' ON ROLE seclabel_user2 IS 'unclassified';   -- OK
+SECURITY LABEL FOR 'unknown_seclabel' ON ROLE seclabel_user1 IS 'unclassified';        -- fail
+ERROR:  security label provider "unknown_seclabel" is not loaded
+SECURITY LABEL ON ROLE seclabel_user1 IS 'secret';     -- fail (not superuser)
+ERROR:  only superuser can set 'secret' label
+SECURITY LABEL ON ROLE seclabel_user3 IS 'unclassified';       -- fail (not found)
+ERROR:  role "seclabel_user3" does not exist
+SET SESSION AUTHORIZATION seclabel_user2;
+SECURITY LABEL ON ROLE seclabel_user2 IS 'unclassified';       -- fail (not privileged)
+ERROR:  must have CREATEROLE privilege
+RESET SESSION AUTHORIZATION;
+--
+-- Test for various types of object
+--
 RESET SESSION AUTHORIZATION;
 SECURITY LABEL ON TABLE seclabel_tbl1 IS 'top secret';                 -- OK
 SECURITY LABEL ON VIEW seclabel_view1 IS 'classified';                 -- OK
 SECURITY LABEL ON FUNCTION seclabel_four() IS 'classified';            -- OK
 SECURITY LABEL ON DOMAIN seclabel_domain IS 'classified';              -- OK
-SECURITY LABEL ON LANGUAGE plpgsql IS 'unclassified';                  -- OK
-SECURITY LABEL ON SCHEMA public IS 'unclassified';                             -- OK
+CREATE SCHEMA seclabel_test;
+SECURITY LABEL ON SCHEMA seclabel_test IS 'unclassified';              -- OK
 SELECT objtype, objname, provider, label FROM pg_seclabels
        ORDER BY objtype, objname;
  objtype  |     objname     | provider |    label     
@@ -66,15 +95,14 @@ SELECT objtype, objname, provider, label FROM pg_seclabels
  column   | seclabel_tbl1.a | dummy    | unclassified
  domain   | seclabel_domain | dummy    | classified
  function | seclabel_four() | dummy    | classified
- language | plpgsql         | dummy    | unclassified
- schema   | public          | dummy    | unclassified
+ role     | seclabel_user1  | dummy    | classified
+ role     | seclabel_user2  | dummy    | unclassified
+ schema   | seclabel_test   | dummy    | unclassified
  table    | seclabel_tbl1   | dummy    | top secret
  table    | seclabel_tbl2   | dummy    | classified
  view     | seclabel_view1  | dummy    | classified
-(8 rows)
+(9 rows)
 
-SECURITY LABEL ON LANGUAGE plpgsql IS NULL;                                            -- OK
-SECURITY LABEL ON SCHEMA public IS NULL;                                               -- OK
 -- clean up objects
 DROP FUNCTION seclabel_four();
 DROP DOMAIN seclabel_domain;
@@ -83,6 +111,7 @@ DROP TABLE seclabel_tbl1;
 DROP TABLE seclabel_tbl2;
 DROP USER seclabel_user1;
 DROP USER seclabel_user2;
+DROP SCHEMA seclabel_test;
 -- make sure we don't have any leftovers
 SELECT objtype, objname, provider, label FROM pg_seclabels
        ORDER BY objtype, objname;