aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--contrib/dblink/Makefile3
-rw-r--r--contrib/dblink/expected/dblink.out2
-rw-r--r--contrib/dblink/sql/dblink.sql2
-rw-r--r--contrib/pg_upgrade/test.sh15
-rw-r--r--doc/src/sgml/regress.sgml13
-rw-r--r--src/test/regress/pg_regress.c170
-rw-r--r--src/tools/msvc/vcregress.pl14
7 files changed, 195 insertions, 24 deletions
diff --git a/contrib/dblink/Makefile b/contrib/dblink/Makefile
index 09032f89702..97cc98d4f06 100644
--- a/contrib/dblink/Makefile
+++ b/contrib/dblink/Makefile
@@ -10,7 +10,8 @@ EXTENSION = dblink
DATA = dblink--1.1.sql dblink--1.0--1.1.sql dblink--unpackaged--1.0.sql
REGRESS = paths dblink
-REGRESS_OPTS = --dlpath=$(top_builddir)/src/test/regress
+REGRESS_OPTS = --dlpath=$(top_builddir)/src/test/regress \
+ --create-role=dblink_regression_test
EXTRA_CLEAN = sql/paths.sql expected/paths.out
# the db name is hard-coded in the tests
diff --git a/contrib/dblink/expected/dblink.out b/contrib/dblink/expected/dblink.out
index f503691bf21..87eb142bd30 100644
--- a/contrib/dblink/expected/dblink.out
+++ b/contrib/dblink/expected/dblink.out
@@ -809,7 +809,6 @@ SELECT dblink_disconnect('dtest1');
(1 row)
-- test foreign data wrapper functionality
-CREATE USER dblink_regression_test;
CREATE SERVER fdtest FOREIGN DATA WRAPPER dblink_fdw
OPTIONS (dbname 'contrib_regression');
CREATE USER MAPPING FOR public SERVER fdtest
@@ -851,7 +850,6 @@ SELECT * FROM dblink('myconn','SELECT * FROM foo') AS t(a int, b text, c text[])
\c - :ORIGINAL_USER
REVOKE USAGE ON FOREIGN SERVER fdtest FROM dblink_regression_test;
REVOKE EXECUTE ON FUNCTION dblink_connect_u(text, text) FROM dblink_regression_test;
-DROP USER dblink_regression_test;
DROP USER MAPPING FOR public SERVER fdtest;
DROP SERVER fdtest;
-- test asynchronous notifications
diff --git a/contrib/dblink/sql/dblink.sql b/contrib/dblink/sql/dblink.sql
index d8d248260c0..5305d5a8f5b 100644
--- a/contrib/dblink/sql/dblink.sql
+++ b/contrib/dblink/sql/dblink.sql
@@ -387,7 +387,6 @@ SELECT dblink_error_message('dtest1');
SELECT dblink_disconnect('dtest1');
-- test foreign data wrapper functionality
-CREATE USER dblink_regression_test;
CREATE SERVER fdtest FOREIGN DATA WRAPPER dblink_fdw
OPTIONS (dbname 'contrib_regression');
CREATE USER MAPPING FOR public SERVER fdtest
@@ -408,7 +407,6 @@ SELECT * FROM dblink('myconn','SELECT * FROM foo') AS t(a int, b text, c text[])
\c - :ORIGINAL_USER
REVOKE USAGE ON FOREIGN SERVER fdtest FROM dblink_regression_test;
REVOKE EXECUTE ON FUNCTION dblink_connect_u(text, text) FROM dblink_regression_test;
-DROP USER dblink_regression_test;
DROP USER MAPPING FOR public SERVER fdtest;
DROP SERVER fdtest;
diff --git a/contrib/pg_upgrade/test.sh b/contrib/pg_upgrade/test.sh
index 03dce0c0db6..c6056d20fd5 100644
--- a/contrib/pg_upgrade/test.sh
+++ b/contrib/pg_upgrade/test.sh
@@ -17,13 +17,20 @@ set -e
unset MAKEFLAGS
unset MAKELEVEL
+# Run a given "initdb" binary and overlay the regression testing
+# authentication configuration.
+standard_initdb() {
+ "$1" -N
+ ../../src/test/regress/pg_regress --config-auth "$PGDATA"
+}
+
# Establish how the server will listen for connections
testhost=`uname -s`
case $testhost in
MINGW*)
LISTEN_ADDRESSES="localhost"
- PGHOST=""; unset PGHOST
+ PGHOST=localhost
;;
*)
LISTEN_ADDRESSES=""
@@ -49,11 +56,11 @@ case $testhost in
trap 'rm -rf "$PGHOST"' 0
trap 'exit 3' 1 2 13 15
fi
- export PGHOST
;;
esac
POSTMASTER_OPTS="-F -c listen_addresses=$LISTEN_ADDRESSES -k \"$PGHOST\""
+export PGHOST
temp_root=$PWD/tmp_check
@@ -141,7 +148,7 @@ export EXTRA_REGRESS_OPTS
# enable echo so the user can see what is being executed
set -x
-$oldbindir/initdb -N
+standard_initdb "$oldbindir"/initdb
$oldbindir/pg_ctl start -l "$logdir/postmaster1.log" -o "$POSTMASTER_OPTS" -w
if "$MAKE" -C "$oldsrc" installcheck; then
pg_dumpall -f "$temp_root"/dump1.sql || pg_dumpall1_status=$?
@@ -181,7 +188,7 @@ fi
PGDATA=$BASE_PGDATA
-initdb -N
+standard_initdb 'initdb'
pg_upgrade $PG_UPGRADE_OPTS -d "${PGDATA}.old" -D "${PGDATA}" -b "$oldbindir" -B "$bindir" -p "$PGPORT" -P "$PGPORT"
diff --git a/doc/src/sgml/regress.sgml b/doc/src/sgml/regress.sgml
index cb412978fcf..b88038f12c3 100644
--- a/doc/src/sgml/regress.sgml
+++ b/doc/src/sgml/regress.sgml
@@ -56,19 +56,6 @@ gmake check
<quote>failure</> represents a serious problem.
</para>
- <warning>
- <para>
- On systems lacking Unix-domain sockets, notably Windows, this test method
- starts a temporary server configured to accept any connection originating
- on the local machine. Any local user can gain database superuser
- privileges when connecting to this server, and could in principle exploit
- all privileges of the operating-system user running the tests. Therefore,
- it is not recommended that you use <literal>gmake check</> on an affected
- system shared with untrusted users. Instead, run the tests after
- completing the installation, as described in the next section.
- </para>
- </warning>
-
<para>
Because this test method runs a temporary server, it will not work
if you did the build as the root user, since the server will not start as
diff --git a/src/test/regress/pg_regress.c b/src/test/regress/pg_regress.c
index bad5831ec7d..3e98acc47ee 100644
--- a/src/test/regress/pg_regress.c
+++ b/src/test/regress/pg_regress.c
@@ -104,6 +104,7 @@ static char *dlpath = PKGLIBDIR;
static char *user = NULL;
static _stringlist *extraroles = NULL;
static _stringlist *extra_install = NULL;
+static char *config_auth_datadir = NULL;
/* internal variables */
static const char *progname;
@@ -971,6 +972,150 @@ initialize_environment(void)
load_resultmap();
}
+#ifdef ENABLE_SSPI
+/*
+ * Get account and domain/realm names for the current user. This is based on
+ * pg_SSPI_recvauth(). The returned strings use static storage.
+ */
+static void
+current_windows_user(const char **acct, const char **dom)
+{
+ static char accountname[MAXPGPATH];
+ static char domainname[MAXPGPATH];
+ HANDLE token;
+ TOKEN_USER *tokenuser;
+ DWORD retlen;
+ DWORD accountnamesize = sizeof(accountname);
+ DWORD domainnamesize = sizeof(domainname);
+ SID_NAME_USE accountnameuse;
+
+ if (!OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &token))
+ {
+ fprintf(stderr,
+ _("%s: could not open process token: error code %lu\n"),
+ progname, GetLastError());
+ exit(2);
+ }
+
+ if (!GetTokenInformation(token, TokenUser, NULL, 0, &retlen) && GetLastError() != 122)
+ {
+ fprintf(stderr,
+ _("%s: could not get token user size: error code %lu\n"),
+ progname, GetLastError());
+ exit(2);
+ }
+ tokenuser = malloc(retlen);
+ if (!GetTokenInformation(token, TokenUser, tokenuser, retlen, &retlen))
+ {
+ fprintf(stderr,
+ _("%s: could not get token user: error code %lu\n"),
+ progname, GetLastError());
+ exit(2);
+ }
+
+ if (!LookupAccountSid(NULL, tokenuser->User.Sid, accountname, &accountnamesize,
+ domainname, &domainnamesize, &accountnameuse))
+ {
+ fprintf(stderr,
+ _("%s: could not look up account SID: error code %lu\n"),
+ progname, GetLastError());
+ exit(2);
+ }
+
+ free(tokenuser);
+
+ *acct = accountname;
+ *dom = domainname;
+}
+
+/*
+ * Rewrite pg_hba.conf and pg_ident.conf to use SSPI authentication. Permit
+ * the current OS user to authenticate as the bootstrap superuser and as any
+ * user named in a --create-role option.
+ */
+static void
+config_sspi_auth(const char *pgdata)
+{
+ const char *accountname,
+ *domainname;
+ char username[128];
+ DWORD sz = sizeof(username) - 1;
+ char fname[MAXPGPATH];
+ int res;
+ FILE *hba,
+ *ident;
+ _stringlist *sl;
+
+ /*
+ * "username", the initdb-chosen bootstrap superuser name, may always
+ * match "accountname", the value SSPI authentication discovers. The
+ * underlying system functions do not clearly guarantee that.
+ */
+ current_windows_user(&accountname, &domainname);
+ if (!GetUserName(username, &sz))
+ {
+ fprintf(stderr, _("%s: could not get current user name: %s\n"),
+ progname, strerror(errno));
+ exit(2);
+ }
+
+ /* Check a Write outcome and report any error. */
+#define CW(cond) \
+ do { \
+ if (!(cond)) \
+ { \
+ fprintf(stderr, _("%s: could not write to file \"%s\": %s\n"), \
+ progname, fname, strerror(errno)); \
+ exit(2); \
+ } \
+ } while (0)
+
+ res = snprintf(fname, sizeof(fname), "%s/pg_hba.conf", pgdata);
+ if (res < 0 || res >= sizeof(fname) - 1)
+ {
+ /*
+ * Truncating this name is a fatal error, because we must not fail to
+ * overwrite an original trust-authentication pg_hba.conf.
+ */
+ fprintf(stderr, _("%s: directory name too long\n"), progname);
+ exit(2);
+ }
+ hba = fopen(fname, "w");
+ if (hba == NULL)
+ {
+ fprintf(stderr, _("%s: could not open file \"%s\" for writing: %s\n"),
+ progname, fname, strerror(errno));
+ exit(2);
+ }
+ CW(fputs("# Configuration written by config_sspi_auth()\n", hba) >= 0);
+ CW(fputs("host all all 127.0.0.1/32 sspi include_realm=1 map=regress\n",
+ hba) >= 0);
+ CW(fclose(hba) == 0);
+
+ snprintf(fname, sizeof(fname), "%s/pg_ident.conf", pgdata);
+ ident = fopen(fname, "w");
+ if (ident == NULL)
+ {
+ fprintf(stderr, _("%s: could not open file \"%s\" for writing: %s\n"),
+ progname, fname, strerror(errno));
+ exit(2);
+ }
+ CW(fputs("# Configuration written by config_sspi_auth()\n", ident) >= 0);
+
+ /*
+ * Double-quote for the benefit of account names containing whitespace or
+ * '#'. Windows forbids the double-quote character itself, so don't
+ * bother escaping embedded double-quote characters.
+ */
+ CW(fprintf(ident, "regress \"%s@%s\" \"%s\"\n",
+ accountname, domainname, username) >= 0);
+ for (sl = extraroles; sl; sl = sl->next)
+ CW(fprintf(ident, "regress \"%s@%s\" \"%s\"\n",
+ accountname, domainname, sl->str) >= 0);
+ CW(fclose(ident) == 0);
+}
+#endif
+
/*
* Issue a command via psql, connecting to the specified database
*
@@ -1970,6 +2115,7 @@ help(void)
printf(_("Usage:\n %s [OPTION]... [EXTRA-TEST]...\n"), progname);
printf(_("\n"));
printf(_("Options:\n"));
+ printf(_(" --config-auth=DATADIR update authentication settings for DATADIR\n"));
printf(_(" --create-role=ROLE create the specified role before testing\n"));
printf(_(" --dbname=DB use database DB (default \"regression\")\n"));
printf(_(" --debug turn on debug mode in programs that are run\n"));
@@ -2036,6 +2182,7 @@ regression_main(int argc, char *argv[], init_function ifunc, test_function tfunc
{"launcher", required_argument, NULL, 21},
{"load-extension", required_argument, NULL, 22},
{"extra-install", required_argument, NULL, 23},
+ {"config-auth", required_argument, NULL, 24},
{NULL, 0, NULL, 0}
};
@@ -2150,6 +2297,9 @@ regression_main(int argc, char *argv[], init_function ifunc, test_function tfunc
case 23:
add_stringlist_item(&extra_install, optarg);
break;
+ case 24:
+ config_auth_datadir = pstrdup(optarg);
+ break;
default:
/* getopt_long already emitted a complaint */
fprintf(stderr, _("\nTry \"%s -h\" for more information.\n"),
@@ -2167,6 +2317,14 @@ regression_main(int argc, char *argv[], init_function ifunc, test_function tfunc
optind++;
}
+ if (config_auth_datadir)
+ {
+#ifdef ENABLE_SSPI
+ config_sspi_auth(config_auth_datadir);
+#endif
+ exit(0);
+ }
+
if (temp_install && !port_specified_by_user)
/*
@@ -2307,6 +2465,18 @@ regression_main(int argc, char *argv[], init_function ifunc, test_function tfunc
fclose(pg_conf);
+#ifdef ENABLE_SSPI
+
+ /*
+ * Since we successfully used the same buffer for the much-longer
+ * "initdb" command, this can't truncate.
+ */
+ snprintf(buf, sizeof(buf), "%s/data", temp_install);
+ config_sspi_auth(buf);
+#elif !defined(HAVE_UNIX_SOCKETS)
+#error Platform has no means to secure the test installation.
+#endif
+
/*
* Check if there is a postmaster running already.
*/
diff --git a/src/tools/msvc/vcregress.pl b/src/tools/msvc/vcregress.pl
index 5f5c9bc228b..30da0ba0e65 100644
--- a/src/tools/msvc/vcregress.pl
+++ b/src/tools/msvc/vcregress.pl
@@ -242,6 +242,15 @@ sub contribcheck
exit $mstat if $mstat;
}
+# Run "initdb", then reconfigure authentication.
+sub standard_initdb
+{
+ return (
+ system('initdb', '-N') == 0 and system(
+ "$topdir/$Config/pg_regress/pg_regress", '--config-auth',
+ $ENV{PGDATA}) == 0);
+}
+
sub upgradecheck
{
my $status;
@@ -253,6 +262,7 @@ sub upgradecheck
# i.e. only this version to this version check. That's
# what pg_upgrade's "make check" does.
+ $ENV{PGHOST} = 'localhost';
$ENV{PGPORT} ||= 50432;
my $tmp_root = "$topdir/contrib/pg_upgrade/tmp_check";
(mkdir $tmp_root || die $!) unless -d $tmp_root;
@@ -270,7 +280,7 @@ sub upgradecheck
my $logdir = "$topdir/contrib/pg_upgrade/log";
(mkdir $logdir || die $!) unless -d $logdir;
print "\nRunning initdb on old cluster\n\n";
- system("initdb") == 0 or exit 1;
+ standard_initdb() or exit 1;
print "\nStarting old cluster\n\n";
system("pg_ctl start -l $logdir/postmaster1.log -w") == 0 or exit 1;
print "\nSetting up data for upgrading\n\n";
@@ -284,7 +294,7 @@ sub upgradecheck
system("pg_ctl -m fast stop") == 0 or exit 1;
$ENV{PGDATA} = "$data";
print "\nSetting up new cluster\n\n";
- system("initdb") == 0 or exit 1;
+ standard_initdb() or exit 1;
print "\nRunning pg_upgrade\n\n";
system("pg_upgrade -d $data.old -D $data -b $bindir -B $bindir") == 0
or exit 1;