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 17:13:01 Functions: 85.7 % 7 6 1 6 1 6
Baseline: 15 Line coverage date bins:
Baseline Date: 2023-04-08 15:09:40 (60,120] days: 0.0 % 2 0 2
Legend: Lines: hit not hit (120,180] days: 60.7 % 28 17 11 1 1 15
(240..) days: 48.2 % 199 96 1 20 50 32 15 52 29 63 52
Function coverage date bins:
(240..) days: 46.2 % 13 6 1 6 1 5

 Age         Owner                  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 *
  381 michael                    53 GIC          28 : get_hba_options(HbaLine *hba)
                                 54                 : {
  381 michael                    55 ECB             :     int         noptions;
                                 56                 :     Datum       options[MAX_HBA_OPTIONS];
                                 57                 : 
  381 michael                    58 GIC          28 :     noptions = 0;
                                 59                 : 
  381 michael                    60 CBC          28 :     if (hba->auth_method == uaGSS || hba->auth_method == uaSSPI)
                                 61                 :     {
  381 michael                    62 LBC           0 :         if (hba->include_realm)
  381 michael                    63 UIC           0 :             options[noptions++] =
  381 michael                    64 UBC           0 :                 CStringGetTextDatum("include_realm=true");
  381 michael                    65 EUB             : 
  381 michael                    66 UBC           0 :         if (hba->krb_realm)
  381 michael                    67 UIC           0 :             options[noptions++] =
  381 michael                    68 UBC           0 :                 CStringGetTextDatum(psprintf("krb_realm=%s", hba->krb_realm));
  381 michael                    69 EUB             :     }
                                 70                 : 
  381 michael                    71 GIC          28 :     if (hba->usermap)
  381 michael                    72 UIC           0 :         options[noptions++] =
  381 michael                    73 LBC           0 :             CStringGetTextDatum(psprintf("map=%s", hba->usermap));
  381 michael                    74 EUB             : 
  381 michael                    75 GBC          28 :     if (hba->clientcert != clientCertOff)
  381 michael                    76 UIC           0 :         options[noptions++] =
  381 michael                    77 LBC           0 :             CStringGetTextDatum(psprintf("clientcert=%s", (hba->clientcert == clientCertCA) ? "verify-ca" : "verify-full"));
  381 michael                    78 EUB             : 
  381 michael                    79 GBC          28 :     if (hba->pamservice)
  381 michael                    80 UIC           0 :         options[noptions++] =
  381 michael                    81 LBC           0 :             CStringGetTextDatum(psprintf("pamservice=%s", hba->pamservice));
  381 michael                    82 EUB             : 
  381 michael                    83 GBC          28 :     if (hba->auth_method == uaLDAP)
                                 84                 :     {
  381 michael                    85 LBC           0 :         if (hba->ldapserver)
  381 michael                    86 UIC           0 :             options[noptions++] =
  381 michael                    87 UBC           0 :                 CStringGetTextDatum(psprintf("ldapserver=%s", hba->ldapserver));
  381 michael                    88 EUB             : 
  381 michael                    89 UBC           0 :         if (hba->ldapport)
  381 michael                    90 UIC           0 :             options[noptions++] =
  381 michael                    91 UBC           0 :                 CStringGetTextDatum(psprintf("ldapport=%d", hba->ldapport));
  381 michael                    92 EUB             : 
  381 michael                    93 UBC           0 :         if (hba->ldaptls)
  381 michael                    94 UIC           0 :             options[noptions++] =
  381 michael                    95 UBC           0 :                 CStringGetTextDatum("ldaptls=true");
  381 michael                    96 EUB             : 
  381 michael                    97 UBC           0 :         if (hba->ldapprefix)
  381 michael                    98 UIC           0 :             options[noptions++] =
  381 michael                    99 UBC           0 :                 CStringGetTextDatum(psprintf("ldapprefix=%s", hba->ldapprefix));
  381 michael                   100 EUB             : 
  381 michael                   101 UBC           0 :         if (hba->ldapsuffix)
  381 michael                   102 UIC           0 :             options[noptions++] =
  381 michael                   103 UBC           0 :                 CStringGetTextDatum(psprintf("ldapsuffix=%s", hba->ldapsuffix));
  381 michael                   104 EUB             : 
  381 michael                   105 UBC           0 :         if (hba->ldapbasedn)
  381 michael                   106 UIC           0 :             options[noptions++] =
  381 michael                   107 UBC           0 :                 CStringGetTextDatum(psprintf("ldapbasedn=%s", hba->ldapbasedn));
  381 michael                   108 EUB             : 
  381 michael                   109 UBC           0 :         if (hba->ldapbinddn)
  381 michael                   110 UIC           0 :             options[noptions++] =
  381 michael                   111 UBC           0 :                 CStringGetTextDatum(psprintf("ldapbinddn=%s", hba->ldapbinddn));
  381 michael                   112 EUB             : 
  381 michael                   113 UBC           0 :         if (hba->ldapbindpasswd)
  381 michael                   114 UIC           0 :             options[noptions++] =
  381 michael                   115 UBC           0 :                 CStringGetTextDatum(psprintf("ldapbindpasswd=%s",
  381 michael                   116 EUB             :                                              hba->ldapbindpasswd));
                                117                 : 
  381 michael                   118 UIC           0 :         if (hba->ldapsearchattribute)
                                119               0 :             options[noptions++] =
  381 michael                   120 UBC           0 :                 CStringGetTextDatum(psprintf("ldapsearchattribute=%s",
  381 michael                   121 EUB             :                                              hba->ldapsearchattribute));
                                122                 : 
  381 michael                   123 UIC           0 :         if (hba->ldapsearchfilter)
                                124               0 :             options[noptions++] =
  381 michael                   125 UBC           0 :                 CStringGetTextDatum(psprintf("ldapsearchfilter=%s",
  381 michael                   126 EUB             :                                              hba->ldapsearchfilter));
                                127                 : 
  381 michael                   128 UIC           0 :         if (hba->ldapscope)
                                129               0 :             options[noptions++] =
  381 michael                   130 UBC           0 :                 CStringGetTextDatum(psprintf("ldapscope=%d", hba->ldapscope));
  381 michael                   131 EUB             :     }
                                132                 : 
  381 michael                   133 GIC          28 :     if (hba->auth_method == uaRADIUS)
                                134                 :     {
  381 michael                   135 LBC           0 :         if (hba->radiusservers_s)
  381 michael                   136 UIC           0 :             options[noptions++] =
  381 michael                   137 UBC           0 :                 CStringGetTextDatum(psprintf("radiusservers=%s", hba->radiusservers_s));
  381 michael                   138 EUB             : 
  381 michael                   139 UBC           0 :         if (hba->radiussecrets_s)
  381 michael                   140 UIC           0 :             options[noptions++] =
  381 michael                   141 UBC           0 :                 CStringGetTextDatum(psprintf("radiussecrets=%s", hba->radiussecrets_s));
  381 michael                   142 EUB             : 
  381 michael                   143 UBC           0 :         if (hba->radiusidentifiers_s)
  381 michael                   144 UIC           0 :             options[noptions++] =
  381 michael                   145 UBC           0 :                 CStringGetTextDatum(psprintf("radiusidentifiers=%s", hba->radiusidentifiers_s));
  381 michael                   146 EUB             : 
  381 michael                   147 UBC           0 :         if (hba->radiusports_s)
  381 michael                   148 UIC           0 :             options[noptions++] =
  381 michael                   149 UBC           0 :                 CStringGetTextDatum(psprintf("radiusports=%s", hba->radiusports_s));
  381 michael                   150 EUB             :     }
                                151                 : 
                                152                 :     /* If you add more options, consider increasing MAX_HBA_OPTIONS. */
  381 michael                   153 GIC          28 :     Assert(noptions <= MAX_HBA_OPTIONS);
                                154                 : 
  381 michael                   155 CBC          28 :     if (noptions > 0)
  282 peter                     156 UNC           0 :         return construct_array_builtin(options, noptions, TEXTOID);
  381 michael                   157 ECB             :     else
  381 michael                   158 GBC          28 :         return NULL;
                                159                 : }
  381 michael                   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
  381 michael                   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];
  381 michael                   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                 : 
  381 michael                   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;
  381 michael                   200 ECB             : 
                                201                 :     /* rule_number, nothing on error */
  165 michael                   202 GNC          28 :     if (err_msg)
  165 michael                   203 UNC           0 :         nulls[index++] = true;
                                204                 :     else
  165 michael                   205 GNC          28 :         values[index++] = Int32GetDatum(rule_number);
                                206                 : 
                                207                 :     /* file_name */
  136                           208              28 :     values[index++] = CStringGetTextDatum(filename);
                                209                 : 
                                210                 :     /* line_number */
  381 michael                   211 CBC          28 :     values[index++] = Int32GetDatum(lineno);
  381 michael                   212 ECB             : 
  381 michael                   213 CBC          28 :     if (hba != NULL)
                                214                 :     {
                                215                 :         /* type */
  381 michael                   216 ECB             :         /* Avoid a default: case so compiler will warn about missing cases */
  381 michael                   217 GBC          28 :         typestr = NULL;
  381 michael                   218 GIC          28 :         switch (hba->conntype)
  381 michael                   219 ECB             :         {
  381 michael                   220 GIC          16 :             case ctLocal:
                                221              16 :                 typestr = "local";
  381 michael                   222 CBC          16 :                 break;
  381 michael                   223 GIC          12 :             case ctHost:
                                224              12 :                 typestr = "host";
  381 michael                   225 CBC          12 :                 break;
  381 michael                   226 UIC           0 :             case ctHostSSL:
  381 michael                   227 LBC           0 :                 typestr = "hostssl";
  381 michael                   228 UIC           0 :                 break;
                                229               0 :             case ctHostNoSSL:
                                230               0 :                 typestr = "hostnossl";
  381 michael                   231 LBC           0 :                 break;
                                232               0 :             case ctHostGSS:
  381 michael                   233 UIC           0 :                 typestr = "hostgssenc";
  381 michael                   234 LBC           0 :                 break;
                                235               0 :             case ctHostNoGSS:
                                236               0 :                 typestr = "hostnogssenc";
                                237               0 :                 break;
  381 michael                   238 ECB             :         }
  381 michael                   239 CBC          28 :         if (typestr)
  381 michael                   240 GBC          28 :             values[index++] = CStringGetTextDatum(typestr);
  381 michael                   241 EUB             :         else
  381 michael                   242 UBC           0 :             nulls[index++] = true;
  381 michael                   243 EUB             : 
                                244                 :         /* database */
  381 michael                   245 GBC          28 :         if (hba->databases)
  381 michael                   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
  381 michael                   253 ECB             :              * databases/roles that way are inflicting their own pain.
                                254                 :              */
  381 michael                   255 GIC          28 :             List       *names = NIL;
  381 michael                   256 EUB             : 
  381 michael                   257 GIC          57 :             foreach(lc, hba->databases)
                                258                 :             {
  381 michael                   259 CBC          29 :                 AuthToken  *tok = lfirst(lc);
                                260                 : 
  381 michael                   261 GIC          29 :                 names = lappend(names, tok->string);
                                262                 :             }
                                263              28 :             values[index++] = PointerGetDatum(strlist_to_textarray(names));
                                264                 :         }
                                265                 :         else
  381 michael                   266 UIC           0 :             nulls[index++] = true;
                                267                 : 
                                268                 :         /* user */
  381 michael                   269 CBC          28 :         if (hba->roles)
                                270                 :         {
  381 michael                   271 ECB             :             /* Flatten AuthToken list to string list; see comment above */
  381 michael                   272 GIC          28 :             List       *roles = NIL;
  381 michael                   273 ECB             : 
  381 michael                   274 GIC          56 :             foreach(lc, hba->roles)
  381 michael                   275 ECB             :             {
  381 michael                   276 GIC          28 :                 AuthToken  *tok = lfirst(lc);
  381 michael                   277 ECB             : 
  381 michael                   278 GIC          28 :                 roles = lappend(roles, tok->string);
                                279                 :             }
  381 michael                   280 GBC          28 :             values[index++] = PointerGetDatum(strlist_to_textarray(roles));
                                281                 :         }
                                282                 :         else
  381 michael                   283 LBC           0 :             nulls[index++] = true;
                                284                 : 
                                285                 :         /* address and netmask */
  381 michael                   286 ECB             :         /* Avoid a default: case so compiler will warn about missing cases */
  381 michael                   287 GIC          28 :         addrstr = maskstr = NULL;
  381 michael                   288 CBC          28 :         switch (hba->ip_cmp_method)
                                289                 :         {
                                290              28 :             case ipCmpMask:
  381 michael                   291 GIC          28 :                 if (hba->hostname)
  381 michael                   292 ECB             :                 {
  381 michael                   293 UIC           0 :                     addrstr = hba->hostname;
  381 michael                   294 ECB             :                 }
                                295                 :                 else
                                296                 :                 {
  381 michael                   297 EUB             :                     /*
                                298                 :                      * Note: if pg_getnameinfo_all fails, it'll set buffer to
                                299                 :                      * "???", which we want to return.
                                300                 :                      */
  381 michael                   301 CBC          28 :                     if (hba->addrlen > 0)
  381 michael                   302 ECB             :                     {
  381 michael                   303 GIC          12 :                         if (pg_getnameinfo_all(&hba->addr, hba->addrlen,
  381 michael                   304 ECB             :                                                buffer, sizeof(buffer),
                                305                 :                                                NULL, 0,
                                306                 :                                                NI_NUMERICHOST) == 0)
  381 michael                   307 GBC          12 :                             clean_ipv6_addr(hba->addr.ss_family, buffer);
  381 michael                   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,
  381 michael                   315 ECB             :                                                NI_NUMERICHOST) == 0)
  381 michael                   316 GIC          12 :                             clean_ipv6_addr(hba->mask.ss_family, buffer);
  381 michael                   317 CBC          12 :                         maskstr = pstrdup(buffer);
                                318                 :                     }
                                319                 :                 }
  381 michael                   320 GIC          28 :                 break;
  381 michael                   321 LBC           0 :             case ipCmpAll:
                                322               0 :                 addrstr = "all";
  381 michael                   323 UIC           0 :                 break;
  381 michael                   324 LBC           0 :             case ipCmpSameHost:
  381 michael                   325 UIC           0 :                 addrstr = "samehost";
  381 michael                   326 LBC           0 :                 break;
  381 michael                   327 UIC           0 :             case ipCmpSameNet:
                                328               0 :                 addrstr = "samenet";
                                329               0 :                 break;
  381 michael                   330 ECB             :         }
  381 michael                   331 CBC          28 :         if (addrstr)
  381 michael                   332 GIC          12 :             values[index++] = CStringGetTextDatum(addrstr);
                                333                 :         else
  381 michael                   334 CBC          16 :             nulls[index++] = true;
  381 michael                   335 GBC          28 :         if (maskstr)
                                336              12 :             values[index++] = CStringGetTextDatum(maskstr);
  381 michael                   337 EUB             :         else
  381 michael                   338 GBC          16 :             nulls[index++] = true;
  381 michael                   339 EUB             : 
                                340                 :         /* auth_method */
  381 michael                   341 GBC          28 :         values[index++] = CStringGetTextDatum(hba_authname(hba->auth_method));
  381 michael                   342 EUB             : 
                                343                 :         /* options */
  381 michael                   344 GIC          28 :         options = get_hba_options(hba);
  381 michael                   345 CBC          28 :         if (options)
  381 michael                   346 LBC           0 :             values[index++] = PointerGetDatum(options);
                                347                 :         else
  381 michael                   348 CBC          28 :             nulls[index++] = true;
  381 michael                   349 ECB             :     }
                                350                 :     else
                                351                 :     {
                                352                 :         /* no parsing result, so set relevant fields to nulls */
  136 michael                   353 UNC           0 :         memset(&nulls[3], true, (NUM_PG_HBA_FILE_RULES_ATTS - 4) * sizeof(bool));
                                354                 :     }
  381 michael                   355 ECB             : 
                                356                 :     /* error */
  381 michael                   357 GIC          28 :     if (err_msg)
  381 michael                   358 LBC           0 :         values[NUM_PG_HBA_FILE_RULES_ATTS - 1] = CStringGetTextDatum(err_msg);
  381 michael                   359 ECB             :     else
  381 michael                   360 GBC          28 :         nulls[NUM_PG_HBA_FILE_RULES_ATTS - 1] = true;
                                361                 : 
  381 michael                   362 CBC          28 :     tuple = heap_form_tuple(tupdesc, values, nulls);
  381 michael                   363 GIC          28 :     tuplestore_puttuple(tuple_store, tuple);
                                364              28 : }
                                365                 : 
                                366                 : /*
  381 michael                   367 EUB             :  * fill_hba_view
                                368                 :  *      Read the pg_hba.conf file and fill the tuplestore with view records.
                                369                 :  */
                                370                 : static void
  381 michael                   371 CBC           4 : fill_hba_view(Tuplestorestate *tuple_store, TupleDesc tupdesc)
  381 michael                   372 EUB             : {
                                373                 :     FILE       *file;
  381 michael                   374 CBC           4 :     List       *hba_lines = NIL;
                                375                 :     ListCell   *line;
  165 michael                   376 GNC           4 :     int         rule_number = 0;
  381 michael                   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                 :      */
  146 michael                   386 GNC           4 :     file = open_auth_file(HbaFileName, ERROR, 0, NULL);
                                387                 : 
  136                           388               4 :     tokenize_auth_file(HbaFileName, file, &hba_lines, DEBUG3, 0);
                                389                 : 
                                390                 :     /* Now parse all the lines */
  381 michael                   391 GIC           4 :     hbacxt = AllocSetContextCreate(CurrentMemoryContext,
                                392                 :                                    "hba parser context",
                                393                 :                                    ALLOCSET_SMALL_SIZES);
  381 michael                   394 CBC           4 :     oldcxt = MemoryContextSwitchTo(hbacxt);
  381 michael                   395 GIC          32 :     foreach(line, hba_lines)
  381 michael                   396 ECB             :     {
  381 michael                   397 GIC          28 :         TokenizedAuthLine *tok_line = (TokenizedAuthLine *) lfirst(line);
                                398              28 :         HbaLine    *hbaline = NULL;
  381 michael                   399 ECB             : 
                                400                 :         /* don't parse lines that already have errors */
  381 michael                   401 GIC          28 :         if (tok_line->err_msg == NULL)
  381 michael                   402 CBC          28 :             hbaline = parse_hba_line(tok_line, DEBUG3);
  381 michael                   403 ECB             : 
                                404                 :         /* No error, set a new rule number */
  165 michael                   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,
  136                           410              28 :                       tok_line->err_msg);
  381 michael                   411 ECB             :     }
                                412                 : 
                                413                 :     /* Free tokenizer memory */
  136 michael                   414 GNC           4 :     free_auth_file(file, 0);
  381 michael                   415 ECB             :     /* Free parse_hba_line memory */
  381 michael                   416 GIC           4 :     MemoryContextSwitchTo(oldcxt);
                                417               4 :     MemoryContextDelete(hbacxt);
  381 michael                   418 CBC           4 : }
  381 michael                   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
  381 michael                   427 CBC           4 : pg_hba_file_rules(PG_FUNCTION_ARGS)
                                428                 : {
  381 michael                   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                 :      */
  173 michael                   437 GIC           4 :     InitMaterializedSRF(fcinfo, 0);
                                438                 : 
                                439                 :     /* Fill the tuplestore */
  381 michael                   440 CBC           4 :     rsi = (ReturnSetInfo *) fcinfo->resultinfo;
  381 michael                   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                 : /*
  376 michael                   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
  376 michael                   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 */
  165 michael                   481 UNC           0 :     if (err_msg)
                                482               0 :         nulls[index++] = true;
                                483                 :     else
                                484               0 :         values[index++] = Int32GetDatum(map_number);
                                485                 : 
                                486                 :     /* file_name */
  136                           487               0 :     values[index++] = CStringGetTextDatum(filename);
                                488                 : 
                                489                 :     /* line_number */
  376 michael                   490 UBC           0 :     values[index++] = Int32GetDatum(lineno);
                                491                 : 
  376 michael                   492 UIC           0 :     if (ident != NULL)
                                493                 :     {
                                494               0 :         values[index++] = CStringGetTextDatum(ident->usermap);
   87 michael                   495 UNC           0 :         values[index++] = CStringGetTextDatum(ident->system_user->string);
   83                           496               0 :         values[index++] = CStringGetTextDatum(ident->pg_user->string);
                                497                 :     }
                                498                 :     else
  376 michael                   499 EUB             :     {
                                500                 :         /* no parsing result, so set relevant fields to nulls */
  136 michael                   501 UNC           0 :         memset(&nulls[3], true, (NUM_PG_IDENT_FILE_MAPPINGS_ATTS - 4) * sizeof(bool));
  376 michael                   502 EUB             :     }
                                503                 : 
                                504                 :     /* error */
  376 michael                   505 UIC           0 :     if (err_msg)
  376 michael                   506 UBC           0 :         values[NUM_PG_IDENT_FILE_MAPPINGS_ATTS - 1] = CStringGetTextDatum(err_msg);
  376 michael                   507 EUB             :     else
  376 michael                   508 UIC           0 :         nulls[NUM_PG_IDENT_FILE_MAPPINGS_ATTS - 1] = true;
  376 michael                   509 EUB             : 
  376 michael                   510 UIC           0 :     tuple = heap_form_tuple(tupdesc, values, nulls);
                                511               0 :     tuplestore_puttuple(tuple_store, tuple);
  376 michael                   512 UBC           0 : }
                                513                 : 
                                514                 : /*
  376 michael                   515 EUB             :  * Read the pg_ident.conf file and fill the tuplestore with view records.
                                516                 :  */
                                517                 : static void
  376 michael                   518 GIC           3 : fill_ident_view(Tuplestorestate *tuple_store, TupleDesc tupdesc)
  376 michael                   519 EUB             : {
                                520                 :     FILE       *file;
  376 michael                   521 GBC           3 :     List       *ident_lines = NIL;
                                522                 :     ListCell   *line;
  165 michael                   523 GNC           3 :     int         map_number = 0;
                                524                 :     MemoryContext identcxt;
                                525                 :     MemoryContext oldcxt;
  376 michael                   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                 :      */
  146 michael                   533 GNC           3 :     file = open_auth_file(IdentFileName, ERROR, 0, NULL);
                                534                 : 
  136                           535               3 :     tokenize_auth_file(IdentFileName, file, &ident_lines, DEBUG3, 0);
                                536                 : 
  376 michael                   537 ECB             :     /* Now parse all the lines */
  376 michael                   538 GIC           3 :     identcxt = AllocSetContextCreate(CurrentMemoryContext,
                                539                 :                                      "ident parser context",
  376 michael                   540 ECB             :                                      ALLOCSET_SMALL_SIZES);
  376 michael                   541 GIC           3 :     oldcxt = MemoryContextSwitchTo(identcxt);
  376 michael                   542 CBC           3 :     foreach(line, ident_lines)
                                543                 :     {
  376 michael                   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 */
  165 michael                   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,
  136                           557               0 :                         identline, tok_line->err_msg);
                                558                 :     }
  376 michael                   559 ECB             : 
                                560                 :     /* Free tokenizer memory */
  136 michael                   561 GNC           3 :     free_auth_file(file, 0);
  376 michael                   562 ECB             :     /* Free parse_ident_line memory */
  376 michael                   563 GIC           3 :     MemoryContextSwitchTo(oldcxt);
                                564               3 :     MemoryContextDelete(identcxt);
  376 michael                   565 CBC           3 : }
  376 michael                   566 ECB             : 
                                567                 : /*
  376 michael                   568 EUB             :  * SQL-accessible SRF to return all the entries in the pg_ident.conf file.
                                569                 :  */
                                570                 : Datum
  376 michael                   571 GIC           3 : pg_ident_file_mappings(PG_FUNCTION_ARGS)
  376 michael                   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                 :      */
  173 michael                   581 GBC           3 :     InitMaterializedSRF(fcinfo, 0);
                                582                 : 
                                583                 :     /* Fill the tuplestore */
  376 michael                   584 GIC           3 :     rsi = (ReturnSetInfo *) fcinfo->resultinfo;
  376 michael                   585 CBC           3 :     fill_ident_view(rsi->setResult, rsi->setDesc);
                                586                 : 
                                587               3 :     PG_RETURN_NULL();
  376 michael                   588 ECB             : }
        

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