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

Generated by: LCOV version 1.16