aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/adt/hbafuncs.c
diff options
context:
space:
mode:
authorMichael Paquier <michael@paquier.xyz>2022-03-29 10:15:48 +0900
committerMichael Paquier <michael@paquier.xyz>2022-03-29 10:15:48 +0900
commita2c84990bea7beadb599d02328190e2a763dcb86 (patch)
tree9ae2c552d668a4e4781ae0fac25a5a1ff29d5e17 /src/backend/utils/adt/hbafuncs.c
parent091a971bb59ca9751f32a4aa5aee969c5a915754 (diff)
downloadpostgresql-a2c84990bea7beadb599d02328190e2a763dcb86.tar.gz
postgresql-a2c84990bea7beadb599d02328190e2a763dcb86.zip
Add system view pg_ident_file_mappings
This view is similar to pg_hba_file_rules view, except that it is associated with the parsing of pg_ident.conf. Similarly to its cousin, this view is useful to check via SQL if changes planned in pg_ident.conf would work upon reload or restart, or to diagnose a previous failure. Bumps catalog version. Author: Julien Rouhaud Reviewed-by: Aleksander Alekseev, Michael Paquier Discussion: https://postgr.es/m/20220223045959.35ipdsvbxcstrhya@jrouhaud
Diffstat (limited to 'src/backend/utils/adt/hbafuncs.c')
-rw-r--r--src/backend/utils/adt/hbafuncs.c136
1 files changed, 136 insertions, 0 deletions
diff --git a/src/backend/utils/adt/hbafuncs.c b/src/backend/utils/adt/hbafuncs.c
index f46cd935a1c..9fe7b62c9a0 100644
--- a/src/backend/utils/adt/hbafuncs.c
+++ b/src/backend/utils/adt/hbafuncs.c
@@ -28,6 +28,9 @@ static ArrayType *get_hba_options(HbaLine *hba);
static void fill_hba_line(Tuplestorestate *tuple_store, TupleDesc tupdesc,
int lineno, HbaLine *hba, const char *err_msg);
static void fill_hba_view(Tuplestorestate *tuple_store, TupleDesc tupdesc);
+static void fill_ident_line(Tuplestorestate *tuple_store, TupleDesc tupdesc,
+ int lineno, IdentLine *ident, const char *err_msg);
+static void fill_ident_view(Tuplestorestate *tuple_store, TupleDesc tupdesc);
/*
@@ -426,3 +429,136 @@ pg_hba_file_rules(PG_FUNCTION_ARGS)
PG_RETURN_NULL();
}
+
+/* Number of columns in pg_ident_file_mappings view */
+#define NUM_PG_IDENT_FILE_MAPPINGS_ATTS 5
+
+/*
+ * fill_ident_line: build one row of pg_ident_file_mappings view, add it to
+ * tuplestore
+ *
+ * tuple_store: where to store data
+ * tupdesc: tuple descriptor for the view
+ * lineno: pg_ident.conf line number (must always be valid)
+ * ident: parsed line data (can be NULL, in which case err_msg should be set)
+ * err_msg: error message (NULL if none)
+ *
+ * Note: leaks memory, but we don't care since this is run in a short-lived
+ * memory context.
+ */
+static void
+fill_ident_line(Tuplestorestate *tuple_store, TupleDesc tupdesc,
+ int lineno, IdentLine *ident, const char *err_msg)
+{
+ Datum values[NUM_PG_IDENT_FILE_MAPPINGS_ATTS];
+ bool nulls[NUM_PG_IDENT_FILE_MAPPINGS_ATTS];
+ HeapTuple tuple;
+ int index;
+
+ Assert(tupdesc->natts == NUM_PG_IDENT_FILE_MAPPINGS_ATTS);
+
+ memset(values, 0, sizeof(values));
+ memset(nulls, 0, sizeof(nulls));
+ index = 0;
+
+ /* line_number */
+ values[index++] = Int32GetDatum(lineno);
+
+ if (ident != NULL)
+ {
+ values[index++] = CStringGetTextDatum(ident->usermap);
+ values[index++] = CStringGetTextDatum(ident->ident_user);
+ values[index++] = CStringGetTextDatum(ident->pg_role);
+ }
+ else
+ {
+ /* no parsing result, so set relevant fields to nulls */
+ memset(&nulls[1], true, (NUM_PG_IDENT_FILE_MAPPINGS_ATTS - 2) * sizeof(bool));
+ }
+
+ /* error */
+ if (err_msg)
+ values[NUM_PG_IDENT_FILE_MAPPINGS_ATTS - 1] = CStringGetTextDatum(err_msg);
+ else
+ nulls[NUM_PG_IDENT_FILE_MAPPINGS_ATTS - 1] = true;
+
+ tuple = heap_form_tuple(tupdesc, values, nulls);
+ tuplestore_puttuple(tuple_store, tuple);
+}
+
+/*
+ * Read the pg_ident.conf file and fill the tuplestore with view records.
+ */
+static void
+fill_ident_view(Tuplestorestate *tuple_store, TupleDesc tupdesc)
+{
+ FILE *file;
+ List *ident_lines = NIL;
+ ListCell *line;
+ MemoryContext linecxt;
+ MemoryContext identcxt;
+ MemoryContext oldcxt;
+
+ /*
+ * In the unlikely event that we can't open pg_ident.conf, we throw an
+ * error, rather than trying to report it via some sort of view entry.
+ * (Most other error conditions should result in a message in a view
+ * entry.)
+ */
+ file = AllocateFile(IdentFileName, "r");
+ if (file == NULL)
+ ereport(ERROR,
+ (errcode_for_file_access(),
+ errmsg("could not open usermap file \"%s\": %m",
+ IdentFileName)));
+
+ linecxt = tokenize_auth_file(HbaFileName, file, &ident_lines, DEBUG3);
+ FreeFile(file);
+
+ /* Now parse all the lines */
+ identcxt = AllocSetContextCreate(CurrentMemoryContext,
+ "ident parser context",
+ ALLOCSET_SMALL_SIZES);
+ oldcxt = MemoryContextSwitchTo(identcxt);
+ foreach(line, ident_lines)
+ {
+ TokenizedAuthLine *tok_line = (TokenizedAuthLine *) lfirst(line);
+ IdentLine *identline = NULL;
+
+ /* don't parse lines that already have errors */
+ if (tok_line->err_msg == NULL)
+ identline = parse_ident_line(tok_line, DEBUG3);
+
+ fill_ident_line(tuple_store, tupdesc, tok_line->line_num, identline,
+ tok_line->err_msg);
+ }
+
+ /* Free tokenizer memory */
+ MemoryContextDelete(linecxt);
+ /* Free parse_ident_line memory */
+ MemoryContextSwitchTo(oldcxt);
+ MemoryContextDelete(identcxt);
+}
+
+/*
+ * SQL-accessible SRF to return all the entries in the pg_ident.conf file.
+ */
+Datum
+pg_ident_file_mappings(PG_FUNCTION_ARGS)
+{
+ ReturnSetInfo *rsi;
+
+ /*
+ * Build tuplestore to hold the result rows. We must use the Materialize
+ * mode to be safe against HBA file changes while the cursor is open. It's
+ * also more efficient than having to look up our current position in the
+ * parsed list every time.
+ */
+ SetSingleFuncCall(fcinfo, 0);
+
+ /* Fill the tuplestore */
+ rsi = (ReturnSetInfo *) fcinfo->resultinfo;
+ fill_ident_view(rsi->setResult, rsi->setDesc);
+
+ PG_RETURN_NULL();
+}