@@ -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 ;
@@ -970,6 +971,150 @@ initialize_environment(void)
970
971
load_resultmap ();
971
972
}
972
973
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
+
973
1118
/*
974
1119
* Issue a command via psql, connecting to the specified database
975
1120
*
@@ -1969,6 +2114,7 @@ help(void)
1969
2114
printf (_ ("Usage:\n %s [OPTION]... [EXTRA-TEST]...\n" ), progname );
1970
2115
printf (_ ("\n" ));
1971
2116
printf (_ ("Options:\n" ));
2117
+ printf (_ (" --config-auth=DATADIR update authentication settings for DATADIR\n" ));
1972
2118
printf (_ (" --create-role=ROLE create the specified role before testing\n" ));
1973
2119
printf (_ (" --dbname=DB use database DB (default \"regression\")\n" ));
1974
2120
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
2042
2188
{"launcher" , required_argument , NULL , 21 },
2043
2189
{"load-extension" , required_argument , NULL , 22 },
2044
2190
{"extra-install" , required_argument , NULL , 23 },
2191
+ {"config-auth" , required_argument , NULL , 24 },
2045
2192
{NULL , 0 , NULL , 0 }
2046
2193
};
2047
2194
@@ -2146,6 +2293,14 @@ regression_main(int argc, char *argv[], init_function ifunc, test_function tfunc
2146
2293
case 23 :
2147
2294
add_stringlist_item (& extra_install , optarg );
2148
2295
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 ;
2149
2304
default :
2150
2305
/* getopt_long already emitted a complaint */
2151
2306
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
2163
2318
optind ++ ;
2164
2319
}
2165
2320
2321
+ if (config_auth_datadir )
2322
+ {
2323
+ #ifdef ENABLE_SSPI
2324
+ config_sspi_auth (config_auth_datadir );
2325
+ #endif
2326
+ exit (0 );
2327
+ }
2328
+
2166
2329
if (temp_install && !port_specified_by_user )
2167
2330
2168
2331
/*
@@ -2303,6 +2466,18 @@ regression_main(int argc, char *argv[], init_function ifunc, test_function tfunc
2303
2466
2304
2467
fclose (pg_conf );
2305
2468
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
+
2306
2481
/*
2307
2482
* Check if there is a postmaster running already.
2308
2483
*/
0 commit comments