@@ -105,6 +105,7 @@ static char *dlpath = PKGLIBDIR;
105105static char * user = NULL ;
106106static _stringlist * extraroles = NULL ;
107107static _stringlist * extra_install = NULL ;
108+ static char * config_auth_datadir = NULL ;
108109
109110/* internal variables */
110111static const char * progname ;
@@ -970,6 +971,150 @@ initialize_environment(void)
970971 load_resultmap ();
971972}
972973
974+ #ifdef ENABLE_SSPI
975+ /*
976+ * Get account and domain/realm names for the current user. This is based on
977+ * pg_SSPI_recvauth(). The returned strings use static storage.
978+ */
979+ static void
980+ current_windows_user (const char * * acct , const char * * dom )
981+ {
982+ static char accountname [MAXPGPATH ];
983+ static char domainname [MAXPGPATH ];
984+ HANDLE token ;
985+ TOKEN_USER * tokenuser ;
986+ DWORD retlen ;
987+ DWORD accountnamesize = sizeof (accountname );
988+ DWORD domainnamesize = sizeof (domainname );
989+ SID_NAME_USE accountnameuse ;
990+
991+ if (!OpenProcessToken (GetCurrentProcess (), TOKEN_READ , & token ))
992+ {
993+ fprintf (stderr ,
994+ _ ("%s: could not open process token: error code %lu\n" ),
995+ progname , GetLastError ());
996+ exit (2 );
997+ }
998+
999+ if (!GetTokenInformation (token , TokenUser , NULL , 0 , & retlen ) && GetLastError () != 122 )
1000+ {
1001+ fprintf (stderr ,
1002+ _ ("%s: could not get token user size: error code %lu\n" ),
1003+ progname , GetLastError ());
1004+ exit (2 );
1005+ }
1006+ tokenuser = malloc (retlen );
1007+ if (!GetTokenInformation (token , TokenUser , tokenuser , retlen , & retlen ))
1008+ {
1009+ fprintf (stderr ,
1010+ _ ("%s: could not get token user: error code %lu\n" ),
1011+ progname , GetLastError ());
1012+ exit (2 );
1013+ }
1014+
1015+ if (!LookupAccountSid (NULL , tokenuser -> User .Sid , accountname , & accountnamesize ,
1016+ domainname , & domainnamesize , & accountnameuse ))
1017+ {
1018+ fprintf (stderr ,
1019+ _ ("%s: could not look up account SID: error code %lu\n" ),
1020+ progname , GetLastError ());
1021+ exit (2 );
1022+ }
1023+
1024+ free (tokenuser );
1025+
1026+ * acct = accountname ;
1027+ * dom = domainname ;
1028+ }
1029+
1030+ /*
1031+ * Rewrite pg_hba.conf and pg_ident.conf to use SSPI authentication. Permit
1032+ * the current OS user to authenticate as the bootstrap superuser and as any
1033+ * user named in a --create-role option.
1034+ */
1035+ static void
1036+ config_sspi_auth (const char * pgdata )
1037+ {
1038+ const char * accountname ,
1039+ * domainname ;
1040+ char username [128 ];
1041+ DWORD sz = sizeof (username ) - 1 ;
1042+ char fname [MAXPGPATH ];
1043+ int res ;
1044+ FILE * hba ,
1045+ * ident ;
1046+ _stringlist * sl ;
1047+
1048+ /*
1049+ * "username", the initdb-chosen bootstrap superuser name, may always
1050+ * match "accountname", the value SSPI authentication discovers. The
1051+ * underlying system functions do not clearly guarantee that.
1052+ */
1053+ current_windows_user (& accountname , & domainname );
1054+ if (!GetUserName (username , & sz ))
1055+ {
1056+ fprintf (stderr , _ ("%s: could not get current user name: %s\n" ),
1057+ progname , strerror (errno ));
1058+ exit (2 );
1059+ }
1060+
1061+ /* Check a Write outcome and report any error. */
1062+ #define CW (cond ) \
1063+ do { \
1064+ if (!(cond)) \
1065+ { \
1066+ fprintf(stderr, _("%s: could not write to file \"%s\": %s\n"), \
1067+ progname, fname, strerror(errno)); \
1068+ exit(2); \
1069+ } \
1070+ } while (0)
1071+
1072+ res = snprintf (fname , sizeof (fname ), "%s/pg_hba.conf" , pgdata );
1073+ if (res < 0 || res >= sizeof (fname ) - 1 )
1074+ {
1075+ /*
1076+ * Truncating this name is a fatal error, because we must not fail to
1077+ * overwrite an original trust-authentication pg_hba.conf.
1078+ */
1079+ fprintf (stderr , _ ("%s: directory name too long\n" ), progname );
1080+ exit (2 );
1081+ }
1082+ hba = fopen (fname , "w" );
1083+ if (hba == NULL )
1084+ {
1085+ fprintf (stderr , _ ("%s: could not open file \"%s\" for writing: %s\n" ),
1086+ progname , fname , strerror (errno ));
1087+ exit (2 );
1088+ }
1089+ CW (fputs ("# Configuration written by config_sspi_auth()\n" , hba ) >= 0 );
1090+ CW (fputs ("host all all 127.0.0.1/32 sspi include_realm=1 map=regress\n" ,
1091+ hba ) >= 0 );
1092+ CW (fclose (hba ) == 0 );
1093+
1094+ snprintf (fname , sizeof (fname ), "%s/pg_ident.conf" , pgdata );
1095+ ident = fopen (fname , "w" );
1096+ if (ident == NULL )
1097+ {
1098+ fprintf (stderr , _ ("%s: could not open file \"%s\" for writing: %s\n" ),
1099+ progname , fname , strerror (errno ));
1100+ exit (2 );
1101+ }
1102+ CW (fputs ("# Configuration written by config_sspi_auth()\n" , ident ) >= 0 );
1103+
1104+ /*
1105+ * Double-quote for the benefit of account names containing whitespace or
1106+ * '#'. Windows forbids the double-quote character itself, so don't
1107+ * bother escaping embedded double-quote characters.
1108+ */
1109+ CW (fprintf (ident , "regress \"%s@%s\" \"%s\"\n" ,
1110+ accountname , domainname , username ) >= 0 );
1111+ for (sl = extraroles ; sl ; sl = sl -> next )
1112+ CW (fprintf (ident , "regress \"%s@%s\" \"%s\"\n" ,
1113+ accountname , domainname , sl -> str ) >= 0 );
1114+ CW (fclose (ident ) == 0 );
1115+ }
1116+ #endif
1117+
9731118/*
9741119 * Issue a command via psql, connecting to the specified database
9751120 *
@@ -1969,6 +2114,7 @@ help(void)
19692114 printf (_ ("Usage:\n %s [OPTION]... [EXTRA-TEST]...\n" ), progname );
19702115 printf (_ ("\n" ));
19712116 printf (_ ("Options:\n" ));
2117+ printf (_ (" --config-auth=DATADIR update authentication settings for DATADIR\n" ));
19722118 printf (_ (" --create-role=ROLE create the specified role before testing\n" ));
19732119 printf (_ (" --dbname=DB use database DB (default \"regression\")\n" ));
19742120 printf (_ (" --debug turn on debug mode in programs that are run\n" ));
@@ -2042,6 +2188,7 @@ regression_main(int argc, char *argv[], init_function ifunc, test_function tfunc
20422188 {"launcher" , required_argument , NULL , 21 },
20432189 {"load-extension" , required_argument , NULL , 22 },
20442190 {"extra-install" , required_argument , NULL , 23 },
2191+ {"config-auth" , required_argument , NULL , 24 },
20452192 {NULL , 0 , NULL , 0 }
20462193 };
20472194
@@ -2146,6 +2293,14 @@ regression_main(int argc, char *argv[], init_function ifunc, test_function tfunc
21462293 case 23 :
21472294 add_stringlist_item (& extra_install , optarg );
21482295 break ;
2296+ case 24 :
2297+ config_auth_datadir = strdup (optarg );
2298+ if (!config_auth_datadir )
2299+ {
2300+ fprintf (stderr , _ ("out of memory\n" ));
2301+ exit (EXIT_FAILURE );
2302+ }
2303+ break ;
21492304 default :
21502305 /* getopt_long already emitted a complaint */
21512306 fprintf (stderr , _ ("\nTry \"%s -h\" for more information.\n" ),
@@ -2163,6 +2318,14 @@ regression_main(int argc, char *argv[], init_function ifunc, test_function tfunc
21632318 optind ++ ;
21642319 }
21652320
2321+ if (config_auth_datadir )
2322+ {
2323+ #ifdef ENABLE_SSPI
2324+ config_sspi_auth (config_auth_datadir );
2325+ #endif
2326+ exit (0 );
2327+ }
2328+
21662329 if (temp_install && !port_specified_by_user )
21672330
21682331 /*
@@ -2303,6 +2466,18 @@ regression_main(int argc, char *argv[], init_function ifunc, test_function tfunc
23032466
23042467 fclose (pg_conf );
23052468
2469+ #ifdef ENABLE_SSPI
2470+
2471+ /*
2472+ * Since we successfully used the same buffer for the much-longer
2473+ * "initdb" command, this can't truncate.
2474+ */
2475+ snprintf (buf , sizeof (buf ), "%s/data" , temp_install );
2476+ config_sspi_auth (buf );
2477+ #elif !defined(HAVE_UNIX_SOCKETS )
2478+ #error Platform has no means to secure the test installation.
2479+ #endif
2480+
23062481 /*
23072482 * Check if there is a postmaster running already.
23082483 */
0 commit comments