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 <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include "catalog/pg_collation.h"
#include "common/ip.h"
#include "common/string.h"
#include "libpq/hba.h"
#include "libpq/ifaddr.h"
#include "libpq/libpq-be.h"
#include "postmaster/postmaster.h"
#include "regex/regex.h"
#include "replication/walsender.h"
#include "storage/fd.h"
#include "utils/acl.h"
#include "utils/conffiles.h"
#include "utils/guc.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  tokenize_error_callback_arg
 

Macros

#define token_has_regexp(t)   (t->regex != NULL)
 
#define token_is_member_check(t)   (!t->quoted && t->string[0] == '+')
 
#define token_is_keyword(t, k)   (!t->quoted && strcmp(t->string, k) == 0)
 
#define token_matches(t, k)   (strcmp(t->string, k) == 0)
 
#define token_matches_insensitive(t, k)   (pg_strcasecmp(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)
 

Typedefs

typedef struct check_network_data check_network_data
 

Functions

 StaticAssertDecl (lengthof(UserAuthName)==USER_AUTH_LAST+1, "UserAuthName[] must match the UserAuth enum")
 
static Listtokenize_expand_file (List *tokens, const char *outer_filename, const char *inc_filename, int elevel, int depth, char **err_msg)
 
static bool parse_hba_auth_opt (char *name, char *val, HbaLine *hbaline, int elevel, char **err_msg)
 
static int regcomp_auth_token (AuthToken *token, char *filename, int line_num, char **err_msg, int elevel)
 
static int regexec_auth_token (const char *match, AuthToken *token, size_t nmatch, regmatch_t pmatch[])
 
static void tokenize_error_callback (void *arg)
 
bool pg_isblank (const char c)
 
static bool next_token (char **lineptr, StringInfo buf, bool *initial_quote, bool *terminating_comma)
 
static AuthTokenmake_auth_token (const char *token, bool quoted)
 
static void free_auth_token (AuthToken *token)
 
static AuthTokencopy_auth_token (AuthToken *in)
 
static Listnext_field_expand (const char *filename, char **lineptr, int elevel, int depth, char **err_msg)
 
static void tokenize_include_file (const char *outer_filename, const char *inc_filename, List **tok_lines, int elevel, int depth, bool missing_ok, char **err_msg)
 
void free_auth_file (FILE *file, int depth)
 
FILE * open_auth_file (const char *filename, int elevel, int depth, char **err_msg)
 
void tokenize_auth_file (const char *filename, FILE *file, List **tok_lines, int elevel, int depth)
 
static bool is_member (Oid userid, const char *role)
 
static bool check_role (const char *role, Oid roleid, List *tokens, bool case_insensitive)
 
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 ipv6eq (struct sockaddr_in6 *a, struct sockaddr_in6 *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)
 
HbaLineparse_hba_line (TokenizedAuthLine *tok_line, int elevel)
 
static void check_hba (hbaPort *port)
 
bool load_hba (void)
 
IdentLineparse_ident_line (TokenizedAuthLine *tok_line, int elevel)
 
static void check_ident_usermap (IdentLine *identLine, const char *usermap_name, const char *pg_user, const char *system_user, bool case_insensitive, bool *found_p, bool *error_p)
 
int check_usermap (const char *usermap_name, const char *pg_user, const char *system_user, bool case_insensitive)
 
bool load_ident (void)
 
void hba_getauthmethod (hbaPort *port)
 
const char * hba_authname (UserAuth auth_method)
 

Variables

static MemoryContext tokenize_context = NULL
 
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(elevel, \
(errcode(ERRCODE_CONFIG_FILE_ERROR), \
errmsg("missing entry at end of line"), \
errcontext("line %d of configuration file \"%s\"", \
line_num, file_name))); \
*err_msg = pstrdup("missing entry at end of line"); \
return NULL; \
} \
} while (0)
int errcode(int sqlerrcode)
Definition: elog.c:859
int errmsg(const char *fmt,...)
Definition: elog.c:1072
#define errcontext
Definition: elog.h:196
char * pstrdup(const char *in)
Definition: mcxt.c:1695

Definition at line 1282 of file hba.c.

◆ IDENT_MULTI_VALUE

#define IDENT_MULTI_VALUE (   tokens)
Value:
do { \
if (tokens->length > 1) { \
ereport(elevel, \
(errcode(ERRCODE_CONFIG_FILE_ERROR), \
errmsg("multiple values in ident field"), \
errcontext("line %d of configuration file \"%s\"", \
line_num, file_name))); \
*err_msg = pstrdup("multiple values in ident field"); \
return NULL; \
} \
} while (0)

Definition at line 1295 of file hba.c.

◆ 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, file_name))); \
*err_msg = psprintf("authentication option \"%s\" is only valid for authentication methods %s", \
optname, validmethods); \
return false; \
} while (0)
#define _(x)
Definition: elog.c:90
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46

Definition at line 1238 of file hba.c.

◆ 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, file_name))); \
*err_msg = psprintf("authentication method \"%s\" requires argument \"%s\" to be set", \
authname, argname); \
return NULL; \
} \
} while (0)

Definition at line 1258 of file hba.c.

◆ 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 1252 of file hba.c.

◆ token_has_regexp

#define token_has_regexp (   t)    (t->regex != NULL)

Definition at line 68 of file hba.c.

◆ token_is_keyword

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

Definition at line 70 of file hba.c.

◆ token_is_member_check

#define token_is_member_check (   t)    (!t->quoted && t->string[0] == '+')

Definition at line 69 of file hba.c.

◆ token_matches

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

Definition at line 71 of file hba.c.

◆ token_matches_insensitive

#define token_matches_insensitive (   t,
 
)    (pg_strcasecmp(t->string, k) == 0)

Definition at line 72 of file hba.c.

Typedef Documentation

◆ check_network_data

Function Documentation

◆ check_db()

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

Definition at line 987 of file hba.c.

988 {
989  ListCell *cell;
990  AuthToken *tok;
991 
992  foreach(cell, tokens)
993  {
994  tok = lfirst(cell);
996  {
997  /*
998  * physical replication walsender connections can only match
999  * replication keyword
1000  */
1001  if (token_is_keyword(tok, "replication"))
1002  return true;
1003  }
1004  else if (token_is_keyword(tok, "all"))
1005  return true;
1006  else if (token_is_keyword(tok, "sameuser"))
1007  {
1008  if (strcmp(dbname, role) == 0)
1009  return true;
1010  }
1011  else if (token_is_keyword(tok, "samegroup") ||
1012  token_is_keyword(tok, "samerole"))
1013  {
1014  if (is_member(roleid, dbname))
1015  return true;
1016  }
1017  else if (token_is_keyword(tok, "replication"))
1018  continue; /* never match this if not walsender */
1019  else if (token_has_regexp(tok))
1020  {
1021  if (regexec_auth_token(dbname, tok, 0, NULL) == REG_OKAY)
1022  return true;
1023  }
1024  else if (token_matches(tok, dbname))
1025  return true;
1026  }
1027  return false;
1028 }
static bool is_member(Oid userid, const char *role)
Definition: hba.c:919
#define token_is_keyword(t, k)
Definition: hba.c:70
static int regexec_auth_token(const char *match, AuthToken *token, size_t nmatch, regmatch_t pmatch[])
Definition: hba.c:346
#define token_has_regexp(t)
Definition: hba.c:68
#define token_matches(t, k)
Definition: hba.c:71
#define lfirst(lc)
Definition: pg_list.h:172
#define REG_OKAY
Definition: regex.h:137
char * dbname
Definition: streamutil.c:52
Definition: hba.h:88
bool am_walsender
Definition: walsender.c:115
bool am_db_walsender
Definition: walsender.c:118

References am_db_walsender, am_walsender, dbname, is_member(), lfirst, REG_OKAY, regexec_auth_token(), token_has_regexp, token_is_keyword, and token_matches.

Referenced by check_hba().

◆ check_hba()

static void check_hba ( hbaPort port)
static

Definition at line 2469 of file hba.c.

2470 {
2471  Oid roleid;
2472  ListCell *line;
2473  HbaLine *hba;
2474 
2475  /* Get the target role's OID. Note we do not error out for bad role. */
2476  roleid = get_role_oid(port->user_name, true);
2477 
2478  foreach(line, parsed_hba_lines)
2479  {
2480  hba = (HbaLine *) lfirst(line);
2481 
2482  /* Check connection type */
2483  if (hba->conntype == ctLocal)
2484  {
2485  if (port->raddr.addr.ss_family != AF_UNIX)
2486  continue;
2487  }
2488  else
2489  {
2490  if (port->raddr.addr.ss_family == AF_UNIX)
2491  continue;
2492 
2493  /* Check SSL state */
2494  if (port->ssl_in_use)
2495  {
2496  /* Connection is SSL, match both "host" and "hostssl" */
2497  if (hba->conntype == ctHostNoSSL)
2498  continue;
2499  }
2500  else
2501  {
2502  /* Connection is not SSL, match both "host" and "hostnossl" */
2503  if (hba->conntype == ctHostSSL)
2504  continue;
2505  }
2506 
2507  /* Check GSSAPI state */
2508 #ifdef ENABLE_GSS
2509  if (port->gss && port->gss->enc &&
2510  hba->conntype == ctHostNoGSS)
2511  continue;
2512  else if (!(port->gss && port->gss->enc) &&
2513  hba->conntype == ctHostGSS)
2514  continue;
2515 #else
2516  if (hba->conntype == ctHostGSS)
2517  continue;
2518 #endif
2519 
2520  /* Check IP address */
2521  switch (hba->ip_cmp_method)
2522  {
2523  case ipCmpMask:
2524  if (hba->hostname)
2525  {
2526  if (!check_hostname(port,
2527  hba->hostname))
2528  continue;
2529  }
2530  else
2531  {
2532  if (!check_ip(&port->raddr,
2533  (struct sockaddr *) &hba->addr,
2534  (struct sockaddr *) &hba->mask))
2535  continue;
2536  }
2537  break;
2538  case ipCmpAll:
2539  break;
2540  case ipCmpSameHost:
2541  case ipCmpSameNet:
2542  if (!check_same_host_or_net(&port->raddr,
2543  hba->ip_cmp_method))
2544  continue;
2545  break;
2546  default:
2547  /* shouldn't get here, but deem it no-match if so */
2548  continue;
2549  }
2550  } /* != ctLocal */
2551 
2552  /* Check database and role */
2553  if (!check_db(port->database_name, port->user_name, roleid,
2554  hba->databases))
2555  continue;
2556 
2557  if (!check_role(port->user_name, roleid, hba->roles, false))
2558  continue;
2559 
2560  /* Found a record that matched! */
2561  port->hba = hba;
2562  return;
2563  }
2564 
2565  /* If no matching entry was found, then implicitly reject. */
2566  hba = palloc0(sizeof(HbaLine));
2568  port->hba = hba;
2569 }
Oid get_role_oid(const char *rolname, bool missing_ok)
Definition: acl.c:5414
static bool check_role(const char *role, Oid roleid, List *tokens, bool case_insensitive)
Definition: hba.c:948
static bool check_ip(SockAddr *raddr, struct sockaddr *addr, struct sockaddr *mask)
Definition: hba.c:1163
static bool check_same_host_or_net(SockAddr *raddr, IPCompareMethod method)
Definition: hba.c:1204
static bool check_hostname(hbaPort *port, const char *hostname)
Definition: hba.c:1072
static List * parsed_hba_lines
Definition: hba.c:85
static bool check_db(const char *dbname, const char *role, Oid roleid, List *tokens)
Definition: hba.c:987
@ ipCmpAll
Definition: hba.h:54
@ ipCmpSameNet
Definition: hba.h:53
@ ipCmpMask
Definition: hba.h:51
@ ipCmpSameHost
Definition: hba.h:52
@ ctHostNoGSS
Definition: hba.h:64
@ ctHostSSL
Definition: hba.h:61
@ ctHostNoSSL
Definition: hba.h:62
@ ctHostGSS
Definition: hba.h:63
@ ctLocal
Definition: hba.h:59
@ uaImplicitReject
Definition: hba.h:28
void * palloc0(Size size)
Definition: mcxt.c:1346
static int port
Definition: pg_regress.c:116
unsigned int Oid
Definition: postgres_ext.h:31
Definition: hba.h:95
UserAuth auth_method
Definition: hba.h:108
struct sockaddr_storage mask
Definition: hba.h:104
char * hostname
Definition: hba.h:107
List * databases
Definition: hba.h:100
ConnType conntype
Definition: hba.h:99
struct sockaddr_storage addr
Definition: hba.h:102
List * roles
Definition: hba.h:101
IPCompareMethod ip_cmp_method
Definition: hba.h:106

References 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, HbaLine::databases, get_role_oid(), HbaLine::hostname, HbaLine::ip_cmp_method, ipCmpAll, ipCmpMask, ipCmpSameHost, ipCmpSameNet, lfirst, HbaLine::mask, palloc0(), parsed_hba_lines, port, HbaLine::roles, and uaImplicitReject.

Referenced by hba_getauthmethod().

◆ check_hostname()

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

Definition at line 1072 of file hba.c.

1073 {
1074  struct addrinfo *gai_result,
1075  *gai;
1076  int ret;
1077  bool found;
1078 
1079  /* Quick out if remote host name already known bad */
1080  if (port->remote_hostname_resolv < 0)
1081  return false;
1082 
1083  /* Lookup remote host name if not already done */
1084  if (!port->remote_hostname)
1085  {
1086  char remote_hostname[NI_MAXHOST];
1087 
1088  ret = pg_getnameinfo_all(&port->raddr.addr, port->raddr.salen,
1089  remote_hostname, sizeof(remote_hostname),
1090  NULL, 0,
1091  NI_NAMEREQD);
1092  if (ret != 0)
1093  {
1094  /* remember failure; don't complain in the postmaster log yet */
1095  port->remote_hostname_resolv = -2;
1096  port->remote_hostname_errcode = ret;
1097  return false;
1098  }
1099 
1100  port->remote_hostname = pstrdup(remote_hostname);
1101  }
1102 
1103  /* Now see if remote host name matches this pg_hba line */
1104  if (!hostname_match(hostname, port->remote_hostname))
1105  return false;
1106 
1107  /* If we already verified the forward lookup, we're done */
1108  if (port->remote_hostname_resolv == +1)
1109  return true;
1110 
1111  /* Lookup IP from host name and check against original IP */
1112  ret = getaddrinfo(port->remote_hostname, NULL, NULL, &gai_result);
1113  if (ret != 0)
1114  {
1115  /* remember failure; don't complain in the postmaster log yet */
1116  port->remote_hostname_resolv = -2;
1117  port->remote_hostname_errcode = ret;
1118  return false;
1119  }
1120 
1121  found = false;
1122  for (gai = gai_result; gai; gai = gai->ai_next)
1123  {
1124  if (gai->ai_addr->sa_family == port->raddr.addr.ss_family)
1125  {
1126  if (gai->ai_addr->sa_family == AF_INET)
1127  {
1128  if (ipv4eq((struct sockaddr_in *) gai->ai_addr,
1129  (struct sockaddr_in *) &port->raddr.addr))
1130  {
1131  found = true;
1132  break;
1133  }
1134  }
1135  else if (gai->ai_addr->sa_family == AF_INET6)
1136  {
1137  if (ipv6eq((struct sockaddr_in6 *) gai->ai_addr,
1138  (struct sockaddr_in6 *) &port->raddr.addr))
1139  {
1140  found = true;
1141  break;
1142  }
1143  }
1144  }
1145  }
1146 
1147  if (gai_result)
1148  freeaddrinfo(gai_result);
1149 
1150  if (!found)
1151  elog(DEBUG2, "pg_hba.conf host name \"%s\" rejected because address resolution did not return a match with IP address of client",
1152  hostname);
1153 
1154  port->remote_hostname_resolv = found ? +1 : -1;
1155 
1156  return found;
1157 }
#define DEBUG2
Definition: elog.h:29
#define elog(elevel,...)
Definition: elog.h:224
static bool hostname_match(const char *pattern, const char *actual_hostname)
Definition: hba.c:1052
static bool ipv4eq(struct sockaddr_in *a, struct sockaddr_in *b)
Definition: hba.c:1031
static bool ipv6eq(struct sockaddr_in6 *a, struct sockaddr_in6 *b)
Definition: hba.c:1037
int pg_getnameinfo_all(const struct sockaddr_storage *addr, int salen, char *node, int nodelen, char *service, int servicelen, int flags)
Definition: ip.c:114
static char * hostname
Definition: pg_regress.c:115

References DEBUG2, elog, hostname, hostname_match(), ipv4eq(), ipv6eq(), pg_getnameinfo_all(), port, and pstrdup().

Referenced by check_hba().

◆ check_ident_usermap()

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

Definition at line 2757 of file hba.c.

2760 {
2761  Oid roleid;
2762 
2763  *found_p = false;
2764  *error_p = false;
2765 
2766  if (strcmp(identLine->usermap, usermap_name) != 0)
2767  /* Line does not match the map name we're looking for, so just abort */
2768  return;
2769 
2770  /* Get the target role's OID. Note we do not error out for bad role. */
2771  roleid = get_role_oid(pg_user, true);
2772 
2773  /* Match? */
2774  if (token_has_regexp(identLine->system_user))
2775  {
2776  /*
2777  * Process the system username as a regular expression that returns
2778  * exactly one match. This is replaced for \1 in the database username
2779  * string, if present.
2780  */
2781  int r;
2782  regmatch_t matches[2];
2783  char *ofs;
2784  AuthToken *expanded_pg_user_token;
2785  bool created_temporary_token = false;
2786 
2787  r = regexec_auth_token(system_user, identLine->system_user, 2, matches);
2788  if (r)
2789  {
2790  char errstr[100];
2791 
2792  if (r != REG_NOMATCH)
2793  {
2794  /* REG_NOMATCH is not an error, everything else is */
2795  pg_regerror(r, identLine->system_user->regex, errstr, sizeof(errstr));
2796  ereport(LOG,
2797  (errcode(ERRCODE_INVALID_REGULAR_EXPRESSION),
2798  errmsg("regular expression match for \"%s\" failed: %s",
2799  identLine->system_user->string + 1, errstr)));
2800  *error_p = true;
2801  }
2802  return;
2803  }
2804 
2805  /*
2806  * Replace \1 with the first captured group unless the field already
2807  * has some special meaning, like a group membership or a regexp-based
2808  * check.
2809  */
2810  if (!token_is_member_check(identLine->pg_user) &&
2811  !token_has_regexp(identLine->pg_user) &&
2812  (ofs = strstr(identLine->pg_user->string, "\\1")) != NULL)
2813  {
2814  char *expanded_pg_user;
2815  int offset;
2816 
2817  /* substitution of the first argument requested */
2818  if (matches[1].rm_so < 0)
2819  {
2820  ereport(LOG,
2821  (errcode(ERRCODE_INVALID_REGULAR_EXPRESSION),
2822  errmsg("regular expression \"%s\" has no subexpressions as requested by backreference in \"%s\"",
2823  identLine->system_user->string + 1, identLine->pg_user->string)));
2824  *error_p = true;
2825  return;
2826  }
2827 
2828  /*
2829  * length: original length minus length of \1 plus length of match
2830  * plus null terminator
2831  */
2832  expanded_pg_user = palloc0(strlen(identLine->pg_user->string) - 2 + (matches[1].rm_eo - matches[1].rm_so) + 1);
2833  offset = ofs - identLine->pg_user->string;
2834  memcpy(expanded_pg_user, identLine->pg_user->string, offset);
2835  memcpy(expanded_pg_user + offset,
2836  system_user + matches[1].rm_so,
2837  matches[1].rm_eo - matches[1].rm_so);
2838  strcat(expanded_pg_user, ofs + 2);
2839 
2840  /*
2841  * Mark the token as quoted, so it will only be compared literally
2842  * and not for some special meaning, such as "all" or a group
2843  * membership check.
2844  */
2845  expanded_pg_user_token = make_auth_token(expanded_pg_user, true);
2846  created_temporary_token = true;
2847  pfree(expanded_pg_user);
2848  }
2849  else
2850  {
2851  expanded_pg_user_token = identLine->pg_user;
2852  }
2853 
2854  /* check the Postgres user */
2855  *found_p = check_role(pg_user, roleid,
2856  list_make1(expanded_pg_user_token),
2857  case_insensitive);
2858 
2859  if (created_temporary_token)
2860  free_auth_token(expanded_pg_user_token);
2861 
2862  return;
2863  }
2864  else
2865  {
2866  /*
2867  * Not a regular expression, so make a complete match. If the system
2868  * user does not match, just leave.
2869  */
2870  if (case_insensitive)
2871  {
2872  if (!token_matches_insensitive(identLine->system_user,
2873  system_user))
2874  return;
2875  }
2876  else
2877  {
2878  if (!token_matches(identLine->system_user, system_user))
2879  return;
2880  }
2881 
2882  /* check the Postgres user */
2883  *found_p = check_role(pg_user, roleid,
2884  list_make1(identLine->pg_user),
2885  case_insensitive);
2886  }
2887 }
#define LOG
Definition: elog.h:31
#define ereport(elevel,...)
Definition: elog.h:149
#define token_is_member_check(t)
Definition: hba.c:69
#define token_matches_insensitive(t, k)
Definition: hba.c:72
static void free_auth_token(AuthToken *token)
Definition: hba.c:278
static AuthToken * make_auth_token(const char *token, bool quoted)
Definition: hba.c:257
void pfree(void *pointer)
Definition: mcxt.c:1520
Datum system_user(PG_FUNCTION_ARGS)
Definition: miscinit.c:891
#define list_make1(x1)
Definition: pg_list.h:212
size_t pg_regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size)
Definition: regerror.c:60
#define REG_NOMATCH
Definition: regex.h:138
regex_t * regex
Definition: hba.h:91
char * string
Definition: hba.h:89
AuthToken * pg_user
Definition: hba.h:146
AuthToken * system_user
Definition: hba.h:145
char * usermap
Definition: hba.h:144

References check_role(), ereport, errcode(), errmsg(), free_auth_token(), get_role_oid(), list_make1, LOG, make_auth_token(), palloc0(), pfree(), pg_regerror(), IdentLine::pg_user, REG_NOMATCH, AuthToken::regex, regexec_auth_token(), regmatch_t::rm_eo, regmatch_t::rm_so, AuthToken::string, system_user(), IdentLine::system_user, token_has_regexp, token_is_member_check, token_matches, token_matches_insensitive, and IdentLine::usermap.

Referenced by check_usermap().

◆ check_ip()

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

Definition at line 1163 of file hba.c.

1164 {
1165  if (raddr->addr.ss_family == addr->sa_family &&
1166  pg_range_sockaddr(&raddr->addr,
1167  (struct sockaddr_storage *) addr,
1168  (struct sockaddr_storage *) mask))
1169  return true;
1170  return false;
1171 }
int pg_range_sockaddr(const struct sockaddr_storage *addr, const struct sockaddr_storage *netaddr, const struct sockaddr_storage *netmask)
Definition: ifaddr.c:49
struct sockaddr_storage addr
Definition: pqcomm.h:32

References SockAddr::addr, and pg_range_sockaddr().

Referenced by check_hba(), and check_network_callback().

◆ check_network_callback()

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

Definition at line 1177 of file hba.c.

1179 {
1180  check_network_data *cn = (check_network_data *) cb_data;
1181  struct sockaddr_storage mask;
1182 
1183  /* Already found a match? */
1184  if (cn->result)
1185  return;
1186 
1187  if (cn->method == ipCmpSameHost)
1188  {
1189  /* Make an all-ones netmask of appropriate length for family */
1190  pg_sockaddr_cidr_mask(&mask, NULL, addr->sa_family);
1191  cn->result = check_ip(cn->raddr, addr, (struct sockaddr *) &mask);
1192  }
1193  else
1194  {
1195  /* Use the netmask of the interface itself */
1196  cn->result = check_ip(cn->raddr, addr, netmask);
1197  }
1198 }
int pg_sockaddr_cidr_mask(struct sockaddr_storage *mask, char *numbits, int family)
Definition: ifaddr.c:105
bool result
Definition: hba.c:59
SockAddr * raddr
Definition: hba.c:58
IPCompareMethod method
Definition: hba.c:57

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().

◆ check_role()

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

Definition at line 948 of file hba.c.

949 {
950  ListCell *cell;
951  AuthToken *tok;
952 
953  foreach(cell, tokens)
954  {
955  tok = lfirst(cell);
956  if (token_is_member_check(tok))
957  {
958  if (is_member(roleid, tok->string + 1))
959  return true;
960  }
961  else if (token_is_keyword(tok, "all"))
962  return true;
963  else if (token_has_regexp(tok))
964  {
965  if (regexec_auth_token(role, tok, 0, NULL) == REG_OKAY)
966  return true;
967  }
968  else if (case_insensitive)
969  {
970  if (token_matches_insensitive(tok, role))
971  return true;
972  }
973  else if (token_matches(tok, role))
974  return true;
975  }
976  return false;
977 }

References is_member(), lfirst, REG_OKAY, regexec_auth_token(), AuthToken::string, token_has_regexp, token_is_keyword, token_is_member_check, token_matches, and token_matches_insensitive.

Referenced by check_hba(), and check_ident_usermap().

◆ check_same_host_or_net()

static bool check_same_host_or_net ( SockAddr raddr,
IPCompareMethod  method 
)
static

Definition at line 1204 of file hba.c.

1205 {
1206  check_network_data cn;
1207 
1208  cn.method = method;
1209  cn.raddr = raddr;
1210  cn.result = false;
1211 
1212  errno = 0;
1214  {
1215  ereport(LOG,
1216  (errmsg("error enumerating network interfaces: %m")));
1217  return false;
1218  }
1219 
1220  return cn.result;
1221 }
static void check_network_callback(struct sockaddr *addr, struct sockaddr *netmask, void *cb_data)
Definition: hba.c:1177
int pg_foreach_ifaddr(PgIfAddrCallback callback, void *cb_data)
Definition: ifaddr.c:425

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().

◆ check_usermap()

int check_usermap ( const char *  usermap_name,
const char *  pg_user,
const char *  system_user,
bool  case_insensitive 
)

Definition at line 2904 of file hba.c.

2908 {
2909  bool found_entry = false,
2910  error = false;
2911 
2912  if (usermap_name == NULL || usermap_name[0] == '\0')
2913  {
2914  if (case_insensitive)
2915  {
2916  if (pg_strcasecmp(pg_user, system_user) == 0)
2917  return STATUS_OK;
2918  }
2919  else
2920  {
2921  if (strcmp(pg_user, system_user) == 0)
2922  return STATUS_OK;
2923  }
2924  ereport(LOG,
2925  (errmsg("provided user name (%s) and authenticated user name (%s) do not match",
2926  pg_user, system_user)));
2927  return STATUS_ERROR;
2928  }
2929  else
2930  {
2931  ListCell *line_cell;
2932 
2933  foreach(line_cell, parsed_ident_lines)
2934  {
2935  check_ident_usermap(lfirst(line_cell), usermap_name,
2936  pg_user, system_user, case_insensitive,
2937  &found_entry, &error);
2938  if (found_entry || error)
2939  break;
2940  }
2941  }
2942  if (!found_entry && !error)
2943  {
2944  ereport(LOG,
2945  (errmsg("no match in usermap \"%s\" for user \"%s\" authenticated as \"%s\"",
2946  usermap_name, pg_user, system_user)));
2947  }
2948  return found_entry ? STATUS_OK : STATUS_ERROR;
2949 }
#define STATUS_OK
Definition: c.h:1169
#define STATUS_ERROR
Definition: c.h:1170
static List * parsed_ident_lines
Definition: hba.c:92
static void check_ident_usermap(IdentLine *identLine, const char *usermap_name, const char *pg_user, const char *system_user, bool case_insensitive, bool *found_p, bool *error_p)
Definition: hba.c:2757
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:36
static void error(void)
Definition: sql-dyntest.c:147

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

Referenced by auth_peer(), and ident_inet().

◆ copy_auth_token()

static AuthToken* copy_auth_token ( AuthToken in)
static

Definition at line 288 of file hba.c.

289 {
290  AuthToken *out = make_auth_token(in->string, in->quoted);
291 
292  return out;
293 }
bool quoted
Definition: hba.h:90

References make_auth_token(), AuthToken::quoted, and AuthToken::string.

Referenced by parse_hba_line(), and parse_ident_line().

◆ free_auth_file()

void free_auth_file ( FILE *  file,
int  depth 
)

Definition at line 570 of file hba.c.

571 {
572  FreeFile(file);
573 
574  /* If this is the last cleanup, remove the tokenization context */
575  if (depth == CONF_FILE_START_DEPTH)
576  {
578  tokenize_context = NULL;
579  }
580 }
#define CONF_FILE_START_DEPTH
Definition: conffiles.h:17
int FreeFile(FILE *file)
Definition: fd.c:2781
static MemoryContext tokenize_context
Definition: hba.c:79
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:454

References CONF_FILE_START_DEPTH, FreeFile(), MemoryContextDelete(), and tokenize_context.

Referenced by fill_hba_view(), fill_ident_view(), load_hba(), load_ident(), tokenize_expand_file(), and tokenize_include_file().

◆ free_auth_token()

static void free_auth_token ( AuthToken token)
static

Definition at line 278 of file hba.c.

279 {
280  if (token_has_regexp(token))
281  pg_regfree(token->regex);
282 }
#define token
Definition: indent_globs.h:126
void pg_regfree(regex_t *re)
Definition: regfree.c:49

References pg_regfree(), token, and token_has_regexp.

Referenced by check_ident_usermap().

◆ hba_authname()

const char* hba_authname ( UserAuth  auth_method)

Definition at line 3061 of file hba.c.

3062 {
3063  return UserAuthName[auth_method];
3064 }
static const char *const UserAuthName[]
Definition: hba.c:101

References UserAuthName.

Referenced by ClientAuthentication(), fill_hba_line(), InitPostgres(), ParallelWorkerMain(), and set_authn_id().

◆ hba_getauthmethod()

void hba_getauthmethod ( hbaPort port)

Definition at line 3048 of file hba.c.

3049 {
3050  check_hba(port);
3051 }
static void check_hba(hbaPort *port)
Definition: hba.c:2469

References check_hba(), and port.

Referenced by ClientAuthentication().

◆ hostname_match()

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

Definition at line 1052 of file hba.c.

1053 {
1054  if (pattern[0] == '.') /* suffix match */
1055  {
1056  size_t plen = strlen(pattern);
1057  size_t hlen = strlen(actual_hostname);
1058 
1059  if (hlen < plen)
1060  return false;
1061 
1062  return (pg_strcasecmp(pattern, actual_hostname + (hlen - plen)) == 0);
1063  }
1064  else
1065  return (pg_strcasecmp(pattern, actual_hostname) == 0);
1066 }

References pg_strcasecmp().

Referenced by check_hostname().

◆ ipv4eq()

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

Definition at line 1031 of file hba.c.

1032 {
1033  return (a->sin_addr.s_addr == b->sin_addr.s_addr);
1034 }
int b
Definition: isn.c:70
int a
Definition: isn.c:69

References a, and b.

Referenced by check_hostname().

◆ ipv6eq()

static bool ipv6eq ( struct sockaddr_in6 *  a,
struct sockaddr_in6 *  b 
)
static

Definition at line 1037 of file hba.c.

1038 {
1039  int i;
1040 
1041  for (i = 0; i < 16; i++)
1042  if (a->sin6_addr.s6_addr[i] != b->sin6_addr.s6_addr[i])
1043  return false;
1044 
1045  return true;
1046 }
int i
Definition: isn.c:73

References a, b, and i.

Referenced by check_hostname().

◆ is_member()

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

Definition at line 919 of file hba.c.

920 {
921  Oid roleid;
922 
923  if (!OidIsValid(userid))
924  return false; /* if user not exist, say "no" */
925 
926  roleid = get_role_oid(role, true);
927 
928  if (!OidIsValid(roleid))
929  return false; /* if target role not exist, say "no" */
930 
931  /*
932  * See if user is directly or indirectly a member of role. For this
933  * purpose, a superuser is not considered to be automatically a member of
934  * the role, so group auth only applies to explicit membership.
935  */
936  return is_member_of_role_nosuper(userid, roleid);
937 }
bool is_member_of_role_nosuper(Oid member, Oid role)
Definition: acl.c:5236
#define OidIsValid(objectId)
Definition: c.h:775

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

Referenced by check_db(), and check_role().

◆ load_hba()

bool load_hba ( void  )

Definition at line 2583 of file hba.c.

2584 {
2585  FILE *file;
2586  List *hba_lines = NIL;
2587  ListCell *line;
2588  List *new_parsed_lines = NIL;
2589  bool ok = true;
2590  MemoryContext oldcxt;
2591  MemoryContext hbacxt;
2592 
2593  file = open_auth_file(HbaFileName, LOG, 0, NULL);
2594  if (file == NULL)
2595  {
2596  /* error already logged */
2597  return false;
2598  }
2599 
2600  tokenize_auth_file(HbaFileName, file, &hba_lines, LOG, 0);
2601 
2602  /* Now parse all the lines */
2605  "hba parser context",
2607  oldcxt = MemoryContextSwitchTo(hbacxt);
2608  foreach(line, hba_lines)
2609  {
2610  TokenizedAuthLine *tok_line = (TokenizedAuthLine *) lfirst(line);
2611  HbaLine *newline;
2612 
2613  /* don't parse lines that already have errors */
2614  if (tok_line->err_msg != NULL)
2615  {
2616  ok = false;
2617  continue;
2618  }
2619 
2620  if ((newline = parse_hba_line(tok_line, LOG)) == NULL)
2621  {
2622  /* Parse error; remember there's trouble */
2623  ok = false;
2624 
2625  /*
2626  * Keep parsing the rest of the file so we can report errors on
2627  * more than the first line. Error has already been logged, no
2628  * need for more chatter here.
2629  */
2630  continue;
2631  }
2632 
2633  new_parsed_lines = lappend(new_parsed_lines, newline);
2634  }
2635 
2636  /*
2637  * A valid HBA file must have at least one entry; else there's no way to
2638  * connect to the postmaster. But only complain about this if we didn't
2639  * already have parsing errors.
2640  */
2641  if (ok && new_parsed_lines == NIL)
2642  {
2643  ereport(LOG,
2644  (errcode(ERRCODE_CONFIG_FILE_ERROR),
2645  errmsg("configuration file \"%s\" contains no entries",
2646  HbaFileName)));
2647  ok = false;
2648  }
2649 
2650  /* Free tokenizer memory */
2651  free_auth_file(file, 0);
2652  MemoryContextSwitchTo(oldcxt);
2653 
2654  if (!ok)
2655  {
2656  /*
2657  * File contained one or more errors, so bail out. MemoryContextDelete
2658  * is enough to clean up everything, including regexes.
2659  */
2660  MemoryContextDelete(hbacxt);
2661  return false;
2662  }
2663 
2664  /* Loaded new file successfully, replace the one we use */
2665  if (parsed_hba_context != NULL)
2667  parsed_hba_context = hbacxt;
2668  parsed_hba_lines = new_parsed_lines;
2669 
2670  return true;
2671 }
#define Assert(condition)
Definition: c.h:858
char * HbaFileName
Definition: guc_tables.c:542
FILE * open_auth_file(const char *filename, int elevel, int depth, char **err_msg)
Definition: hba.c:595
static MemoryContext parsed_hba_context
Definition: hba.c:86
void free_auth_file(FILE *file, int depth)
Definition: hba.c:570
HbaLine * parse_hba_line(TokenizedAuthLine *tok_line, int elevel)
Definition: hba.c:1322
void tokenize_auth_file(const char *filename, FILE *file, List **tok_lines, int elevel, int depth)
Definition: hba.c:686
#define newline
Definition: indent_codes.h:35
List * lappend(List *list, void *datum)
Definition: list.c:339
MemoryContext PostmasterContext
Definition: mcxt.c:151
#define AllocSetContextCreate
Definition: memutils.h:129
#define ALLOCSET_SMALL_SIZES
Definition: memutils.h:170
#define NIL
Definition: pg_list.h:68
MemoryContextSwitchTo(old_ctx)
Definition: pg_list.h:54
char * err_msg
Definition: hba.h:164

References ALLOCSET_SMALL_SIZES, AllocSetContextCreate, Assert, ereport, TokenizedAuthLine::err_msg, errcode(), errmsg(), free_auth_file(), HbaFileName, lappend(), lfirst, LOG, MemoryContextDelete(), MemoryContextSwitchTo(), newline, NIL, open_auth_file(), parse_hba_line(), parsed_hba_context, parsed_hba_lines, PostmasterContext, and tokenize_auth_file().

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

◆ load_ident()

bool load_ident ( void  )

Definition at line 2959 of file hba.c.

2960 {
2961  FILE *file;
2962  List *ident_lines = NIL;
2963  ListCell *line_cell;
2964  List *new_parsed_lines = NIL;
2965  bool ok = true;
2966  MemoryContext oldcxt;
2967  MemoryContext ident_context;
2968  IdentLine *newline;
2969 
2970  /* not FATAL ... we just won't do any special ident maps */
2971  file = open_auth_file(IdentFileName, LOG, 0, NULL);
2972  if (file == NULL)
2973  {
2974  /* error already logged */
2975  return false;
2976  }
2977 
2978  tokenize_auth_file(IdentFileName, file, &ident_lines, LOG, 0);
2979 
2980  /* Now parse all the lines */
2982  ident_context = AllocSetContextCreate(PostmasterContext,
2983  "ident parser context",
2985  oldcxt = MemoryContextSwitchTo(ident_context);
2986  foreach(line_cell, ident_lines)
2987  {
2988  TokenizedAuthLine *tok_line = (TokenizedAuthLine *) lfirst(line_cell);
2989 
2990  /* don't parse lines that already have errors */
2991  if (tok_line->err_msg != NULL)
2992  {
2993  ok = false;
2994  continue;
2995  }
2996 
2997  if ((newline = parse_ident_line(tok_line, LOG)) == NULL)
2998  {
2999  /* Parse error; remember there's trouble */
3000  ok = false;
3001 
3002  /*
3003  * Keep parsing the rest of the file so we can report errors on
3004  * more than the first line. Error has already been logged, no
3005  * need for more chatter here.
3006  */
3007  continue;
3008  }
3009 
3010  new_parsed_lines = lappend(new_parsed_lines, newline);
3011  }
3012 
3013  /* Free tokenizer memory */
3014  free_auth_file(file, 0);
3015  MemoryContextSwitchTo(oldcxt);
3016 
3017  if (!ok)
3018  {
3019  /*
3020  * File contained one or more errors, so bail out. MemoryContextDelete
3021  * is enough to clean up everything, including regexes.
3022  */
3023  MemoryContextDelete(ident_context);
3024  return false;
3025  }
3026 
3027  /* Loaded new file successfully, replace the one we use */
3028  if (parsed_ident_context != NULL)
3030 
3031  parsed_ident_context = ident_context;
3032  parsed_ident_lines = new_parsed_lines;
3033 
3034  return true;
3035 }
char * IdentFileName
Definition: guc_tables.c:543
IdentLine * parse_ident_line(TokenizedAuthLine *tok_line, int elevel)
Definition: hba.c:2689
static MemoryContext parsed_ident_context
Definition: hba.c:93
Definition: hba.h:141

References ALLOCSET_SMALL_SIZES, AllocSetContextCreate, Assert, TokenizedAuthLine::err_msg, free_auth_file(), IdentFileName, lappend(), lfirst, LOG, MemoryContextDelete(), MemoryContextSwitchTo(), newline, NIL, open_auth_file(), parse_ident_line(), parsed_ident_context, parsed_ident_lines, PostmasterContext, and tokenize_auth_file().

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

◆ make_auth_token()

static AuthToken* make_auth_token ( const char *  token,
bool  quoted 
)
static

Definition at line 257 of file hba.c.

258 {
259  AuthToken *authtoken;
260  int toklen;
261 
262  toklen = strlen(token);
263  /* we copy string into same palloc block as the struct */
264  authtoken = (AuthToken *) palloc0(sizeof(AuthToken) + toklen + 1);
265  authtoken->string = (char *) authtoken + sizeof(AuthToken);
266  authtoken->quoted = quoted;
267  authtoken->regex = NULL;
268  memcpy(authtoken->string, token, toklen + 1);
269 
270  return authtoken;
271 }

References palloc0(), AuthToken::quoted, AuthToken::regex, AuthToken::string, and token.

Referenced by check_ident_usermap(), copy_auth_token(), and next_field_expand().

◆ next_field_expand()

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

Definition at line 379 of file hba.c.

381 {
383  bool trailing_comma;
384  bool initial_quote;
385  List *tokens = NIL;
386 
388 
389  do
390  {
391  if (!next_token(lineptr, &buf,
392  &initial_quote, &trailing_comma))
393  break;
394 
395  /* Is this referencing a file? */
396  if (!initial_quote && buf.len > 1 && buf.data[0] == '@')
397  tokens = tokenize_expand_file(tokens, filename, buf.data + 1,
398  elevel, depth + 1, err_msg);
399  else
400  {
401  MemoryContext oldcxt;
402 
403  /*
404  * lappend() may do its own allocations, so move to the context
405  * for the list of tokens.
406  */
408  tokens = lappend(tokens, make_auth_token(buf.data, initial_quote));
409  MemoryContextSwitchTo(oldcxt);
410  }
411  } while (trailing_comma && (*err_msg == NULL));
412 
413  pfree(buf.data);
414 
415  return tokens;
416 }
static List * tokenize_expand_file(List *tokens, const char *outer_filename, const char *inc_filename, int elevel, int depth, char **err_msg)
Definition: hba.c:493
static bool next_token(char **lineptr, StringInfo buf, bool *initial_quote, bool *terminating_comma)
Definition: hba.c:185
static char * filename
Definition: pg_dumpall.c:119
static char * buf
Definition: pg_test_fsync.c:73
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59

References buf, filename, initStringInfo(), lappend(), make_auth_token(), MemoryContextSwitchTo(), next_token(), NIL, pfree(), tokenize_context, and tokenize_expand_file().

Referenced by tokenize_auth_file().

◆ next_token()

static bool next_token ( char **  lineptr,
StringInfo  buf,
bool initial_quote,
bool terminating_comma 
)
static

Definition at line 185 of file hba.c.

187 {
188  int c;
189  bool in_quote = false;
190  bool was_quote = false;
191  bool saw_quote = false;
192 
193  /* Initialize output parameters */
195  *initial_quote = false;
196  *terminating_comma = false;
197 
198  /* Move over any whitespace and commas preceding the next token */
199  while ((c = (*(*lineptr)++)) != '\0' && (pg_isblank(c) || c == ','))
200  ;
201 
202  /*
203  * Build a token in buf of next characters up to EOL, unquoted comma, or
204  * unquoted whitespace.
205  */
206  while (c != '\0' &&
207  (!pg_isblank(c) || in_quote))
208  {
209  /* skip comments to EOL */
210  if (c == '#' && !in_quote)
211  {
212  while ((c = (*(*lineptr)++)) != '\0')
213  ;
214  break;
215  }
216 
217  /* we do not pass back a terminating comma in the token */
218  if (c == ',' && !in_quote)
219  {
220  *terminating_comma = true;
221  break;
222  }
223 
224  if (c != '"' || was_quote)
226 
227  /* Literal double-quote is two double-quotes */
228  if (in_quote && c == '"')
229  was_quote = !was_quote;
230  else
231  was_quote = false;
232 
233  if (c == '"')
234  {
235  in_quote = !in_quote;
236  saw_quote = true;
237  if (buf->len == 0)
238  *initial_quote = true;
239  }
240 
241  c = *(*lineptr)++;
242  }
243 
244  /*
245  * Un-eat the char right after the token (critical in case it is '\0',
246  * else next call will read past end of string).
247  */
248  (*lineptr)--;
249 
250  return (saw_quote || buf->len > 0);
251 }
bool pg_isblank(const char c)
Definition: hba.c:144
char * c
void resetStringInfo(StringInfo str)
Definition: stringinfo.c:78
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:194

References appendStringInfoChar(), buf, pg_isblank(), and resetStringInfo().

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

◆ open_auth_file()

FILE* open_auth_file ( const char *  filename,
int  elevel,
int  depth,
char **  err_msg 
)

Definition at line 595 of file hba.c.

597 {
598  FILE *file;
599 
600  /*
601  * Reject too-deep include nesting depth. This is just a safety check to
602  * avoid dumping core due to stack overflow if an include file loops back
603  * to itself. The maximum nesting depth is pretty arbitrary.
604  */
605  if (depth > CONF_FILE_MAX_DEPTH)
606  {
607  ereport(elevel,
609  errmsg("could not open file \"%s\": maximum nesting depth exceeded",
610  filename)));
611  if (err_msg)
612  *err_msg = psprintf("could not open file \"%s\": maximum nesting depth exceeded",
613  filename);
614  return NULL;
615  }
616 
617  file = AllocateFile(filename, "r");
618  if (file == NULL)
619  {
620  int save_errno = errno;
621 
622  ereport(elevel,
624  errmsg("could not open file \"%s\": %m",
625  filename)));
626  if (err_msg)
627  *err_msg = psprintf("could not open file \"%s\": %s",
628  filename, strerror(save_errno));
629  /* the caller may care about some specific errno */
630  errno = save_errno;
631  return NULL;
632  }
633 
634  /*
635  * When opening the top-level file, create the memory context used for the
636  * tokenization. This will be closed with this file when coming back to
637  * this level of cleanup.
638  */
639  if (depth == CONF_FILE_START_DEPTH)
640  {
641  /*
642  * A context may be present, but assume that it has been eliminated
643  * already.
644  */
646  "tokenize_context",
648  }
649 
650  return file;
651 }
#define CONF_FILE_MAX_DEPTH
Definition: conffiles.h:18
int errcode_for_file_access(void)
Definition: elog.c:882
FILE * AllocateFile(const char *name, const char *mode)
Definition: fd.c:2583
MemoryContext CurrentMemoryContext
Definition: mcxt.c:143
#define ALLOCSET_START_SMALL_SIZES
Definition: memutils.h:177
#define strerror
Definition: port.h:251

References AllocateFile(), ALLOCSET_START_SMALL_SIZES, AllocSetContextCreate, CONF_FILE_MAX_DEPTH, CONF_FILE_START_DEPTH, CurrentMemoryContext, ereport, errcode_for_file_access(), errmsg(), filename, psprintf(), strerror, and tokenize_context.

Referenced by fill_hba_view(), fill_ident_view(), load_hba(), load_ident(), tokenize_expand_file(), and tokenize_include_file().

◆ 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 2049 of file hba.c.

2051 {
2052  int line_num = hbaline->linenumber;
2053  char *file_name = hbaline->sourcefile;
2054 
2055 #ifdef USE_LDAP
2056  hbaline->ldapscope = LDAP_SCOPE_SUBTREE;
2057 #endif
2058 
2059  if (strcmp(name, "map") == 0)
2060  {
2061  if (hbaline->auth_method != uaIdent &&
2062  hbaline->auth_method != uaPeer &&
2063  hbaline->auth_method != uaGSS &&
2064  hbaline->auth_method != uaSSPI &&
2065  hbaline->auth_method != uaCert)
2066  INVALID_AUTH_OPTION("map", gettext_noop("ident, peer, gssapi, sspi, and cert"));
2067  hbaline->usermap = pstrdup(val);
2068  }
2069  else if (strcmp(name, "clientcert") == 0)
2070  {
2071  if (hbaline->conntype != ctHostSSL)
2072  {
2073  ereport(elevel,
2074  (errcode(ERRCODE_CONFIG_FILE_ERROR),
2075  errmsg("clientcert can only be configured for \"hostssl\" rows"),
2076  errcontext("line %d of configuration file \"%s\"",
2077  line_num, file_name)));
2078  *err_msg = "clientcert can only be configured for \"hostssl\" rows";
2079  return false;
2080  }
2081 
2082  if (strcmp(val, "verify-full") == 0)
2083  {
2084  hbaline->clientcert = clientCertFull;
2085  }
2086  else if (strcmp(val, "verify-ca") == 0)
2087  {
2088  if (hbaline->auth_method == uaCert)
2089  {
2090  ereport(elevel,
2091  (errcode(ERRCODE_CONFIG_FILE_ERROR),
2092  errmsg("clientcert only accepts \"verify-full\" when using \"cert\" authentication"),
2093  errcontext("line %d of configuration file \"%s\"",
2094  line_num, file_name)));
2095  *err_msg = "clientcert can only be set to \"verify-full\" when using \"cert\" authentication";
2096  return false;
2097  }
2098 
2099  hbaline->clientcert = clientCertCA;
2100  }
2101  else
2102  {
2103  ereport(elevel,
2104  (errcode(ERRCODE_CONFIG_FILE_ERROR),
2105  errmsg("invalid value for clientcert: \"%s\"", val),
2106  errcontext("line %d of configuration file \"%s\"",
2107  line_num, file_name)));
2108  return false;
2109  }
2110  }
2111  else if (strcmp(name, "clientname") == 0)
2112  {
2113  if (hbaline->conntype != ctHostSSL)
2114  {
2115  ereport(elevel,
2116  (errcode(ERRCODE_CONFIG_FILE_ERROR),
2117  errmsg("clientname can only be configured for \"hostssl\" rows"),
2118  errcontext("line %d of configuration file \"%s\"",
2119  line_num, file_name)));
2120  *err_msg = "clientname can only be configured for \"hostssl\" rows";
2121  return false;
2122  }
2123 
2124  if (strcmp(val, "CN") == 0)
2125  {
2126  hbaline->clientcertname = clientCertCN;
2127  }
2128  else if (strcmp(val, "DN") == 0)
2129  {
2130  hbaline->clientcertname = clientCertDN;
2131  }
2132  else
2133  {
2134  ereport(elevel,
2135  (errcode(ERRCODE_CONFIG_FILE_ERROR),
2136  errmsg("invalid value for clientname: \"%s\"", val),
2137  errcontext("line %d of configuration file \"%s\"",
2138  line_num, file_name)));
2139  return false;
2140  }
2141  }
2142  else if (strcmp(name, "pamservice") == 0)
2143  {
2144  REQUIRE_AUTH_OPTION(uaPAM, "pamservice", "pam");
2145  hbaline->pamservice = pstrdup(val);
2146  }
2147  else if (strcmp(name, "pam_use_hostname") == 0)
2148  {
2149  REQUIRE_AUTH_OPTION(uaPAM, "pam_use_hostname", "pam");
2150  if (strcmp(val, "1") == 0)
2151  hbaline->pam_use_hostname = true;
2152  else
2153  hbaline->pam_use_hostname = false;
2154  }
2155  else if (strcmp(name, "ldapurl") == 0)
2156  {
2157 #ifdef LDAP_API_FEATURE_X_OPENLDAP
2158  LDAPURLDesc *urldata;
2159  int rc;
2160 #endif
2161 
2162  REQUIRE_AUTH_OPTION(uaLDAP, "ldapurl", "ldap");
2163 #ifdef LDAP_API_FEATURE_X_OPENLDAP
2164  rc = ldap_url_parse(val, &urldata);
2165  if (rc != LDAP_SUCCESS)
2166  {
2167  ereport(elevel,
2168  (errcode(ERRCODE_CONFIG_FILE_ERROR),
2169  errmsg("could not parse LDAP URL \"%s\": %s", val, ldap_err2string(rc))));
2170  *err_msg = psprintf("could not parse LDAP URL \"%s\": %s",
2171  val, ldap_err2string(rc));
2172  return false;
2173  }
2174 
2175  if (strcmp(urldata->lud_scheme, "ldap") != 0 &&
2176  strcmp(urldata->lud_scheme, "ldaps") != 0)
2177  {
2178  ereport(elevel,
2179  (errcode(ERRCODE_CONFIG_FILE_ERROR),
2180  errmsg("unsupported LDAP URL scheme: %s", urldata->lud_scheme)));
2181  *err_msg = psprintf("unsupported LDAP URL scheme: %s",
2182  urldata->lud_scheme);
2183  ldap_free_urldesc(urldata);
2184  return false;
2185  }
2186 
2187  if (urldata->lud_scheme)
2188  hbaline->ldapscheme = pstrdup(urldata->lud_scheme);
2189  if (urldata->lud_host)
2190  hbaline->ldapserver = pstrdup(urldata->lud_host);
2191  hbaline->ldapport = urldata->lud_port;
2192  if (urldata->lud_dn)
2193  hbaline->ldapbasedn = pstrdup(urldata->lud_dn);
2194 
2195  if (urldata->lud_attrs)
2196  hbaline->ldapsearchattribute = pstrdup(urldata->lud_attrs[0]); /* only use first one */
2197  hbaline->ldapscope = urldata->lud_scope;
2198  if (urldata->lud_filter)
2199  hbaline->ldapsearchfilter = pstrdup(urldata->lud_filter);
2200  ldap_free_urldesc(urldata);
2201 #else /* not OpenLDAP */
2202  ereport(elevel,
2203  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2204  errmsg("LDAP URLs not supported on this platform")));
2205  *err_msg = "LDAP URLs not supported on this platform";
2206 #endif /* not OpenLDAP */
2207  }
2208  else if (strcmp(name, "ldaptls") == 0)
2209  {
2210  REQUIRE_AUTH_OPTION(uaLDAP, "ldaptls", "ldap");
2211  if (strcmp(val, "1") == 0)
2212  hbaline->ldaptls = true;
2213  else
2214  hbaline->ldaptls = false;
2215  }
2216  else if (strcmp(name, "ldapscheme") == 0)
2217  {
2218  REQUIRE_AUTH_OPTION(uaLDAP, "ldapscheme", "ldap");
2219  if (strcmp(val, "ldap") != 0 && strcmp(val, "ldaps") != 0)
2220  ereport(elevel,
2221  (errcode(ERRCODE_CONFIG_FILE_ERROR),
2222  errmsg("invalid ldapscheme value: \"%s\"", val),
2223  errcontext("line %d of configuration file \"%s\"",
2224  line_num, file_name)));
2225  hbaline->ldapscheme = pstrdup(val);
2226  }
2227  else if (strcmp(name, "ldapserver") == 0)
2228  {
2229  REQUIRE_AUTH_OPTION(uaLDAP, "ldapserver", "ldap");
2230  hbaline->ldapserver = pstrdup(val);
2231  }
2232  else if (strcmp(name, "ldapport") == 0)
2233  {
2234  REQUIRE_AUTH_OPTION(uaLDAP, "ldapport", "ldap");
2235  hbaline->ldapport = atoi(val);
2236  if (hbaline->ldapport == 0)
2237  {
2238  ereport(elevel,
2239  (errcode(ERRCODE_CONFIG_FILE_ERROR),
2240  errmsg("invalid LDAP port number: \"%s\"", val),
2241  errcontext("line %d of configuration file \"%s\"",
2242  line_num, file_name)));
2243  *err_msg = psprintf("invalid LDAP port number: \"%s\"", val);
2244  return false;
2245  }
2246  }
2247  else if (strcmp(name, "ldapbinddn") == 0)
2248  {
2249  REQUIRE_AUTH_OPTION(uaLDAP, "ldapbinddn", "ldap");
2250  hbaline->ldapbinddn = pstrdup(val);
2251  }
2252  else if (strcmp(name, "ldapbindpasswd") == 0)
2253  {
2254  REQUIRE_AUTH_OPTION(uaLDAP, "ldapbindpasswd", "ldap");
2255  hbaline->ldapbindpasswd = pstrdup(val);
2256  }
2257  else if (strcmp(name, "ldapsearchattribute") == 0)
2258  {
2259  REQUIRE_AUTH_OPTION(uaLDAP, "ldapsearchattribute", "ldap");
2260  hbaline->ldapsearchattribute = pstrdup(val);
2261  }
2262  else if (strcmp(name, "ldapsearchfilter") == 0)
2263  {
2264  REQUIRE_AUTH_OPTION(uaLDAP, "ldapsearchfilter", "ldap");
2265  hbaline->ldapsearchfilter = pstrdup(val);
2266  }
2267  else if (strcmp(name, "ldapbasedn") == 0)
2268  {
2269  REQUIRE_AUTH_OPTION(uaLDAP, "ldapbasedn", "ldap");
2270  hbaline->ldapbasedn = pstrdup(val);
2271  }
2272  else if (strcmp(name, "ldapprefix") == 0)
2273  {
2274  REQUIRE_AUTH_OPTION(uaLDAP, "ldapprefix", "ldap");
2275  hbaline->ldapprefix = pstrdup(val);
2276  }
2277  else if (strcmp(name, "ldapsuffix") == 0)
2278  {
2279  REQUIRE_AUTH_OPTION(uaLDAP, "ldapsuffix", "ldap");
2280  hbaline->ldapsuffix = pstrdup(val);
2281  }
2282  else if (strcmp(name, "krb_realm") == 0)
2283  {
2284  if (hbaline->auth_method != uaGSS &&
2285  hbaline->auth_method != uaSSPI)
2286  INVALID_AUTH_OPTION("krb_realm", gettext_noop("gssapi and sspi"));
2287  hbaline->krb_realm = pstrdup(val);
2288  }
2289  else if (strcmp(name, "include_realm") == 0)
2290  {
2291  if (hbaline->auth_method != uaGSS &&
2292  hbaline->auth_method != uaSSPI)
2293  INVALID_AUTH_OPTION("include_realm", gettext_noop("gssapi and sspi"));
2294  if (strcmp(val, "1") == 0)
2295  hbaline->include_realm = true;
2296  else
2297  hbaline->include_realm = false;
2298  }
2299  else if (strcmp(name, "compat_realm") == 0)
2300  {
2301  if (hbaline->auth_method != uaSSPI)
2302  INVALID_AUTH_OPTION("compat_realm", gettext_noop("sspi"));
2303  if (strcmp(val, "1") == 0)
2304  hbaline->compat_realm = true;
2305  else
2306  hbaline->compat_realm = false;
2307  }
2308  else if (strcmp(name, "upn_username") == 0)
2309  {
2310  if (hbaline->auth_method != uaSSPI)
2311  INVALID_AUTH_OPTION("upn_username", gettext_noop("sspi"));
2312  if (strcmp(val, "1") == 0)
2313  hbaline->upn_username = true;
2314  else
2315  hbaline->upn_username = false;
2316  }
2317  else if (strcmp(name, "radiusservers") == 0)
2318  {
2319  struct addrinfo *gai_result;
2320  struct addrinfo hints;
2321  int ret;
2322  List *parsed_servers;
2323  ListCell *l;
2324  char *dupval = pstrdup(val);
2325 
2326  REQUIRE_AUTH_OPTION(uaRADIUS, "radiusservers", "radius");
2327 
2328  if (!SplitGUCList(dupval, ',', &parsed_servers))
2329  {
2330  /* syntax error in list */
2331  ereport(elevel,
2332  (errcode(ERRCODE_CONFIG_FILE_ERROR),
2333  errmsg("could not parse RADIUS server list \"%s\"",
2334  val),
2335  errcontext("line %d of configuration file \"%s\"",
2336  line_num, file_name)));
2337  return false;
2338  }
2339 
2340  /* For each entry in the list, translate it */
2341  foreach(l, parsed_servers)
2342  {
2343  MemSet(&hints, 0, sizeof(hints));
2344  hints.ai_socktype = SOCK_DGRAM;
2345  hints.ai_family = AF_UNSPEC;
2346 
2347  ret = pg_getaddrinfo_all((char *) lfirst(l), NULL, &hints, &gai_result);
2348  if (ret || !gai_result)
2349  {
2350  ereport(elevel,
2351  (errcode(ERRCODE_CONFIG_FILE_ERROR),
2352  errmsg("could not translate RADIUS server name \"%s\" to address: %s",
2353  (char *) lfirst(l), gai_strerror(ret)),
2354  errcontext("line %d of configuration file \"%s\"",
2355  line_num, file_name)));
2356  if (gai_result)
2357  pg_freeaddrinfo_all(hints.ai_family, gai_result);
2358 
2359  list_free(parsed_servers);
2360  return false;
2361  }
2362  pg_freeaddrinfo_all(hints.ai_family, gai_result);
2363  }
2364 
2365  /* All entries are OK, so store them */
2366  hbaline->radiusservers = parsed_servers;
2367  hbaline->radiusservers_s = pstrdup(val);
2368  }
2369  else if (strcmp(name, "radiusports") == 0)
2370  {
2371  List *parsed_ports;
2372  ListCell *l;
2373  char *dupval = pstrdup(val);
2374 
2375  REQUIRE_AUTH_OPTION(uaRADIUS, "radiusports", "radius");
2376 
2377  if (!SplitGUCList(dupval, ',', &parsed_ports))
2378  {
2379  ereport(elevel,
2380  (errcode(ERRCODE_CONFIG_FILE_ERROR),
2381  errmsg("could not parse RADIUS port list \"%s\"",
2382  val),
2383  errcontext("line %d of configuration file \"%s\"",
2384  line_num, file_name)));
2385  *err_msg = psprintf("invalid RADIUS port number: \"%s\"", val);
2386  return false;
2387  }
2388 
2389  foreach(l, parsed_ports)
2390  {
2391  if (atoi(lfirst(l)) == 0)
2392  {
2393  ereport(elevel,
2394  (errcode(ERRCODE_CONFIG_FILE_ERROR),
2395  errmsg("invalid RADIUS port number: \"%s\"", val),
2396  errcontext("line %d of configuration file \"%s\"",
2397  line_num, file_name)));
2398 
2399  return false;
2400  }
2401  }
2402  hbaline->radiusports = parsed_ports;
2403  hbaline->radiusports_s = pstrdup(val);
2404  }
2405  else if (strcmp(name, "radiussecrets") == 0)
2406  {
2407  List *parsed_secrets;
2408  char *dupval = pstrdup(val);
2409 
2410  REQUIRE_AUTH_OPTION(uaRADIUS, "radiussecrets", "radius");
2411 
2412  if (!SplitGUCList(dupval, ',', &parsed_secrets))
2413  {
2414  /* syntax error in list */
2415  ereport(elevel,
2416  (errcode(ERRCODE_CONFIG_FILE_ERROR),
2417  errmsg("could not parse RADIUS secret list \"%s\"",
2418  val),
2419  errcontext("line %d of configuration file \"%s\"",
2420  line_num, file_name)));
2421  return false;
2422  }
2423 
2424  hbaline->radiussecrets = parsed_secrets;
2425  hbaline->radiussecrets_s = pstrdup(val);
2426  }
2427  else if (strcmp(name, "radiusidentifiers") == 0)
2428  {
2429  List *parsed_identifiers;
2430  char *dupval = pstrdup(val);
2431 
2432  REQUIRE_AUTH_OPTION(uaRADIUS, "radiusidentifiers", "radius");
2433 
2434  if (!SplitGUCList(dupval, ',', &parsed_identifiers))
2435  {
2436  /* syntax error in list */
2437  ereport(elevel,
2438  (errcode(ERRCODE_CONFIG_FILE_ERROR),
2439  errmsg("could not parse RADIUS identifiers list \"%s\"",
2440  val),
2441  errcontext("line %d of configuration file \"%s\"",
2442  line_num, file_name)));
2443  return false;
2444  }
2445 
2446  hbaline->radiusidentifiers = parsed_identifiers;
2447  hbaline->radiusidentifiers_s = pstrdup(val);
2448  }
2449  else
2450  {
2451  ereport(elevel,
2452  (errcode(ERRCODE_CONFIG_FILE_ERROR),
2453  errmsg("unrecognized authentication option name: \"%s\"",
2454  name),
2455  errcontext("line %d of configuration file \"%s\"",
2456  line_num, file_name)));
2457  *err_msg = psprintf("unrecognized authentication option name: \"%s\"",
2458  name);
2459  return false;
2460  }
2461  return true;
2462 }
#define gettext_noop(x)
Definition: c.h:1196
#define MemSet(start, val, len)
Definition: c.h:1020
#define INVALID_AUTH_OPTION(optname, validmethods)
Definition: hba.c:1238
#define REQUIRE_AUTH_OPTION(methodval, optname, validmethods)
Definition: hba.c:1252
@ uaLDAP
Definition: hba.h:38
@ uaPeer
Definition: hba.h:41
@ uaPAM
Definition: hba.h:36
@ uaCert
Definition: hba.h:39
@ uaGSS
Definition: hba.h:34
@ uaRADIUS
Definition: hba.h:40
@ uaIdent
Definition: hba.h:30
@ uaSSPI
Definition: hba.h:35
@ clientCertDN
Definition: hba.h:77
@ clientCertCN
Definition: hba.h:76
@ clientCertFull
Definition: hba.h:71
@ clientCertCA
Definition: hba.h:70
long val
Definition: informix.c:670
void pg_freeaddrinfo_all(int hint_ai_family, struct addrinfo *ai)
Definition: ip.c:82
int pg_getaddrinfo_all(const char *hostname, const char *servname, const struct addrinfo *hintp, struct addrinfo **result)
Definition: ip.c:53
void list_free(List *list)
Definition: list.c:1546
const char * gai_strerror(int ecode)
bool upn_username
Definition: hba.h:129
char * sourcefile
Definition: hba.h:96
ClientCertName clientcertname
Definition: hba.h:125
List * radiusservers
Definition: hba.h:130
char * ldapserver
Definition: hba.h:114
bool include_realm
Definition: hba.h:127
ClientCertMode clientcert
Definition: hba.h:124
char * ldapsearchfilter
Definition: hba.h:119
char * ldapscheme
Definition: hba.h:113
char * ldapprefix
Definition: hba.h:122
List * radiussecrets
Definition: hba.h:132
char * ldapsearchattribute
Definition: hba.h:118
char * krb_realm
Definition: hba.h:126
char * ldapbasedn
Definition: hba.h:120
bool pam_use_hostname
Definition: hba.h:111
int linenumber
Definition: hba.h:97
char * radiussecrets_s
Definition: hba.h:133
List * radiusports
Definition: hba.h:136
List * radiusidentifiers
Definition: hba.h:134
char * pamservice
Definition: hba.h:110
char * usermap
Definition: hba.h:109
char * ldapsuffix
Definition: hba.h:123
int ldapport
Definition: hba.h:115
char * ldapbindpasswd
Definition: hba.h:117
char * radiusports_s
Definition: hba.h:137
char * ldapbinddn
Definition: hba.h:116
bool compat_realm
Definition: hba.h:128
int ldapscope
Definition: hba.h:121
bool ldaptls
Definition: hba.h:112
char * radiusservers_s
Definition: hba.h:131
char * radiusidentifiers_s
Definition: hba.h:135
bool SplitGUCList(char *rawstring, char separator, List **namelist)
Definition: varlena.c:3705
const char * name

References 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, 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, name, 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, HbaLine::sourcefile, SplitGUCList(), uaCert, uaGSS, uaIdent, uaLDAP, uaPAM, uaPeer, uaRADIUS, uaSSPI, HbaLine::upn_username, HbaLine::usermap, and val.

Referenced by parse_hba_line().

◆ parse_hba_line()

HbaLine* parse_hba_line ( TokenizedAuthLine tok_line,
int  elevel 
)

Definition at line 1322 of file hba.c.

1323 {
1324  int line_num = tok_line->line_num;
1325  char *file_name = tok_line->file_name;
1326  char **err_msg = &tok_line->err_msg;
1327  char *str;
1328  struct addrinfo *gai_result;
1329  struct addrinfo hints;
1330  int ret;
1331  char *cidr_slash;
1332  char *unsupauth;
1333  ListCell *field;
1334  List *tokens;
1335  ListCell *tokencell;
1336  AuthToken *token;
1337  HbaLine *parsedline;
1338 
1339  parsedline = palloc0(sizeof(HbaLine));
1340  parsedline->sourcefile = pstrdup(file_name);
1341  parsedline->linenumber = line_num;
1342  parsedline->rawline = pstrdup(tok_line->raw_line);
1343 
1344  /* Check the record type. */
1345  Assert(tok_line->fields != NIL);
1346  field = list_head(tok_line->fields);
1347  tokens = lfirst(field);
1348  if (tokens->length > 1)
1349  {
1350  ereport(elevel,
1351  (errcode(ERRCODE_CONFIG_FILE_ERROR),
1352  errmsg("multiple values specified for connection type"),
1353  errhint("Specify exactly one connection type per line."),
1354  errcontext("line %d of configuration file \"%s\"",
1355  line_num, file_name)));
1356  *err_msg = "multiple values specified for connection type";
1357  return NULL;
1358  }
1359  token = linitial(tokens);
1360  if (strcmp(token->string, "local") == 0)
1361  {
1362  parsedline->conntype = ctLocal;
1363  }
1364  else if (strcmp(token->string, "host") == 0 ||
1365  strcmp(token->string, "hostssl") == 0 ||
1366  strcmp(token->string, "hostnossl") == 0 ||
1367  strcmp(token->string, "hostgssenc") == 0 ||
1368  strcmp(token->string, "hostnogssenc") == 0)
1369  {
1370 
1371  if (token->string[4] == 's') /* "hostssl" */
1372  {
1373  parsedline->conntype = ctHostSSL;
1374  /* Log a warning if SSL support is not active */
1375 #ifdef USE_SSL
1376  if (!EnableSSL)
1377  {
1378  ereport(elevel,
1379  (errcode(ERRCODE_CONFIG_FILE_ERROR),
1380  errmsg("hostssl record cannot match because SSL is disabled"),
1381  errhint("Set ssl = on in postgresql.conf."),
1382  errcontext("line %d of configuration file \"%s\"",
1383  line_num, file_name)));
1384  *err_msg = "hostssl record cannot match because SSL is disabled";
1385  }
1386 #else
1387  ereport(elevel,
1388  (errcode(ERRCODE_CONFIG_FILE_ERROR),
1389  errmsg("hostssl record cannot match because SSL is not supported by this build"),
1390  errcontext("line %d of configuration file \"%s\"",
1391  line_num, file_name)));
1392  *err_msg = "hostssl record cannot match because SSL is not supported by this build";
1393 #endif
1394  }
1395  else if (token->string[4] == 'g') /* "hostgssenc" */
1396  {
1397  parsedline->conntype = ctHostGSS;
1398 #ifndef ENABLE_GSS
1399  ereport(elevel,
1400  (errcode(ERRCODE_CONFIG_FILE_ERROR),
1401  errmsg("hostgssenc record cannot match because GSSAPI is not supported by this build"),
1402  errcontext("line %d of configuration file \"%s\"",
1403  line_num, file_name)));
1404  *err_msg = "hostgssenc record cannot match because GSSAPI is not supported by this build";
1405 #endif
1406  }
1407  else if (token->string[4] == 'n' && token->string[6] == 's')
1408  parsedline->conntype = ctHostNoSSL;
1409  else if (token->string[4] == 'n' && token->string[6] == 'g')
1410  parsedline->conntype = ctHostNoGSS;
1411  else
1412  {
1413  /* "host" */
1414  parsedline->conntype = ctHost;
1415  }
1416  } /* record type */
1417  else
1418  {
1419  ereport(elevel,
1420  (errcode(ERRCODE_CONFIG_FILE_ERROR),
1421  errmsg("invalid connection type \"%s\"",
1422  token->string),
1423  errcontext("line %d of configuration file \"%s\"",
1424  line_num, file_name)));
1425  *err_msg = psprintf("invalid connection type \"%s\"", token->string);
1426  return NULL;
1427  }
1428 
1429  /* Get the databases. */
1430  field = lnext(tok_line->fields, field);
1431  if (!field)
1432  {
1433  ereport(elevel,
1434  (errcode(ERRCODE_CONFIG_FILE_ERROR),
1435  errmsg("end-of-line before database specification"),
1436  errcontext("line %d of configuration file \"%s\"",
1437  line_num, file_name)));
1438  *err_msg = "end-of-line before database specification";
1439  return NULL;
1440  }
1441  parsedline->databases = NIL;
1442  tokens = lfirst(field);
1443  foreach(tokencell, tokens)
1444  {
1445  AuthToken *tok = copy_auth_token(lfirst(tokencell));
1446 
1447  /* Compile a regexp for the database token, if necessary */
1448  if (regcomp_auth_token(tok, file_name, line_num, err_msg, elevel))
1449  return NULL;
1450 
1451  parsedline->databases = lappend(parsedline->databases, tok);
1452  }
1453 
1454  /* Get the roles. */
1455  field = lnext(tok_line->fields, field);
1456  if (!field)
1457  {
1458  ereport(elevel,
1459  (errcode(ERRCODE_CONFIG_FILE_ERROR),
1460  errmsg("end-of-line before role specification"),
1461  errcontext("line %d of configuration file \"%s\"",
1462  line_num, file_name)));
1463  *err_msg = "end-of-line before role specification";
1464  return NULL;
1465  }
1466  parsedline->roles = NIL;
1467  tokens = lfirst(field);
1468  foreach(tokencell, tokens)
1469  {
1470  AuthToken *tok = copy_auth_token(lfirst(tokencell));
1471 
1472  /* Compile a regexp from the role token, if necessary */
1473  if (regcomp_auth_token(tok, file_name, line_num, err_msg, elevel))
1474  return NULL;
1475 
1476  parsedline->roles = lappend(parsedline->roles, tok);
1477  }
1478 
1479  if (parsedline->conntype != ctLocal)
1480  {
1481  /* Read the IP address field. (with or without CIDR netmask) */
1482  field = lnext(tok_line->fields, field);
1483  if (!field)
1484  {
1485  ereport(elevel,
1486  (errcode(ERRCODE_CONFIG_FILE_ERROR),
1487  errmsg("end-of-line before IP address specification"),
1488  errcontext("line %d of configuration file \"%s\"",
1489  line_num, file_name)));
1490  *err_msg = "end-of-line before IP address specification";
1491  return NULL;
1492  }
1493  tokens = lfirst(field);
1494  if (tokens->length > 1)
1495  {
1496  ereport(elevel,
1497  (errcode(ERRCODE_CONFIG_FILE_ERROR),
1498  errmsg("multiple values specified for host address"),
1499  errhint("Specify one address range per line."),
1500  errcontext("line %d of configuration file \"%s\"",
1501  line_num, file_name)));
1502  *err_msg = "multiple values specified for host address";
1503  return NULL;
1504  }
1505  token = linitial(tokens);
1506 
1507  if (token_is_keyword(token, "all"))
1508  {
1509  parsedline->ip_cmp_method = ipCmpAll;
1510  }
1511  else if (token_is_keyword(token, "samehost"))
1512  {
1513  /* Any IP on this host is allowed to connect */
1514  parsedline->ip_cmp_method = ipCmpSameHost;
1515  }
1516  else if (token_is_keyword(token, "samenet"))
1517  {
1518  /* Any IP on the host's subnets is allowed to connect */
1519  parsedline->ip_cmp_method = ipCmpSameNet;
1520  }
1521  else
1522  {
1523  /* IP and netmask are specified */
1524  parsedline->ip_cmp_method = ipCmpMask;
1525 
1526  /* need a modifiable copy of token */
1527  str = pstrdup(token->string);
1528 
1529  /* Check if it has a CIDR suffix and if so isolate it */
1530  cidr_slash = strchr(str, '/');
1531  if (cidr_slash)
1532  *cidr_slash = '\0';
1533 
1534  /* Get the IP address either way */
1535  hints.ai_flags = AI_NUMERICHOST;
1536  hints.ai_family = AF_UNSPEC;
1537  hints.ai_socktype = 0;
1538  hints.ai_protocol = 0;
1539  hints.ai_addrlen = 0;
1540  hints.ai_canonname = NULL;
1541  hints.ai_addr = NULL;
1542  hints.ai_next = NULL;
1543 
1544  ret = pg_getaddrinfo_all(str, NULL, &hints, &gai_result);
1545  if (ret == 0 && gai_result)
1546  {
1547  memcpy(&parsedline->addr, gai_result->ai_addr,
1548  gai_result->ai_addrlen);
1549  parsedline->addrlen = gai_result->ai_addrlen;
1550  }
1551  else if (ret == EAI_NONAME)
1552  parsedline->hostname = str;
1553  else
1554  {
1555  ereport(elevel,
1556  (errcode(ERRCODE_CONFIG_FILE_ERROR),
1557  errmsg("invalid IP address \"%s\": %s",
1558  str, gai_strerror(ret)),
1559  errcontext("line %d of configuration file \"%s\"",
1560  line_num, file_name)));
1561  *err_msg = psprintf("invalid IP address \"%s\": %s",
1562  str, gai_strerror(ret));
1563  if (gai_result)
1564  pg_freeaddrinfo_all(hints.ai_family, gai_result);
1565  return NULL;
1566  }
1567 
1568  pg_freeaddrinfo_all(hints.ai_family, gai_result);
1569 
1570  /* Get the netmask */
1571  if (cidr_slash)
1572  {
1573  if (parsedline->hostname)
1574  {
1575  ereport(elevel,
1576  (errcode(ERRCODE_CONFIG_FILE_ERROR),
1577  errmsg("specifying both host name and CIDR mask is invalid: \"%s\"",
1578  token->string),
1579  errcontext("line %d of configuration file \"%s\"",
1580  line_num, file_name)));
1581  *err_msg = psprintf("specifying both host name and CIDR mask is invalid: \"%s\"",
1582  token->string);
1583  return NULL;
1584  }
1585 
1586  if (pg_sockaddr_cidr_mask(&parsedline->mask, cidr_slash + 1,
1587  parsedline->addr.ss_family) < 0)
1588  {
1589  ereport(elevel,
1590  (errcode(ERRCODE_CONFIG_FILE_ERROR),
1591  errmsg("invalid CIDR mask in address \"%s\"",
1592  token->string),
1593  errcontext("line %d of configuration file \"%s\"",
1594  line_num, file_name)));
1595  *err_msg = psprintf("invalid CIDR mask in address \"%s\"",
1596  token->string);
1597  return NULL;
1598  }
1599  parsedline->masklen = parsedline->addrlen;
1600  pfree(str);
1601  }
1602  else if (!parsedline->hostname)
1603  {
1604  /* Read the mask field. */
1605  pfree(str);
1606  field = lnext(tok_line->fields, field);
1607  if (!field)
1608  {
1609  ereport(elevel,
1610  (errcode(ERRCODE_CONFIG_FILE_ERROR),
1611  errmsg("end-of-line before netmask specification"),
1612  errhint("Specify an address range in CIDR notation, or provide a separate netmask."),
1613  errcontext("line %d of configuration file \"%s\"",
1614  line_num, file_name)));
1615  *err_msg = "end-of-line before netmask specification";
1616  return NULL;
1617  }
1618  tokens = lfirst(field);
1619  if (tokens->length > 1)
1620  {
1621  ereport(elevel,
1622  (errcode(ERRCODE_CONFIG_FILE_ERROR),
1623  errmsg("multiple values specified for netmask"),
1624  errcontext("line %d of configuration file \"%s\"",
1625  line_num, file_name)));
1626  *err_msg = "multiple values specified for netmask";
1627  return NULL;
1628  }
1629  token = linitial(tokens);
1630 
1631  ret = pg_getaddrinfo_all(token->string, NULL,
1632  &hints, &gai_result);
1633  if (ret || !gai_result)
1634  {
1635  ereport(elevel,
1636  (errcode(ERRCODE_CONFIG_FILE_ERROR),
1637  errmsg("invalid IP mask \"%s\": %s",
1638  token->string, gai_strerror(ret)),
1639  errcontext("line %d of configuration file \"%s\"",
1640  line_num, file_name)));
1641  *err_msg = psprintf("invalid IP mask \"%s\": %s",
1642  token->string, gai_strerror(ret));
1643  if (gai_result)
1644  pg_freeaddrinfo_all(hints.ai_family, gai_result);
1645  return NULL;
1646  }
1647 
1648  memcpy(&parsedline->mask, gai_result->ai_addr,
1649  gai_result->ai_addrlen);
1650  parsedline->masklen = gai_result->ai_addrlen;
1651  pg_freeaddrinfo_all(hints.ai_family, gai_result);
1652 
1653  if (parsedline->addr.ss_family != parsedline->mask.ss_family)
1654  {
1655  ereport(elevel,
1656  (errcode(ERRCODE_CONFIG_FILE_ERROR),
1657  errmsg("IP address and mask do not match"),
1658  errcontext("line %d of configuration file \"%s\"",
1659  line_num, file_name)));
1660  *err_msg = "IP address and mask do not match";
1661  return NULL;
1662  }
1663  }
1664  }
1665  } /* != ctLocal */
1666 
1667  /* Get the authentication method */
1668  field = lnext(tok_line->fields, field);
1669  if (!field)
1670  {
1671  ereport(elevel,
1672  (errcode(ERRCODE_CONFIG_FILE_ERROR),
1673  errmsg("end-of-line before authentication method"),
1674  errcontext("line %d of configuration file \"%s\"",
1675  line_num, file_name)));
1676  *err_msg = "end-of-line before authentication method";
1677  return NULL;
1678  }
1679  tokens = lfirst(field);
1680  if (tokens->length > 1)
1681  {
1682  ereport(elevel,
1683  (errcode(ERRCODE_CONFIG_FILE_ERROR),
1684  errmsg("multiple values specified for authentication type"),
1685  errhint("Specify exactly one authentication type per line."),
1686  errcontext("line %d of configuration file \"%s\"",
1687  line_num, file_name)));
1688  *err_msg = "multiple values specified for authentication type";
1689  return NULL;
1690  }
1691  token = linitial(tokens);
1692 
1693  unsupauth = NULL;
1694  if (strcmp(token->string, "trust") == 0)
1695  parsedline->auth_method = uaTrust;
1696  else if (strcmp(token->string, "ident") == 0)
1697  parsedline->auth_method = uaIdent;
1698  else if (strcmp(token->string, "peer") == 0)
1699  parsedline->auth_method = uaPeer;
1700  else if (strcmp(token->string, "password") == 0)
1701  parsedline->auth_method = uaPassword;
1702  else if (strcmp(token->string, "gss") == 0)
1703 #ifdef ENABLE_GSS
1704  parsedline->auth_method = uaGSS;
1705 #else
1706  unsupauth = "gss";
1707 #endif
1708  else if (strcmp(token->string, "sspi") == 0)
1709 #ifdef ENABLE_SSPI
1710  parsedline->auth_method = uaSSPI;
1711 #else
1712  unsupauth = "sspi";
1713 #endif
1714  else if (strcmp(token->string, "reject") == 0)
1715  parsedline->auth_method = uaReject;
1716  else if (strcmp(token->string, "md5") == 0)
1717  parsedline->auth_method = uaMD5;
1718  else if (strcmp(token->string, "scram-sha-256") == 0)
1719  parsedline->auth_method = uaSCRAM;
1720  else if (strcmp(token->string, "pam") == 0)
1721 #ifdef USE_PAM
1722  parsedline->auth_method = uaPAM;
1723 #else
1724  unsupauth = "pam";
1725 #endif
1726  else if (strcmp(token->string, "bsd") == 0)
1727 #ifdef USE_BSD_AUTH
1728  parsedline->auth_method = uaBSD;
1729 #else
1730  unsupauth = "bsd";
1731 #endif
1732  else if (strcmp(token->string, "ldap") == 0)
1733 #ifdef USE_LDAP
1734  parsedline->auth_method = uaLDAP;
1735 #else
1736  unsupauth = "ldap";
1737 #endif
1738  else if (strcmp(token->string, "cert") == 0)
1739 #ifdef USE_SSL
1740  parsedline->auth_method = uaCert;
1741 #else
1742  unsupauth = "cert";
1743 #endif
1744  else if (strcmp(token->string, "radius") == 0)
1745  parsedline->auth_method = uaRADIUS;
1746  else
1747  {
1748  ereport(elevel,
1749  (errcode(ERRCODE_CONFIG_FILE_ERROR),
1750  errmsg("invalid authentication method \"%s\"",
1751  token->string),
1752  errcontext("line %d of configuration file \"%s\"",
1753  line_num, file_name)));
1754  *err_msg = psprintf("invalid authentication method \"%s\"",
1755  token->string);
1756  return NULL;
1757  }
1758 
1759  if (unsupauth)
1760  {
1761  ereport(elevel,
1762  (errcode(ERRCODE_CONFIG_FILE_ERROR),
1763  errmsg("invalid authentication method \"%s\": not supported by this build",
1764  token->string),
1765  errcontext("line %d of configuration file \"%s\"",
1766  line_num, file_name)));
1767  *err_msg = psprintf("invalid authentication method \"%s\": not supported by this build",
1768  token->string);
1769  return NULL;
1770  }
1771 
1772  /*
1773  * XXX: When using ident on local connections, change it to peer, for
1774  * backwards compatibility.
1775  */
1776  if (parsedline->conntype == ctLocal &&
1777  parsedline->auth_method == uaIdent)
1778  parsedline->auth_method = uaPeer;
1779 
1780  /* Invalid authentication combinations */
1781  if (parsedline->conntype == ctLocal &&
1782  parsedline->auth_method == uaGSS)
1783  {
1784  ereport(elevel,
1785  (errcode(ERRCODE_CONFIG_FILE_ERROR),
1786  errmsg("gssapi authentication is not supported on local sockets"),
1787  errcontext("line %d of configuration file \"%s\"",
1788  line_num, file_name)));
1789  *err_msg = "gssapi authentication is not supported on local sockets";
1790  return NULL;
1791  }
1792 
1793  if (parsedline->conntype != ctLocal &&
1794  parsedline->auth_method == uaPeer)
1795  {
1796  ereport(elevel,
1797  (errcode(ERRCODE_CONFIG_FILE_ERROR),
1798  errmsg("peer authentication is only supported on local sockets"),
1799  errcontext("line %d of configuration file \"%s\"",
1800  line_num, file_name)));
1801  *err_msg = "peer authentication is only supported on local sockets";
1802  return NULL;
1803  }
1804 
1805  /*
1806  * SSPI authentication can never be enabled on ctLocal connections,
1807  * because it's only supported on Windows, where ctLocal isn't supported.
1808  */
1809 
1810 
1811  if (parsedline->conntype != ctHostSSL &&
1812  parsedline->auth_method == uaCert)
1813  {
1814  ereport(elevel,
1815  (errcode(ERRCODE_CONFIG_FILE_ERROR),
1816  errmsg("cert authentication is only supported on hostssl connections"),
1817  errcontext("line %d of configuration file \"%s\"",
1818  line_num, file_name)));
1819  *err_msg = "cert authentication is only supported on hostssl connections";
1820  return NULL;
1821  }
1822 
1823  /*
1824  * For GSS and SSPI, set the default value of include_realm to true.
1825  * Having include_realm set to false is dangerous in multi-realm
1826  * situations and is generally considered bad practice. We keep the
1827  * capability around for backwards compatibility, but we might want to
1828  * remove it at some point in the future. Users who still need to strip
1829  * the realm off would be better served by using an appropriate regex in a
1830  * pg_ident.conf mapping.
1831  */
1832  if (parsedline->auth_method == uaGSS ||
1833  parsedline->auth_method == uaSSPI)
1834  parsedline->include_realm = true;
1835 
1836  /*
1837  * For SSPI, include_realm defaults to the SAM-compatible domain (aka
1838  * NetBIOS name) and user names instead of the Kerberos principal name for
1839  * compatibility.
1840  */
1841  if (parsedline->auth_method == uaSSPI)
1842  {
1843  parsedline->compat_realm = true;
1844  parsedline->upn_username = false;
1845  }
1846 
1847  /* Parse remaining arguments */
1848  while ((field = lnext(tok_line->fields, field)) != NULL)
1849  {
1850  tokens = lfirst(field);
1851  foreach(tokencell, tokens)
1852  {
1853  char *val;
1854 
1855  token = lfirst(tokencell);
1856 
1857  str = pstrdup(token->string);
1858  val = strchr(str, '=');
1859  if (val == NULL)
1860  {
1861  /*
1862  * Got something that's not a name=value pair.
1863  */
1864  ereport(elevel,
1865  (errcode(ERRCODE_CONFIG_FILE_ERROR),
1866  errmsg("authentication option not in name=value format: %s", token->string),
1867  errcontext("line %d of configuration file \"%s\"",
1868  line_num, file_name)));
1869  *err_msg = psprintf("authentication option not in name=value format: %s",
1870  token->string);
1871  return NULL;
1872  }
1873 
1874  *val++ = '\0'; /* str now holds "name", val holds "value" */
1875  if (!parse_hba_auth_opt(str, val, parsedline, elevel, err_msg))
1876  /* parse_hba_auth_opt already logged the error message */
1877  return NULL;
1878  pfree(str);
1879  }
1880  }
1881 
1882  /*
1883  * Check if the selected authentication method has any mandatory arguments
1884  * that are not set.
1885  */
1886  if (parsedline->auth_method == uaLDAP)
1887  {
1888 #ifndef HAVE_LDAP_INITIALIZE
1889  /* Not mandatory for OpenLDAP, because it can use DNS SRV records */
1890  MANDATORY_AUTH_ARG(parsedline->ldapserver, "ldapserver", "ldap");
1891 #endif
1892 
1893  /*
1894  * LDAP can operate in two modes: either with a direct bind, using
1895  * ldapprefix and ldapsuffix, or using a search+bind, using
1896  * ldapbasedn, ldapbinddn, ldapbindpasswd and one of
1897  * ldapsearchattribute or ldapsearchfilter. Disallow mixing these
1898  * parameters.
1899  */
1900  if (parsedline->ldapprefix || parsedline->ldapsuffix)
1901  {
1902  if (parsedline->ldapbasedn ||
1903  parsedline->ldapbinddn ||
1904  parsedline->ldapbindpasswd ||
1905  parsedline->ldapsearchattribute ||
1906  parsedline->ldapsearchfilter)
1907  {
1908  ereport(elevel,
1909  (errcode(ERRCODE_CONFIG_FILE_ERROR),
1910  errmsg("cannot use ldapbasedn, ldapbinddn, ldapbindpasswd, ldapsearchattribute, ldapsearchfilter, or ldapurl together with ldapprefix"),
1911  errcontext("line %d of configuration file \"%s\"",
1912  line_num, file_name)));
1913  *err_msg = "cannot use ldapbasedn, ldapbinddn, ldapbindpasswd, ldapsearchattribute, ldapsearchfilter, or ldapurl together with ldapprefix";
1914  return NULL;
1915  }
1916  }
1917  else if (!parsedline->ldapbasedn)
1918  {
1919  ereport(elevel,
1920  (errcode(ERRCODE_CONFIG_FILE_ERROR),
1921  errmsg("authentication method \"ldap\" requires argument \"ldapbasedn\", \"ldapprefix\", or \"ldapsuffix\" to be set"),
1922  errcontext("line %d of configuration file \"%s\"",
1923  line_num, file_name)));
1924  *err_msg = "authentication method \"ldap\" requires argument \"ldapbasedn\", \"ldapprefix\", or \"ldapsuffix\" to be set";
1925  return NULL;
1926  }
1927 
1928  /*
1929  * When using search+bind, you can either use a simple attribute
1930  * (defaulting to "uid") or a fully custom search filter. You can't
1931  * do both.
1932  */
1933  if (parsedline->ldapsearchattribute && parsedline->ldapsearchfilter)
1934  {
1935  ereport(elevel,
1936  (errcode(ERRCODE_CONFIG_FILE_ERROR),
1937  errmsg("cannot use ldapsearchattribute together with ldapsearchfilter"),
1938  errcontext("line %d of configuration file \"%s\"",
1939  line_num, file_name)));
1940  *err_msg = "cannot use ldapsearchattribute together with ldapsearchfilter";
1941  return NULL;
1942  }
1943  }
1944 
1945  if (parsedline->auth_method == uaRADIUS)
1946  {
1947  MANDATORY_AUTH_ARG(parsedline->radiusservers, "radiusservers", "radius");
1948  MANDATORY_AUTH_ARG(parsedline->radiussecrets, "radiussecrets", "radius");
1949 
1950  if (parsedline->radiusservers == NIL)
1951  {
1952  ereport(elevel,
1953  (errcode(ERRCODE_CONFIG_FILE_ERROR),
1954  errmsg("list of RADIUS servers cannot be empty"),
1955  errcontext("line %d of configuration file \"%s\"",
1956  line_num, file_name)));
1957  *err_msg = "list of RADIUS servers cannot be empty";
1958  return NULL;
1959  }
1960 
1961  if (parsedline->radiussecrets == NIL)
1962  {
1963  ereport(elevel,
1964  (errcode(ERRCODE_CONFIG_FILE_ERROR),
1965  errmsg("list of RADIUS secrets cannot be empty"),
1966  errcontext("line %d of configuration file \"%s\"",
1967  line_num, file_name)));
1968  *err_msg = "list of RADIUS secrets cannot be empty";
1969  return NULL;
1970  }
1971 
1972  /*
1973  * Verify length of option lists - each can be 0 (except for secrets,
1974  * but that's already checked above), 1 (use the same value
1975  * everywhere) or the same as the number of servers.
1976  */
1977  if (!(list_length(parsedline->radiussecrets) == 1 ||
1978  list_length(parsedline->radiussecrets) == list_length(parsedline->radiusservers)))
1979  {
1980  ereport(elevel,
1981  (errcode(ERRCODE_CONFIG_FILE_ERROR),
1982  errmsg("the number of RADIUS secrets (%d) must be 1 or the same as the number of RADIUS servers (%d)",
1983  list_length(parsedline->radiussecrets),
1984  list_length(parsedline->radiusservers)),
1985  errcontext("line %d of configuration file \"%s\"",
1986  line_num, file_name)));
1987  *err_msg = psprintf("the number of RADIUS secrets (%d) must be 1 or the same as the number of RADIUS servers (%d)",
1988  list_length(parsedline->radiussecrets),
1989  list_length(parsedline->radiusservers));
1990  return NULL;
1991  }
1992  if (!(list_length(parsedline->radiusports) == 0 ||
1993  list_length(parsedline->radiusports) == 1 ||
1994  list_length(parsedline->radiusports) == list_length(parsedline->radiusservers)))
1995  {
1996  ereport(elevel,
1997  (errcode(ERRCODE_CONFIG_FILE_ERROR),
1998  errmsg("the number of RADIUS ports (%d) must be 1 or the same as the number of RADIUS servers (%d)",
1999  list_length(parsedline->radiusports),
2000  list_length(parsedline->radiusservers)),
2001  errcontext("line %d of configuration file \"%s\"",
2002  line_num, file_name)));
2003  *err_msg = psprintf("the number of RADIUS ports (%d) must be 1 or the same as the number of RADIUS servers (%d)",
2004  list_length(parsedline->radiusports),
2005  list_length(parsedline->radiusservers));
2006  return NULL;
2007  }
2008  if (!(list_length(parsedline->radiusidentifiers) == 0 ||
2009  list_length(parsedline->radiusidentifiers) == 1 ||
2010  list_length(parsedline->radiusidentifiers) == list_length(parsedline->radiusservers)))
2011  {
2012  ereport(elevel,
2013  (errcode(ERRCODE_CONFIG_FILE_ERROR),
2014  errmsg("the number of RADIUS identifiers (%d) must be 1 or the same as the number of RADIUS servers (%d)",
2015  list_length(parsedline->radiusidentifiers),
2016  list_length(parsedline->radiusservers)),
2017  errcontext("line %d of configuration file \"%s\"",
2018  line_num, file_name)));
2019  *err_msg = psprintf("the number of RADIUS identifiers (%d) must be 1 or the same as the number of RADIUS servers (%d)",
2020  list_length(parsedline->radiusidentifiers),
2021  list_length(parsedline->radiusservers));
2022  return NULL;
2023  }
2024  }
2025 
2026  /*
2027  * Enforce any parameters implied by other settings.
2028  */
2029  if (parsedline->auth_method == uaCert)
2030  {
2031  /*
2032  * For auth method cert, client certificate validation is mandatory,
2033  * and it implies the level of verify-full.
2034  */
2035  parsedline->clientcert = clientCertFull;
2036  }
2037 
2038  return parsedline;
2039 }
int errhint(const char *fmt,...)
Definition: elog.c:1319
const char * str
#define MANDATORY_AUTH_ARG(argvar, argname, authname)
Definition: hba.c:1258
static bool parse_hba_auth_opt(char *name, char *val, HbaLine *hbaline, int elevel, char **err_msg)
Definition: hba.c:2049
static int regcomp_auth_token(AuthToken *token, char *filename, int line_num, char **err_msg, int elevel)
Definition: hba.c:301
static AuthToken * copy_auth_token(AuthToken *in)
Definition: hba.c:288
@ ctHost
Definition: hba.h:60
@ uaBSD
Definition: hba.h:37
@ uaPassword
Definition: hba.h:31
@ uaMD5
Definition: hba.h:32
@ uaReject
Definition: hba.h:27
@ uaSCRAM
Definition: hba.h:33
@ uaTrust
Definition: hba.h:29
static int list_length(const List *l)
Definition: pg_list.h:152
static ListCell * list_head(const List *l)
Definition: pg_list.h:128
#define linitial(l)
Definition: pg_list.h:178
static ListCell * lnext(const List *l, const ListCell *c)
Definition: pg_list.h:343
bool EnableSSL
Definition: postmaster.c:225
int addrlen
Definition: hba.h:103
int masklen
Definition: hba.h:105
char * rawline
Definition: hba.h:98
int length
Definition: pg_list.h:56
char * raw_line
Definition: hba.h:163
int line_num
Definition: hba.h:162
char * file_name
Definition: hba.h:161
List * fields
Definition: hba.h:160

References HbaLine::addr, HbaLine::addrlen, Assert, HbaLine::auth_method, HbaLine::clientcert, clientCertFull, HbaLine::compat_realm, HbaLine::conntype, copy_auth_token(), ctHost, ctHostGSS, ctHostNoGSS, ctHostNoSSL, ctHostSSL, ctLocal, HbaLine::databases, EnableSSL, ereport, TokenizedAuthLine::err_msg, errcode(), errcontext, errhint(), errmsg(), TokenizedAuthLine::fields, TokenizedAuthLine::file_name, gai_strerror(), 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, TokenizedAuthLine::line_num, HbaLine::linenumber, linitial, list_head(), list_length(), lnext(), 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, TokenizedAuthLine::raw_line, HbaLine::rawline, regcomp_auth_token(), HbaLine::roles, HbaLine::sourcefile, str, token, token_is_keyword, uaBSD, uaCert, uaGSS, uaIdent, uaLDAP, uaMD5, uaPAM, uaPassword, uaPeer, uaRADIUS, uaReject, uaSCRAM, uaSSPI, uaTrust, HbaLine::upn_username, and val.

Referenced by fill_hba_view(), and load_hba().

◆ parse_ident_line()

IdentLine* parse_ident_line ( TokenizedAuthLine tok_line,
int  elevel 
)

Definition at line 2689 of file hba.c.

2690 {
2691  int line_num = tok_line->line_num;
2692  char *file_name = tok_line->file_name;
2693  char **err_msg = &tok_line->err_msg;
2694  ListCell *field;
2695  List *tokens;
2696  AuthToken *token;
2697  IdentLine *parsedline;
2698 
2699  Assert(tok_line->fields != NIL);
2700  field = list_head(tok_line->fields);
2701 
2702  parsedline = palloc0(sizeof(IdentLine));
2703  parsedline->linenumber = line_num;
2704 
2705  /* Get the map token (must exist) */
2706  tokens = lfirst(field);
2707  IDENT_MULTI_VALUE(tokens);
2708  token = linitial(tokens);
2709  parsedline->usermap = pstrdup(token->string);
2710 
2711  /* Get the ident user token */
2712  field = lnext(tok_line->fields, field);
2713  IDENT_FIELD_ABSENT(field);
2714  tokens = lfirst(field);
2715  IDENT_MULTI_VALUE(tokens);
2716  token = linitial(tokens);
2717 
2718  /* Copy the ident user token */
2719  parsedline->system_user = copy_auth_token(token);
2720 
2721  /* Get the PG rolename token */
2722  field = lnext(tok_line->fields, field);
2723  IDENT_FIELD_ABSENT(field);
2724  tokens = lfirst(field);
2725  IDENT_MULTI_VALUE(tokens);
2726  token = linitial(tokens);
2727  parsedline->pg_user = copy_auth_token(token);
2728 
2729  /*
2730  * Now that the field validation is done, compile a regex from the user
2731  * tokens, if necessary.
2732  */
2733  if (regcomp_auth_token(parsedline->system_user, file_name, line_num,
2734  err_msg, elevel))
2735  {
2736  /* err_msg includes the error to report */
2737  return NULL;
2738  }
2739 
2740  if (regcomp_auth_token(parsedline->pg_user, file_name, line_num,
2741  err_msg, elevel))
2742  {
2743  /* err_msg includes the error to report */
2744  return NULL;
2745  }
2746 
2747  return parsedline;
2748 }
#define IDENT_FIELD_ABSENT(field)
Definition: hba.c:1282
#define IDENT_MULTI_VALUE(tokens)
Definition: hba.c:1295
int linenumber
Definition: hba.h:142

References Assert, copy_auth_token(), TokenizedAuthLine::err_msg, TokenizedAuthLine::fields, TokenizedAuthLine::file_name, IDENT_FIELD_ABSENT, IDENT_MULTI_VALUE, lfirst, TokenizedAuthLine::line_num, IdentLine::linenumber, linitial, list_head(), lnext(), NIL, palloc0(), IdentLine::pg_user, pstrdup(), regcomp_auth_token(), IdentLine::system_user, token, and IdentLine::usermap.

Referenced by fill_ident_view(), and load_ident().

◆ pg_isblank()

bool pg_isblank ( const char  c)

Definition at line 144 of file hba.c.

145 {
146  return c == ' ' || c == '\t' || c == '\r';
147 }

Referenced by interpret_ident_response(), and next_token().

◆ regcomp_auth_token()

static int regcomp_auth_token ( AuthToken token,
char *  filename,
int  line_num,
char **  err_msg,
int  elevel 
)
static

Definition at line 301 of file hba.c.

303 {
304  pg_wchar *wstr;
305  int wlen;
306  int rc;
307 
308  Assert(token->regex == NULL);
309 
310  if (token->string[0] != '/')
311  return 0; /* nothing to compile */
312 
313  token->regex = (regex_t *) palloc0(sizeof(regex_t));
314  wstr = palloc((strlen(token->string + 1) + 1) * sizeof(pg_wchar));
315  wlen = pg_mb2wchar_with_len(token->string + 1,
316  wstr, strlen(token->string + 1));
317 
318  rc = pg_regcomp(token->regex, wstr, wlen, REG_ADVANCED, C_COLLATION_OID);
319 
320  if (rc)
321  {
322  char errstr[100];
323 
324  pg_regerror(rc, token->regex, errstr, sizeof(errstr));
325  ereport(elevel,
326  (errcode(ERRCODE_INVALID_REGULAR_EXPRESSION),
327  errmsg("invalid regular expression \"%s\": %s",
328  token->string + 1, errstr),
329  errcontext("line %d of configuration file \"%s\"",
330  line_num, filename)));
331 
332  *err_msg = psprintf("invalid regular expression \"%s\": %s",
333  token->string + 1, errstr);
334  }
335 
336  pfree(wstr);
337  return rc;
338 }
unsigned int pg_wchar
Definition: mbprint.c:31
int pg_mb2wchar_with_len(const char *from, pg_wchar *to, int len)
Definition: mbutils.c:986
void * palloc(Size size)
Definition: mcxt.c:1316
int pg_regcomp(regex_t *re, const chr *string, size_t len, int flags, Oid collation)
Definition: regcomp.c:370
#define REG_ADVANCED
Definition: regex.h:103
Definition: regex.h:56

References Assert, ereport, errcode(), errcontext, errmsg(), filename, palloc(), palloc0(), pfree(), pg_mb2wchar_with_len(), pg_regcomp(), pg_regerror(), psprintf(), REG_ADVANCED, and token.

Referenced by parse_hba_line(), and parse_ident_line().

◆ regexec_auth_token()

static int regexec_auth_token ( const char *  match,
AuthToken token,
size_t  nmatch,
regmatch_t  pmatch[] 
)
static

Definition at line 346 of file hba.c.

348 {
349  pg_wchar *wmatchstr;
350  int wmatchlen;
351  int r;
352 
353  Assert(token->string[0] == '/' && token->regex);
354 
355  wmatchstr = palloc((strlen(match) + 1) * sizeof(pg_wchar));
356  wmatchlen = pg_mb2wchar_with_len(match, wmatchstr, strlen(match));
357 
358  r = pg_regexec(token->regex, wmatchstr, wmatchlen, 0, NULL, nmatch, pmatch, 0);
359 
360  pfree(wmatchstr);
361  return r;
362 }
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:185

References Assert, palloc(), pfree(), pg_mb2wchar_with_len(), pg_regexec(), and token.

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

◆ StaticAssertDecl()

StaticAssertDecl ( lengthof(UserAuthName = =USER_AUTH_LAST+1,
"UserAuthName []must match the UserAuth enum"   
)

◆ tokenize_auth_file()

void tokenize_auth_file ( const char *  filename,
FILE *  file,
List **  tok_lines,
int  elevel,
int  depth 
)

Definition at line 686 of file hba.c.

688 {
689  int line_number = 1;
691  MemoryContext linecxt;
692  MemoryContext funccxt; /* context of this function's caller */
693  ErrorContextCallback tokenerrcontext;
694  tokenize_error_callback_arg callback_arg;
695 
697 
698  callback_arg.filename = filename;
699  callback_arg.linenum = line_number;
700 
701  tokenerrcontext.callback = tokenize_error_callback;
702  tokenerrcontext.arg = (void *) &callback_arg;
703  tokenerrcontext.previous = error_context_stack;
704  error_context_stack = &tokenerrcontext;
705 
706  /*
707  * Do all the local tokenization in its own context, to ease the cleanup
708  * of any memory allocated while tokenizing.
709  */
711  "tokenize_auth_file",
713  funccxt = MemoryContextSwitchTo(linecxt);
714 
716 
717  if (depth == CONF_FILE_START_DEPTH)
718  *tok_lines = NIL;
719 
720  while (!feof(file) && !ferror(file))
721  {
722  TokenizedAuthLine *tok_line;
723  MemoryContext oldcxt;
724  char *lineptr;
725  List *current_line = NIL;
726  char *err_msg = NULL;
727  int last_backslash_buflen = 0;
728  int continuations = 0;
729 
730  /* Collect the next input line, handling backslash continuations */
732 
733  while (pg_get_line_append(file, &buf, NULL))
734  {
735  /* Strip trailing newline, including \r in case we're on Windows */
736  buf.len = pg_strip_crlf(buf.data);
737 
738  /*
739  * Check for backslash continuation. The backslash must be after
740  * the last place we found a continuation, else two backslashes
741  * followed by two \n's would behave surprisingly.
742  */
743  if (buf.len > last_backslash_buflen &&
744  buf.data[buf.len - 1] == '\\')
745  {
746  /* Continuation, so strip it and keep reading */
747  buf.data[--buf.len] = '\0';
748  last_backslash_buflen = buf.len;
749  continuations++;
750  continue;
751  }
752 
753  /* Nope, so we have the whole line */
754  break;
755  }
756 
757  if (ferror(file))
758  {
759  /* I/O error! */
760  int save_errno = errno;
761 
762  ereport(elevel,
764  errmsg("could not read file \"%s\": %m", filename)));
765  err_msg = psprintf("could not read file \"%s\": %s",
766  filename, strerror(save_errno));
767  break;
768  }
769 
770  /* Parse fields */
771  lineptr = buf.data;
772  while (*lineptr && err_msg == NULL)
773  {
774  List *current_field;
775 
776  current_field = next_field_expand(filename, &lineptr,
777  elevel, depth, &err_msg);
778  /* add field to line, unless we are at EOL or comment start */
779  if (current_field != NIL)
780  {
781  /*
782  * lappend() may do its own allocations, so move to the
783  * context for the list of tokens.
784  */
786  current_line = lappend(current_line, current_field);
787  MemoryContextSwitchTo(oldcxt);
788  }
789  }
790 
791  /*
792  * Reached EOL; no need to emit line to TokenizedAuthLine list if it's
793  * boring.
794  */
795  if (current_line == NIL && err_msg == NULL)
796  goto next_line;
797 
798  /* If the line is valid, check if that's an include directive */
799  if (err_msg == NULL && list_length(current_line) == 2)
800  {
801  AuthToken *first,
802  *second;
803 
804  first = linitial(linitial_node(List, current_line));
805  second = linitial(lsecond_node(List, current_line));
806 
807  if (strcmp(first->string, "include") == 0)
808  {
809  tokenize_include_file(filename, second->string, tok_lines,
810  elevel, depth + 1, false, &err_msg);
811 
812  if (err_msg)
813  goto process_line;
814 
815  /*
816  * tokenize_auth_file() has taken care of creating the
817  * TokenizedAuthLines.
818  */
819  goto next_line;
820  }
821  else if (strcmp(first->string, "include_dir") == 0)
822  {
823  char **filenames;
824  char *dir_name = second->string;
825  int num_filenames;
826  StringInfoData err_buf;
827 
828  filenames = GetConfFilesInDir(dir_name, filename, elevel,
829  &num_filenames, &err_msg);
830 
831  if (!filenames)
832  {
833  /* the error is in err_msg, so create an entry */
834  goto process_line;
835  }
836 
837  initStringInfo(&err_buf);
838  for (int i = 0; i < num_filenames; i++)
839  {
840  tokenize_include_file(filename, filenames[i], tok_lines,
841  elevel, depth + 1, false, &err_msg);
842  /* cumulate errors if any */
843  if (err_msg)
844  {
845  if (err_buf.len > 0)
846  appendStringInfoChar(&err_buf, '\n');
847  appendStringInfoString(&err_buf, err_msg);
848  }
849  }
850 
851  /* clean up things */
852  for (int i = 0; i < num_filenames; i++)
853  pfree(filenames[i]);
854  pfree(filenames);
855 
856  /*
857  * If there were no errors, the line is fully processed,
858  * bypass the general TokenizedAuthLine processing.
859  */
860  if (err_buf.len == 0)
861  goto next_line;
862 
863  /* Otherwise, process the cumulated errors, if any. */
864  err_msg = err_buf.data;
865  goto process_line;
866  }
867  else if (strcmp(first->string, "include_if_exists") == 0)
868  {
869 
870  tokenize_include_file(filename, second->string, tok_lines,
871  elevel, depth + 1, true, &err_msg);
872  if (err_msg)
873  goto process_line;
874 
875  /*
876  * tokenize_auth_file() has taken care of creating the
877  * TokenizedAuthLines.
878  */
879  goto next_line;
880  }
881  }
882 
883 process_line:
884 
885  /*
886  * General processing: report the error if any and emit line to the
887  * TokenizedAuthLine. This is saved in the memory context dedicated
888  * to this list.
889  */
891  tok_line = (TokenizedAuthLine *) palloc0(sizeof(TokenizedAuthLine));
892  tok_line->fields = current_line;
893  tok_line->file_name = pstrdup(filename);
894  tok_line->line_num = line_number;
895  tok_line->raw_line = pstrdup(buf.data);
896  tok_line->err_msg = err_msg ? pstrdup(err_msg) : NULL;
897  *tok_lines = lappend(*tok_lines, tok_line);
898  MemoryContextSwitchTo(oldcxt);
899 
900 next_line:
901  line_number += continuations + 1;
902  callback_arg.linenum = line_number;
903  }
904 
905  MemoryContextSwitchTo(funccxt);
906  MemoryContextDelete(linecxt);
907 
908  error_context_stack = tokenerrcontext.previous;
909 }
char ** GetConfFilesInDir(const char *includedir, const char *calling_file, int elevel, int *num_filenames, char **err_msg)
Definition: conffiles.c:70
ErrorContextCallback * error_context_stack
Definition: elog.c:94
static List * next_field_expand(const char *filename, char **lineptr, int elevel, int depth, char **err_msg)
Definition: hba.c:379
static void tokenize_include_file(const char *outer_filename, const char *inc_filename, List **tok_lines, int elevel, int depth, bool missing_ok, char **err_msg)
Definition: hba.c:438
static void tokenize_error_callback(void *arg)
Definition: hba.c:657
bool pg_get_line_append(FILE *stream, StringInfo buf, PromptInterruptContext *prompt_ctx)
Definition: pg_get_line.c:124
#define linitial_node(type, l)
Definition: pg_list.h:181
#define lsecond_node(type, l)
Definition: pg_list.h:186
int pg_strip_crlf(char *str)
Definition: string.c:155
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:182
struct ErrorContextCallback * previous
Definition: elog.h:295
void(* callback)(void *arg)
Definition: elog.h:296
const char * filename
Definition: hba.c:64

References ALLOCSET_SMALL_SIZES, AllocSetContextCreate, appendStringInfoChar(), appendStringInfoString(), ErrorContextCallback::arg, Assert, buf, ErrorContextCallback::callback, CONF_FILE_START_DEPTH, CurrentMemoryContext, StringInfoData::data, ereport, TokenizedAuthLine::err_msg, errcode_for_file_access(), errmsg(), error_context_stack, TokenizedAuthLine::fields, TokenizedAuthLine::file_name, tokenize_error_callback_arg::filename, filename, GetConfFilesInDir(), i, initStringInfo(), lappend(), StringInfoData::len, TokenizedAuthLine::line_num, tokenize_error_callback_arg::linenum, linitial, linitial_node, list_length(), lsecond_node, MemoryContextDelete(), MemoryContextSwitchTo(), next_field_expand(), NIL, palloc0(), pfree(), pg_get_line_append(), pg_strip_crlf(), ErrorContextCallback::previous, psprintf(), pstrdup(), TokenizedAuthLine::raw_line, resetStringInfo(), strerror, AuthToken::string, tokenize_context, tokenize_error_callback(), and tokenize_include_file().

Referenced by fill_hba_view(), fill_ident_view(), load_hba(), load_ident(), tokenize_expand_file(), and tokenize_include_file().

◆ tokenize_error_callback()

static void tokenize_error_callback ( void *  arg)
static

Definition at line 657 of file hba.c.

658 {
660 
661  errcontext("line %d of configuration file \"%s\"",
662  callback_arg->linenum, callback_arg->filename);
663 }
void * arg

References arg, errcontext, tokenize_error_callback_arg::filename, and tokenize_error_callback_arg::linenum.

Referenced by tokenize_auth_file().

◆ tokenize_expand_file()

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

Definition at line 493 of file hba.c.

499 {
500  char *inc_fullname;
501  FILE *inc_file;
502  List *inc_lines = NIL;
503  ListCell *inc_line;
504 
505  inc_fullname = AbsoluteConfigLocation(inc_filename, outer_filename);
506  inc_file = open_auth_file(inc_fullname, elevel, depth, err_msg);
507 
508  if (inc_file == NULL)
509  {
510  /* error already logged */
511  pfree(inc_fullname);
512  return tokens;
513  }
514 
515  /*
516  * There is possible recursion here if the file contains @ or an include
517  * record.
518  */
519  tokenize_auth_file(inc_fullname, inc_file, &inc_lines, elevel,
520  depth);
521 
522  pfree(inc_fullname);
523 
524  /*
525  * Move all the tokens found in the file to the tokens list. These are
526  * already saved in tokenize_context.
527  */
528  foreach(inc_line, inc_lines)
529  {
530  TokenizedAuthLine *tok_line = (TokenizedAuthLine *) lfirst(inc_line);
531  ListCell *inc_field;
532 
533  /* If any line has an error, propagate that up to caller */
534  if (tok_line->err_msg)
535  {
536  *err_msg = pstrdup(tok_line->err_msg);
537  break;
538  }
539 
540  foreach(inc_field, tok_line->fields)
541  {
542  List *inc_tokens = lfirst(inc_field);
543  ListCell *inc_token;
544 
545  foreach(inc_token, inc_tokens)
546  {
547  AuthToken *token = lfirst(inc_token);
548  MemoryContext oldcxt;
549 
550  /*
551  * lappend() may do its own allocations, so move to the
552  * context for the list of tokens.
553  */
555  tokens = lappend(tokens, token);
556  MemoryContextSwitchTo(oldcxt);
557  }
558  }
559  }
560 
561  free_auth_file(inc_file, depth);
562  return tokens;
563 }
char * AbsoluteConfigLocation(const char *location, const char *calling_file)
Definition: conffiles.c:36

References AbsoluteConfigLocation(), TokenizedAuthLine::err_msg, TokenizedAuthLine::fields, free_auth_file(), lappend(), lfirst, MemoryContextSwitchTo(), NIL, open_auth_file(), pfree(), pstrdup(), token, tokenize_auth_file(), and tokenize_context.

Referenced by next_field_expand().

◆ tokenize_include_file()

static void tokenize_include_file ( const char *  outer_filename,
const char *  inc_filename,
List **  tok_lines,
int  elevel,
int  depth,
bool  missing_ok,
char **  err_msg 
)
static

Definition at line 438 of file hba.c.

445 {
446  char *inc_fullname;
447  FILE *inc_file;
448 
449  inc_fullname = AbsoluteConfigLocation(inc_filename, outer_filename);
450  inc_file = open_auth_file(inc_fullname, elevel, depth, err_msg);
451 
452  if (!inc_file)
453  {
454  if (errno == ENOENT && missing_ok)
455  {
456  ereport(elevel,
457  (errmsg("skipping missing authentication file \"%s\"",
458  inc_fullname)));
459  *err_msg = NULL;
460  pfree(inc_fullname);
461  return;
462  }
463 
464  /* error in err_msg, so leave and report */
465  pfree(inc_fullname);
466  Assert(err_msg);
467  return;
468  }
469 
470  tokenize_auth_file(inc_fullname, inc_file, tok_lines, elevel,
471  depth);
472  free_auth_file(inc_file, depth);
473  pfree(inc_fullname);
474 }

References AbsoluteConfigLocation(), Assert, ereport, errmsg(), free_auth_file(), open_auth_file(), pfree(), and tokenize_auth_file().

Referenced by tokenize_auth_file().

Variable Documentation

◆ parsed_hba_context

MemoryContext parsed_hba_context = NULL
static

Definition at line 86 of file hba.c.

Referenced by load_hba().

◆ parsed_hba_lines

List* parsed_hba_lines = NIL
static

Definition at line 85 of file hba.c.

Referenced by check_hba(), and load_hba().

◆ parsed_ident_context

MemoryContext parsed_ident_context = NULL
static

Definition at line 93 of file hba.c.

Referenced by load_ident().

◆ parsed_ident_lines

List* parsed_ident_lines = NIL
static

Definition at line 92 of file hba.c.

Referenced by check_usermap(), and load_ident().

◆ tokenize_context

MemoryContext tokenize_context = NULL
static

◆ 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 101 of file hba.c.

Referenced by hba_authname().