Veil2
Postgres extension for VPD implementations
veil2.c File Reference

Provides callable veil2 functions. These are written in C for performance and to ensure that they cannot be easily subverted. More...

#include "postgres.h"
#include "funcapi.h"
#include "catalog/pg_type.h"
#include "access/xact.h"
#include "executor/spi.h"
#include "utils/builtins.h"
#include "veil2.h"
Include dependency graph for veil2.c:

Go to the source code of this file.

Data Structures

struct  ContextPrivs
 
struct  SessionPrivs
 

Macros

#define CONTEXT_PRIVS_INCREMENT   16
 
#define CONTEXT_PRIVS_SIZE(elems)
 

Functions

static void findContext (int *p_idx, int scope_type, int scope)
 
static bool checkContext (int *p_idx, int scope_type, int scope, int priv)
 
static void freeContextPrivs (ContextPrivs *cp)
 
static void clear_session_privs ()
 
static SessionPrivsextendSessionPrivs (SessionPrivs *session_privs)
 
static void add_scope_privs (int scope_type, int scope, Bitmap *privs)
 
static bool fetch_scope_privs (HeapTuple tuple, TupleDesc tupdesc, void *p_result)
 
static void do_load_session_privs ()
 
static void load_privs ()
 
static bool error_if_no_session ()
 
static bool fetch_2ints (HeapTuple tuple, TupleDesc tupdesc, void *p_result)
 
static void create_temp_tables ()
 
static void truncate_temp_tables (bool clear_context)
 
Datum veil2_session_ready (FunctionCallInfo fcinfo)
 
static void do_reset_session (bool clear_context)
 
Datum veil2_reset_session (FunctionCallInfo fcinfo)
 
Datum veil2_reset_session_privs (FunctionCallInfo fcinfo)
 
Datum veil2_true (FunctionCallInfo fcinfo)
 
static bool checkSessionReady ()
 
Datum veil2_i_have_global_priv (FunctionCallInfo fcinfo)
 
Datum veil2_i_have_personal_priv (FunctionCallInfo fcinfo)
 
Datum veil2_i_have_priv_in_scope (FunctionCallInfo fcinfo)
 
Datum veil2_i_have_priv_in_scope_or_global (FunctionCallInfo fcinfo)
 
Datum veil2_i_have_priv_in_superior_scope (FunctionCallInfo fcinfo)
 
Datum veil2_i_have_priv_in_scope_or_superior (FunctionCallInfo fcinfo)
 
Datum veil2_i_have_priv_in_scope_or_superior_or_global (FunctionCallInfo fcinfo)
 
Datum veil2_result_counts (FunctionCallInfo fcinfo)
 
static text * textfromstr (char *in)
 
Datum veil2_docpath (FunctionCallInfo fcinfo)
 
Datum veil2_datapath (FunctionCallInfo fcinfo)
 

Variables

static bool session_ready = ((bool) 0)
 
static int result_counts [] = {0, 0}
 
static SessionPrivssession_privs = ((void *) 0)
 
static bool session_privs_loaded = ((bool) 0)
 

Detailed Description

Provides callable veil2 functions. These are written in C for performance and to ensure that they cannot be easily subverted.

Author: Marc Munro
Copyright (c) 2020 Marc Munro
License: GPL V3

Definition in file veil2.c.

Macro Definition Documentation

◆ CONTEXT_PRIVS_INCREMENT

#define CONTEXT_PRIVS_INCREMENT   16

How many ContextPrivs entries a SessionPrivs structure will be created with/extended by.

Definition at line 228 of file veil2.c.

◆ CONTEXT_PRIVS_SIZE

#define CONTEXT_PRIVS_SIZE (   elems)
Value:
( \
sizeof(SessionPrivs) + \
(sizeof(ContextPrivs) * \
#define CONTEXT_PRIVS_INCREMENT
Definition: veil2.c:228

Provide the size that we want our SessionPrivs structure to be.

Parameters
elemsthe number of ContextPrivs entries already in place. This will be increased by CONTEXT_PRIVS_INCREMENT.

Definition at line 235 of file veil2.c.

Function Documentation

◆ add_scope_privs()

static void add_scope_privs ( int  scope_type,
int  scope,
Bitmap *  privs 
)
static

Add a ContextPrivs entry to session_privs, from the parameters.

Parameters
scope_typeThe scope_type for the new entry
thescope scope for the new entry
privsThe privileges Bitmap for the new entry

Definition at line 283 of file veil2.c.

Here is the call graph for this function:

◆ checkContext()

static bool checkContext ( int *  p_idx,
int  scope_type,
int  scope,
int  priv 
)
static

Wrapper for findContext() that finds the context and checks for a privilege in a single operation.

Parameters
p_idxPointer to a cached index value for the entry in the session_privs->active_contexts that the search should start from. This allows the caller to cache the last returned index in the hope that they will be looking for the same entry next time. If no cached value exists, the caller should provide -1. The index of the found ContextPrivs entry will be returned through this, or -1 if no context can be found.
scope_typeThe scope_type_id of the ContextPrivs entry we are looking for.
scopeThe scope_id of the ContextPrivs entry we are looking for.
privThe privilege to test for.
Returns
false if no context can be found, otherwise true if the user has priv in the supplied scope.

Definition at line 183 of file veil2.c.

Here is the call graph for this function:

◆ checkSessionReady()

static bool checkSessionReady ( )
static

Check whether a session has been properly initialized. If not, and we are supposed to fail in such a situation, fail with an appropriate error message. Otherwise return true if the session is ready to go.

Returns
boolean True if our session has been properly initialized.

Definition at line 644 of file veil2.c.

Here is the call graph for this function:

◆ clear_session_privs()

static void clear_session_privs ( )
static

Clear all ContextPrivs entries in session_privs.

Definition at line 212 of file veil2.c.

Here is the call graph for this function:

◆ create_temp_tables()

static void create_temp_tables ( )
static

Create the temporary tables used for recording session privileges and context.

Definition at line 438 of file veil2.c.

Here is the call graph for this function:

◆ do_load_session_privs()

static void do_load_session_privs ( )
static

Does the donkey-work of loading session privileges into session memory.

Definition at line 338 of file veil2.c.

Here is the call graph for this function:

◆ do_reset_session()

static void do_reset_session ( bool  clear_context)
static

Does the database donkey-work for veil2_reset_session().

Parameters
clear_contextWhether veil2_session_context should be cleared as well as the privileges temp tables.

Definition at line 509 of file veil2.c.

Here is the call graph for this function:

◆ error_if_no_session()

static bool error_if_no_session ( )
static

Predicate to indicate whether to raise an error if a privilege test function has been called prior to a session being established. If not, the privilege testing function should return false. The determination of whether to error or return false is based on the value of the veil2.system_parameter 'error on uninitialized session' at the time that the database session is established.

Returns
boolean, whether or not to raise an error.

Definition at line 387 of file veil2.c.

Here is the call graph for this function:

◆ extendSessionPrivs()

static SessionPrivs* extendSessionPrivs ( SessionPrivs session_privs)
static

Definition at line 246 of file veil2.c.

◆ fetch_2ints()

static bool fetch_2ints ( HeapTuple  tuple,
TupleDesc  tupdesc,
void *  p_result 
)
static

This is a Fetch_fn() for dealing with tuples containing 2 integers. Its job is to populate the p_result parameter with 2 integers from a Postgres SPI query.

Parameters
tupleThe ::HeapTuple returned from a Postgres SPI query. This will contain a tuple of 2 integers.
tupdescThe ::TupleDesc returned from the same Postgres SPI query
p_resultPointer to a tuple_2ints struct into which the 2 integers from the SPI query will be placed.
Returns
bool false, indicating to veil2_query() that no more rows are expected.

Definition at line 422 of file veil2.c.

◆ fetch_scope_privs()

static bool fetch_scope_privs ( HeapTuple  tuple,
TupleDesc  tupdesc,
void *  p_result 
)
static

A Fetch_fn for veil2_query() that retrieves the details for a ContextPrivs entry and adds it to session_privs using add_scope_privs().

Parameters
tupleThe ::HeapTuple returned from a Postgres SPI query. This will contain a tuple of 2 integers.
tupdescThe ::TupleDesc returned from the same Postgres SPI query
p_resultThis should be null.
Returns
true, to indicate to veil2_query() that there may be more records to fetch.

Definition at line 318 of file veil2.c.

Here is the call graph for this function:

◆ findContext()

static void findContext ( int *  p_idx,
int  scope_type,
int  scope 
)
static

Locate a particular ContextPriv entry in session_privs.

Parameters
p_idxPointer to a cached index value for the entry in the session_privs->active_contexts that the search should start from. This allows the caller to cache the last returned index in the hope that they will be looking for the same entry next time. If no cached value exists, the caller should provide -1. The index of the found ContextPrivs entry will be returned through this, or -1 if no context can be found.
scope_typeThe scope_type_id of the ContextPrivs entry we are looking for.
scopeThe scope_id of the ContextPrivs entry we are looking for.

Definition at line 120 of file veil2.c.

◆ freeContextPrivs()

static void freeContextPrivs ( ContextPrivs cp)
static

Free a ContextPrivs entry. This just means freeing the privileges Bitmap and zeroing the pointer for it.

Parameters
cpThe ContextPrivs entry to be cleared out.

Definition at line 201 of file veil2.c.

◆ load_privs()

static void load_privs ( )
static

Manage the conditional loading of session privileges into session memory. If the session is already loaded, it does nothing.

Definition at line 368 of file veil2.c.

Here is the call graph for this function:

◆ textfromstr()

static text* textfromstr ( char *  in)
static

Create a dynamically allocated text value as a copy of a C string.

Parameters
inString to be copied
Returns
Dynamically allocated (by palloc()) copy of in.

Definition at line 1009 of file veil2.c.

◆ truncate_temp_tables()

static void truncate_temp_tables ( bool  clear_context)
static

Truncate the veil2_session_privileges and veil2_session_context temporary tables (actually we use deletion rather than truncation as it seems faster.

Parameters
clear_contextWhether veil2_session_context should be cleared as well as the privileges temp tables.

Definition at line 470 of file veil2.c.

Here is the call graph for this function:

◆ veil2_datapath()

Datum veil2_datapath ( FunctionCallInfo  fcinfo)

Provide the path to where veil2 sql scripts should be stored on the server.

Returns
Text value containing the path.

Definition at line 1037 of file veil2.c.

Here is the call graph for this function:

◆ veil2_docpath()

Datum veil2_docpath ( FunctionCallInfo  fcinfo)

Provide the path to where documentation should be stored on the server.

Returns
Text value containing the path.

Definition at line 1025 of file veil2.c.

Here is the call graph for this function:

◆ veil2_i_have_global_priv()

Datum veil2_i_have_global_priv ( FunctionCallInfo  fcinfo)

veil2.i_have_global_priv(priv) returns bool

Predicate to determine whether the current session user has a given privilege, priv, with global scope.

Parameters
privilege_idInteger giving privilege to test for
Returns
boolean true if the session has the given privilege

Definition at line 669 of file veil2.c.

Here is the call graph for this function:

◆ veil2_i_have_personal_priv()

Datum veil2_i_have_personal_priv ( FunctionCallInfo  fcinfo)

veil2.i_have_personal_priv(priv, accessor_id) returns bool

Predicate to determine whether the current session user has a given privilege, priv, in their personal scope (ie for data pertaining to themselves).

Parameters
privilege_idInteger giving privilege to test for
accessor_idInteger id for a party from the record being checked.
Returns
boolean true if the session has the given privilege in the personal scope of the given accessor_id

Definition at line 699 of file veil2.c.

Here is the call graph for this function:

◆ veil2_i_have_priv_in_scope()

Datum veil2_i_have_priv_in_scope ( FunctionCallInfo  fcinfo)

veil2.i_have_priv_in_scope(priv, scope_type_id, scope_id) returns bool

Predicate to determine whether the current session user has a given privilege, priv, in a specific scope (scope_type_id, scope_id).

Parameters
privilege_idInteger giving privilege to test for
scope_type_idInteger id of the scope type to be checked
scope_idInteger id of the scop to be checked
Returns
boolean true if the session has the given privilege for the given scope_type_id and scope_id

Definition at line 731 of file veil2.c.

Here is the call graph for this function:

◆ veil2_i_have_priv_in_scope_or_global()

Datum veil2_i_have_priv_in_scope_or_global ( FunctionCallInfo  fcinfo)

veil2.i_have_priv_in_scope_or_global(priv, scope_type_id, scope_id) returns bool

Predicate to determine whether the current session user has a given privilege, priv, in a specific scope (scope_type_id, scope_id), or in global scope.

Parameters
privilege_idInteger giving privilege to test for
scope_type_idInteger id of the scope type to be checked
scope_idInteger id of the scop to be checked
Returns
boolean true if the session has the given privilege for the given scope_type_id and scope_id

Definition at line 764 of file veil2.c.

Here is the call graph for this function:

◆ veil2_i_have_priv_in_scope_or_superior()

Datum veil2_i_have_priv_in_scope_or_superior ( FunctionCallInfo  fcinfo)

veil2.i_have_priv_in_scope_or_superior(priv, scope_type_id, scope_id) returns bool

Predicate to determine whether the current session user has a given privilege, priv, in the supplied scope or a superior one: scope_type_id, scope_id.

Parameters
privilege_idInteger giving privilege to test for
scope_type_idInteger id of the scope type to be checked
scope_idInteger id of the scop to be checked
Returns
boolean true if the session has the given privilege in the scope given by scope_type_id and scope_id or a supeior one.

Definition at line 857 of file veil2.c.

Here is the call graph for this function:

◆ veil2_i_have_priv_in_scope_or_superior_or_global()

Datum veil2_i_have_priv_in_scope_or_superior_or_global ( FunctionCallInfo  fcinfo)

veil2.i_have_priv_in_scope_or_superior_or_global(priv, scope_type_id, scope_id) returns bool

Predicate to determine whether the current session user has a given privilege, priv, in global_scope, or the supplied scope, or a superior one: scope_type_id, scope_id.

Parameters
privilege_idInteger giving privilege to test for
scope_type_idInteger id of the scope type to be checked
scope_idInteger id of the scop to be checked
Returns
boolean true if the session has the given privilege in the scope given by scope_type_id and scope_id or a supeior one or global scope.

Definition at line 924 of file veil2.c.

Here is the call graph for this function:

◆ veil2_i_have_priv_in_superior_scope()

Datum veil2_i_have_priv_in_superior_scope ( FunctionCallInfo  fcinfo)

veil2.i_have_priv_in_superior_scope(priv, scope_type_id, scope_id) returns bool

Predicate to determine whether the current session user has a given privilege, priv, in a superior scope to that supplied: scope_type_id, scope_id.

Parameters
privilege_idInteger giving privilege to test for
scope_type_idInteger id of the scope type to be checked
scope_idInteger id of the scop to be checked
Returns
boolean true if the session has the given privilege in a scope superior to that given by scope_type_id and scope_id

Definition at line 801 of file veil2.c.

Here is the call graph for this function:

◆ veil2_reset_session()

Datum veil2_reset_session ( FunctionCallInfo  fcinfo)

veil2.reset_session() returns void

Resets a postgres session prior to the recording of session privilege information. This ensures that the Veil2 temporary tables, on which our security depends, exist and have not been tamperered with. Unless this function succeeds, the privilege testing functions veil2_i_have_global_priv(), veil2_i_have_personal_priv(), veil2_i_have_priv_in_scope() and veil2_i_have_priv_in_superior_scope() will always return false.

Returns
void

Definition at line 588 of file veil2.c.

Here is the call graph for this function:

◆ veil2_reset_session_privs()

Datum veil2_reset_session_privs ( FunctionCallInfo  fcinfo)

veil2.reset_session_privs() returns void

Clears the temp table and cached privileges for a postgres session and reloads them.

Returns
void

Definition at line 609 of file veil2.c.

Here is the call graph for this function:

◆ veil2_result_counts()

Datum veil2_result_counts ( FunctionCallInfo  fcinfo)

Return the number of times one of the i_have_privilege_xxxx() functions has returned false and true.

Returns
Record: false_count, true_count

Definition at line 980 of file veil2.c.

◆ veil2_session_ready()

Datum veil2_session_ready ( FunctionCallInfo  fcinfo)

veil2_session_ready() returns bool Predicate to indicate whether the current session has been properly initialized by veil2_reset_session(). It tests the static variable session_ready.

Returns
bool true if this session has been set up.

Definition at line 496 of file veil2.c.

◆ veil2_true()

Datum veil2_true ( FunctionCallInfo  fcinfo)

veil2.true(params) returns bool

Always return true, regardless of parameters. This is used to determine the minimum possible overhead for a privilege testing predicate, for performance measurements.

Returns
boolean true

Definition at line 630 of file veil2.c.

Variable Documentation

◆ result_counts

int result_counts[] = {0, 0}
static

Used to record counts of false and true results from the i_have_priv_xxx() functions.

Definition at line 67 of file veil2.c.

◆ session_privs

SessionPrivs* session_privs = ((void *) 0)
static

The SessionPrivs object for this session.

Definition at line 96 of file veil2.c.

◆ session_privs_loaded

bool session_privs_loaded = ((bool) 0)
static

Whether we have loaded our session's ContextPrivs into session memory.

Definition at line 101 of file veil2.c.

◆ session_ready

bool session_ready = ((bool) 0)
static

Used to record whether the current session's temporary tables have been properly initialised using veil2_reset_session(). If not the privilege testing functions veil2_i_have_global_priv(), veil2_i_have_personal_priv(), veil2_i_have_priv_in_scope() and veil2_i_have_priv_in_superior_scope() will always return false. If you need to implement your own pl/pgsql base privilege testing function, it should call veil2_session_reeady() to ensure that privileges have been correctly set up.

The primary reason for this variable to exist is to ensure that a user cannot trick the privileges functions by creating their own session_privileges table.

Definition at line 60 of file veil2.c.