LCOV - code coverage report
Current view: top level - src/backend/utils/adt - hbafuncs.c (source / functions) Hit Total Coverage
Test: PostgreSQL 17devel Lines: 136 226 60.2 %
Date: 2024-04-20 05:11:05 Functions: 7 7 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * hbafuncs.c
       4             :  *    Support functions for SQL views of authentication files.
       5             :  *
       6             :  * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
       7             :  * Portions Copyright (c) 1994, Regents of the University of California
       8             :  *
       9             :  *
      10             :  * IDENTIFICATION
      11             :  *    src/backend/utils/adt/hbafuncs.c
      12             :  *
      13             :  *-------------------------------------------------------------------------
      14             :  */
      15             : #include "postgres.h"
      16             : 
      17             : #include "catalog/objectaddress.h"
      18             : #include "common/ip.h"
      19             : #include "funcapi.h"
      20             : #include "libpq/hba.h"
      21             : #include "utils/array.h"
      22             : #include "utils/builtins.h"
      23             : #include "utils/guc.h"
      24             : 
      25             : 
      26             : static ArrayType *get_hba_options(HbaLine *hba);
      27             : static void fill_hba_line(Tuplestorestate *tuple_store, TupleDesc tupdesc,
      28             :                           int rule_number, char *filename, int lineno,
      29             :                           HbaLine *hba, const char *err_msg);
      30             : static void fill_hba_view(Tuplestorestate *tuple_store, TupleDesc tupdesc);
      31             : static void fill_ident_line(Tuplestorestate *tuple_store, TupleDesc tupdesc,
      32             :                             int map_number, char *filename, int lineno,
      33             :                             IdentLine *ident, const char *err_msg);
      34             : static void fill_ident_view(Tuplestorestate *tuple_store, TupleDesc tupdesc);
      35             : 
      36             : 
      37             : /*
      38             :  * This macro specifies the maximum number of authentication options
      39             :  * that are possible with any given authentication method that is supported.
      40             :  * Currently LDAP supports 11, and there are 3 that are not dependent on
      41             :  * the auth method here.  It may not actually be possible to set all of them
      42             :  * at the same time, but we'll set the macro value high enough to be
      43             :  * conservative and avoid warnings from static analysis tools.
      44             :  */
      45             : #define MAX_HBA_OPTIONS 14
      46             : 
      47             : /*
      48             :  * Create a text array listing the options specified in the HBA line.
      49             :  * Return NULL if no options are specified.
      50             :  */
      51             : static ArrayType *
      52          56 : get_hba_options(HbaLine *hba)
      53             : {
      54             :     int         noptions;
      55             :     Datum       options[MAX_HBA_OPTIONS];
      56             : 
      57          56 :     noptions = 0;
      58             : 
      59          56 :     if (hba->auth_method == uaGSS || hba->auth_method == uaSSPI)
      60             :     {
      61           0 :         if (hba->include_realm)
      62           0 :             options[noptions++] =
      63           0 :                 CStringGetTextDatum("include_realm=true");
      64             : 
      65           0 :         if (hba->krb_realm)
      66           0 :             options[noptions++] =
      67           0 :                 CStringGetTextDatum(psprintf("krb_realm=%s", hba->krb_realm));
      68             :     }
      69             : 
      70          56 :     if (hba->usermap)
      71           0 :         options[noptions++] =
      72           0 :             CStringGetTextDatum(psprintf("map=%s", hba->usermap));
      73             : 
      74          56 :     if (hba->clientcert != clientCertOff)
      75           0 :         options[noptions++] =
      76           0 :             CStringGetTextDatum(psprintf("clientcert=%s", (hba->clientcert == clientCertCA) ? "verify-ca" : "verify-full"));
      77             : 
      78          56 :     if (hba->pamservice)
      79           0 :         options[noptions++] =
      80           0 :             CStringGetTextDatum(psprintf("pamservice=%s", hba->pamservice));
      81             : 
      82          56 :     if (hba->auth_method == uaLDAP)
      83             :     {
      84           0 :         if (hba->ldapserver)
      85           0 :             options[noptions++] =
      86           0 :                 CStringGetTextDatum(psprintf("ldapserver=%s", hba->ldapserver));
      87             : 
      88           0 :         if (hba->ldapport)
      89           0 :             options[noptions++] =
      90           0 :                 CStringGetTextDatum(psprintf("ldapport=%d", hba->ldapport));
      91             : 
      92           0 :         if (hba->ldaptls)
      93           0 :             options[noptions++] =
      94           0 :                 CStringGetTextDatum("ldaptls=true");
      95             : 
      96           0 :         if (hba->ldapprefix)
      97           0 :             options[noptions++] =
      98           0 :                 CStringGetTextDatum(psprintf("ldapprefix=%s", hba->ldapprefix));
      99             : 
     100           0 :         if (hba->ldapsuffix)
     101           0 :             options[noptions++] =
     102           0 :                 CStringGetTextDatum(psprintf("ldapsuffix=%s", hba->ldapsuffix));
     103             : 
     104           0 :         if (hba->ldapbasedn)
     105           0 :             options[noptions++] =
     106           0 :                 CStringGetTextDatum(psprintf("ldapbasedn=%s", hba->ldapbasedn));
     107             : 
     108           0 :         if (hba->ldapbinddn)
     109           0 :             options[noptions++] =
     110           0 :                 CStringGetTextDatum(psprintf("ldapbinddn=%s", hba->ldapbinddn));
     111             : 
     112           0 :         if (hba->ldapbindpasswd)
     113           0 :             options[noptions++] =
     114           0 :                 CStringGetTextDatum(psprintf("ldapbindpasswd=%s",
     115             :                                              hba->ldapbindpasswd));
     116             : 
     117           0 :         if (hba->ldapsearchattribute)
     118           0 :             options[noptions++] =
     119           0 :                 CStringGetTextDatum(psprintf("ldapsearchattribute=%s",
     120             :                                              hba->ldapsearchattribute));
     121             : 
     122           0 :         if (hba->ldapsearchfilter)
     123           0 :             options[noptions++] =
     124           0 :                 CStringGetTextDatum(psprintf("ldapsearchfilter=%s",
     125             :                                              hba->ldapsearchfilter));
     126             : 
     127           0 :         if (hba->ldapscope)
     128           0 :             options[noptions++] =
     129           0 :                 CStringGetTextDatum(psprintf("ldapscope=%d", hba->ldapscope));
     130             :     }
     131             : 
     132          56 :     if (hba->auth_method == uaRADIUS)
     133             :     {
     134           0 :         if (hba->radiusservers_s)
     135           0 :             options[noptions++] =
     136           0 :                 CStringGetTextDatum(psprintf("radiusservers=%s", hba->radiusservers_s));
     137             : 
     138           0 :         if (hba->radiussecrets_s)
     139           0 :             options[noptions++] =
     140           0 :                 CStringGetTextDatum(psprintf("radiussecrets=%s", hba->radiussecrets_s));
     141             : 
     142           0 :         if (hba->radiusidentifiers_s)
     143           0 :             options[noptions++] =
     144           0 :                 CStringGetTextDatum(psprintf("radiusidentifiers=%s", hba->radiusidentifiers_s));
     145             : 
     146           0 :         if (hba->radiusports_s)
     147           0 :             options[noptions++] =
     148           0 :                 CStringGetTextDatum(psprintf("radiusports=%s", hba->radiusports_s));
     149             :     }
     150             : 
     151             :     /* If you add more options, consider increasing MAX_HBA_OPTIONS. */
     152             :     Assert(noptions <= MAX_HBA_OPTIONS);
     153             : 
     154          56 :     if (noptions > 0)
     155           0 :         return construct_array_builtin(options, noptions, TEXTOID);
     156             :     else
     157          56 :         return NULL;
     158             : }
     159             : 
     160             : /* Number of columns in pg_hba_file_rules view */
     161             : #define NUM_PG_HBA_FILE_RULES_ATTS   11
     162             : 
     163             : /*
     164             :  * fill_hba_line
     165             :  *      Build one row of pg_hba_file_rules view, add it to tuplestore.
     166             :  *
     167             :  * tuple_store: where to store data
     168             :  * tupdesc: tuple descriptor for the view
     169             :  * rule_number: unique identifier among all valid rules
     170             :  * filename: configuration file name (must always be valid)
     171             :  * lineno: line number of configuration file (must always be valid)
     172             :  * hba: parsed line data (can be NULL, in which case err_msg should be set)
     173             :  * err_msg: error message (NULL if none)
     174             :  *
     175             :  * Note: leaks memory, but we don't care since this is run in a short-lived
     176             :  * memory context.
     177             :  */
     178             : static void
     179          56 : fill_hba_line(Tuplestorestate *tuple_store, TupleDesc tupdesc,
     180             :               int rule_number, char *filename, int lineno, HbaLine *hba,
     181             :               const char *err_msg)
     182             : {
     183             :     Datum       values[NUM_PG_HBA_FILE_RULES_ATTS];
     184             :     bool        nulls[NUM_PG_HBA_FILE_RULES_ATTS];
     185             :     char        buffer[NI_MAXHOST];
     186             :     HeapTuple   tuple;
     187             :     int         index;
     188             :     ListCell   *lc;
     189             :     const char *typestr;
     190             :     const char *addrstr;
     191             :     const char *maskstr;
     192             :     ArrayType  *options;
     193             : 
     194             :     Assert(tupdesc->natts == NUM_PG_HBA_FILE_RULES_ATTS);
     195             : 
     196          56 :     memset(values, 0, sizeof(values));
     197          56 :     memset(nulls, 0, sizeof(nulls));
     198          56 :     index = 0;
     199             : 
     200             :     /* rule_number, nothing on error */
     201          56 :     if (err_msg)
     202           0 :         nulls[index++] = true;
     203             :     else
     204          56 :         values[index++] = Int32GetDatum(rule_number);
     205             : 
     206             :     /* file_name */
     207          56 :     values[index++] = CStringGetTextDatum(filename);
     208             : 
     209             :     /* line_number */
     210          56 :     values[index++] = Int32GetDatum(lineno);
     211             : 
     212          56 :     if (hba != NULL)
     213             :     {
     214             :         /* type */
     215             :         /* Avoid a default: case so compiler will warn about missing cases */
     216          56 :         typestr = NULL;
     217          56 :         switch (hba->conntype)
     218             :         {
     219          32 :             case ctLocal:
     220          32 :                 typestr = "local";
     221          32 :                 break;
     222          24 :             case ctHost:
     223          24 :                 typestr = "host";
     224          24 :                 break;
     225           0 :             case ctHostSSL:
     226           0 :                 typestr = "hostssl";
     227           0 :                 break;
     228           0 :             case ctHostNoSSL:
     229           0 :                 typestr = "hostnossl";
     230           0 :                 break;
     231           0 :             case ctHostGSS:
     232           0 :                 typestr = "hostgssenc";
     233           0 :                 break;
     234           0 :             case ctHostNoGSS:
     235           0 :                 typestr = "hostnogssenc";
     236           0 :                 break;
     237             :         }
     238          56 :         if (typestr)
     239          56 :             values[index++] = CStringGetTextDatum(typestr);
     240             :         else
     241           0 :             nulls[index++] = true;
     242             : 
     243             :         /* database */
     244          56 :         if (hba->databases)
     245             :         {
     246             :             /*
     247             :              * Flatten AuthToken list to string list.  It might seem that we
     248             :              * should re-quote any quoted tokens, but that has been rejected
     249             :              * on the grounds that it makes it harder to compare the array
     250             :              * elements to other system catalogs.  That makes entries like
     251             :              * "all" or "samerole" formally ambiguous ... but users who name
     252             :              * databases/roles that way are inflicting their own pain.
     253             :              */
     254          56 :             List       *names = NIL;
     255             : 
     256         114 :             foreach(lc, hba->databases)
     257             :             {
     258          58 :                 AuthToken  *tok = lfirst(lc);
     259             : 
     260          58 :                 names = lappend(names, tok->string);
     261             :             }
     262          56 :             values[index++] = PointerGetDatum(strlist_to_textarray(names));
     263             :         }
     264             :         else
     265           0 :             nulls[index++] = true;
     266             : 
     267             :         /* user */
     268          56 :         if (hba->roles)
     269             :         {
     270             :             /* Flatten AuthToken list to string list; see comment above */
     271          56 :             List       *roles = NIL;
     272             : 
     273         112 :             foreach(lc, hba->roles)
     274             :             {
     275          56 :                 AuthToken  *tok = lfirst(lc);
     276             : 
     277          56 :                 roles = lappend(roles, tok->string);
     278             :             }
     279          56 :             values[index++] = PointerGetDatum(strlist_to_textarray(roles));
     280             :         }
     281             :         else
     282           0 :             nulls[index++] = true;
     283             : 
     284             :         /* address and netmask */
     285             :         /* Avoid a default: case so compiler will warn about missing cases */
     286          56 :         addrstr = maskstr = NULL;
     287          56 :         switch (hba->ip_cmp_method)
     288             :         {
     289          56 :             case ipCmpMask:
     290          56 :                 if (hba->hostname)
     291             :                 {
     292           0 :                     addrstr = hba->hostname;
     293             :                 }
     294             :                 else
     295             :                 {
     296             :                     /*
     297             :                      * Note: if pg_getnameinfo_all fails, it'll set buffer to
     298             :                      * "???", which we want to return.
     299             :                      */
     300          56 :                     if (hba->addrlen > 0)
     301             :                     {
     302          24 :                         if (pg_getnameinfo_all(&hba->addr, hba->addrlen,
     303             :                                                buffer, sizeof(buffer),
     304             :                                                NULL, 0,
     305             :                                                NI_NUMERICHOST) == 0)
     306          24 :                             clean_ipv6_addr(hba->addr.ss_family, buffer);
     307          24 :                         addrstr = pstrdup(buffer);
     308             :                     }
     309          56 :                     if (hba->masklen > 0)
     310             :                     {
     311          24 :                         if (pg_getnameinfo_all(&hba->mask, hba->masklen,
     312             :                                                buffer, sizeof(buffer),
     313             :                                                NULL, 0,
     314             :                                                NI_NUMERICHOST) == 0)
     315          24 :                             clean_ipv6_addr(hba->mask.ss_family, buffer);
     316          24 :                         maskstr = pstrdup(buffer);
     317             :                     }
     318             :                 }
     319          56 :                 break;
     320           0 :             case ipCmpAll:
     321           0 :                 addrstr = "all";
     322           0 :                 break;
     323           0 :             case ipCmpSameHost:
     324           0 :                 addrstr = "samehost";
     325           0 :                 break;
     326           0 :             case ipCmpSameNet:
     327           0 :                 addrstr = "samenet";
     328           0 :                 break;
     329             :         }
     330          56 :         if (addrstr)
     331          24 :             values[index++] = CStringGetTextDatum(addrstr);
     332             :         else
     333          32 :             nulls[index++] = true;
     334          56 :         if (maskstr)
     335          24 :             values[index++] = CStringGetTextDatum(maskstr);
     336             :         else
     337          32 :             nulls[index++] = true;
     338             : 
     339             :         /* auth_method */
     340          56 :         values[index++] = CStringGetTextDatum(hba_authname(hba->auth_method));
     341             : 
     342             :         /* options */
     343          56 :         options = get_hba_options(hba);
     344          56 :         if (options)
     345           0 :             values[index++] = PointerGetDatum(options);
     346             :         else
     347          56 :             nulls[index++] = true;
     348             :     }
     349             :     else
     350             :     {
     351             :         /* no parsing result, so set relevant fields to nulls */
     352           0 :         memset(&nulls[3], true, (NUM_PG_HBA_FILE_RULES_ATTS - 4) * sizeof(bool));
     353             :     }
     354             : 
     355             :     /* error */
     356          56 :     if (err_msg)
     357           0 :         values[NUM_PG_HBA_FILE_RULES_ATTS - 1] = CStringGetTextDatum(err_msg);
     358             :     else
     359          56 :         nulls[NUM_PG_HBA_FILE_RULES_ATTS - 1] = true;
     360             : 
     361          56 :     tuple = heap_form_tuple(tupdesc, values, nulls);
     362          56 :     tuplestore_puttuple(tuple_store, tuple);
     363          56 : }
     364             : 
     365             : /*
     366             :  * fill_hba_view
     367             :  *      Read the pg_hba.conf file and fill the tuplestore with view records.
     368             :  */
     369             : static void
     370           8 : fill_hba_view(Tuplestorestate *tuple_store, TupleDesc tupdesc)
     371             : {
     372             :     FILE       *file;
     373           8 :     List       *hba_lines = NIL;
     374             :     ListCell   *line;
     375           8 :     int         rule_number = 0;
     376             :     MemoryContext hbacxt;
     377             :     MemoryContext oldcxt;
     378             : 
     379             :     /*
     380             :      * In the unlikely event that we can't open pg_hba.conf, we throw an
     381             :      * error, rather than trying to report it via some sort of view entry.
     382             :      * (Most other error conditions should result in a message in a view
     383             :      * entry.)
     384             :      */
     385           8 :     file = open_auth_file(HbaFileName, ERROR, 0, NULL);
     386             : 
     387           8 :     tokenize_auth_file(HbaFileName, file, &hba_lines, DEBUG3, 0);
     388             : 
     389             :     /* Now parse all the lines */
     390           8 :     hbacxt = AllocSetContextCreate(CurrentMemoryContext,
     391             :                                    "hba parser context",
     392             :                                    ALLOCSET_SMALL_SIZES);
     393           8 :     oldcxt = MemoryContextSwitchTo(hbacxt);
     394          64 :     foreach(line, hba_lines)
     395             :     {
     396          56 :         TokenizedAuthLine *tok_line = (TokenizedAuthLine *) lfirst(line);
     397          56 :         HbaLine    *hbaline = NULL;
     398             : 
     399             :         /* don't parse lines that already have errors */
     400          56 :         if (tok_line->err_msg == NULL)
     401          56 :             hbaline = parse_hba_line(tok_line, DEBUG3);
     402             : 
     403             :         /* No error, set a new rule number */
     404          56 :         if (tok_line->err_msg == NULL)
     405          56 :             rule_number++;
     406             : 
     407          56 :         fill_hba_line(tuple_store, tupdesc, rule_number,
     408             :                       tok_line->file_name, tok_line->line_num, hbaline,
     409          56 :                       tok_line->err_msg);
     410             :     }
     411             : 
     412             :     /* Free tokenizer memory */
     413           8 :     free_auth_file(file, 0);
     414             :     /* Free parse_hba_line memory */
     415           8 :     MemoryContextSwitchTo(oldcxt);
     416           8 :     MemoryContextDelete(hbacxt);
     417           8 : }
     418             : 
     419             : /*
     420             :  * pg_hba_file_rules
     421             :  *
     422             :  * SQL-accessible set-returning function to return all the entries in the
     423             :  * pg_hba.conf file.
     424             :  */
     425             : Datum
     426           8 : pg_hba_file_rules(PG_FUNCTION_ARGS)
     427             : {
     428             :     ReturnSetInfo *rsi;
     429             : 
     430             :     /*
     431             :      * Build tuplestore to hold the result rows.  We must use the Materialize
     432             :      * mode to be safe against HBA file changes while the cursor is open. It's
     433             :      * also more efficient than having to look up our current position in the
     434             :      * parsed list every time.
     435             :      */
     436           8 :     InitMaterializedSRF(fcinfo, 0);
     437             : 
     438             :     /* Fill the tuplestore */
     439           8 :     rsi = (ReturnSetInfo *) fcinfo->resultinfo;
     440           8 :     fill_hba_view(rsi->setResult, rsi->setDesc);
     441             : 
     442           8 :     PG_RETURN_NULL();
     443             : }
     444             : 
     445             : /* Number of columns in pg_ident_file_mappings view */
     446             : #define NUM_PG_IDENT_FILE_MAPPINGS_ATTS  7
     447             : 
     448             : /*
     449             :  * fill_ident_line: build one row of pg_ident_file_mappings view, add it to
     450             :  * tuplestore
     451             :  *
     452             :  * tuple_store: where to store data
     453             :  * tupdesc: tuple descriptor for the view
     454             :  * map_number: unique identifier among all valid maps
     455             :  * filename: configuration file name (must always be valid)
     456             :  * lineno: line number of configuration file (must always be valid)
     457             :  * ident: parsed line data (can be NULL, in which case err_msg should be set)
     458             :  * err_msg: error message (NULL if none)
     459             :  *
     460             :  * Note: leaks memory, but we don't care since this is run in a short-lived
     461             :  * memory context.
     462             :  */
     463             : static void
     464          16 : fill_ident_line(Tuplestorestate *tuple_store, TupleDesc tupdesc,
     465             :                 int map_number, char *filename, int lineno, IdentLine *ident,
     466             :                 const char *err_msg)
     467             : {
     468             :     Datum       values[NUM_PG_IDENT_FILE_MAPPINGS_ATTS];
     469             :     bool        nulls[NUM_PG_IDENT_FILE_MAPPINGS_ATTS];
     470             :     HeapTuple   tuple;
     471             :     int         index;
     472             : 
     473             :     Assert(tupdesc->natts == NUM_PG_IDENT_FILE_MAPPINGS_ATTS);
     474             : 
     475          16 :     memset(values, 0, sizeof(values));
     476          16 :     memset(nulls, 0, sizeof(nulls));
     477          16 :     index = 0;
     478             : 
     479             :     /* map_number, nothing on error */
     480          16 :     if (err_msg)
     481           0 :         nulls[index++] = true;
     482             :     else
     483          16 :         values[index++] = Int32GetDatum(map_number);
     484             : 
     485             :     /* file_name */
     486          16 :     values[index++] = CStringGetTextDatum(filename);
     487             : 
     488             :     /* line_number */
     489          16 :     values[index++] = Int32GetDatum(lineno);
     490             : 
     491          16 :     if (ident != NULL)
     492             :     {
     493          16 :         values[index++] = CStringGetTextDatum(ident->usermap);
     494          16 :         values[index++] = CStringGetTextDatum(ident->system_user->string);
     495          16 :         values[index++] = CStringGetTextDatum(ident->pg_user->string);
     496             :     }
     497             :     else
     498             :     {
     499             :         /* no parsing result, so set relevant fields to nulls */
     500           0 :         memset(&nulls[3], true, (NUM_PG_IDENT_FILE_MAPPINGS_ATTS - 4) * sizeof(bool));
     501             :     }
     502             : 
     503             :     /* error */
     504          16 :     if (err_msg)
     505           0 :         values[NUM_PG_IDENT_FILE_MAPPINGS_ATTS - 1] = CStringGetTextDatum(err_msg);
     506             :     else
     507          16 :         nulls[NUM_PG_IDENT_FILE_MAPPINGS_ATTS - 1] = true;
     508             : 
     509          16 :     tuple = heap_form_tuple(tupdesc, values, nulls);
     510          16 :     tuplestore_puttuple(tuple_store, tuple);
     511          16 : }
     512             : 
     513             : /*
     514             :  * Read the pg_ident.conf file and fill the tuplestore with view records.
     515             :  */
     516             : static void
     517           8 : fill_ident_view(Tuplestorestate *tuple_store, TupleDesc tupdesc)
     518             : {
     519             :     FILE       *file;
     520           8 :     List       *ident_lines = NIL;
     521             :     ListCell   *line;
     522           8 :     int         map_number = 0;
     523             :     MemoryContext identcxt;
     524             :     MemoryContext oldcxt;
     525             : 
     526             :     /*
     527             :      * In the unlikely event that we can't open pg_ident.conf, we throw an
     528             :      * error, rather than trying to report it via some sort of view entry.
     529             :      * (Most other error conditions should result in a message in a view
     530             :      * entry.)
     531             :      */
     532           8 :     file = open_auth_file(IdentFileName, ERROR, 0, NULL);
     533             : 
     534           8 :     tokenize_auth_file(IdentFileName, file, &ident_lines, DEBUG3, 0);
     535             : 
     536             :     /* Now parse all the lines */
     537           8 :     identcxt = AllocSetContextCreate(CurrentMemoryContext,
     538             :                                      "ident parser context",
     539             :                                      ALLOCSET_SMALL_SIZES);
     540           8 :     oldcxt = MemoryContextSwitchTo(identcxt);
     541          24 :     foreach(line, ident_lines)
     542             :     {
     543          16 :         TokenizedAuthLine *tok_line = (TokenizedAuthLine *) lfirst(line);
     544          16 :         IdentLine  *identline = NULL;
     545             : 
     546             :         /* don't parse lines that already have errors */
     547          16 :         if (tok_line->err_msg == NULL)
     548          16 :             identline = parse_ident_line(tok_line, DEBUG3);
     549             : 
     550             :         /* no error, set a new mapping number */
     551          16 :         if (tok_line->err_msg == NULL)
     552          16 :             map_number++;
     553             : 
     554          16 :         fill_ident_line(tuple_store, tupdesc, map_number,
     555             :                         tok_line->file_name, tok_line->line_num,
     556          16 :                         identline, tok_line->err_msg);
     557             :     }
     558             : 
     559             :     /* Free tokenizer memory */
     560           8 :     free_auth_file(file, 0);
     561             :     /* Free parse_ident_line memory */
     562           8 :     MemoryContextSwitchTo(oldcxt);
     563           8 :     MemoryContextDelete(identcxt);
     564           8 : }
     565             : 
     566             : /*
     567             :  * SQL-accessible SRF to return all the entries in the pg_ident.conf file.
     568             :  */
     569             : Datum
     570           8 : pg_ident_file_mappings(PG_FUNCTION_ARGS)
     571             : {
     572             :     ReturnSetInfo *rsi;
     573             : 
     574             :     /*
     575             :      * Build tuplestore to hold the result rows.  We must use the Materialize
     576             :      * mode to be safe against HBA file changes while the cursor is open. It's
     577             :      * also more efficient than having to look up our current position in the
     578             :      * parsed list every time.
     579             :      */
     580           8 :     InitMaterializedSRF(fcinfo, 0);
     581             : 
     582             :     /* Fill the tuplestore */
     583           8 :     rsi = (ReturnSetInfo *) fcinfo->resultinfo;
     584           8 :     fill_ident_view(rsi->setResult, rsi->setDesc);
     585             : 
     586           8 :     PG_RETURN_NULL();
     587             : }

Generated by: LCOV version 1.14