Add a GUC_SUPERUSER_ONLY flag to mark GUC variables that should not be

examinable by non-superusers, and use it to protect the recently-added
GUC variables for data directory and config files.  For now I have only
flagged those variables that could be used to deduce something about
the server's filesystem layout, but possibly we should also mark vars
related to logging settings and other admin-only information?
This commit is contained in:
Tom Lane 2004-10-22 19:48:19 +00:00
parent 9309d5f2ba
commit 9e83d73b6c
3 changed files with 53 additions and 25 deletions

View File

@ -10,7 +10,7 @@
* Written by Peter Eisentraut <peter_e@gmx.net>. * Written by Peter Eisentraut <peter_e@gmx.net>.
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.245 2004/10/17 22:01:51 tgl Exp $ * $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.246 2004/10/22 19:48:19 tgl Exp $
* *
*-------------------------------------------------------------------- *--------------------------------------------------------------------
*/ */
@ -1522,7 +1522,8 @@ static struct config_string ConfigureNamesString[] =
gettext_noop("If a dynamically loadable module needs to be opened and " gettext_noop("If a dynamically loadable module needs to be opened and "
"the specified name does not have a directory component (i.e., the " "the specified name does not have a directory component (i.e., the "
"name does not contain a slash), the system will search this path for " "name does not contain a slash), the system will search this path for "
"the specified file.") "the specified file."),
GUC_SUPERUSER_ONLY
}, },
&Dynamic_library_path, &Dynamic_library_path,
"$libdir", NULL, NULL "$libdir", NULL, NULL
@ -1531,7 +1532,8 @@ static struct config_string ConfigureNamesString[] =
{ {
{"krb_server_keyfile", PGC_POSTMASTER, CONN_AUTH_SECURITY, {"krb_server_keyfile", PGC_POSTMASTER, CONN_AUTH_SECURITY,
gettext_noop("Sets the location of the Kerberos server key file."), gettext_noop("Sets the location of the Kerberos server key file."),
NULL NULL,
GUC_SUPERUSER_ONLY
}, },
&pg_krb_server_keyfile, &pg_krb_server_keyfile,
PG_KRB_SRVTAB, NULL, NULL PG_KRB_SRVTAB, NULL, NULL
@ -1608,7 +1610,7 @@ static struct config_string ConfigureNamesString[] =
{"preload_libraries", PGC_POSTMASTER, RESOURCES_KERNEL, {"preload_libraries", PGC_POSTMASTER, RESOURCES_KERNEL,
gettext_noop("Lists shared libraries to preload into server."), gettext_noop("Lists shared libraries to preload into server."),
NULL, NULL,
GUC_LIST_INPUT | GUC_LIST_QUOTE GUC_LIST_INPUT | GUC_LIST_QUOTE | GUC_SUPERUSER_ONLY
}, },
&preload_libraries_string, &preload_libraries_string,
"", NULL, NULL "", NULL, NULL
@ -1680,7 +1682,8 @@ static struct config_string ConfigureNamesString[] =
{"log_directory", PGC_SIGHUP, LOGGING_WHERE, {"log_directory", PGC_SIGHUP, LOGGING_WHERE,
gettext_noop("Sets the destination directory for log files."), gettext_noop("Sets the destination directory for log files."),
gettext_noop("May be specified as relative to the data directory " gettext_noop("May be specified as relative to the data directory "
"or as absolute path.") "or as absolute path."),
GUC_SUPERUSER_ONLY
}, },
&Log_directory, &Log_directory,
"pg_log", assign_canonical_path, NULL "pg_log", assign_canonical_path, NULL
@ -1688,7 +1691,8 @@ static struct config_string ConfigureNamesString[] =
{ {
{"log_filename", PGC_SIGHUP, LOGGING_WHERE, {"log_filename", PGC_SIGHUP, LOGGING_WHERE,
gettext_noop("Sets the file name pattern for log files."), gettext_noop("Sets the file name pattern for log files."),
NULL NULL,
GUC_SUPERUSER_ONLY
}, },
&Log_filename, &Log_filename,
"postgresql-%Y-%m-%d_%H%M%S.log", NULL, NULL "postgresql-%Y-%m-%d_%H%M%S.log", NULL, NULL
@ -1747,7 +1751,8 @@ static struct config_string ConfigureNamesString[] =
{ {
{"unix_socket_directory", PGC_POSTMASTER, CONN_AUTH_SETTINGS, {"unix_socket_directory", PGC_POSTMASTER, CONN_AUTH_SETTINGS,
gettext_noop("Sets the directory where the Unix-domain socket will be created."), gettext_noop("Sets the directory where the Unix-domain socket will be created."),
NULL NULL,
GUC_SUPERUSER_ONLY
}, },
&UnixSocketDir, &UnixSocketDir,
"", assign_canonical_path, NULL "", assign_canonical_path, NULL
@ -1774,7 +1779,7 @@ static struct config_string ConfigureNamesString[] =
{ {
{"custom_variable_classes", PGC_POSTMASTER, RESOURCES_KERNEL, {"custom_variable_classes", PGC_POSTMASTER, RESOURCES_KERNEL,
gettext_noop("Sets the list of known custom variable classes"), gettext_noop("Sets the list of known custom variable classes."),
NULL, NULL,
GUC_LIST_INPUT | GUC_LIST_QUOTE GUC_LIST_INPUT | GUC_LIST_QUOTE
}, },
@ -1785,7 +1790,8 @@ static struct config_string ConfigureNamesString[] =
{ {
{"data_directory", PGC_POSTMASTER, FILE_LOCATIONS, {"data_directory", PGC_POSTMASTER, FILE_LOCATIONS,
gettext_noop("Sets the server's data directory."), gettext_noop("Sets the server's data directory."),
NULL NULL,
GUC_SUPERUSER_ONLY
}, },
&data_directory, &data_directory,
NULL, NULL, NULL NULL, NULL, NULL
@ -1795,7 +1801,7 @@ static struct config_string ConfigureNamesString[] =
{"config_file", PGC_POSTMASTER, FILE_LOCATIONS, {"config_file", PGC_POSTMASTER, FILE_LOCATIONS,
gettext_noop("Sets the server's main configuration file."), gettext_noop("Sets the server's main configuration file."),
NULL, NULL,
GUC_DISALLOW_IN_FILE GUC_DISALLOW_IN_FILE | GUC_SUPERUSER_ONLY
}, },
&ConfigFileName, &ConfigFileName,
NULL, NULL, NULL NULL, NULL, NULL
@ -1804,7 +1810,8 @@ static struct config_string ConfigureNamesString[] =
{ {
{"hba_file", PGC_POSTMASTER, FILE_LOCATIONS, {"hba_file", PGC_POSTMASTER, FILE_LOCATIONS,
gettext_noop("Sets the server's \"hba\" configuration file"), gettext_noop("Sets the server's \"hba\" configuration file"),
NULL NULL,
GUC_SUPERUSER_ONLY
}, },
&HbaFileName, &HbaFileName,
NULL, NULL, NULL NULL, NULL, NULL
@ -1813,7 +1820,8 @@ static struct config_string ConfigureNamesString[] =
{ {
{"ident_file", PGC_POSTMASTER, FILE_LOCATIONS, {"ident_file", PGC_POSTMASTER, FILE_LOCATIONS,
gettext_noop("Sets the server's \"ident\" configuration file"), gettext_noop("Sets the server's \"ident\" configuration file"),
NULL NULL,
GUC_SUPERUSER_ONLY
}, },
&IdentFileName, &IdentFileName,
NULL, NULL, NULL NULL, NULL, NULL
@ -1822,7 +1830,8 @@ static struct config_string ConfigureNamesString[] =
{ {
{"external_pid_file", PGC_POSTMASTER, FILE_LOCATIONS, {"external_pid_file", PGC_POSTMASTER, FILE_LOCATIONS,
gettext_noop("Writes the postmaster PID to the specified file."), gettext_noop("Writes the postmaster PID to the specified file."),
NULL NULL,
GUC_SUPERUSER_ONLY
}, },
&external_pid_file, &external_pid_file,
NULL, assign_canonical_path, NULL NULL, assign_canonical_path, NULL
@ -1874,6 +1883,8 @@ static int guc_var_compare(const void *a, const void *b);
static int guc_name_compare(const char *namea, const char *nameb); static int guc_name_compare(const char *namea, const char *nameb);
static void push_old_value(struct config_generic * gconf); static void push_old_value(struct config_generic * gconf);
static void ReportGUCOption(struct config_generic * record); static void ReportGUCOption(struct config_generic * record);
static void ShowGUCConfigOption(const char *name, DestReceiver *dest);
static void ShowAllGUCConfig(DestReceiver *dest);
static char *_ShowOption(struct config_generic * record); static char *_ShowOption(struct config_generic * record);
static bool check_userlimit_privilege(struct config_generic *record, static bool check_userlimit_privilege(struct config_generic *record,
GucSource source, int elevel); GucSource source, int elevel);
@ -3966,6 +3977,10 @@ GetConfigOption(const char *name)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT), (errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("unrecognized configuration parameter \"%s\"", name))); errmsg("unrecognized configuration parameter \"%s\"", name)));
if ((record->flags & GUC_SUPERUSER_ONLY) && !superuser())
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must be superuser to examine \"%s\"", name)));
switch (record->vartype) switch (record->vartype)
{ {
@ -4002,6 +4017,10 @@ GetConfigOptionResetString(const char *name)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT), (errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("unrecognized configuration parameter \"%s\"", name))); errmsg("unrecognized configuration parameter \"%s\"", name)));
if ((record->flags & GUC_SUPERUSER_ONLY) && !superuser())
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must be superuser to examine \"%s\"", name)));
switch (record->vartype) switch (record->vartype)
{ {
@ -4268,8 +4287,7 @@ define_custom_variable(struct config_generic * variable)
} }
static void static void
init_custom_variable( init_custom_variable(struct config_generic * gen,
struct config_generic * gen,
const char *name, const char *name,
const char *short_desc, const char *short_desc,
const char *long_desc, const char *long_desc,
@ -4462,7 +4480,7 @@ ResetPGVariable(const char *name)
/* /*
* SHOW command * SHOW command
*/ */
void static void
ShowGUCConfigOption(const char *name, DestReceiver *dest) ShowGUCConfigOption(const char *name, DestReceiver *dest)
{ {
TupOutputState *tstate; TupOutputState *tstate;
@ -4490,9 +4508,10 @@ ShowGUCConfigOption(const char *name, DestReceiver *dest)
/* /*
* SHOW ALL command * SHOW ALL command
*/ */
void static void
ShowAllGUCConfig(DestReceiver *dest) ShowAllGUCConfig(DestReceiver *dest)
{ {
bool am_superuser = superuser();
int i; int i;
TupOutputState *tstate; TupOutputState *tstate;
TupleDesc tupdesc; TupleDesc tupdesc;
@ -4512,7 +4531,8 @@ ShowAllGUCConfig(DestReceiver *dest)
{ {
struct config_generic *conf = guc_variables[i]; struct config_generic *conf = guc_variables[i];
if (conf->flags & GUC_NO_SHOW_ALL) if ((conf->flags & GUC_NO_SHOW_ALL) ||
((conf->flags & GUC_SUPERUSER_ONLY) && !am_superuser))
continue; continue;
/* assign to the values array */ /* assign to the values array */
@ -4544,6 +4564,10 @@ GetConfigOptionByName(const char *name, const char **varname)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT), (errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("unrecognized configuration parameter \"%s\"", name))); errmsg("unrecognized configuration parameter \"%s\"", name)));
if ((record->flags & GUC_SUPERUSER_ONLY) && !superuser())
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must be superuser to examine \"%s\"", name)));
if (varname) if (varname)
*varname = record->name; *varname = record->name;
@ -4567,7 +4591,13 @@ GetConfigOptionByNum(int varnum, const char **values, bool *noshow)
conf = guc_variables[varnum]; conf = guc_variables[varnum];
if (noshow) if (noshow)
*noshow = (conf->flags & GUC_NO_SHOW_ALL) ? true : false; {
if ((conf->flags & GUC_NO_SHOW_ALL) ||
((conf->flags & GUC_SUPERUSER_ONLY) && !superuser()))
*noshow = true;
else
*noshow = false;
}
/* first get the generic attributes */ /* first get the generic attributes */

View File

@ -7,7 +7,7 @@
* Copyright (c) 2000-2004, PostgreSQL Global Development Group * Copyright (c) 2000-2004, PostgreSQL Global Development Group
* Written by Peter Eisentraut <peter_e@gmx.net>. * Written by Peter Eisentraut <peter_e@gmx.net>.
* *
* $PostgreSQL: pgsql/src/include/utils/guc.h,v 1.53 2004/10/09 23:13:22 tgl Exp $ * $PostgreSQL: pgsql/src/include/utils/guc.h,v 1.54 2004/10/22 19:48:19 tgl Exp $
*-------------------------------------------------------------------- *--------------------------------------------------------------------
*/ */
#ifndef GUC_H #ifndef GUC_H
@ -194,8 +194,6 @@ extern void ParseLongOption(const char *string, char **name, char **value);
extern bool set_config_option(const char *name, const char *value, extern bool set_config_option(const char *name, const char *value,
GucContext context, GucSource source, GucContext context, GucSource source,
bool isLocal, bool changeVal); bool isLocal, bool changeVal);
extern void ShowGUCConfigOption(const char *name, DestReceiver *dest);
extern void ShowAllGUCConfig(DestReceiver *dest);
extern char *GetConfigOptionByName(const char *name, const char **varname); extern char *GetConfigOptionByName(const char *name, const char **varname);
extern void GetConfigOptionByNum(int varnum, const char **values, bool *noshow); extern void GetConfigOptionByNum(int varnum, const char **values, bool *noshow);
extern int GetNumConfigOptions(void); extern int GetNumConfigOptions(void);

View File

@ -7,7 +7,7 @@
* *
* Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group
* *
* $PostgreSQL: pgsql/src/include/utils/guc_tables.h,v 1.17 2004/10/08 01:36:36 tgl Exp $ * $PostgreSQL: pgsql/src/include/utils/guc_tables.h,v 1.18 2004/10/22 19:48:19 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -123,8 +123,8 @@ struct config_generic
#define GUC_REPORT 0x0010 /* auto-report changes to client */ #define GUC_REPORT 0x0010 /* auto-report changes to client */
#define GUC_NOT_IN_SAMPLE 0x0020 /* not in postgresql.conf.sample */ #define GUC_NOT_IN_SAMPLE 0x0020 /* not in postgresql.conf.sample */
#define GUC_DISALLOW_IN_FILE 0x0040 /* can't set in postgresql.conf */ #define GUC_DISALLOW_IN_FILE 0x0040 /* can't set in postgresql.conf */
#define GUC_CUSTOM_PLACEHOLDER 0x0080 /* placeholder for a custom #define GUC_CUSTOM_PLACEHOLDER 0x0080 /* placeholder for custom variable */
* variable */ #define GUC_SUPERUSER_ONLY 0x0100 /* show only to superusers */
/* bit values in status field */ /* bit values in status field */
#define GUC_HAVE_TENTATIVE 0x0001 /* tentative value is defined */ #define GUC_HAVE_TENTATIVE 0x0001 /* tentative value is defined */