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