aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/init/postinit.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/utils/init/postinit.c')
-rw-r--r--src/backend/utils/init/postinit.c104
1 files changed, 102 insertions, 2 deletions
diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c
index bd8598ce13d..11eeec353c9 100644
--- a/src/backend/utils/init/postinit.c
+++ b/src/backend/utils/init/postinit.c
@@ -8,13 +8,14 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/init/postinit.c,v 1.194 2009/08/12 20:53:30 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/init/postinit.c,v 1.195 2009/08/29 19:26:51 tgl Exp $
*
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
+#include <ctype.h>
#include <fcntl.h>
#include <unistd.h>
@@ -27,6 +28,7 @@
#include "catalog/pg_authid.h"
#include "catalog/pg_database.h"
#include "catalog/pg_tablespace.h"
+#include "libpq/auth.h"
#include "libpq/libpq-be.h"
#include "mb/pg_wchar.h"
#include "miscadmin.h"
@@ -54,6 +56,7 @@
static HeapTuple GetDatabaseTuple(const char *dbname);
static HeapTuple GetDatabaseTupleByOid(Oid dboid);
+static void PerformAuthentication(Port *port);
static void CheckMyDatabase(const char *name, bool am_superuser);
static void InitCommunication(void);
static void ShutdownPostgres(int code, Datum arg);
@@ -159,6 +162,66 @@ GetDatabaseTupleByOid(Oid dboid)
/*
+ * PerformAuthentication -- authenticate a remote client
+ *
+ * returns: nothing. Will not return at all if there's any failure.
+ */
+static void
+PerformAuthentication(Port *port)
+{
+ /* This should be set already, but let's make sure */
+ ClientAuthInProgress = true; /* limit visibility of log messages */
+
+ /*
+ * In EXEC_BACKEND case, we didn't inherit the contents of pg_hba.conf
+ * etcetera from the postmaster, and have to load them ourselves. Note
+ * we are loading them into the startup transaction's memory context,
+ * not PostmasterContext, but that shouldn't matter.
+ *
+ * FIXME: [fork/exec] Ugh. Is there a way around this overhead?
+ */
+#ifdef EXEC_BACKEND
+ if (!load_hba())
+ {
+ /*
+ * It makes no sense to continue if we fail to load the HBA file,
+ * since there is no way to connect to the database in this case.
+ */
+ ereport(FATAL,
+ (errmsg("could not load pg_hba.conf")));
+ }
+ load_ident();
+#endif
+
+ /*
+ * Set up a timeout in case a buggy or malicious client fails to respond
+ * during authentication. Since we're inside a transaction and might do
+ * database access, we have to use the statement_timeout infrastructure.
+ */
+ if (!enable_sig_alarm(AuthenticationTimeout * 1000, true))
+ elog(FATAL, "could not set timer for authorization timeout");
+
+ /*
+ * Now perform authentication exchange.
+ */
+ ClientAuthentication(port); /* might not return, if failure */
+
+ /*
+ * Done with authentication. Disable the timeout, and log if needed.
+ */
+ if (!disable_sig_alarm(true))
+ elog(FATAL, "could not disable timer for authorization timeout");
+
+ if (Log_connections)
+ ereport(LOG,
+ (errmsg("connection authorized: user=%s database=%s",
+ port->user_name, port->database_name)));
+
+ ClientAuthInProgress = false; /* client_min_messages is active now */
+}
+
+
+/*
* CheckMyDatabase -- fetch information from the pg_database entry for our DB
*/
static void
@@ -330,6 +393,38 @@ InitCommunication(void)
/*
+ * pg_split_opts -- split a string of options and append it to an argv array
+ *
+ * NB: the input string is destructively modified! Also, caller is responsible
+ * for ensuring the argv array is large enough. The maximum possible number
+ * of arguments added by this routine is (strlen(optstr) + 1) / 2.
+ *
+ * Since no current POSTGRES arguments require any quoting characters,
+ * we can use the simple-minded tactic of assuming each set of space-
+ * delimited characters is a separate argv element.
+ *
+ * If you don't like that, well, we *used* to pass the whole option string
+ * as ONE argument to execl(), which was even less intelligent...
+ */
+void
+pg_split_opts(char **argv, int *argcp, char *optstr)
+{
+ while (*optstr)
+ {
+ while (isspace((unsigned char) *optstr))
+ optstr++;
+ if (*optstr == '\0')
+ break;
+ argv[(*argcp)++] = optstr;
+ while (*optstr && !isspace((unsigned char) *optstr))
+ optstr++;
+ if (*optstr)
+ *optstr++ = '\0';
+ }
+}
+
+
+/*
* Early initialization of a backend (either standalone or under postmaster).
* This happens even before InitPostgres.
*
@@ -388,6 +483,8 @@ InitPostgres(const char *in_dbname, Oid dboid, const char *username,
char *fullpath;
char dbname[NAMEDATALEN];
+ elog(DEBUG3, "InitPostgres");
+
/*
* Add my PGPROC struct to the ProcArray.
*
@@ -599,7 +696,8 @@ InitPostgres(const char *in_dbname, Oid dboid, const char *username,
RelationCacheInitializePhase3();
/*
- * Figure out our postgres user id, and see if we are a superuser.
+ * Perform client authentication if necessary, then figure out our
+ * postgres user id, and see if we are a superuser.
*
* In standalone mode and in the autovacuum process, we use a fixed id,
* otherwise we figure it out from the authenticated user name.
@@ -623,6 +721,8 @@ InitPostgres(const char *in_dbname, Oid dboid, const char *username,
else
{
/* normal multiuser case */
+ Assert(MyProcPort != NULL);
+ PerformAuthentication(MyProcPort);
InitializeSessionUserId(username);
am_superuser = superuser();
}