PostgreSQL Source Code  git master
hba.c File Reference
#include "postgres.h"
#include <ctype.h>
#include <pwd.h>
#include <fcntl.h>
#include <sys/param.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include "access/htup_details.h"
#include "catalog/pg_collation.h"
#include "catalog/pg_type.h"
#include "common/ip.h"
#include "common/string.h"
#include "funcapi.h"
#include "libpq/ifaddr.h"
#include "libpq/libpq.h"
#include "miscadmin.h"
#include "postmaster/postmaster.h"
#include "regex/regex.h"
#include "replication/walsender.h"
#include "storage/fd.h"
#include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/guc.h"
#include "utils/lsyscache.h"
#include "utils/memutils.h"
#include "utils/varlena.h"
Include dependency graph for hba.c:

Go to the source code of this file.

Data Structures

struct  check_network_data
 
struct  HbaToken
 
struct  TokenizedLine
 

Macros

#define MAX_TOKEN   256
 
#define token_is_keyword(t, k)   (!t->quoted && strcmp(t->string, k) == 0)
 
#define token_matches(t, k)   (strcmp(t->string, k) == 0)
 
#define INVALID_AUTH_OPTION(optname, validmethods)
 
#define REQUIRE_AUTH_OPTION(methodval, optname, validmethods)
 
#define MANDATORY_AUTH_ARG(argvar, argname, authname)
 
#define IDENT_FIELD_ABSENT(field)
 
#define IDENT_MULTI_VALUE(tokens)
 
#define MAX_HBA_OPTIONS   14
 
#define NUM_PG_HBA_FILE_RULES_ATTS   9
 

Typedefs

typedef struct check_network_data check_network_data
 
typedef struct HbaToken HbaToken
 
typedef struct TokenizedLine TokenizedLine
 

Functions

static MemoryContext tokenize_file (const char *filename, FILE *file, List **tok_lines, int elevel)
 
static Listtokenize_inc_file (List *tokens, const char *outer_filename, const char *inc_filename, int elevel, char **err_msg)
 
static bool parse_hba_auth_opt (char *name, char *val, HbaLine *hbaline, int elevel, char **err_msg)
 
static bool verify_option_list_length (List *options, const char *optionname, List *comparelist, const char *comparename, int line_num)
 
static ArrayTypegethba_options (HbaLine *hba)
 
static void fill_hba_line (Tuplestorestate *tuple_store, TupleDesc tupdesc, int lineno, HbaLine *hba, const char *err_msg)
 
static void fill_hba_view (Tuplestorestate *tuple_store, TupleDesc tupdesc)
 
bool pg_isblank (const char c)
 
static bool next_token (char **lineptr, char *buf, int bufsz, bool *initial_quote, bool *terminating_comma, int elevel, char **err_msg)
 
static HbaTokenmake_hba_token (const char *token, bool quoted)
 
static HbaTokencopy_hba_token (HbaToken *in)
 
static Listnext_field_expand (const char *filename, char **lineptr, int elevel, char **err_msg)
 
static bool is_member (Oid userid, const char *role)
 
static bool check_role (const char *role, Oid roleid, List *tokens)
 
static bool check_db (const char *dbname, const char *role, Oid roleid, List *tokens)
 
static bool ipv4eq (struct sockaddr_in *a, struct sockaddr_in *b)
 
static bool hostname_match (const char *pattern, const char *actual_hostname)
 
static bool check_hostname (hbaPort *port, const char *hostname)
 
static bool check_ip (SockAddr *raddr, struct sockaddr *addr, struct sockaddr *mask)
 
static void check_network_callback (struct sockaddr *addr, struct sockaddr *netmask, void *cb_data)
 
static bool check_same_host_or_net (SockAddr *raddr, IPCompareMethod method)
 
static HbaLineparse_hba_line (TokenizedLine *tok_line, int elevel)
 
static void check_hba (hbaPort *port)
 
bool load_hba (void)
 
Datum pg_hba_file_rules (PG_FUNCTION_ARGS)
 
static IdentLineparse_ident_line (TokenizedLine *tok_line)
 
static void check_ident_usermap (IdentLine *identLine, const char *usermap_name, const char *pg_role, const char *ident_user, bool case_insensitive, bool *found_p, bool *error_p)
 
int check_usermap (const char *usermap_name, const char *pg_role, const char *auth_user, bool case_insensitive)
 
bool load_ident (void)
 
void hba_getauthmethod (hbaPort *port)
 
const char * hba_authname (UserAuth auth_method)
 

Variables

static Listparsed_hba_lines = NIL
 
static MemoryContext parsed_hba_context = NULL
 
static Listparsed_ident_lines = NIL
 
static MemoryContext parsed_ident_context = NULL
 
static const char *const UserAuthName []
 

Macro Definition Documentation

◆ IDENT_FIELD_ABSENT

#define IDENT_FIELD_ABSENT (   field)
Value:
do { \
if (!field) { \
ereport(LOG, \
(errcode(ERRCODE_CONFIG_FILE_ERROR), \
errmsg("missing entry in file \"%s\" at end of line %d", \
IdentFileName, line_num))); \
return NULL; \
} \
} while (0)
int errcode(int sqlerrcode)
Definition: elog.c:698
#define LOG
Definition: elog.h:26
char * IdentFileName
Definition: guc.c:585
int errmsg(const char *fmt,...)
Definition: elog.c:909

Definition at line 931 of file hba.c.

Referenced by parse_ident_line().

◆ IDENT_MULTI_VALUE

#define IDENT_MULTI_VALUE (   tokens)
Value:
do { \
if (tokens->length > 1) { \
ereport(LOG, \
(errcode(ERRCODE_CONFIG_FILE_ERROR), \
errmsg("multiple values in ident field"), \
errcontext("line %d of configuration file \"%s\"", \
line_num, IdentFileName))); \
return NULL; \
} \
} while (0)
int errcode(int sqlerrcode)
Definition: elog.c:698
#define LOG
Definition: elog.h:26
char * IdentFileName
Definition: guc.c:585
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define errcontext
Definition: elog.h:204

Definition at line 942 of file hba.c.

Referenced by parse_ident_line().

◆ INVALID_AUTH_OPTION

#define INVALID_AUTH_OPTION (   optname,
  validmethods 
)
Value:
do { \
ereport(elevel, \
(errcode(ERRCODE_CONFIG_FILE_ERROR), \
/* translator: the second %s is a list of auth methods */ \
errmsg("authentication option \"%s\" is only valid for authentication methods %s", \
optname, _(validmethods)), \
errcontext("line %d of configuration file \"%s\"", \
line_num, HbaFileName))); \
*err_msg = psprintf("authentication option \"%s\" is only valid for authentication methods %s", \
optname, validmethods); \
return false; \
} while (0)
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46
int errcode(int sqlerrcode)
Definition: elog.c:698
char * HbaFileName
Definition: guc.c:584
static int elevel
Definition: vacuumlazy.c:400
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define errcontext
Definition: elog.h:204
#define _(x)
Definition: elog.c:89

Definition at line 883 of file hba.c.

Referenced by parse_hba_auth_opt().

◆ MANDATORY_AUTH_ARG

#define MANDATORY_AUTH_ARG (   argvar,
  argname,
  authname 
)
Value:
do { \
if (argvar == NULL) { \
ereport(elevel, \
(errcode(ERRCODE_CONFIG_FILE_ERROR), \
errmsg("authentication method \"%s\" requires argument \"%s\" to be set", \
authname, argname), \
errcontext("line %d of configuration file \"%s\"", \
line_num, HbaFileName))); \
*err_msg = psprintf("authentication method \"%s\" requires argument \"%s\" to be set", \
authname, argname); \
return NULL; \
} \
} while (0)
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46
int errcode(int sqlerrcode)
Definition: elog.c:698
char * HbaFileName
Definition: guc.c:584
static int elevel
Definition: vacuumlazy.c:400
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define errcontext
Definition: elog.h:204

Definition at line 903 of file hba.c.

Referenced by parse_hba_line().

◆ MAX_HBA_OPTIONS

#define MAX_HBA_OPTIONS   14

Definition at line 2329 of file hba.c.

Referenced by gethba_options().

◆ MAX_TOKEN

#define MAX_TOKEN   256

Definition at line 57 of file hba.c.

Referenced by next_field_expand().

◆ NUM_PG_HBA_FILE_RULES_ATTS

#define NUM_PG_HBA_FILE_RULES_ATTS   9

Definition at line 2445 of file hba.c.

Referenced by fill_hba_line().

◆ REQUIRE_AUTH_OPTION

#define REQUIRE_AUTH_OPTION (   methodval,
  optname,
  validmethods 
)
Value:
do { \
if (hbaline->auth_method != methodval) \
INVALID_AUTH_OPTION(optname, validmethods); \
} while (0)

Definition at line 897 of file hba.c.

Referenced by parse_hba_auth_opt().

◆ token_is_keyword

#define token_is_keyword (   t,
 
)    (!t->quoted && strcmp(t->string, k) == 0)

Definition at line 68 of file hba.c.

Referenced by check_db(), check_role(), and parse_hba_line().

◆ token_matches

#define token_matches (   t,
 
)    (strcmp(t->string, k) == 0)

Definition at line 69 of file hba.c.

Referenced by check_db(), and check_role().

Typedef Documentation

◆ check_network_data

◆ HbaToken

typedef struct HbaToken HbaToken

◆ TokenizedLine

typedef struct TokenizedLine TokenizedLine

Function Documentation

◆ check_db()

static bool check_db ( const char *  dbname,
const char *  role,
Oid  roleid,
List tokens 
)
static

Definition at line 632 of file hba.c.

References am_db_walsender, am_walsender, is_member(), lfirst, token_is_keyword, and token_matches.

Referenced by check_hba().

633 {
634  ListCell *cell;
635  HbaToken *tok;
636 
637  foreach(cell, tokens)
638  {
639  tok = lfirst(cell);
641  {
642  /*
643  * physical replication walsender connections can only match
644  * replication keyword
645  */
646  if (token_is_keyword(tok, "replication"))
647  return true;
648  }
649  else if (token_is_keyword(tok, "all"))
650  return true;
651  else if (token_is_keyword(tok, "sameuser"))
652  {
653  if (strcmp(dbname, role) == 0)
654  return true;
655  }
656  else if (token_is_keyword(tok, "samegroup") ||
657  token_is_keyword(tok, "samerole"))
658  {
659  if (is_member(roleid, dbname))
660  return true;
661  }
662  else if (token_is_keyword(tok, "replication"))
663  continue; /* never match this if not walsender */
664  else if (token_matches(tok, dbname))
665  return true;
666  }
667  return false;
668 }
#define token_matches(t, k)
Definition: hba.c:69
bool am_walsender
Definition: walsender.c:115
Definition: hba.c:75
bool am_db_walsender
Definition: walsender.c:118
#define lfirst(lc)
Definition: pg_list.h:169
char * dbname
Definition: streamutil.c:51
static bool is_member(Oid userid, const char *role)
Definition: hba.c:584
#define token_is_keyword(t, k)
Definition: hba.c:68

◆ check_hba()

static void check_hba ( hbaPort port)
static

Definition at line 2115 of file hba.c.

References SockAddr::addr, HbaLine::addr, HbaLine::auth_method, check_db(), check_hostname(), check_ip(), check_role(), check_same_host_or_net(), HbaLine::conntype, ctHostGSS, ctHostNoGSS, ctHostNoSSL, ctHostSSL, ctLocal, Port::database_name, HbaLine::databases, get_role_oid(), Port::gss, Port::hba, HbaLine::hostname, HbaLine::ip_cmp_method, ipCmpAll, ipCmpMask, ipCmpSameHost, ipCmpSameNet, IS_AF_UNIX, lfirst, HbaLine::mask, palloc0(), Port::raddr, HbaLine::roles, Port::ssl_in_use, uaImplicitReject, and Port::user_name.

Referenced by hba_getauthmethod().

2116 {
2117  Oid roleid;
2118  ListCell *line;
2119  HbaLine *hba;
2120 
2121  /* Get the target role's OID. Note we do not error out for bad role. */
2122  roleid = get_role_oid(port->user_name, true);
2123 
2124  foreach(line, parsed_hba_lines)
2125  {
2126  hba = (HbaLine *) lfirst(line);
2127 
2128  /* Check connection type */
2129  if (hba->conntype == ctLocal)
2130  {
2131  if (!IS_AF_UNIX(port->raddr.addr.ss_family))
2132  continue;
2133  }
2134  else
2135  {
2136  if (IS_AF_UNIX(port->raddr.addr.ss_family))
2137  continue;
2138 
2139  /* Check SSL state */
2140  if (port->ssl_in_use)
2141  {
2142  /* Connection is SSL, match both "host" and "hostssl" */
2143  if (hba->conntype == ctHostNoSSL)
2144  continue;
2145  }
2146  else
2147  {
2148  /* Connection is not SSL, match both "host" and "hostnossl" */
2149  if (hba->conntype == ctHostSSL)
2150  continue;
2151  }
2152 
2153  /* Check GSSAPI state */
2154 #ifdef ENABLE_GSS
2155  if (port->gss && port->gss->enc &&
2156  hba->conntype == ctHostNoGSS)
2157  continue;
2158  else if (!(port->gss && port->gss->enc) &&
2159  hba->conntype == ctHostGSS)
2160  continue;
2161 #else
2162  if (hba->conntype == ctHostGSS)
2163  continue;
2164 #endif
2165 
2166  /* Check IP address */
2167  switch (hba->ip_cmp_method)
2168  {
2169  case ipCmpMask:
2170  if (hba->hostname)
2171  {
2172  if (!check_hostname(port,
2173  hba->hostname))
2174  continue;
2175  }
2176  else
2177  {
2178  if (!check_ip(&port->raddr,
2179  (struct sockaddr *) &hba->addr,
2180  (struct sockaddr *) &hba->mask))
2181  continue;
2182  }
2183  break;
2184  case ipCmpAll:
2185  break;
2186  case ipCmpSameHost:
2187  case ipCmpSameNet:
2188  if (!check_same_host_or_net(&port->raddr,
2189  hba->ip_cmp_method))
2190  continue;
2191  break;
2192  default:
2193  /* shouldn't get here, but deem it no-match if so */
2194  continue;
2195  }
2196  } /* != ctLocal */
2197 
2198  /* Check database and role */
2199  if (!check_db(port->database_name, port->user_name, roleid,
2200  hba->databases))
2201  continue;
2202 
2203  if (!check_role(port->user_name, roleid, hba->roles))
2204  continue;
2205 
2206  /* Found a record that matched! */
2207  port->hba = hba;
2208  return;
2209  }
2210 
2211  /* If no matching entry was found, then implicitly reject. */
2212  hba = palloc0(sizeof(HbaLine));
2214  port->hba = hba;
2215 }
List * databases
Definition: hba.h:85
Definition: hba.h:80
struct sockaddr_storage mask
Definition: hba.h:89
Definition: hba.h:51
struct sockaddr_storage addr
Definition: pqcomm.h:64
bool ssl_in_use
Definition: libpq-be.h:209
unsigned int Oid
Definition: postgres_ext.h:31
static bool check_hostname(hbaPort *port, const char *hostname)
Definition: hba.c:715
static List * parsed_hba_lines
Definition: hba.c:101
Oid get_role_oid(const char *rolname, bool missing_ok)
Definition: acl.c:5094
SockAddr raddr
Definition: libpq-be.h:131
ConnType conntype
Definition: hba.h:84
Definition: hba.h:61
struct sockaddr_storage addr
Definition: hba.h:87
#define IS_AF_UNIX(fam)
Definition: ip.h:24
Definition: hba.h:63
static bool check_ip(SockAddr *raddr, struct sockaddr *addr, struct sockaddr *mask)
Definition: hba.c:808
char * user_name
Definition: libpq-be.h:146
static bool check_role(const char *role, Oid roleid, List *tokens)
Definition: hba.c:608
Definition: hba.h:59
HbaLine * hba
Definition: libpq-be.h:160
Definition: hba.h:54
void * palloc0(Size size)
Definition: mcxt.c:1093
char * hostname
Definition: hba.h:92
List * roles
Definition: hba.h:86
#define lfirst(lc)
Definition: pg_list.h:169
static bool check_db(const char *dbname, const char *role, Oid roleid, List *tokens)
Definition: hba.c:632
void * gss
Definition: libpq-be.h:203
static bool check_same_host_or_net(SockAddr *raddr, IPCompareMethod method)
Definition: hba.c:849
IPCompareMethod ip_cmp_method
Definition: hba.h:91
char * database_name
Definition: libpq-be.h:145
UserAuth auth_method
Definition: hba.h:93

◆ check_hostname()

static bool check_hostname ( hbaPort port,
const char *  hostname 
)
static

Definition at line 715 of file hba.c.

References SockAddr::addr, addrinfo::ai_addr, addrinfo::ai_next, DEBUG2, elog, freeaddrinfo, getaddrinfo, hostname_match(), ipv4eq(), NI_MAXHOST, NI_NAMEREQD, pg_getnameinfo_all(), pstrdup(), Port::raddr, Port::remote_hostname, Port::remote_hostname_errcode, Port::remote_hostname_resolv, and SockAddr::salen.

Referenced by check_hba().

716 {
717  struct addrinfo *gai_result,
718  *gai;
719  int ret;
720  bool found;
721 
722  /* Quick out if remote host name already known bad */
723  if (port->remote_hostname_resolv < 0)
724  return false;
725 
726  /* Lookup remote host name if not already done */
727  if (!port->remote_hostname)
728  {
729  char remote_hostname[NI_MAXHOST];
730 
731  ret = pg_getnameinfo_all(&port->raddr.addr, port->raddr.salen,
732  remote_hostname, sizeof(remote_hostname),
733  NULL, 0,
734  NI_NAMEREQD);
735  if (ret != 0)
736  {
737  /* remember failure; don't complain in the postmaster log yet */
738  port->remote_hostname_resolv = -2;
739  port->remote_hostname_errcode = ret;
740  return false;
741  }
742 
743  port->remote_hostname = pstrdup(remote_hostname);
744  }
745 
746  /* Now see if remote host name matches this pg_hba line */
748  return false;
749 
750  /* If we already verified the forward lookup, we're done */
751  if (port->remote_hostname_resolv == +1)
752  return true;
753 
754  /* Lookup IP from host name and check against original IP */
755  ret = getaddrinfo(port->remote_hostname, NULL, NULL, &gai_result);
756  if (ret != 0)
757  {
758  /* remember failure; don't complain in the postmaster log yet */
759  port->remote_hostname_resolv = -2;
760  port->remote_hostname_errcode = ret;
761  return false;
762  }
763 
764  found = false;
765  for (gai = gai_result; gai; gai = gai->ai_next)
766  {
767  if (gai->ai_addr->sa_family == port->raddr.addr.ss_family)
768  {
769  if (gai->ai_addr->sa_family == AF_INET)
770  {
771  if (ipv4eq((struct sockaddr_in *) gai->ai_addr,
772  (struct sockaddr_in *) &port->raddr.addr))
773  {
774  found = true;
775  break;
776  }
777  }
778 #ifdef HAVE_IPV6
779  else if (gai->ai_addr->sa_family == AF_INET6)
780  {
781  if (ipv6eq((struct sockaddr_in6 *) gai->ai_addr,
782  (struct sockaddr_in6 *) &port->raddr.addr))
783  {
784  found = true;
785  break;
786  }
787  }
788 #endif
789  }
790  }
791 
792  if (gai_result)
793  freeaddrinfo(gai_result);
794 
795  if (!found)
796  elog(DEBUG2, "pg_hba.conf host name \"%s\" rejected because address resolution did not return a match with IP address of client",
797  hostname);
798 
799  port->remote_hostname_resolv = found ? +1 : -1;
800 
801  return found;
802 }
#define getaddrinfo
Definition: getaddrinfo.h:136
#define NI_NAMEREQD
Definition: getaddrinfo.h:84
char * pstrdup(const char *in)
Definition: mcxt.c:1299
#define freeaddrinfo
Definition: getaddrinfo.h:141
struct sockaddr_storage addr
Definition: pqcomm.h:64
static bool ipv4eq(struct sockaddr_in *a, struct sockaddr_in *b)
Definition: hba.c:671
char * remote_hostname
Definition: libpq-be.h:133
SockAddr raddr
Definition: libpq-be.h:131
#define NI_MAXHOST
Definition: getaddrinfo.h:88
static bool hostname_match(const char *pattern, const char *actual_hostname)
Definition: hba.c:695
#define DEBUG2
Definition: elog.h:24
int remote_hostname_errcode
Definition: libpq-be.h:136
ACCEPT_TYPE_ARG3 salen
Definition: pqcomm.h:65
int pg_getnameinfo_all(const struct sockaddr_storage *addr, int salen, char *node, int nodelen, char *service, int servicelen, int flags)
Definition: ip.c:122
int remote_hostname_resolv
Definition: libpq-be.h:135
struct addrinfo * ai_next
Definition: getaddrinfo.h:107
#define elog(elevel,...)
Definition: elog.h:232
static char * hostname
Definition: pg_regress.c:91
struct sockaddr * ai_addr
Definition: getaddrinfo.h:105

◆ check_ident_usermap()

static void check_ident_usermap ( IdentLine identLine,
const char *  usermap_name,
const char *  pg_role,
const char *  ident_user,
bool  case_insensitive,
bool found_p,
bool error_p 
)
static

Definition at line 2833 of file hba.c.

References ereport, errcode(), errmsg(), IdentLine::ident_user, LOG, palloc(), palloc0(), pfree(), pg_mb2wchar_with_len(), pg_regerror(), pg_regexec(), IdentLine::pg_role, pg_strcasecmp(), pstrdup(), IdentLine::re, REG_NOMATCH, regmatch_t::rm_eo, regmatch_t::rm_so, and IdentLine::usermap.

Referenced by check_usermap().

2836 {
2837  *found_p = false;
2838  *error_p = false;
2839 
2840  if (strcmp(identLine->usermap, usermap_name) != 0)
2841  /* Line does not match the map name we're looking for, so just abort */
2842  return;
2843 
2844  /* Match? */
2845  if (identLine->ident_user[0] == '/')
2846  {
2847  /*
2848  * When system username starts with a slash, treat it as a regular
2849  * expression. In this case, we process the system username as a
2850  * regular expression that returns exactly one match. This is replaced
2851  * for \1 in the database username string, if present.
2852  */
2853  int r;
2854  regmatch_t matches[2];
2855  pg_wchar *wstr;
2856  int wlen;
2857  char *ofs;
2858  char *regexp_pgrole;
2859 
2860  wstr = palloc((strlen(ident_user) + 1) * sizeof(pg_wchar));
2861  wlen = pg_mb2wchar_with_len(ident_user, wstr, strlen(ident_user));
2862 
2863  r = pg_regexec(&identLine->re, wstr, wlen, 0, NULL, 2, matches, 0);
2864  if (r)
2865  {
2866  char errstr[100];
2867 
2868  if (r != REG_NOMATCH)
2869  {
2870  /* REG_NOMATCH is not an error, everything else is */
2871  pg_regerror(r, &identLine->re, errstr, sizeof(errstr));
2872  ereport(LOG,
2873  (errcode(ERRCODE_INVALID_REGULAR_EXPRESSION),
2874  errmsg("regular expression match for \"%s\" failed: %s",
2875  identLine->ident_user + 1, errstr)));
2876  *error_p = true;
2877  }
2878 
2879  pfree(wstr);
2880  return;
2881  }
2882  pfree(wstr);
2883 
2884  if ((ofs = strstr(identLine->pg_role, "\\1")) != NULL)
2885  {
2886  int offset;
2887 
2888  /* substitution of the first argument requested */
2889  if (matches[1].rm_so < 0)
2890  {
2891  ereport(LOG,
2892  (errcode(ERRCODE_INVALID_REGULAR_EXPRESSION),
2893  errmsg("regular expression \"%s\" has no subexpressions as requested by backreference in \"%s\"",
2894  identLine->ident_user + 1, identLine->pg_role)));
2895  *error_p = true;
2896  return;
2897  }
2898 
2899  /*
2900  * length: original length minus length of \1 plus length of match
2901  * plus null terminator
2902  */
2903  regexp_pgrole = palloc0(strlen(identLine->pg_role) - 2 + (matches[1].rm_eo - matches[1].rm_so) + 1);
2904  offset = ofs - identLine->pg_role;
2905  memcpy(regexp_pgrole, identLine->pg_role, offset);
2906  memcpy(regexp_pgrole + offset,
2907  ident_user + matches[1].rm_so,
2908  matches[1].rm_eo - matches[1].rm_so);
2909  strcat(regexp_pgrole, ofs + 2);
2910  }
2911  else
2912  {
2913  /* no substitution, so copy the match */
2914  regexp_pgrole = pstrdup(identLine->pg_role);
2915  }
2916 
2917  /*
2918  * now check if the username actually matched what the user is trying
2919  * to connect as
2920  */
2921  if (case_insensitive)
2922  {
2923  if (pg_strcasecmp(regexp_pgrole, pg_role) == 0)
2924  *found_p = true;
2925  }
2926  else
2927  {
2928  if (strcmp(regexp_pgrole, pg_role) == 0)
2929  *found_p = true;
2930  }
2931  pfree(regexp_pgrole);
2932 
2933  return;
2934  }
2935  else
2936  {
2937  /* Not regular expression, so make complete match */
2938  if (case_insensitive)
2939  {
2940  if (pg_strcasecmp(identLine->pg_role, pg_role) == 0 &&
2941  pg_strcasecmp(identLine->ident_user, ident_user) == 0)
2942  *found_p = true;
2943  }
2944  else
2945  {
2946  if (strcmp(identLine->pg_role, pg_role) == 0 &&
2947  strcmp(identLine->ident_user, ident_user) == 0)
2948  *found_p = true;
2949  }
2950  }
2951 }
regex_t re
Definition: hba.h:132
char * pstrdup(const char *in)
Definition: mcxt.c:1299
regoff_t rm_so
Definition: regex.h:87
int errcode(int sqlerrcode)
Definition: elog.c:698
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:36
#define LOG
Definition: elog.h:26
regoff_t rm_eo
Definition: regex.h:88
void pfree(void *pointer)
Definition: mcxt.c:1169
char * usermap
Definition: hba.h:129
size_t pg_regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size)
Definition: regerror.c:60
unsigned int pg_wchar
Definition: mbprint.c:31
void * palloc0(Size size)
Definition: mcxt.c:1093
int pg_mb2wchar_with_len(const char *from, pg_wchar *to, int len)
Definition: mbutils.c:929
#define ereport(elevel,...)
Definition: elog.h:157
char * ident_user
Definition: hba.h:130
int pg_regexec(regex_t *re, const chr *string, size_t len, size_t search_start, rm_detail_t *details, size_t nmatch, regmatch_t pmatch[], int flags)
Definition: regexec.c:176
void * palloc(Size size)
Definition: mcxt.c:1062
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define REG_NOMATCH
Definition: regex.h:140
char * pg_role
Definition: hba.h:131

◆ check_ip()

static bool check_ip ( SockAddr raddr,
struct sockaddr *  addr,
struct sockaddr *  mask 
)
static

Definition at line 808 of file hba.c.

References SockAddr::addr, and pg_range_sockaddr().

Referenced by check_hba(), and check_network_callback().

809 {
810  if (raddr->addr.ss_family == addr->sa_family &&
811  pg_range_sockaddr(&raddr->addr,
812  (struct sockaddr_storage *) addr,
813  (struct sockaddr_storage *) mask))
814  return true;
815  return false;
816 }
struct sockaddr_storage addr
Definition: pqcomm.h:64
int pg_range_sockaddr(const struct sockaddr_storage *addr, const struct sockaddr_storage *netaddr, const struct sockaddr_storage *netmask)
Definition: ifaddr.c:53

◆ check_network_callback()

static void check_network_callback ( struct sockaddr *  addr,
struct sockaddr *  netmask,
void *  cb_data 
)
static

Definition at line 822 of file hba.c.

References check_ip(), ipCmpSameHost, check_network_data::method, pg_sockaddr_cidr_mask(), check_network_data::raddr, and check_network_data::result.

Referenced by check_same_host_or_net().

824 {
825  check_network_data *cn = (check_network_data *) cb_data;
826  struct sockaddr_storage mask;
827 
828  /* Already found a match? */
829  if (cn->result)
830  return;
831 
832  if (cn->method == ipCmpSameHost)
833  {
834  /* Make an all-ones netmask of appropriate length for family */
835  pg_sockaddr_cidr_mask(&mask, NULL, addr->sa_family);
836  cn->result = check_ip(cn->raddr, addr, (struct sockaddr *) &mask);
837  }
838  else
839  {
840  /* Use the netmask of the interface itself */
841  cn->result = check_ip(cn->raddr, addr, netmask);
842  }
843 }
SockAddr * raddr
Definition: hba.c:63
IPCompareMethod method
Definition: hba.c:62
int pg_sockaddr_cidr_mask(struct sockaddr_storage *mask, char *numbits, int family)
Definition: ifaddr.c:115
static bool check_ip(SockAddr *raddr, struct sockaddr *addr, struct sockaddr *mask)
Definition: hba.c:808
bool result
Definition: hba.c:64

◆ check_role()

static bool check_role ( const char *  role,
Oid  roleid,
List tokens 
)
static

Definition at line 608 of file hba.c.

References is_member(), lfirst, HbaToken::quoted, HbaToken::string, token_is_keyword, and token_matches.

Referenced by check_hba().

609 {
610  ListCell *cell;
611  HbaToken *tok;
612 
613  foreach(cell, tokens)
614  {
615  tok = lfirst(cell);
616  if (!tok->quoted && tok->string[0] == '+')
617  {
618  if (is_member(roleid, tok->string + 1))
619  return true;
620  }
621  else if (token_matches(tok, role) ||
622  token_is_keyword(tok, "all"))
623  return true;
624  }
625  return false;
626 }
#define token_matches(t, k)
Definition: hba.c:69
Definition: hba.c:75
char * string
Definition: hba.c:77
bool quoted
Definition: hba.c:78
#define lfirst(lc)
Definition: pg_list.h:169
static bool is_member(Oid userid, const char *role)
Definition: hba.c:584
#define token_is_keyword(t, k)
Definition: hba.c:68

◆ check_same_host_or_net()

static bool check_same_host_or_net ( SockAddr raddr,
IPCompareMethod  method 
)
static

Definition at line 849 of file hba.c.

References check_network_callback(), ereport, errmsg(), LOG, check_network_data::method, pg_foreach_ifaddr(), check_network_data::raddr, and check_network_data::result.

Referenced by check_hba().

850 {
852 
853  cn.method = method;
854  cn.raddr = raddr;
855  cn.result = false;
856 
857  errno = 0;
859  {
860  ereport(LOG,
861  (errmsg("error enumerating network interfaces: %m")));
862  return false;
863  }
864 
865  return cn.result;
866 }
SockAddr * raddr
Definition: hba.c:63
#define LOG
Definition: elog.h:26
IPCompareMethod method
Definition: hba.c:62
int pg_foreach_ifaddr(PgIfAddrCallback callback, void *cb_data)
Definition: ifaddr.c:559
static void check_network_callback(struct sockaddr *addr, struct sockaddr *netmask, void *cb_data)
Definition: hba.c:822
#define ereport(elevel,...)
Definition: elog.h:157
bool result
Definition: hba.c:64
int errmsg(const char *fmt,...)
Definition: elog.c:909

◆ check_usermap()

int check_usermap ( const char *  usermap_name,
const char *  pg_role,
const char *  auth_user,
bool  case_insensitive 
)

Definition at line 2968 of file hba.c.

References check_ident_usermap(), ereport, errmsg(), error(), lfirst, LOG, pg_strcasecmp(), STATUS_ERROR, and STATUS_OK.

Referenced by auth_peer(), CheckSCRAMAuth(), and ident_inet().

2972 {
2973  bool found_entry = false,
2974  error = false;
2975 
2976  if (usermap_name == NULL || usermap_name[0] == '\0')
2977  {
2978  if (case_insensitive)
2979  {
2980  if (pg_strcasecmp(pg_role, auth_user) == 0)
2981  return STATUS_OK;
2982  }
2983  else
2984  {
2985  if (strcmp(pg_role, auth_user) == 0)
2986  return STATUS_OK;
2987  }
2988  ereport(LOG,
2989  (errmsg("provided user name (%s) and authenticated user name (%s) do not match",
2990  pg_role, auth_user)));
2991  return STATUS_ERROR;
2992  }
2993  else
2994  {
2995  ListCell *line_cell;
2996 
2997  foreach(line_cell, parsed_ident_lines)
2998  {
2999  check_ident_usermap(lfirst(line_cell), usermap_name,
3000  pg_role, auth_user, case_insensitive,
3001  &found_entry, &error);
3002  if (found_entry || error)
3003  break;
3004  }
3005  }
3006  if (!found_entry && !error)
3007  {
3008  ereport(LOG,
3009  (errmsg("no match in usermap \"%s\" for user \"%s\" authenticated as \"%s\"",
3010  usermap_name, pg_role, auth_user)));
3011  }
3012  return found_entry ? STATUS_OK : STATUS_ERROR;
3013 }
static void check_ident_usermap(IdentLine *identLine, const char *usermap_name, const char *pg_role, const char *ident_user, bool case_insensitive, bool *found_p, bool *error_p)
Definition: hba.c:2833
static void error(void)
Definition: sql-dyntest.c:147
#define STATUS_ERROR
Definition: c.h:1171
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:36
#define LOG
Definition: elog.h:26
#define STATUS_OK
Definition: c.h:1170
#define ereport(elevel,...)
Definition: elog.h:157
static List * parsed_ident_lines
Definition: hba.c:112
#define lfirst(lc)
Definition: pg_list.h:169
int errmsg(const char *fmt,...)
Definition: elog.c:909

◆ copy_hba_token()

static HbaToken* copy_hba_token ( HbaToken in)
static

Definition at line 315 of file hba.c.

References make_hba_token(), HbaToken::quoted, and HbaToken::string.

Referenced by parse_hba_line(), and tokenize_inc_file().

316 {
317  HbaToken *out = make_hba_token(in->string, in->quoted);
318 
319  return out;
320 }
Definition: hba.c:75
char * string
Definition: hba.c:77
bool quoted
Definition: hba.c:78
static HbaToken * make_hba_token(const char *token, bool quoted)
Definition: hba.c:296

◆ fill_hba_line()

static void fill_hba_line ( Tuplestorestate tuple_store,
TupleDesc  tupdesc,
int  lineno,
HbaLine hba,
const char *  err_msg 
)
static

Definition at line 2460 of file hba.c.

References HbaLine::addr, HbaLine::addrlen, Assert, HbaLine::auth_method, clean_ipv6_addr(), HbaLine::conntype, CStringGetTextDatum, ctHost, ctHostGSS, ctHostNoGSS, ctHostNoSSL, ctHostSSL, ctLocal, HbaLine::databases, gethba_options(), hba_authname(), heap_form_tuple(), HbaLine::hostname, Int32GetDatum, HbaLine::ip_cmp_method, ipCmpAll, ipCmpMask, ipCmpSameHost, ipCmpSameNet, lappend(), lfirst, HbaLine::mask, HbaLine::masklen, TupleDescData::natts, NI_MAXHOST, NI_NUMERICHOST, NIL, NUM_PG_HBA_FILE_RULES_ATTS, options, pg_getnameinfo_all(), PointerGetDatum, pstrdup(), HbaLine::roles, HbaToken::string, strlist_to_textarray(), tuplestore_puttuple(), and values.

Referenced by fill_hba_view().

2462 {
2464  bool nulls[NUM_PG_HBA_FILE_RULES_ATTS];
2465  char buffer[NI_MAXHOST];
2466  HeapTuple tuple;
2467  int index;
2468  ListCell *lc;
2469  const char *typestr;
2470  const char *addrstr;
2471  const char *maskstr;
2472  ArrayType *options;
2473 
2475 
2476  memset(values, 0, sizeof(values));
2477  memset(nulls, 0, sizeof(nulls));
2478  index = 0;
2479 
2480  /* line_number */
2481  values[index++] = Int32GetDatum(lineno);
2482 
2483  if (hba != NULL)
2484  {
2485  /* type */
2486  /* Avoid a default: case so compiler will warn about missing cases */
2487  typestr = NULL;
2488  switch (hba->conntype)
2489  {
2490  case ctLocal:
2491  typestr = "local";
2492  break;
2493  case ctHost:
2494  typestr = "host";
2495  break;
2496  case ctHostSSL:
2497  typestr = "hostssl";
2498  break;
2499  case ctHostNoSSL:
2500  typestr = "hostnossl";
2501  break;
2502  case ctHostGSS:
2503  typestr = "hostgssenc";
2504  break;
2505  case ctHostNoGSS:
2506  typestr = "hostnogssenc";
2507  break;
2508  }
2509  if (typestr)
2510  values[index++] = CStringGetTextDatum(typestr);
2511  else
2512  nulls[index++] = true;
2513 
2514  /* database */
2515  if (hba->databases)
2516  {
2517  /*
2518  * Flatten HbaToken list to string list. It might seem that we
2519  * should re-quote any quoted tokens, but that has been rejected
2520  * on the grounds that it makes it harder to compare the array
2521  * elements to other system catalogs. That makes entries like
2522  * "all" or "samerole" formally ambiguous ... but users who name
2523  * databases/roles that way are inflicting their own pain.
2524  */
2525  List *names = NIL;
2526 
2527  foreach(lc, hba->databases)
2528  {
2529  HbaToken *tok = lfirst(lc);
2530 
2531  names = lappend(names, tok->string);
2532  }
2533  values[index++] = PointerGetDatum(strlist_to_textarray(names));
2534  }
2535  else
2536  nulls[index++] = true;
2537 
2538  /* user */
2539  if (hba->roles)
2540  {
2541  /* Flatten HbaToken list to string list; see comment above */
2542  List *roles = NIL;
2543 
2544  foreach(lc, hba->roles)
2545  {
2546  HbaToken *tok = lfirst(lc);
2547 
2548  roles = lappend(roles, tok->string);
2549  }
2550  values[index++] = PointerGetDatum(strlist_to_textarray(roles));
2551  }
2552  else
2553  nulls[index++] = true;
2554 
2555  /* address and netmask */
2556  /* Avoid a default: case so compiler will warn about missing cases */
2557  addrstr = maskstr = NULL;
2558  switch (hba->ip_cmp_method)
2559  {
2560  case ipCmpMask:
2561  if (hba->hostname)
2562  {
2563  addrstr = hba->hostname;
2564  }
2565  else
2566  {
2567  /*
2568  * Note: if pg_getnameinfo_all fails, it'll set buffer to
2569  * "???", which we want to return.
2570  */
2571  if (hba->addrlen > 0)
2572  {
2573  if (pg_getnameinfo_all(&hba->addr, hba->addrlen,
2574  buffer, sizeof(buffer),
2575  NULL, 0,
2576  NI_NUMERICHOST) == 0)
2577  clean_ipv6_addr(hba->addr.ss_family, buffer);
2578  addrstr = pstrdup(buffer);
2579  }
2580  if (hba->masklen > 0)
2581  {
2582  if (pg_getnameinfo_all(&hba->mask, hba->masklen,
2583  buffer, sizeof(buffer),
2584  NULL, 0,
2585  NI_NUMERICHOST) == 0)
2586  clean_ipv6_addr(hba->mask.ss_family, buffer);
2587  maskstr = pstrdup(buffer);
2588  }
2589  }
2590  break;
2591  case ipCmpAll:
2592  addrstr = "all";
2593  break;
2594  case ipCmpSameHost:
2595  addrstr = "samehost";
2596  break;
2597  case ipCmpSameNet:
2598  addrstr = "samenet";
2599  break;
2600  }
2601  if (addrstr)
2602  values[index++] = CStringGetTextDatum(addrstr);
2603  else
2604  nulls[index++] = true;
2605  if (maskstr)
2606  values[index++] = CStringGetTextDatum(maskstr);
2607  else
2608  nulls[index++] = true;
2609 
2610  /* auth_method */
2611  values[index++] = CStringGetTextDatum(hba_authname(hba->auth_method));
2612 
2613  /* options */
2614  options = gethba_options(hba);
2615  if (options)
2616  values[index++] = PointerGetDatum(options);
2617  else
2618  nulls[index++] = true;
2619  }
2620  else
2621  {
2622  /* no parsing result, so set relevant fields to nulls */
2623  memset(&nulls[1], true, (NUM_PG_HBA_FILE_RULES_ATTS - 2) * sizeof(bool));
2624  }
2625 
2626  /* error */
2627  if (err_msg)
2628  values[NUM_PG_HBA_FILE_RULES_ATTS - 1] = CStringGetTextDatum(err_msg);
2629  else
2630  nulls[NUM_PG_HBA_FILE_RULES_ATTS - 1] = true;
2631 
2632  tuple = heap_form_tuple(tupdesc, values, nulls);
2633  tuplestore_puttuple(tuple_store, tuple);
2634 }
List * databases
Definition: hba.h:85
#define NIL
Definition: pg_list.h:65
struct sockaddr_storage mask
Definition: hba.h:89
#define NI_NUMERICHOST
Definition: getaddrinfo.h:78
#define PointerGetDatum(X)
Definition: postgres.h:600
Definition: hba.h:51
char * pstrdup(const char *in)
Definition: mcxt.c:1299
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1020
Definition: type.h:89
ConnType conntype
Definition: hba.h:84
Definition: hba.h:61
#define NI_MAXHOST
Definition: getaddrinfo.h:88
struct sockaddr_storage addr
Definition: hba.h:87
Definition: hba.h:63
void tuplestore_puttuple(Tuplestorestate *state, HeapTuple tuple)
Definition: tuplestore.c:730
Definition: hba.c:75
Definition: hba.h:59
List * lappend(List *list, void *datum)
Definition: list.c:336
static char ** options
Definition: hba.h:54
uintptr_t Datum
Definition: postgres.h:411
char * hostname
Definition: hba.h:92
char * string
Definition: hba.c:77
List * roles
Definition: hba.h:86
#define Assert(condition)
Definition: c.h:804
#define lfirst(lc)
Definition: pg_list.h:169
int pg_getnameinfo_all(const struct sockaddr_storage *addr, int salen, char *node, int nodelen, char *service, int servicelen, int flags)
Definition: ip.c:122
#define NUM_PG_HBA_FILE_RULES_ATTS
Definition: hba.c:2445
void clean_ipv6_addr(int addr_family, char *addr)
Definition: network.c:2118
static Datum values[MAXATTR]
Definition: bootstrap.c:166
#define Int32GetDatum(X)
Definition: postgres.h:523
const char * hba_authname(UserAuth auth_method)
Definition: hba.c:3147
#define CStringGetTextDatum(s)
Definition: builtins.h:82
ArrayType * strlist_to_textarray(List *list)
IPCompareMethod ip_cmp_method
Definition: hba.h:91
int masklen
Definition: hba.h:90
int addrlen
Definition: hba.h:88
Definition: pg_list.h:50
Definition: hba.h:60
UserAuth auth_method
Definition: hba.h:93
static ArrayType * gethba_options(HbaLine *hba)
Definition: hba.c:2336

◆ fill_hba_view()

static void fill_hba_view ( Tuplestorestate tuple_store,
TupleDesc  tupdesc 
)
static

Definition at line 2640 of file hba.c.

References AllocateFile(), ALLOCSET_SMALL_SIZES, AllocSetContextCreate, CurrentMemoryContext, DEBUG3, ereport, TokenizedLine::err_msg, errcode_for_file_access(), errmsg(), ERROR, fill_hba_line(), FreeFile(), HbaFileName, lfirst, TokenizedLine::line_num, MemoryContextDelete(), MemoryContextSwitchTo(), NIL, parse_hba_line(), and tokenize_file().

Referenced by pg_hba_file_rules().

2641 {
2642  FILE *file;
2643  List *hba_lines = NIL;
2644  ListCell *line;
2645  MemoryContext linecxt;
2646  MemoryContext hbacxt;
2647  MemoryContext oldcxt;
2648 
2649  /*
2650  * In the unlikely event that we can't open pg_hba.conf, we throw an
2651  * error, rather than trying to report it via some sort of view entry.
2652  * (Most other error conditions should result in a message in a view
2653  * entry.)
2654  */
2655  file = AllocateFile(HbaFileName, "r");
2656  if (file == NULL)
2657  ereport(ERROR,
2659  errmsg("could not open configuration file \"%s\": %m",
2660  HbaFileName)));
2661 
2662  linecxt = tokenize_file(HbaFileName, file, &hba_lines, DEBUG3);
2663  FreeFile(file);
2664 
2665  /* Now parse all the lines */
2667  "hba parser context",
2669  oldcxt = MemoryContextSwitchTo(hbacxt);
2670  foreach(line, hba_lines)
2671  {
2672  TokenizedLine *tok_line = (TokenizedLine *) lfirst(line);
2673  HbaLine *hbaline = NULL;
2674 
2675  /* don't parse lines that already have errors */
2676  if (tok_line->err_msg == NULL)
2677  hbaline = parse_hba_line(tok_line, DEBUG3);
2678 
2679  fill_hba_line(tuple_store, tupdesc, tok_line->line_num,
2680  hbaline, tok_line->err_msg);
2681  }
2682 
2683  /* Free tokenizer memory */
2684  MemoryContextDelete(linecxt);
2685  /* Free parse_hba_line memory */
2686  MemoryContextSwitchTo(oldcxt);
2687  MemoryContextDelete(hbacxt);
2688 }
Definition: hba.h:80
#define NIL
Definition: pg_list.h:65
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:218
#define AllocSetContextCreate
Definition: memutils.h:173
#define DEBUG3
Definition: elog.h:23
#define ALLOCSET_SMALL_SIZES
Definition: memutils.h:205
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
char * HbaFileName
Definition: guc.c:584
#define ERROR
Definition: elog.h:46
int line_num
Definition: hba.c:92
char * err_msg
Definition: hba.c:94
int errcode_for_file_access(void)
Definition: elog.c:721
FILE * AllocateFile(const char *name, const char *mode)
Definition: fd.c:2373
MemoryContext CurrentMemoryContext
Definition: mcxt.c:42
static HbaLine * parse_hba_line(TokenizedLine *tok_line, int elevel)
Definition: hba.c:968
static void fill_hba_line(Tuplestorestate *tuple_store, TupleDesc tupdesc, int lineno, HbaLine *hba, const char *err_msg)
Definition: hba.c:2460
#define ereport(elevel,...)
Definition: elog.h:157
#define lfirst(lc)
Definition: pg_list.h:169
static MemoryContext tokenize_file(const char *filename, FILE *file, List **tok_lines, int elevel)
Definition: hba.c:478
int FreeFile(FILE *file)
Definition: fd.c:2572
int errmsg(const char *fmt,...)
Definition: elog.c:909
Definition: pg_list.h:50

◆ gethba_options()

static ArrayType * gethba_options ( HbaLine hba)
static

Definition at line 2336 of file hba.c.

References Assert, HbaLine::auth_method, HbaLine::clientcert, clientCertCA, clientCertOff, construct_array(), CStringGetTextDatum, HbaLine::include_realm, HbaLine::krb_realm, HbaLine::ldapbasedn, HbaLine::ldapbinddn, HbaLine::ldapbindpasswd, HbaLine::ldapport, HbaLine::ldapprefix, HbaLine::ldapscope, HbaLine::ldapsearchattribute, HbaLine::ldapsearchfilter, HbaLine::ldapserver, HbaLine::ldapsuffix, HbaLine::ldaptls, MAX_HBA_OPTIONS, noptions, HbaLine::pamservice, psprintf(), HbaLine::radiusidentifiers_s, HbaLine::radiusports_s, HbaLine::radiussecrets_s, HbaLine::radiusservers_s, uaGSS, uaLDAP, uaRADIUS, uaSSPI, and HbaLine::usermap.

Referenced by fill_hba_line().

2337 {
2338  int noptions;
2340 
2341  noptions = 0;
2342 
2343  if (hba->auth_method == uaGSS || hba->auth_method == uaSSPI)
2344  {
2345  if (hba->include_realm)
2346  options[noptions++] =
2347  CStringGetTextDatum("include_realm=true");
2348 
2349  if (hba->krb_realm)
2350  options[noptions++] =
2351  CStringGetTextDatum(psprintf("krb_realm=%s", hba->krb_realm));
2352  }
2353 
2354  if (hba->usermap)
2355  options[noptions++] =
2356  CStringGetTextDatum(psprintf("map=%s", hba->usermap));
2357 
2358  if (hba->clientcert != clientCertOff)
2359  options[noptions++] =
2360  CStringGetTextDatum(psprintf("clientcert=%s", (hba->clientcert == clientCertCA) ? "verify-ca" : "verify-full"));
2361 
2362  if (hba->pamservice)
2363  options[noptions++] =
2364  CStringGetTextDatum(psprintf("pamservice=%s", hba->pamservice));
2365 
2366  if (hba->auth_method == uaLDAP)
2367  {
2368  if (hba->ldapserver)
2369  options[noptions++] =
2370  CStringGetTextDatum(psprintf("ldapserver=%s", hba->ldapserver));
2371 
2372  if (hba->ldapport)
2373  options[noptions++] =
2374  CStringGetTextDatum(psprintf("ldapport=%d", hba->ldapport));
2375 
2376  if (hba->ldaptls)
2377  options[noptions++] =
2378  CStringGetTextDatum("ldaptls=true");
2379 
2380  if (hba->ldapprefix)
2381  options[noptions++] =
2382  CStringGetTextDatum(psprintf("ldapprefix=%s", hba->ldapprefix));
2383 
2384  if (hba->ldapsuffix)
2385  options[noptions++] =
2386  CStringGetTextDatum(psprintf("ldapsuffix=%s", hba->ldapsuffix));
2387 
2388  if (hba->ldapbasedn)
2389  options[noptions++] =
2390  CStringGetTextDatum(psprintf("ldapbasedn=%s", hba->ldapbasedn));
2391 
2392  if (hba->ldapbinddn)
2393  options[noptions++] =
2394  CStringGetTextDatum(psprintf("ldapbinddn=%s", hba->ldapbinddn));
2395 
2396  if (hba->ldapbindpasswd)
2397  options[noptions++] =
2398  CStringGetTextDatum(psprintf("ldapbindpasswd=%s",
2399  hba->ldapbindpasswd));
2400 
2401  if (hba->ldapsearchattribute)
2402  options[noptions++] =
2403  CStringGetTextDatum(psprintf("ldapsearchattribute=%s",
2404  hba->ldapsearchattribute));
2405 
2406  if (hba->ldapsearchfilter)
2407  options[noptions++] =
2408  CStringGetTextDatum(psprintf("ldapsearchfilter=%s",
2409  hba->ldapsearchfilter));
2410 
2411  if (hba->ldapscope)
2412  options[noptions++] =
2413  CStringGetTextDatum(psprintf("ldapscope=%d", hba->ldapscope));
2414  }
2415 
2416  if (hba->auth_method == uaRADIUS)
2417  {
2418  if (hba->radiusservers_s)
2419  options[noptions++] =
2420  CStringGetTextDatum(psprintf("radiusservers=%s", hba->radiusservers_s));
2421 
2422  if (hba->radiussecrets_s)
2423  options[noptions++] =
2424  CStringGetTextDatum(psprintf("radiussecrets=%s", hba->radiussecrets_s));
2425 
2426  if (hba->radiusidentifiers_s)
2427  options[noptions++] =
2428  CStringGetTextDatum(psprintf("radiusidentifiers=%s", hba->radiusidentifiers_s));
2429 
2430  if (hba->radiusports_s)
2431  options[noptions++] =
2432  CStringGetTextDatum(psprintf("radiusports=%s", hba->radiusports_s));
2433  }
2434 
2435  /* If you add more options, consider increasing MAX_HBA_OPTIONS. */
2436  Assert(noptions <= MAX_HBA_OPTIONS);
2437 
2438  if (noptions > 0)
2439  return construct_array(options, noptions, TEXTOID, -1, false, TYPALIGN_INT);
2440  else
2441  return NULL;
2442 }
int ldapscope
Definition: hba.h:106
char * radiusports_s
Definition: hba.h:122
char * ldapserver
Definition: hba.h:99
Definition: hba.h:38
int ldapport
Definition: hba.h:100
char * ldapbasedn
Definition: hba.h:105
char * pamservice
Definition: hba.h:95
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46
Definition: hba.h:35
ArrayType * construct_array(Datum *elems, int nelems, Oid elmtype, int elmlen, bool elmbyval, char elmalign)
Definition: arrayfuncs.c:3318
char * ldapsuffix
Definition: hba.h:108
Definition: hba.h:34
char * radiusservers_s
Definition: hba.h:116
char * usermap
Definition: hba.h:94
bool include_realm
Definition: hba.h:112
char * ldapbinddn
Definition: hba.h:101
char * krb_realm
Definition: hba.h:111
char * ldapbindpasswd
Definition: hba.h:102
char * ldapprefix
Definition: hba.h:107
uintptr_t Datum
Definition: postgres.h:411
char * radiusidentifiers_s
Definition: hba.h:120
char * radiussecrets_s
Definition: hba.h:118
#define Assert(condition)
Definition: c.h:804
char * ldapsearchfilter
Definition: hba.h:104
ClientCertMode clientcert
Definition: hba.h:109
bool ldaptls
Definition: hba.h:97
char * ldapsearchattribute
Definition: hba.h:103
#define CStringGetTextDatum(s)
Definition: builtins.h:82
static size_t noptions
Definition: hba.h:40
UserAuth auth_method
Definition: hba.h:93
#define MAX_HBA_OPTIONS
Definition: hba.c:2329

◆ hba_authname()

const char* hba_authname ( UserAuth  auth_method)

Definition at line 3147 of file hba.c.

References lengthof, StaticAssertStmt, USER_AUTH_LAST, and UserAuthName.

Referenced by fill_hba_line(), and set_authn_id().

3148 {
3149  /*
3150  * Make sure UserAuthName[] tracks additions to the UserAuth enum
3151  */
3153  "UserAuthName[] must match the UserAuth enum");
3154 
3155  return UserAuthName[auth_method];
3156 }
static const char *const UserAuthName[]
Definition: hba.c:121
#define lengthof(array)
Definition: c.h:734
#define StaticAssertStmt(condition, errmessage)
Definition: c.h:918
#define USER_AUTH_LAST
Definition: hba.h:42

◆ hba_getauthmethod()

void hba_getauthmethod ( hbaPort port)

Definition at line 3134 of file hba.c.

References check_hba().

Referenced by ClientAuthentication().

3135 {
3136  check_hba(port);
3137 }
static void check_hba(hbaPort *port)
Definition: hba.c:2115

◆ hostname_match()

static bool hostname_match ( const char *  pattern,
const char *  actual_hostname 
)
static

Definition at line 695 of file hba.c.

References pg_strcasecmp().

Referenced by check_hostname().

696 {
697  if (pattern[0] == '.') /* suffix match */
698  {
699  size_t plen = strlen(pattern);
700  size_t hlen = strlen(actual_hostname);
701 
702  if (hlen < plen)
703  return false;
704 
705  return (pg_strcasecmp(pattern, actual_hostname + (hlen - plen)) == 0);
706  }
707  else
708  return (pg_strcasecmp(pattern, actual_hostname) == 0);
709 }
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:36

◆ ipv4eq()

static bool ipv4eq ( struct sockaddr_in *  a,
struct sockaddr_in *  b 
)
static

Definition at line 671 of file hba.c.

References i.

Referenced by check_hostname().

672 {
673  return (a->sin_addr.s_addr == b->sin_addr.s_addr);
674 }

◆ is_member()

static bool is_member ( Oid  userid,
const char *  role 
)
static

Definition at line 584 of file hba.c.

References get_role_oid(), is_member_of_role_nosuper(), and OidIsValid.

Referenced by check_db(), and check_role().

585 {
586  Oid roleid;
587 
588  if (!OidIsValid(userid))
589  return false; /* if user not exist, say "no" */
590 
591  roleid = get_role_oid(role, true);
592 
593  if (!OidIsValid(roleid))
594  return false; /* if target role not exist, say "no" */
595 
596  /*
597  * See if user is directly or indirectly a member of role. For this
598  * purpose, a superuser is not considered to be automatically a member of
599  * the role, so group auth only applies to explicit membership.
600  */
601  return is_member_of_role_nosuper(userid, roleid);
602 }
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:710
Oid get_role_oid(const char *rolname, bool missing_ok)
Definition: acl.c:5094
bool is_member_of_role_nosuper(Oid member, Oid role)
Definition: acl.c:4909

◆ load_hba()

bool load_hba ( void  )

Definition at line 2229 of file hba.c.

References AllocateFile(), ALLOCSET_SMALL_SIZES, AllocSetContextCreate, Assert, ereport, TokenizedLine::err_msg, errcode(), errcode_for_file_access(), errmsg(), FreeFile(), HbaFileName, lappend(), lfirst, LOG, MemoryContextDelete(), MemoryContextSwitchTo(), newline(), NIL, parse_hba_line(), PostmasterContext, and tokenize_file().

Referenced by PerformAuthentication(), PostmasterMain(), and SIGHUP_handler().

2230 {
2231  FILE *file;
2232  List *hba_lines = NIL;
2233  ListCell *line;
2234  List *new_parsed_lines = NIL;
2235  bool ok = true;
2236  MemoryContext linecxt;
2237  MemoryContext oldcxt;
2238  MemoryContext hbacxt;
2239 
2240  file = AllocateFile(HbaFileName, "r");
2241  if (file == NULL)
2242  {
2243  ereport(LOG,
2245  errmsg("could not open configuration file \"%s\": %m",
2246  HbaFileName)));
2247  return false;
2248  }
2249 
2250  linecxt = tokenize_file(HbaFileName, file, &hba_lines, LOG);
2251  FreeFile(file);
2252 
2253  /* Now parse all the lines */
2256  "hba parser context",
2258  oldcxt = MemoryContextSwitchTo(hbacxt);
2259  foreach(line, hba_lines)
2260  {
2261  TokenizedLine *tok_line = (TokenizedLine *) lfirst(line);
2262  HbaLine *newline;
2263 
2264  /* don't parse lines that already have errors */
2265  if (tok_line->err_msg != NULL)
2266  {
2267  ok = false;
2268  continue;
2269  }
2270 
2271  if ((newline = parse_hba_line(tok_line, LOG)) == NULL)
2272  {
2273  /* Parse error; remember there's trouble */
2274  ok = false;
2275 
2276  /*
2277  * Keep parsing the rest of the file so we can report errors on
2278  * more than the first line. Error has already been logged, no
2279  * need for more chatter here.
2280  */
2281  continue;
2282  }
2283 
2284  new_parsed_lines = lappend(new_parsed_lines, newline);
2285  }
2286 
2287  /*
2288  * A valid HBA file must have at least one entry; else there's no way to
2289  * connect to the postmaster. But only complain about this if we didn't
2290  * already have parsing errors.
2291  */
2292  if (ok && new_parsed_lines == NIL)
2293  {
2294  ereport(LOG,
2295  (errcode(ERRCODE_CONFIG_FILE_ERROR),
2296  errmsg("configuration file \"%s\" contains no entries",
2297  HbaFileName)));
2298  ok = false;
2299  }
2300 
2301  /* Free tokenizer memory */
2302  MemoryContextDelete(linecxt);
2303  MemoryContextSwitchTo(oldcxt);
2304 
2305  if (!ok)
2306  {
2307  /* File contained one or more errors, so bail out */
2308  MemoryContextDelete(hbacxt);
2309  return false;
2310  }
2311 
2312  /* Loaded new file successfully, replace the one we use */
2313  if (parsed_hba_context != NULL)
2315  parsed_hba_context = hbacxt;
2316  parsed_hba_lines = new_parsed_lines;
2317 
2318  return true;
2319 }
Definition: hba.h:80
#define NIL
Definition: pg_list.h:65
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:218
#define AllocSetContextCreate
Definition: memutils.h:173
#define ALLOCSET_SMALL_SIZES
Definition: memutils.h:205
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
int errcode(int sqlerrcode)
Definition: elog.c:698
#define LOG
Definition: elog.h:26
static chr newline(void)
Definition: regc_lex.c:1004
static List * parsed_hba_lines
Definition: hba.c:101
char * HbaFileName
Definition: guc.c:584
static MemoryContext parsed_hba_context
Definition: hba.c:102
char * err_msg
Definition: hba.c:94
int errcode_for_file_access(void)
Definition: elog.c:721
FILE * AllocateFile(const char *name, const char *mode)
Definition: fd.c:2373
List * lappend(List *list, void *datum)
Definition: list.c:336
static HbaLine * parse_hba_line(TokenizedLine *tok_line, int elevel)
Definition: hba.c:968
#define ereport(elevel,...)
Definition: elog.h:157
#define Assert(condition)
Definition: c.h:804
#define lfirst(lc)
Definition: pg_list.h:169
static MemoryContext tokenize_file(const char *filename, FILE *file, List **tok_lines, int elevel)
Definition: hba.c:478
int FreeFile(FILE *file)
Definition: fd.c:2572
int errmsg(const char *fmt,...)
Definition: elog.c:909
Definition: pg_list.h:50
MemoryContext PostmasterContext
Definition: mcxt.c:50

◆ load_ident()

bool load_ident ( void  )

Definition at line 3023 of file hba.c.

References AllocateFile(), ALLOCSET_SMALL_SIZES, AllocSetContextCreate, Assert, ereport, TokenizedLine::err_msg, errcode_for_file_access(), errmsg(), FreeFile(), IdentLine::ident_user, IdentFileName, lappend(), lfirst, LOG, MemoryContextDelete(), MemoryContextSwitchTo(), newline(), NIL, parse_ident_line(), pg_regfree(), PostmasterContext, IdentLine::re, and tokenize_file().

Referenced by PerformAuthentication(), PostmasterMain(), and SIGHUP_handler().

3024 {
3025  FILE *file;
3026  List *ident_lines = NIL;
3027  ListCell *line_cell,
3028  *parsed_line_cell;
3029  List *new_parsed_lines = NIL;
3030  bool ok = true;
3031  MemoryContext linecxt;
3032  MemoryContext oldcxt;
3033  MemoryContext ident_context;
3034  IdentLine *newline;
3035 
3036  file = AllocateFile(IdentFileName, "r");
3037  if (file == NULL)
3038  {
3039  /* not fatal ... we just won't do any special ident maps */
3040  ereport(LOG,
3042  errmsg("could not open usermap file \"%s\": %m",
3043  IdentFileName)));
3044  return false;
3045  }
3046 
3047  linecxt = tokenize_file(IdentFileName, file, &ident_lines, LOG);
3048  FreeFile(file);
3049 
3050  /* Now parse all the lines */
3052  ident_context = AllocSetContextCreate(PostmasterContext,
3053  "ident parser context",
3055  oldcxt = MemoryContextSwitchTo(ident_context);
3056  foreach(line_cell, ident_lines)
3057  {
3058  TokenizedLine *tok_line = (TokenizedLine *) lfirst(line_cell);
3059 
3060  /* don't parse lines that already have errors */
3061  if (tok_line->err_msg != NULL)
3062  {
3063  ok = false;
3064  continue;
3065  }
3066 
3067  if ((newline = parse_ident_line(tok_line)) == NULL)
3068  {
3069  /* Parse error; remember there's trouble */
3070  ok = false;
3071 
3072  /*
3073  * Keep parsing the rest of the file so we can report errors on
3074  * more than the first line. Error has already been logged, no
3075  * need for more chatter here.
3076  */
3077  continue;
3078  }
3079 
3080  new_parsed_lines = lappend(new_parsed_lines, newline);
3081  }
3082 
3083  /* Free tokenizer memory */
3084  MemoryContextDelete(linecxt);
3085  MemoryContextSwitchTo(oldcxt);
3086 
3087  if (!ok)
3088  {
3089  /*
3090  * File contained one or more errors, so bail out, first being careful
3091  * to clean up whatever we allocated. Most stuff will go away via
3092  * MemoryContextDelete, but we have to clean up regexes explicitly.
3093  */
3094  foreach(parsed_line_cell, new_parsed_lines)
3095  {
3096  newline = (IdentLine *) lfirst(parsed_line_cell);
3097  if (newline->ident_user[0] == '/')
3098  pg_regfree(&newline->re);
3099  }
3100  MemoryContextDelete(ident_context);
3101  return false;
3102  }
3103 
3104  /* Loaded new file successfully, replace the one we use */
3105  if (parsed_ident_lines != NIL)
3106  {
3107  foreach(parsed_line_cell, parsed_ident_lines)
3108  {
3109  newline = (IdentLine *) lfirst(parsed_line_cell);
3110  if (newline->ident_user[0] == '/')
3111  pg_regfree(&newline->re);
3112  }
3113  }
3114  if (parsed_ident_context != NULL)
3116 
3117  parsed_ident_context = ident_context;
3118  parsed_ident_lines = new_parsed_lines;
3119 
3120  return true;
3121 }
#define NIL
Definition: pg_list.h:65
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:218
#define AllocSetContextCreate
Definition: memutils.h:173
regex_t re
Definition: hba.h:132
#define ALLOCSET_SMALL_SIZES
Definition: memutils.h:205
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define LOG
Definition: elog.h:26
static chr newline(void)
Definition: regc_lex.c:1004
char * err_msg
Definition: hba.c:94
int errcode_for_file_access(void)
Definition: elog.c:721
FILE * AllocateFile(const char *name, const char *mode)
Definition: fd.c:2373
char * IdentFileName
Definition: guc.c:585
List * lappend(List *list, void *datum)
Definition: list.c:336
#define ereport(elevel,...)
Definition: elog.h:157
static List * parsed_ident_lines
Definition: hba.c:112
static MemoryContext parsed_ident_context
Definition: hba.c:113
#define Assert(condition)
Definition: c.h:804
#define lfirst(lc)
Definition: pg_list.h:169
static MemoryContext tokenize_file(const char *filename, FILE *file, List **tok_lines, int elevel)
Definition: hba.c:478
Definition: hba.h:125
int FreeFile(FILE *file)
Definition: fd.c:2572
char * ident_user
Definition: hba.h:130
int errmsg(const char *fmt,...)
Definition: elog.c:909
static IdentLine * parse_ident_line(TokenizedLine *tok_line)
Definition: hba.c:2756
void pg_regfree(regex_t *re)
Definition: regfree.c:49
Definition: pg_list.h:50
MemoryContext PostmasterContext
Definition: mcxt.c:50

◆ make_hba_token()

static HbaToken* make_hba_token ( const char *  token,
bool  quoted 
)
static

Definition at line 296 of file hba.c.

References palloc(), HbaToken::quoted, and HbaToken::string.

Referenced by copy_hba_token(), and next_field_expand().

297 {
298  HbaToken *hbatoken;
299  int toklen;
300 
301  toklen = strlen(token);
302  /* we copy string into same palloc block as the struct */
303  hbatoken = (HbaToken *) palloc(sizeof(HbaToken) + toklen + 1);
304  hbatoken->string = (char *) hbatoken + sizeof(HbaToken);
305  hbatoken->quoted = quoted;
306  memcpy(hbatoken->string, token, toklen + 1);
307 
308  return hbatoken;
309 }
Definition: hba.c:75
char * string
Definition: hba.c:77
bool quoted
Definition: hba.c:78
void * palloc(Size size)
Definition: mcxt.c:1062

◆ next_field_expand()

static List* next_field_expand ( const char *  filename,
char **  lineptr,
int  elevel,
char **  err_msg 
)
static

Definition at line 338 of file hba.c.

References buf, lappend(), make_hba_token(), MAX_TOKEN, next_token(), NIL, and tokenize_inc_file().

Referenced by tokenize_file().

340 {
341  char buf[MAX_TOKEN];
342  bool trailing_comma;
343  bool initial_quote;
344  List *tokens = NIL;
345 
346  do
347  {
348  if (!next_token(lineptr, buf, sizeof(buf),
349  &initial_quote, &trailing_comma,
350  elevel, err_msg))
351  break;
352 
353  /* Is this referencing a file? */
354  if (!initial_quote && buf[0] == '@' && buf[1] != '\0')
355  tokens = tokenize_inc_file(tokens, filename, buf + 1,
356  elevel, err_msg);
357  else
358  tokens = lappend(tokens, make_hba_token(buf, initial_quote));
359  } while (trailing_comma && (*err_msg == NULL));
360 
361  return tokens;
362 }
#define NIL
Definition: pg_list.h:65
static bool next_token(char **lineptr, char *buf, int bufsz, bool *initial_quote, bool *terminating_comma, int elevel, char **err_msg)
Definition: hba.c:203
static char * buf
Definition: pg_test_fsync.c:68
List * lappend(List *list, void *datum)
Definition: list.c:336
static int elevel
Definition: vacuumlazy.c:400
#define MAX_TOKEN
Definition: hba.c:57
static char * filename
Definition: pg_dumpall.c:91
Definition: pg_list.h:50
static List * tokenize_inc_file(List *tokens, const char *outer_filename, const char *inc_filename, int elevel, char **err_msg)
Definition: hba.c:380
static HbaToken * make_hba_token(const char *token, bool quoted)
Definition: hba.c:296

◆ next_token()

static bool next_token ( char **  lineptr,
char *  buf,
int  bufsz,
bool initial_quote,
bool terminating_comma,
int  elevel,
char **  err_msg 
)
static

Definition at line 203 of file hba.c.

References Assert, buf, ereport, errcode(), errmsg(), and pg_isblank().

Referenced by base_yylex(), filtered_base_yylex(), and next_field_expand().

206 {
207  int c;
208  char *start_buf = buf;
209  char *end_buf = buf + (bufsz - 1);
210  bool in_quote = false;
211  bool was_quote = false;
212  bool saw_quote = false;
213 
214  Assert(end_buf > start_buf);
215 
216  *initial_quote = false;
217  *terminating_comma = false;
218 
219  /* Move over any whitespace and commas preceding the next token */
220  while ((c = (*(*lineptr)++)) != '\0' && (pg_isblank(c) || c == ','))
221  ;
222 
223  /*
224  * Build a token in buf of next characters up to EOL, unquoted comma, or
225  * unquoted whitespace.
226  */
227  while (c != '\0' &&
228  (!pg_isblank(c) || in_quote))
229  {
230  /* skip comments to EOL */
231  if (c == '#' && !in_quote)
232  {
233  while ((c = (*(*lineptr)++)) != '\0')
234  ;
235  break;
236  }
237 
238  if (buf >= end_buf)
239  {
240  *buf = '\0';
241  ereport(elevel,
242  (errcode(ERRCODE_CONFIG_FILE_ERROR),
243  errmsg("authentication file token too long, skipping: \"%s\"",
244  start_buf)));
245  *err_msg = "authentication file token too long";
246  /* Discard remainder of line */
247  while ((c = (*(*lineptr)++)) != '\0')
248  ;
249  /* Un-eat the '\0', in case we're called again */
250  (*lineptr)--;
251  return false;
252  }
253 
254  /* we do not pass back a terminating comma in the token */
255  if (c == ',' && !in_quote)
256  {
257  *terminating_comma = true;
258  break;
259  }
260 
261  if (c != '"' || was_quote)
262  *buf++ = c;
263 
264  /* Literal double-quote is two double-quotes */
265  if (in_quote && c == '"')
266  was_quote = !was_quote;
267  else
268  was_quote = false;
269 
270  if (c == '"')
271  {
272  in_quote = !in_quote;
273  saw_quote = true;
274  if (buf == start_buf)
275  *initial_quote = true;
276  }
277 
278  c = *(*lineptr)++;
279  }
280 
281  /*
282  * Un-eat the char right after the token (critical in case it is '\0',
283  * else next call will read past end of string).
284  */
285  (*lineptr)--;
286 
287  *buf = '\0';
288 
289  return (saw_quote || buf > start_buf);
290 }
bool pg_isblank(const char c)
Definition: hba.c:160
int errcode(int sqlerrcode)
Definition: elog.c:698
char * c
static char * buf
Definition: pg_test_fsync.c:68
static int elevel
Definition: vacuumlazy.c:400
#define ereport(elevel,...)
Definition: elog.h:157
#define Assert(condition)
Definition: c.h:804
int errmsg(const char *fmt,...)
Definition: elog.c:909

◆ parse_hba_auth_opt()

static bool parse_hba_auth_opt ( char *  name,
char *  val,
HbaLine hbaline,
int  elevel,
char **  err_msg 
)
static

Definition at line 1695 of file hba.c.

References addrinfo::ai_family, addrinfo::ai_socktype, HbaLine::auth_method, HbaLine::clientcert, clientCertCA, clientCertCN, clientCertDN, clientCertFull, HbaLine::clientcertname, HbaLine::compat_realm, HbaLine::conntype, ctHostSSL, ereport, errcode(), errcontext, errmsg(), gai_strerror, gettext_noop, HbaFileName, HbaLine::include_realm, INVALID_AUTH_OPTION, HbaLine::krb_realm, HbaLine::ldapbasedn, HbaLine::ldapbinddn, HbaLine::ldapbindpasswd, HbaLine::ldapport, HbaLine::ldapprefix, HbaLine::ldapscheme, HbaLine::ldapscope, HbaLine::ldapsearchattribute, HbaLine::ldapsearchfilter, HbaLine::ldapserver, HbaLine::ldapsuffix, HbaLine::ldaptls, lfirst, HbaLine::linenumber, list_free(), MemSet, HbaLine::pam_use_hostname, HbaLine::pamservice, pg_freeaddrinfo_all(), pg_getaddrinfo_all(), psprintf(), pstrdup(), HbaLine::radiusidentifiers, HbaLine::radiusidentifiers_s, HbaLine::radiusports, HbaLine::radiusports_s, HbaLine::radiussecrets, HbaLine::radiussecrets_s, HbaLine::radiusservers, HbaLine::radiusservers_s, REQUIRE_AUTH_OPTION, SplitGUCList(), uaCert, uaGSS, uaIdent, uaLDAP, uaPAM, uaRADIUS, uaSSPI, HbaLine::upn_username, and HbaLine::usermap.

Referenced by parse_hba_line().

1697 {
1698  int line_num = hbaline->linenumber;
1699 
1700 #ifdef USE_LDAP
1701  hbaline->ldapscope = LDAP_SCOPE_SUBTREE;
1702 #endif
1703 
1704  if (strcmp(name, "map") == 0)
1705  {
1706  if (hbaline->auth_method != uaIdent &&
1707  hbaline->auth_method != uaPeer &&
1708  hbaline->auth_method != uaGSS &&
1709  hbaline->auth_method != uaSSPI &&
1710  hbaline->auth_method != uaCert)
1711  INVALID_AUTH_OPTION("map", gettext_noop("ident, peer, gssapi, sspi, and cert"));
1712  hbaline->usermap = pstrdup(val);
1713  }
1714  else if (strcmp(name, "clientcert") == 0)
1715  {
1716  if (hbaline->conntype != ctHostSSL)
1717  {
1718  ereport(elevel,
1719  (errcode(ERRCODE_CONFIG_FILE_ERROR),
1720  errmsg("clientcert can only be configured for \"hostssl\" rows"),
1721  errcontext("line %d of configuration file \"%s\"",
1722  line_num, HbaFileName)));
1723  *err_msg = "clientcert can only be configured for \"hostssl\" rows";
1724  return false;
1725  }
1726 
1727  if (strcmp(val, "verify-full") == 0)
1728  {
1729  hbaline->clientcert = clientCertFull;
1730  }
1731  else if (strcmp(val, "verify-ca") == 0)
1732  {
1733  if (hbaline->auth_method == uaCert)
1734  {
1735  ereport(elevel,
1736  (errcode(ERRCODE_CONFIG_FILE_ERROR),
1737  errmsg("clientcert only accepts \"verify-full\" when using \"cert\" authentication"),
1738  errcontext("line %d of configuration file \"%s\"",
1739  line_num, HbaFileName)));
1740  *err_msg = "clientcert can only be set to \"verify-full\" when using \"cert\" authentication";
1741  return false;
1742  }
1743 
1744  hbaline->clientcert = clientCertCA;
1745  }
1746  else
1747  {
1748  ereport(elevel,
1749  (errcode(ERRCODE_CONFIG_FILE_ERROR),
1750  errmsg("invalid value for clientcert: \"%s\"", val),
1751  errcontext("line %d of configuration file \"%s\"",
1752  line_num, HbaFileName)));
1753  return false;
1754  }
1755  }
1756  else if (strcmp(name, "clientname") == 0)
1757  {
1758  if (hbaline->conntype != ctHostSSL)
1759  {
1760  ereport(elevel,
1761  (errcode(ERRCODE_CONFIG_FILE_ERROR),
1762  errmsg("clientname can only be configured for \"hostssl\" rows"),
1763  errcontext("line %d of configuration file \"%s\"",
1764  line_num, HbaFileName)));
1765  *err_msg = "clientname can only be configured for \"hostssl\" rows";
1766  return false;
1767  }
1768 
1769  if (strcmp(val, "CN") == 0)
1770  {
1771  hbaline->clientcertname = clientCertCN;
1772  }
1773  else if (strcmp(val, "DN") == 0)
1774  {
1775  hbaline->clientcertname = clientCertDN;
1776  }
1777  else
1778  {
1779  ereport(elevel,
1780  (errcode(ERRCODE_CONFIG_FILE_ERROR),
1781  errmsg("invalid value for clientname: \"%s\"", val),
1782  errcontext("line %d of configuration file \"%s\"",
1783  line_num, HbaFileName)));
1784  return false;
1785  }
1786  }
1787  else if (strcmp(name, "pamservice") == 0)
1788  {
1789  REQUIRE_AUTH_OPTION(uaPAM, "pamservice", "pam");
1790  hbaline->pamservice = pstrdup(val);
1791  }
1792  else if (strcmp(name, "pam_use_hostname") == 0)
1793  {
1794  REQUIRE_AUTH_OPTION(uaPAM, "pam_use_hostname", "pam");
1795  if (strcmp(val, "1") == 0)
1796  hbaline->pam_use_hostname = true;
1797  else
1798  hbaline->pam_use_hostname = false;
1799 
1800  }
1801  else if (strcmp(name, "ldapurl") == 0)
1802  {
1803 #ifdef LDAP_API_FEATURE_X_OPENLDAP
1804  LDAPURLDesc *urldata;
1805  int rc;
1806 #endif
1807 
1808  REQUIRE_AUTH_OPTION(uaLDAP, "ldapurl", "ldap");
1809 #ifdef LDAP_API_FEATURE_X_OPENLDAP
1810  rc = ldap_url_parse(val, &urldata);
1811  if (rc != LDAP_SUCCESS)
1812  {
1813  ereport(elevel,
1814  (errcode(ERRCODE_CONFIG_FILE_ERROR),
1815  errmsg("could not parse LDAP URL \"%s\": %s", val, ldap_err2string(rc))));
1816  *err_msg = psprintf("could not parse LDAP URL \"%s\": %s",
1817  val, ldap_err2string(rc));
1818  return false;
1819  }
1820 
1821  if (strcmp(urldata->lud_scheme, "ldap") != 0 &&
1822  strcmp(urldata->lud_scheme, "ldaps") != 0)
1823  {
1824  ereport(elevel,
1825  (errcode(ERRCODE_CONFIG_FILE_ERROR),
1826  errmsg("unsupported LDAP URL scheme: %s", urldata->lud_scheme)));
1827  *err_msg = psprintf("unsupported LDAP URL scheme: %s",
1828  urldata->lud_scheme);
1829  ldap_free_urldesc(urldata);
1830  return false;
1831  }
1832 
1833  if (urldata->lud_scheme)
1834  hbaline->ldapscheme = pstrdup(urldata->lud_scheme);
1835  if (urldata->lud_host)
1836  hbaline->ldapserver = pstrdup(urldata->lud_host);
1837  hbaline->ldapport = urldata->lud_port;
1838  if (urldata->lud_dn)
1839  hbaline->ldapbasedn = pstrdup(urldata->lud_dn);
1840 
1841  if (urldata->lud_attrs)
1842  hbaline->ldapsearchattribute = pstrdup(urldata->lud_attrs[0]); /* only use first one */
1843  hbaline->ldapscope = urldata->lud_scope;
1844  if (urldata->lud_filter)
1845  hbaline->ldapsearchfilter = pstrdup(urldata->lud_filter);
1846  ldap_free_urldesc(urldata);
1847 #else /* not OpenLDAP */
1848  ereport(elevel,
1849  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1850  errmsg("LDAP URLs not supported on this platform")));
1851  *err_msg = "LDAP URLs not supported on this platform";
1852 #endif /* not OpenLDAP */
1853  }
1854  else if (strcmp(name, "ldaptls") == 0)
1855  {
1856  REQUIRE_AUTH_OPTION(uaLDAP, "ldaptls", "ldap");
1857  if (strcmp(val, "1") == 0)
1858  hbaline->ldaptls = true;
1859  else
1860  hbaline->ldaptls = false;
1861  }
1862  else if (strcmp(name, "ldapscheme") == 0)
1863  {
1864  REQUIRE_AUTH_OPTION(uaLDAP, "ldapscheme", "ldap");
1865  if (strcmp(val, "ldap") != 0 && strcmp(val, "ldaps") != 0)
1866  ereport(elevel,
1867  (errcode(ERRCODE_CONFIG_FILE_ERROR),
1868  errmsg("invalid ldapscheme value: \"%s\"", val),
1869  errcontext("line %d of configuration file \"%s\"",
1870  line_num, HbaFileName)));
1871  hbaline->ldapscheme = pstrdup(val);
1872  }
1873  else if (strcmp(name, "ldapserver") == 0)
1874  {
1875  REQUIRE_AUTH_OPTION(uaLDAP, "ldapserver", "ldap");
1876  hbaline->ldapserver = pstrdup(val);
1877  }
1878  else if (strcmp(name, "ldapport") == 0)
1879  {
1880  REQUIRE_AUTH_OPTION(uaLDAP, "ldapport", "ldap");
1881  hbaline->ldapport = atoi(val);
1882  if (hbaline->ldapport == 0)
1883  {
1884  ereport(elevel,
1885  (errcode(ERRCODE_CONFIG_FILE_ERROR),
1886  errmsg("invalid LDAP port number: \"%s\"", val),
1887  errcontext("line %d of configuration file \"%s\"",
1888  line_num, HbaFileName)));
1889  *err_msg = psprintf("invalid LDAP port number: \"%s\"", val);
1890  return false;
1891  }
1892  }
1893  else if (strcmp(name, "ldapbinddn") == 0)
1894  {
1895  REQUIRE_AUTH_OPTION(uaLDAP, "ldapbinddn", "ldap");
1896  hbaline->ldapbinddn = pstrdup(val);
1897  }
1898  else if (strcmp(name, "ldapbindpasswd") == 0)
1899  {
1900  REQUIRE_AUTH_OPTION(uaLDAP, "ldapbindpasswd", "ldap");
1901  hbaline->ldapbindpasswd = pstrdup(val);
1902  }
1903  else if (strcmp(name, "ldapsearchattribute") == 0)
1904  {
1905  REQUIRE_AUTH_OPTION(uaLDAP, "ldapsearchattribute", "ldap");
1906  hbaline->ldapsearchattribute = pstrdup(val);
1907  }
1908  else if (strcmp(name, "ldapsearchfilter") == 0)
1909  {
1910  REQUIRE_AUTH_OPTION(uaLDAP, "ldapsearchfilter", "ldap");
1911  hbaline->ldapsearchfilter = pstrdup(val);
1912  }
1913  else if (strcmp(name, "ldapbasedn") == 0)
1914  {
1915  REQUIRE_AUTH_OPTION(uaLDAP, "ldapbasedn", "ldap");
1916  hbaline->ldapbasedn = pstrdup(val);
1917  }
1918  else if (strcmp(name, "ldapprefix") == 0)
1919  {
1920  REQUIRE_AUTH_OPTION(uaLDAP, "ldapprefix", "ldap");
1921  hbaline->ldapprefix = pstrdup(val);
1922  }
1923  else if (strcmp(name, "ldapsuffix") == 0)
1924  {
1925  REQUIRE_AUTH_OPTION(uaLDAP, "ldapsuffix", "ldap");
1926  hbaline->ldapsuffix = pstrdup(val);
1927  }
1928  else if (strcmp(name, "krb_realm") == 0)
1929  {
1930  if (hbaline->auth_method != uaGSS &&
1931  hbaline->auth_method != uaSSPI)
1932  INVALID_AUTH_OPTION("krb_realm", gettext_noop("gssapi and sspi"));
1933  hbaline->krb_realm = pstrdup(val);
1934  }
1935  else if (strcmp(name, "include_realm") == 0)
1936  {
1937  if (hbaline->auth_method != uaGSS &&
1938  hbaline->auth_method != uaSSPI)
1939  INVALID_AUTH_OPTION("include_realm", gettext_noop("gssapi and sspi"));
1940  if (strcmp(val, "1") == 0)
1941  hbaline->include_realm = true;
1942  else
1943  hbaline->include_realm = false;
1944  }
1945  else if (strcmp(name, "compat_realm") == 0)
1946  {
1947  if (hbaline->auth_method != uaSSPI)
1948  INVALID_AUTH_OPTION("compat_realm", gettext_noop("sspi"));
1949  if (strcmp(val, "1") == 0)
1950  hbaline->compat_realm = true;
1951  else
1952  hbaline->compat_realm = false;
1953  }
1954  else if (strcmp(name, "upn_username") == 0)
1955  {
1956  if (hbaline->auth_method != uaSSPI)
1957  INVALID_AUTH_OPTION("upn_username", gettext_noop("sspi"));
1958  if (strcmp(val, "1") == 0)
1959  hbaline->upn_username = true;
1960  else
1961  hbaline->upn_username = false;
1962  }
1963  else if (strcmp(name, "radiusservers") == 0)
1964  {
1965  struct addrinfo *gai_result;
1966  struct addrinfo hints;
1967  int ret;
1968  List *parsed_servers;
1969  ListCell *l;
1970  char *dupval = pstrdup(val);
1971 
1972  REQUIRE_AUTH_OPTION(uaRADIUS, "radiusservers", "radius");
1973 
1974  if (!SplitGUCList(dupval, ',', &parsed_servers))
1975  {
1976  /* syntax error in list */
1977  ereport(elevel,
1978  (errcode(ERRCODE_CONFIG_FILE_ERROR),
1979  errmsg("could not parse RADIUS server list \"%s\"",
1980  val),
1981  errcontext("line %d of configuration file \"%s\"",
1982  line_num, HbaFileName)));
1983  return false;
1984  }
1985 
1986  /* For each entry in the list, translate it */
1987  foreach(l, parsed_servers)
1988  {
1989  MemSet(&hints, 0, sizeof(hints));
1990  hints.ai_socktype = SOCK_DGRAM;
1991  hints.ai_family = AF_UNSPEC;
1992 
1993  ret = pg_getaddrinfo_all((char *) lfirst(l), NULL, &hints, &gai_result);
1994  if (ret || !gai_result)
1995  {
1996  ereport(elevel,
1997  (errcode(ERRCODE_CONFIG_FILE_ERROR),
1998  errmsg("could not translate RADIUS server name \"%s\" to address: %s",
1999  (char *) lfirst(l), gai_strerror(ret)),
2000  errcontext("line %d of configuration file \"%s\"",
2001  line_num, HbaFileName)));
2002  if (gai_result)
2003  pg_freeaddrinfo_all(hints.ai_family, gai_result);
2004 
2005  list_free(parsed_servers);
2006  return false;
2007  }
2008  pg_freeaddrinfo_all(hints.ai_family, gai_result);
2009  }
2010 
2011  /* All entries are OK, so store them */
2012  hbaline->radiusservers = parsed_servers;
2013  hbaline->radiusservers_s = pstrdup(val);
2014  }
2015  else if (strcmp(name, "radiusports") == 0)
2016  {
2017  List *parsed_ports;
2018  ListCell *l;
2019  char *dupval = pstrdup(val);
2020 
2021  REQUIRE_AUTH_OPTION(uaRADIUS, "radiusports", "radius");
2022 
2023  if (!SplitGUCList(dupval, ',', &parsed_ports))
2024  {
2025  ereport(elevel,
2026  (errcode(ERRCODE_CONFIG_FILE_ERROR),
2027  errmsg("could not parse RADIUS port list \"%s\"",
2028  val),
2029  errcontext("line %d of configuration file \"%s\"",
2030  line_num, HbaFileName)));
2031  *err_msg = psprintf("invalid RADIUS port number: \"%s\"", val);
2032  return false;
2033  }
2034 
2035  foreach(l, parsed_ports)
2036  {
2037  if (atoi(lfirst(l)) == 0)
2038  {
2039  ereport(elevel,
2040  (errcode(ERRCODE_CONFIG_FILE_ERROR),
2041  errmsg("invalid RADIUS port number: \"%s\"", val),
2042  errcontext("line %d of configuration file \"%s\"",
2043  line_num, HbaFileName)));
2044 
2045  return false;
2046  }
2047  }
2048  hbaline->radiusports = parsed_ports;
2049  hbaline->radiusports_s = pstrdup(val);
2050  }
2051  else if (strcmp(name, "radiussecrets") == 0)
2052  {
2053  List *parsed_secrets;
2054  char *dupval = pstrdup(val);
2055 
2056  REQUIRE_AUTH_OPTION(uaRADIUS, "radiussecrets", "radius");
2057 
2058  if (!SplitGUCList(dupval, ',', &parsed_secrets))
2059  {
2060  /* syntax error in list */
2061  ereport(elevel,
2062  (errcode(ERRCODE_CONFIG_FILE_ERROR),
2063  errmsg("could not parse RADIUS secret list \"%s\"",
2064  val),
2065  errcontext("line %d of configuration file \"%s\"",
2066  line_num, HbaFileName)));
2067  return false;
2068  }
2069 
2070  hbaline->radiussecrets = parsed_secrets;
2071  hbaline->radiussecrets_s = pstrdup(val);
2072  }
2073  else if (strcmp(name, "radiusidentifiers") == 0)
2074  {
2075  List *parsed_identifiers;
2076  char *dupval = pstrdup(val);
2077 
2078  REQUIRE_AUTH_OPTION(uaRADIUS, "radiusidentifiers", "radius");
2079 
2080  if (!SplitGUCList(dupval, ',', &parsed_identifiers))
2081  {
2082  /* syntax error in list */
2083  ereport(elevel,
2084  (errcode(ERRCODE_CONFIG_FILE_ERROR),
2085  errmsg("could not parse RADIUS identifiers list \"%s\"",
2086  val),
2087  errcontext("line %d of configuration file \"%s\"",
2088  line_num, HbaFileName)));
2089  return false;
2090  }
2091 
2092  hbaline->radiusidentifiers = parsed_identifiers;
2093  hbaline->radiusidentifiers_s = pstrdup(val);
2094  }
2095  else
2096  {
2097  ereport(elevel,
2098  (errcode(ERRCODE_CONFIG_FILE_ERROR),
2099  errmsg("unrecognized authentication option name: \"%s\"",
2100  name),
2101  errcontext("line %d of configuration file \"%s\"",
2102  line_num, HbaFileName)));
2103  *err_msg = psprintf("unrecognized authentication option name: \"%s\"",
2104  name);
2105  return false;
2106  }
2107  return true;
2108 }
int ldapscope
Definition: hba.h:106
char * radiusports_s
Definition: hba.h:122
Definition: hba.h:30
char * ldapserver
Definition: hba.h:99
#define REQUIRE_AUTH_OPTION(methodval, optname, validmethods)
Definition: hba.c:897
void pg_freeaddrinfo_all(int hint_ai_family, struct addrinfo *ai)
Definition: ip.c:88
Definition: hba.h:38
int ldapport
Definition: hba.h:100
char * ldapbasedn
Definition: hba.h:105
char * ldapscheme
Definition: hba.h:98
char * pamservice
Definition: hba.h:95
char * pstrdup(const char *in)
Definition: mcxt.c:1299
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46
Definition: hba.h:35
#define gettext_noop(x)
Definition: c.h:1197
int errcode(int sqlerrcode)
Definition: elog.c:698
#define MemSet(start, val, len)
Definition: c.h:1008
List * radiussecrets
Definition: hba.h:117
#define gai_strerror
Definition: getaddrinfo.h:146
char * ldapsuffix
Definition: hba.h:108
char * HbaFileName
Definition: guc.c:584
int pg_getaddrinfo_all(const char *hostname, const char *servname, const struct addrinfo *hintp, struct addrinfo **result)
Definition: ip.c:57
#define INVALID_AUTH_OPTION(optname, validmethods)
Definition: hba.c:883
Definition: hba.h:34
ConnType conntype
Definition: hba.h:84
char * radiusservers_s
Definition: hba.h:116
Definition: hba.h:61
bool pam_use_hostname
Definition: hba.h:96
Definition: hba.h:39
char * usermap
Definition: hba.h:94
List * radiusports
Definition: hba.h:121
List * radiusservers
Definition: hba.h:115
bool include_realm
Definition: hba.h:112
char * ldapbinddn
Definition: hba.h:101
char * krb_realm
Definition: hba.h:111
int linenumber
Definition: hba.h:82
char * ldapbindpasswd
Definition: hba.h:102
char * ldapprefix
Definition: hba.h:107
static int elevel
Definition: vacuumlazy.c:400
char * radiusidentifiers_s
Definition: hba.h:120
List * radiusidentifiers
Definition: hba.h:119
char * radiussecrets_s
Definition: hba.h:118
#define ereport(elevel,...)
Definition: elog.h:157
#define lfirst(lc)
Definition: pg_list.h:169
char * ldapsearchfilter
Definition: hba.h:104
ClientCertMode clientcert
Definition: hba.h:109
bool ldaptls
Definition: hba.h:97
char * ldapsearchattribute
Definition: hba.h:103
const char * name
Definition: encode.c:515
bool upn_username
Definition: hba.h:114
int errmsg(const char *fmt,...)
Definition: elog.c:909
void list_free(List *list)
Definition: list.c:1391
#define errcontext
Definition: elog.h:204
bool SplitGUCList(char *rawstring, char separator, List **namelist)
Definition: varlena.c:4001
ClientCertName clientcertname
Definition: hba.h:110
Definition: pg_list.h:50
Definition: hba.h:36
bool compat_realm
Definition: hba.h:113
long val
Definition: informix.c:664
Definition: hba.h:40
UserAuth auth_method
Definition: hba.h:93

◆ parse_hba_line()

static HbaLine* parse_hba_line ( TokenizedLine tok_line,
int  elevel 
)
static

Definition at line 968 of file hba.c.

References HbaLine::addr, HbaLine::addrlen, addrinfo::ai_addr, addrinfo::ai_addrlen, addrinfo::ai_canonname, addrinfo::ai_family, addrinfo::ai_flags, addrinfo::ai_next, AI_NUMERICHOST, addrinfo::ai_protocol, addrinfo::ai_socktype, Assert, HbaLine::auth_method, HbaLine::clientcert, clientCertCA, HbaLine::compat_realm, HbaLine::conntype, copy_hba_token(), ctHost, ctHostGSS, ctHostNoGSS, ctHostNoSSL, ctHostSSL, ctLocal, HbaLine::databases, Db_user_namespace, EAI_NONAME, EnableSSL, ereport, TokenizedLine::err_msg, errcode(), errcontext, errhint(), errmsg(), TokenizedLine::fields, gai_strerror, HbaFileName, HbaLine::hostname, HbaLine::include_realm, HbaLine::ip_cmp_method, ipCmpAll, ipCmpMask, ipCmpSameHost, ipCmpSameNet, lappend(), HbaLine::ldapbasedn, HbaLine::ldapbinddn, HbaLine::ldapbindpasswd, HbaLine::ldapprefix, HbaLine::ldapsearchattribute, HbaLine::ldapsearchfilter, HbaLine::ldapserver, HbaLine::ldapsuffix, List::length, lfirst, TokenizedLine::line_num, HbaLine::linenumber, linitial, list_head(), list_length(), lnext(), LOG, MANDATORY_AUTH_ARG, HbaLine::mask, HbaLine::masklen, NIL, palloc0(), parse_hba_auth_opt(), pfree(), pg_freeaddrinfo_all(), pg_getaddrinfo_all(), pg_sockaddr_cidr_mask(), psprintf(), pstrdup(), HbaLine::radiusidentifiers, HbaLine::radiusports, HbaLine::radiussecrets, HbaLine::radiusservers, TokenizedLine::raw_line, HbaLine::rawline, HbaLine::roles, generate_unaccent_rules::str, HbaToken::string, token_is_keyword, uaBSD, uaCert, uaGSS, uaIdent, uaLDAP, uaMD5, uaPAM, uaPassword, uaRADIUS, uaReject, uaSCRAM, uaSSPI, uaTrust, HbaLine::upn_username, val, and verify_option_list_length().

Referenced by fill_hba_view(), and load_hba().

969 {
970  int line_num = tok_line->line_num;
971  char **err_msg = &tok_line->err_msg;
972  char *str;
973  struct addrinfo *gai_result;
974  struct addrinfo hints;
975  int ret;
976  char *cidr_slash;
977  char *unsupauth;
978  ListCell *field;
979  List *tokens;
980  ListCell *tokencell;
981  HbaToken *token;
982  HbaLine *parsedline;
983 
984  parsedline = palloc0(sizeof(HbaLine));
985  parsedline->linenumber = line_num;
986  parsedline->rawline = pstrdup(tok_line->raw_line);
987 
988  /* Check the record type. */
989  Assert(tok_line->fields != NIL);
990  field = list_head(tok_line->fields);
991  tokens = lfirst(field);
992  if (tokens->length > 1)
993  {
994  ereport(elevel,
995  (errcode(ERRCODE_CONFIG_FILE_ERROR),
996  errmsg("multiple values specified for connection type"),
997  errhint("Specify exactly one connection type per line."),
998  errcontext("line %d of configuration file \"%s\"",
999  line_num, HbaFileName)));
1000  *err_msg = "multiple values specified for connection type";
1001  return NULL;
1002  }
1003  token = linitial(tokens);
1004  if (strcmp(token->string, "local") == 0)
1005  {
1006 #ifdef HAVE_UNIX_SOCKETS
1007  parsedline->conntype = ctLocal;
1008 #else
1009  ereport(elevel,
1010  (errcode(ERRCODE_CONFIG_FILE_ERROR),
1011  errmsg("local connections are not supported by this build"),
1012  errcontext("line %d of configuration file \"%s\"",
1013  line_num, HbaFileName)));
1014  *err_msg = "local connections are not supported by this build";
1015  return NULL;
1016 #endif
1017  }
1018  else if (strcmp(token->string, "host") == 0 ||
1019  strcmp(token->string, "hostssl") == 0 ||
1020  strcmp(token->string, "hostnossl") == 0 ||
1021  strcmp(token->string, "hostgssenc") == 0 ||
1022  strcmp(token->string, "hostnogssenc") == 0)
1023  {
1024 
1025  if (token->string[4] == 's') /* "hostssl" */
1026  {
1027  parsedline->conntype = ctHostSSL;
1028  /* Log a warning if SSL support is not active */
1029 #ifdef USE_SSL
1030  if (!EnableSSL)
1031  {
1032  ereport(elevel,
1033  (errcode(ERRCODE_CONFIG_FILE_ERROR),
1034  errmsg("hostssl record cannot match because SSL is disabled"),
1035  errhint("Set ssl = on in postgresql.conf."),
1036  errcontext("line %d of configuration file \"%s\"",
1037  line_num, HbaFileName)));
1038  *err_msg = "hostssl record cannot match because SSL is disabled";
1039  }
1040 #else
1041  ereport(elevel,
1042  (errcode(ERRCODE_CONFIG_FILE_ERROR),
1043  errmsg("hostssl record cannot match because SSL is not supported by this build"),
1044  errhint("Compile with --with-ssl to use SSL connections."),
1045  errcontext("line %d of configuration file \"%s\"",
1046  line_num, HbaFileName)));
1047  *err_msg = "hostssl record cannot match because SSL is not supported by this build";
1048 #endif
1049  }
1050  else if (token->string[4] == 'g') /* "hostgssenc" */
1051  {
1052  parsedline->conntype = ctHostGSS;
1053 #ifndef ENABLE_GSS
1054  ereport(elevel,
1055  (errcode(ERRCODE_CONFIG_FILE_ERROR),
1056  errmsg("hostgssenc record cannot match because GSSAPI is not supported by this build"),
1057  errhint("Compile with --with-gssapi to use GSSAPI connections."),
1058  errcontext("line %d of configuration file \"%s\"",
1059  line_num, HbaFileName)));
1060  *err_msg = "hostgssenc record cannot match because GSSAPI is not supported by this build";
1061 #endif
1062  }
1063  else if (token->string[4] == 'n' && token->string[6] == 's')
1064  parsedline->conntype = ctHostNoSSL;
1065  else if (token->string[4] == 'n' && token->string[6] == 'g')
1066  parsedline->conntype = ctHostNoGSS;
1067  else
1068  {
1069  /* "host" */
1070  parsedline->conntype = ctHost;
1071  }
1072  } /* record type */
1073  else
1074  {
1075  ereport(elevel,
1076  (errcode(ERRCODE_CONFIG_FILE_ERROR),
1077  errmsg("invalid connection type \"%s\"",
1078  token->string),
1079  errcontext("line %d of configuration file \"%s\"",
1080  line_num, HbaFileName)));
1081  *err_msg = psprintf("invalid connection type \"%s\"", token->string);
1082  return NULL;
1083  }
1084 
1085  /* Get the databases. */
1086  field = lnext(tok_line->fields, field);
1087  if (!field)
1088  {
1089  ereport(elevel,
1090  (errcode(ERRCODE_CONFIG_FILE_ERROR),
1091  errmsg("end-of-line before database specification"),
1092  errcontext("line %d of configuration file \"%s\"",
1093  line_num, HbaFileName)));
1094  *err_msg = "end-of-line before database specification";
1095  return NULL;
1096  }
1097  parsedline->databases = NIL;
1098  tokens = lfirst(field);
1099  foreach(tokencell, tokens)
1100  {
1101  parsedline->databases = lappend(parsedline->databases,
1102  copy_hba_token(lfirst(tokencell)));
1103  }
1104 
1105  /* Get the roles. */
1106  field = lnext(tok_line->fields, field);
1107  if (!field)
1108  {
1109  ereport(elevel,
1110  (errcode(ERRCODE_CONFIG_FILE_ERROR),
1111  errmsg("end-of-line before role specification"),
1112  errcontext("line %d of configuration file \"%s\"",
1113  line_num, HbaFileName)));
1114  *err_msg = "end-of-line before role specification";
1115  return NULL;
1116  }
1117  parsedline->roles = NIL;
1118  tokens = lfirst(field);
1119  foreach(tokencell, tokens)
1120  {
1121  parsedline->roles = lappend(parsedline->roles,
1122  copy_hba_token(lfirst(tokencell)));
1123  }
1124 
1125  if (parsedline->conntype != ctLocal)
1126  {
1127  /* Read the IP address field. (with or without CIDR netmask) */
1128  field = lnext(tok_line->fields, field);
1129  if (!field)
1130  {
1131  ereport(elevel,
1132  (errcode(ERRCODE_CONFIG_FILE_ERROR),
1133  errmsg("end-of-line before IP address specification"),
1134  errcontext("line %d of configuration file \"%s\"",
1135  line_num, HbaFileName)));
1136  *err_msg = "end-of-line before IP address specification";
1137  return NULL;
1138  }
1139  tokens = lfirst(field);
1140  if (tokens->length > 1)
1141  {
1142  ereport(elevel,
1143  (errcode(ERRCODE_CONFIG_FILE_ERROR),
1144  errmsg("multiple values specified for host address"),
1145  errhint("Specify one address range per line."),
1146  errcontext("line %d of configuration file \"%s\"",
1147  line_num, HbaFileName)));
1148  *err_msg = "multiple values specified for host address";
1149  return NULL;
1150  }
1151  token = linitial(tokens);
1152 
1153  if (token_is_keyword(token, "all"))
1154  {
1155  parsedline->ip_cmp_method = ipCmpAll;
1156  }
1157  else if (token_is_keyword(token, "samehost"))
1158  {
1159  /* Any IP on this host is allowed to connect */
1160  parsedline->ip_cmp_method = ipCmpSameHost;
1161  }
1162  else if (token_is_keyword(token, "samenet"))
1163  {
1164  /* Any IP on the host's subnets is allowed to connect */
1165  parsedline->ip_cmp_method = ipCmpSameNet;
1166  }
1167  else
1168  {
1169  /* IP and netmask are specified */
1170  parsedline->ip_cmp_method = ipCmpMask;
1171 
1172  /* need a modifiable copy of token */
1173  str = pstrdup(token->string);
1174 
1175  /* Check if it has a CIDR suffix and if so isolate it */
1176  cidr_slash = strchr(str, '/');
1177  if (cidr_slash)
1178  *cidr_slash = '\0';
1179 
1180  /* Get the IP address either way */
1181  hints.ai_flags = AI_NUMERICHOST;
1182  hints.ai_family = AF_UNSPEC;
1183  hints.ai_socktype = 0;
1184  hints.ai_protocol = 0;
1185  hints.ai_addrlen = 0;
1186  hints.ai_canonname = NULL;
1187  hints.ai_addr = NULL;
1188  hints.ai_next = NULL;
1189 
1190  ret = pg_getaddrinfo_all(str, NULL, &hints, &gai_result);
1191  if (ret == 0 && gai_result)
1192  {
1193  memcpy(&parsedline->addr, gai_result->ai_addr,
1194  gai_result->ai_addrlen);
1195  parsedline->addrlen = gai_result->ai_addrlen;
1196  }
1197  else if (ret == EAI_NONAME)
1198  parsedline->hostname = str;
1199  else
1200  {
1201  ereport(elevel,
1202  (errcode(ERRCODE_CONFIG_FILE_ERROR),
1203  errmsg("invalid IP address \"%s\": %s",
1204  str, gai_strerror(ret)),
1205  errcontext("line %d of configuration file \"%s\"",
1206  line_num, HbaFileName)));
1207  *err_msg = psprintf("invalid IP address \"%s\": %s",
1208  str, gai_strerror(ret));
1209  if (gai_result)
1210  pg_freeaddrinfo_all(hints.ai_family, gai_result);
1211  return NULL;
1212  }
1213 
1214  pg_freeaddrinfo_all(hints.ai_family, gai_result);
1215 
1216  /* Get the netmask */
1217  if (cidr_slash)
1218  {
1219  if (parsedline->hostname)
1220  {
1221  ereport(elevel,
1222  (errcode(ERRCODE_CONFIG_FILE_ERROR),
1223  errmsg("specifying both host name and CIDR mask is invalid: \"%s\"",
1224  token->string),
1225  errcontext("line %d of configuration file \"%s\"",
1226  line_num, HbaFileName)));
1227  *err_msg = psprintf("specifying both host name and CIDR mask is invalid: \"%s\"",
1228  token->string);
1229  return NULL;
1230  }
1231 
1232  if (pg_sockaddr_cidr_mask(&parsedline->mask, cidr_slash + 1,
1233  parsedline->addr.ss_family) < 0)
1234  {
1235  ereport(elevel,
1236  (errcode(ERRCODE_CONFIG_FILE_ERROR),
1237  errmsg("invalid CIDR mask in address \"%s\"",
1238  token->string),
1239  errcontext("line %d of configuration file \"%s\"",
1240  line_num, HbaFileName)));
1241  *err_msg = psprintf("invalid CIDR mask in address \"%s\"",
1242  token->string);
1243  return NULL;
1244  }
1245  parsedline->masklen = parsedline->addrlen;
1246  pfree(str);
1247  }
1248  else if (!parsedline->hostname)
1249  {
1250  /* Read the mask field. */
1251  pfree(str);
1252  field = lnext(tok_line->fields, field);
1253  if (!field)
1254  {
1255  ereport(elevel,
1256  (errcode(ERRCODE_CONFIG_FILE_ERROR),
1257  errmsg("end-of-line before netmask specification"),
1258  errhint("Specify an address range in CIDR notation, or provide a separate netmask."),
1259  errcontext("line %d of configuration file \"%s\"",
1260  line_num, HbaFileName)));
1261  *err_msg = "end-of-line before netmask specification";
1262  return NULL;
1263  }
1264  tokens = lfirst(field);
1265  if (tokens->length > 1)
1266  {
1267  ereport(elevel,
1268  (errcode(ERRCODE_CONFIG_FILE_ERROR),
1269  errmsg("multiple values specified for netmask"),
1270  errcontext("line %d of configuration file \"%s\"",
1271  line_num, HbaFileName)));
1272  *err_msg = "multiple values specified for netmask";
1273  return NULL;
1274  }
1275  token = linitial(tokens);
1276 
1277  ret = pg_getaddrinfo_all(token->string, NULL,
1278  &hints, &gai_result);
1279  if (ret || !gai_result)
1280  {
1281  ereport(elevel,
1282  (errcode(ERRCODE_CONFIG_FILE_ERROR),
1283  errmsg("invalid IP mask \"%s\": %s",
1284  token->string, gai_strerror(ret)),
1285  errcontext("line %d of configuration file \"%s\"",
1286  line_num, HbaFileName)));
1287  *err_msg = psprintf("invalid IP mask \"%s\": %s",
1288  token->string, gai_strerror(ret));
1289  if (gai_result)
1290  pg_freeaddrinfo_all(hints.ai_family, gai_result);
1291  return NULL;
1292  }
1293 
1294  memcpy(&parsedline->mask, gai_result->ai_addr,
1295  gai_result->ai_addrlen);
1296  parsedline->masklen = gai_result->ai_addrlen;
1297  pg_freeaddrinfo_all(hints.ai_family, gai_result);
1298 
1299  if (parsedline->addr.ss_family != parsedline->mask.ss_family)
1300  {
1301  ereport(elevel,
1302  (errcode(ERRCODE_CONFIG_FILE_ERROR),
1303  errmsg("IP address and mask do not match"),
1304  errcontext("line %d of configuration file \"%s\"",
1305  line_num, HbaFileName)));
1306  *err_msg = "IP address and mask do not match";
1307  return NULL;
1308  }
1309  }
1310  }
1311  } /* != ctLocal */
1312 
1313  /* Get the authentication method */
1314  field = lnext(tok_line->fields, field);
1315  if (!field)
1316  {
1317  ereport(elevel,
1318  (errcode(ERRCODE_CONFIG_FILE_ERROR),
1319  errmsg("end-of-line before authentication method"),
1320  errcontext("line %d of configuration file \"%s\"",
1321  line_num, HbaFileName)));
1322  *err_msg = "end-of-line before authentication method";
1323  return NULL;
1324  }
1325  tokens = lfirst(field);
1326  if (tokens->length > 1)
1327  {
1328  ereport(elevel,
1329  (errcode(ERRCODE_CONFIG_FILE_ERROR),
1330  errmsg("multiple values specified for authentication type"),
1331  errhint("Specify exactly one authentication type per line."),
1332  errcontext("line %d of configuration file \"%s\"",
1333  line_num, HbaFileName)));
1334  *err_msg = "multiple values specified for authentication type";
1335  return NULL;
1336  }
1337  token = linitial(tokens);
1338 
1339  unsupauth = NULL;
1340  if (strcmp(token->string, "trust") == 0)
1341  parsedline->auth_method = uaTrust;
1342  else if (strcmp(token->string, "ident") == 0)
1343  parsedline->auth_method = uaIdent;
1344  else if (strcmp(token->string, "peer") == 0)
1345  parsedline->auth_method = uaPeer;
1346  else if (strcmp(token->string, "password") == 0)
1347  parsedline->auth_method = uaPassword;
1348  else if (strcmp(token->string, "gss") == 0)
1349 #ifdef ENABLE_GSS
1350  parsedline->auth_method = uaGSS;
1351 #else
1352  unsupauth = "gss";
1353 #endif
1354  else if (strcmp(token->string, "sspi") == 0)
1355 #ifdef ENABLE_SSPI
1356  parsedline->auth_method = uaSSPI;
1357 #else
1358  unsupauth = "sspi";
1359 #endif
1360  else if (strcmp(token->string, "reject") == 0)
1361  parsedline->auth_method = uaReject;
1362  else if (strcmp(token->string, "md5") == 0)
1363  {
1364  if (Db_user_namespace)
1365  {
1366  ereport(elevel,
1367  (errcode(ERRCODE_CONFIG_FILE_ERROR),
1368  errmsg("MD5 authentication is not supported when \"db_user_namespace\" is enabled"),
1369  errcontext("line %d of configuration file \"%s\"",
1370  line_num, HbaFileName)));
1371  *err_msg = "MD5 authentication is not supported when \"db_user_namespace\" is enabled";
1372  return NULL;
1373  }
1374  parsedline->auth_method = uaMD5;
1375  }
1376  else if (strcmp(token->string, "scram-sha-256") == 0)
1377  parsedline->auth_method = uaSCRAM;
1378  else if (strcmp(token->string, "pam") == 0)
1379 #ifdef USE_PAM
1380  parsedline->auth_method = uaPAM;
1381 #else
1382  unsupauth = "pam";
1383 #endif
1384  else if (strcmp(token->string, "bsd") == 0)
1385 #ifdef USE_BSD_AUTH
1386  parsedline->auth_method = uaBSD;
1387 #else
1388  unsupauth = "bsd";
1389 #endif
1390  else if (strcmp(token->string, "ldap") == 0)
1391 #ifdef USE_LDAP
1392  parsedline->auth_method = uaLDAP;
1393 #else
1394  unsupauth = "ldap";
1395 #endif
1396  else if (strcmp(token->string, "cert") == 0)
1397 #ifdef USE_SSL
1398  parsedline->auth_method = uaCert;
1399 #else
1400  unsupauth = "cert";
1401 #endif
1402  else if (strcmp(token->string, "radius") == 0)
1403  parsedline->auth_method = uaRADIUS;
1404  else
1405  {
1406  ereport(elevel,
1407  (errcode(ERRCODE_CONFIG_FILE_ERROR),
1408  errmsg("invalid authentication method \"%s\"",
1409  token->string),
1410  errcontext("line %d of configuration file \"%s\"",
1411  line_num, HbaFileName)));
1412  *err_msg = psprintf("invalid authentication method \"%s\"",
1413  token->string);
1414  return NULL;
1415  }
1416 
1417  if (unsupauth)
1418  {
1419  ereport(elevel,
1420  (errcode(ERRCODE_CONFIG_FILE_ERROR),
1421  errmsg("invalid authentication method \"%s\": not supported by this build",
1422  token->string),
1423  errcontext("line %d of configuration file \"%s\"",
1424  line_num, HbaFileName)));
1425  *err_msg = psprintf("invalid authentication method \"%s\": not supported by this build",
1426  token->string);
1427  return NULL;
1428  }
1429 
1430  /*
1431  * XXX: When using ident on local connections, change it to peer, for
1432  * backwards compatibility.
1433  */
1434  if (parsedline->conntype == ctLocal &&
1435  parsedline->auth_method == uaIdent)
1436  parsedline->auth_method = uaPeer;
1437 
1438  /* Invalid authentication combinations */
1439  if (parsedline->conntype == ctLocal &&
1440  parsedline->auth_method == uaGSS)
1441  {
1442  ereport(elevel,
1443  (errcode(ERRCODE_CONFIG_FILE_ERROR),
1444  errmsg("gssapi authentication is not supported on local sockets"),
1445  errcontext("line %d of configuration file \"%s\"",
1446  line_num, HbaFileName)));
1447  *err_msg = "gssapi authentication is not supported on local sockets";
1448  return NULL;
1449  }
1450 
1451  if (parsedline->conntype != ctLocal &&
1452  parsedline->auth_method == uaPeer)
1453  {
1454  ereport(elevel,
1455  (errcode(ERRCODE_CONFIG_FILE_ERROR),
1456  errmsg("peer authentication is only supported on local sockets"),
1457  errcontext("line %d of configuration file \"%s\"",
1458  line_num, HbaFileName)));
1459  *err_msg = "peer authentication is only supported on local sockets";
1460  return NULL;
1461  }
1462 
1463  /*
1464  * SSPI authentication can never be enabled on ctLocal connections,
1465  * because it's only supported on Windows, where ctLocal isn't supported.
1466  */
1467 
1468 
1469  if (parsedline->conntype != ctHostSSL &&
1470  parsedline->auth_method == uaCert)
1471  {
1472  ereport(elevel,
1473  (errcode(ERRCODE_CONFIG_FILE_ERROR),
1474  errmsg("cert authentication is only supported on hostssl connections"),
1475  errcontext("line %d of configuration file \"%s\"",
1476  line_num, HbaFileName)));
1477  *err_msg = "cert authentication is only supported on hostssl connections";
1478  return NULL;
1479  }
1480 
1481  /*
1482  * For GSS and SSPI, set the default value of include_realm to true.
1483  * Having include_realm set to false is dangerous in multi-realm
1484  * situations and is generally considered bad practice. We keep the
1485  * capability around for backwards compatibility, but we might want to
1486  * remove it at some point in the future. Users who still need to strip
1487  * the realm off would be better served by using an appropriate regex in a
1488  * pg_ident.conf mapping.
1489  */
1490  if (parsedline->auth_method == uaGSS ||
1491  parsedline->auth_method == uaSSPI)
1492  parsedline->include_realm = true;
1493 
1494  /*
1495  * For SSPI, include_realm defaults to the SAM-compatible domain (aka
1496  * NetBIOS name) and user names instead of the Kerberos principal name for
1497  * compatibility.
1498  */
1499  if (parsedline->auth_method == uaSSPI)
1500  {
1501  parsedline->compat_realm = true;
1502  parsedline->upn_username = false;
1503  }
1504 
1505  /* Parse remaining arguments */
1506  while ((field = lnext(tok_line->fields, field)) != NULL)
1507  {
1508  tokens = lfirst(field);
1509  foreach(tokencell, tokens)
1510  {
1511  char *val;
1512 
1513  token = lfirst(tokencell);
1514 
1515  str = pstrdup(token->string);
1516  val = strchr(str, '=');
1517  if (val == NULL)
1518  {
1519  /*
1520  * Got something that's not a name=value pair.
1521  */
1522  ereport(elevel,
1523  (errcode(ERRCODE_CONFIG_FILE_ERROR),
1524  errmsg("authentication option not in name=value format: %s", token->string),
1525  errcontext("line %d of configuration file \"%s\"",
1526  line_num, HbaFileName)));
1527  *err_msg = psprintf("authentication option not in name=value format: %s",
1528  token->string);
1529  return NULL;
1530  }
1531 
1532  *val++ = '\0'; /* str now holds "name", val holds "value" */
1533  if (!parse_hba_auth_opt(str, val, parsedline, elevel, err_msg))
1534  /* parse_hba_auth_opt already logged the error message */
1535  return NULL;
1536  pfree(str);
1537  }
1538  }
1539 
1540  /*
1541  * Check if the selected authentication method has any mandatory arguments
1542  * that are not set.
1543  */
1544  if (parsedline->auth_method == uaLDAP)
1545  {
1546 #ifndef HAVE_LDAP_INITIALIZE
1547  /* Not mandatory for OpenLDAP, because it can use DNS SRV records */
1548  MANDATORY_AUTH_ARG(parsedline->ldapserver, "ldapserver", "ldap");
1549 #endif
1550 
1551  /*
1552  * LDAP can operate in two modes: either with a direct bind, using
1553  * ldapprefix and ldapsuffix, or using a search+bind, using
1554  * ldapbasedn, ldapbinddn, ldapbindpasswd and one of
1555  * ldapsearchattribute or ldapsearchfilter. Disallow mixing these
1556  * parameters.
1557  */
1558  if (parsedline->ldapprefix || parsedline->ldapsuffix)
1559  {
1560  if (parsedline->ldapbasedn ||
1561  parsedline->ldapbinddn ||
1562  parsedline->ldapbindpasswd ||
1563  parsedline->ldapsearchattribute ||
1564  parsedline->ldapsearchfilter)
1565  {
1566  ereport(elevel,
1567  (errcode(ERRCODE_CONFIG_FILE_ERROR),
1568  errmsg("cannot use ldapbasedn, ldapbinddn, ldapbindpasswd, ldapsearchattribute, ldapsearchfilter, or ldapurl together with ldapprefix"),
1569  errcontext("line %d of configuration file \"%s\"",
1570  line_num, HbaFileName)));
1571  *err_msg = "cannot use ldapbasedn, ldapbinddn, ldapbindpasswd, ldapsearchattribute, ldapsearchfilter, or ldapurl together with ldapprefix";
1572  return NULL;
1573  }
1574  }
1575  else if (!parsedline->ldapbasedn)
1576  {
1577  ereport(elevel,
1578  (errcode(ERRCODE_CONFIG_FILE_ERROR),
1579  errmsg("authentication method \"ldap\" requires argument \"ldapbasedn\", \"ldapprefix\", or \"ldapsuffix\" to be set"),
1580  errcontext("line %d of configuration file \"%s\"",
1581  line_num, HbaFileName)));
1582  *err_msg = "authentication method \"ldap\" requires argument \"ldapbasedn\", \"ldapprefix\", or \"ldapsuffix\" to be set";
1583  return NULL;
1584  }
1585 
1586  /*
1587  * When using search+bind, you can either use a simple attribute
1588  * (defaulting to "uid") or a fully custom search filter. You can't
1589  * do both.
1590  */
1591  if (parsedline->ldapsearchattribute && parsedline->ldapsearchfilter)
1592  {
1593  ereport(elevel,
1594  (errcode(ERRCODE_CONFIG_FILE_ERROR),
1595  errmsg("cannot use ldapsearchattribute together with ldapsearchfilter"),
1596  errcontext("line %d of configuration file \"%s\"",
1597  line_num, HbaFileName)));
1598  *err_msg = "cannot use ldapsearchattribute together with ldapsearchfilter";
1599  return NULL;
1600  }
1601  }
1602 
1603  if (parsedline->auth_method == uaRADIUS)
1604  {
1605  MANDATORY_AUTH_ARG(parsedline->radiusservers, "radiusservers", "radius");
1606  MANDATORY_AUTH_ARG(parsedline->radiussecrets, "radiussecrets", "radius");
1607 
1608  if (list_length(parsedline->radiusservers) < 1)
1609  {
1610  ereport(LOG,
1611  (errcode(ERRCODE_CONFIG_FILE_ERROR),
1612  errmsg("list of RADIUS servers cannot be empty"),
1613  errcontext("line %d of configuration file \"%s\"",
1614  line_num, HbaFileName)));
1615  return NULL;
1616  }
1617 
1618  if (list_length(parsedline->radiussecrets) < 1)
1619  {
1620  ereport(LOG,
1621  (errcode(ERRCODE_CONFIG_FILE_ERROR),
1622  errmsg("list of RADIUS secrets cannot be empty"),
1623  errcontext("line %d of configuration file \"%s\"",
1624  line_num, HbaFileName)));
1625  return NULL;
1626  }
1627 
1628  /*
1629  * Verify length of option lists - each can be 0 (except for secrets,
1630  * but that's already checked above), 1 (use the same value
1631  * everywhere) or the same as the number of servers.
1632  */
1633  if (!verify_option_list_length(parsedline->radiussecrets,
1634  "RADIUS secrets",
1635  parsedline->radiusservers,
1636  "RADIUS servers",
1637  line_num))
1638  return NULL;
1639  if (!verify_option_list_length(parsedline->radiusports,
1640  "RADIUS ports",
1641  parsedline->radiusservers,
1642  "RADIUS servers",
1643  line_num))
1644  return NULL;
1646  "RADIUS identifiers",
1647  parsedline->radiusservers,
1648  "RADIUS servers",
1649  line_num))
1650  return NULL;
1651  }
1652 
1653  /*
1654  * Enforce any parameters implied by other settings.
1655  */
1656  if (parsedline->auth_method == uaCert)
1657  {
1658  parsedline->clientcert = clientCertCA;
1659  }
1660 
1661  return parsedline;
1662 }
List * databases
Definition: hba.h:85
Definition: hba.h:80
#define NIL
Definition: pg_list.h:65
Definition: hba.h:30
bool EnableSSL
Definition: postmaster.c:233
char * ldapserver
Definition: hba.h:99
void pg_freeaddrinfo_all(int hint_ai_family, struct addrinfo *ai)
Definition: ip.c:88
struct sockaddr_storage mask
Definition: hba.h:89
int errhint(const char *fmt,...)
Definition: elog.c:1156
Definition: hba.h:38
char * ldapbasedn
Definition: hba.h:105
static ListCell * lnext(const List *l, const ListCell *c)
Definition: pg_list.h:322
Definition: hba.h:32
static bool parse_hba_auth_opt(char *name, char *val, HbaLine *hbaline, int elevel, char **err_msg)
Definition: hba.c:1695
Definition: hba.h:51
char * pstrdup(const char *in)
Definition: mcxt.c:1299
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46
Definition: hba.h:35
int errcode(int sqlerrcode)
Definition: elog.c:698
#define LOG
Definition: elog.h:26
#define AI_NUMERICHOST
Definition: getaddrinfo.h:73
List * radiussecrets
Definition: hba.h:117
#define gai_strerror
Definition: getaddrinfo.h:146
char * ldapsuffix
Definition: hba.h:108
char * HbaFileName
Definition: guc.c:584
int pg_getaddrinfo_all(const char *hostname, const char *servname, const struct addrinfo *hintp, struct addrinfo **result)
Definition: ip.c:57
Definition: hba.h:34
Definition: hba.h:31
ConnType conntype
Definition: hba.h:84
void pfree(void *pointer)
Definition: mcxt.c:1169
Definition: hba.h:61
#define linitial(l)
Definition: pg_list.h:174
Definition: hba.h:39
int pg_sockaddr_cidr_mask(struct sockaddr_storage *mask, char *numbits, int family)
Definition: ifaddr.c:115
struct sockaddr_storage addr
Definition: hba.h:87
Definition: hba.h:63
int line_num
Definition: hba.c:92
List * radiusports
Definition: hba.h:121
Definition: hba.h:27
List * radiusservers
Definition: hba.h:115
bool include_realm
Definition: hba.h:112
Definition: hba.h:29
bool Db_user_namespace
Definition: postmaster.c:240
char * err_msg
Definition: hba.c:94
Definition: hba.c:75
char * ldapbinddn
Definition: hba.h:101
#define EAI_NONAME
Definition: getaddrinfo.h:34
static ListCell * list_head(const List *l)
Definition: pg_list.h:125
int linenumber
Definition: hba.h:82
#define MANDATORY_AUTH_ARG(argvar, argname, authname)
Definition: hba.c:903
char * ldapbindpasswd
Definition: hba.h:102
List * fields
Definition: hba.c:91
static bool verify_option_list_length(List *options, const char *optionname, List *comparelist, const char *comparename, int line_num)
Definition: hba.c:1666
char * ldapprefix
Definition: hba.h:107
Definition: hba.h:59
List * lappend(List *list, void *datum)
Definition: list.c:336
static int elevel
Definition: vacuumlazy.c:400
Definition: hba.h:33
Definition: hba.h:54
void * palloc0(Size size)
Definition: mcxt.c:1093
char * hostname
Definition: hba.h:92
char * string
Definition: hba.c:77
List * radiusidentifiers
Definition: hba.h:119
Definition: hba.h:37
#define ereport(elevel,...)
Definition: elog.h:157
List * roles
Definition: hba.h:86
#define Assert(condition)
Definition: c.h:804
#define lfirst(lc)
Definition: pg_list.h:169
char * ldapsearchfilter
Definition: hba.h:104
ClientCertMode clientcert
Definition: hba.h:109
static int list_length(const List *l)
Definition: pg_list.h:149
char * ldapsearchattribute
Definition: hba.h:103
int length
Definition: pg_list.h:53
char * rawline
Definition: hba.h:83
static HbaToken * copy_hba_token(HbaToken *in)
Definition: hba.c:315
bool upn_username
Definition: hba.h:114
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define token_is_keyword(t, k)
Definition: hba.c:68
#define errcontext
Definition: elog.h:204
size_t ai_addrlen
Definition: getaddrinfo.h:104
char * raw_line
Definition: hba.c:93
IPCompareMethod ip_cmp_method
Definition: hba.h:91
int masklen
Definition: hba.h:90
int addrlen
Definition: hba.h:88
Definition: pg_list.h:50
Definition: hba.h:36
bool compat_realm
Definition: hba.h:113
long val
Definition: informix.c:664
Definition: hba.h:60
Definition: hba.h:40
UserAuth auth_method
Definition: hba.h:93
struct sockaddr * ai_addr
Definition: getaddrinfo.h:105

◆ parse_ident_line()

static IdentLine* parse_ident_line ( TokenizedLine tok_line)
static

Definition at line 2756 of file hba.c.

References Assert, ereport, errcode(), errmsg(), TokenizedLine::fields, IDENT_FIELD_ABSENT, IDENT_MULTI_VALUE, IdentLine::ident_user, lfirst, TokenizedLine::line_num, IdentLine::linenumber, linitial, list_head(), lnext(), LOG, NIL, palloc(), palloc0(), pfree(), pg_mb2wchar_with_len(), pg_regcomp(), pg_regerror(), IdentLine::pg_role, pstrdup(), IdentLine::re, REG_ADVANCED, HbaToken::string, and IdentLine::usermap.

Referenced by load_ident().

2757 {
2758  int line_num = tok_line->line_num;
2759  ListCell *field;
2760  List *tokens;
2761  HbaToken *token;
2762  IdentLine *parsedline;
2763 
2764  Assert(tok_line->fields != NIL);
2765  field = list_head(tok_line->fields);
2766 
2767  parsedline = palloc0(sizeof(IdentLine));
2768  parsedline->linenumber = line_num;
2769 
2770  /* Get the map token (must exist) */
2771  tokens = lfirst(field);
2772  IDENT_MULTI_VALUE(tokens);
2773  token = linitial(tokens);
2774  parsedline->usermap = pstrdup(token->string);
2775 
2776  /* Get the ident user token */
2777  field = lnext(tok_line->fields, field);
2778  IDENT_FIELD_ABSENT(field);
2779  tokens = lfirst(field);
2780  IDENT_MULTI_VALUE(tokens);
2781  token = linitial(tokens);
2782  parsedline->ident_user = pstrdup(token->string);
2783 
2784  /* Get the PG rolename token */
2785  field = lnext(tok_line->fields, field);
2786  IDENT_FIELD_ABSENT(field);
2787  tokens = lfirst(field);
2788  IDENT_MULTI_VALUE(tokens);
2789  token = linitial(tokens);
2790  parsedline->pg_role = pstrdup(token->string);
2791 
2792  if (parsedline->ident_user[0] == '/')
2793  {
2794  /*
2795  * When system username starts with a slash, treat it as a regular
2796  * expression. Pre-compile it.
2797  */
2798  int r;
2799  pg_wchar *wstr;
2800  int wlen;
2801 
2802  wstr = palloc((strlen(parsedline->ident_user + 1) + 1) * sizeof(pg_wchar));
2803  wlen = pg_mb2wchar_with_len(parsedline->ident_user + 1,
2804  wstr, strlen(parsedline->ident_user + 1));
2805 
2806  r = pg_regcomp(&parsedline->re, wstr, wlen, REG_ADVANCED, C_COLLATION_OID);
2807  if (r)
2808  {
2809  char errstr[100];
2810 
2811  pg_regerror(r, &parsedline->re, errstr, sizeof(errstr));
2812  ereport(LOG,
2813  (errcode(ERRCODE_INVALID_REGULAR_EXPRESSION),
2814  errmsg("invalid regular expression \"%s\": %s",
2815  parsedline->ident_user + 1, errstr)));
2816 
2817  pfree(wstr);
2818  return NULL;
2819  }
2820  pfree(wstr);
2821  }
2822 
2823  return parsedline;
2824 }
#define NIL
Definition: pg_list.h:65
static ListCell * lnext(const List *l, const ListCell *c)
Definition: pg_list.h:322
regex_t re
Definition: hba.h:132
char * pstrdup(const char *in)
Definition: mcxt.c:1299
int errcode(int sqlerrcode)
Definition: elog.c:698
#define LOG
Definition: elog.h:26
int pg_regcomp(regex_t *re, const chr *string, size_t len, int flags, Oid collation)
Definition: regcomp.c:328
#define IDENT_FIELD_ABSENT(field)
Definition: hba.c:931
int linenumber
Definition: hba.h:127
void pfree(void *pointer)
Definition: mcxt.c:1169
#define linitial(l)
Definition: pg_list.h:174
int line_num
Definition: hba.c:92
char * usermap
Definition: hba.h:129
Definition: hba.c:75
static ListCell * list_head(const List *l)
Definition: pg_list.h:125
size_t pg_regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size)
Definition: regerror.c:60
#define REG_ADVANCED
Definition: regex.h:105
List * fields
Definition: hba.c:91
unsigned int pg_wchar
Definition: mbprint.c:31
#define IDENT_MULTI_VALUE(tokens)
Definition: hba.c:942
void * palloc0(Size size)
Definition: mcxt.c:1093
char * string
Definition: hba.c:77
int pg_mb2wchar_with_len(const char *from, pg_wchar *to, int len)
Definition: mbutils.c:929
#define ereport(elevel,...)
Definition: elog.h:157
#define Assert(condition)
Definition: c.h:804
#define lfirst(lc)
Definition: pg_list.h:169
Definition: hba.h:125
char * ident_user
Definition: hba.h:130
void * palloc(Size size)
Definition: mcxt.c:1062
int errmsg(const char *fmt,...)
Definition: elog.c:909
Definition: pg_list.h:50
char * pg_role
Definition: hba.h:131

◆ pg_hba_file_rules()

Datum pg_hba_file_rules ( PG_FUNCTION_ARGS  )

Definition at line 2694 of file hba.c.

References ReturnSetInfo::allowedModes, ReturnSetInfo::econtext, ExprContext::ecxt_per_query_memory, elog, ereport, errcode(), errmsg(), ERROR, fill_hba_view(), get_call_result_type(), IsA, MemoryContextSwitchTo(), PG_RETURN_NULL, ReturnSetInfo::returnMode, ReturnSetInfo::setDesc, ReturnSetInfo::setResult, SFRM_Materialize, SFRM_Materialize_Random, tuplestore_begin_heap(), TYPEFUNC_COMPOSITE, and work_mem.

2695 {
2696  Tuplestorestate *tuple_store;
2697  TupleDesc tupdesc;
2698  MemoryContext old_cxt;
2699  ReturnSetInfo *rsi;
2700 
2701  /*
2702  * We must use the Materialize mode to be safe against HBA file changes
2703  * while the cursor is open. It's also more efficient than having to look
2704  * up our current position in the parsed list every time.
2705  */
2706  rsi = (ReturnSetInfo *) fcinfo->resultinfo;
2707 
2708  /* Check to see if caller supports us returning a tuplestore */
2709  if (rsi == NULL || !IsA(rsi, ReturnSetInfo))
2710  ereport(ERROR,
2711  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2712  errmsg("set-valued function called in context that cannot accept a set")));
2713  if (!(rsi->allowedModes & SFRM_Materialize))
2714  ereport(ERROR,
2715  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2716  errmsg("materialize mode required, but it is not allowed in this context")));
2717 
2719 
2720  /* Build a tuple descriptor for our result type */
2721  if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
2722  elog(ERROR, "return type must be a row type");
2723 
2724  /* Build tuplestore to hold the result rows */
2726 
2727  tuple_store =
2729  false, work_mem);
2730  rsi->setDesc = tupdesc;
2731  rsi->setResult = tuple_store;
2732 
2733  MemoryContextSwitchTo(old_cxt);
2734 
2735  /* Fill the tuplestore */
2736  fill_hba_view(tuple_store, tupdesc);
2737 
2738  PG_RETURN_NULL();
2739 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:590
TypeFuncClass get_call_result_type(FunctionCallInfo fcinfo, Oid *resultTypeId, TupleDesc *resultTupleDesc)
Definition: funcapi.c:207
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
int errcode(int sqlerrcode)
Definition: elog.c:698
#define ERROR
Definition: elog.h:46
Tuplestorestate * tuplestore_begin_heap(bool randomAccess, bool interXact, int maxKBytes)
Definition: tuplestore.c:318
static void fill_hba_view(Tuplestorestate *tuple_store, TupleDesc tupdesc)
Definition: hba.c:2640
int work_mem
Definition: globals.c:124
#define ereport(elevel,...)
Definition: elog.h:157
int allowedModes
Definition: execnodes.h:305
SetFunctionReturnMode returnMode
Definition: execnodes.h:307
MemoryContext ecxt_per_query_memory
Definition: execnodes.h:233
Tuplestorestate * setResult
Definition: execnodes.h:310
ExprContext * econtext
Definition: execnodes.h:303
TupleDesc setDesc
Definition: execnodes.h:311
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define elog(elevel,...)
Definition: elog.h:232
#define PG_RETURN_NULL()
Definition: fmgr.h:345

◆ pg_isblank()

bool pg_isblank ( const char  c)

Definition at line 160 of file hba.c.

Referenced by interpret_ident_response(), and next_token().

161 {
162  return c == ' ' || c == '\t' || c == '\r';
163 }
char * c

◆ tokenize_file()

static MemoryContext tokenize_file ( const char *  filename,
FILE *  file,
List **  tok_lines,
int  elevel 
)
static

Definition at line 478 of file hba.c.

References ALLOCSET_SMALL_SIZES, AllocSetContextCreate, buf, CurrentMemoryContext, StringInfoData::data, ereport, TokenizedLine::err_msg, errcode_for_file_access(), errmsg(), TokenizedLine::fields, initStringInfo(), lappend(), StringInfoData::len, TokenizedLine::line_num, MemoryContextSwitchTo(), next_field_expand(), NIL, palloc(), pg_get_line_append(), pg_strip_crlf(), psprintf(), pstrdup(), TokenizedLine::raw_line, resetStringInfo(), and strerror.

Referenced by fill_hba_view(), load_hba(), load_ident(), and tokenize_inc_file().

479 {
480  int line_number = 1;
482  MemoryContext linecxt;
483  MemoryContext oldcxt;
484 
486  "tokenize_file",
488  oldcxt = MemoryContextSwitchTo(linecxt);
489 
490  initStringInfo(&buf);
491 
492  *tok_lines = NIL;
493 
494  while (!feof(file) && !ferror(file))
495  {
496  char *lineptr;
497  List *current_line = NIL;
498  char *err_msg = NULL;
499  int last_backslash_buflen = 0;
500  int continuations = 0;
501 
502  /* Collect the next input line, handling backslash continuations */
503  resetStringInfo(&buf);
504 
505  while (pg_get_line_append(file, &buf))
506  {
507  /* Strip trailing newline, including \r in case we're on Windows */
508  buf.len = pg_strip_crlf(buf.data);
509 
510  /*
511  * Check for backslash continuation. The backslash must be after
512  * the last place we found a continuation, else two backslashes
513  * followed by two \n's would behave surprisingly.
514  */
515  if (buf.len > last_backslash_buflen &&
516  buf.data[buf.len - 1] == '\\')
517  {
518  /* Continuation, so strip it and keep reading */
519  buf.data[--buf.len] = '\0';
520  last_backslash_buflen = buf.len;
521  continuations++;
522  continue;
523  }
524 
525  /* Nope, so we have the whole line */
526  break;
527  }
528 
529  if (ferror(file))
530  {
531  /* I/O error! */
532  int save_errno = errno;
533 
534  ereport(elevel,
536  errmsg("could not read file \"%s\": %m", filename)));
537  err_msg = psprintf("could not read file \"%s\": %s",
538  filename, strerror(save_errno));
539  break;
540  }
541 
542  /* Parse fields */
543  lineptr = buf.data;
544  while (*lineptr && err_msg == NULL)
545  {
546  List *current_field;
547 
548  current_field = next_field_expand(filename, &lineptr,
549  elevel, &err_msg);
550  /* add field to line, unless we are at EOL or comment start */
551  if (current_field != NIL)
552  current_line = lappend(current_line, current_field);
553  }
554 
555  /* Reached EOL; emit line to TokenizedLine list unless it's boring */
556  if (current_line != NIL || err_msg != NULL)
557  {
558  TokenizedLine *tok_line;
559 
560  tok_line = (TokenizedLine *) palloc(sizeof(TokenizedLine));
561  tok_line->fields = current_line;
562  tok_line->line_num = line_number;
563  tok_line->raw_line = pstrdup(buf.data);
564  tok_line->err_msg = err_msg;
565  *tok_lines = lappend(*tok_lines, tok_line);
566  }
567 
568  line_number += continuations + 1;
569  }
570 
571  MemoryContextSwitchTo(oldcxt);
572 
573  return linecxt;
574 }
#define NIL
Definition: pg_list.h:65
#define AllocSetContextCreate
Definition: memutils.h:173
int pg_strip_crlf(char *str)
Definition: string.c:121
char * pstrdup(const char *in)
Definition: mcxt.c:1299
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46
#define ALLOCSET_SMALL_SIZES
Definition: memutils.h:205
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
int line_num
Definition: hba.c:92
static char * buf
Definition: pg_test_fsync.c:68
char * err_msg
Definition: hba.c:94
int errcode_for_file_access(void)
Definition: elog.c:721
void resetStringInfo(StringInfo str)
Definition: stringinfo.c:75
MemoryContext CurrentMemoryContext
Definition: mcxt.c:42
List * fields
Definition: hba.c:91
List * lappend(List *list, void *datum)
Definition: list.c:336
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59
static int elevel
Definition: vacuumlazy.c:400
#define ereport(elevel,...)
Definition: elog.h:157
#define strerror
Definition: port.h:229
bool pg_get_line_append(FILE *stream, StringInfo buf)
Definition: pg_get_line.c:112
static char * filename
Definition: pg_dumpall.c:91
void * palloc(Size size)
Definition: mcxt.c:1062
int errmsg(const char *fmt,...)
Definition: elog.c:909
char * raw_line
Definition: hba.c:93
Definition: pg_list.h:50
static List * next_field_expand(const char *filename, char **lineptr, int elevel, char **err_msg)
Definition: hba.c:338

◆ tokenize_inc_file()

static List * tokenize_inc_file ( List tokens,
const char *  outer_filename,
const char *  inc_filename,
int  elevel,
char **  err_msg 
)
static

Definition at line 380 of file hba.c.

References AllocateFile(), canonicalize_path(), copy_hba_token(), ereport, TokenizedLine::err_msg, errcode_for_file_access(), errmsg(), TokenizedLine::fields, FreeFile(), get_parent_directory(), is_absolute_path, join_path_components(), lappend(), lfirst, MemoryContextDelete(), palloc(), pfree(), psprintf(), pstrdup(), strerror, and tokenize_file().

Referenced by next_field_expand().

385 {
386  char *inc_fullname;
387  FILE *inc_file;
388  List *inc_lines;
389  ListCell *inc_line;
390  MemoryContext linecxt;
391 
392  if (is_absolute_path(inc_filename))
393  {
394  /* absolute path is taken as-is */
395  inc_fullname = pstrdup(inc_filename);
396  }
397  else
398  {
399  /* relative path is relative to dir of calling file */
400  inc_fullname = (char *) palloc(strlen(outer_filename) + 1 +
401  strlen(inc_filename) + 1);
402  strcpy(inc_fullname, outer_filename);
403  get_parent_directory(inc_fullname);
404  join_path_components(inc_fullname, inc_fullname, inc_filename);
405  canonicalize_path(inc_fullname);
406  }
407 
408  inc_file = AllocateFile(inc_fullname, "r");
409  if (inc_file == NULL)
410  {
411  int save_errno = errno;
412 
413  ereport(elevel,
415  errmsg("could not open secondary authentication file \"@%s\" as \"%s\": %m",
416  inc_filename, inc_fullname)));
417  *err_msg = psprintf("could not open secondary authentication file \"@%s\" as \"%s\": %s",
418  inc_filename, inc_fullname, strerror(save_errno));
419  pfree(inc_fullname);
420  return tokens;
421  }
422 
423  /* There is possible recursion here if the file contains @ */
424  linecxt = tokenize_file(inc_fullname, inc_file, &inc_lines, elevel);
425 
426  FreeFile(inc_file);
427  pfree(inc_fullname);
428 
429  /* Copy all tokens found in the file and append to the tokens list */
430  foreach(inc_line, inc_lines)
431  {
432  TokenizedLine *tok_line = (TokenizedLine *) lfirst(inc_line);
433  ListCell *inc_field;
434 
435  /* If any line has an error, propagate that up to caller */
436  if (tok_line->err_msg)
437  {
438  *err_msg = pstrdup(tok_line->err_msg);
439  break;
440  }
441 
442  foreach(inc_field, tok_line->fields)
443  {
444  List *inc_tokens = lfirst(inc_field);
445  ListCell *inc_token;
446 
447  foreach(inc_token, inc_tokens)
448  {
449  HbaToken *token = lfirst(inc_token);
450 
451  tokens = lappend(tokens, copy_hba_token(token));
452  }
453  }
454  }
455 
456  MemoryContextDelete(linecxt);
457  return tokens;
458 }
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:218
char * pstrdup(const char *in)
Definition: mcxt.c:1299
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46
void canonicalize_path(char *path)
Definition: path.c:254
void pfree(void *pointer)
Definition: mcxt.c:1169
char * err_msg
Definition: hba.c:94
Definition: hba.c:75
int errcode_for_file_access(void)
Definition: elog.c:721
#define is_absolute_path(filename)
Definition: port.h:86
void get_parent_directory(char *path)
Definition: path.c:854
FILE * AllocateFile(const char *name, const char *mode)
Definition: fd.c:2373
List * fields
Definition: hba.c:91
List * lappend(List *list, void *datum)
Definition: list.c:336
static int elevel
Definition: vacuumlazy.c:400
#define ereport(elevel,...)
Definition: elog.h:157
#define lfirst(lc)
Definition: pg_list.h:169
#define strerror
Definition: port.h:229
static MemoryContext tokenize_file(const char *filename, FILE *file, List **tok_lines, int elevel)
Definition: hba.c:478
void join_path_components(char *ret_path, const char *head, const char *tail)
Definition: path.c:218
static HbaToken * copy_hba_token(HbaToken *in)
Definition: hba.c:315
int FreeFile(FILE *file)
Definition: fd.c:2572
void * palloc(Size size)
Definition: mcxt.c:1062
int errmsg(const char *fmt,...)
Definition: elog.c:909
Definition: pg_list.h:50

◆ verify_option_list_length()

static bool verify_option_list_length ( List options,
const char *  optionname,
List comparelist,
const char *  comparename,
int  line_num 
)
static

Definition at line 1666 of file hba.c.

References ereport, errcode(), errcontext, errmsg(), HbaFileName, list_length(), and LOG.

Referenced by parse_hba_line().

1669 {
1670  if (list_length(options) == 0 ||
1671  list_length(options) == 1 ||
1672  list_length(options) == list_length(comparelist))
1673  return true;
1674 
1675  ereport(LOG,
1676  (errcode(ERRCODE_CONFIG_FILE_ERROR),
1677  errmsg("the number of %s (%d) must be 1 or the same as the number of %s (%d)",
1678  optionname,
1679  list_length(options),
1680  comparename,
1681  list_length(comparelist)
1682  ),
1683  errcontext("line %d of configuration file \"%s\"",
1684  line_num, HbaFileName)));
1685  return false;
1686 }
int errcode(int sqlerrcode)
Definition: elog.c:698
#define LOG
Definition: elog.h:26
char * HbaFileName
Definition: guc.c:584
#define ereport(elevel,...)
Definition: elog.h:157
static int list_length(const List *l)
Definition: pg_list.h:149
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define errcontext
Definition: elog.h:204

Variable Documentation

◆ parsed_hba_context

MemoryContext parsed_hba_context = NULL
static

Definition at line 102 of file hba.c.

◆ parsed_hba_lines

List* parsed_hba_lines = NIL
static

Definition at line 101 of file hba.c.

◆ parsed_ident_context

MemoryContext parsed_ident_context = NULL
static

Definition at line 113 of file hba.c.

◆ parsed_ident_lines

List* parsed_ident_lines = NIL
static

Definition at line 112 of file hba.c.

◆ UserAuthName

const char* const UserAuthName[]
static
Initial value:
=
{
"reject",
"implicit reject",
"trust",
"ident",
"password",
"md5",
"scram-sha-256",
"gss",
"sspi",
"pam",
"bsd",
"ldap",
"cert",
"radius",
"peer"
}

Definition at line 121 of file hba.c.

Referenced by hba_authname().