LCOV - code coverage report
Current view: top level - src/backend/utils/adt - hbafuncs.c (source / functions) Coverage Total Hit
Test: PostgreSQL 19devel Lines: 46.3 % 242 112
Test Date: 2026-03-01 01:14:39 Functions: 85.7 % 7 6
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              : 
      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           28 : get_hba_options(HbaLine *hba)
      54              : {
      55              :     int         noptions;
      56              :     Datum       options[MAX_HBA_OPTIONS];
      57              : 
      58           28 :     noptions = 0;
      59              : 
      60           28 :     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           28 :     if (hba->usermap)
      72            0 :         options[noptions++] =
      73            0 :             CStringGetTextDatum(psprintf("map=%s", hba->usermap));
      74              : 
      75           28 :     if (hba->clientcert != clientCertOff)
      76            0 :         options[noptions++] =
      77            0 :             CStringGetTextDatum(psprintf("clientcert=%s", (hba->clientcert == clientCertCA) ? "verify-ca" : "verify-full"));
      78              : 
      79           28 :     if (hba->pamservice)
      80            0 :         options[noptions++] =
      81            0 :             CStringGetTextDatum(psprintf("pamservice=%s", hba->pamservice));
      82              : 
      83           28 :     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           28 :     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           28 :     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           28 :     if (noptions > 0)
     179            0 :         return construct_array_builtin(options, noptions, TEXTOID);
     180              :     else
     181           28 :         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           28 : 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           28 :     memset(values, 0, sizeof(values));
     221           28 :     memset(nulls, 0, sizeof(nulls));
     222           28 :     index = 0;
     223              : 
     224              :     /* rule_number, nothing on error */
     225           28 :     if (err_msg)
     226            0 :         nulls[index++] = true;
     227              :     else
     228           28 :         values[index++] = Int32GetDatum(rule_number);
     229              : 
     230              :     /* file_name */
     231           28 :     values[index++] = CStringGetTextDatum(filename);
     232              : 
     233              :     /* line_number */
     234           28 :     values[index++] = Int32GetDatum(lineno);
     235              : 
     236           28 :     if (hba != NULL)
     237              :     {
     238              :         /* type */
     239              :         /* Avoid a default: case so compiler will warn about missing cases */
     240           28 :         typestr = NULL;
     241           28 :         switch (hba->conntype)
     242              :         {
     243           16 :             case ctLocal:
     244           16 :                 typestr = "local";
     245           16 :                 break;
     246           12 :             case ctHost:
     247           12 :                 typestr = "host";
     248           12 :                 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           28 :         if (typestr)
     263           28 :             values[index++] = CStringGetTextDatum(typestr);
     264              :         else
     265            0 :             nulls[index++] = true;
     266              : 
     267              :         /* database */
     268           28 :         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           28 :             List       *names = NIL;
     279              : 
     280           57 :             foreach(lc, hba->databases)
     281              :             {
     282           29 :                 AuthToken  *tok = lfirst(lc);
     283              : 
     284           29 :                 names = lappend(names, tok->string);
     285              :             }
     286           28 :             values[index++] = PointerGetDatum(strlist_to_textarray(names));
     287              :         }
     288              :         else
     289            0 :             nulls[index++] = true;
     290              : 
     291              :         /* user */
     292           28 :         if (hba->roles)
     293              :         {
     294              :             /* Flatten AuthToken list to string list; see comment above */
     295           28 :             List       *roles = NIL;
     296              : 
     297           56 :             foreach(lc, hba->roles)
     298              :             {
     299           28 :                 AuthToken  *tok = lfirst(lc);
     300              : 
     301           28 :                 roles = lappend(roles, tok->string);
     302              :             }
     303           28 :             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           28 :         addrstr = maskstr = NULL;
     311           28 :         switch (hba->ip_cmp_method)
     312              :         {
     313           28 :             case ipCmpMask:
     314           28 :                 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           28 :                     if (hba->addrlen > 0)
     325              :                     {
     326           12 :                         if (pg_getnameinfo_all(&hba->addr, hba->addrlen,
     327              :                                                buffer, sizeof(buffer),
     328              :                                                NULL, 0,
     329              :                                                NI_NUMERICHOST) == 0)
     330           12 :                             clean_ipv6_addr(hba->addr.ss_family, buffer);
     331           12 :                         addrstr = pstrdup(buffer);
     332              :                     }
     333           28 :                     if (hba->masklen > 0)
     334              :                     {
     335           12 :                         if (pg_getnameinfo_all(&hba->mask, hba->masklen,
     336              :                                                buffer, sizeof(buffer),
     337              :                                                NULL, 0,
     338              :                                                NI_NUMERICHOST) == 0)
     339           12 :                             clean_ipv6_addr(hba->mask.ss_family, buffer);
     340           12 :                         maskstr = pstrdup(buffer);
     341              :                     }
     342              :                 }
     343           28 :                 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           28 :         if (addrstr)
     355           12 :             values[index++] = CStringGetTextDatum(addrstr);
     356              :         else
     357           16 :             nulls[index++] = true;
     358           28 :         if (maskstr)
     359           12 :             values[index++] = CStringGetTextDatum(maskstr);
     360              :         else
     361           16 :             nulls[index++] = true;
     362              : 
     363              :         /* auth_method */
     364           28 :         values[index++] = CStringGetTextDatum(hba_authname(hba->auth_method));
     365              : 
     366              :         /* options */
     367           28 :         options = get_hba_options(hba);
     368           28 :         if (options)
     369            0 :             values[index++] = PointerGetDatum(options);
     370              :         else
     371           28 :             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           28 :     if (err_msg)
     381            0 :         values[NUM_PG_HBA_FILE_RULES_ATTS - 1] = CStringGetTextDatum(err_msg);
     382              :     else
     383           28 :         nulls[NUM_PG_HBA_FILE_RULES_ATTS - 1] = true;
     384              : 
     385           28 :     tuple = heap_form_tuple(tupdesc, values, nulls);
     386           28 :     tuplestore_puttuple(tuple_store, tuple);
     387           28 : }
     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            4 : fill_hba_view(Tuplestorestate *tuple_store, TupleDesc tupdesc)
     395              : {
     396              :     FILE       *file;
     397            4 :     List       *hba_lines = NIL;
     398              :     ListCell   *line;
     399            4 :     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            4 :     file = open_auth_file(HbaFileName, ERROR, 0, NULL);
     410              : 
     411            4 :     tokenize_auth_file(HbaFileName, file, &hba_lines, DEBUG3, 0);
     412              : 
     413              :     /* Now parse all the lines */
     414            4 :     hbacxt = AllocSetContextCreate(CurrentMemoryContext,
     415              :                                    "hba parser context",
     416              :                                    ALLOCSET_SMALL_SIZES);
     417            4 :     oldcxt = MemoryContextSwitchTo(hbacxt);
     418           32 :     foreach(line, hba_lines)
     419              :     {
     420           28 :         TokenizedAuthLine *tok_line = (TokenizedAuthLine *) lfirst(line);
     421           28 :         HbaLine    *hbaline = NULL;
     422              : 
     423              :         /* don't parse lines that already have errors */
     424           28 :         if (tok_line->err_msg == NULL)
     425           28 :             hbaline = parse_hba_line(tok_line, DEBUG3);
     426              : 
     427              :         /* No error, set a new rule number */
     428           28 :         if (tok_line->err_msg == NULL)
     429           28 :             rule_number++;
     430              : 
     431           28 :         fill_hba_line(tuple_store, tupdesc, rule_number,
     432              :                       tok_line->file_name, tok_line->line_num, hbaline,
     433           28 :                       tok_line->err_msg);
     434              :     }
     435              : 
     436              :     /* Free tokenizer memory */
     437            4 :     free_auth_file(file, 0);
     438              :     /* Free parse_hba_line memory */
     439            4 :     MemoryContextSwitchTo(oldcxt);
     440            4 :     MemoryContextDelete(hbacxt);
     441            4 : }
     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            4 : 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            4 :     InitMaterializedSRF(fcinfo, 0);
     461              : 
     462              :     /* Fill the tuplestore */
     463            4 :     rsi = (ReturnSetInfo *) fcinfo->resultinfo;
     464            4 :     fill_hba_view(rsi->setResult, rsi->setDesc);
     465              : 
     466            4 :     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            3 : fill_ident_view(Tuplestorestate *tuple_store, TupleDesc tupdesc)
     542              : {
     543              :     FILE       *file;
     544            3 :     List       *ident_lines = NIL;
     545              :     ListCell   *line;
     546            3 :     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            3 :     file = open_auth_file(IdentFileName, ERROR, 0, NULL);
     557              : 
     558            3 :     tokenize_auth_file(IdentFileName, file, &ident_lines, DEBUG3, 0);
     559              : 
     560              :     /* Now parse all the lines */
     561            3 :     identcxt = AllocSetContextCreate(CurrentMemoryContext,
     562              :                                      "ident parser context",
     563              :                                      ALLOCSET_SMALL_SIZES);
     564            3 :     oldcxt = MemoryContextSwitchTo(identcxt);
     565            3 :     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            3 :     free_auth_file(file, 0);
     585              :     /* Free parse_ident_line memory */
     586            3 :     MemoryContextSwitchTo(oldcxt);
     587            3 :     MemoryContextDelete(identcxt);
     588            3 : }
     589              : 
     590              : /*
     591              :  * SQL-accessible SRF to return all the entries in the pg_ident.conf file.
     592              :  */
     593              : Datum
     594            3 : 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            3 :     InitMaterializedSRF(fcinfo, 0);
     605              : 
     606              :     /* Fill the tuplestore */
     607            3 :     rsi = (ReturnSetInfo *) fcinfo->resultinfo;
     608            3 :     fill_ident_view(rsi->setResult, rsi->setDesc);
     609              : 
     610            3 :     PG_RETURN_NULL();
     611              : }
        

Generated by: LCOV version 2.0-1