PostgreSQL Source Code git master
Loading...
Searching...
No Matches
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  AuthToken
 
struct  HbaLine
 
struct  IdentLine
 
struct  HostsLine
 
struct  TokenizedAuthLine
 

Macros

#define USER_AUTH_LAST   uaOAuth /* 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 AuthToken AuthToken
 
typedef struct HbaLine HbaLine
 
typedef struct IdentLine IdentLine
 
typedef struct HostsLine HostsLine
 
typedef enum HostsFileLoadResult HostsFileLoadResult
 
typedef struct TokenizedAuthLine TokenizedAuthLine
 
typedef struct Port Port
 

Enumerations

enum  UserAuth {
  uaReject , uaImplicitReject , uaTrust , uaIdent ,
  uaPassword , uaMD5 , uaSCRAM , uaGSS ,
  uaSSPI , uaPAM , uaBSD , uaLDAP ,
  uaCert , uaPeer , uaOAuth
}
 
enum  IPCompareMethod { ipCmpMask , ipCmpSameHost , ipCmpSameNet , ipCmpAll }
 
enum  ConnType {
  ctLocal , ctHost , ctHostSSL , ctHostNoSSL ,
  ctHostGSS , ctHostNoGSS
}
 
enum  ClientCertMode { clientCertOff , clientCertCA , clientCertFull }
 
enum  ClientCertName { clientCertCN , clientCertDN }
 
enum  HostsFileLoadResult {
  HOSTSFILE_LOAD_OK = 0 , HOSTSFILE_LOAD_FAILED , HOSTSFILE_EMPTY , HOSTSFILE_MISSING ,
  HOSTSFILE_DISABLED
}
 

Functions

bool load_hba (void)
 
bool load_ident (void)
 
const charhba_authname (UserAuth auth_method)
 
void hba_getauthmethod (Port *port)
 
int check_usermap (const char *usermap_name, const char *pg_user, const char *system_user, bool case_insensitive)
 
HbaLineparse_hba_line (TokenizedAuthLine *tok_line, int elevel)
 
IdentLineparse_ident_line (TokenizedAuthLine *tok_line, int elevel)
 
FILEopen_auth_file (const char *filename, int elevel, int depth, char **err_msg)
 
void free_auth_file (FILE *file, int depth)
 
void tokenize_auth_file (const char *filename, FILE *file, List **tok_lines, int elevel, int depth)
 

Macro Definition Documentation

◆ USER_AUTH_LAST

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

Definition at line 42 of file hba.h.

Typedef Documentation

◆ AuthToken

◆ ClientCertMode

◆ ClientCertName

◆ ConnType

◆ HbaLine

◆ HostsFileLoadResult

◆ HostsLine

◆ IdentLine

◆ IPCompareMethod

◆ Port

typedef struct Port Port

Definition at line 196 of file hba.h.

◆ TokenizedAuthLine

◆ 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

Enumerator
ctLocal 
ctHost 
ctHostSSL 
ctHostNoSSL 
ctHostGSS 
ctHostNoGSS 

Definition at line 57 of file hba.h.

58{
59 ctLocal,
60 ctHost,
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

◆ HostsFileLoadResult

Enumerator
HOSTSFILE_LOAD_OK 
HOSTSFILE_LOAD_FAILED 
HOSTSFILE_EMPTY 
HOSTSFILE_MISSING 
HOSTSFILE_DISABLED 

Definition at line 168 of file hba.h.

169{
HostsFileLoadResult
Definition hba.h:169
@ HOSTSFILE_MISSING
Definition hba.h:173
@ HOSTSFILE_LOAD_OK
Definition hba.h:170
@ HOSTSFILE_EMPTY
Definition hba.h:172
@ HOSTSFILE_DISABLED
Definition hba.h:174
@ HOSTSFILE_LOAD_FAILED
Definition hba.h:171

◆ IPCompareMethod

Enumerator
ipCmpMask 
ipCmpSameHost 
ipCmpSameNet 
ipCmpAll 

Definition at line 49 of file hba.h.

50{
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

Enumerator
uaReject 
uaImplicitReject 
uaTrust 
uaIdent 
uaPassword 
uaMD5 
uaSCRAM 
uaGSS 
uaSSPI 
uaPAM 
uaBSD 
uaLDAP 
uaCert 
uaPeer 
uaOAuth 

Definition at line 25 of file hba.h.

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

Function Documentation

◆ check_usermap()

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

Definition at line 2791 of file hba.c.

2795{
2796 bool found_entry = false,
2797 error = false;
2798
2799 if (usermap_name == NULL || usermap_name[0] == '\0')
2800 {
2801 if (case_insensitive)
2802 {
2803 if (pg_strcasecmp(pg_user, system_user) == 0)
2804 return STATUS_OK;
2805 }
2806 else
2807 {
2808 if (strcmp(pg_user, system_user) == 0)
2809 return STATUS_OK;
2810 }
2811 ereport(LOG,
2812 (errmsg("provided user name (%s) and authenticated user name (%s) do not match",
2813 pg_user, system_user)));
2814 return STATUS_ERROR;
2815 }
2816 else
2817 {
2819
2821 {
2823 pg_user, system_user, case_insensitive,
2824 &found_entry, &error);
2825 if (found_entry || error)
2826 break;
2827 }
2828 }
2829 if (!found_entry && !error)
2830 {
2831 ereport(LOG,
2832 (errmsg("no match in usermap \"%s\" for user \"%s\" authenticated as \"%s\"",
2833 usermap_name, pg_user, system_user)));
2834 }
2836}
#define STATUS_OK
Definition c.h:1258
#define STATUS_ERROR
Definition c.h:1259
#define LOG
Definition elog.h:32
#define ereport(elevel,...)
Definition elog.h:152
static List * parsed_ident_lines
Definition hba.c:93
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:2626
Datum system_user(PG_FUNCTION_ARGS)
Definition miscinit.c:900
static char * errmsg
#define lfirst(lc)
Definition pg_list.h:172
int pg_strcasecmp(const char *s1, const char *s2)
static int fb(int x)
static void error(void)

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

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

◆ free_auth_file()

void free_auth_file ( FILE file,
int  depth 
)
extern

Definition at line 568 of file hba.c.

569{
570 FreeFile(file);
571
572 /* If this is the last cleanup, remove the tokenization context */
573 if (depth == CONF_FILE_START_DEPTH)
574 {
577 }
578}
#define CONF_FILE_START_DEPTH
Definition conffiles.h:17
int FreeFile(FILE *file)
Definition fd.c:2827
static MemoryContext tokenize_context
Definition hba.c:80
void MemoryContextDelete(MemoryContext context)
Definition mcxt.c:472

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

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

◆ hba_authname()

const char * hba_authname ( UserAuth  auth_method)
extern

Definition at line 2948 of file hba.c.

2949{
2950 return UserAuthName[auth_method];
2951}
static const char *const UserAuthName[]
Definition hba.c:102

References UserAuthName.

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

◆ hba_getauthmethod()

void hba_getauthmethod ( Port port)
extern

Definition at line 2935 of file hba.c.

2936{
2937 check_hba(port);
2938}
static void check_hba(Port *port)
Definition hba.c:2338
static int port
Definition pg_regress.c:117

References check_hba(), and port.

Referenced by ClientAuthentication().

◆ load_hba()

bool load_hba ( void  )
extern

Definition at line 2452 of file hba.c.

2453{
2454 FILE *file;
2455 List *hba_lines = NIL;
2456 ListCell *line;
2458 bool ok = true;
2461
2462 file = open_auth_file(HbaFileName, LOG, 0, NULL);
2463 if (file == NULL)
2464 {
2465 /* error already logged */
2466 return false;
2467 }
2468
2470
2471 /* Now parse all the lines */
2474 "hba parser context",
2477 foreach(line, hba_lines)
2478 {
2481
2482 /* don't parse lines that already have errors */
2483 if (tok_line->err_msg != NULL)
2484 {
2485 ok = false;
2486 continue;
2487 }
2488
2489 if ((newline = parse_hba_line(tok_line, LOG)) == NULL)
2490 {
2491 /* Parse error; remember there's trouble */
2492 ok = false;
2493
2494 /*
2495 * Keep parsing the rest of the file so we can report errors on
2496 * more than the first line. Error has already been logged, no
2497 * need for more chatter here.
2498 */
2499 continue;
2500 }
2501
2503 }
2504
2505 /*
2506 * A valid HBA file must have at least one entry; else there's no way to
2507 * connect to the postmaster. But only complain about this if we didn't
2508 * already have parsing errors.
2509 */
2510 if (ok && new_parsed_lines == NIL)
2511 {
2512 ereport(LOG,
2514 errmsg("configuration file \"%s\" contains no entries",
2515 HbaFileName)));
2516 ok = false;
2517 }
2518
2519 /* Free tokenizer memory */
2520 free_auth_file(file, 0);
2522
2523 if (!ok)
2524 {
2525 /*
2526 * File contained one or more errors, so bail out. MemoryContextDelete
2527 * is enough to clean up everything, including regexes.
2528 */
2530 return false;
2531 }
2532
2533 /* Loaded new file successfully, replace the one we use */
2534 if (parsed_hba_context != NULL)
2538
2539 return true;
2540}
#define Assert(condition)
Definition c.h:943
int errcode(int sqlerrcode)
Definition elog.c:875
char * HbaFileName
Definition guc_tables.c:584
HbaLine * parse_hba_line(TokenizedAuthLine *tok_line, int elevel)
Definition hba.c:1324
static MemoryContext parsed_hba_context
Definition hba.c:87
void free_auth_file(FILE *file, int depth)
Definition hba.c:568
static List * parsed_hba_lines
Definition hba.c:86
void tokenize_auth_file(const char *filename, FILE *file, List **tok_lines, int elevel, int depth)
Definition hba.c:687
FILE * open_auth_file(const char *filename, int elevel, int depth, char **err_msg)
Definition hba.c:593
#define newline
List * lappend(List *list, void *datum)
Definition list.c:339
MemoryContext PostmasterContext
Definition mcxt.c:168
#define AllocSetContextCreate
Definition memutils.h:129
#define ALLOCSET_SMALL_SIZES
Definition memutils.h:170
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition palloc.h:124
#define NIL
Definition pg_list.h:68
Definition hba.h:95
Definition pg_list.h:54

References ALLOCSET_SMALL_SIZES, AllocSetContextCreate, Assert, ereport, errcode(), errmsg, fb(), 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  )
extern

Definition at line 2846 of file hba.c.

2847{
2848 FILE *file;
2849 List *ident_lines = NIL;
2852 bool ok = true;
2856
2857 /* not FATAL ... we just won't do any special ident maps */
2858 file = open_auth_file(IdentFileName, LOG, 0, NULL);
2859 if (file == NULL)
2860 {
2861 /* error already logged */
2862 return false;
2863 }
2864
2866
2867 /* Now parse all the lines */
2870 "ident parser context",
2873 foreach(line_cell, ident_lines)
2874 {
2876
2877 /* don't parse lines that already have errors */
2878 if (tok_line->err_msg != NULL)
2879 {
2880 ok = false;
2881 continue;
2882 }
2883
2885 {
2886 /* Parse error; remember there's trouble */
2887 ok = false;
2888
2889 /*
2890 * Keep parsing the rest of the file so we can report errors on
2891 * more than the first line. Error has already been logged, no
2892 * need for more chatter here.
2893 */
2894 continue;
2895 }
2896
2898 }
2899
2900 /* Free tokenizer memory */
2901 free_auth_file(file, 0);
2903
2904 if (!ok)
2905 {
2906 /*
2907 * File contained one or more errors, so bail out. MemoryContextDelete
2908 * is enough to clean up everything, including regexes.
2909 */
2911 return false;
2912 }
2913
2914 /* Loaded new file successfully, replace the one we use */
2917
2920
2921 return true;
2922}
char * IdentFileName
Definition guc_tables.c:585
static MemoryContext parsed_ident_context
Definition hba.c:94
IdentLine * parse_ident_line(TokenizedAuthLine *tok_line, int elevel)
Definition hba.c:2558

References ALLOCSET_SMALL_SIZES, AllocSetContextCreate, Assert, fb(), 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().

◆ open_auth_file()

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

Definition at line 593 of file hba.c.

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

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

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

◆ parse_hba_line()

HbaLine * parse_hba_line ( TokenizedAuthLine tok_line,
int  elevel 
)
extern

Definition at line 1324 of file hba.c.

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

References Assert, check_oauth_validator(), clientCertFull, copy_auth_token(), ctHost, ctHostGSS, ctHostNoGSS, ctHostNoSSL, ctHostSSL, ctLocal, EnableSSL, ereport, errcode(), errcontext, errhint(), errmsg, fb(), gai_strerror(), ipCmpAll, ipCmpMask, ipCmpSameHost, ipCmpSameNet, lappend(), lfirst, linitial, list_head(), lnext(), MANDATORY_AUTH_ARG, memcpy(), NIL, palloc0_object, parse_hba_auth_opt(), pfree(), pg_freeaddrinfo_all(), pg_getaddrinfo_all(), pg_sockaddr_cidr_mask(), psprintf(), pstrdup(), regcomp_auth_token(), str, token, token_is_keyword, uaBSD, uaCert, uaGSS, uaIdent, uaLDAP, uaMD5, uaOAuth, uaPAM, uaPassword, uaPeer, uaReject, uaSCRAM, uaSSPI, uaTrust, and val.

Referenced by fill_hba_view(), and load_hba().

◆ parse_ident_line()

IdentLine * parse_ident_line ( TokenizedAuthLine tok_line,
int  elevel 
)
extern

Definition at line 2558 of file hba.c.

2559{
2560 int line_num = tok_line->line_num;
2561 char *file_name = tok_line->file_name;
2562 char **err_msg = &tok_line->err_msg;
2563 ListCell *field;
2564 List *tokens;
2567
2568 Assert(tok_line->fields != NIL);
2569 field = list_head(tok_line->fields);
2570
2572 parsedline->linenumber = line_num;
2573
2574 /* Get the map token (must exist) */
2575 tokens = lfirst(field);
2578 parsedline->usermap = pstrdup(token->string);
2579
2580 /* Get the ident user token */
2581 field = lnext(tok_line->fields, field);
2582 IDENT_FIELD_ABSENT(field);
2583 tokens = lfirst(field);
2586
2587 /* Copy the ident user token */
2588 parsedline->system_user = copy_auth_token(token);
2589
2590 /* Get the PG rolename token */
2591 field = lnext(tok_line->fields, field);
2592 IDENT_FIELD_ABSENT(field);
2593 tokens = lfirst(field);
2596 parsedline->pg_user = copy_auth_token(token);
2597
2598 /*
2599 * Now that the field validation is done, compile a regex from the user
2600 * tokens, if necessary.
2601 */
2602 if (regcomp_auth_token(parsedline->system_user, file_name, line_num,
2603 err_msg, elevel))
2604 {
2605 /* err_msg includes the error to report */
2606 return NULL;
2607 }
2608
2609 if (regcomp_auth_token(parsedline->pg_user, file_name, line_num,
2610 err_msg, elevel))
2611 {
2612 /* err_msg includes the error to report */
2613 return NULL;
2614 }
2615
2616 return parsedline;
2617}
#define IDENT_FIELD_ABSENT(field)
Definition hba.c:1284
#define IDENT_MULTI_VALUE(tokens)
Definition hba.c:1297

References Assert, copy_auth_token(), fb(), IDENT_FIELD_ABSENT, IDENT_MULTI_VALUE, lfirst, linitial, list_head(), lnext(), NIL, palloc0_object, pstrdup(), regcomp_auth_token(), and token.

Referenced by fill_ident_view(), and load_ident().

◆ tokenize_auth_file()

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

Definition at line 687 of file hba.c.

689{
690 int line_number = 1;
693 MemoryContext funccxt; /* context of this function's caller */
695 tokenize_error_callback_arg callback_arg;
696
698
699 callback_arg.filename = filename;
700 callback_arg.linenum = line_number;
701
703 tokenerrcontext.arg = &callback_arg;
706
707 /*
708 * Do all the local tokenization in its own context, to ease the cleanup
709 * of any memory allocated while tokenizing.
710 */
712 "tokenize_auth_file",
715
717
718 if (depth == CONF_FILE_START_DEPTH)
719 *tok_lines = NIL;
720
721 while (!feof(file) && !ferror(file))
722 {
725 char *lineptr;
727 char *err_msg = NULL;
728 int last_backslash_buflen = 0;
729 int continuations = 0;
730
731 /* Collect the next input line, handling backslash continuations */
733
734 while (pg_get_line_append(file, &buf, NULL))
735 {
736 /* Strip trailing newline, including \r in case we're on Windows */
737 buf.len = pg_strip_crlf(buf.data);
738
739 /*
740 * Check for backslash continuation. The backslash must be after
741 * the last place we found a continuation, else two backslashes
742 * followed by two \n's would behave surprisingly.
743 */
744 if (buf.len > last_backslash_buflen &&
745 buf.data[buf.len - 1] == '\\')
746 {
747 /* Continuation, so strip it and keep reading */
748 buf.data[--buf.len] = '\0';
751 continue;
752 }
753
754 /* Nope, so we have the whole line */
755 break;
756 }
757
758 if (ferror(file))
759 {
760 /* I/O error! */
761 int save_errno = errno;
762
763 ereport(elevel,
765 errmsg("could not read file \"%s\": %m", filename)));
767 err_msg = psprintf("could not read file \"%s\": %m",
768 filename);
769 break;
770 }
771
772 /* Parse fields */
773 lineptr = buf.data;
774 while (*lineptr && err_msg == NULL)
775 {
777
779 elevel, depth, &err_msg);
780 /* add field to line, unless we are at EOL or comment start */
781 if (current_field != NIL)
782 {
783 /*
784 * lappend() may do its own allocations, so move to the
785 * context for the list of tokens.
786 */
790 }
791 }
792
793 /*
794 * Reached EOL; no need to emit line to TokenizedAuthLine list if it's
795 * boring.
796 */
797 if (current_line == NIL && err_msg == NULL)
798 goto next_line;
799
800 /* If the line is valid, check if that's an include directive */
801 if (err_msg == NULL && list_length(current_line) == 2)
802 {
803 AuthToken *first,
804 *second;
805
808
809 if (strcmp(first->string, "include") == 0)
810 {
812 elevel, depth + 1, false, &err_msg);
813
814 if (err_msg)
815 goto process_line;
816
817 /*
818 * tokenize_auth_file() has taken care of creating the
819 * TokenizedAuthLines.
820 */
821 goto next_line;
822 }
823 else if (strcmp(first->string, "include_dir") == 0)
824 {
825 char **filenames;
826 char *dir_name = second->string;
827 int num_filenames;
829
831 &num_filenames, &err_msg);
832
833 if (!filenames)
834 {
835 /* the error is in err_msg, so create an entry */
836 goto process_line;
837 }
838
840 for (int i = 0; i < num_filenames; i++)
841 {
843 elevel, depth + 1, false, &err_msg);
844 /* cumulate errors if any */
845 if (err_msg)
846 {
847 if (err_buf.len > 0)
850 }
851 }
852
853 /* clean up things */
854 for (int i = 0; i < num_filenames; i++)
855 pfree(filenames[i]);
857
858 /*
859 * If there were no errors, the line is fully processed,
860 * bypass the general TokenizedAuthLine processing.
861 */
862 if (err_buf.len == 0)
863 goto next_line;
864
865 /* Otherwise, process the cumulated errors, if any. */
866 err_msg = err_buf.data;
867 goto process_line;
868 }
869 else if (strcmp(first->string, "include_if_exists") == 0)
870 {
871
873 elevel, depth + 1, true, &err_msg);
874 if (err_msg)
875 goto process_line;
876
877 /*
878 * tokenize_auth_file() has taken care of creating the
879 * TokenizedAuthLines.
880 */
881 goto next_line;
882 }
883 }
884
886
887 /*
888 * General processing: report the error if any and emit line to the
889 * TokenizedAuthLine. This is saved in the memory context dedicated
890 * to this list.
891 */
894 tok_line->fields = current_line;
895 tok_line->file_name = pstrdup(filename);
896 tok_line->line_num = line_number;
897 tok_line->raw_line = pstrdup(buf.data);
898 tok_line->err_msg = err_msg ? pstrdup(err_msg) : NULL;
901
903 line_number += continuations + 1;
904 callback_arg.linenum = line_number;
905 }
906
909
911}
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:100
static List * next_field_expand(const char *filename, char **lineptr, int elevel, int depth, char **err_msg)
Definition hba.c:377
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:436
static void tokenize_error_callback(void *arg)
Definition hba.c:658
int i
Definition isn.c:77
bool pg_get_line_append(FILE *stream, StringInfo buf, PromptInterruptContext *prompt_ctx)
static int list_length(const List *l)
Definition pg_list.h:152
#define linitial_node(type, l)
Definition pg_list.h:181
#define lsecond_node(type, l)
Definition pg_list.h:186
static char buf[DEFAULT_XLOG_SEG_SIZE]
int pg_strip_crlf(char *str)
Definition string.c:154
void resetStringInfo(StringInfo str)
Definition stringinfo.c:126
void appendStringInfoString(StringInfo str, const char *s)
Definition stringinfo.c:230
void appendStringInfoChar(StringInfo str, char ch)
Definition stringinfo.c:242
void initStringInfo(StringInfo str)
Definition stringinfo.c:97
char * string
Definition hba.h:89
struct ErrorContextCallback * previous
Definition elog.h:299
const char * filename
Definition hba.c:65

References ALLOCSET_SMALL_SIZES, AllocSetContextCreate, appendStringInfoChar(), appendStringInfoString(), Assert, buf, CONF_FILE_START_DEPTH, CurrentMemoryContext, ereport, errcode_for_file_access(), errmsg, error_context_stack, fb(), tokenize_error_callback_arg::filename, filename, GetConfFilesInDir(), i, initStringInfo(), lappend(), tokenize_error_callback_arg::linenum, linitial, linitial_node, list_length(), lsecond_node, MemoryContextDelete(), MemoryContextSwitchTo(), next_field_expand(), NIL, palloc0_object, pfree(), pg_get_line_append(), pg_strip_crlf(), ErrorContextCallback::previous, psprintf(), pstrdup(), resetStringInfo(), AuthToken::string, tokenize_context, tokenize_error_callback(), and tokenize_include_file().

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