@@ -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)
974975 load_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)
19632108 printf (_ ("Usage: %s [options...] [extra tests...]\n" ), progname );
19642109 printf (_ ("\n" ));
19652110 printf (_ ("Options:\n" ));
2111+ printf (_ (" --config-auth=DATADIR update authentication settings for DATADIR\n" ));
19662112 printf (_ (" --dbname=DB use database DB (default \"regression\")\n" ));
19672113 printf (_ (" --debug turn on debug mode in programs that are run\n" ));
19682114 printf (_ (" --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
21222269 case 20 :
21232270 use_existing = true;
21242271 break ;
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 ;
21252280 default :
21262281 /* getopt_long already emitted a complaint */
21272282 fprintf (stderr , _ ("\nTry \"%s -h\" for more information.\n" ),
@@ -2139,6 +2294,14 @@ regression_main(int argc, char *argv[], init_function ifunc, test_function tfunc
21392294 optind ++ ;
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+
21422305 if (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
22612424 fclose (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 */
0 commit comments