LCOV - differential code coverage report
Current view: top level - src/backend/utils/adt - hbafuncs.c (source / functions) Coverage Total Hit UNC LBC UIC UBC GBC GIC GNC CBC EUB ECB DUB DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 49.3 % 229 113 14 20 50 32 16 53 15 29 63 58 5 6
Current Date: 2023-04-08 15:15:32 Functions: 85.7 % 7 6 1 6 1 6
Baseline: 15
Baseline Date: 2023-04-08 15:09:40
Legend: Lines: hit not hit

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

Generated by: LCOV version v1.16-55-g56c0a2a