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

Generated by: LCOV version 1.14