You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

proc.c 7.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335
  1. /* -------------------------------------------------------------------------
  2. *
  3. * contrib/sepgsql/proc.c
  4. *
  5. * Routines corresponding to procedure objects
  6. *
  7. * Copyright (c) 2010-2019, PostgreSQL Global Development Group
  8. *
  9. * -------------------------------------------------------------------------
  10. */
  11. #include "postgres.h"
  12. #include "access/genam.h"
  13. #include "access/heapam.h"
  14. #include "access/htup_details.h"
  15. #include "access/sysattr.h"
  16. #include "catalog/dependency.h"
  17. #include "catalog/indexing.h"
  18. #include "catalog/pg_namespace.h"
  19. #include "catalog/pg_proc.h"
  20. #include "catalog/pg_type.h"
  21. #include "commands/seclabel.h"
  22. #include "lib/stringinfo.h"
  23. #include "utils/builtins.h"
  24. #include "utils/fmgroids.h"
  25. #include "utils/lsyscache.h"
  26. #include "utils/syscache.h"
  27. #include "utils/tqual.h"
  28. #include "sepgsql.h"
  29. /*
  30. * sepgsql_proc_post_create
  31. *
  32. * This routine assigns a default security label on a newly defined
  33. * procedure.
  34. */
  35. void
  36. sepgsql_proc_post_create(Oid functionId)
  37. {
  38. Relation rel;
  39. ScanKeyData skey;
  40. SysScanDesc sscan;
  41. HeapTuple tuple;
  42. char *nsp_name;
  43. char *scontext;
  44. char *tcontext;
  45. char *ncontext;
  46. uint32 required;
  47. int i;
  48. StringInfoData audit_name;
  49. ObjectAddress object;
  50. Form_pg_proc proForm;
  51. /*
  52. * Fetch namespace of the new procedure. Because pg_proc entry is not
  53. * visible right now, we need to scan the catalog using SnapshotSelf.
  54. */
  55. rel = heap_open(ProcedureRelationId, AccessShareLock);
  56. ScanKeyInit(&skey,
  57. Anum_pg_proc_oid,
  58. BTEqualStrategyNumber, F_OIDEQ,
  59. ObjectIdGetDatum(functionId));
  60. sscan = systable_beginscan(rel, ProcedureOidIndexId, true,
  61. SnapshotSelf, 1, &skey);
  62. tuple = systable_getnext(sscan);
  63. if (!HeapTupleIsValid(tuple))
  64. elog(ERROR, "could not find tuple for function %u", functionId);
  65. proForm = (Form_pg_proc) GETSTRUCT(tuple);
  66. /*
  67. * check db_schema:{add_name} permission of the namespace
  68. */
  69. object.classId = NamespaceRelationId;
  70. object.objectId = proForm->pronamespace;
  71. object.objectSubId = 0;
  72. sepgsql_avc_check_perms(&object,
  73. SEPG_CLASS_DB_SCHEMA,
  74. SEPG_DB_SCHEMA__ADD_NAME,
  75. getObjectIdentity(&object),
  76. true);
  77. /*
  78. * XXX - db_language:{implement} also should be checked here
  79. */
  80. /*
  81. * Compute a default security label when we create a new procedure object
  82. * under the specified namespace.
  83. */
  84. scontext = sepgsql_get_client_label();
  85. tcontext = sepgsql_get_label(NamespaceRelationId,
  86. proForm->pronamespace, 0);
  87. ncontext = sepgsql_compute_create(scontext, tcontext,
  88. SEPG_CLASS_DB_PROCEDURE,
  89. NameStr(proForm->proname));
  90. /*
  91. * check db_procedure:{create (install)} permission
  92. */
  93. initStringInfo(&audit_name);
  94. nsp_name = get_namespace_name(proForm->pronamespace);
  95. appendStringInfo(&audit_name, "%s(",
  96. quote_qualified_identifier(nsp_name, NameStr(proForm->proname)));
  97. for (i = 0; i < proForm->pronargs; i++)
  98. {
  99. if (i > 0)
  100. appendStringInfoChar(&audit_name, ',');
  101. object.classId = TypeRelationId;
  102. object.objectId = proForm->proargtypes.values[i];
  103. object.objectSubId = 0;
  104. appendStringInfoString(&audit_name, getObjectIdentity(&object));
  105. }
  106. appendStringInfoChar(&audit_name, ')');
  107. required = SEPG_DB_PROCEDURE__CREATE;
  108. if (proForm->proleakproof)
  109. required |= SEPG_DB_PROCEDURE__INSTALL;
  110. sepgsql_avc_check_perms_label(ncontext,
  111. SEPG_CLASS_DB_PROCEDURE,
  112. required,
  113. audit_name.data,
  114. true);
  115. /*
  116. * Assign the default security label on a new procedure
  117. */
  118. object.classId = ProcedureRelationId;
  119. object.objectId = functionId;
  120. object.objectSubId = 0;
  121. SetSecurityLabel(&object, SEPGSQL_LABEL_TAG, ncontext);
  122. /*
  123. * Cleanup
  124. */
  125. systable_endscan(sscan);
  126. heap_close(rel, AccessShareLock);
  127. pfree(audit_name.data);
  128. pfree(tcontext);
  129. pfree(ncontext);
  130. }
  131. /*
  132. * sepgsql_proc_drop
  133. *
  134. * It checks privileges to drop the supplied function.
  135. */
  136. void
  137. sepgsql_proc_drop(Oid functionId)
  138. {
  139. ObjectAddress object;
  140. char *audit_name;
  141. /*
  142. * check db_schema:{remove_name} permission
  143. */
  144. object.classId = NamespaceRelationId;
  145. object.objectId = get_func_namespace(functionId);
  146. object.objectSubId = 0;
  147. audit_name = getObjectIdentity(&object);
  148. sepgsql_avc_check_perms(&object,
  149. SEPG_CLASS_DB_SCHEMA,
  150. SEPG_DB_SCHEMA__REMOVE_NAME,
  151. audit_name,
  152. true);
  153. pfree(audit_name);
  154. /*
  155. * check db_procedure:{drop} permission
  156. */
  157. object.classId = ProcedureRelationId;
  158. object.objectId = functionId;
  159. object.objectSubId = 0;
  160. audit_name = getObjectIdentity(&object);
  161. sepgsql_avc_check_perms(&object,
  162. SEPG_CLASS_DB_PROCEDURE,
  163. SEPG_DB_PROCEDURE__DROP,
  164. audit_name,
  165. true);
  166. pfree(audit_name);
  167. }
  168. /*
  169. * sepgsql_proc_relabel
  170. *
  171. * It checks privileges to relabel the supplied function
  172. * by the `seclabel'.
  173. */
  174. void
  175. sepgsql_proc_relabel(Oid functionId, const char *seclabel)
  176. {
  177. ObjectAddress object;
  178. char *audit_name;
  179. object.classId = ProcedureRelationId;
  180. object.objectId = functionId;
  181. object.objectSubId = 0;
  182. audit_name = getObjectIdentity(&object);
  183. /*
  184. * check db_procedure:{setattr relabelfrom} permission
  185. */
  186. sepgsql_avc_check_perms(&object,
  187. SEPG_CLASS_DB_PROCEDURE,
  188. SEPG_DB_PROCEDURE__SETATTR |
  189. SEPG_DB_PROCEDURE__RELABELFROM,
  190. audit_name,
  191. true);
  192. /*
  193. * check db_procedure:{relabelto} permission
  194. */
  195. sepgsql_avc_check_perms_label(seclabel,
  196. SEPG_CLASS_DB_PROCEDURE,
  197. SEPG_DB_PROCEDURE__RELABELTO,
  198. audit_name,
  199. true);
  200. pfree(audit_name);
  201. }
  202. /*
  203. * sepgsql_proc_setattr
  204. *
  205. * It checks privileges to alter the supplied function.
  206. */
  207. void
  208. sepgsql_proc_setattr(Oid functionId)
  209. {
  210. Relation rel;
  211. ScanKeyData skey;
  212. SysScanDesc sscan;
  213. HeapTuple oldtup;
  214. HeapTuple newtup;
  215. Form_pg_proc oldform;
  216. Form_pg_proc newform;
  217. uint32 required;
  218. ObjectAddress object;
  219. char *audit_name;
  220. /*
  221. * Fetch newer catalog
  222. */
  223. rel = heap_open(ProcedureRelationId, AccessShareLock);
  224. ScanKeyInit(&skey,
  225. Anum_pg_proc_oid,
  226. BTEqualStrategyNumber, F_OIDEQ,
  227. ObjectIdGetDatum(functionId));
  228. sscan = systable_beginscan(rel, ProcedureOidIndexId, true,
  229. SnapshotSelf, 1, &skey);
  230. newtup = systable_getnext(sscan);
  231. if (!HeapTupleIsValid(newtup))
  232. elog(ERROR, "could not find tuple for function %u", functionId);
  233. newform = (Form_pg_proc) GETSTRUCT(newtup);
  234. /*
  235. * Fetch older catalog
  236. */
  237. oldtup = SearchSysCache1(PROCOID, ObjectIdGetDatum(functionId));
  238. if (!HeapTupleIsValid(oldtup))
  239. elog(ERROR, "cache lookup failed for function %u", functionId);
  240. oldform = (Form_pg_proc) GETSTRUCT(oldtup);
  241. /*
  242. * Does this ALTER command takes operation to namespace?
  243. */
  244. if (newform->pronamespace != oldform->pronamespace)
  245. {
  246. sepgsql_schema_remove_name(oldform->pronamespace);
  247. sepgsql_schema_add_name(oldform->pronamespace);
  248. }
  249. if (strcmp(NameStr(newform->proname), NameStr(oldform->proname)) != 0)
  250. sepgsql_schema_rename(oldform->pronamespace);
  251. /*
  252. * check db_procedure:{setattr (install)} permission
  253. */
  254. required = SEPG_DB_PROCEDURE__SETATTR;
  255. if (!oldform->proleakproof && newform->proleakproof)
  256. required |= SEPG_DB_PROCEDURE__INSTALL;
  257. object.classId = ProcedureRelationId;
  258. object.objectId = functionId;
  259. object.objectSubId = 0;
  260. audit_name = getObjectIdentity(&object);
  261. sepgsql_avc_check_perms(&object,
  262. SEPG_CLASS_DB_PROCEDURE,
  263. required,
  264. audit_name,
  265. true);
  266. /* cleanups */
  267. pfree(audit_name);
  268. ReleaseSysCache(oldtup);
  269. systable_endscan(sscan);
  270. heap_close(rel, AccessShareLock);
  271. }
  272. /*
  273. * sepgsql_proc_execute
  274. *
  275. * It checks privileges to execute the supplied function
  276. */
  277. void
  278. sepgsql_proc_execute(Oid functionId)
  279. {
  280. ObjectAddress object;
  281. char *audit_name;
  282. /*
  283. * check db_procedure:{execute} permission
  284. */
  285. object.classId = ProcedureRelationId;
  286. object.objectId = functionId;
  287. object.objectSubId = 0;
  288. audit_name = getObjectIdentity(&object);
  289. sepgsql_avc_check_perms(&object,
  290. SEPG_CLASS_DB_PROCEDURE,
  291. SEPG_DB_PROCEDURE__EXECUTE,
  292. audit_name,
  293. true);
  294. pfree(audit_name);
  295. }