diff --git a/doc/src/sgml/client-auth.sgml b/doc/src/sgml/client-auth.sgml index 126d3a810d..edcefa6903 100644 --- a/doc/src/sgml/client-auth.sgml +++ b/doc/src/sgml/client-auth.sgml @@ -1,5 +1,5 @@ @@ -175,8 +175,7 @@ hostnossl database user a specific PostgreSQL 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 @. The file must be in - the same directory as pg_hba.conf. + preceding the file name with @. @@ -192,8 +191,7 @@ hostnossl database user can be supplied by separating them with commas. Group names can be specified by preceding the group name with +. A file containing user names can be specified by preceding the - file name with @. The file must be in the same - directory as pg_hba.conf. + file name with @. @@ -393,6 +391,16 @@ hostnossl database user + + Files included by @ constructs are read as lists of names, + which can be separated by either whitespace or commas. Comments are + introduced by #, just as in + pg_hba.conf, and nested @ constructs are + allowed. Unless the file name following @ is an absolute + path, it is taken to be relative to the directory containing the + referencing file. + + Since the pg_hba.conf records are examined sequentially for each connection attempt, the order of the records is diff --git a/src/backend/libpq/hba.c b/src/backend/libpq/hba.c index 40ff28059a..190f582550 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); } }