1
0
mirror of https://github.com/postgres/postgres.git synced 2025-06-11 20:28:21 +03:00

Modify backend switch parsing to prevent 'insecure' switches

from being accepted when they are passed from client connection request.
Get rid of a couple that no longer do anything (like -P).
This commit is contained in:
Tom Lane
1999-05-22 17:47:54 +00:00
parent e9edb3ef92
commit cf1478982c
9 changed files with 211 additions and 181 deletions

View File

@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.114 1999/05/22 02:55:58 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.115 1999/05/22 17:47:49 tgl Exp $
*
* NOTES
* this is the "main" module of the postgres backend and
@ -776,7 +776,7 @@ pg_exec_query_dest(char *query_string, /* string to execute */
* Some backend has bought the farm,
* so we need to stop what we're doing and exit.
*
* die() preforms an orderly cleanup via ExitPostgres()
* die() performs an orderly cleanup via ExitPostgres()
* --------------------------------
*/
@ -832,7 +832,6 @@ QueryCancelHandler(SIGNAL_ARGS)
void
CancelQuery(void)
{
/*
* QueryCancel flag will be reset in main loop, which we reach by
* longjmp from elog().
@ -857,36 +856,42 @@ usage(char *progname)
#ifdef LOCK_MGR_DEBUG
fprintf(stderr, "\t-K lev\t\tset locking debug level [0|1|2]\n");
#endif
fprintf(stderr, "\t-L \t\tturn off locking\n");
fprintf(stderr, "\t-N \t\tdon't use newline as interactive query delimiter\n");
fprintf(stderr, "\t-O \t\tallow system table structure changes\n");
fprintf(stderr, "\t-P port\t\tset port file descriptor\n");
fprintf(stderr, "\t-Q \t\tsuppress informational messages\n");
fprintf(stderr, "\t-S buffers\tset amount of sort memory available\n");
fprintf(stderr, "\t-S kbytes\tset amount of memory for sorts (in kbytes)\n");
fprintf(stderr, "\t-T options\tspecify pg_options\n");
fprintf(stderr, "\t-W sec\t\twait N seconds to allow attach from a debugger\n");
fprintf(stderr, "\t-d [1|2|3]\tset debug level\n");
fprintf(stderr, "\t-e \t\tturn on European date format\n");
fprintf(stderr, "\t-f [s|i|n|m|h]\tforbid use of some plan types\n");
fprintf(stderr, "\t-o file\t\tsend stdout and stderr to given filename \n");
fprintf(stderr, "\t-i \t\tdon't execute queries\n");
fprintf(stderr, "\t-o file\t\tsend stdout and stderr to given filename\n");
fprintf(stderr, "\t-p database\tbackend is started under a postmaster\n");
fprintf(stderr, "\t-s \t\tshow stats after each query\n");
fprintf(stderr, "\t-t [pa|pl|ex]\tshow timings after each query\n");
fprintf(stderr, "\t-v version\tset protocol version being used by frontend\n");
}
/* ----------------------------------------------------------------
* PostgresMain
* postgres main loop
* PostgresMain
* postgres main loop
* all backends, interactive or otherwise start here
*
* argc/argv are the command line arguments to be used. When being forked
* by the postmaster, these are not the original argv array of the process.
* real_argc/real_argv point to the original argv array, which is needed by
* PS_INIT_STATUS on some platforms.
* ----------------------------------------------------------------
*/
int
PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[])
{
bool flagC = false,
flagQ = false,
flagE = false,
flagEu = false;
int flag;
char *DBName = NULL;
bool secure = true;
int errs = 0;
char firstchar;
@ -903,25 +908,18 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[])
extern char *optarg;
extern short DebugLvl;
/* ----------------
* parse command line arguments
* ----------------
*/
/*
* Set default values.
* Set default values for command-line options.
*/
IsUnderPostmaster = false;
ShowStats = 0;
ShowParserStats = ShowPlannerStats = ShowExecutorStats = 0;
DeadlockCheckTimer = DEADLOCK_CHECK_TIMER;
Noversion = false;
EchoQuery = false;
#ifdef LOCK_MGR_DEBUG
LockDebug = 0;
#endif
/*
* get hostname is either the environment variable PGHOST or NULL NULL
* means Unix-socket only
*/
DataDir = getenv("PGDATA");
/*
@ -943,8 +941,7 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[])
DateStyle = USE_GERMAN_DATES;
EuroDates = TRUE;
}
if (strcasecmp(DBDate, "NONEURO") == 0)
else if (strcasecmp(DBDate, "NONEURO") == 0)
EuroDates = FALSE;
else if (strcasecmp(DBDate, "EURO") == 0)
EuroDates = TRUE;
@ -953,14 +950,30 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[])
/*
* Read default pg_options from file $DATADIR/pg_options.
*/
if(DataDir) {
if (DataDir)
read_pg_options(0);
}
optind = 1; /* reset after postmaster usage */
/* ----------------
* parse command line arguments
*
* There are now two styles of command line layout for the backend:
*
* For interactive use (not started from postmaster) the format is
* postgres [switches] [databasename]
* If the databasename is omitted it is taken to be the user name.
*
* When started from the postmaster, the format is
* postgres [secure switches] -p databasename [insecure switches]
* Switches appearing after -p came from the client (via "options"
* field of connection request). For security reasons we restrict
* what these switches can do.
* ----------------
*/
optind = 1; /* reset after postmaster's usage */
while ((flag = getopt(argc, argv,
"A:B:CD:d:EeFf:iK:LMm:NOo:P:pQS:sT:t:v:W:x:"))
"A:B:CD:d:EeFf:iK:LNOo:p:QS:sT:t:v:W:x:"))
!= EOF)
switch (flag)
{
@ -981,28 +994,32 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[])
* specify the size of buffer pool
* ----------------
*/
NBuffers = atoi(optarg);
if (secure)
NBuffers = atoi(optarg);
break;
case 'C':
/* ----------------
* don't print version string (don't know why this is 'C' --mao)
* don't print version string
* ----------------
*/
flagC = true;
Noversion = true;
break;
case 'D': /* PGDATA directory */
if (!DataDir) {
DataDir = optarg;
/* must be done after DataDir is defined */
read_pg_options(0);
if (secure)
{
if (!DataDir)
{
DataDir = optarg;
/* must be done after DataDir is defined */
read_pg_options(0);
}
DataDir = optarg;
}
DataDir = optarg;
break;
case 'd': /* debug level */
flagQ = false;
DebugLvl = (short) atoi(optarg);
if (DebugLvl >= 1)
Verbose = DebugLvl;
@ -1029,7 +1046,7 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[])
* E - echo the query the user entered
* ----------------
*/
flagE = true;
EchoQuery = true;
break;
case 'e':
@ -1037,7 +1054,7 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[])
* Use european date formats.
* --------------------------
*/
flagEu = true;
EuroDates = true;
break;
case 'F':
@ -1045,7 +1062,8 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[])
* turn off fsync
* --------------------
*/
disableFsync = true;
if (secure)
disableFsync = true;
break;
case 'f':
@ -1092,15 +1110,8 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[])
* turn off locking
* --------------------
*/
lockingOff = 1;
break;
case 'M':
exit(PostmasterMain(argc, argv));
break;
case 'm':
/* Multiplexed backends are no longer supported. */
if (secure)
lockingOff = 1;
break;
case 'N':
@ -1116,7 +1127,8 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[])
* allow system table structure modifications
* --------------------
*/
allowSystemTableMods = true;
if (secure) /* XXX safe to allow from client??? */
allowSystemTableMods = true;
break;
case 'o':
@ -1124,26 +1136,22 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[])
* o - send output (stdout and stderr) to the given file
* ----------------
*/
StrNCpy(OutputFileName, optarg, MAXPGPATH);
if (secure)
StrNCpy(OutputFileName, optarg, MAXPGPATH);
break;
case 'p': /* started by postmaster */
case 'p':
/* ----------------
* p - special flag passed if backend was forked
* by a postmaster.
* ----------------
*/
IsUnderPostmaster = true;
break;
case 'P':
/* ----------------
* P - Use the passed file descriptor number as the port
* on which to communicate with the user. This is ONLY
* useful for debugging when fired up by the postmaster.
* ----------------
*/
Portfd = atoi(optarg);
if (secure)
{
IsUnderPostmaster = true;
DBName = optarg;
secure = false; /* subsequent switches are NOT secure */
}
break;
case 'Q':
@ -1151,7 +1159,6 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[])
* Q - set Quiet mode (reduce debugging output)
* ----------------
*/
flagQ = true;
Verbose = 0;
break;
@ -1179,7 +1186,11 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[])
break;
case 'T':
parse_options(optarg);
/* ----------------
* T - tracing options
* ----------------
*/
parse_options(optarg, secure);
break;
case 't':
@ -1214,7 +1225,8 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[])
break;
case 'v':
FrontendProtocol = (ProtocolVersion) atoi(optarg);
if (secure)
FrontendProtocol = (ProtocolVersion) atoi(optarg);
break;
case 'W':
@ -1268,32 +1280,38 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[])
}
/* ----------------
* get user name and pathname and check command line validity
* get user name (needed now in case it is the default database name)
* and check command line validity
* ----------------
*/
SetPgUserName();
userName = GetPgUserName();
#ifdef CYR_RECODE
SetCharSet();
#endif
if (FindExec(pg_pathname, argv[0], "postgres") < 0)
elog(FATAL, "%s: could not locate executable, bailing out...",
argv[0]);
if (errs || argc - optind > 1)
if (IsUnderPostmaster)
{
usage(argv[0]);
proc_exit(1);
/* noninteractive case: nothing should be left after switches */
if (errs || argc != optind || DBName == NULL)
{
usage(argv[0]);
proc_exit(1);
}
}
else if (argc - optind == 1)
DBName = argv[optind];
else if ((DBName = userName) == NULL)
else
{
fprintf(stderr, "%s: USER undefined and no database specified\n",
argv[0]);
proc_exit(1);
/* interactive case: database name can be last arg on command line */
if (errs || argc - optind > 1)
{
usage(argv[0]);
proc_exit(1);
}
else if (argc - optind == 1)
DBName = argv[optind];
else if ((DBName = userName) == NULL)
{
fprintf(stderr, "%s: USER undefined and no database specified\n",
argv[0]);
proc_exit(1);
}
}
if (ShowStats &&
@ -1308,14 +1326,22 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[])
fprintf(stderr, "%s does not know where to find the database system "
"data. You must specify the directory that contains the "
"database system either by specifying the -D invocation "
"option or by setting the PGDATA environment variable.\n\n",
"option or by setting the PGDATA environment variable.\n\n",
argv[0]);
proc_exit(1);
}
Noversion = flagC;
EchoQuery = flagE;
EuroDates = flagEu;
/*
* Set up additional info.
*/
#ifdef CYR_RECODE
SetCharSet();
#endif
if (FindExec(pg_pathname, argv[0], "postgres") < 0)
elog(FATAL, "%s: could not locate executable, bailing out...",
argv[0]);
/*
* Find remote host name or address.
@ -1398,30 +1424,23 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[])
}
/* ----------------
* initialize portal file descriptors
* initialize I/O
* ----------------
*/
if (IsUnderPostmaster)
{
if (Portfd < 0)
{
fprintf(stderr,
"Postmaster flag set: no port number specified, use /dev/null\n");
#ifndef __CYGWIN32__
Portfd = open(NULL_DEV, O_RDWR, 0666);
#else
Portfd = open(NULL_DEV, O_RDWR | O_BINARY, 0666);
#endif
}
pq_init(); /* reset libpq */
pq_init(); /* initialize libpq at backend startup */
whereToSendOutput = Remote;
}
else
whereToSendOutput = Debug;
/* ----------------
* general initialization
* ----------------
*/
SetProcessingMode(InitProcessing);
/* initialize */
if (Verbose)
TPRINTF(TRACE_VERBOSE, "InitPostgres");
@ -1485,7 +1504,7 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[])
if (!IsUnderPostmaster)
{
puts("\nPOSTGRES backend interactive interface ");
puts("$Revision: 1.114 $ $Date: 1999/05/22 02:55:58 $\n");
puts("$Revision: 1.115 $ $Date: 1999/05/22 17:47:49 $\n");
}
/* ----------------
@ -1493,9 +1512,6 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[])
*
* if an exception is encountered, processing resumes here
* so we abort the current transaction and start a new one.
* This must be done after we initialize the slave backends
* so that the slaves signal the master to abort the transaction
* rather than calling AbortCurrentTransaction() themselves.
*
* Note: elog(ERROR) does a siglongjmp() to transfer control here.
* ----------------