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

Generated by: LCOV version 2.0-1