aboutsummaryrefslogtreecommitdiff
path: root/src/test
diff options
context:
space:
mode:
Diffstat (limited to 'src/test')
-rw-r--r--src/test/perl/TestLib.pm11
-rw-r--r--src/test/regress/pg_regress.c171
2 files changed, 181 insertions, 1 deletions
diff --git a/src/test/perl/TestLib.pm b/src/test/perl/TestLib.pm
index 46a8bece1e5..57abdb92bf4 100644
--- a/src/test/perl/TestLib.pm
+++ b/src/test/perl/TestLib.pm
@@ -7,6 +7,7 @@ use Exporter 'import';
our @EXPORT = qw(
tempdir
tempdir_short
+ standard_initdb
start_test_server
restart_test_server
psql
@@ -69,6 +70,14 @@ sub tempdir_short
return File::Temp::tempdir(CLEANUP => 1);
}
+sub standard_initdb
+{
+ my $pgdata = shift;
+ system_or_bail("initdb -D '$pgdata' -A trust -N >/dev/null");
+ system_or_bail("$ENV{top_srcdir}/src/test/regress/pg_regress",
+ '--config-auth', $pgdata);
+}
+
my ($test_server_datadir, $test_server_logfile);
sub start_test_server
@@ -78,7 +87,7 @@ sub start_test_server
my $tempdir_short = tempdir_short;
- system "initdb -D '$tempdir'/pgdata -A trust -N >/dev/null";
+ standard_initdb "$tempdir/pgdata";
$ret = system 'pg_ctl', '-D', "$tempdir/pgdata", '-s', '-w', '-l',
"$tempdir/logfile", '-o',
"--fsync=off -k $tempdir_short --listen-addresses='' --log-statement=all",
diff --git a/src/test/regress/pg_regress.c b/src/test/regress/pg_regress.c
index 27c46abc96a..cb092f9d821 100644
--- a/src/test/regress/pg_regress.c
+++ b/src/test/regress/pg_regress.c
@@ -29,6 +29,7 @@
#include <sys/resource.h>
#endif
+#include "common/username.h"
#include "getopt_long.h"
#include "libpq/pqcomm.h" /* needed for UNIXSOCK_PATH() */
#include "pg_config_paths.h"
@@ -104,6 +105,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;
@@ -965,6 +967,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;
+ const char *username;
+ char *errstr;
+ 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);
+ username = get_user_name(&errstr);
+ if (username == NULL)
+ {
+ fprintf(stderr, "%s: %s\n", progname, errstr);
+ 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
*
@@ -1957,6 +2103,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"));
@@ -2023,6 +2170,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}
};
@@ -2137,6 +2285,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"),
@@ -2154,6 +2305,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)
/*
@@ -2298,6 +2457,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.
*/