@@ -105,6 +105,7 @@ static char *dlpath = PKGLIBDIR;
105
105
static char * user = NULL ;
106
106
static _stringlist * extraroles = NULL ;
107
107
static _stringlist * extra_install = NULL ;
108
+ static char * config_auth_datadir = NULL ;
108
109
109
110
/* internal variables */
110
111
static const char * progname ;
@@ -979,6 +980,150 @@ initialize_environment(void)
979
980
load_resultmap ();
980
981
}
981
982
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
+
982
1127
/*
983
1128
* Issue a command via psql, connecting to the specified database
984
1129
*
@@ -1978,6 +2123,7 @@ help(void)
1978
2123
printf (_ ("Usage: %s [options...] [extra tests...]\n" ),progname );
1979
2124
printf (_ ("\n" ));
1980
2125
printf (_ ("Options:\n" ));
2126
+ printf (_ (" --config-auth=DATADIR update authentication settings for DATADIR\n" ));
1981
2127
printf (_ (" --dbname=DB use database DB (default \"regression\")\n" ));
1982
2128
printf (_ (" --debug turn on debug mode in programs that are run\n" ));
1983
2129
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
2051
2197
{"launcher" ,required_argument ,NULL ,21 },
2052
2198
{"load-extension" ,required_argument ,NULL ,22 },
2053
2199
{"extra-install" ,required_argument ,NULL ,23 },
2200
+ {"config-auth" ,required_argument ,NULL ,24 },
2054
2201
{NULL ,0 ,NULL ,0 }
2055
2202
};
2056
2203
@@ -2153,6 +2300,14 @@ regression_main(int argc, char *argv[], init_function ifunc, test_function tfunc
2153
2300
case 23 :
2154
2301
add_stringlist_item (& extra_install ,optarg );
2155
2302
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 ;
2156
2311
default :
2157
2312
/* getopt_long already emitted a complaint */
2158
2313
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
2170
2325
optind ++ ;
2171
2326
}
2172
2327
2328
+ if (config_auth_datadir )
2329
+ {
2330
+ #ifdef ENABLE_SSPI
2331
+ config_sspi_auth (config_auth_datadir );
2332
+ #endif
2333
+ exit (0 );
2334
+ }
2335
+
2173
2336
if (temp_install && !port_specified_by_user )
2174
2337
2175
2338
/*
@@ -2310,6 +2473,18 @@ regression_main(int argc, char *argv[], init_function ifunc, test_function tfunc
2310
2473
2311
2474
fclose (pg_conf );
2312
2475
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
+
2313
2488
/*
2314
2489
* Check if there is a postmaster running already.
2315
2490
*/