Header And Logo

PostgreSQL
| The world's most advanced open source database.

schema.c

Go to the documentation of this file.
00001 /* -------------------------------------------------------------------------
00002  *
00003  * contrib/sepgsql/schema.c
00004  *
00005  * Routines corresponding to schema objects
00006  *
00007  * Copyright (c) 2010-2013, PostgreSQL Global Development Group
00008  *
00009  * -------------------------------------------------------------------------
00010  */
00011 #include "postgres.h"
00012 
00013 #include "access/genam.h"
00014 #include "access/heapam.h"
00015 #include "access/htup_details.h"
00016 #include "access/sysattr.h"
00017 #include "catalog/dependency.h"
00018 #include "catalog/indexing.h"
00019 #include "catalog/pg_database.h"
00020 #include "catalog/pg_namespace.h"
00021 #include "commands/seclabel.h"
00022 #include "lib/stringinfo.h"
00023 #include "miscadmin.h"
00024 #include "utils/builtins.h"
00025 #include "utils/fmgroids.h"
00026 #include "utils/lsyscache.h"
00027 #include "utils/tqual.h"
00028 
00029 #include "sepgsql.h"
00030 
00031 /*
00032  * sepgsql_schema_post_create
00033  *
00034  * This routine assigns a default security label on a newly defined
00035  * schema.
00036  */
00037 void
00038 sepgsql_schema_post_create(Oid namespaceId)
00039 {
00040     Relation    rel;
00041     ScanKeyData skey;
00042     SysScanDesc sscan;
00043     HeapTuple   tuple;
00044     char       *tcontext;
00045     char       *ncontext;
00046     const char *nsp_name;
00047     ObjectAddress object;
00048     Form_pg_namespace nspForm;
00049     StringInfoData audit_name;
00050 
00051     /*
00052      * Compute a default security label when we create a new schema object
00053      * under the working database.
00054      *
00055      * XXX - uncoming version of libselinux supports to take object name to
00056      * handle special treatment on default security label; such as special
00057      * label on "pg_temp" schema.
00058      */
00059     rel = heap_open(NamespaceRelationId, AccessShareLock);
00060 
00061     ScanKeyInit(&skey,
00062                 ObjectIdAttributeNumber,
00063                 BTEqualStrategyNumber, F_OIDEQ,
00064                 ObjectIdGetDatum(namespaceId));
00065 
00066     sscan = systable_beginscan(rel, NamespaceOidIndexId, true,
00067                                SnapshotSelf, 1, &skey);
00068     tuple = systable_getnext(sscan);
00069     if (!HeapTupleIsValid(tuple))
00070         elog(ERROR, "catalog lookup failed for namespace %u", namespaceId);
00071 
00072     nspForm = (Form_pg_namespace) GETSTRUCT(tuple);
00073     nsp_name = NameStr(nspForm->nspname);
00074     if (strncmp(nsp_name, "pg_temp_", 8) == 0)
00075         nsp_name = "pg_temp";
00076     else if (strncmp(nsp_name, "pg_toast_temp_", 14) == 0)
00077         nsp_name = "pg_toast_temp";
00078 
00079     tcontext = sepgsql_get_label(DatabaseRelationId, MyDatabaseId, 0);
00080     ncontext = sepgsql_compute_create(sepgsql_get_client_label(),
00081                                       tcontext,
00082                                       SEPG_CLASS_DB_SCHEMA,
00083                                       nsp_name);
00084     /*
00085      * check db_schema:{create}
00086      */
00087     initStringInfo(&audit_name);
00088     appendStringInfo(&audit_name, "%s", quote_identifier(nsp_name));
00089     sepgsql_avc_check_perms_label(ncontext,
00090                                   SEPG_CLASS_DB_SCHEMA,
00091                                   SEPG_DB_SCHEMA__CREATE,
00092                                   audit_name.data,
00093                                   true);
00094     systable_endscan(sscan);
00095     heap_close(rel, AccessShareLock);
00096 
00097     /*
00098      * Assign the default security label on a new procedure
00099      */
00100     object.classId = NamespaceRelationId;
00101     object.objectId = namespaceId;
00102     object.objectSubId = 0;
00103     SetSecurityLabel(&object, SEPGSQL_LABEL_TAG, ncontext);
00104 
00105     pfree(ncontext);
00106     pfree(tcontext);
00107 }
00108 
00109 /*
00110  * sepgsql_schema_drop
00111  *
00112  * It checks privileges to drop the supplied schema object.
00113  */
00114 void
00115 sepgsql_schema_drop(Oid namespaceId)
00116 {
00117     ObjectAddress object;
00118     char       *audit_name;
00119 
00120     /*
00121      * check db_schema:{drop} permission
00122      */
00123     object.classId = NamespaceRelationId;
00124     object.objectId = namespaceId;
00125     object.objectSubId = 0;
00126     audit_name = getObjectIdentity(&object);
00127 
00128     sepgsql_avc_check_perms(&object,
00129                             SEPG_CLASS_DB_SCHEMA,
00130                             SEPG_DB_SCHEMA__DROP,
00131                             audit_name,
00132                             true);
00133     pfree(audit_name);
00134 }
00135 
00136 /*
00137  * sepgsql_schema_relabel
00138  *
00139  * It checks privileges to relabel the supplied schema
00140  * by the `seclabel'.
00141  */
00142 void
00143 sepgsql_schema_relabel(Oid namespaceId, const char *seclabel)
00144 {
00145     ObjectAddress object;
00146     char       *audit_name;
00147 
00148     object.classId = NamespaceRelationId;
00149     object.objectId = namespaceId;
00150     object.objectSubId = 0;
00151     audit_name = getObjectIdentity(&object);
00152 
00153     /*
00154      * check db_schema:{setattr relabelfrom} permission
00155      */
00156     sepgsql_avc_check_perms(&object,
00157                             SEPG_CLASS_DB_SCHEMA,
00158                             SEPG_DB_SCHEMA__SETATTR |
00159                             SEPG_DB_SCHEMA__RELABELFROM,
00160                             audit_name,
00161                             true);
00162 
00163     /*
00164      * check db_schema:{relabelto} permission
00165      */
00166     sepgsql_avc_check_perms_label(seclabel,
00167                                   SEPG_CLASS_DB_SCHEMA,
00168                                   SEPG_DB_SCHEMA__RELABELTO,
00169                                   audit_name,
00170                                   true);
00171     pfree(audit_name);
00172 }
00173 
00174 /*
00175  * sepgsql_schema_check_perms
00176  *
00177  * utility routine to check db_schema:{xxx} permissions
00178  */
00179 static bool
00180 check_schema_perms(Oid namespaceId, uint32 required, bool abort_on_violation)
00181 {
00182     ObjectAddress object;
00183     char       *audit_name;
00184     bool        result;
00185 
00186     object.classId = NamespaceRelationId;
00187     object.objectId = namespaceId;
00188     object.objectSubId = 0;
00189     audit_name = getObjectIdentity(&object);
00190 
00191     result = sepgsql_avc_check_perms(&object,
00192                                      SEPG_CLASS_DB_SCHEMA,
00193                                      required,
00194                                      audit_name,
00195                                      abort_on_violation);
00196     pfree(audit_name);
00197 
00198     return result;
00199 }
00200 
00201 /* db_schema:{setattr} permission */
00202 void
00203 sepgsql_schema_setattr(Oid namespaceId)
00204 {
00205     check_schema_perms(namespaceId, SEPG_DB_SCHEMA__SETATTR, true);
00206 }
00207 
00208 /* db_schema:{search} permission */
00209 bool
00210 sepgsql_schema_search(Oid namespaceId, bool abort_on_violation)
00211 {
00212     return check_schema_perms(namespaceId,
00213                               SEPG_DB_SCHEMA__SEARCH,
00214                               abort_on_violation);
00215 }
00216 
00217 void
00218 sepgsql_schema_add_name(Oid namespaceId)
00219 {
00220     check_schema_perms(namespaceId, SEPG_DB_SCHEMA__ADD_NAME, true);
00221 }
00222 
00223 void
00224 sepgsql_schema_remove_name(Oid namespaceId)
00225 {
00226     check_schema_perms(namespaceId, SEPG_DB_SCHEMA__REMOVE_NAME, true);
00227 }
00228 
00229 void
00230 sepgsql_schema_rename(Oid namespaceId)
00231 {
00232     check_schema_perms(namespaceId,
00233                        SEPG_DB_SCHEMA__ADD_NAME |
00234                        SEPG_DB_SCHEMA__REMOVE_NAME,
00235                        true);
00236 }