@@ -102,6 +102,7 @@ static bool port_specified_by_user = false;
102102static char * dlpath = PKGLIBDIR ;
103103static char * user = NULL ;
104104static _stringlist * extraroles = NULL ;
105+ static char * config_auth_datadir = NULL ;
105106
106107/* internal variables */
107108static const char * progname ;
@@ -974,6 +975,150 @@ initialize_environment(void)
974975load_resultmap ();
975976}
976977
978+ #ifdef ENABLE_SSPI
979+ /*
980+ * Get account and domain/realm names for the current user. This is based on
981+ * pg_SSPI_recvauth(). The returned strings use static storage.
982+ */
983+ static void
984+ current_windows_user (const char * * acct ,const char * * dom )
985+ {
986+ static char accountname [MAXPGPATH ];
987+ static char domainname [MAXPGPATH ];
988+ HANDLE token ;
989+ TOKEN_USER * tokenuser ;
990+ DWORD retlen ;
991+ DWORD accountnamesize = sizeof (accountname );
992+ DWORD domainnamesize = sizeof (domainname );
993+ SID_NAME_USE accountnameuse ;
994+
995+ if (!OpenProcessToken (GetCurrentProcess (),TOKEN_READ ,& token ))
996+ {
997+ fprintf (stderr ,
998+ _ ("%s: could not open process token: error code %lu\n" ),
999+ progname ,GetLastError ());
1000+ exit (2 );
1001+ }
1002+
1003+ if (!GetTokenInformation (token ,TokenUser ,NULL ,0 ,& retlen )&& GetLastError ()!= 122 )
1004+ {
1005+ fprintf (stderr ,
1006+ _ ("%s: could not get token user size: error code %lu\n" ),
1007+ progname ,GetLastError ());
1008+ exit (2 );
1009+ }
1010+ tokenuser = malloc (retlen );
1011+ if (!GetTokenInformation (token ,TokenUser ,tokenuser ,retlen ,& retlen ))
1012+ {
1013+ fprintf (stderr ,
1014+ _ ("%s: could not get token user: error code %lu\n" ),
1015+ progname ,GetLastError ());
1016+ exit (2 );
1017+ }
1018+
1019+ if (!LookupAccountSid (NULL ,tokenuser -> User .Sid ,accountname ,& accountnamesize ,
1020+ domainname ,& domainnamesize ,& accountnameuse ))
1021+ {
1022+ fprintf (stderr ,
1023+ _ ("%s: could not look up account SID: error code %lu\n" ),
1024+ progname ,GetLastError ());
1025+ exit (2 );
1026+ }
1027+
1028+ free (tokenuser );
1029+
1030+ * acct = accountname ;
1031+ * dom = domainname ;
1032+ }
1033+
1034+ /*
1035+ * Rewrite pg_hba.conf and pg_ident.conf to use SSPI authentication. Permit
1036+ * the current OS user to authenticate as the bootstrap superuser and as any
1037+ * user named in a --create-role option.
1038+ */
1039+ static void
1040+ config_sspi_auth (const char * pgdata )
1041+ {
1042+ const char * accountname ,
1043+ * domainname ;
1044+ char username [128 ];
1045+ DWORD sz = sizeof (username )- 1 ;
1046+ char fname [MAXPGPATH ];
1047+ int res ;
1048+ FILE * hba ,
1049+ * ident ;
1050+ _stringlist * sl ;
1051+
1052+ /*
1053+ * "username", the initdb-chosen bootstrap superuser name, may always
1054+ * match "accountname", the value SSPI authentication discovers. The
1055+ * underlying system functions do not clearly guarantee that.
1056+ */
1057+ current_windows_user (& accountname ,& domainname );
1058+ if (!GetUserName (username ,& sz ))
1059+ {
1060+ fprintf (stderr ,_ ("%s: could not get current user name: %s\n" ),
1061+ progname ,strerror (errno ));
1062+ exit (2 );
1063+ }
1064+
1065+ /* Check a Write outcome and report any error. */
1066+ #define CW (cond )\
1067+ do { \
1068+ if (!(cond)) \
1069+ { \
1070+ fprintf(stderr, _("%s: could not write to file \"%s\": %s\n"), \
1071+ progname, fname, strerror(errno)); \
1072+ exit(2); \
1073+ } \
1074+ } while (0)
1075+
1076+ res = snprintf (fname ,sizeof (fname ),"%s/pg_hba.conf" ,pgdata );
1077+ if (res < 0 || res >=sizeof (fname )- 1 )
1078+ {
1079+ /*
1080+ * Truncating this name is a fatal error, because we must not fail to
1081+ * overwrite an original trust-authentication pg_hba.conf.
1082+ */
1083+ fprintf (stderr ,_ ("%s: directory name too long\n" ),progname );
1084+ exit (2 );
1085+ }
1086+ hba = fopen (fname ,"w" );
1087+ if (hba == NULL )
1088+ {
1089+ fprintf (stderr ,_ ("%s: could not open file \"%s\" for writing: %s\n" ),
1090+ progname ,fname ,strerror (errno ));
1091+ exit (2 );
1092+ }
1093+ CW (fputs ("# Configuration written by config_sspi_auth()\n" ,hba ) >=0 );
1094+ CW (fputs ("host all all 127.0.0.1/32 sspi include_realm=1 map=regress\n" ,
1095+ hba ) >=0 );
1096+ CW (fclose (hba )== 0 );
1097+
1098+ snprintf (fname ,sizeof (fname ),"%s/pg_ident.conf" ,pgdata );
1099+ ident = fopen (fname ,"w" );
1100+ if (ident == NULL )
1101+ {
1102+ fprintf (stderr ,_ ("%s: could not open file \"%s\" for writing: %s\n" ),
1103+ progname ,fname ,strerror (errno ));
1104+ exit (2 );
1105+ }
1106+ CW (fputs ("# Configuration written by config_sspi_auth()\n" ,ident ) >=0 );
1107+
1108+ /*
1109+ * Double-quote for the benefit of account names containing whitespace or
1110+ * '#'. Windows forbids the double-quote character itself, so don't
1111+ * bother escaping embedded double-quote characters.
1112+ */
1113+ CW (fprintf (ident ,"regress \"%s@%s\" \"%s\"\n" ,
1114+ accountname ,domainname ,username ) >=0 );
1115+ for (sl = extraroles ;sl ;sl = sl -> next )
1116+ CW (fprintf (ident ,"regress \"%s@%s\" \"%s\"\n" ,
1117+ accountname ,domainname ,sl -> str ) >=0 );
1118+ CW (fclose (ident )== 0 );
1119+ }
1120+ #endif
1121+
9771122/*
9781123 * Issue a command via psql, connecting to the specified database
9791124 *
@@ -1963,6 +2108,7 @@ help(void)
19632108printf (_ ("Usage: %s [options...] [extra tests...]\n" ),progname );
19642109printf (_ ("\n" ));
19652110printf (_ ("Options:\n" ));
2111+ printf (_ (" --config-auth=DATADIR update authentication settings for DATADIR\n" ));
19662112printf (_ (" --dbname=DB use database DB (default \"regression\")\n" ));
19672113printf (_ (" --debug turn on debug mode in programs that are run\n" ));
19682114printf (_ (" --inputdir=DIR take input files from DIR (default \".\")\n" ));
@@ -2029,6 +2175,7 @@ regression_main(int argc, char *argv[], init_function ifunc, test_function tfunc
20292175{"create-role" ,required_argument ,NULL ,18 },
20302176{"temp-config" ,required_argument ,NULL ,19 },
20312177{"use-existing" ,no_argument ,NULL ,20 },
2178+ {"config-auth" ,required_argument ,NULL ,24 },
20322179{NULL ,0 ,NULL ,0 }
20332180};
20342181
@@ -2122,6 +2269,14 @@ regression_main(int argc, char *argv[], init_function ifunc, test_function tfunc
21222269case 20 :
21232270use_existing = true;
21242271break ;
2272+ case 24 :
2273+ config_auth_datadir = strdup (optarg );
2274+ if (!config_auth_datadir )
2275+ {
2276+ fprintf (stderr ,_ ("out of memory\n" ));
2277+ exit (EXIT_FAILURE );
2278+ }
2279+ break ;
21252280default :
21262281/* getopt_long already emitted a complaint */
21272282fprintf (stderr ,_ ("\nTry \"%s -h\" for more information.\n" ),
@@ -2139,6 +2294,14 @@ regression_main(int argc, char *argv[], init_function ifunc, test_function tfunc
21392294optind ++ ;
21402295}
21412296
2297+ if (config_auth_datadir )
2298+ {
2299+ #ifdef ENABLE_SSPI
2300+ config_sspi_auth (config_auth_datadir );
2301+ #endif
2302+ exit (0 );
2303+ }
2304+
21422305if (temp_install && !port_specified_by_user )
21432306
21442307/*
@@ -2260,6 +2423,18 @@ regression_main(int argc, char *argv[], init_function ifunc, test_function tfunc
22602423
22612424fclose (pg_conf );
22622425
2426+ #ifdef ENABLE_SSPI
2427+
2428+ /*
2429+ * Since we successfully used the same buffer for the much-longer
2430+ * "initdb" command, this can't truncate.
2431+ */
2432+ snprintf (buf ,sizeof (buf ),"%s/data" ,temp_install );
2433+ config_sspi_auth (buf );
2434+ #elif !defined(HAVE_UNIX_SOCKETS )
2435+ #error Platform has no means to secure the test installation.
2436+ #endif
2437+
22632438/*
22642439 * Check if there is a postmaster running already.
22652440 */