@@ -102,6 +102,7 @@ static bool port_specified_by_user = false;
102
102
static char * dlpath = PKGLIBDIR ;
103
103
static char * user = NULL ;
104
104
static _stringlist * extraroles = NULL ;
105
+ static char * config_auth_datadir = NULL ;
105
106
106
107
/* internal variables */
107
108
static const char * progname ;
@@ -974,6 +975,150 @@ initialize_environment(void)
974
975
load_resultmap ();
975
976
}
976
977
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
+
977
1122
/*
978
1123
* Issue a command via psql, connecting to the specified database
979
1124
*
@@ -1963,6 +2108,7 @@ help(void)
1963
2108
printf (_ ("Usage: %s [options...] [extra tests...]\n" ),progname );
1964
2109
printf (_ ("\n" ));
1965
2110
printf (_ ("Options:\n" ));
2111
+ printf (_ (" --config-auth=DATADIR update authentication settings for DATADIR\n" ));
1966
2112
printf (_ (" --dbname=DB use database DB (default \"regression\")\n" ));
1967
2113
printf (_ (" --debug turn on debug mode in programs that are run\n" ));
1968
2114
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
2029
2175
{"create-role" ,required_argument ,NULL ,18 },
2030
2176
{"temp-config" ,required_argument ,NULL ,19 },
2031
2177
{"use-existing" ,no_argument ,NULL ,20 },
2178
+ {"config-auth" ,required_argument ,NULL ,24 },
2032
2179
{NULL ,0 ,NULL ,0 }
2033
2180
};
2034
2181
@@ -2122,6 +2269,14 @@ regression_main(int argc, char *argv[], init_function ifunc, test_function tfunc
2122
2269
case 20 :
2123
2270
use_existing = true;
2124
2271
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 ;
2125
2280
default :
2126
2281
/* getopt_long already emitted a complaint */
2127
2282
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
2139
2294
optind ++ ;
2140
2295
}
2141
2296
2297
+ if (config_auth_datadir )
2298
+ {
2299
+ #ifdef ENABLE_SSPI
2300
+ config_sspi_auth (config_auth_datadir );
2301
+ #endif
2302
+ exit (0 );
2303
+ }
2304
+
2142
2305
if (temp_install && !port_specified_by_user )
2143
2306
2144
2307
/*
@@ -2260,6 +2423,18 @@ regression_main(int argc, char *argv[], init_function ifunc, test_function tfunc
2260
2423
2261
2424
fclose (pg_conf );
2262
2425
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
+
2263
2438
/*
2264
2439
* Check if there is a postmaster running already.
2265
2440
*/