PostgreSQL Source Code  git master
hba.h File Reference
#include "libpq/pqcomm.h"
#include "nodes/pg_list.h"
#include "regex/regex.h"
Include dependency graph for hba.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  HbaLine
 
struct  IdentLine
 
struct  AuthToken
 
struct  TokenizedAuthLine
 

Macros

#define USER_AUTH_LAST   uaPeer /* Must be last value of this enum */
 

Typedefs

typedef enum UserAuth UserAuth
 
typedef enum IPCompareMethod IPCompareMethod
 
typedef enum ConnType ConnType
 
typedef enum ClientCertMode ClientCertMode
 
typedef enum ClientCertName ClientCertName
 
typedef struct HbaLine HbaLine
 
typedef struct IdentLine IdentLine
 
typedef struct AuthToken AuthToken
 
typedef struct TokenizedAuthLine TokenizedAuthLine
 
typedef struct Port hbaPort
 

Enumerations

enum  UserAuth {
  uaReject , uaImplicitReject , uaTrust , uaIdent ,
  uaPassword , uaMD5 , uaSCRAM , uaGSS ,
  uaSSPI , uaPAM , uaBSD , uaLDAP ,
  uaCert , uaRADIUS
}
 
enum  IPCompareMethod { ipCmpMask , ipCmpSameHost , ipCmpSameNet , ipCmpAll }
 
enum  ConnType {
  ctLocal , ctHost , ctHostSSL , ctHostNoSSL ,
  ctHostGSS , ctHostNoGSS
}
 
enum  ClientCertMode { clientCertOff , clientCertCA , clientCertFull }
 
enum  ClientCertName { clientCertCN , clientCertDN }
 

Functions

bool load_hba (void)
 
bool load_ident (void)
 
const char * hba_authname (UserAuth auth_method)
 
void hba_getauthmethod (hbaPort *port)
 
int check_usermap (const char *usermap_name, const char *pg_role, const char *auth_user, bool case_sensitive)
 
HbaLineparse_hba_line (TokenizedAuthLine *tok_line, int elevel)
 
IdentLineparse_ident_line (TokenizedAuthLine *tok_line, int elevel)
 
bool pg_isblank (const char c)
 
MemoryContext tokenize_auth_file (const char *filename, FILE *file, List **tok_lines, int elevel)
 

Macro Definition Documentation

◆ USER_AUTH_LAST

#define USER_AUTH_LAST   uaPeer /* Must be last value of this enum */

Definition at line 42 of file hba.h.

Typedef Documentation

◆ AuthToken

typedef struct AuthToken AuthToken

◆ ClientCertMode

◆ ClientCertName

◆ ConnType

typedef enum ConnType ConnType

◆ HbaLine

typedef struct HbaLine HbaLine

◆ hbaPort

typedef struct Port hbaPort

Definition at line 1 of file hba.h.

◆ IdentLine

typedef struct IdentLine IdentLine

◆ IPCompareMethod

◆ TokenizedAuthLine

◆ UserAuth

typedef enum UserAuth UserAuth

Enumeration Type Documentation

◆ ClientCertMode

Enumerator
clientCertOff 
clientCertCA 
clientCertFull 

Definition at line 67 of file hba.h.

68 {
ClientCertMode
Definition: hba.h:68
@ clientCertOff
Definition: hba.h:69
@ clientCertFull
Definition: hba.h:71
@ clientCertCA
Definition: hba.h:70

◆ ClientCertName

Enumerator
clientCertCN 
clientCertDN 

Definition at line 74 of file hba.h.

75 {
ClientCertName
Definition: hba.h:75
@ clientCertDN
Definition: hba.h:77
@ clientCertCN
Definition: hba.h:76

◆ ConnType

enum ConnType
Enumerator
ctLocal 
ctHost 
ctHostSSL 
ctHostNoSSL 
ctHostGSS 
ctHostNoGSS 

Definition at line 57 of file hba.h.

58 {
59  ctLocal,
60  ctHost,
61  ctHostSSL,
63  ctHostGSS,
65 } ConnType;
ConnType
Definition: hba.h:58
@ ctHostNoGSS
Definition: hba.h:64
@ ctHostSSL
Definition: hba.h:61
@ ctHostNoSSL
Definition: hba.h:62
@ ctHost
Definition: hba.h:60
@ ctHostGSS
Definition: hba.h:63
@ ctLocal
Definition: hba.h:59

◆ IPCompareMethod

Enumerator
ipCmpMask 
ipCmpSameHost 
ipCmpSameNet 
ipCmpAll 

Definition at line 49 of file hba.h.

50 {
51  ipCmpMask,
54  ipCmpAll
IPCompareMethod
Definition: hba.h:50
@ ipCmpAll
Definition: hba.h:54
@ ipCmpSameNet
Definition: hba.h:53
@ ipCmpMask
Definition: hba.h:51
@ ipCmpSameHost
Definition: hba.h:52

◆ UserAuth

enum UserAuth
Enumerator
uaReject 
uaImplicitReject 
uaTrust 
uaIdent 
uaPassword 
uaMD5 
uaSCRAM 
uaGSS 
uaSSPI 
uaPAM 
uaBSD 
uaLDAP 
uaCert 
uaRADIUS 

Definition at line 25 of file hba.h.

26 {
27  uaReject,
28  uaImplicitReject, /* Not a user-visible option */
29  uaTrust,
30  uaIdent,
31  uaPassword,
32  uaMD5,
33  uaSCRAM,
34  uaGSS,
35  uaSSPI,
36  uaPAM,
37  uaBSD,
38  uaLDAP,
39  uaCert,
40  uaRADIUS,
41  uaPeer
42 #define USER_AUTH_LAST uaPeer /* Must be last value of this enum */
43 } UserAuth;
UserAuth
Definition: hba.h:26
@ uaBSD
Definition: hba.h:37
@ uaLDAP
Definition: hba.h:38
@ uaPAM
Definition: hba.h:36
@ uaPassword
Definition: hba.h:31
@ uaCert
Definition: hba.h:39
@ uaMD5
Definition: hba.h:32
@ uaReject
Definition: hba.h:27
@ uaGSS
Definition: hba.h:34
@ uaSCRAM
Definition: hba.h:33
@ uaImplicitReject
Definition: hba.h:28
@ uaRADIUS
Definition: hba.h:40
@ uaIdent
Definition: hba.h:30
@ uaTrust
Definition: hba.h:29
@ uaSSPI
Definition: hba.h:35

Function Documentation

◆ check_usermap()

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

Definition at line 2531 of file hba.c.

2535 {
2536  bool found_entry = false,
2537  error = false;
2538 
2539  if (usermap_name == NULL || usermap_name[0] == '\0')
2540  {
2541  if (case_insensitive)
2542  {
2543  if (pg_strcasecmp(pg_role, auth_user) == 0)
2544  return STATUS_OK;
2545  }
2546  else
2547  {
2548  if (strcmp(pg_role, auth_user) == 0)
2549  return STATUS_OK;
2550  }
2551  ereport(LOG,
2552  (errmsg("provided user name (%s) and authenticated user name (%s) do not match",
2553  pg_role, auth_user)));
2554  return STATUS_ERROR;
2555  }
2556  else
2557  {
2558  ListCell *line_cell;
2559 
2560  foreach(line_cell, parsed_ident_lines)
2561  {
2562  check_ident_usermap(lfirst(line_cell), usermap_name,
2563  pg_role, auth_user, case_insensitive,
2564  &found_entry, &error);
2565  if (found_entry || error)
2566  break;
2567  }
2568  }
2569  if (!found_entry && !error)
2570  {
2571  ereport(LOG,
2572  (errmsg("no match in usermap \"%s\" for user \"%s\" authenticated as \"%s\"",
2573  usermap_name, pg_role, auth_user)));
2574  }
2575  return found_entry ? STATUS_OK : STATUS_ERROR;
2576 }
#define STATUS_OK
Definition: c.h:1178
#define STATUS_ERROR
Definition: c.h:1179
int errmsg(const char *fmt,...)
Definition: elog.c:904
#define LOG
Definition: elog.h:25
#define ereport(elevel,...)
Definition: elog.h:143
static void check_ident_usermap(IdentLine *identLine, const char *usermap_name, const char *pg_role, const char *ident_user, bool case_insensitive, bool *found_p, bool *error_p)
Definition: hba.c:2396
static List * parsed_ident_lines
Definition: hba.c:86
#define lfirst(lc)
Definition: pg_list.h:170
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, and STATUS_OK.

Referenced by auth_peer(), and ident_inet().

◆ hba_authname()

const char* hba_authname ( UserAuth  auth_method)

Definition at line 2710 of file hba.c.

2711 {
2712  /*
2713  * Make sure UserAuthName[] tracks additions to the UserAuth enum
2714  */
2716  "UserAuthName[] must match the UserAuth enum");
2717 
2718  return UserAuthName[auth_method];
2719 }
#define lengthof(array)
Definition: c.h:745
#define StaticAssertStmt(condition, errmessage)
Definition: c.h:929
static const char *const UserAuthName[]
Definition: hba.c:95
#define USER_AUTH_LAST
Definition: hba.h:42

References lengthof, StaticAssertStmt, USER_AUTH_LAST, and UserAuthName.

Referenced by fill_hba_line(), and set_authn_id().

◆ hba_getauthmethod()

void hba_getauthmethod ( hbaPort port)

Definition at line 2697 of file hba.c.

2698 {
2699  check_hba(port);
2700 }
static void check_hba(hbaPort *port)
Definition: hba.c:2093
static int port
Definition: pg_regress.c:92

References check_hba(), and port.

Referenced by ClientAuthentication().

◆ load_hba()

bool load_hba ( void  )

Definition at line 2207 of file hba.c.

2208 {
2209  FILE *file;
2210  List *hba_lines = NIL;
2211  ListCell *line;
2212  List *new_parsed_lines = NIL;
2213  bool ok = true;
2214  MemoryContext linecxt;
2215  MemoryContext oldcxt;
2216  MemoryContext hbacxt;
2217 
2218  file = AllocateFile(HbaFileName, "r");
2219  if (file == NULL)
2220  {
2221  ereport(LOG,
2223  errmsg("could not open configuration file \"%s\": %m",
2224  HbaFileName)));
2225  return false;
2226  }
2227 
2228  linecxt = tokenize_auth_file(HbaFileName, file, &hba_lines, LOG);
2229  FreeFile(file);
2230 
2231  /* Now parse all the lines */
2234  "hba parser context",
2236  oldcxt = MemoryContextSwitchTo(hbacxt);
2237  foreach(line, hba_lines)
2238  {
2239  TokenizedAuthLine *tok_line = (TokenizedAuthLine *) lfirst(line);
2240  HbaLine *newline;
2241 
2242  /* don't parse lines that already have errors */
2243  if (tok_line->err_msg != NULL)
2244  {
2245  ok = false;
2246  continue;
2247  }
2248 
2249  if ((newline = parse_hba_line(tok_line, LOG)) == NULL)
2250  {
2251  /* Parse error; remember there's trouble */
2252  ok = false;
2253 
2254  /*
2255  * Keep parsing the rest of the file so we can report errors on
2256  * more than the first line. Error has already been logged, no
2257  * need for more chatter here.
2258  */
2259  continue;
2260  }
2261 
2262  new_parsed_lines = lappend(new_parsed_lines, newline);
2263  }
2264 
2265  /*
2266  * A valid HBA file must have at least one entry; else there's no way to
2267  * connect to the postmaster. But only complain about this if we didn't
2268  * already have parsing errors.
2269  */
2270  if (ok && new_parsed_lines == NIL)
2271  {
2272  ereport(LOG,
2273  (errcode(ERRCODE_CONFIG_FILE_ERROR),
2274  errmsg("configuration file \"%s\" contains no entries",
2275  HbaFileName)));
2276  ok = false;
2277  }
2278 
2279  /* Free tokenizer memory */
2280  MemoryContextDelete(linecxt);
2281  MemoryContextSwitchTo(oldcxt);
2282 
2283  if (!ok)
2284  {
2285  /* File contained one or more errors, so bail out */
2286  MemoryContextDelete(hbacxt);
2287  return false;
2288  }
2289 
2290  /* Loaded new file successfully, replace the one we use */
2291  if (parsed_hba_context != NULL)
2293  parsed_hba_context = hbacxt;
2294  parsed_hba_lines = new_parsed_lines;
2295 
2296  return true;
2297 }
int errcode_for_file_access(void)
Definition: elog.c:716
int errcode(int sqlerrcode)
Definition: elog.c:693
FILE * AllocateFile(const char *name, const char *mode)
Definition: fd.c:2398
int FreeFile(FILE *file)
Definition: fd.c:2597
char * HbaFileName
Definition: guc.c:655
static MemoryContext parsed_hba_context
Definition: hba.c:76
HbaLine * parse_hba_line(TokenizedAuthLine *tok_line, int elevel)
Definition: hba.c:937
MemoryContext tokenize_auth_file(const char *filename, FILE *file, List **tok_lines, int elevel)
Definition: hba.c:446
static List * parsed_hba_lines
Definition: hba.c:75
Assert(fmt[strlen(fmt) - 1] !='\n')
List * lappend(List *list, void *datum)
Definition: list.c:338
MemoryContext PostmasterContext
Definition: mcxt.c:50
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:218
#define AllocSetContextCreate
Definition: memutils.h:173
#define ALLOCSET_SMALL_SIZES
Definition: memutils.h:207
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define NIL
Definition: pg_list.h:66
static chr newline(void)
Definition: regc_lex.c:1001
Definition: hba.h:81
Definition: pg_list.h:52
char * err_msg
Definition: hba.h:160

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

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

◆ load_ident()

bool load_ident ( void  )

Definition at line 2586 of file hba.c.

2587 {
2588  FILE *file;
2589  List *ident_lines = NIL;
2590  ListCell *line_cell,
2591  *parsed_line_cell;
2592  List *new_parsed_lines = NIL;
2593  bool ok = true;
2594  MemoryContext linecxt;
2595  MemoryContext oldcxt;
2596  MemoryContext ident_context;
2597  IdentLine *newline;
2598 
2599  file = AllocateFile(IdentFileName, "r");
2600  if (file == NULL)
2601  {
2602  /* not fatal ... we just won't do any special ident maps */
2603  ereport(LOG,
2605  errmsg("could not open usermap file \"%s\": %m",
2606  IdentFileName)));
2607  return false;
2608  }
2609 
2610  linecxt = tokenize_auth_file(IdentFileName, file, &ident_lines, LOG);
2611  FreeFile(file);
2612 
2613  /* Now parse all the lines */
2615  ident_context = AllocSetContextCreate(PostmasterContext,
2616  "ident parser context",
2618  oldcxt = MemoryContextSwitchTo(ident_context);
2619  foreach(line_cell, ident_lines)
2620  {
2621  TokenizedAuthLine *tok_line = (TokenizedAuthLine *) lfirst(line_cell);
2622 
2623  /* don't parse lines that already have errors */
2624  if (tok_line->err_msg != NULL)
2625  {
2626  ok = false;
2627  continue;
2628  }
2629 
2630  if ((newline = parse_ident_line(tok_line, LOG)) == NULL)
2631  {
2632  /* Parse error; remember there's trouble */
2633  ok = false;
2634 
2635  /*
2636  * Keep parsing the rest of the file so we can report errors on
2637  * more than the first line. Error has already been logged, no
2638  * need for more chatter here.
2639  */
2640  continue;
2641  }
2642 
2643  new_parsed_lines = lappend(new_parsed_lines, newline);
2644  }
2645 
2646  /* Free tokenizer memory */
2647  MemoryContextDelete(linecxt);
2648  MemoryContextSwitchTo(oldcxt);
2649 
2650  if (!ok)
2651  {
2652  /*
2653  * File contained one or more errors, so bail out, first being careful
2654  * to clean up whatever we allocated. Most stuff will go away via
2655  * MemoryContextDelete, but we have to clean up regexes explicitly.
2656  */
2657  foreach(parsed_line_cell, new_parsed_lines)
2658  {
2659  newline = (IdentLine *) lfirst(parsed_line_cell);
2660  if (newline->ident_user[0] == '/')
2661  pg_regfree(&newline->re);
2662  }
2663  MemoryContextDelete(ident_context);
2664  return false;
2665  }
2666 
2667  /* Loaded new file successfully, replace the one we use */
2668  if (parsed_ident_lines != NIL)
2669  {
2670  foreach(parsed_line_cell, parsed_ident_lines)
2671  {
2672  newline = (IdentLine *) lfirst(parsed_line_cell);
2673  if (newline->ident_user[0] == '/')
2674  pg_regfree(&newline->re);
2675  }
2676  }
2677  if (parsed_ident_context != NULL)
2679 
2680  parsed_ident_context = ident_context;
2681  parsed_ident_lines = new_parsed_lines;
2682 
2683  return true;
2684 }
char * IdentFileName
Definition: guc.c:656
IdentLine * parse_ident_line(TokenizedAuthLine *tok_line, int elevel)
Definition: hba.c:2315
static MemoryContext parsed_ident_context
Definition: hba.c:87
void pg_regfree(regex_t *re)
Definition: regfree.c:49
Definition: hba.h:126

References AllocateFile(), ALLOCSET_SMALL_SIZES, AllocSetContextCreate, Assert(), ereport, TokenizedAuthLine::err_msg, errcode_for_file_access(), errmsg(), FreeFile(), IdentFileName, lappend(), lfirst, LOG, MemoryContextDelete(), MemoryContextSwitchTo(), newline(), NIL, parse_ident_line(), parsed_ident_context, parsed_ident_lines, pg_regfree(), PostmasterContext, and tokenize_auth_file().

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

◆ parse_hba_line()

HbaLine* parse_hba_line ( TokenizedAuthLine tok_line,
int  elevel 
)

Definition at line 937 of file hba.c.

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

References HbaLine::addr, HbaLine::addrlen, addrinfo::ai_addr, addrinfo::ai_addrlen, addrinfo::ai_canonname, addrinfo::ai_family, addrinfo::ai_flags, addrinfo::ai_next, AI_NUMERICHOST, addrinfo::ai_protocol, addrinfo::ai_socktype, Assert(), HbaLine::auth_method, HbaLine::clientcert, clientCertFull, HbaLine::compat_realm, HbaLine::conntype, copy_auth_token(), ctHost, ctHostGSS, ctHostNoGSS, ctHostNoSSL, ctHostSSL, ctLocal, HbaLine::databases, Db_user_namespace, EAI_NONAME, EnableSSL, ereport, TokenizedAuthLine::err_msg, errcode(), errcontext, errhint(), errmsg(), TokenizedAuthLine::fields, gai_strerror, HbaFileName, HbaLine::hostname, HbaLine::include_realm, HbaLine::ip_cmp_method, ipCmpAll, ipCmpMask, ipCmpSameHost, ipCmpSameNet, lappend(), HbaLine::ldapbasedn, HbaLine::ldapbinddn, HbaLine::ldapbindpasswd, HbaLine::ldapprefix, HbaLine::ldapsearchattribute, HbaLine::ldapsearchfilter, HbaLine::ldapserver, HbaLine::ldapsuffix, List::length, lfirst, 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, HbaLine::roles, generate_unaccent_rules::str, AuthToken::string, 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 2315 of file hba.c.

2316 {
2317  int line_num = tok_line->line_num;
2318  char **err_msg = &tok_line->err_msg;
2319  ListCell *field;
2320  List *tokens;
2321  AuthToken *token;
2322  IdentLine *parsedline;
2323 
2324  Assert(tok_line->fields != NIL);
2325  field = list_head(tok_line->fields);
2326 
2327  parsedline = palloc0(sizeof(IdentLine));
2328  parsedline->linenumber = line_num;
2329 
2330  /* Get the map token (must exist) */
2331  tokens = lfirst(field);
2332  IDENT_MULTI_VALUE(tokens);
2333  token = linitial(tokens);
2334  parsedline->usermap = pstrdup(token->string);
2335 
2336  /* Get the ident user token */
2337  field = lnext(tok_line->fields, field);
2338  IDENT_FIELD_ABSENT(field);
2339  tokens = lfirst(field);
2340  IDENT_MULTI_VALUE(tokens);
2341  token = linitial(tokens);
2342  parsedline->ident_user = pstrdup(token->string);
2343 
2344  /* Get the PG rolename token */
2345  field = lnext(tok_line->fields, field);
2346  IDENT_FIELD_ABSENT(field);
2347  tokens = lfirst(field);
2348  IDENT_MULTI_VALUE(tokens);
2349  token = linitial(tokens);
2350  parsedline->pg_role = pstrdup(token->string);
2351 
2352  if (parsedline->ident_user[0] == '/')
2353  {
2354  /*
2355  * When system username starts with a slash, treat it as a regular
2356  * expression. Pre-compile it.
2357  */
2358  int r;
2359  pg_wchar *wstr;
2360  int wlen;
2361 
2362  wstr = palloc((strlen(parsedline->ident_user + 1) + 1) * sizeof(pg_wchar));
2363  wlen = pg_mb2wchar_with_len(parsedline->ident_user + 1,
2364  wstr, strlen(parsedline->ident_user + 1));
2365 
2366  r = pg_regcomp(&parsedline->re, wstr, wlen, REG_ADVANCED, C_COLLATION_OID);
2367  if (r)
2368  {
2369  char errstr[100];
2370 
2371  pg_regerror(r, &parsedline->re, errstr, sizeof(errstr));
2372  ereport(elevel,
2373  (errcode(ERRCODE_INVALID_REGULAR_EXPRESSION),
2374  errmsg("invalid regular expression \"%s\": %s",
2375  parsedline->ident_user + 1, errstr)));
2376 
2377  *err_msg = psprintf("invalid regular expression \"%s\": %s",
2378  parsedline->ident_user + 1, errstr);
2379 
2380  pfree(wstr);
2381  return NULL;
2382  }
2383  pfree(wstr);
2384  }
2385 
2386  return parsedline;
2387 }
#define IDENT_FIELD_ABSENT(field)
Definition: hba.c:898
#define IDENT_MULTI_VALUE(tokens)
Definition: hba.c:910
unsigned int pg_wchar
Definition: mbprint.c:31
int pg_mb2wchar_with_len(const char *from, pg_wchar *to, int len)
Definition: mbutils.c:929
void * palloc(Size size)
Definition: mcxt.c:1068
int pg_regcomp(regex_t *re, const chr *string, size_t len, int flags, Oid collation)
Definition: regcomp.c:328
size_t pg_regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size)
Definition: regerror.c:60
#define REG_ADVANCED
Definition: regex.h:103
char * ident_user
Definition: hba.h:130
char * pg_role
Definition: hba.h:131
regex_t re
Definition: hba.h:132
char * usermap
Definition: hba.h:129
int linenumber
Definition: hba.h:127

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

Referenced by fill_ident_view(), and load_ident().

◆ pg_isblank()

bool pg_isblank ( const char  c)

Definition at line 126 of file hba.c.

127 {
128  return c == ' ' || c == '\t' || c == '\r';
129 }
char * c

Referenced by interpret_ident_response(), and next_token().

◆ tokenize_auth_file()

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

Definition at line 446 of file hba.c.

448 {
449  int line_number = 1;
451  MemoryContext linecxt;
452  MemoryContext oldcxt;
453 
455  "tokenize_auth_file",
457  oldcxt = MemoryContextSwitchTo(linecxt);
458 
460 
461  *tok_lines = NIL;
462 
463  while (!feof(file) && !ferror(file))
464  {
465  char *lineptr;
466  List *current_line = NIL;
467  char *err_msg = NULL;
468  int last_backslash_buflen = 0;
469  int continuations = 0;
470 
471  /* Collect the next input line, handling backslash continuations */
473 
474  while (pg_get_line_append(file, &buf, NULL))
475  {
476  /* Strip trailing newline, including \r in case we're on Windows */
477  buf.len = pg_strip_crlf(buf.data);
478 
479  /*
480  * Check for backslash continuation. The backslash must be after
481  * the last place we found a continuation, else two backslashes
482  * followed by two \n's would behave surprisingly.
483  */
484  if (buf.len > last_backslash_buflen &&
485  buf.data[buf.len - 1] == '\\')
486  {
487  /* Continuation, so strip it and keep reading */
488  buf.data[--buf.len] = '\0';
489  last_backslash_buflen = buf.len;
490  continuations++;
491  continue;
492  }
493 
494  /* Nope, so we have the whole line */
495  break;
496  }
497 
498  if (ferror(file))
499  {
500  /* I/O error! */
501  int save_errno = errno;
502 
503  ereport(elevel,
505  errmsg("could not read file \"%s\": %m", filename)));
506  err_msg = psprintf("could not read file \"%s\": %s",
507  filename, strerror(save_errno));
508  break;
509  }
510 
511  /* Parse fields */
512  lineptr = buf.data;
513  while (*lineptr && err_msg == NULL)
514  {
515  List *current_field;
516 
517  current_field = next_field_expand(filename, &lineptr,
518  elevel, &err_msg);
519  /* add field to line, unless we are at EOL or comment start */
520  if (current_field != NIL)
521  current_line = lappend(current_line, current_field);
522  }
523 
524  /*
525  * Reached EOL; emit line to TokenizedAuthLine list unless it's boring
526  */
527  if (current_line != NIL || err_msg != NULL)
528  {
529  TokenizedAuthLine *tok_line;
530 
531  tok_line = (TokenizedAuthLine *) palloc(sizeof(TokenizedAuthLine));
532  tok_line->fields = current_line;
533  tok_line->line_num = line_number;
534  tok_line->raw_line = pstrdup(buf.data);
535  tok_line->err_msg = err_msg;
536  *tok_lines = lappend(*tok_lines, tok_line);
537  }
538 
539  line_number += continuations + 1;
540  }
541 
542  MemoryContextSwitchTo(oldcxt);
543 
544  return linecxt;
545 }
static List * next_field_expand(const char *filename, char **lineptr, int elevel, char **err_msg)
Definition: hba.c:304
MemoryContext CurrentMemoryContext
Definition: mcxt.c:42
static char * filename
Definition: pg_dumpall.c:94
bool pg_get_line_append(FILE *stream, StringInfo buf, PromptInterruptContext *prompt_ctx)
Definition: pg_get_line.c:124
static char * buf
Definition: pg_test_fsync.c:67
#define strerror
Definition: port.h:238
int pg_strip_crlf(char *str)
Definition: string.c:121
void resetStringInfo(StringInfo str)
Definition: stringinfo.c:75
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59

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

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