aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/src/sgml/client-auth.sgml18
-rw-r--r--src/backend/libpq/hba.c158
2 files changed, 95 insertions, 81 deletions
diff --git a/doc/src/sgml/client-auth.sgml b/doc/src/sgml/client-auth.sgml
index 126d3a810df..edcefa6903e 100644
--- a/doc/src/sgml/client-auth.sgml
+++ b/doc/src/sgml/client-auth.sgml
@@ -1,5 +1,5 @@
<!--
-$PostgreSQL: pgsql/doc/src/sgml/client-auth.sgml,v 1.69 2004/12/26 23:06:56 tgl Exp $
+$PostgreSQL: pgsql/doc/src/sgml/client-auth.sgml,v 1.70 2004/12/27 19:19:23 tgl Exp $
-->
<chapter id="client-authentication">
@@ -175,8 +175,7 @@ hostnossl <replaceable>database</replaceable> <replaceable>user</replaceable>
a specific <productname>PostgreSQL</productname> database.
Multiple database names can be supplied by separating them with
commas. A file containing database names can be specified by
- preceding the file name with <literal>@</>. The file must be in
- the same directory as <filename>pg_hba.conf</>.
+ preceding the file name with <literal>@</>.
</para>
</listitem>
</varlistentry>
@@ -192,8 +191,7 @@ hostnossl <replaceable>database</replaceable> <replaceable>user</replaceable>
can be supplied by separating them with commas. Group names can
be specified by preceding the group name with <literal>+</>. A
file containing user names can be specified by preceding the
- file name with <literal>@</>. The file must be in the same
- directory as <filename>pg_hba.conf</>.
+ file name with <literal>@</>.
</para>
</listitem>
</varlistentry>
@@ -394,6 +392,16 @@ hostnossl <replaceable>database</replaceable> <replaceable>user</replaceable>
</para>
<para>
+ Files included by <literal>@</> constructs are read as lists of names,
+ which can be separated by either whitespace or commas. Comments are
+ introduced by <literal>#</literal>, just as in
+ <filename>pg_hba.conf</filename>, and nested <literal>@</> constructs are
+ allowed. Unless the file name following <literal>@</> is an absolute
+ path, it is taken to be relative to the directory containing the
+ referencing file.
+ </para>
+
+ <para>
Since the <filename>pg_hba.conf</filename> records are examined
sequentially for each connection attempt, the order of the records is
significant. Typically, earlier records will have tight connection
diff --git a/src/backend/libpq/hba.c b/src/backend/libpq/hba.c
index 40ff28059a4..190f582550a 100644
--- a/src/backend/libpq/hba.c
+++ b/src/backend/libpq/hba.c
@@ -10,7 +10,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/libpq/hba.c,v 1.134 2004/11/17 19:54:24 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/libpq/hba.c,v 1.135 2004/12/27 19:19:24 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -82,8 +82,10 @@ static List **group_sorted = NULL; /* sorted group list, for
static int user_length;
static int group_length;
-static void tokenize_file(FILE *file, List **lines, List **line_nums);
-static char *tokenize_inc_file(const char *inc_filename);
+static void tokenize_file(const char *filename, FILE *file,
+ List **lines, List **line_nums);
+static char *tokenize_inc_file(const char *outer_filename,
+ const char *inc_filename);
/*
* isblank() exists in the ISO C99 spec, but it's not very portable yet,
@@ -212,7 +214,7 @@ next_token(FILE *fp, char *buf, int bufsz)
* we have reached EOL.
*/
static char *
-next_token_expand(FILE *file)
+next_token_expand(const char *filename, FILE *file)
{
char buf[MAX_TOKEN];
char *comma_str = pstrdup("");
@@ -236,7 +238,7 @@ next_token_expand(FILE *file)
/* Is this referencing a file? */
if (buf[0] == '@')
- incbuf = tokenize_inc_file(buf + 1);
+ incbuf = tokenize_inc_file(filename, buf + 1);
else
incbuf = pstrdup(buf);
@@ -301,23 +303,34 @@ free_lines(List **lines, List **line_nums)
static char *
-tokenize_inc_file(const char *inc_filename)
+tokenize_inc_file(const char *outer_filename,
+ const char *inc_filename)
{
char *inc_fullname;
FILE *inc_file;
List *inc_lines;
List *inc_line_nums;
ListCell *line;
- char *comma_str = pstrdup("");
+ char *comma_str;
- inc_fullname = (char *) palloc(strlen(DataDir) + 1 +
- strlen(inc_filename) + 1);
- strcpy(inc_fullname, DataDir);
- strcat(inc_fullname, "/");
- strcat(inc_fullname, inc_filename);
+ if (is_absolute_path(inc_filename))
+ {
+ /* absolute path is taken as-is */
+ inc_fullname = pstrdup(inc_filename);
+ }
+ else
+ {
+ /* relative path is relative to dir of calling file */
+ inc_fullname = (char *) palloc(strlen(outer_filename) + 1 +
+ strlen(inc_filename) + 1);
+ strcpy(inc_fullname, outer_filename);
+ get_parent_directory(inc_fullname);
+ join_path_components(inc_fullname, inc_fullname, inc_filename);
+ canonicalize_path(inc_fullname);
+ }
inc_file = AllocateFile(inc_fullname, "r");
- if (!inc_file)
+ if (inc_file == NULL)
{
ereport(LOG,
(errcode_for_file_access(),
@@ -325,16 +338,18 @@ tokenize_inc_file(const char *inc_filename)
inc_filename, inc_fullname)));
pfree(inc_fullname);
- /* return empty string, it matches nothing */
- return comma_str;
+ /* return single space, it matches nothing */
+ return pstrdup(" ");
}
- pfree(inc_fullname);
/* There is possible recursion here if the file contains @ */
- tokenize_file(inc_file, &inc_lines, &inc_line_nums);
+ tokenize_file(inc_fullname, inc_file, &inc_lines, &inc_line_nums);
+
FreeFile(inc_file);
+ pfree(inc_fullname);
/* Create comma-separated string from List */
+ comma_str = pstrdup("");
foreach(line, inc_lines)
{
List *token_list = (List *) lfirst(line);
@@ -357,6 +372,13 @@ tokenize_inc_file(const char *inc_filename)
free_lines(&inc_lines, &inc_line_nums);
+ /* if file is empty, return single space rather than empty string */
+ if (strlen(comma_str) == 0)
+ {
+ pfree(comma_str);
+ return pstrdup(" ");
+ }
+
return comma_str;
}
@@ -365,9 +387,12 @@ tokenize_inc_file(const char *inc_filename)
* Tokenize the given file, storing the resulting data into two lists:
* a list of sublists, each sublist containing the tokens in a line of
* the file, and a list of line numbers.
+ *
+ * filename must be the absolute path to the target file.
*/
static void
-tokenize_file(FILE *file, List **lines, List **line_nums)
+tokenize_file(const char *filename, FILE *file,
+ List **lines, List **line_nums)
{
List *current_line = NIL;
int line_number = 1;
@@ -377,7 +402,7 @@ tokenize_file(FILE *file, List **lines, List **line_nums)
while (!feof(file))
{
- buf = next_token_expand(file);
+ buf = next_token_expand(filename, file);
/* add token to list, unless we are at EOL or comment start */
if (buf[0])
@@ -893,61 +918,13 @@ check_hba(hbaPort *port)
}
-
-/*
- * Open the group file if possible (return NULL if not)
- */
-static FILE *
-group_openfile(void)
-{
- char *filename;
- FILE *groupfile;
-
- filename = group_getfilename();
- groupfile = AllocateFile(filename, "r");
-
- if (groupfile == NULL && errno != ENOENT)
- ereport(LOG,
- (errcode_for_file_access(),
- errmsg("could not open file \"%s\": %m", filename)));
-
- pfree(filename);
-
- return groupfile;
-}
-
-
-
-/*
- * Open the password file if possible (return NULL if not)
- */
-static FILE *
-user_openfile(void)
-{
- char *filename;
- FILE *pwdfile;
-
- filename = user_getfilename();
- pwdfile = AllocateFile(filename, "r");
-
- if (pwdfile == NULL && errno != ENOENT)
- ereport(LOG,
- (errcode_for_file_access(),
- errmsg("could not open file \"%s\": %m", filename)));
-
- pfree(filename);
-
- return pwdfile;
-}
-
-
-
/*
* Load group/user name mapping file
*/
void
load_group(void)
{
+ char *filename;
FILE *group_file;
/* Discard any old data */
@@ -958,11 +935,25 @@ load_group(void)
group_sorted = NULL;
group_length = 0;
- group_file = group_openfile();
- if (!group_file)
+ /* Read in the file contents */
+ filename = group_getfilename();
+ group_file = AllocateFile(filename, "r");
+
+ if (group_file == NULL)
+ {
+ /* no complaint if not there */
+ if (errno != ENOENT)
+ ereport(LOG,
+ (errcode_for_file_access(),
+ errmsg("could not open file \"%s\": %m", filename)));
+ pfree(filename);
return;
- tokenize_file(group_file, &group_lines, &group_line_nums);
+ }
+
+ tokenize_file(filename, group_file, &group_lines, &group_line_nums);
+
FreeFile(group_file);
+ pfree(filename);
/* create sorted lines for binary searching */
group_length = list_length(group_lines);
@@ -990,6 +981,7 @@ load_group(void)
void
load_user(void)
{
+ char *filename;
FILE *user_file;
/* Discard any old data */
@@ -1000,11 +992,25 @@ load_user(void)
user_sorted = NULL;
user_length = 0;
- user_file = user_openfile();
- if (!user_file)
+ /* Read in the file contents */
+ filename = user_getfilename();
+ user_file = AllocateFile(filename, "r");
+
+ if (user_file == NULL)
+ {
+ /* no complaint if not there */
+ if (errno != ENOENT)
+ ereport(LOG,
+ (errcode_for_file_access(),
+ errmsg("could not open file \"%s\": %m", filename)));
+ pfree(filename);
return;
- tokenize_file(user_file, &user_lines, &user_line_nums);
+ }
+
+ tokenize_file(filename, user_file, &user_lines, &user_line_nums);
+
FreeFile(user_file);
+ pfree(filename);
/* create sorted lines for binary searching */
user_length = list_length(user_lines);
@@ -1045,7 +1051,7 @@ load_hba(void)
errmsg("could not open configuration file \"%s\": %m",
HbaFileName)));
- tokenize_file(file, &hba_lines, &hba_line_nums);
+ tokenize_file(HbaFileName, file, &hba_lines, &hba_line_nums);
FreeFile(file);
}
@@ -1189,7 +1195,7 @@ load_ident(void)
}
else
{
- tokenize_file(file, &ident_lines, &ident_line_nums);
+ tokenize_file(IdentFileName, file, &ident_lines, &ident_line_nums);
FreeFile(file);
}
}