@@ -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 ;
@@ -979,6 +980,150 @@ initialize_environment(void)
979980 load_resultmap ();
980981}
981982
983+ #ifdef ENABLE_SSPI
984+ /*
985+ * Get account and domain/realm names for the current user. This is based on
986+ * pg_SSPI_recvauth(). The returned strings use static storage.
987+ */
988+ static void
989+ current_windows_user (const char * * acct , const char * * dom )
990+ {
991+ static char accountname [MAXPGPATH ];
992+ static char domainname [MAXPGPATH ];
993+ HANDLE token ;
994+ TOKEN_USER * tokenuser ;
995+ DWORD retlen ;
996+ DWORD accountnamesize = sizeof (accountname );
997+ DWORD domainnamesize = sizeof (domainname );
998+ SID_NAME_USE accountnameuse ;
999+
1000+ if (!OpenProcessToken (GetCurrentProcess (), TOKEN_READ , & token ))
1001+ {
1002+ fprintf (stderr ,
1003+ _ ("%s: could not open process token: error code %lu\n" ),
1004+ progname , GetLastError ());
1005+ exit (2 );
1006+ }
1007+
1008+ if (!GetTokenInformation (token , TokenUser , NULL , 0 , & retlen ) && GetLastError () != 122 )
1009+ {
1010+ fprintf (stderr ,
1011+ _ ("%s: could not get token user size: error code %lu\n" ),
1012+ progname , GetLastError ());
1013+ exit (2 );
1014+ }
1015+ tokenuser = malloc (retlen );
1016+ if (!GetTokenInformation (token , TokenUser , tokenuser , retlen , & retlen ))
1017+ {
1018+ fprintf (stderr ,
1019+ _ ("%s: could not get token user: error code %lu\n" ),
1020+ progname , GetLastError ());
1021+ exit (2 );
1022+ }
1023+
1024+ if (!LookupAccountSid (NULL , tokenuser -> User .Sid , accountname , & accountnamesize ,
1025+ domainname , & domainnamesize , & accountnameuse ))
1026+ {
1027+ fprintf (stderr ,
1028+ _ ("%s: could not look up account SID: error code %lu\n" ),
1029+ progname , GetLastError ());
1030+ exit (2 );
1031+ }
1032+
1033+ free (tokenuser );
1034+
1035+ * acct = accountname ;
1036+ * dom = domainname ;
1037+ }
1038+
1039+ /*
1040+ * Rewrite pg_hba.conf and pg_ident.conf to use SSPI authentication. Permit
1041+ * the current OS user to authenticate as the bootstrap superuser and as any
1042+ * user named in a --create-role option.
1043+ */
1044+ static void
1045+ config_sspi_auth (const char * pgdata )
1046+ {
1047+ const char * accountname ,
1048+ * domainname ;
1049+ char username [128 ];
1050+ DWORD sz = sizeof (username ) - 1 ;
1051+ char fname [MAXPGPATH ];
1052+ int res ;
1053+ FILE * hba ,
1054+ * ident ;
1055+ _stringlist * sl ;
1056+
1057+ /*
1058+ * "username", the initdb-chosen bootstrap superuser name, may always
1059+ * match "accountname", the value SSPI authentication discovers. The
1060+ * underlying system functions do not clearly guarantee that.
1061+ */
1062+ current_windows_user (& accountname , & domainname );
1063+ if (!GetUserName (username , & sz ))
1064+ {
1065+ fprintf (stderr , _ ("%s: could not get current user name: %s\n" ),
1066+ progname , strerror (errno ));
1067+ exit (2 );
1068+ }
1069+
1070+ /* Check a Write outcome and report any error. */
1071+ #define CW (cond ) \
1072+ do { \
1073+ if (!(cond)) \
1074+ { \
1075+ fprintf(stderr, _("%s: could not write to file \"%s\": %s\n"), \
1076+ progname, fname, strerror(errno)); \
1077+ exit(2); \
1078+ } \
1079+ } while (0)
1080+
1081+ res = snprintf (fname , sizeof (fname ), "%s/pg_hba.conf" , pgdata );
1082+ if (res < 0 || res >= sizeof (fname ) - 1 )
1083+ {
1084+ /*
1085+ * Truncating this name is a fatal error, because we must not fail to
1086+ * overwrite an original trust-authentication pg_hba.conf.
1087+ */
1088+ fprintf (stderr , _ ("%s: directory name too long\n" ), progname );
1089+ exit (2 );
1090+ }
1091+ hba = fopen (fname , "w" );
1092+ if (hba == NULL )
1093+ {
1094+ fprintf (stderr , _ ("%s: could not open file \"%s\" for writing: %s\n" ),
1095+ progname , fname , strerror (errno ));
1096+ exit (2 );
1097+ }
1098+ CW (fputs ("# Configuration written by config_sspi_auth()\n" , hba ) >= 0 );
1099+ CW (fputs ("host all all 127.0.0.1/32 sspi include_realm=1 map=regress\n" ,
1100+ hba ) >= 0 );
1101+ CW (fclose (hba ) == 0 );
1102+
1103+ snprintf (fname , sizeof (fname ), "%s/pg_ident.conf" , pgdata );
1104+ ident = fopen (fname , "w" );
1105+ if (ident == NULL )
1106+ {
1107+ fprintf (stderr , _ ("%s: could not open file \"%s\" for writing: %s\n" ),
1108+ progname , fname , strerror (errno ));
1109+ exit (2 );
1110+ }
1111+ CW (fputs ("# Configuration written by config_sspi_auth()\n" , ident ) >= 0 );
1112+
1113+ /*
1114+ * Double-quote for the benefit of account names containing whitespace or
1115+ * '#'. Windows forbids the double-quote character itself, so don't
1116+ * bother escaping embedded double-quote characters.
1117+ */
1118+ CW (fprintf (ident , "regress \"%s@%s\" \"%s\"\n" ,
1119+ accountname , domainname , username ) >= 0 );
1120+ for (sl = extraroles ; sl ; sl = sl -> next )
1121+ CW (fprintf (ident , "regress \"%s@%s\" \"%s\"\n" ,
1122+ accountname , domainname , sl -> str ) >= 0 );
1123+ CW (fclose (ident ) == 0 );
1124+ }
1125+ #endif
1126+
9821127/*
9831128 * Issue a command via psql, connecting to the specified database
9841129 *
@@ -1978,6 +2123,7 @@ help(void)
19782123 printf (_ ("Usage: %s [options...] [extra tests...]\n" ), progname );
19792124 printf (_ ("\n" ));
19802125 printf (_ ("Options:\n" ));
2126+ printf (_ (" --config-auth=DATADIR update authentication settings for DATADIR\n" ));
19812127 printf (_ (" --dbname=DB use database DB (default \"regression\")\n" ));
19822128 printf (_ (" --debug turn on debug mode in programs that are run\n" ));
19832129 printf (_ (" --inputdir=DIR take input files from DIR (default \".\")\n" ));
@@ -2051,6 +2197,7 @@ regression_main(int argc, char *argv[], init_function ifunc, test_function tfunc
20512197 {"launcher" , required_argument , NULL , 21 },
20522198 {"load-extension" , required_argument , NULL , 22 },
20532199 {"extra-install" , required_argument , NULL , 23 },
2200+ {"config-auth" , required_argument , NULL , 24 },
20542201 {NULL , 0 , NULL , 0 }
20552202 };
20562203
@@ -2153,6 +2300,14 @@ regression_main(int argc, char *argv[], init_function ifunc, test_function tfunc
21532300 case 23 :
21542301 add_stringlist_item (& extra_install , optarg );
21552302 break ;
2303+ case 24 :
2304+ config_auth_datadir = strdup (optarg );
2305+ if (!config_auth_datadir )
2306+ {
2307+ fprintf (stderr , _ ("out of memory\n" ));
2308+ exit (EXIT_FAILURE );
2309+ }
2310+ break ;
21562311 default :
21572312 /* getopt_long already emitted a complaint */
21582313 fprintf (stderr , _ ("\nTry \"%s -h\" for more information.\n" ),
@@ -2170,6 +2325,14 @@ regression_main(int argc, char *argv[], init_function ifunc, test_function tfunc
21702325 optind ++ ;
21712326 }
21722327
2328+ if (config_auth_datadir )
2329+ {
2330+ #ifdef ENABLE_SSPI
2331+ config_sspi_auth (config_auth_datadir );
2332+ #endif
2333+ exit (0 );
2334+ }
2335+
21732336 if (temp_install && !port_specified_by_user )
21742337
21752338 /*
@@ -2310,6 +2473,18 @@ regression_main(int argc, char *argv[], init_function ifunc, test_function tfunc
23102473
23112474 fclose (pg_conf );
23122475
2476+ #ifdef ENABLE_SSPI
2477+
2478+ /*
2479+ * Since we successfully used the same buffer for the much-longer
2480+ * "initdb" command, this can't truncate.
2481+ */
2482+ snprintf (buf , sizeof (buf ), "%s/data" , temp_install );
2483+ config_sspi_auth (buf );
2484+ #elif !defined(HAVE_UNIX_SOCKETS )
2485+ #error Platform has no means to secure the test installation.
2486+ #endif
2487+
23132488 /*
23142489 * Check if there is a postmaster running already.
23152490 */
0 commit comments