mirror of
https://github.com/postgres/postgres.git
synced 2025-05-01 01:04:50 +03:00
Refactor code related to pg_hba_file_rules() into new file
hba.c is growing big, and more contents are planned for it. In order to prepare for this future work, this commit moves all the code related to the system function processing the contents of pg_hba.conf, pg_hba_file_rules() to a new file called hbafuncs.c, which will be used as the location for the SQL portion of the authentication file parsing. While on it, HbaToken, the structure holding a string token lexed from a configuration file related to authentication, is renamed to a more generic AuthToken, as it gets used not only for pg_hba.conf, but also for pg_ident.conf. TokenizedLine is now named TokenizedAuthLine. The size of hba.c is reduced by ~12%. Author: Julien Rouhaud Reviewed-by: Aleksander Alekseev, Michael Paquier Discussion: https://postgr.es/m/20220223045959.35ipdsvbxcstrhya@jrouhaud
This commit is contained in:
parent
a1bc4d3590
commit
d4781d8873
@ -68,32 +68,6 @@ typedef struct check_network_data
|
||||
#define token_is_keyword(t, k) (!t->quoted && strcmp(t->string, k) == 0)
|
||||
#define token_matches(t, k) (strcmp(t->string, k) == 0)
|
||||
|
||||
/*
|
||||
* A single string token lexed from a config file, together with whether
|
||||
* the token had been quoted.
|
||||
*/
|
||||
typedef struct HbaToken
|
||||
{
|
||||
char *string;
|
||||
bool quoted;
|
||||
} HbaToken;
|
||||
|
||||
/*
|
||||
* TokenizedLine represents one line lexed from a config file.
|
||||
* Each item in the "fields" list is a sub-list of HbaTokens.
|
||||
* We don't emit a TokenizedLine for empty or all-comment lines,
|
||||
* so "fields" is never NIL (nor are any of its sub-lists).
|
||||
* Exception: if an error occurs during tokenization, we might
|
||||
* have fields == NIL, in which case err_msg != NULL.
|
||||
*/
|
||||
typedef struct TokenizedLine
|
||||
{
|
||||
List *fields; /* List of lists of HbaTokens */
|
||||
int line_num; /* Line number */
|
||||
char *raw_line; /* Raw line text */
|
||||
char *err_msg; /* Error message if any */
|
||||
} TokenizedLine;
|
||||
|
||||
/*
|
||||
* pre-parsed content of HBA config file: list of HbaLine structs.
|
||||
* parsed_hba_context is the memory context where it lives.
|
||||
@ -138,16 +112,10 @@ static const char *const UserAuthName[] =
|
||||
};
|
||||
|
||||
|
||||
static MemoryContext tokenize_file(const char *filename, FILE *file,
|
||||
List **tok_lines, int elevel);
|
||||
static List *tokenize_inc_file(List *tokens, const char *outer_filename,
|
||||
const char *inc_filename, int elevel, char **err_msg);
|
||||
static bool parse_hba_auth_opt(char *name, char *val, HbaLine *hbaline,
|
||||
int elevel, char **err_msg);
|
||||
static ArrayType *gethba_options(HbaLine *hba);
|
||||
static void fill_hba_line(Tuplestorestate *tuple_store, TupleDesc tupdesc,
|
||||
int lineno, HbaLine *hba, const char *err_msg);
|
||||
static void fill_hba_view(Tuplestorestate *tuple_store, TupleDesc tupdesc);
|
||||
|
||||
|
||||
/*
|
||||
@ -288,31 +256,31 @@ next_token(char **lineptr, char *buf, int bufsz,
|
||||
}
|
||||
|
||||
/*
|
||||
* Construct a palloc'd HbaToken struct, copying the given string.
|
||||
* Construct a palloc'd AuthToken struct, copying the given string.
|
||||
*/
|
||||
static HbaToken *
|
||||
make_hba_token(const char *token, bool quoted)
|
||||
static AuthToken *
|
||||
make_auth_token(const char *token, bool quoted)
|
||||
{
|
||||
HbaToken *hbatoken;
|
||||
AuthToken *authtoken;
|
||||
int toklen;
|
||||
|
||||
toklen = strlen(token);
|
||||
/* we copy string into same palloc block as the struct */
|
||||
hbatoken = (HbaToken *) palloc(sizeof(HbaToken) + toklen + 1);
|
||||
hbatoken->string = (char *) hbatoken + sizeof(HbaToken);
|
||||
hbatoken->quoted = quoted;
|
||||
memcpy(hbatoken->string, token, toklen + 1);
|
||||
authtoken = (AuthToken *) palloc(sizeof(AuthToken) + toklen + 1);
|
||||
authtoken->string = (char *) authtoken + sizeof(AuthToken);
|
||||
authtoken->quoted = quoted;
|
||||
memcpy(authtoken->string, token, toklen + 1);
|
||||
|
||||
return hbatoken;
|
||||
return authtoken;
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy a HbaToken struct into freshly palloc'd memory.
|
||||
* Copy a AuthToken struct into freshly palloc'd memory.
|
||||
*/
|
||||
static HbaToken *
|
||||
copy_hba_token(HbaToken *in)
|
||||
static AuthToken *
|
||||
copy_auth_token(AuthToken *in)
|
||||
{
|
||||
HbaToken *out = make_hba_token(in->string, in->quoted);
|
||||
AuthToken *out = make_auth_token(in->string, in->quoted);
|
||||
|
||||
return out;
|
||||
}
|
||||
@ -329,7 +297,7 @@ copy_hba_token(HbaToken *in)
|
||||
* may be non-NIL anyway, so *err_msg must be tested to determine whether
|
||||
* there was an error.
|
||||
*
|
||||
* The result is a List of HbaToken structs, one for each token in the field,
|
||||
* The result is a List of AuthToken structs, one for each token in the field,
|
||||
* or NIL if we reached EOL.
|
||||
*/
|
||||
static List *
|
||||
@ -353,7 +321,7 @@ next_field_expand(const char *filename, char **lineptr,
|
||||
tokens = tokenize_inc_file(tokens, filename, buf + 1,
|
||||
elevel, err_msg);
|
||||
else
|
||||
tokens = lappend(tokens, make_hba_token(buf, initial_quote));
|
||||
tokens = lappend(tokens, make_auth_token(buf, initial_quote));
|
||||
} while (trailing_comma && (*err_msg == NULL));
|
||||
|
||||
return tokens;
|
||||
@ -364,7 +332,7 @@ next_field_expand(const char *filename, char **lineptr,
|
||||
* Expand a file included from another file into an hba "field"
|
||||
*
|
||||
* Opens and tokenises a file included from another HBA config file with @,
|
||||
* and returns all values found therein as a flat list of HbaTokens. If a
|
||||
* and returns all values found therein as a flat list of AuthTokens. If a
|
||||
* @-token is found, recursively expand it. The newly read tokens are
|
||||
* appended to "tokens" (so that foo,bar,@baz does what you expect).
|
||||
* All new tokens are allocated in caller's memory context.
|
||||
@ -419,7 +387,7 @@ tokenize_inc_file(List *tokens,
|
||||
}
|
||||
|
||||
/* There is possible recursion here if the file contains @ */
|
||||
linecxt = tokenize_file(inc_fullname, inc_file, &inc_lines, elevel);
|
||||
linecxt = tokenize_auth_file(inc_fullname, inc_file, &inc_lines, elevel);
|
||||
|
||||
FreeFile(inc_file);
|
||||
pfree(inc_fullname);
|
||||
@ -427,7 +395,7 @@ tokenize_inc_file(List *tokens,
|
||||
/* Copy all tokens found in the file and append to the tokens list */
|
||||
foreach(inc_line, inc_lines)
|
||||
{
|
||||
TokenizedLine *tok_line = (TokenizedLine *) lfirst(inc_line);
|
||||
TokenizedAuthLine *tok_line = (TokenizedAuthLine *) lfirst(inc_line);
|
||||
ListCell *inc_field;
|
||||
|
||||
/* If any line has an error, propagate that up to caller */
|
||||
@ -444,9 +412,9 @@ tokenize_inc_file(List *tokens,
|
||||
|
||||
foreach(inc_token, inc_tokens)
|
||||
{
|
||||
HbaToken *token = lfirst(inc_token);
|
||||
AuthToken *token = lfirst(inc_token);
|
||||
|
||||
tokens = lappend(tokens, copy_hba_token(token));
|
||||
tokens = lappend(tokens, copy_auth_token(token));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -456,9 +424,11 @@ tokenize_inc_file(List *tokens,
|
||||
}
|
||||
|
||||
/*
|
||||
* Tokenize the given file.
|
||||
* tokenize_auth_file
|
||||
* Tokenize the given file.
|
||||
*
|
||||
* The output is a list of TokenizedLine structs; see struct definition above.
|
||||
* The output is a list of TokenizedAuthLine structs; see the struct definition
|
||||
* in libpq/hba.h.
|
||||
*
|
||||
* filename: the absolute path to the target file
|
||||
* file: the already-opened target file
|
||||
@ -466,14 +436,15 @@ tokenize_inc_file(List *tokens,
|
||||
* elevel: message logging level
|
||||
*
|
||||
* Errors are reported by logging messages at ereport level elevel and by
|
||||
* adding TokenizedLine structs containing non-null err_msg fields to the
|
||||
* adding TokenizedAuthLine structs containing non-null err_msg fields to the
|
||||
* output list.
|
||||
*
|
||||
* Return value is a memory context which contains all memory allocated by
|
||||
* this function (it's a child of caller's context).
|
||||
*/
|
||||
static MemoryContext
|
||||
tokenize_file(const char *filename, FILE *file, List **tok_lines, int elevel)
|
||||
MemoryContext
|
||||
tokenize_auth_file(const char *filename, FILE *file, List **tok_lines,
|
||||
int elevel)
|
||||
{
|
||||
int line_number = 1;
|
||||
StringInfoData buf;
|
||||
@ -481,7 +452,7 @@ tokenize_file(const char *filename, FILE *file, List **tok_lines, int elevel)
|
||||
MemoryContext oldcxt;
|
||||
|
||||
linecxt = AllocSetContextCreate(CurrentMemoryContext,
|
||||
"tokenize_file",
|
||||
"tokenize_auth_file",
|
||||
ALLOCSET_SMALL_SIZES);
|
||||
oldcxt = MemoryContextSwitchTo(linecxt);
|
||||
|
||||
@ -550,12 +521,14 @@ tokenize_file(const char *filename, FILE *file, List **tok_lines, int elevel)
|
||||
current_line = lappend(current_line, current_field);
|
||||
}
|
||||
|
||||
/* Reached EOL; emit line to TokenizedLine list unless it's boring */
|
||||
/*
|
||||
* Reached EOL; emit line to TokenizedAuthLine list unless it's boring
|
||||
*/
|
||||
if (current_line != NIL || err_msg != NULL)
|
||||
{
|
||||
TokenizedLine *tok_line;
|
||||
TokenizedAuthLine *tok_line;
|
||||
|
||||
tok_line = (TokenizedLine *) palloc(sizeof(TokenizedLine));
|
||||
tok_line = (TokenizedAuthLine *) palloc(sizeof(TokenizedAuthLine));
|
||||
tok_line->fields = current_line;
|
||||
tok_line->line_num = line_number;
|
||||
tok_line->raw_line = pstrdup(buf.data);
|
||||
@ -600,13 +573,13 @@ is_member(Oid userid, const char *role)
|
||||
}
|
||||
|
||||
/*
|
||||
* Check HbaToken list for a match to role, allowing group names.
|
||||
* Check AuthToken list for a match to role, allowing group names.
|
||||
*/
|
||||
static bool
|
||||
check_role(const char *role, Oid roleid, List *tokens)
|
||||
{
|
||||
ListCell *cell;
|
||||
HbaToken *tok;
|
||||
AuthToken *tok;
|
||||
|
||||
foreach(cell, tokens)
|
||||
{
|
||||
@ -624,13 +597,13 @@ check_role(const char *role, Oid roleid, List *tokens)
|
||||
}
|
||||
|
||||
/*
|
||||
* Check to see if db/role combination matches HbaToken list.
|
||||
* Check to see if db/role combination matches AuthToken list.
|
||||
*/
|
||||
static bool
|
||||
check_db(const char *dbname, const char *role, Oid roleid, List *tokens)
|
||||
{
|
||||
ListCell *cell;
|
||||
HbaToken *tok;
|
||||
AuthToken *tok;
|
||||
|
||||
foreach(cell, tokens)
|
||||
{
|
||||
@ -962,8 +935,8 @@ do { \
|
||||
* to have set a memory context that will be reset if this function returns
|
||||
* NULL.
|
||||
*/
|
||||
static HbaLine *
|
||||
parse_hba_line(TokenizedLine *tok_line, int elevel)
|
||||
HbaLine *
|
||||
parse_hba_line(TokenizedAuthLine *tok_line, int elevel)
|
||||
{
|
||||
int line_num = tok_line->line_num;
|
||||
char **err_msg = &tok_line->err_msg;
|
||||
@ -976,7 +949,7 @@ parse_hba_line(TokenizedLine *tok_line, int elevel)
|
||||
ListCell *field;
|
||||
List *tokens;
|
||||
ListCell *tokencell;
|
||||
HbaToken *token;
|
||||
AuthToken *token;
|
||||
HbaLine *parsedline;
|
||||
|
||||
parsedline = palloc0(sizeof(HbaLine));
|
||||
@ -1097,7 +1070,7 @@ parse_hba_line(TokenizedLine *tok_line, int elevel)
|
||||
foreach(tokencell, tokens)
|
||||
{
|
||||
parsedline->databases = lappend(parsedline->databases,
|
||||
copy_hba_token(lfirst(tokencell)));
|
||||
copy_auth_token(lfirst(tokencell)));
|
||||
}
|
||||
|
||||
/* Get the roles. */
|
||||
@ -1117,7 +1090,7 @@ parse_hba_line(TokenizedLine *tok_line, int elevel)
|
||||
foreach(tokencell, tokens)
|
||||
{
|
||||
parsedline->roles = lappend(parsedline->roles,
|
||||
copy_hba_token(lfirst(tokencell)));
|
||||
copy_auth_token(lfirst(tokencell)));
|
||||
}
|
||||
|
||||
if (parsedline->conntype != ctLocal)
|
||||
@ -2257,7 +2230,7 @@ load_hba(void)
|
||||
return false;
|
||||
}
|
||||
|
||||
linecxt = tokenize_file(HbaFileName, file, &hba_lines, LOG);
|
||||
linecxt = tokenize_auth_file(HbaFileName, file, &hba_lines, LOG);
|
||||
FreeFile(file);
|
||||
|
||||
/* Now parse all the lines */
|
||||
@ -2268,7 +2241,7 @@ load_hba(void)
|
||||
oldcxt = MemoryContextSwitchTo(hbacxt);
|
||||
foreach(line, hba_lines)
|
||||
{
|
||||
TokenizedLine *tok_line = (TokenizedLine *) lfirst(line);
|
||||
TokenizedAuthLine *tok_line = (TokenizedAuthLine *) lfirst(line);
|
||||
HbaLine *newline;
|
||||
|
||||
/* don't parse lines that already have errors */
|
||||
@ -2328,398 +2301,6 @@ load_hba(void)
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* This macro specifies the maximum number of authentication options
|
||||
* that are possible with any given authentication method that is supported.
|
||||
* Currently LDAP supports 11, and there are 3 that are not dependent on
|
||||
* the auth method here. It may not actually be possible to set all of them
|
||||
* at the same time, but we'll set the macro value high enough to be
|
||||
* conservative and avoid warnings from static analysis tools.
|
||||
*/
|
||||
#define MAX_HBA_OPTIONS 14
|
||||
|
||||
/*
|
||||
* Create a text array listing the options specified in the HBA line.
|
||||
* Return NULL if no options are specified.
|
||||
*/
|
||||
static ArrayType *
|
||||
gethba_options(HbaLine *hba)
|
||||
{
|
||||
int noptions;
|
||||
Datum options[MAX_HBA_OPTIONS];
|
||||
|
||||
noptions = 0;
|
||||
|
||||
if (hba->auth_method == uaGSS || hba->auth_method == uaSSPI)
|
||||
{
|
||||
if (hba->include_realm)
|
||||
options[noptions++] =
|
||||
CStringGetTextDatum("include_realm=true");
|
||||
|
||||
if (hba->krb_realm)
|
||||
options[noptions++] =
|
||||
CStringGetTextDatum(psprintf("krb_realm=%s", hba->krb_realm));
|
||||
}
|
||||
|
||||
if (hba->usermap)
|
||||
options[noptions++] =
|
||||
CStringGetTextDatum(psprintf("map=%s", hba->usermap));
|
||||
|
||||
if (hba->clientcert != clientCertOff)
|
||||
options[noptions++] =
|
||||
CStringGetTextDatum(psprintf("clientcert=%s", (hba->clientcert == clientCertCA) ? "verify-ca" : "verify-full"));
|
||||
|
||||
if (hba->pamservice)
|
||||
options[noptions++] =
|
||||
CStringGetTextDatum(psprintf("pamservice=%s", hba->pamservice));
|
||||
|
||||
if (hba->auth_method == uaLDAP)
|
||||
{
|
||||
if (hba->ldapserver)
|
||||
options[noptions++] =
|
||||
CStringGetTextDatum(psprintf("ldapserver=%s", hba->ldapserver));
|
||||
|
||||
if (hba->ldapport)
|
||||
options[noptions++] =
|
||||
CStringGetTextDatum(psprintf("ldapport=%d", hba->ldapport));
|
||||
|
||||
if (hba->ldaptls)
|
||||
options[noptions++] =
|
||||
CStringGetTextDatum("ldaptls=true");
|
||||
|
||||
if (hba->ldapprefix)
|
||||
options[noptions++] =
|
||||
CStringGetTextDatum(psprintf("ldapprefix=%s", hba->ldapprefix));
|
||||
|
||||
if (hba->ldapsuffix)
|
||||
options[noptions++] =
|
||||
CStringGetTextDatum(psprintf("ldapsuffix=%s", hba->ldapsuffix));
|
||||
|
||||
if (hba->ldapbasedn)
|
||||
options[noptions++] =
|
||||
CStringGetTextDatum(psprintf("ldapbasedn=%s", hba->ldapbasedn));
|
||||
|
||||
if (hba->ldapbinddn)
|
||||
options[noptions++] =
|
||||
CStringGetTextDatum(psprintf("ldapbinddn=%s", hba->ldapbinddn));
|
||||
|
||||
if (hba->ldapbindpasswd)
|
||||
options[noptions++] =
|
||||
CStringGetTextDatum(psprintf("ldapbindpasswd=%s",
|
||||
hba->ldapbindpasswd));
|
||||
|
||||
if (hba->ldapsearchattribute)
|
||||
options[noptions++] =
|
||||
CStringGetTextDatum(psprintf("ldapsearchattribute=%s",
|
||||
hba->ldapsearchattribute));
|
||||
|
||||
if (hba->ldapsearchfilter)
|
||||
options[noptions++] =
|
||||
CStringGetTextDatum(psprintf("ldapsearchfilter=%s",
|
||||
hba->ldapsearchfilter));
|
||||
|
||||
if (hba->ldapscope)
|
||||
options[noptions++] =
|
||||
CStringGetTextDatum(psprintf("ldapscope=%d", hba->ldapscope));
|
||||
}
|
||||
|
||||
if (hba->auth_method == uaRADIUS)
|
||||
{
|
||||
if (hba->radiusservers_s)
|
||||
options[noptions++] =
|
||||
CStringGetTextDatum(psprintf("radiusservers=%s", hba->radiusservers_s));
|
||||
|
||||
if (hba->radiussecrets_s)
|
||||
options[noptions++] =
|
||||
CStringGetTextDatum(psprintf("radiussecrets=%s", hba->radiussecrets_s));
|
||||
|
||||
if (hba->radiusidentifiers_s)
|
||||
options[noptions++] =
|
||||
CStringGetTextDatum(psprintf("radiusidentifiers=%s", hba->radiusidentifiers_s));
|
||||
|
||||
if (hba->radiusports_s)
|
||||
options[noptions++] =
|
||||
CStringGetTextDatum(psprintf("radiusports=%s", hba->radiusports_s));
|
||||
}
|
||||
|
||||
/* If you add more options, consider increasing MAX_HBA_OPTIONS. */
|
||||
Assert(noptions <= MAX_HBA_OPTIONS);
|
||||
|
||||
if (noptions > 0)
|
||||
return construct_array(options, noptions, TEXTOID, -1, false, TYPALIGN_INT);
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Number of columns in pg_hba_file_rules view */
|
||||
#define NUM_PG_HBA_FILE_RULES_ATTS 9
|
||||
|
||||
/*
|
||||
* fill_hba_line: build one row of pg_hba_file_rules view, add it to tuplestore
|
||||
*
|
||||
* tuple_store: where to store data
|
||||
* tupdesc: tuple descriptor for the view
|
||||
* lineno: pg_hba.conf line number (must always be valid)
|
||||
* hba: parsed line data (can be NULL, in which case err_msg should be set)
|
||||
* err_msg: error message (NULL if none)
|
||||
*
|
||||
* Note: leaks memory, but we don't care since this is run in a short-lived
|
||||
* memory context.
|
||||
*/
|
||||
static void
|
||||
fill_hba_line(Tuplestorestate *tuple_store, TupleDesc tupdesc,
|
||||
int lineno, HbaLine *hba, const char *err_msg)
|
||||
{
|
||||
Datum values[NUM_PG_HBA_FILE_RULES_ATTS];
|
||||
bool nulls[NUM_PG_HBA_FILE_RULES_ATTS];
|
||||
char buffer[NI_MAXHOST];
|
||||
HeapTuple tuple;
|
||||
int index;
|
||||
ListCell *lc;
|
||||
const char *typestr;
|
||||
const char *addrstr;
|
||||
const char *maskstr;
|
||||
ArrayType *options;
|
||||
|
||||
Assert(tupdesc->natts == NUM_PG_HBA_FILE_RULES_ATTS);
|
||||
|
||||
memset(values, 0, sizeof(values));
|
||||
memset(nulls, 0, sizeof(nulls));
|
||||
index = 0;
|
||||
|
||||
/* line_number */
|
||||
values[index++] = Int32GetDatum(lineno);
|
||||
|
||||
if (hba != NULL)
|
||||
{
|
||||
/* type */
|
||||
/* Avoid a default: case so compiler will warn about missing cases */
|
||||
typestr = NULL;
|
||||
switch (hba->conntype)
|
||||
{
|
||||
case ctLocal:
|
||||
typestr = "local";
|
||||
break;
|
||||
case ctHost:
|
||||
typestr = "host";
|
||||
break;
|
||||
case ctHostSSL:
|
||||
typestr = "hostssl";
|
||||
break;
|
||||
case ctHostNoSSL:
|
||||
typestr = "hostnossl";
|
||||
break;
|
||||
case ctHostGSS:
|
||||
typestr = "hostgssenc";
|
||||
break;
|
||||
case ctHostNoGSS:
|
||||
typestr = "hostnogssenc";
|
||||
break;
|
||||
}
|
||||
if (typestr)
|
||||
values[index++] = CStringGetTextDatum(typestr);
|
||||
else
|
||||
nulls[index++] = true;
|
||||
|
||||
/* database */
|
||||
if (hba->databases)
|
||||
{
|
||||
/*
|
||||
* Flatten HbaToken list to string list. It might seem that we
|
||||
* should re-quote any quoted tokens, but that has been rejected
|
||||
* on the grounds that it makes it harder to compare the array
|
||||
* elements to other system catalogs. That makes entries like
|
||||
* "all" or "samerole" formally ambiguous ... but users who name
|
||||
* databases/roles that way are inflicting their own pain.
|
||||
*/
|
||||
List *names = NIL;
|
||||
|
||||
foreach(lc, hba->databases)
|
||||
{
|
||||
HbaToken *tok = lfirst(lc);
|
||||
|
||||
names = lappend(names, tok->string);
|
||||
}
|
||||
values[index++] = PointerGetDatum(strlist_to_textarray(names));
|
||||
}
|
||||
else
|
||||
nulls[index++] = true;
|
||||
|
||||
/* user */
|
||||
if (hba->roles)
|
||||
{
|
||||
/* Flatten HbaToken list to string list; see comment above */
|
||||
List *roles = NIL;
|
||||
|
||||
foreach(lc, hba->roles)
|
||||
{
|
||||
HbaToken *tok = lfirst(lc);
|
||||
|
||||
roles = lappend(roles, tok->string);
|
||||
}
|
||||
values[index++] = PointerGetDatum(strlist_to_textarray(roles));
|
||||
}
|
||||
else
|
||||
nulls[index++] = true;
|
||||
|
||||
/* address and netmask */
|
||||
/* Avoid a default: case so compiler will warn about missing cases */
|
||||
addrstr = maskstr = NULL;
|
||||
switch (hba->ip_cmp_method)
|
||||
{
|
||||
case ipCmpMask:
|
||||
if (hba->hostname)
|
||||
{
|
||||
addrstr = hba->hostname;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Note: if pg_getnameinfo_all fails, it'll set buffer to
|
||||
* "???", which we want to return.
|
||||
*/
|
||||
if (hba->addrlen > 0)
|
||||
{
|
||||
if (pg_getnameinfo_all(&hba->addr, hba->addrlen,
|
||||
buffer, sizeof(buffer),
|
||||
NULL, 0,
|
||||
NI_NUMERICHOST) == 0)
|
||||
clean_ipv6_addr(hba->addr.ss_family, buffer);
|
||||
addrstr = pstrdup(buffer);
|
||||
}
|
||||
if (hba->masklen > 0)
|
||||
{
|
||||
if (pg_getnameinfo_all(&hba->mask, hba->masklen,
|
||||
buffer, sizeof(buffer),
|
||||
NULL, 0,
|
||||
NI_NUMERICHOST) == 0)
|
||||
clean_ipv6_addr(hba->mask.ss_family, buffer);
|
||||
maskstr = pstrdup(buffer);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ipCmpAll:
|
||||
addrstr = "all";
|
||||
break;
|
||||
case ipCmpSameHost:
|
||||
addrstr = "samehost";
|
||||
break;
|
||||
case ipCmpSameNet:
|
||||
addrstr = "samenet";
|
||||
break;
|
||||
}
|
||||
if (addrstr)
|
||||
values[index++] = CStringGetTextDatum(addrstr);
|
||||
else
|
||||
nulls[index++] = true;
|
||||
if (maskstr)
|
||||
values[index++] = CStringGetTextDatum(maskstr);
|
||||
else
|
||||
nulls[index++] = true;
|
||||
|
||||
/* auth_method */
|
||||
values[index++] = CStringGetTextDatum(hba_authname(hba->auth_method));
|
||||
|
||||
/* options */
|
||||
options = gethba_options(hba);
|
||||
if (options)
|
||||
values[index++] = PointerGetDatum(options);
|
||||
else
|
||||
nulls[index++] = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* no parsing result, so set relevant fields to nulls */
|
||||
memset(&nulls[1], true, (NUM_PG_HBA_FILE_RULES_ATTS - 2) * sizeof(bool));
|
||||
}
|
||||
|
||||
/* error */
|
||||
if (err_msg)
|
||||
values[NUM_PG_HBA_FILE_RULES_ATTS - 1] = CStringGetTextDatum(err_msg);
|
||||
else
|
||||
nulls[NUM_PG_HBA_FILE_RULES_ATTS - 1] = true;
|
||||
|
||||
tuple = heap_form_tuple(tupdesc, values, nulls);
|
||||
tuplestore_puttuple(tuple_store, tuple);
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the pg_hba.conf file and fill the tuplestore with view records.
|
||||
*/
|
||||
static void
|
||||
fill_hba_view(Tuplestorestate *tuple_store, TupleDesc tupdesc)
|
||||
{
|
||||
FILE *file;
|
||||
List *hba_lines = NIL;
|
||||
ListCell *line;
|
||||
MemoryContext linecxt;
|
||||
MemoryContext hbacxt;
|
||||
MemoryContext oldcxt;
|
||||
|
||||
/*
|
||||
* In the unlikely event that we can't open pg_hba.conf, we throw an
|
||||
* error, rather than trying to report it via some sort of view entry.
|
||||
* (Most other error conditions should result in a message in a view
|
||||
* entry.)
|
||||
*/
|
||||
file = AllocateFile(HbaFileName, "r");
|
||||
if (file == NULL)
|
||||
ereport(ERROR,
|
||||
(errcode_for_file_access(),
|
||||
errmsg("could not open configuration file \"%s\": %m",
|
||||
HbaFileName)));
|
||||
|
||||
linecxt = tokenize_file(HbaFileName, file, &hba_lines, DEBUG3);
|
||||
FreeFile(file);
|
||||
|
||||
/* Now parse all the lines */
|
||||
hbacxt = AllocSetContextCreate(CurrentMemoryContext,
|
||||
"hba parser context",
|
||||
ALLOCSET_SMALL_SIZES);
|
||||
oldcxt = MemoryContextSwitchTo(hbacxt);
|
||||
foreach(line, hba_lines)
|
||||
{
|
||||
TokenizedLine *tok_line = (TokenizedLine *) lfirst(line);
|
||||
HbaLine *hbaline = NULL;
|
||||
|
||||
/* don't parse lines that already have errors */
|
||||
if (tok_line->err_msg == NULL)
|
||||
hbaline = parse_hba_line(tok_line, DEBUG3);
|
||||
|
||||
fill_hba_line(tuple_store, tupdesc, tok_line->line_num,
|
||||
hbaline, tok_line->err_msg);
|
||||
}
|
||||
|
||||
/* Free tokenizer memory */
|
||||
MemoryContextDelete(linecxt);
|
||||
/* Free parse_hba_line memory */
|
||||
MemoryContextSwitchTo(oldcxt);
|
||||
MemoryContextDelete(hbacxt);
|
||||
}
|
||||
|
||||
/*
|
||||
* SQL-accessible SRF to return all the entries in the pg_hba.conf file.
|
||||
*/
|
||||
Datum
|
||||
pg_hba_file_rules(PG_FUNCTION_ARGS)
|
||||
{
|
||||
ReturnSetInfo *rsi;
|
||||
|
||||
/*
|
||||
* Build tuplestore to hold the result rows. We must use the Materialize
|
||||
* mode to be safe against HBA file changes while the cursor is open.
|
||||
* It's also more efficient than having to look up our current position in
|
||||
* the parsed list every time.
|
||||
*/
|
||||
SetSingleFuncCall(fcinfo, 0);
|
||||
|
||||
/* Fill the tuplestore */
|
||||
rsi = (ReturnSetInfo *) fcinfo->resultinfo;
|
||||
fill_hba_view(rsi->setResult, rsi->setDesc);
|
||||
|
||||
PG_RETURN_NULL();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Parse one tokenised line from the ident config file and store the result in
|
||||
@ -2735,12 +2316,12 @@ pg_hba_file_rules(PG_FUNCTION_ARGS)
|
||||
* NULL.
|
||||
*/
|
||||
static IdentLine *
|
||||
parse_ident_line(TokenizedLine *tok_line)
|
||||
parse_ident_line(TokenizedAuthLine *tok_line)
|
||||
{
|
||||
int line_num = tok_line->line_num;
|
||||
ListCell *field;
|
||||
List *tokens;
|
||||
HbaToken *token;
|
||||
AuthToken *token;
|
||||
IdentLine *parsedline;
|
||||
|
||||
Assert(tok_line->fields != NIL);
|
||||
@ -3026,7 +2607,7 @@ load_ident(void)
|
||||
return false;
|
||||
}
|
||||
|
||||
linecxt = tokenize_file(IdentFileName, file, &ident_lines, LOG);
|
||||
linecxt = tokenize_auth_file(IdentFileName, file, &ident_lines, LOG);
|
||||
FreeFile(file);
|
||||
|
||||
/* Now parse all the lines */
|
||||
@ -3037,7 +2618,7 @@ load_ident(void)
|
||||
oldcxt = MemoryContextSwitchTo(ident_context);
|
||||
foreach(line_cell, ident_lines)
|
||||
{
|
||||
TokenizedLine *tok_line = (TokenizedLine *) lfirst(line_cell);
|
||||
TokenizedAuthLine *tok_line = (TokenizedAuthLine *) lfirst(line_cell);
|
||||
|
||||
/* don't parse lines that already have errors */
|
||||
if (tok_line->err_msg != NULL)
|
||||
|
@ -42,6 +42,7 @@ OBJS = \
|
||||
geo_ops.o \
|
||||
geo_selfuncs.o \
|
||||
geo_spgist.o \
|
||||
hbafuncs.o \
|
||||
inet_cidr_ntop.o \
|
||||
inet_net_pton.o \
|
||||
int.o \
|
||||
|
428
src/backend/utils/adt/hbafuncs.c
Normal file
428
src/backend/utils/adt/hbafuncs.c
Normal file
@ -0,0 +1,428 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* hbafuncs.c
|
||||
* Support functions for SQL views of authentication files.
|
||||
*
|
||||
* Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* src/backend/utils/adt/hbafuncs.c
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
#include "postgres.h"
|
||||
|
||||
#include "catalog/objectaddress.h"
|
||||
#include "common/ip.h"
|
||||
#include "funcapi.h"
|
||||
#include "libpq/hba.h"
|
||||
#include "miscadmin.h"
|
||||
#include "utils/array.h"
|
||||
#include "utils/builtins.h"
|
||||
#include "utils/guc.h"
|
||||
|
||||
|
||||
static ArrayType *get_hba_options(HbaLine *hba);
|
||||
static void fill_hba_line(Tuplestorestate *tuple_store, TupleDesc tupdesc,
|
||||
int lineno, HbaLine *hba, const char *err_msg);
|
||||
static void fill_hba_view(Tuplestorestate *tuple_store, TupleDesc tupdesc);
|
||||
|
||||
|
||||
/*
|
||||
* This macro specifies the maximum number of authentication options
|
||||
* that are possible with any given authentication method that is supported.
|
||||
* Currently LDAP supports 11, and there are 3 that are not dependent on
|
||||
* the auth method here. It may not actually be possible to set all of them
|
||||
* at the same time, but we'll set the macro value high enough to be
|
||||
* conservative and avoid warnings from static analysis tools.
|
||||
*/
|
||||
#define MAX_HBA_OPTIONS 14
|
||||
|
||||
/*
|
||||
* Create a text array listing the options specified in the HBA line.
|
||||
* Return NULL if no options are specified.
|
||||
*/
|
||||
static ArrayType *
|
||||
get_hba_options(HbaLine *hba)
|
||||
{
|
||||
int noptions;
|
||||
Datum options[MAX_HBA_OPTIONS];
|
||||
|
||||
noptions = 0;
|
||||
|
||||
if (hba->auth_method == uaGSS || hba->auth_method == uaSSPI)
|
||||
{
|
||||
if (hba->include_realm)
|
||||
options[noptions++] =
|
||||
CStringGetTextDatum("include_realm=true");
|
||||
|
||||
if (hba->krb_realm)
|
||||
options[noptions++] =
|
||||
CStringGetTextDatum(psprintf("krb_realm=%s", hba->krb_realm));
|
||||
}
|
||||
|
||||
if (hba->usermap)
|
||||
options[noptions++] =
|
||||
CStringGetTextDatum(psprintf("map=%s", hba->usermap));
|
||||
|
||||
if (hba->clientcert != clientCertOff)
|
||||
options[noptions++] =
|
||||
CStringGetTextDatum(psprintf("clientcert=%s", (hba->clientcert == clientCertCA) ? "verify-ca" : "verify-full"));
|
||||
|
||||
if (hba->pamservice)
|
||||
options[noptions++] =
|
||||
CStringGetTextDatum(psprintf("pamservice=%s", hba->pamservice));
|
||||
|
||||
if (hba->auth_method == uaLDAP)
|
||||
{
|
||||
if (hba->ldapserver)
|
||||
options[noptions++] =
|
||||
CStringGetTextDatum(psprintf("ldapserver=%s", hba->ldapserver));
|
||||
|
||||
if (hba->ldapport)
|
||||
options[noptions++] =
|
||||
CStringGetTextDatum(psprintf("ldapport=%d", hba->ldapport));
|
||||
|
||||
if (hba->ldaptls)
|
||||
options[noptions++] =
|
||||
CStringGetTextDatum("ldaptls=true");
|
||||
|
||||
if (hba->ldapprefix)
|
||||
options[noptions++] =
|
||||
CStringGetTextDatum(psprintf("ldapprefix=%s", hba->ldapprefix));
|
||||
|
||||
if (hba->ldapsuffix)
|
||||
options[noptions++] =
|
||||
CStringGetTextDatum(psprintf("ldapsuffix=%s", hba->ldapsuffix));
|
||||
|
||||
if (hba->ldapbasedn)
|
||||
options[noptions++] =
|
||||
CStringGetTextDatum(psprintf("ldapbasedn=%s", hba->ldapbasedn));
|
||||
|
||||
if (hba->ldapbinddn)
|
||||
options[noptions++] =
|
||||
CStringGetTextDatum(psprintf("ldapbinddn=%s", hba->ldapbinddn));
|
||||
|
||||
if (hba->ldapbindpasswd)
|
||||
options[noptions++] =
|
||||
CStringGetTextDatum(psprintf("ldapbindpasswd=%s",
|
||||
hba->ldapbindpasswd));
|
||||
|
||||
if (hba->ldapsearchattribute)
|
||||
options[noptions++] =
|
||||
CStringGetTextDatum(psprintf("ldapsearchattribute=%s",
|
||||
hba->ldapsearchattribute));
|
||||
|
||||
if (hba->ldapsearchfilter)
|
||||
options[noptions++] =
|
||||
CStringGetTextDatum(psprintf("ldapsearchfilter=%s",
|
||||
hba->ldapsearchfilter));
|
||||
|
||||
if (hba->ldapscope)
|
||||
options[noptions++] =
|
||||
CStringGetTextDatum(psprintf("ldapscope=%d", hba->ldapscope));
|
||||
}
|
||||
|
||||
if (hba->auth_method == uaRADIUS)
|
||||
{
|
||||
if (hba->radiusservers_s)
|
||||
options[noptions++] =
|
||||
CStringGetTextDatum(psprintf("radiusservers=%s", hba->radiusservers_s));
|
||||
|
||||
if (hba->radiussecrets_s)
|
||||
options[noptions++] =
|
||||
CStringGetTextDatum(psprintf("radiussecrets=%s", hba->radiussecrets_s));
|
||||
|
||||
if (hba->radiusidentifiers_s)
|
||||
options[noptions++] =
|
||||
CStringGetTextDatum(psprintf("radiusidentifiers=%s", hba->radiusidentifiers_s));
|
||||
|
||||
if (hba->radiusports_s)
|
||||
options[noptions++] =
|
||||
CStringGetTextDatum(psprintf("radiusports=%s", hba->radiusports_s));
|
||||
}
|
||||
|
||||
/* If you add more options, consider increasing MAX_HBA_OPTIONS. */
|
||||
Assert(noptions <= MAX_HBA_OPTIONS);
|
||||
|
||||
if (noptions > 0)
|
||||
return construct_array(options, noptions, TEXTOID, -1, false, TYPALIGN_INT);
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Number of columns in pg_hba_file_rules view */
|
||||
#define NUM_PG_HBA_FILE_RULES_ATTS 9
|
||||
|
||||
/*
|
||||
* fill_hba_line
|
||||
* Build one row of pg_hba_file_rules view, add it to tuplestore.
|
||||
*
|
||||
* tuple_store: where to store data
|
||||
* tupdesc: tuple descriptor for the view
|
||||
* lineno: pg_hba.conf line number (must always be valid)
|
||||
* hba: parsed line data (can be NULL, in which case err_msg should be set)
|
||||
* err_msg: error message (NULL if none)
|
||||
*
|
||||
* Note: leaks memory, but we don't care since this is run in a short-lived
|
||||
* memory context.
|
||||
*/
|
||||
static void
|
||||
fill_hba_line(Tuplestorestate *tuple_store, TupleDesc tupdesc,
|
||||
int lineno, HbaLine *hba, const char *err_msg)
|
||||
{
|
||||
Datum values[NUM_PG_HBA_FILE_RULES_ATTS];
|
||||
bool nulls[NUM_PG_HBA_FILE_RULES_ATTS];
|
||||
char buffer[NI_MAXHOST];
|
||||
HeapTuple tuple;
|
||||
int index;
|
||||
ListCell *lc;
|
||||
const char *typestr;
|
||||
const char *addrstr;
|
||||
const char *maskstr;
|
||||
ArrayType *options;
|
||||
|
||||
Assert(tupdesc->natts == NUM_PG_HBA_FILE_RULES_ATTS);
|
||||
|
||||
memset(values, 0, sizeof(values));
|
||||
memset(nulls, 0, sizeof(nulls));
|
||||
index = 0;
|
||||
|
||||
/* line_number */
|
||||
values[index++] = Int32GetDatum(lineno);
|
||||
|
||||
if (hba != NULL)
|
||||
{
|
||||
/* type */
|
||||
/* Avoid a default: case so compiler will warn about missing cases */
|
||||
typestr = NULL;
|
||||
switch (hba->conntype)
|
||||
{
|
||||
case ctLocal:
|
||||
typestr = "local";
|
||||
break;
|
||||
case ctHost:
|
||||
typestr = "host";
|
||||
break;
|
||||
case ctHostSSL:
|
||||
typestr = "hostssl";
|
||||
break;
|
||||
case ctHostNoSSL:
|
||||
typestr = "hostnossl";
|
||||
break;
|
||||
case ctHostGSS:
|
||||
typestr = "hostgssenc";
|
||||
break;
|
||||
case ctHostNoGSS:
|
||||
typestr = "hostnogssenc";
|
||||
break;
|
||||
}
|
||||
if (typestr)
|
||||
values[index++] = CStringGetTextDatum(typestr);
|
||||
else
|
||||
nulls[index++] = true;
|
||||
|
||||
/* database */
|
||||
if (hba->databases)
|
||||
{
|
||||
/*
|
||||
* Flatten AuthToken list to string list. It might seem that we
|
||||
* should re-quote any quoted tokens, but that has been rejected
|
||||
* on the grounds that it makes it harder to compare the array
|
||||
* elements to other system catalogs. That makes entries like
|
||||
* "all" or "samerole" formally ambiguous ... but users who name
|
||||
* databases/roles that way are inflicting their own pain.
|
||||
*/
|
||||
List *names = NIL;
|
||||
|
||||
foreach(lc, hba->databases)
|
||||
{
|
||||
AuthToken *tok = lfirst(lc);
|
||||
|
||||
names = lappend(names, tok->string);
|
||||
}
|
||||
values[index++] = PointerGetDatum(strlist_to_textarray(names));
|
||||
}
|
||||
else
|
||||
nulls[index++] = true;
|
||||
|
||||
/* user */
|
||||
if (hba->roles)
|
||||
{
|
||||
/* Flatten AuthToken list to string list; see comment above */
|
||||
List *roles = NIL;
|
||||
|
||||
foreach(lc, hba->roles)
|
||||
{
|
||||
AuthToken *tok = lfirst(lc);
|
||||
|
||||
roles = lappend(roles, tok->string);
|
||||
}
|
||||
values[index++] = PointerGetDatum(strlist_to_textarray(roles));
|
||||
}
|
||||
else
|
||||
nulls[index++] = true;
|
||||
|
||||
/* address and netmask */
|
||||
/* Avoid a default: case so compiler will warn about missing cases */
|
||||
addrstr = maskstr = NULL;
|
||||
switch (hba->ip_cmp_method)
|
||||
{
|
||||
case ipCmpMask:
|
||||
if (hba->hostname)
|
||||
{
|
||||
addrstr = hba->hostname;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Note: if pg_getnameinfo_all fails, it'll set buffer to
|
||||
* "???", which we want to return.
|
||||
*/
|
||||
if (hba->addrlen > 0)
|
||||
{
|
||||
if (pg_getnameinfo_all(&hba->addr, hba->addrlen,
|
||||
buffer, sizeof(buffer),
|
||||
NULL, 0,
|
||||
NI_NUMERICHOST) == 0)
|
||||
clean_ipv6_addr(hba->addr.ss_family, buffer);
|
||||
addrstr = pstrdup(buffer);
|
||||
}
|
||||
if (hba->masklen > 0)
|
||||
{
|
||||
if (pg_getnameinfo_all(&hba->mask, hba->masklen,
|
||||
buffer, sizeof(buffer),
|
||||
NULL, 0,
|
||||
NI_NUMERICHOST) == 0)
|
||||
clean_ipv6_addr(hba->mask.ss_family, buffer);
|
||||
maskstr = pstrdup(buffer);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ipCmpAll:
|
||||
addrstr = "all";
|
||||
break;
|
||||
case ipCmpSameHost:
|
||||
addrstr = "samehost";
|
||||
break;
|
||||
case ipCmpSameNet:
|
||||
addrstr = "samenet";
|
||||
break;
|
||||
}
|
||||
if (addrstr)
|
||||
values[index++] = CStringGetTextDatum(addrstr);
|
||||
else
|
||||
nulls[index++] = true;
|
||||
if (maskstr)
|
||||
values[index++] = CStringGetTextDatum(maskstr);
|
||||
else
|
||||
nulls[index++] = true;
|
||||
|
||||
/* auth_method */
|
||||
values[index++] = CStringGetTextDatum(hba_authname(hba->auth_method));
|
||||
|
||||
/* options */
|
||||
options = get_hba_options(hba);
|
||||
if (options)
|
||||
values[index++] = PointerGetDatum(options);
|
||||
else
|
||||
nulls[index++] = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* no parsing result, so set relevant fields to nulls */
|
||||
memset(&nulls[1], true, (NUM_PG_HBA_FILE_RULES_ATTS - 2) * sizeof(bool));
|
||||
}
|
||||
|
||||
/* error */
|
||||
if (err_msg)
|
||||
values[NUM_PG_HBA_FILE_RULES_ATTS - 1] = CStringGetTextDatum(err_msg);
|
||||
else
|
||||
nulls[NUM_PG_HBA_FILE_RULES_ATTS - 1] = true;
|
||||
|
||||
tuple = heap_form_tuple(tupdesc, values, nulls);
|
||||
tuplestore_puttuple(tuple_store, tuple);
|
||||
}
|
||||
|
||||
/*
|
||||
* fill_hba_view
|
||||
* Read the pg_hba.conf file and fill the tuplestore with view records.
|
||||
*/
|
||||
static void
|
||||
fill_hba_view(Tuplestorestate *tuple_store, TupleDesc tupdesc)
|
||||
{
|
||||
FILE *file;
|
||||
List *hba_lines = NIL;
|
||||
ListCell *line;
|
||||
MemoryContext linecxt;
|
||||
MemoryContext hbacxt;
|
||||
MemoryContext oldcxt;
|
||||
|
||||
/*
|
||||
* In the unlikely event that we can't open pg_hba.conf, we throw an
|
||||
* error, rather than trying to report it via some sort of view entry.
|
||||
* (Most other error conditions should result in a message in a view
|
||||
* entry.)
|
||||
*/
|
||||
file = AllocateFile(HbaFileName, "r");
|
||||
if (file == NULL)
|
||||
ereport(ERROR,
|
||||
(errcode_for_file_access(),
|
||||
errmsg("could not open configuration file \"%s\": %m",
|
||||
HbaFileName)));
|
||||
|
||||
linecxt = tokenize_auth_file(HbaFileName, file, &hba_lines, DEBUG3);
|
||||
FreeFile(file);
|
||||
|
||||
/* Now parse all the lines */
|
||||
hbacxt = AllocSetContextCreate(CurrentMemoryContext,
|
||||
"hba parser context",
|
||||
ALLOCSET_SMALL_SIZES);
|
||||
oldcxt = MemoryContextSwitchTo(hbacxt);
|
||||
foreach(line, hba_lines)
|
||||
{
|
||||
TokenizedAuthLine *tok_line = (TokenizedAuthLine *) lfirst(line);
|
||||
HbaLine *hbaline = NULL;
|
||||
|
||||
/* don't parse lines that already have errors */
|
||||
if (tok_line->err_msg == NULL)
|
||||
hbaline = parse_hba_line(tok_line, DEBUG3);
|
||||
|
||||
fill_hba_line(tuple_store, tupdesc, tok_line->line_num,
|
||||
hbaline, tok_line->err_msg);
|
||||
}
|
||||
|
||||
/* Free tokenizer memory */
|
||||
MemoryContextDelete(linecxt);
|
||||
/* Free parse_hba_line memory */
|
||||
MemoryContextSwitchTo(oldcxt);
|
||||
MemoryContextDelete(hbacxt);
|
||||
}
|
||||
|
||||
/*
|
||||
* pg_hba_file_rules
|
||||
*
|
||||
* SQL-accessible set-returning function to return all the entries in the
|
||||
* pg_hba.conf file.
|
||||
*/
|
||||
Datum
|
||||
pg_hba_file_rules(PG_FUNCTION_ARGS)
|
||||
{
|
||||
ReturnSetInfo *rsi;
|
||||
|
||||
/*
|
||||
* Build tuplestore to hold the result rows. We must use the Materialize
|
||||
* mode to be safe against HBA file changes while the cursor is open. It's
|
||||
* also more efficient than having to look up our current position in the
|
||||
* parsed list every time.
|
||||
*/
|
||||
SetSingleFuncCall(fcinfo, 0);
|
||||
|
||||
/* Fill the tuplestore */
|
||||
rsi = (ReturnSetInfo *) fcinfo->resultinfo;
|
||||
fill_hba_view(rsi->setResult, rsi->setDesc);
|
||||
|
||||
PG_RETURN_NULL();
|
||||
}
|
@ -132,6 +132,34 @@ typedef struct IdentLine
|
||||
regex_t re;
|
||||
} IdentLine;
|
||||
|
||||
/*
|
||||
* A single string token lexed from an authentication configuration file
|
||||
* (pg_ident.conf or pg_hba.conf), together with whether the token has
|
||||
* been quoted.
|
||||
*/
|
||||
typedef struct AuthToken
|
||||
{
|
||||
char *string;
|
||||
bool quoted;
|
||||
} AuthToken;
|
||||
|
||||
/*
|
||||
* TokenizedAuthLine represents one line lexed from an authentication
|
||||
* configuration file. Each item in the "fields" list is a sub-list of
|
||||
* AuthTokens. We don't emit a TokenizedAuthLine for empty or all-comment
|
||||
* lines, so "fields" is never NIL (nor are any of its sub-lists).
|
||||
*
|
||||
* Exception: if an error occurs during tokenization, we might have
|
||||
* fields == NIL, in which case err_msg != NULL.
|
||||
*/
|
||||
typedef struct TokenizedAuthLine
|
||||
{
|
||||
List *fields; /* List of lists of AuthTokens */
|
||||
int line_num; /* Line number */
|
||||
char *raw_line; /* Raw line text */
|
||||
char *err_msg; /* Error message if any */
|
||||
} TokenizedAuthLine;
|
||||
|
||||
/* kluge to avoid including libpq/libpq-be.h here */
|
||||
typedef struct Port hbaPort;
|
||||
|
||||
@ -142,6 +170,9 @@ extern void hba_getauthmethod(hbaPort *port);
|
||||
extern int check_usermap(const char *usermap_name,
|
||||
const char *pg_role, const char *auth_user,
|
||||
bool case_sensitive);
|
||||
extern HbaLine *parse_hba_line(TokenizedAuthLine *tok_line, int elevel);
|
||||
extern bool pg_isblank(const char c);
|
||||
extern MemoryContext tokenize_auth_file(const char *filename, FILE *file,
|
||||
List **tok_lines, int elevel);
|
||||
|
||||
#endif /* HBA_H */
|
||||
|
@ -153,6 +153,7 @@ AttrMissing
|
||||
AttrNumber
|
||||
AttributeOpts
|
||||
AuthRequest
|
||||
AuthToken
|
||||
AutoPrewarmSharedState
|
||||
AutoVacOpts
|
||||
AutoVacuumShmemStruct
|
||||
@ -1063,7 +1064,6 @@ HashState
|
||||
HashTapeInfo
|
||||
HashValueFunc
|
||||
HbaLine
|
||||
HbaToken
|
||||
HeadlineJsonState
|
||||
HeadlineParsedText
|
||||
HeadlineWordEntry
|
||||
@ -2699,7 +2699,7 @@ ToastTupleContext
|
||||
ToastedAttribute
|
||||
TocEntry
|
||||
TokenAuxData
|
||||
TokenizedLine
|
||||
TokenizedAuthLine
|
||||
TrackItem
|
||||
TransInvalidationInfo
|
||||
TransState
|
||||
|
Loading…
x
Reference in New Issue
Block a user