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

Generated by: LCOV version 1.14