Header And Logo

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

proc.c

Go to the documentation of this file.
00001 /* -------------------------------------------------------------------------
00002  *
00003  * contrib/sepgsql/proc.c
00004  *
00005  * Routines corresponding to procedure 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_namespace.h"
00020 #include "catalog/pg_proc.h"
00021 #include "catalog/pg_type.h"
00022 #include "commands/seclabel.h"
00023 #include "lib/stringinfo.h"
00024 #include "utils/builtins.h"
00025 #include "utils/fmgroids.h"
00026 #include "utils/lsyscache.h"
00027 #include "utils/syscache.h"
00028 #include "utils/tqual.h"
00029 
00030 #include "sepgsql.h"
00031 
00032 /*
00033  * sepgsql_proc_post_create
00034  *
00035  * This routine assigns a default security label on a newly defined
00036  * procedure.
00037  */
00038 void
00039 sepgsql_proc_post_create(Oid functionId)
00040 {
00041     Relation    rel;
00042     ScanKeyData skey;
00043     SysScanDesc sscan;
00044     HeapTuple   tuple;
00045     char       *nsp_name;
00046     char       *scontext;
00047     char       *tcontext;
00048     char       *ncontext;
00049     uint32      required;
00050     int         i;
00051     StringInfoData audit_name;
00052     ObjectAddress object;
00053     Form_pg_proc proForm;
00054 
00055     /*
00056      * Fetch namespace of the new procedure. Because pg_proc entry is not
00057      * visible right now, we need to scan the catalog using SnapshotSelf.
00058      */
00059     rel = heap_open(ProcedureRelationId, AccessShareLock);
00060 
00061     ScanKeyInit(&skey,
00062                 ObjectIdAttributeNumber,
00063                 BTEqualStrategyNumber, F_OIDEQ,
00064                 ObjectIdGetDatum(functionId));
00065 
00066     sscan = systable_beginscan(rel, ProcedureOidIndexId, true,
00067                                SnapshotSelf, 1, &skey);
00068 
00069     tuple = systable_getnext(sscan);
00070     if (!HeapTupleIsValid(tuple))
00071         elog(ERROR, "catalog lookup failed for proc %u", functionId);
00072 
00073     proForm = (Form_pg_proc) GETSTRUCT(tuple);
00074 
00075     /*
00076      * check db_schema:{add_name} permission of the namespace
00077      */
00078     object.classId = NamespaceRelationId;
00079     object.objectId = proForm->pronamespace;
00080     object.objectSubId = 0;
00081     sepgsql_avc_check_perms(&object,
00082                             SEPG_CLASS_DB_SCHEMA,
00083                             SEPG_DB_SCHEMA__ADD_NAME,
00084                             getObjectIdentity(&object),
00085                             true);
00086 
00087     /*
00088      * XXX - db_language:{implement} also should be checked here
00089      */
00090 
00091 
00092     /*
00093      * Compute a default security label when we create a new procedure object
00094      * under the specified namespace.
00095      */
00096     scontext = sepgsql_get_client_label();
00097     tcontext = sepgsql_get_label(NamespaceRelationId,
00098                                  proForm->pronamespace, 0);
00099     ncontext = sepgsql_compute_create(scontext, tcontext,
00100                                       SEPG_CLASS_DB_PROCEDURE,
00101                                       NameStr(proForm->proname));
00102 
00103     /*
00104      * check db_procedure:{create (install)} permission
00105      */
00106     initStringInfo(&audit_name);
00107     nsp_name = get_namespace_name(proForm->pronamespace);
00108     appendStringInfo(&audit_name, "%s(",
00109             quote_qualified_identifier(nsp_name, NameStr(proForm->proname)));
00110     for (i = 0; i < proForm->pronargs; i++)
00111     {
00112         if (i > 0)
00113             appendStringInfoChar(&audit_name, ',');
00114 
00115         object.classId = TypeRelationId;
00116         object.objectId = proForm->proargtypes.values[i];
00117         object.objectSubId = 0;
00118         appendStringInfoString(&audit_name, getObjectIdentity(&object));
00119     }
00120     appendStringInfoChar(&audit_name, ')');
00121 
00122     required = SEPG_DB_PROCEDURE__CREATE;
00123     if (proForm->proleakproof)
00124         required |= SEPG_DB_PROCEDURE__INSTALL;
00125 
00126     sepgsql_avc_check_perms_label(ncontext,
00127                                   SEPG_CLASS_DB_PROCEDURE,
00128                                   required,
00129                                   audit_name.data,
00130                                   true);
00131 
00132     /*
00133      * Assign the default security label on a new procedure
00134      */
00135     object.classId = ProcedureRelationId;
00136     object.objectId = functionId;
00137     object.objectSubId = 0;
00138     SetSecurityLabel(&object, SEPGSQL_LABEL_TAG, ncontext);
00139 
00140     /*
00141      * Cleanup
00142      */
00143     systable_endscan(sscan);
00144     heap_close(rel, AccessShareLock);
00145 
00146     pfree(audit_name.data);
00147     pfree(tcontext);
00148     pfree(ncontext);
00149 }
00150 
00151 /*
00152  * sepgsql_proc_drop
00153  *
00154  * It checks privileges to drop the supplied function.
00155  */
00156 void
00157 sepgsql_proc_drop(Oid functionId)
00158 {
00159     ObjectAddress object;
00160     char       *audit_name;
00161 
00162     /*
00163      * check db_schema:{remove_name} permission
00164      */
00165     object.classId = NamespaceRelationId;
00166     object.objectId = get_func_namespace(functionId);
00167     object.objectSubId = 0;
00168     audit_name = getObjectIdentity(&object);
00169 
00170     sepgsql_avc_check_perms(&object,
00171                             SEPG_CLASS_DB_SCHEMA,
00172                             SEPG_DB_SCHEMA__REMOVE_NAME,
00173                             audit_name,
00174                             true);
00175     pfree(audit_name);
00176 
00177     /*
00178      * check db_procedure:{drop} permission
00179      */
00180     object.classId = ProcedureRelationId;
00181     object.objectId = functionId;
00182     object.objectSubId = 0;
00183     audit_name = getObjectIdentity(&object);
00184 
00185     sepgsql_avc_check_perms(&object,
00186                             SEPG_CLASS_DB_PROCEDURE,
00187                             SEPG_DB_PROCEDURE__DROP,
00188                             audit_name,
00189                             true);
00190     pfree(audit_name);
00191 }
00192 
00193 /*
00194  * sepgsql_proc_relabel
00195  *
00196  * It checks privileges to relabel the supplied function
00197  * by the `seclabel'.
00198  */
00199 void
00200 sepgsql_proc_relabel(Oid functionId, const char *seclabel)
00201 {
00202     ObjectAddress object;
00203     char       *audit_name;
00204 
00205     object.classId = ProcedureRelationId;
00206     object.objectId = functionId;
00207     object.objectSubId = 0;
00208     audit_name = getObjectIdentity(&object);
00209 
00210     /*
00211      * check db_procedure:{setattr relabelfrom} permission
00212      */
00213     sepgsql_avc_check_perms(&object,
00214                             SEPG_CLASS_DB_PROCEDURE,
00215                             SEPG_DB_PROCEDURE__SETATTR |
00216                             SEPG_DB_PROCEDURE__RELABELFROM,
00217                             audit_name,
00218                             true);
00219 
00220     /*
00221      * check db_procedure:{relabelto} permission
00222      */
00223     sepgsql_avc_check_perms_label(seclabel,
00224                                   SEPG_CLASS_DB_PROCEDURE,
00225                                   SEPG_DB_PROCEDURE__RELABELTO,
00226                                   audit_name,
00227                                   true);
00228     pfree(audit_name);
00229 }
00230 
00231 /*
00232  * sepgsql_proc_setattr
00233  *
00234  * It checks privileges to alter the supplied function.
00235  */
00236 void
00237 sepgsql_proc_setattr(Oid functionId)
00238 {
00239     Relation        rel;
00240     ScanKeyData     skey;
00241     SysScanDesc     sscan;
00242     HeapTuple       oldtup;
00243     HeapTuple       newtup;
00244     Form_pg_proc    oldform;
00245     Form_pg_proc    newform;
00246     uint32          required;
00247     ObjectAddress   object;
00248     char           *audit_name;
00249 
00250     /*
00251      * Fetch newer catalog
00252      */
00253     rel = heap_open(ProcedureRelationId, AccessShareLock);
00254 
00255     ScanKeyInit(&skey,
00256                 ObjectIdAttributeNumber,
00257                 BTEqualStrategyNumber, F_OIDEQ,
00258                 ObjectIdGetDatum(functionId));
00259 
00260     sscan = systable_beginscan(rel, ProcedureOidIndexId, true,
00261                                SnapshotSelf, 1, &skey);
00262     newtup = systable_getnext(sscan);
00263     if (!HeapTupleIsValid(newtup))
00264         elog(ERROR, "catalog lookup failed for function %u", functionId);
00265     newform = (Form_pg_proc) GETSTRUCT(newtup);
00266 
00267     /*
00268      * Fetch older catalog
00269      */
00270     oldtup = SearchSysCache1(PROCOID, ObjectIdGetDatum(functionId));
00271     if (!HeapTupleIsValid(oldtup))
00272         elog(ERROR, "cache lookup failed for function %u", functionId);
00273     oldform = (Form_pg_proc) GETSTRUCT(oldtup);
00274 
00275     /*
00276      * Does this ALTER command takes operation to namespace?
00277      */
00278     if (newform->pronamespace != oldform->pronamespace)
00279     {
00280         sepgsql_schema_remove_name(oldform->pronamespace);
00281         sepgsql_schema_add_name(oldform->pronamespace);
00282     }
00283     if (strcmp(NameStr(newform->proname), NameStr(oldform->proname)) != 0)
00284         sepgsql_schema_rename(oldform->pronamespace);
00285 
00286     /*
00287      * check db_procedure:{setattr (install)} permission
00288      */
00289     required = SEPG_DB_PROCEDURE__SETATTR;
00290     if (!oldform->proleakproof && newform->proleakproof)
00291         required |= SEPG_DB_PROCEDURE__INSTALL;
00292 
00293     object.classId = ProcedureRelationId;
00294     object.objectId = functionId;
00295     object.objectSubId = 0;
00296     audit_name = getObjectIdentity(&object);
00297 
00298     sepgsql_avc_check_perms(&object,
00299                             SEPG_CLASS_DB_PROCEDURE,
00300                             required,
00301                             audit_name,
00302                             true);
00303     /* cleanups */
00304     pfree(audit_name);
00305 
00306     ReleaseSysCache(oldtup);
00307     systable_endscan(sscan);
00308     heap_close(rel, AccessShareLock);
00309 }
00310 
00311 /*
00312  * sepgsql_proc_execute
00313  *
00314  * It checks privileges to execute the supplied function
00315  */
00316 void
00317 sepgsql_proc_execute(Oid functionId)
00318 {
00319     ObjectAddress object;
00320     char       *audit_name;
00321 
00322     /*
00323      * check db_procedure:{execute} permission
00324      */
00325     object.classId = ProcedureRelationId;
00326     object.objectId = functionId;
00327     object.objectSubId = 0;
00328     audit_name = getObjectIdentity(&object);
00329     sepgsql_avc_check_perms(&object,
00330                             SEPG_CLASS_DB_PROCEDURE,
00331                             SEPG_DB_PROCEDURE__EXECUTE,
00332                             audit_name,
00333                             true);
00334     pfree(audit_name);
00335 }