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 "access/htup_details.h"
#include "catalog/pg_collation.h"
#include "catalog/pg_type.h"
#include "common/ip.h"
#include "common/string.h"
#include "funcapi.h"
#include "libpq/ifaddr.h"
#include "libpq/libpq.h"
#include "miscadmin.h"
#include "postmaster/postmaster.h"
#include "regex/regex.h"
#include "replication/walsender.h"
#include "storage/fd.h"
#include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/conffiles.h"
#include "utils/guc.h"
#include "utils/lsyscache.h"
#include "utils/memutils.h"
#include "utils/varlena.h"
Include dependency graph for hba.c:

Go to the source code of this file.

Data Structures

struct  check_network_data
 
struct  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:858
int errmsg(const char *fmt,...)
Definition: elog.c:1069
#define errcontext
Definition: elog.h:196
char * pstrdup(const char *in)
Definition: mcxt.c:1644

Definition at line 1287 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 1300 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:91
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46

Definition at line 1243 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 1263 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 1257 of file hba.c.

◆ token_has_regexp

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

Definition at line 73 of file hba.c.

◆ token_is_keyword

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

Definition at line 75 of file hba.c.

◆ token_is_member_check

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

Definition at line 74 of file hba.c.

◆ token_matches

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

Definition at line 76 of file hba.c.

◆ token_matches_insensitive

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

Definition at line 77 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 992 of file hba.c.

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

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

2475 {
2476  Oid roleid;
2477  ListCell *line;
2478  HbaLine *hba;
2479 
2480  /* Get the target role's OID. Note we do not error out for bad role. */
2481  roleid = get_role_oid(port->user_name, true);
2482 
2483  foreach(line, parsed_hba_lines)
2484  {
2485  hba = (HbaLine *) lfirst(line);
2486 
2487  /* Check connection type */
2488  if (hba->conntype == ctLocal)
2489  {
2490  if (port->raddr.addr.ss_family != AF_UNIX)
2491  continue;
2492  }
2493  else
2494  {
2495  if (port->raddr.addr.ss_family == AF_UNIX)
2496  continue;
2497 
2498  /* Check SSL state */
2499  if (port->ssl_in_use)
2500  {
2501  /* Connection is SSL, match both "host" and "hostssl" */
2502  if (hba->conntype == ctHostNoSSL)
2503  continue;
2504  }
2505  else
2506  {
2507  /* Connection is not SSL, match both "host" and "hostnossl" */
2508  if (hba->conntype == ctHostSSL)
2509  continue;
2510  }
2511 
2512  /* Check GSSAPI state */
2513 #ifdef ENABLE_GSS
2514  if (port->gss && port->gss->enc &&
2515  hba->conntype == ctHostNoGSS)
2516  continue;
2517  else if (!(port->gss && port->gss->enc) &&
2518  hba->conntype == ctHostGSS)
2519  continue;
2520 #else
2521  if (hba->conntype == ctHostGSS)
2522  continue;
2523 #endif
2524 
2525  /* Check IP address */
2526  switch (hba->ip_cmp_method)
2527  {
2528  case ipCmpMask:
2529  if (hba->hostname)
2530  {
2531  if (!check_hostname(port,
2532  hba->hostname))
2533  continue;
2534  }
2535  else
2536  {
2537  if (!check_ip(&port->raddr,
2538  (struct sockaddr *) &hba->addr,
2539  (struct sockaddr *) &hba->mask))
2540  continue;
2541  }
2542  break;
2543  case ipCmpAll:
2544  break;
2545  case ipCmpSameHost:
2546  case ipCmpSameNet:
2547  if (!check_same_host_or_net(&port->raddr,
2548  hba->ip_cmp_method))
2549  continue;
2550  break;
2551  default:
2552  /* shouldn't get here, but deem it no-match if so */
2553  continue;
2554  }
2555  } /* != ctLocal */
2556 
2557  /* Check database and role */
2558  if (!check_db(port->database_name, port->user_name, roleid,
2559  hba->databases))
2560  continue;
2561 
2562  if (!check_role(port->user_name, roleid, hba->roles, false))
2563  continue;
2564 
2565  /* Found a record that matched! */
2566  port->hba = hba;
2567  return;
2568  }
2569 
2570  /* If no matching entry was found, then implicitly reject. */
2571  hba = palloc0(sizeof(HbaLine));
2573  port->hba = hba;
2574 }
Oid get_role_oid(const char *rolname, bool missing_ok)
Definition: acl.c:5247
static bool check_role(const char *role, Oid roleid, List *tokens, bool case_insensitive)
Definition: hba.c:953
static bool check_ip(SockAddr *raddr, struct sockaddr *addr, struct sockaddr *mask)
Definition: hba.c:1168
static bool check_same_host_or_net(SockAddr *raddr, IPCompareMethod method)
Definition: hba.c:1209
static bool check_hostname(hbaPort *port, const char *hostname)
Definition: hba.c:1077
static List * parsed_hba_lines
Definition: hba.c:90
static bool check_db(const char *dbname, const char *role, Oid roleid, List *tokens)
Definition: hba.c:992
@ 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:1257
static int port
Definition: pg_regress.c:109
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 1077 of file hba.c.

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

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

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

1169 {
1170  if (raddr->addr.ss_family == addr->sa_family &&
1171  pg_range_sockaddr(&raddr->addr,
1172  (struct sockaddr_storage *) addr,
1173  (struct sockaddr_storage *) mask))
1174  return true;
1175  return false;
1176 }
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 1182 of file hba.c.

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

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

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

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

1210 {
1211  check_network_data cn;
1212 
1213  cn.method = method;
1214  cn.raddr = raddr;
1215  cn.result = false;
1216 
1217  errno = 0;
1219  {
1220  ereport(LOG,
1221  (errmsg("error enumerating network interfaces: %m")));
1222  return false;
1223  }
1224 
1225  return cn.result;
1226 }
static void check_network_callback(struct sockaddr *addr, struct sockaddr *netmask, void *cb_data)
Definition: hba.c:1182
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 2909 of file hba.c.

2913 {
2914  bool found_entry = false,
2915  error = false;
2916 
2917  if (usermap_name == NULL || usermap_name[0] == '\0')
2918  {
2919  if (case_insensitive)
2920  {
2921  if (pg_strcasecmp(pg_user, system_user) == 0)
2922  return STATUS_OK;
2923  }
2924  else
2925  {
2926  if (strcmp(pg_user, system_user) == 0)
2927  return STATUS_OK;
2928  }
2929  ereport(LOG,
2930  (errmsg("provided user name (%s) and authenticated user name (%s) do not match",
2931  pg_user, system_user)));
2932  return STATUS_ERROR;
2933  }
2934  else
2935  {
2936  ListCell *line_cell;
2937 
2938  foreach(line_cell, parsed_ident_lines)
2939  {
2940  check_ident_usermap(lfirst(line_cell), usermap_name,
2941  pg_user, system_user, case_insensitive,
2942  &found_entry, &error);
2943  if (found_entry || error)
2944  break;
2945  }
2946  }
2947  if (!found_entry && !error)
2948  {
2949  ereport(LOG,
2950  (errmsg("no match in usermap \"%s\" for user \"%s\" authenticated as \"%s\"",
2951  usermap_name, pg_user, system_user)));
2952  }
2953  return found_entry ? STATUS_OK : STATUS_ERROR;
2954 }
#define STATUS_OK
Definition: c.h:1182
#define STATUS_ERROR
Definition: c.h:1183
static List * parsed_ident_lines
Definition: hba.c:97
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:2762
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 293 of file hba.c.

294 {
295  AuthToken *out = make_auth_token(in->string, in->quoted);
296 
297  return out;
298 }
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 575 of file hba.c.

576 {
577  FreeFile(file);
578 
579  /* If this is the last cleanup, remove the tokenization context */
580  if (depth == CONF_FILE_START_DEPTH)
581  {
583  tokenize_context = NULL;
584  }
585 }
#define CONF_FILE_START_DEPTH
Definition: conffiles.h:17
int FreeFile(FILE *file)
Definition: fd.c:2726
static MemoryContext tokenize_context
Definition: hba.c:84
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:403

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

284 {
285  if (token_has_regexp(token))
286  pg_regfree(token->regex);
287 }
#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 3066 of file hba.c.

3067 {
3068  return UserAuthName[auth_method];
3069 }
static const char *const UserAuthName[]
Definition: hba.c:106

References UserAuthName.

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

◆ hba_getauthmethod()

void hba_getauthmethod ( hbaPort port)

Definition at line 3053 of file hba.c.

3054 {
3055  check_hba(port);
3056 }
static void check_hba(hbaPort *port)
Definition: hba.c:2474

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

1058 {
1059  if (pattern[0] == '.') /* suffix match */
1060  {
1061  size_t plen = strlen(pattern);
1062  size_t hlen = strlen(actual_hostname);
1063 
1064  if (hlen < plen)
1065  return false;
1066 
1067  return (pg_strcasecmp(pattern, actual_hostname + (hlen - plen)) == 0);
1068  }
1069  else
1070  return (pg_strcasecmp(pattern, actual_hostname) == 0);
1071 }

References pg_strcasecmp().

Referenced by check_hostname().

◆ ipv4eq()

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

Definition at line 1036 of file hba.c.

1037 {
1038  return (a->sin_addr.s_addr == b->sin_addr.s_addr);
1039 }
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 1042 of file hba.c.

1043 {
1044  int i;
1045 
1046  for (i = 0; i < 16; i++)
1047  if (a->sin6_addr.s6_addr[i] != b->sin6_addr.s6_addr[i])
1048  return false;
1049 
1050  return true;
1051 }
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 924 of file hba.c.

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

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

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

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

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

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

386 {
388  bool trailing_comma;
389  bool initial_quote;
390  List *tokens = NIL;
391 
393 
394  do
395  {
396  if (!next_token(lineptr, &buf,
397  &initial_quote, &trailing_comma))
398  break;
399 
400  /* Is this referencing a file? */
401  if (!initial_quote && buf.len > 1 && buf.data[0] == '@')
402  tokens = tokenize_expand_file(tokens, filename, buf.data + 1,
403  elevel, depth + 1, err_msg);
404  else
405  {
406  MemoryContext oldcxt;
407 
408  /*
409  * lappend() may do its own allocations, so move to the context
410  * for the list of tokens.
411  */
413  tokens = lappend(tokens, make_auth_token(buf.data, initial_quote));
414  MemoryContextSwitchTo(oldcxt);
415  }
416  } while (trailing_comma && (*err_msg == NULL));
417 
418  pfree(buf.data);
419 
420  return tokens;
421 }
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:498
static bool next_token(char **lineptr, StringInfo buf, bool *initial_quote, bool *terminating_comma)
Definition: hba.c:190
static char * filename
Definition: pg_dumpall.c:119
static char * buf
Definition: pg_test_fsync.c:67
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 190 of file hba.c.

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

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

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

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

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

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

150 {
151  return c == ' ' || c == '\t' || c == '\r';
152 }

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

308 {
309  pg_wchar *wstr;
310  int wlen;
311  int rc;
312 
313  Assert(token->regex == NULL);
314 
315  if (token->string[0] != '/')
316  return 0; /* nothing to compile */
317 
318  token->regex = (regex_t *) palloc0(sizeof(regex_t));
319  wstr = palloc((strlen(token->string + 1) + 1) * sizeof(pg_wchar));
320  wlen = pg_mb2wchar_with_len(token->string + 1,
321  wstr, strlen(token->string + 1));
322 
323  rc = pg_regcomp(token->regex, wstr, wlen, REG_ADVANCED, C_COLLATION_OID);
324 
325  if (rc)
326  {
327  char errstr[100];
328 
329  pg_regerror(rc, token->regex, errstr, sizeof(errstr));
330  ereport(elevel,
331  (errcode(ERRCODE_INVALID_REGULAR_EXPRESSION),
332  errmsg("invalid regular expression \"%s\": %s",
333  token->string + 1, errstr),
334  errcontext("line %d of configuration file \"%s\"",
335  line_num, filename)));
336 
337  *err_msg = psprintf("invalid regular expression \"%s\": %s",
338  token->string + 1, errstr);
339  }
340 
341  pfree(wstr);
342  return rc;
343 }
unsigned int pg_wchar
Definition: mbprint.c:31
int pg_mb2wchar_with_len(const char *from, pg_wchar *to, int len)
Definition: mbutils.c:987
void * palloc(Size size)
Definition: mcxt.c:1226
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 351 of file hba.c.

353 {
354  pg_wchar *wmatchstr;
355  int wmatchlen;
356  int r;
357 
358  Assert(token->string[0] == '/' && token->regex);
359 
360  wmatchstr = palloc((strlen(match) + 1) * sizeof(pg_wchar));
361  wmatchlen = pg_mb2wchar_with_len(match, wmatchstr, strlen(match));
362 
363  r = pg_regexec(token->regex, wmatchstr, wmatchlen, 0, NULL, nmatch, pmatch, 0);
364 
365  pfree(wmatchstr);
366  return r;
367 }
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 691 of file hba.c.

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

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

663 {
665 
666  errcontext("line %d of configuration file \"%s\"",
667  callback_arg->linenum, callback_arg->filename);
668 }
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 498 of file hba.c.

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

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

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

Referenced by load_hba().

◆ parsed_hba_lines

List* parsed_hba_lines = NIL
static

Definition at line 90 of file hba.c.

Referenced by check_hba(), and load_hba().

◆ parsed_ident_context

MemoryContext parsed_ident_context = NULL
static

Definition at line 98 of file hba.c.

Referenced by load_ident().

◆ parsed_ident_lines

List* parsed_ident_lines = NIL
static

Definition at line 97 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 106 of file hba.c.

Referenced by hba_authname().