changeset 9914:0b1953a9e081

Merge jdk7u251-b02
author andrew
date Thu, 06 Feb 2020 01:43:16 +0000
parents 625beb747dbc (current diff) c9b1004ad44d (diff)
children 5cfb0b2d8b78
files .hgtags make/java/net/Makefile src/share/classes/com/sun/java/util/jar/pack/ClassReader.java src/share/classes/com/sun/jndi/ldap/Connection.java src/share/classes/java/awt/color/ICC_Profile.java src/share/classes/java/lang/System.java src/share/classes/java/nio/file/Files.java src/share/classes/sun/applet/AppletClassLoader.java src/share/classes/sun/misc/SharedSecrets.java src/share/classes/sun/nio/ch/DatagramChannelImpl.java src/share/classes/sun/nio/ch/Net.java src/share/classes/sun/reflect/misc/MethodUtil.java src/share/classes/sun/security/krb5/Config.java src/share/classes/sun/security/krb5/PrincipalName.java src/share/classes/sun/security/krb5/internal/rcache/CacheTable.java src/share/classes/sun/security/krb5/internal/rcache/ReplayCache.java src/share/classes/sun/security/pkcs12/PKCS12KeyStore.java src/share/classes/sun/security/timestamp/HttpTimestamper.java src/share/lib/security/java.security-linux src/share/lib/security/java.security-macosx src/share/lib/security/java.security-solaris src/share/lib/security/java.security-windows src/share/native/sun/font/freetypeScaler.c src/solaris/classes/sun/nio/ch/AixPollPort.java src/solaris/classes/sun/nio/ch/SctpChannelImpl.java src/solaris/classes/sun/nio/ch/SctpMultiChannelImpl.java src/solaris/classes/sun/nio/ch/SctpServerChannelImpl.java src/solaris/classes/sun/nio/fs/UnixNativeDispatcher.java src/solaris/native/sun/java2d/x11/X11SurfaceData.c src/solaris/native/sun/nio/ch/Net.c test/ProblemList.txt test/sun/security/krb5/ConfPlusProp.java test/sun/security/krb5/DnsFallback.java test/sun/security/krb5/auto/ReplayCache.java test/sun/security/krb5/auto/SaslGSS.java test/sun/security/krb5/auto/ok-as-delegate-xrealm.sh test/sun/security/krb5/auto/ok-as-delegate.sh
diffstat 359 files changed, 11733 insertions(+), 3909 deletions(-) [+]
line wrap: on
line diff
--- a/.hgtags	Wed Nov 20 06:36:47 2019 +0000
+++ b/.hgtags	Thu Feb 06 01:43:16 2020 +0000
@@ -707,3 +707,7 @@
 6a2e99c14397b7ea3b29446826e42074c8933d18 jdk7u241-b01
 5dbb96b727d595be7bef13c5cd2c799a71f389b9 icedtea-2.6.20
 89324d11814dc25f36f5e32ac0797b33bd3337e6 icedtea-2.6.21pre00
+6a2e99c14397b7ea3b29446826e42074c8933d18 jdk7u241-ga
+6a2e99c14397b7ea3b29446826e42074c8933d18 jdk7u251-b00
+ec18dc04c53cc88e732740341caf0d228cd4b90e jdk7u251-b01
+cfc6f6b7d6ff93fcbaed0f1ca8400246e917a20c jdk7u251-b02
--- a/make/java/net/Makefile	Wed Nov 20 06:36:47 2019 +0000
+++ b/make/java/net/Makefile	Thu Feb 06 01:43:16 2020 +0000
@@ -115,7 +115,7 @@
 else
 ifeq ($(PLATFORM), windows)
   OTHER_LDLIBS = ws2_32.lib $(JVMLIB) \
-                 secur32.lib iphlpapi.lib delayimp.lib urlmon.lib \
+                 secur32.lib iphlpapi.lib delayimp.lib \
                  /DELAYLOAD:secur32.dll /DELAYLOAD:iphlpapi.dll
 else
   OTHER_LDLIBS = $(LIBSOCKET) $(LIBNSL) $(JVMLIB)
--- a/make/java/nio/mapfile-bsd	Wed Nov 20 06:36:47 2019 +0000
+++ b/make/java/nio/mapfile-bsd	Thu Feb 06 01:43:16 2020 +0000
@@ -108,6 +108,13 @@
 		Java_sun_nio_ch_Net_setInterface6;
 		Java_sun_nio_ch_Net_getInterface6;
 		Java_sun_nio_ch_Net_shutdown;
+		Java_sun_nio_ch_Net_poll;
+		Java_sun_nio_ch_Net_pollinValue;
+		Java_sun_nio_ch_Net_polloutValue;
+		Java_sun_nio_ch_Net_pollerrValue;
+		Java_sun_nio_ch_Net_pollhupValue;
+		Java_sun_nio_ch_Net_pollnvalValue;
+		Java_sun_nio_ch_Net_pollconnValue;
                 Java_sun_nio_ch_Net_isExclusiveBindAvailable;
                 Java_sun_nio_ch_PollArrayWrapper_interrupt;
                 Java_sun_nio_ch_PollArrayWrapper_poll0;
--- a/make/java/nio/mapfile-linux	Wed Nov 20 06:36:47 2019 +0000
+++ b/make/java/nio/mapfile-linux	Thu Feb 06 01:43:16 2020 +0000
@@ -116,6 +116,13 @@
 		Java_sun_nio_ch_Net_setInterface6;
 		Java_sun_nio_ch_Net_getInterface6;
 		Java_sun_nio_ch_Net_shutdown;
+		Java_sun_nio_ch_Net_poll;
+		Java_sun_nio_ch_Net_pollinValue;
+		Java_sun_nio_ch_Net_polloutValue;
+		Java_sun_nio_ch_Net_pollerrValue;
+		Java_sun_nio_ch_Net_pollhupValue;
+		Java_sun_nio_ch_Net_pollnvalValue;
+		Java_sun_nio_ch_Net_pollconnValue;
                 Java_sun_nio_ch_Net_isExclusiveBindAvailable;
                 Java_sun_nio_ch_PollArrayWrapper_interrupt;
                 Java_sun_nio_ch_PollArrayWrapper_poll0;
--- a/make/java/nio/mapfile-solaris	Wed Nov 20 06:36:47 2019 +0000
+++ b/make/java/nio/mapfile-solaris	Thu Feb 06 01:43:16 2020 +0000
@@ -104,6 +104,13 @@
 		Java_sun_nio_ch_Net_setInterface6;
 		Java_sun_nio_ch_Net_getInterface6;
 		Java_sun_nio_ch_Net_shutdown;
+		Java_sun_nio_ch_Net_poll;
+		Java_sun_nio_ch_Net_pollinValue;
+		Java_sun_nio_ch_Net_polloutValue;
+		Java_sun_nio_ch_Net_pollerrValue;
+		Java_sun_nio_ch_Net_pollhupValue;
+		Java_sun_nio_ch_Net_pollnvalValue;
+		Java_sun_nio_ch_Net_pollconnValue;
                 Java_sun_nio_ch_Net_isExclusiveBindAvailable;
                 Java_sun_nio_ch_PollArrayWrapper_interrupt;
                 Java_sun_nio_ch_PollArrayWrapper_poll0;
--- a/make/sun/javazic/tzdata/VERSION	Wed Nov 20 06:36:47 2019 +0000
+++ b/make/sun/javazic/tzdata/VERSION	Thu Feb 06 01:43:16 2020 +0000
@@ -21,4 +21,4 @@
 # or visit www.oracle.com if you need additional information or have any
 # questions.
 #
-tzdata2019a
+tzdata2019c
--- a/make/sun/javazic/tzdata/africa	Wed Nov 20 06:36:47 2019 +0000
+++ b/make/sun/javazic/tzdata/africa	Thu Feb 06 01:43:16 2020 +0000
@@ -112,7 +112,7 @@
 Rule	Algeria	1980	only	-	Oct	31	 2:00	0	-
 # Shanks & Pottenger give 0:09:20 for Paris Mean Time; go with Howse's
 # more precise 0:09:21.
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Africa/Algiers	0:12:12 -	LMT	1891 Mar 15  0:01
 			0:09:21	-	PMT	1911 Mar 11 # Paris Mean Time
 			0:00	Algeria	WE%sT	1940 Feb 25  2:00
@@ -147,7 +147,7 @@
 # For now, ignore that and follow the 1911-05-26 Portuguese decree
 # (see Europe/Lisbon).
 #
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone Atlantic/Cape_Verde -1:34:04 -	LMT	1912 Jan 01  2:00u # Praia
 			-2:00	-	-02	1942 Sep
 			-2:00	1:00	-01	1945 Oct 15
@@ -158,7 +158,7 @@
 # See Africa/Lagos.
 
 # Chad
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Africa/Ndjamena	1:00:12 -	LMT	1912        # N'Djamena
 			1:00	-	WAT	1979 Oct 14
 			1:00	1:00	WAST	1980 Mar  8
@@ -174,7 +174,7 @@
 # See Africa/Lagos.
 
 # Côte d'Ivoire / Ivory Coast
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Africa/Abidjan	-0:16:08 -	LMT	1912
 			 0:00	-	GMT
 Link Africa/Abidjan Africa/Bamako	# Mali
@@ -379,7 +379,7 @@
 Rule	Egypt	2014	only	-	Jul	31	24:00	1:00	S
 Rule	Egypt	2014	only	-	Sep	lastThu	24:00	0	-
 
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Africa/Cairo	2:05:09 -	LMT	1900 Oct
 			2:00	Egypt	EE%sT
 
@@ -437,7 +437,7 @@
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule	Ghana	1920	1942	-	Sep	 1	0:00	0:20	-
 Rule	Ghana	1920	1942	-	Dec	31	0:00	0	-
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Africa/Accra	-0:00:52 -	LMT	1918
 			 0:00	Ghana	GMT/+0020
 
@@ -451,13 +451,13 @@
 # evidently confusing the date of the Portuguese decree
 # (see Europe/Lisbon) with the date that it took effect.
 #
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Africa/Bissau	-1:02:20 -	LMT	1912 Jan  1  1:00u
 			-1:00	-	-01	1975
 			 0:00	-	GMT
 
 # Kenya
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Africa/Nairobi	2:27:16	-	LMT	1928 Jul
 			3:00	-	EAT	1930
 			2:30	-	+0230	1940
@@ -492,7 +492,7 @@
 # Use the abbreviation "MMT" before 1972, as the more-accurate numeric
 # abbreviation "-004430" would be one byte over the POSIX limit.
 #
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Africa/Monrovia	-0:43:08 -	LMT	1882
 			-0:43:08 -	MMT	1919 Mar # Monrovia Mean Time
 			-0:44:30 -	MMT	1972 Jan 7 # approximately MMT
@@ -542,7 +542,7 @@
 Rule	Libya	1997	only	-	Oct	 4	0:00	0	-
 Rule	Libya	2013	only	-	Mar	lastFri	1:00	1:00	S
 Rule	Libya	2013	only	-	Oct	lastFri	2:00	0	-
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Africa/Tripoli	0:52:44 -	LMT	1920
 			1:00	Libya	CE%sT	1959
 			2:00	-	EET	1982
@@ -652,7 +652,7 @@
 Rule Mauritius	1983	only	-	Mar	21	0:00	0	-
 Rule Mauritius	2008	only	-	Oct	lastSun	2:00	1:00	-
 Rule Mauritius	2009	only	-	Mar	lastSun	2:00	0	-
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone Indian/Mauritius	3:50:00 -	LMT	1907 # Port Louis
 			4:00 Mauritius	+04/+05
 # Agalega Is, Rodriguez
@@ -883,18 +883,24 @@
 # the week end after....  The government does not announce yet the decision
 # about this temporary change.  But it s 99% sure that it will be the case,
 # as in previous years.  An unofficial survey was done these days, showing
-# that 64% of asked peopke are ok for moving from +1 to +0 during Ramadan.
+# that 64% of asked people are ok for moving from +1 to +0 during Ramadan.
 # https://leconomiste.com/article/1035870-enquete-l-economiste-sunergia-64-des-marocains-plebiscitent-le-gmt-pendant-ramadan
+
+# From Naoufal Semlali (2019-04-16):
+# Morocco will be on GMT starting from Sunday, May 5th 2019 at 3am.
+# The switch to GMT+1 will occur on Sunday, June 9th 2019 at 2am....
+# http://fr.le360.ma/societe/voici-la-date-du-retour-a-lheure-legale-au-maroc-188222
 #
-# From Paul Eggert (2018-11-01):
-# For now, guess that Morocco will fall back at 03:00 the last Sunday
-# before Ramadan, and spring forward at 02:00 the first Sunday after
+# From Paul Eggert (2019-05-20):
+# This agrees with our 2018-11-01 guess that the Moroccan government
+# would continue the practice of falling back at 03:00 the last Sunday
+# before Ramadan, and of springing forward at 02:00 the first Sunday after
 # Ramadan, as this has been the practice since 2012.  To implement this,
-# transition dates for 2019 through 2037 were determined by running the
-# following program under GNU Emacs 26.1.
+# transition dates for 2019 through 2087 were determined by running the
+# following program under GNU Emacs 26.2.
 # (let ((islamic-year 1440))
 #   (require 'cal-islam)
-#   (while (< islamic-year 1460)
+#   (while (< islamic-year 1511)
 #     (let ((a (calendar-islamic-to-absolute (list 9 1 islamic-year)))
 #           (b (calendar-islamic-to-absolute (list 10 1 islamic-year)))
 #           (sunday 0))
@@ -993,8 +999,114 @@
 Rule	Morocco	2036	only	-	Nov	23	 2:00	1:00	-
 Rule	Morocco	2037	only	-	Oct	 4	 3:00	0	-
 Rule	Morocco	2037	only	-	Nov	15	 2:00	1:00	-
+Rule	Morocco	2038	only	-	Sep	26	 3:00	0	-
+Rule	Morocco	2038	only	-	Oct	31	 2:00	1:00	-
+Rule	Morocco	2039	only	-	Sep	18	 3:00	0	-
+Rule	Morocco	2039	only	-	Oct	23	 2:00	1:00	-
+Rule	Morocco	2040	only	-	Sep	 2	 3:00	0	-
+Rule	Morocco	2040	only	-	Oct	14	 2:00	1:00	-
+Rule	Morocco	2041	only	-	Aug	25	 3:00	0	-
+Rule	Morocco	2041	only	-	Sep	29	 2:00	1:00	-
+Rule	Morocco	2042	only	-	Aug	10	 3:00	0	-
+Rule	Morocco	2042	only	-	Sep	21	 2:00	1:00	-
+Rule	Morocco	2043	only	-	Aug	 2	 3:00	0	-
+Rule	Morocco	2043	only	-	Sep	 6	 2:00	1:00	-
+Rule	Morocco	2044	only	-	Jul	24	 3:00	0	-
+Rule	Morocco	2044	only	-	Aug	28	 2:00	1:00	-
+Rule	Morocco	2045	only	-	Jul	 9	 3:00	0	-
+Rule	Morocco	2045	only	-	Aug	20	 2:00	1:00	-
+Rule	Morocco	2046	only	-	Jul	 1	 3:00	0	-
+Rule	Morocco	2046	only	-	Aug	 5	 2:00	1:00	-
+Rule	Morocco	2047	only	-	Jun	23	 3:00	0	-
+Rule	Morocco	2047	only	-	Jul	28	 2:00	1:00	-
+Rule	Morocco	2048	only	-	Jun	 7	 3:00	0	-
+Rule	Morocco	2048	only	-	Jul	19	 2:00	1:00	-
+Rule	Morocco	2049	only	-	May	30	 3:00	0	-
+Rule	Morocco	2049	only	-	Jul	 4	 2:00	1:00	-
+Rule	Morocco	2050	only	-	May	15	 3:00	0	-
+Rule	Morocco	2050	only	-	Jun	26	 2:00	1:00	-
+Rule	Morocco	2051	only	-	May	 7	 3:00	0	-
+Rule	Morocco	2051	only	-	Jun	11	 2:00	1:00	-
+Rule	Morocco	2052	only	-	Apr	28	 3:00	0	-
+Rule	Morocco	2052	only	-	Jun	 2	 2:00	1:00	-
+Rule	Morocco	2053	only	-	Apr	13	 3:00	0	-
+Rule	Morocco	2053	only	-	May	25	 2:00	1:00	-
+Rule	Morocco	2054	only	-	Apr	 5	 3:00	0	-
+Rule	Morocco	2054	only	-	May	10	 2:00	1:00	-
+Rule	Morocco	2055	only	-	Mar	28	 3:00	0	-
+Rule	Morocco	2055	only	-	May	 2	 2:00	1:00	-
+Rule	Morocco	2056	only	-	Mar	12	 3:00	0	-
+Rule	Morocco	2056	only	-	Apr	23	 2:00	1:00	-
+Rule	Morocco	2057	only	-	Mar	 4	 3:00	0	-
+Rule	Morocco	2057	only	-	Apr	 8	 2:00	1:00	-
+Rule	Morocco	2058	only	-	Feb	17	 3:00	0	-
+Rule	Morocco	2058	only	-	Mar	31	 2:00	1:00	-
+Rule	Morocco	2059	only	-	Feb	 9	 3:00	0	-
+Rule	Morocco	2059	only	-	Mar	16	 2:00	1:00	-
+Rule	Morocco	2060	only	-	Feb	 1	 3:00	0	-
+Rule	Morocco	2060	only	-	Mar	 7	 2:00	1:00	-
+Rule	Morocco	2061	only	-	Jan	16	 3:00	0	-
+Rule	Morocco	2061	only	-	Feb	27	 2:00	1:00	-
+Rule	Morocco	2062	only	-	Jan	 8	 3:00	0	-
+Rule	Morocco	2062	only	-	Feb	12	 2:00	1:00	-
+Rule	Morocco	2062	only	-	Dec	31	 3:00	0	-
+Rule	Morocco	2063	only	-	Feb	 4	 2:00	1:00	-
+Rule	Morocco	2063	only	-	Dec	16	 3:00	0	-
+Rule	Morocco	2064	only	-	Jan	20	 2:00	1:00	-
+Rule	Morocco	2064	only	-	Dec	 7	 3:00	0	-
+Rule	Morocco	2065	only	-	Jan	11	 2:00	1:00	-
+Rule	Morocco	2065	only	-	Nov	22	 3:00	0	-
+Rule	Morocco	2066	only	-	Jan	 3	 2:00	1:00	-
+Rule	Morocco	2066	only	-	Nov	14	 3:00	0	-
+Rule	Morocco	2066	only	-	Dec	19	 2:00	1:00	-
+Rule	Morocco	2067	only	-	Nov	 6	 3:00	0	-
+Rule	Morocco	2067	only	-	Dec	11	 2:00	1:00	-
+Rule	Morocco	2068	only	-	Oct	21	 3:00	0	-
+Rule	Morocco	2068	only	-	Dec	 2	 2:00	1:00	-
+Rule	Morocco	2069	only	-	Oct	13	 3:00	0	-
+Rule	Morocco	2069	only	-	Nov	17	 2:00	1:00	-
+Rule	Morocco	2070	only	-	Oct	 5	 3:00	0	-
+Rule	Morocco	2070	only	-	Nov	 9	 2:00	1:00	-
+Rule	Morocco	2071	only	-	Sep	20	 3:00	0	-
+Rule	Morocco	2071	only	-	Oct	25	 2:00	1:00	-
+Rule	Morocco	2072	only	-	Sep	11	 3:00	0	-
+Rule	Morocco	2072	only	-	Oct	16	 2:00	1:00	-
+Rule	Morocco	2073	only	-	Aug	27	 3:00	0	-
+Rule	Morocco	2073	only	-	Oct	 8	 2:00	1:00	-
+Rule	Morocco	2074	only	-	Aug	19	 3:00	0	-
+Rule	Morocco	2074	only	-	Sep	23	 2:00	1:00	-
+Rule	Morocco	2075	only	-	Aug	11	 3:00	0	-
+Rule	Morocco	2075	only	-	Sep	15	 2:00	1:00	-
+Rule	Morocco	2076	only	-	Jul	26	 3:00	0	-
+Rule	Morocco	2076	only	-	Sep	 6	 2:00	1:00	-
+Rule	Morocco	2077	only	-	Jul	18	 3:00	0	-
+Rule	Morocco	2077	only	-	Aug	22	 2:00	1:00	-
+Rule	Morocco	2078	only	-	Jul	10	 3:00	0	-
+Rule	Morocco	2078	only	-	Aug	14	 2:00	1:00	-
+Rule	Morocco	2079	only	-	Jun	25	 3:00	0	-
+Rule	Morocco	2079	only	-	Jul	30	 2:00	1:00	-
+Rule	Morocco	2080	only	-	Jun	16	 3:00	0	-
+Rule	Morocco	2080	only	-	Jul	21	 2:00	1:00	-
+Rule	Morocco	2081	only	-	Jun	 1	 3:00	0	-
+Rule	Morocco	2081	only	-	Jul	13	 2:00	1:00	-
+Rule	Morocco	2082	only	-	May	24	 3:00	0	-
+Rule	Morocco	2082	only	-	Jun	28	 2:00	1:00	-
+Rule	Morocco	2083	only	-	May	16	 3:00	0	-
+Rule	Morocco	2083	only	-	Jun	20	 2:00	1:00	-
+Rule	Morocco	2084	only	-	Apr	30	 3:00	0	-
+Rule	Morocco	2084	only	-	Jun	11	 2:00	1:00	-
+Rule	Morocco	2085	only	-	Apr	22	 3:00	0	-
+Rule	Morocco	2085	only	-	May	27	 2:00	1:00	-
+Rule	Morocco	2086	only	-	Apr	14	 3:00	0	-
+Rule	Morocco	2086	only	-	May	19	 2:00	1:00	-
+Rule	Morocco	2087	only	-	Mar	30	 3:00	0	-
+Rule	Morocco	2087	only	-	May	 4	 2:00	1:00	-
+# For dates after the somewhat-arbitrary cutoff of 2087, assume that
+# Morocco will no longer observe DST.  At some point this table will
+# need to be extended, though quite possibly Morocco will change the
+# rules first.
 
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone Africa/Casablanca	-0:30:20 -	LMT	1913 Oct 26
 			 0:00	Morocco	+00/+01	1984 Mar 16
 			 1:00	-	+01	1986
@@ -1024,7 +1136,7 @@
 # https://dre.pt/pdf1sdip/1911/05/12500/23132313.pdf
 # merely made it official?
 #
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Africa/Maputo	2:10:20 -	LMT	1903 Mar
 			2:00	-	CAT
 Link Africa/Maputo Africa/Blantyre	# Malawi
@@ -1096,7 +1208,7 @@
 Rule	Namibia	1995	2017	-	Apr	Sun>=1	2:00	0	WAT
 # End of rearguard section.
 
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Africa/Windhoek	1:08:24 -	LMT	1892 Feb 8
 			1:30	-	+0130	1903 Mar
 			2:00	-	SAST	1942 Sep 20  2:00
@@ -1117,7 +1229,7 @@
 # See Africa/Lagos.
 
 # Nigeria
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Africa/Lagos	0:13:36 -	LMT	1919 Sep
 			1:00	-	WAT
 Link Africa/Lagos Africa/Bangui	     # Central African Republic
@@ -1131,7 +1243,7 @@
 Link Africa/Lagos Africa/Porto-Novo  # Benin
 
 # Réunion
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Indian/Reunion	3:41:52 -	LMT	1911 Jun # Saint-Denis
 			4:00	-	+04
 #
@@ -1191,7 +1303,7 @@
 # See Africa/Abidjan.
 
 # Seychelles
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Indian/Mahe	3:41:48 -	LMT	1906 Jun # Victoria
 			4:00	-	+04
 # From Paul Eggert (2001-05-30):
@@ -1211,7 +1323,7 @@
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule	SA	1942	1943	-	Sep	Sun>=15	2:00	1:00	-
 Rule	SA	1943	1944	-	Mar	Sun>=15	2:00	0	-
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone Africa/Johannesburg 1:52:00 -	LMT	1892 Feb 8
 			1:30	-	SAST	1903 Mar
 			2:00	SA	SAST
@@ -1246,14 +1358,14 @@
 Rule	Sudan	1970	1985	-	Oct	15	0:00	0	-
 Rule	Sudan	1971	only	-	Apr	30	0:00	1:00	S
 Rule	Sudan	1972	1985	-	Apr	lastSun	0:00	1:00	S
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Africa/Khartoum	2:10:08 -	LMT	1931
 			2:00	Sudan	CA%sT	2000 Jan 15 12:00
 			3:00	-	EAT	2017 Nov  1
 			2:00	-	CAT
 
 # South Sudan
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Africa/Juba	2:06:28 -	LMT	1931
 			2:00	Sudan	CA%sT	2000 Jan 15 12:00
 			3:00	-	EAT
@@ -1359,7 +1471,7 @@
 # Shanks & Pottenger give 0:09:20 for Paris Mean Time; go with Howse's
 # more precise 0:09:21.
 # Shanks & Pottenger say the 1911 switch was on Mar 9; go with Howse's Mar 11.
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Africa/Tunis	0:40:44 -	LMT	1881 May 12
 			0:09:21	-	PMT	1911 Mar 11 # Paris Mean Time
 			1:00	Tunisia	CE%sT
--- a/make/sun/javazic/tzdata/antarctica	Wed Nov 20 06:36:47 2019 +0000
+++ b/make/sun/javazic/tzdata/antarctica	Thu Feb 06 01:43:16 2020 +0000
@@ -36,7 +36,7 @@
 # for information.
 # Unless otherwise specified, we have no time zone information.
 
-# FORMAT is '-00' and GMTOFF is 0 for locations while uninhabited.
+# FORMAT is '-00' and STDOFF is 0 for locations while uninhabited.
 
 # Argentina - year-round bases
 # Belgrano II, Confin Coast, -770227-0343737, since 1972-02-05
@@ -93,7 +93,7 @@
 # Australian Antarctica Division informed us that Casey changed time
 # zone to UTC+11 in "the morning of 22nd October 2016".
 
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone Antarctica/Casey	0	-	-00	1969
 			8:00	-	+08	2009 Oct 18  2:00
 			11:00	-	+11	2010 Mar  5  2:00
@@ -165,7 +165,7 @@
 # St Paul Island - near Amsterdam, uninhabited
 #	fishing stations operated variously 1819/1931
 #
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone Indian/Kerguelen	0	-	-00	1950 # Port-aux-Français
 			5:00	-	+05
 #
@@ -176,7 +176,7 @@
 # Another base at Port-Martin, 50km east, began operation in 1947.
 # It was destroyed by fire on 1952-01-14.
 #
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone Antarctica/DumontDUrville 0 -	-00	1947
 			10:00	-	+10	1952 Jan 14
 			0	-	-00	1956 Nov
@@ -204,7 +204,7 @@
 # Syowa station, which is the first antarctic station of Japan,
 # was established on 1957-01-29.  Since Syowa station is still the main
 # station of Japan, it's appropriate for the principal location.
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone Antarctica/Syowa	0	-	-00	1957 Jan 29
 			3:00	-	+03
 # See:
@@ -254,7 +254,7 @@
 #Rule	Troll	2004	max	-	Nov	 7	1:00u	0:00	+00
 # Remove the following line when uncommenting the above '#Rule' lines.
 Rule	Troll	2004	max	-	Oct	lastSun	1:00u	0:00	+00
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone Antarctica/Troll	0	-	-00	2005 Feb 12
 			0:00	Troll	%s
 
@@ -328,7 +328,7 @@
 # From Paul Eggert (2002-10-22)
 # <http://webexhibits.org/daylightsaving/g.html> says Rothera is -03 all year.
 #
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone Antarctica/Rothera	0	-	-00	1976 Dec  1
 			-3:00	-	-03
 
--- a/make/sun/javazic/tzdata/asia	Wed Nov 20 06:36:47 2019 +0000
+++ b/make/sun/javazic/tzdata/asia	Thu Feb 06 01:43:16 2020 +0000
@@ -31,7 +31,7 @@
 # tz@iana.org for general use in the future).  For more, please see
 # the file CONTRIBUTING in the tz distribution.
 
-# From Paul Eggert (2018-06-19):
+# From Paul Eggert (2019-07-11):
 #
 # Unless otherwise specified, the source for data through 1990 is:
 # Thomas G. Shanks and Rique Pottenger, The International Atlas (6th edition),
@@ -70,13 +70,13 @@
 #	7:00 WIB	west Indonesia (Waktu Indonesia Barat)
 #	8:00 WITA	central Indonesia (Waktu Indonesia Tengah)
 #	8:00 CST	China
-#	8:00 PST  PDT*	Philippine Standard Time
+#	8:00 HKT  HKST	Hong Kong (HKWT* for Winter Time in late 1941)
+#	8:00 PST  PDT*	Philippines
 #	8:30 KST  KDT	Korea when at +0830
 #	9:00 WIT	east Indonesia (Waktu Indonesia Timur)
 #	9:00 JST  JDT	Japan
 #	9:00 KST  KDT	Korea when at +09
-#	9:30 ACST	Australian Central Standard Time
-# *I invented the abbreviation PDT; see "Philippines" below.
+# *I invented the abbreviations HKWT and PDT; see below.
 # Otherwise, these tables typically use numeric abbreviations like +03
 # and +0330 for integer hour and minute UT offsets.  Although earlier
 # editions invented alphabetic time zone abbreviations for every
@@ -107,7 +107,7 @@
 Rule RussiaAsia	1996	2010	-	Oct	lastSun	 2:00s	0	-
 
 # Afghanistan
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Kabul	4:36:48 -	LMT	1890
 			4:00	-	+04	1945
 			4:30	-	+0430
@@ -140,7 +140,7 @@
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule Armenia	2011	only	-	Mar	lastSun	 2:00s	1:00	-
 Rule Armenia	2011	only	-	Oct	lastSun	 2:00s	0	-
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Yerevan	2:58:00 -	LMT	1924 May  2
 			3:00	-	+03	1957 Mar
 			4:00 RussiaAsia +04/+05	1991 Mar 31  2:00s
@@ -166,7 +166,7 @@
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule	Azer	1997	2015	-	Mar	lastSun	 4:00	1:00	-
 Rule	Azer	1997	2015	-	Oct	lastSun	 5:00	0	-
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Baku	3:19:24 -	LMT	1924 May  2
 			3:00	-	+03	1957 Mar
 			4:00 RussiaAsia +04/+05	1991 Mar 31  2:00s
@@ -254,7 +254,7 @@
 Rule	Dhaka	2009	only	-	Jun	19	23:00	1:00	-
 Rule	Dhaka	2009	only	-	Dec	31	24:00	0	-
 
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Dhaka	6:01:40 -	LMT	1890
 			5:53:20	-	HMT	1941 Oct    # Howrah Mean Time?
 			6:30	-	+0630	1942 May 15
@@ -264,7 +264,7 @@
 			6:00	Dhaka	+06/+07
 
 # Bhutan
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Thimphu	5:58:36 -	LMT	1947 Aug 15 # or Thimbu
 			5:30	-	+0530	1987 Oct
 			6:00	-	+06
@@ -275,13 +275,13 @@
 # We have no information as to when standard time was introduced;
 # assume it occurred in 1907, the same year as Mauritius (which
 # then contained the Chagos Archipelago).
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Indian/Chagos	4:49:40	-	LMT	1907
 			5:00	-	+05	1996
 			6:00	-	+06
 
 # Brunei
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Brunei	7:39:40 -	LMT	1926 Mar # Bandar Seri Begawan
 			7:30	-	+0730	1933
 			8:00	-	+08
@@ -296,7 +296,7 @@
 # of Greenwich."  This refers to the period before Burma's transition to +0630,
 # a transition for which Shanks is the only source.
 
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Yangon	6:24:47 -	LMT	1880        # or Rangoon
 			6:24:47	-	RMT	1920        # Rangoon local time
 			6:30	-	+0630	1942 May
@@ -584,7 +584,7 @@
 # that the sort of users who prefer Asia/Urumqi now typically ignored the
 # +08 mandate back then.
 
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 # Beijing time, used throughout China; represented by Shanghai.
 Zone	Asia/Shanghai	8:05:43	-	LMT	1901
 			8:00	Shang	C%sT	1949 May 28
@@ -675,11 +675,50 @@
 #   https://i.imgur.com/05KkvtC.png
 # * 1941-09-30, Hong Kong Daily Press, Winter Time Warning.
 #   https://i.imgur.com/dge4kFJ.png
-# Also, the Liberation day of Hong Kong after WWII which British rule
-# over the territory resumed was August 30, 1945, which I think should
-# be the termination date for the use of JST in the territory....
-
-# From Paul Eggert (2018-11-17):
+
+# From Paul Eggert (2019-07-11):
+# "Hong Kong winter time" is considered to be daylight saving.
+# "Hong Kong had adopted daylight saving on June 15 as a wartime measure,
+# clocks moving forward one hour until October 1, when they would be put back
+# by just half an hour for 'Hong Kong Winter time', so that daylight saving
+# operated year round." -- Low Z. The longest day: when wartime Hong Kong
+# introduced daylight saving. South China Morning Post. 2019-06-28.
+# https://www.scmp.com/magazines/post-magazine/short-reads/article/3016281/longest-day-when-wartime-hong-kong-introduced
+
+# From P Chan (2018-12-31):
+# * According to the Hong Kong Daylight-Saving Regulations, 1941, the
+#   1941 spring-forward transition was at 03:00.
+#	http://sunzi.lib.hku.hk/hkgro/view/g1941/304271.pdf
+#	http://sunzi.lib.hku.hk/hkgro/view/g1941/305516.pdf
+# * According to some articles from South China Morning Post, +08 was
+#   resumed on 1945-11-18 at 02:00.
+#	https://i.imgur.com/M2IsZ3c.png
+#	https://i.imgur.com/iOPqrVo.png
+#	https://i.imgur.com/fffcGDs.png
+# * Some newspapers ... said the 1946 spring-forward transition was on
+#   04-21 at 00:00.  The Kung Sheung Evening News 1946-04-20 (Chinese)
+#	https://i.imgur.com/ZSzent0.png
+#	https://mmis.hkpl.gov.hk///c/portal/cover?c=QF757YsWv5%2FH7zGe%2FKF%2BFLYsuqGhRBfe p.4
+#   The Kung Sheung Daily News 1946-04-21 (Chinese)
+#	https://i.imgur.com/7ecmRlcm.png
+#	https://mmis.hkpl.gov.hk///c/portal/cover?c=QF757YsWv5%2BQBGt1%2BwUj5qG2GqtwR3Wh p.4
+# * According to the Summer Time Ordinance (1946), the fallback
+#   transitions between 1946 and 1952 were at 03:30 Standard Time (+08)
+#	http://oelawhk.lib.hku.hk/archive/files/bb74b06a74d5294620a15de560ab33c6.pdf
+# * Some other laws and regulations related to DST from 1953 to 1979
+#   Summer Time Ordinance 1953
+#	https://i.imgur.com/IOlJMav.jpg
+#   Summer Time (Amendment) Ordinance 1965
+#	https://i.imgur.com/8rofeLa.jpg
+#   Interpretation and General Clauses Ordinance (1966)
+#	https://i.imgur.com/joy3msj.jpg
+#   Emergency (Summer Time) Regulation 1973 <https://i.imgur.com/OpRWrKz.jpg>
+#   Interpretation and General Clauses (Amendment) Ordinance 1977
+#	https://i.imgur.com/RaNqnc4.jpg
+#   Resolution of the Legislative Council passed on 9 May 1979
+#	https://www.legco.gov.hk/yr78-79/english/lc_sitg/hansard/h790509.pdf#page=39
+
+# From Paul Eggert (2019-05-31):
 # Here are the dates given at
 # https://www.hko.gov.hk/gts/time/Summertime.htm
 # as of 2014-06-19:
@@ -690,7 +729,7 @@
 # 1944        Whole year
 # 1945        Whole year
 # 1946        20 Apr to 1 Dec
-# 1947        13 Apr to 30 Dec
+# 1947        13 Apr to 30 Nov
 # 1948        2 May to 31 Oct
 # 1949        3 Apr to 30 Oct
 # 1950        2 Apr to 29 Oct
@@ -727,36 +766,28 @@
 # The page does not give times of day for transitions,
 # or dates for the 1942 and 1945 transitions.
 # The Japanese occupation of Hong Kong began 1941-12-25.
-# The Japanese surrender of Hong Kong was signed 1945-09-16; see:
-# Heaver S. The days after the Pacific war ended: unsettling times
-# in Hong Kong. Post Magazine. 2016-06-13.
-# https://www.scmp.com/magazines/post-magazine/article/1852990/days-after-pacific-war-ended-unsettling-times-hong-kong
-# For lack of anything better, use start of those days as the
-# transition times.
 
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
-Rule	HK	1946	only	-	Apr	20	3:30	1:00	S
-Rule	HK	1946	only	-	Dec	1	3:30	0	-
-Rule	HK	1947	only	-	Apr	13	3:30	1:00	S
-Rule	HK	1947	only	-	Dec	30	3:30	0	-
-Rule	HK	1948	only	-	May	2	3:30	1:00	S
-Rule	HK	1948	1951	-	Oct	lastSun	3:30	0	-
-Rule	HK	1952	1953	-	Nov	Sun>=1	3:30	0	-
+Rule	HK	1946	only	-	Apr	21	0:00	1:00	S
+Rule	HK	1946	only	-	Dec	1	3:30s	0	-
+Rule	HK	1947	only	-	Apr	13	3:30s	1:00	S
+Rule	HK	1947	only	-	Nov	30	3:30s	0	-
+Rule	HK	1948	only	-	May	2	3:30s	1:00	S
+Rule	HK	1948	1952	-	Oct	Sun>=28	3:30s	0	-
 Rule	HK	1949	1953	-	Apr	Sun>=1	3:30	1:00	S
+Rule	HK	1953	1964	-	Oct	Sun>=31	3:30	0	-
 Rule	HK	1954	1964	-	Mar	Sun>=18	3:30	1:00	S
-Rule	HK	1954	only	-	Oct	31	3:30	0	-
-Rule	HK	1955	1964	-	Nov	Sun>=1	3:30	0	-
 Rule	HK	1965	1976	-	Apr	Sun>=16	3:30	1:00	S
 Rule	HK	1965	1976	-	Oct	Sun>=16	3:30	0	-
 Rule	HK	1973	only	-	Dec	30	3:30	1:00	S
-Rule	HK	1979	only	-	May	Sun>=8	3:30	1:00	S
-Rule	HK	1979	only	-	Oct	Sun>=16	3:30	0	-
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+Rule	HK	1979	only	-	May	13	3:30	1:00	S
+Rule	HK	1979	only	-	Oct	21	3:30	0	-
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Hong_Kong	7:36:42 -	LMT	1904 Oct 30  0:36:42
-			8:00	-	HKT	1941 Jun 15  3:30
+			8:00	-	HKT	1941 Jun 15  3:00
 			8:00	1:00	HKST	1941 Oct  1  4:00
-			8:30	-	HKT	1941 Dec 25
-			9:00	-	JST	1945 Sep 16
+			8:00	0:30	HKWT	1941 Dec 25
+			9:00	-	JST	1945 Nov 18  2:00
 			8:00	HK	HK%sT
 
 ###############################################################################
@@ -880,7 +911,7 @@
 Rule	Taiwan	1979	only	-	Jul	1	0:00	1:00	D
 Rule	Taiwan	1979	only	-	Oct	1	0:00	0	S
 
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 # Taipei or Taibei or T'ai-pei
 Zone	Asia/Taipei	8:06:00 -	LMT	1896 Jan  1
 			8:00	-	CST	1937 Oct  1
@@ -1018,7 +1049,7 @@
 Rule	Macau	1979	only	-	May	13	03:30	1:00	D
 Rule	Macau	1979	only	-	Oct	Sun>=16	03:30	0	S
 
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Macau	7:34:10 -	LMT	1904 Oct 30
 			8:00	-	CST	1941 Dec 21 23:00
 			9:00	Macau	+09/+10	1945 Sep 30 24:00
@@ -1057,7 +1088,7 @@
 Rule	Cyprus	1978	only	-	Oct	2	0:00	0	-
 Rule	Cyprus	1979	1997	-	Sep	lastSun	0:00	0	-
 Rule	Cyprus	1981	1998	-	Mar	lastSun	0:00	1:00	S
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Nicosia	2:13:28 -	LMT	1921 Nov 14
 			2:00	Cyprus	EE%sT	1998 Sep
 			2:00	EUAsia	EE%sT
@@ -1106,7 +1137,7 @@
 # Byalokoz 1919 says Georgia was 2:59:11.
 # Go with Byalokoz.
 
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Tbilisi	2:59:11 -	LMT	1880
 			2:59:11	-	TBMT	1924 May  2 # Tbilisi Mean Time
 			3:00	-	+03	1957 Mar
@@ -1143,7 +1174,7 @@
 # which will be permanent, with no seasonal adjustment, will happen at
 # midnight on Saturday, September 16.
 
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Dili	8:22:20 -	LMT	1912 Jan  1
 			8:00	-	+08	1942 Feb 21 23:00
 			9:00	-	+09	1976 May  3
@@ -1209,7 +1240,7 @@
 # time for 1870-1941.  Shanks is our only (and dubious) source for the
 # 1941-1945 data.
 
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Kolkata	5:53:28 -	LMT	1854 Jun 28 # Kolkata
 			5:53:20	-	HMT	1870	    # Howrah Mean Time?
 			5:21:10	-	MMT	1906 Jan  1 # Madras local time
@@ -1261,7 +1292,7 @@
 # WITA - +08 - Waktu Indonesia Tengah (Indonesia central time)
 # WIT  - +09 - Waktu Indonesia Timur (Indonesia eastern time)
 #
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 # Java, Sumatra
 Zone Asia/Jakarta	7:07:12 -	LMT	1867 Aug 10
 # Shanks & Pottenger say the next transition was at 1924 Jan 1 0:13,
@@ -1337,9 +1368,9 @@
 # I used the following code in GNU Emacs 26.1 to generate the "Rule Iran"
 # lines from 2008 through 2087.  Emacs 26.1 uses Ed Reingold's
 # cal-persia implementation of Birashk's approximation, which in the
-# 2008-2087 range disagrees with the the astronomical Persian calendar
-# for Persian years 1404 (Gregorian 2025) and 1437 (Gregorian 2058),
-# so the following code special-case those years.  See Table 15.1, page 264, of:
+# 2008-2087 range disagrees with the astronomical Persian calendar
+# for Persian years 1404 (Gregorian 2025) and 1437 (Gregorian 2058), so
+# the following code special-cases those years.  See Table 15.1, page 264, of:
 # Edward M. Reingold and Nachum Dershowitz, Calendrical Calculations:
 # The Ultimate Edition, Cambridge University Press (2018).
 # https://www.cambridge.org/fr/academic/subjects/computer-science/computing-general-interest/calendrical-calculations-ultimate-edition-4th-edition
@@ -1533,7 +1564,7 @@
 Rule	Iran	2088	max	-	Mar	20	24:00	1:00	-
 Rule	Iran	2088	max	-	Sep	20	24:00	0	-
 
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Tehran	3:25:44	-	LMT	1916
 			3:25:44	-	TMT	1946     # Tehran Mean Time
 			3:30	-	+0330	1977 Nov
@@ -1578,7 +1609,7 @@
 #
 Rule	Iraq	1991	2007	-	Apr	 1	3:00s	1:00	-
 Rule	Iraq	1991	2007	-	Oct	 1	3:00s	0	-
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Baghdad	2:57:40	-	LMT	1890
 			2:57:36	-	BMT	1918     # Baghdad Mean Time?
 			3:00	-	+03	1982 May
@@ -1645,7 +1676,7 @@
 Rule	Zion	1975	only	-	Aug	31	0:00	0	S
 
 # From Alois Treindl (2019-03-06):
-# http://www.moin.gov.il/Documents/שעון קיץ/clock-50-years-7-2014.pdf
+# http://www.moin.gov.il/Documents/שעון%20קיץ/clock-50-years-7-2014.pdf
 # From Isaac Starkman (2019-03-06):
 # Summer time was in that period in 1980 and 1984, see
 # https://www.ynet.co.il/articles/0,7340,L-3951073,00.html
@@ -1783,32 +1814,15 @@
 #
 #	ftp://ftp.cs.huji.ac.il/pub/tz/announcements/2005+beyond.ps
 
-# From Paul Eggert (2012-10-26):
-# I used Ephraim Silverberg's dst-israel.el program
-# <ftp://ftp.cs.huji.ac.il/pub/tz/software/dst-israel.el> (2005-02-20)
-# along with Ed Reingold's cal-hebrew in GNU Emacs 21.4,
-# to generate the transitions from 2005 through 2012.
-# (I replaced "lastFri" with "Fri>=26" by hand.)
-# The spring transitions all correspond to the following Rule:
-#
-# Rule	Zion	2005	2012	-	Mar	Fri>=26	2:00	1:00	D
-#
-# but older zic implementations (e.g., Solaris 8) do not support
-# "Fri>=26" to mean April 1 in years like 2005, so for now we list the
-# springtime transitions explicitly.
-
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
-Rule	Zion	2005	only	-	Apr	 1	2:00	1:00	D
+Rule	Zion	2005	2012	-	Apr	Fri<=1	2:00	1:00	D
 Rule	Zion	2005	only	-	Oct	 9	2:00	0	S
-Rule	Zion	2006	2010	-	Mar	Fri>=26	2:00	1:00	D
 Rule	Zion	2006	only	-	Oct	 1	2:00	0	S
 Rule	Zion	2007	only	-	Sep	16	2:00	0	S
 Rule	Zion	2008	only	-	Oct	 5	2:00	0	S
 Rule	Zion	2009	only	-	Sep	27	2:00	0	S
 Rule	Zion	2010	only	-	Sep	12	2:00	0	S
-Rule	Zion	2011	only	-	Apr	 1	2:00	1:00	D
 Rule	Zion	2011	only	-	Oct	 2	2:00	0	S
-Rule	Zion	2012	only	-	Mar	Fri>=26	2:00	1:00	D
 Rule	Zion	2012	only	-	Sep	23	2:00	0	S
 
 # From Ephraim Silverberg (2013-06-27):
@@ -1824,7 +1838,7 @@
 Rule	Zion	2013	max	-	Mar	Fri>=23	2:00	1:00	D
 Rule	Zion	2013	max	-	Oct	lastSun	2:00	0	S
 
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Jerusalem	2:20:54 -	LMT	1880
 			2:20:40	-	JMT	1918 # Jerusalem Mean Time?
 			2:00	Zion	I%sT
@@ -1916,7 +1930,7 @@
 # Central Time (UT+9). The adoption began on Oct 1, 1937.
 # https://ja.wikisource.org/wiki/明治二十八年勅令第百六十七號標準時ニ關スル件中改正ノ件
 
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Tokyo	9:18:59	-	LMT	1887 Dec 31 15:00u
 			9:00	Japan	J%sT
 # Since 1938, all Japanese possessions have been like Asia/Tokyo,
@@ -2019,7 +2033,7 @@
 Rule	Jordan	2013	only	-	Dec	20	0:00	0	-
 Rule	Jordan	2014	max	-	Mar	lastThu	24:00	1:00	S
 Rule	Jordan	2014	max	-	Oct	lastFri	0:00s	0	-
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Amman	2:23:44 -	LMT	1931
 			2:00	Jordan	EE%sT
 
@@ -2060,8 +2074,8 @@
 # text.
 #
 # According to Izvestia newspaper No. 68 (23334) from 1991-03-20
-# (page 6; available at http://libinfo.org/newsr/newsr2574.djvu via
-# http://libinfo.org/index.php?id=58564) on 1991-03-31 at 2:00 during
+# -- page 6; available at http://libinfo.org/newsr/newsr2574.djvu via
+# http://libinfo.org/index.php?id=58564 -- on 1991-03-31 at 2:00 during
 # transition to "summer" time:
 # Republic of Georgia, Latvian SSR, Lithuanian SSR, SSR Moldova,
 # Estonian SSR; Komi ASSR; Kaliningrad oblast; Nenets autonomous okrug
@@ -2077,7 +2091,7 @@
 # Apparently there were last minute changes. Apparently Kazakh act No. 170
 # was one of such changes.
 #
-# https://ru.wikipedia.org/wiki/Декретное время
+# https://ru.wikipedia.org/wiki/Декретное_время
 # claims that Sovetskaya Rossiya newspaper on 1991-03-29 published that
 # Nenets autonomous okrug, Komi and Kazakhstan (excluding Uralsk oblast)
 # were to not move clocks and Uralsk oblast was to move clocks
@@ -2216,7 +2230,7 @@
 # UTC+6 to UTC+5 effective December 21st, 2018. The legal document is
 # located here: http://adilet.zan.kz/rus/docs/P1800000817 (russian language).
 
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 #
 # Almaty (formerly Alma-Ata), representing most locations in Kazakhstan
 # This includes KZ-AKM, KZ-ALA, KZ-ALM, KZ-AST, KZ-BAY, KZ-VOS, KZ-ZHA,
@@ -2318,7 +2332,7 @@
 Rule	Kyrgyz	1992	1996	-	Sep	lastSun	0:00	0	-
 Rule	Kyrgyz	1997	2005	-	Mar	lastSun	2:30	1:00	-
 Rule	Kyrgyz	1997	2004	-	Oct	lastSun	2:30	0	-
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Bishkek	4:58:24 -	LMT	1924 May  2
 			5:00	-	+05	1930 Jun 21
 			6:00 RussiaAsia +06/+07	1991 Mar 31  2:00s
@@ -2433,11 +2447,11 @@
 # The BBC reported that the transition was from 23:30 to 24:00 today.
 # https://www.bbc.com/news/world-asia-44010705
 
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Seoul	8:27:52	-	LMT	1908 Apr  1
 			8:30	-	KST	1912 Jan  1
 			9:00	-	JST	1945 Sep  8
-			9:00	-	KST	1954 Mar 21
+			9:00	ROK	K%sT	1954 Mar 21
 			8:30	ROK	K%sT	1961 Aug 10
 			9:00	ROK	K%sT
 Zone	Asia/Pyongyang	8:23:00 -	LMT	1908 Apr  1
@@ -2482,7 +2496,7 @@
 Rule	Lebanon	1993	max	-	Mar	lastSun	0:00	1:00	S
 Rule	Lebanon	1993	1998	-	Sep	lastSun	0:00	0	-
 Rule	Lebanon	1999	max	-	Oct	lastSun	0:00	0	-
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Beirut	2:22:00 -	LMT	1880
 			2:00	Lebanon	EE%sT
 
@@ -2494,7 +2508,7 @@
 # peninsular Malaysia
 # taken from Mok Ly Yng (2003-10-30)
 # http://www.math.nus.edu.sg/aslaksen/teaching/timezone.html
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone Asia/Kuala_Lumpur	6:46:46 -	LMT	1901 Jan  1
 			6:55:25	-	SMT	1905 Jun  1 # Singapore M.T.
 			7:00	-	+07	1933 Jan  1
@@ -2508,7 +2522,7 @@
 # From Paul Eggert (2014-08-12):
 # The data entries here are mostly from Shanks & Pottenger, but the 1942, 1945
 # and 1982 transition dates are from Mok Ly Yng.
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone Asia/Kuching	7:21:20	-	LMT	1926 Mar
 			7:30	-	+0730	1933
 			8:00 NBorneo  +08/+0820	1942 Feb 16
@@ -2516,7 +2530,7 @@
 			8:00	-	+08
 
 # Maldives
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Indian/Maldives	4:54:00 -	LMT	1880 # Malé
 			4:54:00	-	MMT	1960 # Malé Mean Time
 			5:00	-	+05
@@ -2659,7 +2673,7 @@
 Rule	Mongol	2015	2016	-	Mar	lastSat	2:00	1:00	-
 Rule	Mongol	2015	2016	-	Sep	lastSat	0:00	0	-
 
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 # Hovd, a.k.a. Chovd, Dund-Us, Dzhargalant, Khovd, Jirgalanta
 Zone	Asia/Hovd	6:06:36 -	LMT	1905 Aug
 			6:00	-	+06	1978
@@ -2677,7 +2691,7 @@
 			8:00	Mongol	+08/+09
 
 # Nepal
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Kathmandu	5:41:16 -	LMT	1920
 			5:30	-	+0530	1986
 			5:45	-	+0545
@@ -2827,7 +2841,7 @@
 Rule Pakistan	2008	2009	-	Nov	1	0:00	0	-
 Rule Pakistan	2009	only	-	Apr	15	0:00	1:00	S
 
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Karachi	4:28:12 -	LMT	1907
 			5:30	-	+0530	1942 Sep
 			5:30	1:00	+0630	1945 Oct 15
@@ -3114,13 +3128,21 @@
 # http://www.palestinecabinet.gov.ps/Website/AR/NDecrees/ViewFile.ashx?ID=e7a42ab7-ee23-435a-b9c8-a4f7e81f3817
 
 # From Even Scharning (2019-03-23):
-# DST in Palestine will start on 30 March this year, not 23 March as the time
-# zone database predicted.
-# https://ramallah.news/post/123610
+# http://pnn.ps/news/401130
+# http://palweather.ps/ar/node/50136.html
 #
-# From Tim Parenti (2019-03-23):
-# Combining this with the rules observed since 2016, adjust our spring
-# transition guess to Mar Sat>=24.
+# From Sharif Mustafa (2019-03-26):
+# The Palestinian cabinet announced today that the switch to DST will
+# be on Fri Mar 29th 2019 by advancing the clock by 60 minutes.
+# The decree signing date is Mar 12th but it was not published till today.
+# The decree does not specify the exact time of switch.
+# http://palestinecabinet.gov.ps/Website/AR/NDecrees/ViewFile.ashx?ID=e54e9ea1-50ee-4137-84df-0d6c78da259b
+#
+# From Even Scharning (2019-04-10):
+# Our source in Palestine said it happened Friday 29 at 00:00 local time....
+#
+# From Paul Eggert (2019-04-10):
+# For now, guess spring-ahead transitions are March's last Friday at 00:00.
 
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule EgyptAsia	1957	only	-	May	10	0:00	1:00	S
@@ -3151,10 +3173,11 @@
 Rule Palestine	2013	only	-	Sep	Fri>=21	0:00	0	-
 Rule Palestine	2014	2015	-	Oct	Fri>=21	0:00	0	-
 Rule Palestine	2015	only	-	Mar	lastFri	24:00	1:00	S
-Rule Palestine	2016	max	-	Mar	Sat>=24	1:00	1:00	S
+Rule Palestine	2016	2018	-	Mar	Sat>=24	1:00	1:00	S
 Rule Palestine	2016	max	-	Oct	lastSat	1:00	0	-
-
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+Rule Palestine	2019	max	-	Mar	lastFri	0:00	1:00	S
+
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Gaza	2:17:52	-	LMT	1900 Oct
 			2:00	Zion	EET/EEST 1948 May 15
 			2:00 EgyptAsia	EE%sT	1967 Jun  5
@@ -3228,7 +3251,7 @@
 Rule	Phil	1954	only	-	Jul	1	0:00	0	S
 Rule	Phil	1978	only	-	Mar	22	0:00	1:00	D
 Rule	Phil	1978	only	-	Sep	21	0:00	0	S
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Manila	-15:56:00 -	LMT	1844 Dec 31
 			8:04:00 -	LMT	1899 May 11
 			8:00	Phil	P%sT	1942 May
@@ -3236,7 +3259,7 @@
 			8:00	Phil	P%sT
 
 # Qatar
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Qatar	3:26:08 -	LMT	1920     # Al Dawhah / Doha
 			4:00	-	+04	1972 Jun
 			3:00	-	+03
@@ -3284,7 +3307,7 @@
 # the country.  Presumably this is documenting airline time.  Ignore this,
 # as it's before our 1970 cutoff.
 #
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Riyadh	3:06:52 -	LMT	1947 Mar 14
 			3:00	-	+03
 Link Asia/Riyadh Asia/Aden	# Yemen
@@ -3293,7 +3316,7 @@
 # Singapore
 # taken from Mok Ly Yng (2003-10-30)
 # http://www.math.nus.edu.sg/aslaksen/teaching/timezone.html
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Singapore	6:55:25 -	LMT	1901 Jan  1
 			6:55:25	-	SMT	1905 Jun  1 # Singapore M.T.
 			7:00	-	+07	1933 Jan  1
@@ -3357,7 +3380,7 @@
 # even worse.  For now, let's use a numeric abbreviation; we can
 # switch to "SLST" if it catches on.
 
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Colombo	5:19:24 -	LMT	1880
 			5:19:32	-	MMT	1906        # Moratuwa Mean Time
 			5:30	-	+0530	1942 Jan  5
@@ -3527,13 +3550,13 @@
 Rule	Syria	2012	max	-	Mar	lastFri	0:00	1:00	S
 Rule	Syria	2009	max	-	Oct	lastFri	0:00	0	-
 
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Damascus	2:25:12 -	LMT	1920 # Dimashq
 			2:00	Syria	EE%sT
 
 # Tajikistan
 # From Shanks & Pottenger.
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Dushanbe	4:35:12 -	LMT	1924 May  2
 			5:00	-	+05	1930 Jun 21
 			6:00 RussiaAsia +06/+07	1991 Mar 31  2:00s
@@ -3541,7 +3564,7 @@
 			5:00	-	+05
 
 # Thailand
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Bangkok	6:42:04	-	LMT	1880
 			6:42:04	-	BMT	1920 Apr # Bangkok Mean Time
 			7:00	-	+07
@@ -3550,7 +3573,7 @@
 
 # Turkmenistan
 # From Shanks & Pottenger.
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Ashgabat	3:53:32 -	LMT	1924 May  2 # or Ashkhabad
 			4:00	-	+04	1930 Jun 21
 			5:00 RussiaAsia	+05/+06	1991 Mar 31  2:00
@@ -3558,14 +3581,14 @@
 			5:00	-	+05
 
 # United Arab Emirates
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Dubai	3:41:12 -	LMT	1920
 			4:00	-	+04
 Link Asia/Dubai Asia/Muscat	# Oman
 
 # Uzbekistan
 # Byalokoz 1919 says Uzbekistan was 4:27:53.
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Samarkand	4:27:53 -	LMT	1924 May  2
 			4:00	-	+04	1930 Jun 21
 			5:00	-	+05	1981 Apr  1
@@ -3613,7 +3636,7 @@
 # and in South Vietnam in particular (after 1954):
 # To 07:00 on 1911-05-01.
 # To 08:00 on 1942-12-31 at 23:00.
-# To 09:00 in 1945-03-14 at 23:00.
+# To 09:00 on 1945-03-14 at 23:00.
 # To 07:00 on 1945-09-02 in Vietnam.
 # To 08:00 on 1947-04-01 in French-controlled Indochina.
 # To 07:00 on 1955-07-01 in South Vietnam.
@@ -3631,7 +3654,7 @@
 # Lê Thành Lân: "Lịch hai thế kỷ (1802-2010) và các lịch vĩnh cửu",
 # NXB Thuận Hoá, Huế, 1995.
 
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone Asia/Ho_Chi_Minh	7:06:40 -	LMT	1906 Jul  1
 			7:06:30	-	PLMT	1911 May  1 # Phù Liễn MT
 			7:00	-	+07	1942 Dec 31 23:00
--- a/make/sun/javazic/tzdata/australasia	Wed Nov 20 06:36:47 2019 +0000
+++ b/make/sun/javazic/tzdata/australasia	Thu Feb 06 01:43:16 2020 +0000
@@ -48,7 +48,7 @@
 # says W Australia didn't use DST in 1943/1944.  Ignore Whitman's claim that
 # 1944/1945 was just like 1943/1944.
 
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 # Northern Territory
 Zone Australia/Darwin	 8:43:20 -	LMT	1895 Feb
 			 9:00	-	ACST	1899 May
@@ -125,7 +125,7 @@
 Rule	AS	2007	only	-	Mar	lastSun	2:00s	0	S
 Rule	AS	2008	max	-	Apr	Sun>=1	2:00s	0	S
 Rule	AS	2008	max	-	Oct	Sun>=1	2:00s	1:00	D
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone Australia/Adelaide	9:14:20 -	LMT	1895 Feb
 			9:00	-	ACST	1899 May
 			9:30	Aus	AC%sT	1971
@@ -157,7 +157,7 @@
 Rule	AT	2006	only	-	Apr	Sun>=1	2:00s	0	S
 Rule	AT	2007	only	-	Mar	lastSun	2:00s	0	S
 Rule	AT	2008	max	-	Apr	Sun>=1	2:00s	0	S
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone Australia/Hobart	9:49:16	-	LMT	1895 Sep
 			10:00	-	AEST	1916 Oct  1  2:00
 			10:00	1:00	AEDT	1917 Feb
@@ -185,7 +185,7 @@
 Rule	AV	2007	only	-	Mar	lastSun	2:00s	0	S
 Rule	AV	2008	max	-	Apr	Sun>=1	2:00s	0	S
 Rule	AV	2008	max	-	Oct	Sun>=1	2:00s	1:00	D
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone Australia/Melbourne 9:39:52 -	LMT	1895 Feb
 			10:00	Aus	AE%sT	1971
 			10:00	AV	AE%sT
@@ -208,7 +208,7 @@
 Rule	AN	2007	only	-	Mar	lastSun	2:00s	0	S
 Rule	AN	2008	max	-	Apr	Sun>=1	2:00s	0	S
 Rule	AN	2008	max	-	Oct	Sun>=1	2:00s	1:00	D
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone Australia/Sydney	10:04:52 -	LMT	1895 Feb
 			10:00	Aus	AE%sT	1971
 			10:00	AN	AE%sT
@@ -279,14 +279,14 @@
 			11:00	-	+11
 
 # Christmas
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone Indian/Christmas	7:02:52 -	LMT	1895 Feb
 			7:00	-	+07
 
 # Cocos (Keeling) Is
 # These islands were ruled by the Ross family from about 1830 to 1978.
 # We don't know when standard time was introduced; for now, we guess 1900.
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Indian/Cocos	6:27:40	-	LMT	1900
 			6:30	-	+0630
 
@@ -390,13 +390,18 @@
 # From Raymond Kumar (2018-07-13):
 # http://www.fijitimes.com/government-approves-2018-daylight-saving/
 # ... The daylight saving period will end at 3am on Sunday January 13, 2019.
-#
-# From Paul Eggert (2018-07-15):
-# For now, guess DST from 02:00 the first Sunday in November to 03:00
-# the first Sunday on or after January 13.  January transitions reportedly
+
+# From Paul Eggert (2019-08-06):
+# Today Raymond Kumar reported the Government of Fiji Gazette Supplement No. 27
+# (2019-08-02) said that Fiji observes DST "commencing at 2.00 am on
+# Sunday, 10 November 2019 and ending at 3.00 am on Sunday, 12 January 2020."
+# For now, guess DST from 02:00 the second Sunday in November to 03:00
+# the first Sunday on or after January 12.  January transitions reportedly
 # depend on when school terms start.  Although the guess is ad hoc, it matches
-# transitions since late 2014 and seems more likely to match future
-# practice than guessing no DST.
+# transitions planned this year and seems more likely to match future practice
+# than guessing no DST.
+# From Michael Deckers (2019-08-06):
+# https://www.laws.gov.fj/LawsAsMade/downloadfile/848
 
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule	Fiji	1998	1999	-	Nov	Sun>=1	2:00	1:00	-
@@ -407,14 +412,15 @@
 Rule	Fiji	2011	only	-	Mar	Sun>=1	3:00	0	-
 Rule	Fiji	2012	2013	-	Jan	Sun>=18	3:00	0	-
 Rule	Fiji	2014	only	-	Jan	Sun>=18	2:00	0	-
-Rule	Fiji	2014	max	-	Nov	Sun>=1	2:00	1:00	-
-Rule	Fiji	2015	max	-	Jan	Sun>=13	3:00	0	-
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+Rule	Fiji	2014	2018	-	Nov	Sun>=1	2:00	1:00	-
+Rule	Fiji	2015	max	-	Jan	Sun>=12	3:00	0	-
+Rule	Fiji	2019	max	-	Nov	Sun>=8	2:00	1:00	-
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Pacific/Fiji	11:55:44 -	LMT	1915 Oct 26 # Suva
 			12:00	Fiji	+12/+13
 
 # French Polynesia
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Pacific/Gambier	 -8:59:48 -	LMT	1912 Oct # Rikitea
 			 -9:00	-	-09
 Zone	Pacific/Marquesas -9:18:00 -	LMT	1912 Oct
@@ -457,7 +463,7 @@
 # http://documents.guam.gov/wp-content/uploads/E.O.-77-18-Guam-Standard-Time.pdf
 Rule	Guam	1977	only	-	Aug	28	2:00	0	S
 
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Pacific/Guam	-14:21:00 -	LMT	1844 Dec 31
 			 9:39:00 -	LMT	1901        # Agana
 			10:00	-	GST	1941 Dec 10 # Guam
@@ -467,7 +473,7 @@
 Link Pacific/Guam Pacific/Saipan # N Mariana Is
 
 # Kiribati
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone Pacific/Tarawa	 11:32:04 -	LMT	1901 # Bairiki
 			 12:00	-	+12
 Zone Pacific/Enderbury	-11:24:20 -	LMT	1901
@@ -483,7 +489,7 @@
 # See Pacific/Guam.
 
 # Marshall Is
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone Pacific/Majuro	 11:24:48 -	LMT	1901
 			 11:00	-	+11	1914 Oct
 			  9:00	-	+09	1919 Feb  1
@@ -501,7 +507,7 @@
 			 12:00	-	+12
 
 # Micronesia
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone Pacific/Chuuk	-13:52:52 -	LMT	1844 Dec 31
 			 10:07:08 -	LMT	1901
 			 10:00	-	+10	1914 Oct
@@ -529,7 +535,7 @@
 			 11:00	-	+11
 
 # Nauru
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Pacific/Nauru	11:07:40 -	LMT	1921 Jan 15 # Uaobe
 			11:30	-	+1130	1942 Aug 29
 			 9:00	-	+09	1945 Sep  8
@@ -543,7 +549,7 @@
 Rule	NC	1996	only	-	Dec	 1	2:00s	1:00	-
 # Shanks & Pottenger say the following was at 2:00; go with IATA.
 Rule	NC	1997	only	-	Mar	 2	2:00s	0	-
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Pacific/Noumea	11:05:48 -	LMT	1912 Jan 13 # Nouméa
 			11:00	NC	+11/+12
 
@@ -582,7 +588,7 @@
 Rule	Chatham	2007	max	-	Sep	lastSun	2:45s	1:00	-
 Rule	NZ	2008	max	-	Apr	Sun>=1	2:00s	0	S
 Rule	Chatham	2008	max	-	Apr	Sun>=1	2:45s	0	-
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone Pacific/Auckland	11:39:04 -	LMT	1868 Nov  2
 			11:30	NZ	NZ%sT	1946 Jan  1
 			12:00	NZ	NZ%sT
@@ -608,7 +614,7 @@
 Rule	Cook	1978	only	-	Nov	12	0:00	0:30	-
 Rule	Cook	1979	1991	-	Mar	Sun>=1	0:00	0	-
 Rule	Cook	1979	1990	-	Oct	lastSun	0:00	0:30	-
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone Pacific/Rarotonga	-10:39:04 -	LMT	1901        # Avarua
 			-10:30	-	-1030	1978 Nov 12
 			-10:00	Cook	-10/-0930
@@ -617,29 +623,30 @@
 
 
 # Niue
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Pacific/Niue	-11:19:40 -	LMT	1901        # Alofi
 			-11:20	-	-1120	1951
 			-11:30	-	-1130	1978 Oct  1
 			-11:00	-	-11
 
 # Norfolk
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Pacific/Norfolk	11:11:52 -	LMT	1901 # Kingston
 			11:12	-	+1112	1951
-			11:30	-	+1130	1974 Oct 27 02:00
-			11:30	1:00	+1230	1975 Mar  2 02:00
-			11:30	-	+1130	2015 Oct  4 02:00
-			11:00	-	+11
+			11:30	-	+1130	1974 Oct 27 02:00s
+			11:30	1:00	+1230	1975 Mar  2 02:00s
+			11:30	-	+1130	2015 Oct  4 02:00s
+			11:00	-	+11	2019 Jul
+			11:00	AN	+11/+12
 
 # Palau (Belau)
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone Pacific/Palau	-15:02:04 -	LMT	1844 Dec 31	# Koror
 			  8:57:56 -	LMT	1901
 			  9:00	-	+09
 
 # Papua New Guinea
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone Pacific/Port_Moresby 9:48:40 -	LMT	1880
 			9:48:32	-	PMMT	1895 # Port Moresby Mean Time
 			10:00	-	+10
@@ -669,7 +676,7 @@
 			11:00	-	+11
 
 # Pitcairn
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone Pacific/Pitcairn	-8:40:20 -	LMT	1901        # Adamstown
 			-8:30	-	-0830	1998 Apr 27  0:00
 			-8:00	-	-08
@@ -754,7 +761,7 @@
 Rule	WS	2011	only	-	Sep	lastSat	3:00	1	-
 Rule	WS	2012	max	-	Apr	Sun>=1	4:00	0	-
 Rule	WS	2012	max	-	Sep	lastSun	3:00	1	-
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone Pacific/Apia	 12:33:04 -	LMT	1892 Jul  5
 			-11:26:56 -	LMT	1911
 			-11:30	-	-1130	1950
@@ -763,7 +770,7 @@
 
 # Solomon Is
 # excludes Bougainville, for which see Papua New Guinea
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone Pacific/Guadalcanal 10:39:48 -	LMT	1912 Oct # Honiara
 			11:00	-	+11
 
@@ -786,7 +793,7 @@
 # was "11 hours slow on G.M.T."  Go with Thorsen and assume Shanks & Pottenger
 # are off by an hour starting in 1901.
 
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Pacific/Fakaofo	-11:24:56 -	LMT	1901
 			-11:00	-	-11	2011 Dec 30
 			13:00	-	+13
@@ -799,14 +806,14 @@
 Rule	Tonga	2001	2002	-	Jan	lastSun	2:00	0	-
 Rule	Tonga	2016	only	-	Nov	Sun>=1	2:00	1:00	-
 Rule	Tonga	2017	only	-	Jan	Sun>=15	3:00	0	-
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone Pacific/Tongatapu	12:19:20 -	LMT	1901
 			12:20	-	+1220	1941
 			13:00	-	+13	1999
 			13:00	Tonga	+13/+14
 
 # Tuvalu
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone Pacific/Funafuti	11:56:52 -	LMT	1901
 			12:00	-	+12
 
@@ -867,7 +874,7 @@
 # uninhabited since World War II; was probably like Pacific/Kiritimati
 
 # Wake
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Pacific/Wake	11:06:28 -	LMT	1901
 			12:00	-	+12
 
@@ -880,12 +887,12 @@
 Rule	Vanuatu	1985	1991	-	Sep	Sun>=23	0:00	1:00	-
 Rule	Vanuatu	1992	1993	-	Jan	Sun>=23	0:00	0	-
 Rule	Vanuatu	1992	only	-	Oct	Sun>=23	0:00	1:00	-
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Pacific/Efate	11:13:16 -	LMT	1912 Jan 13 # Vila
 			11:00	Vanuatu	+11/+12
 
 # Wallis and Futuna
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Pacific/Wallis	12:15:20 -	LMT	1901
 			12:00	-	+12
 
@@ -1271,6 +1278,22 @@
 # in WA or its introduction in SA had anything to do with the genesis
 # of this time zone.  My hunch is that it's been around since well
 # before 1975.  I remember seeing it noted on road maps decades ago.
+#
+# From Gilmore Davidson (2019-04-08):
+# https://www.abc.net.au/news/2019-04-08/this-remote-stretch-of-desert-has-its-own-custom-time-zone/10981000
+# ... include[s] a rough description of the geographical boundaries...
+# "The time zone exists for about 340 kilometres and takes in the tiny
+# roadhouse communities of Cocklebiddy, Madura, Eucla and Border Village."
+# ... and an indication that the zone has definitely been in existence
+# since before the 1970 cut-off of the database ...
+# From Paul Eggert (2019-05-17):
+# That ABC Esperance story by Christien de Garis also says:
+#    Although the Central Western Time Zone is not officially recognised (your
+#    phones won't automatically change), there is a sign instructing you which
+#    way to wind your clocks 45 minutes and scrawled underneath one of them in
+#    Texta is the word: 'Why'?
+#    "Good question," Mr Pike said.
+#    "I don't even know that, and it's been going for over 50 years."
 
 # From Paul Eggert (2006-12-15):
 # For lack of better info, assume the tradition dates back to the
@@ -1589,6 +1612,42 @@
 ###############################################################################
 
 
+# Bonin (Ogasawara) Islands and Marcus Island (Minami-Tori-shima)
+
+# From Wakaba (2019-01-28) via Phake Nick:
+# National Diet Library of Japan has several reports by Japanese Government
+# officers that describe the time used in islands when they visited there.
+# According to them (and other sources such as newspapers), standard time UTC
+# + 10 (JST + 1) and DST UTC + 11 (JST + 2) was used until its return to Japan
+# at 1968-06-26 00:00 JST.  The exact periods of DST are still unknown.
+# I guessed Guam, Mariana, and Bonin and Marcus districts might have
+# synchronized their DST periods, but reports imply they had their own
+# decisions, i.e. there were three or more different time zones....
+#
+# https://wiki.suikawiki.org/n/小笠原諸島の標準時
+
+# From Phake Nick (2019-02-12):
+# Because their last time change to return to Japanese time when they returned
+# to Japanese rule was right before 1970, ... per the current tz database
+# rule, the information doesn't warrant creation of a new timezone for Bonin
+# Islands itself and is thus as an anecdotal note for interest purpose only.
+# ... [The abovementioned link] described some special timekeeping phenomenon
+# regarding Marcus island, another remote island currently owned by Japanese
+# in the same administrative unit as Bonin Islands.  Many reports claim that
+# the American coastal guard on the American quarter of the island use its own
+# coastal guard time, and most sources describe the time as UTC+11, being two
+# hours faster than JST used by some Japanese personnel on the island.  Some
+# sites describe it as same as Wake Island/Guam time although it would be
+# incorrect to be same as Guam.  And then in a few Japanese governmental
+# report from 1980s (from National Institute of Information and Communications
+# Technology) regarding the construction of VLBI facility on the Marcus
+# Island, it claimed that there are three time standards being used on the
+# island at the time which include not just JST (UTC+9) or [US]CG time
+# (UTC+11) but also a JMSDF time (UTC+10) (Japan Maritime Self-Defense
+# Force).  Unfortunately there are no other sources that mentioned such time
+# and there are also no information on things like how the time was used.
+
+
 # Fiji
 
 # Howse writes (p 153) that in 1879 the British governor of Fiji
@@ -1846,12 +1905,21 @@
 # ... at 12.30 am (by legal time in New South Wales) on 4 October 2015.
 # http://www.norfolkisland.gov.nf/nia/MediaRelease/Media%20Release%20Norfolk%20Island%20Standard%20Time%20Change.pdf
 
-# From Paul Eggert (2015-09-23):
+# From Paul Eggert (2019-08-28):
 # Transitions before 2015 are from timeanddate.com, which consulted
 # the Norfolk Island Museum and the Australian Bureau of Meteorology's
 # Norfolk Island station, and found no record of Norfolk observing DST
 # other than in 1974/5.  See:
 # https://www.timeanddate.com/time/australia/norfolk-island.html
+# However, disagree with timeanddate about the 1975-03-02 transition;
+# timeanddate has 02:00 but 02:00s corresponds to what the NSW law said
+# (thanks to Michael Deckers).
+
+# Norfolk started observing Australian DST in spring 2019.
+# From Kyle Czech (2019-08-13):
+# https://www.legislation.gov.au/Details/F2018L01702
+# From Michael Deckers (2019-08-14):
+# https://www.legislation.gov.au/Details/F2019C00010
 
 # Palau
 # See commentary for Micronesia.
--- a/make/sun/javazic/tzdata/europe	Wed Nov 20 06:36:47 2019 +0000
+++ b/make/sun/javazic/tzdata/europe	Thu Feb 06 01:43:16 2020 +0000
@@ -145,7 +145,7 @@
 # position is 51° 28' 30" N, 0° 18' 45" W. The longitude should
 # be within about ±2". The Ordnance Survey grid reference is TQ172761.
 #
-# [This yields GMTOFF = -0:01:15 for London LMT in the 18th century.]
+# [This yields STDOFF = -0:01:15 for London LMT in the 18th century.]
 
 # From Paul Eggert (1993-11-18):
 #
@@ -523,7 +523,7 @@
 #
 # Use Europe/London for Jersey, Guernsey, and the Isle of Man.
 
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/London	-0:01:15 -	LMT	1847 Dec  1  0:00s
 			 0:00	GB-Eire	%s	1968 Oct 27
 			 1:00	-	BST	1971 Oct 31  2:00u
@@ -561,7 +561,7 @@
 #Rule	Eire	1990	1995	-	Oct	Sun>=22	 1:00u	-1:00	-
 #Rule	Eire	1996	max	-	Oct	lastSun	 1:00u	-1:00	-
 
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Dublin	-0:25:00 -	LMT	1880 Aug  2
 			-0:25:21 -	DMT	1916 May 21  2:00s
 			-0:25:21 1:00	IST	1916 Oct  1  2:00s
@@ -760,7 +760,7 @@
 
 # These are for backward compatibility with older versions.
 
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	WET		0:00	EU	WE%sT
 Zone	CET		1:00	C-Eur	CE%sT
 Zone	MET		1:00	C-Eur	ME%sT
@@ -820,14 +820,14 @@
 Rule	Albania	1983	only	-	Apr	18	0:00	1:00	S
 Rule	Albania	1983	only	-	Oct	 1	0:00	0	-
 Rule	Albania	1984	only	-	Apr	 1	0:00	1:00	S
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Tirane	1:19:20 -	LMT	1914
 			1:00	-	CET	1940 Jun 16
 			1:00	Albania	CE%sT	1984 Jul
 			1:00	EU	CE%sT
 
 # Andorra
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Andorra	0:06:04 -	LMT	1901
 			0:00	-	WET	1946 Sep 30
 			1:00	-	CET	1985 Mar 31  2:00
@@ -844,16 +844,21 @@
 # Shanks & Pottenger give 02:00, the BEV 00:00.  Go with the BEV,
 # and guess 02:00 for 1945-04-12.
 
+# From Alois Triendl (2019-07-22):
+# In 1946 the end of DST was on Monday, 7 October 1946, at 3:00 am.
+# Shanks had this right.  Source: Die Weltpresse, 5. Oktober 1946, page 5.
+
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule	Austria	1920	only	-	Apr	 5	2:00s	1:00	S
 Rule	Austria	1920	only	-	Sep	13	2:00s	0	-
 Rule	Austria	1946	only	-	Apr	14	2:00s	1:00	S
-Rule	Austria	1946	1948	-	Oct	Sun>=1	2:00s	0	-
+Rule	Austria	1946	only	-	Oct	 7	2:00s	0	-
+Rule	Austria	1947	1948	-	Oct	Sun>=1	2:00s	0	-
 Rule	Austria	1947	only	-	Apr	 6	2:00s	1:00	S
 Rule	Austria	1948	only	-	Apr	18	2:00s	1:00	S
 Rule	Austria	1980	only	-	Apr	 6	0:00	1:00	S
 Rule	Austria	1980	only	-	Sep	28	0:00	0	-
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Vienna	1:05:21 -	LMT	1893 Apr
 			1:00	C-Eur	CE%sT	1920
 			1:00	Austria	CE%sT	1940 Apr  1  2:00s
@@ -885,7 +890,7 @@
 # Belarussian government decided against changing to winter time....
 # http://eng.belta.by/all_news/society/Belarus-decides-against-adjusting-time-in-Russias-wake_i_76335.html
 #
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Minsk	1:50:16 -	LMT	1880
 			1:50	-	MMT	1924 May  2 # Minsk Mean Time
 			2:00	-	EET	1930 Jun 21
@@ -898,15 +903,35 @@
 
 # Belgium
 #
-# From Paul Eggert (1997-07-02):
+# From Michael Deckers (2019-08-25):
+# The exposition in the web page
+# https://www.bestor.be/wiki/index.php/Voyager_dans_le_temps._L%E2%80%99introduction_de_la_norme_de_Greenwich_en_Belgique
+# gives several contemporary sources from which one can conclude that
+# the switch in Europe/Brussels on 1892-05-01 was from 00:17:30 to 00:00:00.
+#
+# From Paul Eggert (2019-08-28):
+# This quote helps explain the late-1914 situation:
+#   In early November 1914, the Germans imposed the time zone used in central
+#   Europe and forced the inhabitants to set their watches and public clocks
+#   sixty minutes ahead.  Many were reluctant to accept "German time" and
+#   continued to use "Belgian time" among themselves.  Reflecting the spirit of
+#   resistance that arose in the population, a song made fun of this change....
+# The song ended:
+#   Putting your clock forward
+#   Will but hasten the happy hour
+#   When we kick out the Boches!
+# See: Pluvinage G. Brussels on German time. Cahiers Bruxellois -
+# Brusselse Cahiers. 2014;XLVI(1E):15-38.
+# https://www.cairn.info/revue-cahiers-bruxellois-2014-1E-page-15.htm
+#
+# Entries from 1914 through 1917 are taken from "De tijd in België"
+# <https://www.astro.oma.be/GENERAL/INFO/nli001a.html>.
 # Entries from 1918 through 1991 are taken from:
 #	Annuaire de L'Observatoire Royal de Belgique,
 #	Avenue Circulaire, 3, B-1180 BRUXELLES, CLVIIe année, 1991
 #	(Imprimerie HAYEZ, s.p.r.l., Rue Fin, 4, 1080 BRUXELLES, MCMXC),
 #	pp 8-9.
-# LMT before 1892 was 0:17:30, according to the official journal of Belgium:
-#	Moniteur Belge, Samedi 30 Avril 1892, N.121.
-# Thanks to Pascal Delmoitie for these references.
+# Thanks to Pascal Delmoitie for the 1918/1991 references.
 # The 1918 rules are listed for completeness; they apply to unoccupied Belgium.
 # Assume Brussels switched to WET in 1918 when the armistice took effect.
 #
@@ -949,9 +974,9 @@
 Rule	Belgium	1945	only	-	Sep	16	 2:00s	0	-
 Rule	Belgium	1946	only	-	May	19	 2:00s	1:00	S
 Rule	Belgium	1946	only	-	Oct	 7	 2:00s	0	-
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Brussels	0:17:30 -	LMT	1880
-			0:17:30	-	BMT	1892 May  1 12:00  # Brussels MT
+			0:17:30	-	BMT	1892 May  1 00:17:30
 			0:00	-	WET	1914 Nov  8
 			1:00	-	CET	1916 May  1  0:00
 			1:00	C-Eur	CE%sT	1918 Nov 11 11:00u
@@ -976,7 +1001,7 @@
 Rule	Bulg	1980	1982	-	Apr	Sat>=1	23:00	1:00	S
 Rule	Bulg	1980	only	-	Sep	29	 1:00	0	-
 Rule	Bulg	1981	only	-	Sep	27	 2:00	0	-
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Sofia	1:33:16 -	LMT	1880
 			1:56:56	-	IMT	1894 Nov 30 # Istanbul MT?
 			2:00	-	EET	1942 Nov  2  3:00
@@ -1009,7 +1034,7 @@
 Rule	Czech	1946	1949	-	Oct	Sun>=1	2:00s	0	-
 Rule	Czech	1947	1948	-	Apr	Sun>=15	2:00s	1:00	S
 Rule	Czech	1949	only	-	Apr	 9	2:00s	1:00	S
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Prague	0:57:44 -	LMT	1850
 			0:57:44	-	PMT	1891 Oct    # Prague Mean Time
 			1:00	C-Eur	CE%sT	1945 May  9
@@ -1071,7 +1096,7 @@
 Rule	Denmark	1948	only	-	May	 9	 2:00s	1:00	S
 Rule	Denmark	1948	only	-	Aug	 8	 2:00s	0	-
 #
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone Europe/Copenhagen	 0:50:20 -	LMT	1890
 			 0:50:20 -	CMT	1894 Jan  1 # Copenhagen MT
 			 1:00	Denmark	CE%sT	1942 Nov  2  2:00s
@@ -1168,7 +1193,7 @@
 Rule	Thule	2007	max	-	Mar	Sun>=8	2:00	1:00	D
 Rule	Thule	2007	max	-	Nov	Sun>=1	2:00	0	S
 #
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone America/Danmarkshavn -1:14:40 -	LMT	1916 Jul 28
 			-3:00	-	-03	1980 Apr  6  2:00
 			-3:00	EU	-03/-02	1996
@@ -1234,7 +1259,7 @@
 # From Urmet Jänes (2002-03-28):
 # The legislative reference is Government decree No. 84 on 2002-02-21.
 
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Tallinn	1:39:00	-	LMT	1880
 			1:39:00	-	TMT	1918 Feb    # Tallinn Mean Time
 			1:00	C-Eur	CE%sT	1919 Jul
@@ -1297,7 +1322,7 @@
 # Milne says Helsinki (Helsingfors) time was 1:39:49.2 (official document);
 # round to nearest.
 
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Helsinki	1:39:49 -	LMT	1878 May 31
 			1:39:49	-	HMT	1921 May    # Helsinki Mean Time
 			2:00	Finland	EE%sT	1983
@@ -1387,7 +1412,7 @@
 # but Howse quotes the actual French legislation as saying 0:09:21.
 # Go with Howse.  Howse writes that the time in France was officially based
 # on PMT-0:09:21 until 1978-08-09, when the time base finally switched to UTC.
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Paris	0:09:21 -	LMT	1891 Mar 15  0:01
 			0:09:21	-	PMT	1911 Mar 11  0:01 # Paris MT
 # Shanks & Pottenger give 1940 Jun 14 0:00; go with Excoffier and Le Corre.
@@ -1435,7 +1460,7 @@
 Rule SovietZone	1945	only	-	Sep	24	3:00	1:00	S
 Rule SovietZone	1945	only	-	Nov	18	2:00s	0	-
 
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Berlin	0:53:28 -	LMT	1893 Apr
 			1:00	C-Eur	CE%sT	1945 May 24  2:00
 			1:00 SovietZone	CE%sT	1946
@@ -1463,7 +1488,7 @@
 # is in Europe.  Our reference location Tbilisi is in the Asian part.
 
 # Gibraltar
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone Europe/Gibraltar	-0:21:24 -	LMT	1880 Aug  2  0:00s
 			0:00	GB-Eire	%s	1957 Apr 14  2:00
 			1:00	-	CET	1982
@@ -1494,7 +1519,7 @@
 Rule	Greece	1979	only	-	Sep	29	2:00	0	-
 Rule	Greece	1980	only	-	Apr	 1	0:00	1:00	S
 Rule	Greece	1980	only	-	Sep	28	0:00	0	-
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Athens	1:34:52 -	LMT	1895 Sep 14
 			1:34:52	-	AMT	1916 Jul 28  0:01 # Athens MT
 			2:00	Greece	EE%sT	1941 Apr 30
@@ -1531,7 +1556,7 @@
 Rule	Hungary	1957	only	-	Jun	Sun>=1	 1:00	1:00	S
 Rule	Hungary	1957	only	-	Sep	lastSun	 3:00	0	-
 Rule	Hungary	1980	only	-	Apr	 6	 1:00	1:00	S
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Budapest	1:16:20 -	LMT	1890 Oct
 			1:00	C-Eur	CE%sT	1918
 			1:00	Hungary	CE%sT	1941 Apr  8
@@ -1592,7 +1617,7 @@
 Rule	Iceland	1949	only	-	Oct	30	 1:00s	0	-
 Rule	Iceland	1950	1966	-	Oct	Sun>=22	 1:00s	0	-
 Rule	Iceland	1967	only	-	Oct	29	 1:00s	0	-
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone Atlantic/Reykjavik	-1:28	-	LMT	1908
 			-1:00	Iceland	-01/+00	1968 Apr  7  1:00s
 			 0:00	-	GMT
@@ -1606,6 +1631,25 @@
 # But these events all occurred before the 1970 cutoff,
 # so record only the time in Rome.
 #
+# From Stephen Trainor (2019-05-06):
+# http://www.ac-ilsestante.it/MERIDIANE/ora_legale/ORA_LEGALE_ESTIVA_IN_ITALIA.htm
+# ... the [1866] law went into effect on 12 December 1866, rather than
+# the date of the decree (22 Sep 1866)
+# https://web.archive.org/web/20070824155341/http://www.iav.it/planetario/didastro/didastro/english.htm
+# ... "In Italy in 1866 there were 6 railway times (Torino, Verona, Firenze,
+# Roma, Napoli, Palermo). On that year it was decided to unify them, adopting
+# the average time of Rome (even if this city was not yet part of the
+# kingdom).  On the 12th December 1866, on the starting of the winter time
+# table, it took effect in the railways, the post office and the telegraph,
+# not only for the internal service but also for the public....  Milano set
+# the public watches on the Rome time on the same day (12th December 1866),
+# Torino and Bologna on the 1st January 1867, Venezia the 1st May 1880 and the
+# last city was Cagliari in 1886."
+#
+# From Luigi Rosa (2019-05-07):
+# this is the scan of the decree:
+# http://www.radiomarconi.com/marconi/filopanti/1866c.jpg
+#
 # From Michael Deckers (2016-10-24):
 # http://www.ac-ilsestante.it/MERIDIANE/ora_legale quotes a law of 1893-08-10
 # ... [translated as] "The preceding dispositions will enter into
@@ -1616,6 +1660,7 @@
 # The authoritative source for time in Italy is the national metrological
 # institute, which has a summary page of historical DST data at
 # http://www.inrim.it/res/tf/ora_legale_i.shtml
+# [now at http://oldsite.inrim.it/res/tf/ora_legale_i.shtml as of 2017]
 # (2016-10-24):
 # http://www.renzobaldini.it/le-ore-legali-in-italia/
 # has still different data for 1944.  It divides Italy in two, as
@@ -1630,6 +1675,13 @@
 # advanced to sixty minutes later starting at hour two on 1944-04-02; ...
 # Starting at hour three on the date 1944-09-17 standard time will be resumed.
 #
+# From Alois Triendl (2019-07-02):
+# I spent 6 Euros to buy two archive copies of Il Messaggero, a Roman paper,
+# for 1 and 2 April 1944.  The edition of 2 April has this note: "Tonight at 2
+# am, put forward the clock by one hour.  Remember that in the night between
+# today and Monday the 'ora legale' will come in force again."  That makes it
+# clear that in Rome the change was on Monday, 3 April 1944 at 2 am.
+#
 # From Paul Eggert (2016-10-27):
 # Go with INRiM for DST rules, except as corrected by Inglis for 1944
 # for the Kingdom of Italy.  This is consistent with Renzo Baldini.
@@ -1679,8 +1731,8 @@
 Rule	Italy	1977	1979	-	May	Sun>=22	 0:00s	1:00	S
 Rule	Italy	1978	only	-	Oct	 1	 0:00s	0	-
 Rule	Italy	1979	only	-	Sep	30	 0:00s	0	-
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Europe/Rome	0:49:56 -	LMT	1866 Sep 22
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
+Zone	Europe/Rome	0:49:56 -	LMT	1866 Dec 12
 			0:49:56	-	RMT	1893 Oct 31 23:49:56 # Rome Mean
 			1:00	Italy	CE%sT	1943 Sep 10
 			1:00	C-Eur	CE%sT	1944 Jun  4
@@ -1755,7 +1807,7 @@
 # Byalokoz 1919 says Latvia was 1:36:34.
 # Go with Byalokoz.
 
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Riga	1:36:34	-	LMT	1880
 			1:36:34	-	RMT	1918 Apr 15  2:00 # Riga MT
 			1:36:34	1:00	LST	1918 Sep 16  3:00 # Latvian ST
@@ -1777,15 +1829,10 @@
 # From Paul Eggert (2013-09-09):
 # Shanks & Pottenger say Vaduz is like Zurich.
 
-# From Alois Treindl (2013-09-18):
-# http://www.eliechtensteinensia.li/LIJ/1978/1938-1978/1941.pdf
-# ... confirms on p. 6 that Liechtenstein followed Switzerland in 1941 and 1942.
-# I ... translate only the last two paragraphs:
-#    ... during second world war, in the years 1941 and 1942, Liechtenstein
-#    introduced daylight saving time, adapting to Switzerland.  From 1943 on
-#    central European time was in force throughout the year.
-#    From a report of the duke's government to the high council,
-#    regarding the introduction of a time law, of 31 May 1977.
+# From Alois Treindl (2019-07-04):
+# I was able to access the online archive of the Vaduz paper Vaterland ...
+# I could confirm from the paper that Liechtenstein did in fact follow
+# the same DST in 1941 and 1942 as Switzerland did.
 
 Link Europe/Zurich Europe/Vaduz
 
@@ -1825,7 +1872,7 @@
 # http://www.lrvk.lt/nut/11/n1749.htm
 
 
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Vilnius	1:41:16	-	LMT	1880
 			1:24:00	-	WMT	1917        # Warsaw Mean Time
 			1:35:36	-	KMT	1919 Oct 10 # Kaunas Mean Time
@@ -1869,7 +1916,7 @@
 Rule	Lux	1927	only	-	Apr	 9	23:00	1:00	S
 Rule	Lux	1928	only	-	Apr	14	23:00	1:00	S
 Rule	Lux	1929	only	-	Apr	20	23:00	1:00	S
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone Europe/Luxembourg	0:24:36 -	LMT	1904 Jun
 			1:00	Lux	CE%sT	1918 Nov 25
 			0:00	Lux	WE%sT	1929 Oct  6  2:00s
@@ -1894,7 +1941,7 @@
 Rule	Malta	1975	1979	-	Apr	Sun>=15	2:00	1:00	S
 Rule	Malta	1975	1980	-	Sep	Sun>=15	2:00	0	-
 Rule	Malta	1980	only	-	Mar	31	2:00	1:00	S
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Malta	0:58:04 -	LMT	1893 Nov  2  0:00s # Valletta
 			1:00	Italy	CE%sT	1973 Mar 31
 			1:00	Malta	CE%sT	1981
@@ -1963,7 +2010,7 @@
 Rule	Moldova	1997	max	-	Mar	lastSun	 2:00	1:00	S
 Rule	Moldova	1997	max	-	Oct	lastSun	 3:00	0	-
 
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Chisinau	1:55:20 -	LMT	1880
 			1:55	-	CMT	1918 Feb 15 # Chisinau MT
 			1:44:24	-	BMT	1931 Jul 24 # Bucharest MT
@@ -1979,7 +2026,7 @@
 # Monaco
 # Shanks & Pottenger give 0:09:20 for Paris Mean Time; go with Howse's
 # more precise 0:09:21.
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Monaco	0:29:32 -	LMT	1891 Mar 15
 			0:09:21	-	PMT	1911 Mar 11 # Paris Mean Time
 			0:00	France	WE%sT	1945 Sep 16  3:00
@@ -2054,8 +2101,8 @@
 Rule	Neth	1945	only	-	Sep	16	2:00s	0	-
 #
 # Amsterdam Mean Time was +00:19:32.13, but the .13 is omitted
-# below because the current format requires GMTOFF to be an integer.
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# below because the current format requires STDOFF to be an integer.
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone Europe/Amsterdam	0:19:32 -	LMT	1835
 			0:19:32	Neth	%s	1937 Jul  1
 			0:20	Neth +0020/+0120 1940 May 16  0:00
@@ -2074,7 +2121,7 @@
 Rule	Norway	1959	1964	-	Mar	Sun>=15	2:00s	1:00	S
 Rule	Norway	1959	1965	-	Sep	Sun>=15	2:00s	0	-
 Rule	Norway	1965	only	-	Apr	25	2:00s	1:00	S
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Oslo	0:43:00 -	LMT	1895 Jan  1
 			1:00	Norway	CE%sT	1940 Aug 10 23:00
 			1:00	C-Eur	CE%sT	1945 Apr  2  2:00
@@ -2165,7 +2212,7 @@
 Rule	Poland	1960	only	-	Apr	 3	1:00s	1:00	S
 Rule	Poland	1961	1964	-	May	lastSun	1:00s	1:00	S
 Rule	Poland	1962	1964	-	Sep	lastSun	1:00s	0	-
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Warsaw	1:24:00 -	LMT	1880
 			1:24:00	-	WMT	1915 Aug  5 # Warsaw Mean Time
 			1:00	C-Eur	CE%sT	1918 Sep 16  3:00
@@ -2270,7 +2317,7 @@
 Rule	Port	1981	1982	-	Mar	lastSun	 1:00s	1:00	S
 Rule	Port	1983	only	-	Mar	lastSun	 2:00s	1:00	S
 #
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Lisbon	-0:36:45 -	LMT	1884
 			-0:36:45 -	LMT	1912 Jan  1  0:00u # Lisbon MT
 			 0:00	Port	WE%sT	1966 Apr  3  2:00
@@ -2329,7 +2376,7 @@
 Rule	Romania	1980	only	-	Sep	lastSun	 1:00	0	-
 Rule	Romania	1991	1993	-	Mar	lastSun	 0:00s	1:00	S
 Rule	Romania	1991	1993	-	Sep	lastSun	 0:00s	0	-
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone Europe/Bucharest	1:44:24 -	LMT	1891 Oct
 			1:44:24	-	BMT	1931 Jul 24 # Bucharest MT
 			2:00	Romania	EE%sT	1981 Mar 29  2:00s
@@ -2493,6 +2540,12 @@
 # Europe/Kaliningrad covers...
 # 39	RU-KGD	Kaliningrad Oblast
 
+# From Paul Eggert (2019-07-25):
+# Although Shanks lists 1945-01-01 as the date for transition from
+# +01/+02 to +02/+03, more likely this is a placeholder.  Guess that
+# the transition occurred at 1945-04-10 00:00, which is about when
+# Königsberg surrendered to Soviet troops.  (Thanks to Alois Triendl.)
+
 # From Paul Eggert (2016-03-18):
 # The 1989 transition is from USSR act No. 227 (1989-03-14).
 
@@ -2509,8 +2562,8 @@
 # Moscow on 1991-11-03, switched to Moscow-1 on 1992-01-19.
 
 Zone Europe/Kaliningrad	 1:22:00 -	LMT	1893 Apr
-			 1:00	C-Eur	CE%sT	1945
-			 2:00	Poland	CE%sT	1946
+			 1:00	C-Eur	CE%sT	1945 Apr 10
+			 2:00	Poland	EE%sT	1946 Apr  7
 			 3:00	Russia	MSK/MSD	1989 Mar 26  2:00s
 			 2:00	Russia	EE%sT	2011 Mar 27  2:00s
 			 3:00	-	+03	2014 Oct 26  2:00s
@@ -3368,7 +3421,7 @@
 # See Europe/Rome.
 
 # Serbia
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Belgrade	1:22:00	-	LMT	1884
 			1:00	-	CET	1941 Apr 18 23:00
 			1:00	C-Eur	CE%sT	1945
@@ -3474,7 +3527,7 @@
 Rule SpainAfrica 1977	only	-	Sep	28	 0:00	0	-
 Rule SpainAfrica 1978	only	-	Jun	 1	 0:00	1:00	S
 Rule SpainAfrica 1978	only	-	Aug	 4	 0:00	0	-
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Madrid	-0:14:44 -	LMT	1900 Dec 31 23:45:16
 			 0:00	Spain	WE%sT	1940 Mar 16 23:00
 			 1:00	Spain	CE%sT	1979
@@ -3542,7 +3595,7 @@
 #
 # Source: The newspaper "Dagens Nyheter", 1916-10-01, page 7 upper left.
 
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone Europe/Stockholm	1:12:12 -	LMT	1879 Jan  1
 			1:00:14	-	SET	1900 Jan  1 # Swedish Time
 			1:00	-	CET	1916 May 14 23:00
@@ -3645,7 +3698,7 @@
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule	Swiss	1941	1942	-	May	Mon>=1	1:00	1:00	S
 Rule	Swiss	1941	1942	-	Oct	Mon>=1	2:00	0	-
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Zurich	0:34:08 -	LMT	1853 Jul 16 # See above comment.
 			0:29:46	-	BMT	1894 Jun    # Bern Mean Time
 			1:00	Swiss	CE%sT	1981
@@ -3653,20 +3706,75 @@
 
 # Turkey
 
+# From Alois Treindl (2019-08-12):
+# http://www.astrolojidergisi.com/yazsaati.htm has researched the time zone
+# history of Turkey, based on newspaper archives and official documents.
+# From Paul Eggert (2019-08-28):
+# That source (Oya Vulaş, "Türkiye'de Yaz Saati Uygulamaları")
+# is used for 1940/1972, where it seems more reliable than our other
+# sources.
+
+# From Kıvanç Yazan (2019-08-12):
+# http://www.resmigazete.gov.tr/arsiv/14539.pdf#page=24
+# 1973-06-03 01:00 -> 02:00, 1973-11-04 02:00 -> 01:00
+#
+# http://www.resmigazete.gov.tr/arsiv/14829.pdf#page=1
+# 1974-03-31 02:00 -> 03:00, 1974-11-03 02:00 -> 01:00
+#
+# http://www.resmigazete.gov.tr/arsiv/15161.pdf#page=1
+# 1975-03-22 02:00 -> 03:00, 1975-11-02 02:00 -> 01:00
+#
+# http://www.resmigazete.gov.tr/arsiv/15535_1.pdf#page=1
+# 1976-03-21 02:00 -> 03:00, 1976-10-31 02:00 -> 01:00
+#
+# http://www.resmigazete.gov.tr/arsiv/15778.pdf#page=5
+# 1977-04-03 02:00 -> 03:00, 1977-10-16 02:00 -> 01:00,
+# 1978-04-02 02:00 -> 03:00 (not applied, see below)
+# 1978-10-15 02:00 -> 01:00 (not applied, see below)
+# 1979-04-01 02:00 -> 03:00 (not applied, see below)
+# 1979-10-14 02:00 -> 01:00 (not applied, see below)
+#
+# http://www.resmigazete.gov.tr/arsiv/16245.pdf#page=17
+# This cancels the previous decision, and repeats it only for 1978.
+# 1978-04-02 02:00 -> 03:00, 1978-10-15 02:00 -> 01:00
+# (not applied due to standard TZ change below)
+#
+# http://www.resmigazete.gov.tr/arsiv/16331.pdf#page=3
+# This decision changes the default longitude for Turkish time zone from 30
+# degrees East to 45 degrees East.  This means a standard TZ change, from +2
+# to +3.  This is published & applied on 1978-06-29.  At that time, Turkey was
+# already on summer time (already on 45E).  Hence, this new law just meant an
+# "continuous summer time".  Note that this was reversed in a few years.
+#
+# http://www.resmigazete.gov.tr/arsiv/18119_1.pdf#page=1
+# 1983-07-31 02:00 -> 03:00 (note that this jumps TZ to +4)
+# 1983-10-02 02:00 -> 01:00 (back to +3)
+#
+# http://www.resmigazete.gov.tr/arsiv/18561.pdf (page 1 and 34)
+# At this time, Turkey is still on +3 with no spring-forward on early
+# 1984.  This decision is published on 10/31/1984.  Page 1 declares
+# the decision of reverting the "default longitude change".  So the
+# standard time should go back to +3 (30E).  And page 34 explains when
+# that will happen: 1984-11-01 02:00 -> 01:00.  You can think of this
+# as "end of continuous summer time, change of standard time zone".
+#
+# http://www.resmigazete.gov.tr/arsiv/18713.pdf#page=1
+# 1985-04-20 01:00 -> 02:00, 1985-09-28 02:00 -> 01:00
+
 # From Kıvanç Yazan (2016-09-25):
 # 1) For 1986-2006, DST started at 01:00 local and ended at 02:00 local, with
 #    no exceptions.
 # 2) 1994's lastSun was overridden with Mar 20 ...
 # Here are official papers:
-# http://www.resmigazete.gov.tr/arsiv/19032.pdf  - page 2 for 1986
-# http://www.resmigazete.gov.tr/arsiv/19400.pdf  - page 4 for 1987
-# http://www.resmigazete.gov.tr/arsiv/19752.pdf  - page 15 for 1988
-# http://www.resmigazete.gov.tr/arsiv/20102.pdf  - page 6 for 1989
-# http://www.resmigazete.gov.tr/arsiv/20464.pdf  - page 1 for 1990 - 1992
-# http://www.resmigazete.gov.tr/arsiv/21531.pdf  - page 15 for 1993 - 1995
-# http://www.resmigazete.gov.tr/arsiv/21879.pdf  - page 1 for overriding 1994
-# http://www.resmigazete.gov.tr/arsiv/22588.pdf  - page 1 for 1996, 1997
-# http://www.resmigazete.gov.tr/arsiv/23286.pdf  - page 10 for 1998 - 2000
+# http://www.resmigazete.gov.tr/arsiv/19032.pdf#page=2 for 1986
+# http://www.resmigazete.gov.tr/arsiv/19400.pdf#page=4 for 1987
+# http://www.resmigazete.gov.tr/arsiv/19752.pdf#page=15 for 1988
+# http://www.resmigazete.gov.tr/arsiv/20102.pdf#page=6 for 1989
+# http://www.resmigazete.gov.tr/arsiv/20464.pdf#page=1 for 1990 - 1992
+# http://www.resmigazete.gov.tr/arsiv/21531.pdf#page=15 for 1993 - 1995
+# http://www.resmigazete.gov.tr/arsiv/21879.pdf#page=1 for overriding 1994
+# http://www.resmigazete.gov.tr/arsiv/22588.pdf#page=1 for 1996, 1997
+# http://www.resmigazete.gov.tr/arsiv/23286.pdf#page=10 for 1998 - 2000
 # http://www.resmigazete.gov.tr/eskiler/2001/03/20010324.htm#2  - for 2001
 # http://www.resmigazete.gov.tr/eskiler/2002/03/20020316.htm#2  - for 2002-2006
 # From Paul Eggert (2016-09-25):
@@ -3750,56 +3858,46 @@
 Rule	Turkey	1924	only	-	May	13	0:00	1:00	S
 Rule	Turkey	1924	1925	-	Oct	 1	0:00	0	-
 Rule	Turkey	1925	only	-	May	 1	0:00	1:00	S
-Rule	Turkey	1940	only	-	Jun	30	0:00	1:00	S
-Rule	Turkey	1940	only	-	Oct	 5	0:00	0	-
+Rule	Turkey	1940	only	-	Jul	 1	0:00	1:00	S
+Rule	Turkey	1940	only	-	Oct	 6	0:00	0	-
 Rule	Turkey	1940	only	-	Dec	 1	0:00	1:00	S
 Rule	Turkey	1941	only	-	Sep	21	0:00	0	-
 Rule	Turkey	1942	only	-	Apr	 1	0:00	1:00	S
-# Whitman omits the next two transition and gives 1945 Oct 1;
-# go with Shanks & Pottenger.
-Rule	Turkey	1942	only	-	Nov	 1	0:00	0	-
-Rule	Turkey	1945	only	-	Apr	 2	0:00	1:00	S
 Rule	Turkey	1945	only	-	Oct	 8	0:00	0	-
 Rule	Turkey	1946	only	-	Jun	 1	0:00	1:00	S
 Rule	Turkey	1946	only	-	Oct	 1	0:00	0	-
 Rule	Turkey	1947	1948	-	Apr	Sun>=16	0:00	1:00	S
-Rule	Turkey	1947	1950	-	Oct	Sun>=2	0:00	0	-
+Rule	Turkey	1947	1951	-	Oct	Sun>=2	0:00	0	-
 Rule	Turkey	1949	only	-	Apr	10	0:00	1:00	S
-Rule	Turkey	1950	only	-	Apr	19	0:00	1:00	S
+Rule	Turkey	1950	only	-	Apr	16	0:00	1:00	S
 Rule	Turkey	1951	only	-	Apr	22	0:00	1:00	S
-Rule	Turkey	1951	only	-	Oct	 8	0:00	0	-
+# DST for 15 months; unusual but we'll let it pass.
 Rule	Turkey	1962	only	-	Jul	15	0:00	1:00	S
-Rule	Turkey	1962	only	-	Oct	 8	0:00	0	-
+Rule	Turkey	1963	only	-	Oct	30	0:00	0	-
 Rule	Turkey	1964	only	-	May	15	0:00	1:00	S
 Rule	Turkey	1964	only	-	Oct	 1	0:00	0	-
-Rule	Turkey	1970	1972	-	May	Sun>=2	0:00	1:00	S
-Rule	Turkey	1970	1972	-	Oct	Sun>=2	0:00	0	-
 Rule	Turkey	1973	only	-	Jun	 3	1:00	1:00	S
-Rule	Turkey	1973	only	-	Nov	 4	3:00	0	-
+Rule	Turkey	1973	1976	-	Oct	Sun>=31	2:00	0	-
 Rule	Turkey	1974	only	-	Mar	31	2:00	1:00	S
-Rule	Turkey	1974	only	-	Nov	 3	5:00	0	-
-Rule	Turkey	1975	only	-	Mar	30	0:00	1:00	S
-Rule	Turkey	1975	1976	-	Oct	lastSun	0:00	0	-
-Rule	Turkey	1976	only	-	Jun	 1	0:00	1:00	S
-Rule	Turkey	1977	1978	-	Apr	Sun>=1	0:00	1:00	S
-Rule	Turkey	1977	only	-	Oct	16	0:00	0	-
-Rule	Turkey	1979	1980	-	Apr	Sun>=1	3:00	1:00	S
-Rule	Turkey	1979	1982	-	Oct	Mon>=11	0:00	0	-
-Rule	Turkey	1981	1982	-	Mar	lastSun	3:00	1:00	S
-Rule	Turkey	1983	only	-	Jul	31	0:00	1:00	S
-Rule	Turkey	1983	only	-	Oct	 2	0:00	0	-
-Rule	Turkey	1985	only	-	Apr	20	0:00	1:00	S
-Rule	Turkey	1985	only	-	Sep	28	0:00	0	-
+Rule	Turkey	1975	only	-	Mar	22	2:00	1:00	S
+Rule	Turkey	1976	only	-	Mar	21	2:00	1:00	S
+Rule	Turkey	1977	1978	-	Apr	Sun>=1	2:00	1:00	S
+Rule	Turkey	1977	1978	-	Oct	Sun>=15	2:00	0	-
+Rule	Turkey	1978	only	-	Jun	29	0:00	0	-
+Rule	Turkey	1983	only	-	Jul	31	2:00	1:00	S
+Rule	Turkey	1983	only	-	Oct	 2	2:00	0	-
+Rule	Turkey	1985	only	-	Apr	20	1:00s	1:00	S
+Rule	Turkey	1985	only	-	Sep	28	1:00s	0	-
 Rule	Turkey	1986	1993	-	Mar	lastSun	1:00s	1:00	S
 Rule	Turkey	1986	1995	-	Sep	lastSun	1:00s	0	-
 Rule	Turkey	1994	only	-	Mar	20	1:00s	1:00	S
 Rule	Turkey	1995	2006	-	Mar	lastSun	1:00s	1:00	S
 Rule	Turkey	1996	2006	-	Oct	lastSun	1:00s	0	-
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Istanbul	1:55:52 -	LMT	1880
 			1:56:56	-	IMT	1910 Oct # Istanbul Mean Time?
-			2:00	Turkey	EE%sT	1978 Oct 15
-			3:00	Turkey	+03/+04	1985 Apr 20
+			2:00	Turkey	EE%sT	1978 Jun 29
+			3:00	Turkey	+03/+04	1984 Nov  1  2:00
 			2:00	Turkey	EE%sT	2007
 			2:00	EU	EE%sT	2011 Mar 27  1:00u
 			2:00	-	EET	2011 Mar 28  1:00u
@@ -3892,16 +3990,8 @@
 # controversial, and some day "Kyiv" may become substantially more popular in
 # English; in the meantime, stick with the traditional English "Kiev" as that
 # means less disruption for our users.
-#
-# Anyway, none of the common English-language spellings (Kiev, Kyiv, Kieff,
-# Kijeff, Kijev, Kiyef, Kiyeff) do justice to the common pronunciation in
-# Ukrainian, namely [ˈkɪjiu̯] (IPA).  This pronunciation has nothing like an
-# English "v" or "f", and instead trails off with what an English-speaker
-# would call a demure "oo" sound, and it would would be better anglicized as
-# "Kuiyu".  Here's a sound file, if you would like to do as the Kuiyuvians do:
-# https://commons.wikimedia.org/wiki/File:Uk-Київ.ogg
-
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 # This represents most of Ukraine.  See above for the spelling of "Kiev".
 Zone Europe/Kiev	2:02:04 -	LMT	1880
 			2:02:04	-	KMT	1924 May  2 # Kiev Mean Time
--- a/make/sun/javazic/tzdata/factory	Wed Nov 20 06:36:47 2019 +0000
+++ b/make/sun/javazic/tzdata/factory	Thu Feb 06 01:43:16 2020 +0000
@@ -31,5 +31,5 @@
 # time zone abbreviation "-00", indicating that the actual time zone
 # is unknown.
 
-# Zone	NAME	GMTOFF	RULES	FORMAT
+# Zone	NAME	STDOFF	RULES	FORMAT
 Zone	Factory	0	-	-00
--- a/make/sun/javazic/tzdata/leapseconds	Wed Nov 20 06:36:47 2019 +0000
+++ b/make/sun/javazic/tzdata/leapseconds	Thu Feb 06 01:43:16 2020 +0000
@@ -26,36 +26,39 @@
 # This file is in the public domain.
 
 # This file is generated automatically from the data in the public-domain
-# leap-seconds.list file, which can be copied from
+# NIST format leap-seconds.list file, which can be copied from
 # <ftp://ftp.nist.gov/pub/time/leap-seconds.list>
-# or <ftp://ftp.boulder.nist.gov/pub/time/leap-seconds.list>
-# or <ftp://tycho.usno.navy.mil/pub/ntp/leap-seconds.list>.
+# or <ftp://ftp.boulder.nist.gov/pub/time/leap-seconds.list>.
 # For more about leap-seconds.list, please see
 # The NTP Timescale and Leap Seconds
 # <https://www.eecis.udel.edu/~mills/leap.html>.
 
-# The International Earth Rotation and Reference Systems Service
+# The rules for leap seconds are specified in Annex 1 (Time scales) of:
+# Standard-frequency and time-signal emissions.
+# International Telecommunication Union - Radiocommunication Sector
+# (ITU-R) Recommendation TF.460-6 (02/2002)
+# <https://www.itu.int/rec/R-REC-TF.460-6-200202-I/>.
+# The International Earth Rotation and Reference Systems Service (IERS)
 # periodically uses leap seconds to keep UTC to within 0.9 s of UT1
-# (which measures the true angular orientation of the earth in space)
+# (a proxy for Earth's angle in space as measured by astronomers)
 # and publishes leap second data in a copyrighted file
 # <https://hpiers.obspm.fr/iers/bul/bulc/Leap_Second.dat>.
 # See: Levine J. Coordinated Universal Time and the leap second.
 # URSI Radio Sci Bull. 2016;89(4):30-6. doi:10.23919/URSIRSB.2016.7909995
 # <https://ieeexplore.ieee.org/document/7909995>.
 
-# There were no leap seconds before 1972, because the official mechanism
-# accounting for the discrepancy between atomic time and the earth's rotation
-# did not exist.  The first ("1 Jan 1972") data line in leap-seconds.list
+# There were no leap seconds before 1972, as no official mechanism
+# accounted for the discrepancy between atomic time (TAI) and the earth's
+# rotation.  The first ("1 Jan 1972") data line in leap-seconds.list
 # does not denote a leap second; it denotes the start of the current definition
 # of UTC.
 
-# The correction (+ or -) is made at the given time, so lines
-# will typically look like:
-#	Leap	YEAR	MON	DAY	23:59:60	+	R/S
-# or
-#	Leap	YEAR	MON	DAY	23:59:59	-	R/S
-
-# If the leap second is Rolling (R) the given time is local time (unused here).
+# All leap-seconds are Stationary (S) at the given UTC time.
+# The correction (+ or -) is made at the given time, so in the unlikely
+# event of a negative leap second, a line would look like this:
+# Leap	YEAR	MON	DAY	23:59:59	-	S
+# Typical lines look like this:
+# Leap	YEAR	MON	DAY	23:59:60	+	S
 Leap	1972	Jun	30	23:59:60	+	S
 Leap	1972	Dec	31	23:59:60	+	S
 Leap	1973	Dec	31	23:59:60	+	S
@@ -85,8 +88,8 @@
 Leap	2016	Dec	31	23:59:60	+	S
 
 # POSIX timestamps for the data in this file:
-#updated 1467936000
-#expires 1577491200
+#updated 1467936000 (2016-07-08 00:00:00 UTC)
+#expires 1593302400 (2020-06-28 00:00:00 UTC)
 
-#	Updated through IERS Bulletin C57
-#	File expires on:  28 December 2019
+#	Updated through IERS Bulletin C58
+#	File expires on:  28 June 2020
--- a/make/sun/javazic/tzdata/northamerica	Wed Nov 20 06:36:47 2019 +0000
+++ b/make/sun/javazic/tzdata/northamerica	Thu Feb 06 01:43:16 2020 +0000
@@ -116,10 +116,33 @@
 # was the first nationwide legal time standard, and apparently
 # time was just called "Standard Time" or "Daylight Saving Time".
 
-# From Arthur David Olson:
-# US Daylight Saving Time ended on the last Sunday of *October* in 1974.
-# See, for example, the front page of the Saturday, 1974-10-26
-# and Sunday, 1974-10-27 editions of the Washington Post.
+# From Paul Eggert (2019-06-04):
+# Here is the legal basis for the US federal rules.
+# * Public Law 65-106 (1918-03-19) implemented standard and daylight saving
+#   time for the first time across the US, springing forward on March's last
+#   Sunday and falling back on October's last Sunday.
+#   https://www.loc.gov/law/help/statutes-at-large/65th-congress/session-2/c65s2ch24.pdf
+# * Public Law 66-40 (1919-08-20) repealed DST on October 1919's last Sunday.
+#   https://www.loc.gov/law/help/statutes-at-large/66th-congress/session-1/c66s1ch51.pdf
+# * Public Law 77-403 (1942-01-20) started wartime DST on 1942-02-09.
+#   https://www.loc.gov/law/help/statutes-at-large/77th-congress/session-2/c77s2ch7.pdf
+# * Public Law 79-187 (1945-09-25) ended wartime DST on 1945-09-30.
+#   https://www.loc.gov/law/help/statutes-at-large/79th-congress/session-1/c79s1ch388.pdf
+# * Public Law 89-387 (1966-04-13) reinstituted a national standard for DST,
+#   from April's last Sunday to October's last Sunday, effective 1967.
+#   https://www.govinfo.gov/content/pkg/STATUTE-80/pdf/STATUTE-80-Pg107.pdf
+# * Public Law 93-182 (1973-12-15) moved the 1974 spring-forward to 01-06.
+#   https://www.govinfo.gov/content/pkg/STATUTE-87/pdf/STATUTE-87-Pg707.pdf
+# * Public Law 93-434 (1974-10-05) moved the 1975 spring-forward to
+#   February's last Sunday.
+#   https://www.govinfo.gov/content/pkg/STATUTE-88/pdf/STATUTE-88-Pg1209.pdf
+# * Public Law 99-359 (1986-07-08) moved the spring-forward to April's first
+#   Sunday.
+#   https://www.govinfo.gov/content/pkg/STATUTE-100/pdf/STATUTE-100-Pg764.pdf
+# * Public Law 109-58 (2005-08-08), effective 2007, moved the spring-forward
+#   to March's second Sunday and the fall-back to November's first Sunday.
+#   https://www.govinfo.gov/content/pkg/PLAW-109publ58/pdf/PLAW-109publ58.pdf
+# All transitions are at 02:00 local time.
 
 # From Arthur David Olson:
 # Before the Uniform Time Act of 1966 took effect in 1967, observance of
@@ -175,11 +198,11 @@
 Rule	US	1918	1919	-	Oct	lastSun	2:00	0	S
 Rule	US	1942	only	-	Feb	9	2:00	1:00	W # War
 Rule	US	1945	only	-	Aug	14	23:00u	1:00	P # Peace
-Rule	US	1945	only	-	Sep	lastSun	2:00	0	S
+Rule	US	1945	only	-	Sep	30	2:00	0	S
 Rule	US	1967	2006	-	Oct	lastSun	2:00	0	S
 Rule	US	1967	1973	-	Apr	lastSun	2:00	1:00	D
 Rule	US	1974	only	-	Jan	6	2:00	1:00	D
-Rule	US	1975	only	-	Feb	23	2:00	1:00	D
+Rule	US	1975	only	-	Feb	lastSun	2:00	1:00	D
 Rule	US	1976	1986	-	Apr	lastSun	2:00	1:00	D
 Rule	US	1987	2006	-	Apr	Sun>=1	2:00	1:00	D
 Rule	US	2007	max	-	Mar	Sun>=8	2:00	1:00	D
@@ -196,7 +219,7 @@
 # increase the chances that they'll actually get compiled and to
 # avoid the need to duplicate the US rules in another file.
 
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	EST		 -5:00	-	EST
 Zone	MST		 -7:00	-	MST
 Zone	HST		-10:00	-	HST
@@ -353,7 +376,7 @@
 Rule	NYC	1921	1966	-	Apr	lastSun	2:00	1:00	D
 Rule	NYC	1921	1954	-	Sep	lastSun	2:00	0	S
 Rule	NYC	1955	1966	-	Oct	lastSun	2:00	0	S
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone America/New_York	-4:56:02 -	LMT	1883 Nov 18 12:03:58
 			-5:00	US	E%sT	1920
 			-5:00	NYC	E%sT	1942
@@ -406,6 +429,31 @@
 # From Paul Eggert (2015-12-25):
 # Assume this practice predates 1970, so Fort Pierre can use America/Chicago.
 
+# From Paul Eggert (2015-04-06):
+# In 1950s Nashville a public clock had dueling faces, one for conservatives
+# and the other for liberals; the two sides didn't agree about the time of day.
+# I haven't found a photo of this clock, nor have I tracked down the TIME
+# magazine report cited below, but here's the story as told by the late
+# American journalist John Seigenthaler, who was there:
+#
+# "The two [newspaper] owners held strongly contrasting political and
+# ideological views.  Evans was a New South liberal, Stahlman an Old South
+# conservative, and their two papers frequently clashed editorially, often on
+# the same day....  In the 1950s as the state legislature was grappling with
+# the question of whether to approve daylight saving time for the entire state,
+# TIME magazine reported:
+#
+# "'The Nashville Banner and The Nashville Tennessean rarely agree on anything
+# but the time of day - and last week they couldn't agree on that.'
+#
+# "It was all too true. The clock on the front of the building had two faces -
+# The Tennessean side of the building facing west, the other, east.  When it
+# was high noon Banner time, it was 11 a.m. Tennessean time."
+#
+# Seigenthaler J. For 100 years, Tennessean had it covered.
+# The Tennessean 2007-05-11, republished 2015-04-06.
+# https://www.tennessean.com/story/insider/extras/2015/04/06/archives-seigenthaler-for-100-years-the-tennessean-had-it-covered/25348545/
+
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER
 Rule	Chicago	1920	only	-	Jun	13	2:00	1:00	D
 Rule	Chicago	1920	1921	-	Oct	lastSun	2:00	0	S
@@ -413,7 +461,7 @@
 Rule	Chicago	1922	1966	-	Apr	lastSun	2:00	1:00	D
 Rule	Chicago	1922	1954	-	Sep	lastSun	2:00	0	S
 Rule	Chicago	1955	1966	-	Oct	lastSun	2:00	0	S
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone America/Chicago	-5:50:36 -	LMT	1883 Nov 18 12:09:24
 			-6:00	US	C%sT	1920
 			-6:00	Chicago	C%sT	1936 Mar  1  2:00
@@ -481,7 +529,7 @@
 Rule	Denver	1921	only	-	May	22	2:00	0	S
 Rule	Denver	1965	1966	-	Apr	lastSun	2:00	1:00	D
 Rule	Denver	1965	1966	-	Oct	lastSun	2:00	0	S
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone America/Denver	-6:59:56 -	LMT	1883 Nov 18 12:00:04
 			-7:00	US	M%sT	1920
 			-7:00	Denver	M%sT	1942
@@ -534,7 +582,7 @@
 Rule	CA	1950	1966	-	Apr	lastSun	1:00	1:00	D
 Rule	CA	1950	1961	-	Sep	lastSun	2:00	0	S
 Rule	CA	1962	1966	-	Oct	lastSun	2:00	0	S
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone America/Los_Angeles -7:52:58 -	LMT	1883 Nov 18 12:07:02
 			-8:00	US	P%sT	1946
 			-8:00	CA	P%sT	1967
@@ -642,7 +690,7 @@
 # So they won't be waiting for Alaska to join them on 2019-03-10, but will
 # rather change their clocks twice in seven weeks.
 
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone America/Juneau	 15:02:19 -	LMT	1867 Oct 19 15:33:32
 			 -8:57:41 -	LMT	1900 Aug 20 12:00
 			 -8:00	-	PST	1942
@@ -762,7 +810,7 @@
 # Note that 1933-05-21 was a Sunday.
 # We're left to guess the time of day when Act 163 was approved; guess noon.
 
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone Pacific/Honolulu	-10:31:26 -	LMT	1896 Jan 13 12:00
 			-10:30	-	HST	1933 Apr 30  2:00
 			-10:30	1:00	HDT	1933 May 21 12:00
@@ -792,7 +840,7 @@
 # Shanks says the 1944 experiment came to an end on 1944-03-17.
 # Go with the Arizona State Library instead.
 
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone America/Phoenix	-7:28:18 -	LMT	1883 Nov 18 11:31:42
 			-7:00	US	M%sT	1944 Jan  1  0:01
 			-7:00	-	MST	1944 Apr  1  0:01
@@ -818,7 +866,7 @@
 # quarter of Idaho county) and eastern Oregon (most of Malheur County)
 # switched four weeks late in 1974.
 #
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone America/Boise	-7:44:49 -	LMT	1883 Nov 18 12:15:11
 			-8:00	US	P%sT	1923 May 13  2:00
 			-7:00	US	M%sT	1974
@@ -890,7 +938,7 @@
 Rule Indianapolis 1941	only	-	Jun	22	2:00	1:00	D
 Rule Indianapolis 1941	1954	-	Sep	lastSun	2:00	0	S
 Rule Indianapolis 1946	1954	-	Apr	lastSun	2:00	1:00	D
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone America/Indiana/Indianapolis -5:44:38 - LMT	1883 Nov 18 12:15:22
 			-6:00	US	C%sT	1920
 			-6:00 Indianapolis C%sT	1942
@@ -910,7 +958,7 @@
 Rule	Marengo	1951	only	-	Sep	lastSun	2:00	0	S
 Rule	Marengo	1954	1960	-	Apr	lastSun	2:00	1:00	D
 Rule	Marengo	1954	1960	-	Sep	lastSun	2:00	0	S
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone America/Indiana/Marengo -5:45:23 -	LMT	1883 Nov 18 12:14:37
 			-6:00	US	C%sT	1951
 			-6:00	Marengo	C%sT	1961 Apr 30  2:00
@@ -934,7 +982,7 @@
 Rule Vincennes	1960	only	-	Oct	lastSun	2:00	0	S
 Rule Vincennes	1961	only	-	Sep	lastSun	2:00	0	S
 Rule Vincennes	1962	1963	-	Oct	lastSun	2:00	0	S
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone America/Indiana/Vincennes -5:50:07 - LMT	1883 Nov 18 12:09:53
 			-6:00	US	C%sT	1946
 			-6:00 Vincennes	C%sT	1964 Apr 26  2:00
@@ -945,21 +993,21 @@
 			-5:00	US	E%sT
 #
 # Perry County, Indiana, switched from eastern to central time in April 2006.
+# From Alois Triendl (2019-07-09):
+# The Indianapolis News, Friday 27 October 1967 states that Perry County
+# returned to CST.  It went again to EST on 27 April 1969, as documented by the
+# Indianapolis star of Saturday 26 April.
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER
-Rule Perry	1946	only	-	Apr	lastSun	2:00	1:00	D
-Rule Perry	1946	only	-	Sep	lastSun	2:00	0	S
-Rule Perry	1953	1954	-	Apr	lastSun	2:00	1:00	D
-Rule Perry	1953	1959	-	Sep	lastSun	2:00	0	S
 Rule Perry	1955	only	-	May	 1	0:00	1:00	D
+Rule Perry	1955	1960	-	Sep	lastSun	2:00	0	S
 Rule Perry	1956	1963	-	Apr	lastSun	2:00	1:00	D
-Rule Perry	1960	only	-	Oct	lastSun	2:00	0	S
-Rule Perry	1961	only	-	Sep	lastSun	2:00	0	S
-Rule Perry	1962	1963	-	Oct	lastSun	2:00	0	S
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+Rule Perry	1961	1963	-	Oct	lastSun	2:00	0	S
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone America/Indiana/Tell_City -5:47:03 - LMT	1883 Nov 18 12:12:57
 			-6:00	US	C%sT	1946
 			-6:00 Perry	C%sT	1964 Apr 26  2:00
-			-5:00	-	EST	1969
+			-5:00	-	EST	1967 Oct 29  2:00
+			-6:00	US	C%sT	1969 Apr 27  2:00
 			-5:00	US	E%sT	1971
 			-5:00	-	EST	2006 Apr  2  2:00
 			-6:00	US	C%sT
@@ -971,7 +1019,7 @@
 Rule	Pike	1955	1960	-	Sep	lastSun	2:00	0	S
 Rule	Pike	1956	1964	-	Apr	lastSun	2:00	1:00	D
 Rule	Pike	1961	1964	-	Oct	lastSun	2:00	0	S
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone America/Indiana/Petersburg -5:49:07 - LMT	1883 Nov 18 12:10:53
 			-6:00	US	C%sT	1955
 			-6:00	Pike	C%sT	1965 Apr 25  2:00
@@ -993,7 +1041,7 @@
 Rule	Starke	1955	1956	-	Oct	lastSun	2:00	0	S
 Rule	Starke	1957	1958	-	Sep	lastSun	2:00	0	S
 Rule	Starke	1959	1961	-	Oct	lastSun	2:00	0	S
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone America/Indiana/Knox -5:46:30 -	LMT	1883 Nov 18 12:13:30
 			-6:00	US	C%sT	1947
 			-6:00	Starke	C%sT	1962 Apr 29  2:00
@@ -1009,7 +1057,7 @@
 Rule	Pulaski	1946	1954	-	Sep	lastSun	2:00	0	S
 Rule	Pulaski	1955	1956	-	Oct	lastSun	2:00	0	S
 Rule	Pulaski	1957	1960	-	Sep	lastSun	2:00	0	S
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone America/Indiana/Winamac -5:46:25 - LMT	1883 Nov 18 12:13:35
 			-6:00	US	C%sT	1946
 			-6:00	Pulaski	C%sT	1961 Apr 30  2:00
@@ -1020,7 +1068,7 @@
 			-5:00	US	E%sT
 #
 # Switzerland County, Indiana, did not observe DST from 1973 through 2005.
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone America/Indiana/Vevay -5:40:16 -	LMT	1883 Nov 18 12:19:44
 			-6:00	US	C%sT	1954 Apr 25  2:00
 			-5:00	-	EST	1969
@@ -1035,17 +1083,28 @@
 # clear how this matched civil time in Louisville, so for now continue
 # to assume Louisville switched at noon new local time, like New York.
 #
+# From Michael Deckers (2019-08-06):
+# From the contemporary source given by Alois Treindl,
+# the switch in Louisville on 1946-04-28 was on 00:01
+# From Paul Eggert (2019-08-26):
+# That source was the Louisville Courier-Journal, 1946-04-27, p 4.
+# Shanks gives 02:00 for all 20th-century transition times in Louisville.
+# Evidently this is wrong for spring 1946.  Although also likely wrong
+# for other dates, we have no data.
+#
 # Part of Kentucky left its clocks alone in 1974.
 # This also includes Clark, Floyd, and Harrison counties in Indiana.
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER
 Rule Louisville	1921	only	-	May	1	2:00	1:00	D
 Rule Louisville	1921	only	-	Sep	1	2:00	0	S
-Rule Louisville	1941	1961	-	Apr	lastSun	2:00	1:00	D
+Rule Louisville	1941	only	-	Apr	lastSun	2:00	1:00	D
 Rule Louisville	1941	only	-	Sep	lastSun	2:00	0	S
+Rule Louisville	1946	only	-	Apr	lastSun	0:01	1:00	D
 Rule Louisville	1946	only	-	Jun	2	2:00	0	S
+Rule Louisville	1950	1961	-	Apr	lastSun	2:00	1:00	D
 Rule Louisville	1950	1955	-	Sep	lastSun	2:00	0	S
-Rule Louisville	1956	1960	-	Oct	lastSun	2:00	0	S
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+Rule Louisville	1956	1961	-	Oct	lastSun	2:00	0	S
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone America/Kentucky/Louisville -5:43:02 -	LMT	1883 Nov 18 12:16:58
 			-6:00	US	C%sT	1921
 			-6:00 Louisville C%sT	1942
@@ -1134,29 +1193,32 @@
 # one hour in 1914."  This change is not in Shanks.  We have no more
 # info, so omit this for now.
 #
-# From Paul Eggert (2017-07-26):
-# Although Shanks says Detroit observed DST in 1967 from 06-14 00:01
-# until 10-29 00:01, I now see multiple reports that this is incorrect.
-# For example, according to a 50-year anniversary report about the 1967
-# Detroit riots and a major-league doubleheader on 1967-07-23, "By the time
-# the last fly ball of the doubleheader settled into the glove of leftfielder
-# Lenny Green, it was after 7 p.m.  Detroit did not observe daylight saving
-# time, so light was already starting to fail.  Twilight was made even deeper
-# by billowing columns of smoke that ascended in an unbroken wall north of the
-# ballpark."  See: Dow B. Detroit '67: As violence unfolded, Tigers played two
-# at home vs. Yankees. Detroit Free Press 2017-07-23.
-# https://www.freep.com/story/sports/mlb/tigers/2017/07/23/detroit-tigers-1967-riot-new-york-yankees/499951001/
+# From Paul Eggert (2019-07-06):
+# Due to a complicated set of legal maneuvers, in 1967 Michigan did
+# not start daylight saving time when the rest of the US did.
+# Instead, it began DST on Jun 14 at 00:01.  This was big news:
+# the Detroit Free Press reported it at the top of Page 1 on
+# 1967-06-14, in an article "State Adjusting to Switch to Fast Time"
+# by Gary Blonston, above an article about Thurgood Marshall's
+# confirmation to the US Supreme Court.  Although Shanks says Detroit
+# observed DST until 1967-10-29 00:01, that time of day seems to be
+# incorrect, as the Free Press later said DST ended in Michigan at the
+# same time as the rest of the US.  Also, although Shanks reports no DST in
+# Detroit in 1968, it did observe DST that year; in the November 1968
+# election Michigan voters narrowly repealed DST, effective 1969.
 #
 # Most of Michigan observed DST from 1973 on, but was a bit late in 1975.
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER
 Rule	Detroit	1948	only	-	Apr	lastSun	2:00	1:00	D
 Rule	Detroit	1948	only	-	Sep	lastSun	2:00	0	S
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone America/Detroit	-5:32:11 -	LMT	1905
 			-6:00	-	CST	1915 May 15  2:00
 			-5:00	-	EST	1942
 			-5:00	US	E%sT	1946
-			-5:00	Detroit	E%sT	1973
+			-5:00	Detroit	E%sT	1967 Jun 14  0:01
+			-5:00	US	E%sT	1969
+			-5:00	-	EST	1973
 			-5:00	US	E%sT	1975
 			-5:00	-	EST	1975 Apr 27  2:00
 			-5:00	US	E%sT
@@ -1168,7 +1230,7 @@
 Rule Menominee	1946	only	-	Sep	lastSun	2:00	0	S
 Rule Menominee	1966	only	-	Apr	lastSun	2:00	1:00	D
 Rule Menominee	1966	only	-	Oct	lastSun	2:00	0	S
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone America/Menominee	-5:50:27 -	LMT	1885 Sep 18 12:00
 			-6:00	US	C%sT	1946
 			-6:00 Menominee	C%sT	1969 Apr 27  2:00
@@ -1205,6 +1267,12 @@
 #
 # Other sources occasionally used include:
 #
+#	Milne J. Civil time. Geogr J. 1899 Feb;13(2):173-94
+#	<https://www.jstor.org/stable/1774359>.
+#
+#	Pearce C. The Great Daylight Saving Time Controversy.
+#	Australian Ebook Publisher. 2017. ISBN 978-1-925516-96-8.
+#
 #	Edward W. Whitman, World Time Differences,
 #	Whitman Publishing Co, 2 Niagara Av, Ealing, London (undated),
 #	which I found in the UCLA library.
@@ -1213,9 +1281,6 @@
 #	<http://cs.ucla.edu/~eggert/The-Waste-of-Daylight-19th.pdf>
 #	[PDF] (1914-03)
 #
-#	Milne J. Civil time. Geogr J. 1899 Feb;13(2):173-94
-#	<https://www.jstor.org/stable/1774359>.
-#
 # See the 'europe' file for Greenland.
 
 # Canada
@@ -1402,7 +1467,7 @@
 Rule	StJohns	2007	2010	-	Nov	Sun>=1	0:01	0	S
 #
 # St John's has an apostrophe, but Posix file names can't have apostrophes.
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone America/St_Johns	-3:30:52 -	LMT	1884
 			-3:30:52 StJohns N%sT	1918
 			-3:30:52 Canada	N%sT	1919
@@ -1415,7 +1480,7 @@
 # most of east Labrador
 
 # The name 'Happy Valley-Goose Bay' is too long; use 'Goose Bay'.
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone America/Goose_Bay	-4:01:40 -	LMT	1884 # Happy Valley-Goose Bay
 			-3:30:52 -	NST	1918
 			-3:30:52 Canada N%sT	1919
@@ -1489,7 +1554,7 @@
 Rule	Halifax	1956	1959	-	Sep	lastSun	2:00	0	S
 Rule	Halifax	1962	1973	-	Apr	lastSun	2:00	1:00	D
 Rule	Halifax	1962	1973	-	Oct	lastSun	2:00	0	S
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone America/Halifax	-4:14:24 -	LMT	1902 Jun 15
 			-4:00	Halifax	A%sT	1918
 			-4:00	Canada	A%sT	1919
@@ -1527,7 +1592,7 @@
 Rule	Moncton	1957	1972	-	Oct	lastSun	2:00	0	S
 Rule	Moncton	1993	2006	-	Apr	Sun>=1	0:01	1:00	D
 Rule	Moncton	1993	2006	-	Oct	lastSun	0:01	0	S
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone America/Moncton	-4:19:08 -	LMT	1883 Dec  9
 			-5:00	-	EST	1902 Jun 15
 			-4:00	Canada	A%sT	1933
@@ -1556,7 +1621,7 @@
 # For lack of better info, guess this practice began around 1970, contra to
 # Shanks & Pottenger who have this region observing AST/ADT.
 
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone America/Blanc-Sablon -3:48:28 -	LMT	1884
 			-4:00	Canada	A%sT	1970
 			-4:00	-	AST
@@ -1724,19 +1789,10 @@
 # was meant.
 Rule	Toronto	1922	1926	-	Sep	Sun>=15	2:00	0	S
 Rule	Toronto	1924	1927	-	May	Sun>=1	2:00	1:00	D
-# The 1927-to-1939 rules can be expressed more simply as
-# Rule	Toronto	1927	1937	-	Sep	Sun>=25	2:00	0	S
-# Rule	Toronto	1928	1937	-	Apr	Sun>=25	2:00	1:00	D
-# Rule	Toronto	1938	1940	-	Apr	lastSun	2:00	1:00	D
-# Rule	Toronto	1938	1939	-	Sep	lastSun	2:00	0	S
-# The rules below avoid use of Sun>=25
-# (which pre-2004 versions of zic cannot handle).
-Rule	Toronto	1927	1932	-	Sep	lastSun	2:00	0	S
-Rule	Toronto	1928	1931	-	Apr	lastSun	2:00	1:00	D
-Rule	Toronto	1932	only	-	May	1	2:00	1:00	D
-Rule	Toronto	1933	1940	-	Apr	lastSun	2:00	1:00	D
-Rule	Toronto	1933	only	-	Oct	1	2:00	0	S
-Rule	Toronto	1934	1939	-	Sep	lastSun	2:00	0	S
+Rule	Toronto	1927	1937	-	Sep	Sun>=25	2:00	0	S
+Rule	Toronto	1928	1937	-	Apr	Sun>=25	2:00	1:00	D
+Rule	Toronto	1938	1940	-	Apr	lastSun	2:00	1:00	D
+Rule	Toronto	1938	1939	-	Sep	lastSun	2:00	0	S
 Rule	Toronto	1945	1946	-	Sep	lastSun	2:00	0	S
 Rule	Toronto	1946	only	-	Apr	lastSun	2:00	1:00	D
 Rule	Toronto	1947	1949	-	Apr	lastSun	0:00	1:00	D
@@ -1769,7 +1825,7 @@
 # War,... [t]he cities agreed to implement DST during the summer
 # months for the remainder of the war years.
 
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone America/Toronto	-5:17:32 -	LMT	1895
 			-5:00	Canada	E%sT	1919
 			-5:00	Toronto	E%sT	1942 Feb  9  2:00s
@@ -1844,7 +1900,7 @@
 Rule	Winn	1966	1986	-	Apr	lastSun	2:00s	1:00	D
 Rule	Winn	1966	2005	-	Oct	lastSun	2:00s	0	S
 Rule	Winn	1987	2005	-	Apr	Sun>=1	2:00s	1:00	D
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone America/Winnipeg	-6:28:36 -	LMT	1887 Jul 16
 			-6:00	Winn	C%sT	2006
 			-6:00	Canada	C%sT
@@ -1866,6 +1922,12 @@
 # Willett (1914-03) notes that DST "has been in operation ... in the
 # City of Moose Jaw, Saskatchewan, for one year."
 
+# From Paul Eggert (2019-07-25):
+# Pearce's book says Regina observed DST in 1914-1917.  No dates and times,
+# unfortunately.  It also says that in 1914 Saskatoon observed DST
+# from 1 June to 6 July, and that DST was also tried out in Davidson,
+# Melfort, and Prince Albert.
+
 # From Paul Eggert (2006-03-22):
 # Shanks & Pottenger say that since 1970 this region has mostly been as Regina.
 # Some western towns (e.g. Swift Current) switched from MST/MDT to CST in 1972.
@@ -1928,7 +1990,7 @@
 Rule	Swift	1959	1961	-	Apr	lastSun	2:00	1:00	D
 Rule	Swift	1959	only	-	Oct	lastSun	2:00	0	S
 Rule	Swift	1960	1961	-	Sep	lastSun	2:00	0	S
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone America/Regina	-6:58:36 -	LMT	1905 Sep
 			-7:00	Regina	M%sT	1960 Apr lastSun  2:00
 			-6:00	-	CST
@@ -1941,6 +2003,19 @@
 
 # Alberta
 
+# From Alois Triendl (2019-07-19):
+# There was no DST in Alberta in 1967... Calgary Herald, 29 April 1967.
+# 1969, no DST, from Edmonton Journal 18 April 1969
+#
+# From Paul Eggert (2019-07-25):
+# Pearce's book says that Alberta's 1948 Daylight Saving Act required
+# Mountain Standard Time without DST, and that "anyone who broke that law
+# could be fined up to $25 and costs".  There seems to be no record of
+# anybody paying the fine.  The law was not changed until an August 1971
+# plebiscite reinstituted DST in 1972.  This story is also mentioned in:
+# Boyer JP. Forcing Choice: The Risky Reward of Referendums. Dundum. 2017.
+# ISBN 978-1459739123.
+
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule	Edm	1918	1919	-	Apr	Sun>=8	2:00	1:00	D
 Rule	Edm	1918	only	-	Oct	27	2:00	0	S
@@ -1953,13 +2028,9 @@
 Rule	Edm	1945	only	-	Sep	lastSun	2:00	0	S
 Rule	Edm	1947	only	-	Apr	lastSun	2:00	1:00	D
 Rule	Edm	1947	only	-	Sep	lastSun	2:00	0	S
-Rule	Edm	1967	only	-	Apr	lastSun	2:00	1:00	D
-Rule	Edm	1967	only	-	Oct	lastSun	2:00	0	S
-Rule	Edm	1969	only	-	Apr	lastSun	2:00	1:00	D
-Rule	Edm	1969	only	-	Oct	lastSun	2:00	0	S
 Rule	Edm	1972	1986	-	Apr	lastSun	2:00	1:00	D
 Rule	Edm	1972	2006	-	Oct	lastSun	2:00	0	S
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone America/Edmonton	-7:33:52 -	LMT	1906 Sep
 			-7:00	Edm	M%sT	1987
 			-7:00	Canada	M%sT
@@ -2039,8 +2110,20 @@
 # been on MST (-0700) like Dawson Creek since it advanced its clocks on
 # 2015-03-08.
 #
-# From Paul Eggert (2015-09-23):
+# From Paul Eggert (2019-07-25):
 # Shanks says Fort Nelson did not observe DST in 1946, unlike Vancouver.
+# Alois Triendl confirmed this on 07-22, citing the 1946-04-27 Vancouver Daily
+# Province.  He also cited the 1946-09-28 Victoria Daily Times, which said
+# that Vancouver, Victoria, etc. "change at midnight Saturday"; for now,
+# guess they meant 02:00 Sunday since 02:00 was common practice in Vancouver.
+#
+# Early Vancouver, Volume Four, by Major J.S. Matthews, V.D., 2011 edition
+# says that a 1922 plebiscite adopted DST, but a 1923 plebiscite rejected it.
+# http://former.vancouver.ca/ctyclerk/archives/digitized/EarlyVan/SearchEarlyVan/Vol4pdf/MatthewsEarlyVancouverVol4_DaylightSavings.pdf
+# A catalog entry for a newspaper clipping seems to indicate that Vancouver
+# observed DST in 1941 from 07-07 through 09-27; see
+# https://searcharchives.vancouver.ca/daylight-saving-1918-starts-again-july-7-1941-start-d-s-sept-27-end-of-d-s-1941
+# We have no further details, so omit them for now.
 
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule	Vanc	1918	only	-	Apr	14	2:00	1:00	D
@@ -2049,10 +2132,10 @@
 Rule	Vanc	1945	only	-	Aug	14	23:00u	1:00	P # Peace
 Rule	Vanc	1945	only	-	Sep	30	2:00	0	S
 Rule	Vanc	1946	1986	-	Apr	lastSun	2:00	1:00	D
-Rule	Vanc	1946	only	-	Oct	13	2:00	0	S
+Rule	Vanc	1946	only	-	Sep	29	2:00	0	S
 Rule	Vanc	1947	1961	-	Sep	lastSun	2:00	0	S
 Rule	Vanc	1962	2006	-	Oct	lastSun	2:00	0	S
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone America/Vancouver	-8:12:28 -	LMT	1884
 			-8:00	Vanc	P%sT	1987
 			-8:00	Canada	P%sT
@@ -2123,7 +2206,7 @@
 #     varying the manner of reckoning standard time.
 #
 # * Yukon Territory Commissioner's Order 1966-20 Interpretation Ordinance
-#   http://? - no online source found
+#   [no online source found]
 #
 # * Standard Time and Time Zones in Canada; Thomson, Malcolm M.; JRASC,
 #   Vol. 64, pp.129-162; June 1970; SAO/NASA Astrophysics Data System (ADS)
@@ -2156,7 +2239,7 @@
 #     to say eight hours behind Greenwich Time.
 #
 # * O.I.C. 1980/02 INTERPRETATION ACT
-#   http://? - no online source found
+#   [no online source found]
 #
 # * Yukon Daylight Saving Time, YOIC 1987/56
 #   https://www.canlii.org/en/yk/laws/regu/yoic-1987-56/latest/yoic-1987-56.html
@@ -2372,7 +2455,7 @@
 Rule	NT_YK	1980	1986	-	Apr	lastSun	2:00	1:00	D
 Rule	NT_YK	1980	2006	-	Oct	lastSun	2:00	0	S
 Rule	NT_YK	1987	2006	-	Apr	Sun>=1	2:00	1:00	D
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 # aka Panniqtuuq
 Zone America/Pangnirtung 0	-	-00	1921 # trading post est.
 			-4:00	NT_YK	A%sT	1995 Apr Sun>=1  2:00
@@ -2519,7 +2602,7 @@
 
 # From Paul Eggert (2001-03-03):
 #
-# http://www.latimes.com/news/nation/20010303/t000018766.html
+# https://www.latimes.com/archives/la-xpm-2001-mar-03-mn-32561-story.html
 # James F. Smith writes in today's LA Times
 # * Sonora will continue to observe standard time.
 # * Last week Mexico City's mayor Andrés Manuel López Obrador decreed that
@@ -2646,7 +2729,7 @@
 Rule	Mexico	2001	only	-	Sep	lastSun	2:00	0	S
 Rule	Mexico	2002	max	-	Apr	Sun>=1	2:00	1:00	D
 Rule	Mexico	2002	max	-	Oct	lastSun	2:00	0	S
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 # Quintana Roo; represented by Cancún
 Zone America/Cancun	-5:47:04 -	LMT	1922 Jan  1  0:12:56
 			-6:00	-	CST	1981 Dec 23
@@ -2839,7 +2922,7 @@
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule	Bahamas	1964	1975	-	Oct	lastSun	2:00	0	S
 Rule	Bahamas	1964	1975	-	Apr	lastSun	2:00	1:00	D
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	America/Nassau	-5:09:30 -	LMT	1912 Mar 2
 			-5:00	Bahamas	E%sT	1976
 			-5:00	US	E%sT
@@ -2854,7 +2937,7 @@
 Rule	Barb	1978	1980	-	Apr	Sun>=15	2:00	1:00	D
 Rule	Barb	1979	only	-	Sep	30	2:00	0	S
 Rule	Barb	1980	only	-	Sep	25	2:00	0	S
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone America/Barbados	-3:58:29 -	LMT	1924 # Bridgetown
 			-3:58:29 -	BMT	1932 # Bridgetown Mean Time
 			-4:00	Barb	A%sT
@@ -2868,7 +2951,7 @@
 Rule	Belize	1974	only	-	Feb	 9	0:00	0	CST
 Rule	Belize	1982	only	-	Dec	18	0:00	1:00	CDT
 Rule	Belize	1983	only	-	Feb	12	0:00	0	CST
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	America/Belize	-5:52:48 -	LMT	1912 Apr
 			-6:00	Belize	%s
 
@@ -2885,7 +2968,7 @@
 # Friday, the same thing will happen in Bermuda.
 # http://www.theroyalgazette.com/apps/pbcs.dll/article?AID=/20060529/NEWS/105290135
 
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone Atlantic/Bermuda	-4:19:18 -	LMT	1930 Jan  1  2:00 # Hamilton
 			-4:00	-	AST	1974 Apr 28  2:00
 			-4:00	Canada	A%sT	1976
@@ -2907,7 +2990,7 @@
 Rule	CR	1991	only	-	Jul	 1	0:00	0	S
 Rule	CR	1992	only	-	Mar	15	0:00	0	S
 # There are too many San Josés elsewhere, so we'll use 'Costa Rica'.
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone America/Costa_Rica	-5:36:13 -	LMT	1890        # San José
 			-5:36:13 -	SJMT	1921 Jan 15 # San José Mean Time
 			-6:00	CR	C%sT
@@ -3113,7 +3196,7 @@
 Rule	Cuba	2012	max	-	Nov	Sun>=1	0:00s	0	S
 Rule	Cuba	2013	max	-	Mar	Sun>=8	0:00s	1:00	D
 
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	America/Havana	-5:29:28 -	LMT	1890
 			-5:29:36 -	HMT	1925 Jul 19 12:00 # Havana MT
 			-5:00	Cuba	C%sT
@@ -3148,7 +3231,7 @@
 Rule	DR	1970	only	-	Feb	21	0:00	0	EST
 Rule	DR	1971	only	-	Jan	20	0:00	0	EST
 Rule	DR	1972	1974	-	Jan	21	0:00	0	EST
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone America/Santo_Domingo -4:39:36 -	LMT	1890
 			-4:40	-	SDMT	1933 Apr  1 12:00 # S. Dom. MT
 			-5:00	DR	%s	1974 Oct 27
@@ -3163,7 +3246,7 @@
 Rule	Salv	1987	1988	-	Sep	lastSun	0:00	0	S
 # There are too many San Salvadors elsewhere, so use America/El_Salvador
 # instead of America/San_Salvador.
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone America/El_Salvador -5:56:48 -	LMT	1921 # San Salvador
 			-6:00	Salv	C%sT
 
@@ -3196,7 +3279,7 @@
 Rule	Guat	1991	only	-	Sep	 7	0:00	0	S
 Rule	Guat	2006	only	-	Apr	30	0:00	1:00	D
 Rule	Guat	2006	only	-	Oct	 1	0:00	0	S
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone America/Guatemala	-6:02:04 -	LMT	1918 Oct 5
 			-6:00	Guat	C%sT
 
@@ -3282,7 +3365,7 @@
 Rule	Haiti	2012	2015	-	Nov	Sun>=1	2:00	0	S
 Rule	Haiti	2017	max	-	Mar	Sun>=8	2:00	1:00	D
 Rule	Haiti	2017	max	-	Nov	Sun>=1	2:00	0	S
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone America/Port-au-Prince -4:49:20 -	LMT	1890
 			-4:49	-	PPMT	1917 Jan 24 12:00 # P-a-P MT
 			-5:00	Haiti	E%sT
@@ -3321,7 +3404,7 @@
 Rule	Hond	1987	1988	-	Sep	lastSun	0:00	0	S
 Rule	Hond	2006	only	-	May	Sun>=1	0:00	1:00	D
 Rule	Hond	2006	only	-	Aug	Mon>=1	0:00	0	S
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone America/Tegucigalpa -5:48:52 -	LMT	1921 Apr
 			-6:00	Hond	C%sT
 #
@@ -3342,7 +3425,7 @@
 # Neita L. The politician in all of us. Jamaica Observer 2014-09-20
 # http://www.jamaicaobserver.com/columns/The-politician-in-all-of-us_17573647
 #
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	America/Jamaica	-5:07:10 -	LMT	1890        # Kingston
 			-5:07:10 -	KMT	1912 Feb    # Kingston Mean Time
 			-5:00	-	EST	1974
@@ -3350,7 +3433,7 @@
 			-5:00	-	EST
 
 # Martinique
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone America/Martinique	-4:04:20 -      LMT	1890        # Fort-de-France
 			-4:04:20 -	FFMT	1911 May    # Fort-de-France MT
 			-4:00	-	AST	1980 Apr  6
@@ -3414,7 +3497,7 @@
 Rule	Nic	2005	only	-	Oct	Sun>=1	0:00	0	S
 Rule	Nic	2006	only	-	Apr	30	2:00	1:00	D
 Rule	Nic	2006	only	-	Oct	Sun>=1	1:00	0	S
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	America/Managua	-5:45:08 -	LMT	1890
 			-5:45:12 -	MMT	1934 Jun 23 # Managua Mean Time?
 			-6:00	-	CST	1973 May
@@ -3426,7 +3509,7 @@
 			-6:00	Nic	C%sT
 
 # Panama
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	America/Panama	-5:18:08 -	LMT	1890
 			-5:19:36 -	CMT	1908 Apr 22 # Colón Mean Time
 			-5:00	-	EST
@@ -3434,7 +3517,7 @@
 
 # Puerto Rico
 # There are too many San Juans elsewhere, so we'll use 'Puerto_Rico'.
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone America/Puerto_Rico -4:24:25 -	LMT	1899 Mar 28 12:00 # San Juan
 			-4:00	-	AST	1942 May  3
 			-4:00	US	A%sT	1946
@@ -3446,7 +3529,7 @@
 
 # St Pierre and Miquelon
 # There are too many St Pierres elsewhere, so we'll use 'Miquelon'.
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone America/Miquelon	-3:44:40 -	LMT	1911 May 15 # St Pierre
 			-4:00	-	AST	1980 May
 			-3:00	-	-03	1987
@@ -3492,7 +3575,7 @@
 # by March 2018 for TCI. Magnetic Media. 2017-08-25.
 # http://magneticmediatv.com/2017/08/time-change-back-by-march-2018-for-tci/
 #
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone America/Grand_Turk	-4:44:32 -	LMT	1890
 			-5:07:10 -	KMT	1912 Feb # Kingston Mean Time
 			-5:00	-	EST	1979
--- a/make/sun/javazic/tzdata/pacificnew	Wed Nov 20 06:36:47 2019 +0000
+++ b/make/sun/javazic/tzdata/pacificnew	Thu Feb 06 01:43:16 2020 +0000
@@ -44,7 +44,7 @@
 ## Rule	Twilite	XXXX	max	uspres	Nov	Sun>=7	2:00	0	S
 ## Rule	Twilite	XXXX	max	nonpres	Oct	lastSun	2:00	0	S
 
-# Zone	NAME			GMTOFF	RULES/SAVE	FORMAT	[UNTIL]
+# Zone	NAME			STDOFF	RULES/SAVE	FORMAT	[UNTIL]
 ## Zone	America/Los_Angeles-PET	-8:00	US		P%sT	XXXX
 ##				-8:00	Twilite		P%sT
 
--- a/make/sun/javazic/tzdata/southamerica	Wed Nov 20 06:36:47 2019 +0000
+++ b/make/sun/javazic/tzdata/southamerica	Thu Feb 06 01:43:16 2020 +0000
@@ -419,7 +419,7 @@
 # plus is that this silences a zic complaint that there's no POSIX TZ
 # setting for timestamps past 2038.
 
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 #
 # Buenos Aires (BA), Capital Federal (CF),
 Zone America/Argentina/Buenos_Aires -3:53:48 - LMT	1894 Oct 31
@@ -600,7 +600,7 @@
 Link America/Curacao America/Aruba
 
 # Bolivia
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	America/La_Paz	-4:32:36 -	LMT	1890
 			-4:32:36 -	CMT	1931 Oct 15 # Calamarca MT
 			-4:32:36 1:00	BST	1932 Mar 21 # Bolivia ST
@@ -943,14 +943,13 @@
 # removed Tocantins.
 Rule	Brazil	2013	2014	-	Feb	Sun>=15	0:00	0	-
 Rule	Brazil	2015	only	-	Feb	Sun>=22	0:00	0	-
-Rule	Brazil	2016	2022	-	Feb	Sun>=15	0:00	0	-
+Rule	Brazil	2016	2019	-	Feb	Sun>=15	0:00	0	-
 # From Steffen Thorsen (2017-12-18):
 # According to many media sources, next year's DST start in Brazil will move to
-# the first Sunday of November, and it will stay like that for the years after.
+# the first Sunday of November
 # ... https://www.timeanddate.com/news/time/brazil-delays-dst-2018.html
 # From Steffen Thorsen (2017-12-20):
 # http://www.planalto.gov.br/ccivil_03/_ato2015-2018/2017/decreto/D9242.htm
-#
 # From Fábio Gomes (2018-10-04):
 # The Brazilian president just announced a new change on this year DST.
 # It was scheduled to start on November 4th and it was changed to November 18th.
@@ -958,22 +957,21 @@
 # The Brazilian government just announced that the change in DST was
 # canceled....  Maybe the president Michel Temer also woke up one hour
 # earlier today. :)
-Rule	Brazil	2018	max	-	Nov	Sun>=1	0:00	1:00	-
-Rule	Brazil	2023	only	-	Feb	Sun>=22	0:00	0	-
-Rule	Brazil	2024	2025	-	Feb	Sun>=15	0:00	0	-
-Rule	Brazil	2026	only	-	Feb	Sun>=22	0:00	0	-
-Rule	Brazil	2027	2033	-	Feb	Sun>=15	0:00	0	-
-Rule	Brazil	2034	only	-	Feb	Sun>=22	0:00	0	-
-Rule	Brazil	2035	2036	-	Feb	Sun>=15	0:00	0	-
-Rule	Brazil	2037	only	-	Feb	Sun>=22	0:00	0	-
-# From Arthur David Olson (2008-09-29):
-# The next is wrong in some years but is better than nothing.
-Rule	Brazil	2038	max	-	Feb	Sun>=15	0:00	0	-
+Rule	Brazil	2018	only	-	Nov	Sun>=1	0:00	1:00	-
+# The last ruleset listed above says that the following states observed DST:
+# DF, ES, GO, MG, MS, MT, PR, RJ, RS, SC, SP.
+#
+# From Steffen Thorsen (2019-04-05):
+# According to multiple sources the Brazilian president wants to get rid of DST.
+# https://gmconline.com.br/noticias/politica/bolsonaro-horario-de-verao-deve-acabar-este-ano
+# https://g1.globo.com/economia/noticia/2019/04/05/governo-anuncia-fim-do-horario-de-verao.ghtml
+# From Marcus Diniz (2019-04-25):
+# Brazil no longer has DST changes - decree signed today
+# https://g1.globo.com/politica/noticia/2019/04/25/bolsonaro-assina-decreto-que-acaba-com-o-horario-de-verao.ghtml
+# From Daniel Soares de Oliveira (2019-04-26):
+# http://www.planalto.gov.br/ccivil_03/_Ato2019-2022/2019/Decreto/D9772.htm
 
-# The latest ruleset listed above says that the following states observe DST:
-# DF, ES, GO, MG, MS, MT, PR, RJ, RS, SC, SP.
-
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 #
 # Fernando de Noronha (administratively part of PE)
 Zone America/Noronha	-2:09:40 -	LMT	1914
@@ -1255,14 +1253,8 @@
 # From Juan Correa (2016-12-04):
 # Magallanes region ... will keep DST (UTC -3) all year round....
 # http://www.soychile.cl/Santiago/Sociedad/2016/12/04/433428/Bachelet-firmo-el-decreto-para-establecer-un-horario-unico-para-la-Region-de-Magallanes.aspx
-#
 # From Deborah Goldsmith (2017-01-19):
 # http://www.diariooficial.interior.gob.cl/publicaciones/2017/01/17/41660/01/1169626.pdf
-# From Paul Eggert (2017-01-19):
-# The above says the Magallanes change expires 2019-05-11 at 24:00,
-# so in theory, they will revert to -04/-03 after that, which means
-# they will switch from -03 to -04 one hour after Santiago does that day.
-# For now, assume that they will not revert.
 
 # From Juan Correa (2018-08-13):
 # As of moments ago, the Ministry of Energy in Chile has announced the new
@@ -1281,6 +1273,13 @@
 # https://twitter.com/MinEnergia/status/1029009354001973248
 # "We will keep the new time policy unchanged for at least the next 4 years."
 # So we extend the new rules on Saturdays at 24:00 mainland time indefinitely.
+# From Juan Correa (2019-02-04):
+# http://www.diariooficial.interior.gob.cl/publicaciones/2018/11/23/42212/01/1498738.pdf
+# From Paul Eggert (2019-09-01):
+# The above says the Magallanes exception expires 2022-04-02 at 24:00,
+# so in theory, they will revert to -04/-03 after that.
+# For now, assume that they will not revert,
+# since they have extended the expiration date once already.
 
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule	Chile	1927	1931	-	Sep	 1	0:00	1:00	-
@@ -1321,7 +1320,7 @@
 Rule	Chile	2019	max	-	Sep	Sun>=2	4:00u	1:00	-
 # IATA SSIM anomalies: (1992-02) says 1992-03-14;
 # (1996-09) says 1998-03-08.  Ignore these.
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone America/Santiago	-4:42:46 -	LMT	1890
 			-4:42:46 -	SMT	1910 Jan 10 # Santiago Mean Time
 			-5:00	-	-05	1916 Jul  1
@@ -1370,7 +1369,7 @@
 # Palmer has followed Chile.  Prior to that, before the Falklands War,
 # Palmer used to be supplied from Argentina.
 #
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone Antarctica/Palmer	0	-	-00	1965
 			-4:00	Arg	-04/-03	1969 Oct  5
 			-3:00	Arg	-03/-02	1982 May
@@ -1385,7 +1384,7 @@
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule	CO	1992	only	-	May	 3	0:00	1:00	-
 Rule	CO	1993	only	-	Apr	 4	0:00	0	-
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	America/Bogota	-4:56:16 -	LMT	1884 Mar 13
 			-4:56:16 -	BMT	1914 Nov 23 # Bogotá Mean Time
 			-5:00	CO	-05/-04
@@ -1410,7 +1409,7 @@
 # Netherlands as Kingdom Islands.  This won't affect their time zones
 # though, as far as we know.
 #
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	America/Curacao	-4:35:47 -	LMT	1912 Feb 12 # Willemstad
 			-4:30	-	-0430	1965
 			-4:00	-	AST
@@ -1446,7 +1445,7 @@
 Rule	Ecuador	1992	only	-	Nov	28	0:00	1:00	-
 Rule	Ecuador	1993	only	-	Feb	 5	0:00	0	-
 #
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone America/Guayaquil	-5:19:20 -	LMT	1890
 			-5:14:00 -	QMT	1931 # Quito Mean Time
 			-5:00	Ecuador	-05/-04
@@ -1549,7 +1548,7 @@
 Rule	Falk	1986	2000	-	Apr	Sun>=16	0:00	0	-
 Rule	Falk	2001	2010	-	Apr	Sun>=15	2:00	0	-
 Rule	Falk	2001	2010	-	Sep	Sun>=1	2:00	1:00	-
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone Atlantic/Stanley	-3:51:24 -	LMT	1890
 			-3:51:24 -	SMT	1912 Mar 12 # Stanley Mean Time
 			-4:00	Falk	-04/-03	1983 May
@@ -1558,13 +1557,13 @@
 			-3:00	-	-03
 
 # French Guiana
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone America/Cayenne	-3:29:20 -	LMT	1911 Jul
 			-4:00	-	-04	1967 Oct
 			-3:00	-	-03
 
 # Guyana
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	America/Guyana	-3:52:40 -	LMT	1915 Mar    # Georgetown
 			-3:45	-	-0345	1975 Jul 31
 			-3:00	-	-03	1991
@@ -1658,7 +1657,7 @@
 # http://www.presidencia.gov.py/archivos/documentos/DECRETO1264_ey9r8zai.pdf
 Rule	Para	2013	max	-	Mar	Sun>=22	0:00	0	-
 
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone America/Asuncion	-3:50:40 -	LMT	1890
 			-3:50:40 -	AMT	1931 Oct 10 # Asunción Mean Time
 			-4:00	-	-04	1972 Oct
@@ -1687,13 +1686,13 @@
 # IATA is ambiguous for 1993/1995; go with Shanks & Pottenger.
 Rule	Peru	1994	only	-	Jan	 1	0:00	1:00	-
 Rule	Peru	1994	only	-	Apr	 1	0:00	0	-
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	America/Lima	-5:08:12 -	LMT	1890
 			-5:08:36 -	LMT	1908 Jul 28 # Lima Mean Time?
 			-5:00	Peru	-05/-04
 
 # South Georgia
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone Atlantic/South_Georgia -2:26:08 -	LMT	1890 # Grytviken
 			-2:00	-	-02
 
@@ -1701,7 +1700,7 @@
 # uninhabited; scientific personnel have wintered
 
 # Suriname
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone America/Paramaribo	-3:40:40 -	LMT	1911
 			-3:40:52 -	PMT	1935     # Paramaribo Mean Time
 			-3:40:36 -	PMT	1945 Oct    # The capital moved?
@@ -1709,7 +1708,7 @@
 			-3:00	-	-03
 
 # Trinidad and Tobago
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone America/Port_of_Spain -4:06:04 -	LMT	1912 Mar 2
 			-4:00	-	AST
 
@@ -1980,7 +1979,7 @@
 # ... published in the official Gazette [2016-04-18], here:
 # http://historico.tsj.gob.ve/gaceta_ext/abril/1842016/E-1842016-4551.pdf
 
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES	FORMAT	[UNTIL]
 Zone	America/Caracas	-4:27:44 -	LMT	1890
 			-4:27:40 -	CMT	1912 Feb 12 # Caracas Mean Time?
 			-4:30	-	-0430	1965 Jan  1  0:00
--- a/make/sun/javazic/tzdata/systemv	Wed Nov 20 06:36:47 2019 +0000
+++ b/make/sun/javazic/tzdata/systemv	Thu Feb 06 01:43:16 2020 +0000
@@ -46,7 +46,7 @@
 Rule	SystemV	1976	max	-	Apr	lastSun	2:00	1:00	D
 Rule	SystemV	1976	max	-	Oct	lastSun	2:00	0	S
 
-# Zone	NAME		GMTOFF	RULES/SAVE	FORMAT	[UNTIL]
+# Zone	NAME		STDOFF	RULES/SAVE	FORMAT	[UNTIL]
 ## Zone	SystemV/AST4ADT	-4:00	SystemV		A%sT
 ## Zone	SystemV/EST5EDT	-5:00	SystemV		E%sT
 ## Zone	SystemV/CST6CDT	-6:00	SystemV		C%sT
--- a/make/sun/javazic/tzdata/zone.tab	Wed Nov 20 06:36:47 2019 +0000
+++ b/make/sun/javazic/tzdata/zone.tab	Thu Feb 06 01:43:16 2020 +0000
@@ -355,7 +355,10 @@
 RS	+4450+02030	Europe/Belgrade
 RU	+5443+02030	Europe/Kaliningrad	MSK-01 - Kaliningrad
 RU	+554521+0373704	Europe/Moscow	MSK+00 - Moscow area
-RU	+4457+03406	Europe/Simferopol	MSK+00 - Crimea
+# The obsolescent zone.tab format cannot represent Europe/Simferopol well.
+# Put it in RU section and list as UA.  See "territorial claims" above.
+# Programs should use zone1970.tab instead; see above.
+UA	+4457+03406	Europe/Simferopol	MSK+00 - Crimea
 RU	+5836+04939	Europe/Kirov	MSK+00 - Kirov
 RU	+4621+04803	Europe/Astrakhan	MSK+01 - Astrakhan
 RU	+4844+04425	Europe/Volgograd	MSK+01 - Volgograd
--- a/src/macosx/classes/sun/nio/ch/KQueueArrayWrapper.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/macosx/classes/sun/nio/ch/KQueueArrayWrapper.java	Thu Feb 06 01:43:16 2020 +0000
@@ -53,10 +53,6 @@
  */
 
 class KQueueArrayWrapper {
-    // Event masks
-    static final short POLLIN       = AbstractPollArrayWrapper.POLLIN;
-    static final short POLLOUT      = AbstractPollArrayWrapper.POLLOUT;
-
     // kevent filters
     static short EVFILT_READ;
     static short EVFILT_WRITE;
@@ -128,9 +124,9 @@
         //   SinkChannelImpl, SourceChannelImpl, DatagramChannelImpl,
         //   ServerSocketChannelImpl, SocketChannelImpl
         if (filter == EVFILT_READ) {
-            result |= POLLIN;
+            result |= Net.POLLIN;
         } else if (filter == EVFILT_WRITE) {
-            result |= POLLOUT;
+            result |= Net.POLLOUT;
         }
 
         return result;
@@ -179,7 +175,7 @@
                 if (!ch.isOpen())
                     continue;
 
-                register0(kq, ch.getFDVal(), u.events & POLLIN, u.events & POLLOUT);
+                register0(kq, ch.getFDVal(), u.events & Net.POLLIN, u.events & Net.POLLOUT);
             }
         }
     }
--- a/src/share/classes/com/sun/crypto/provider/JceKeyStore.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/com/sun/crypto/provider/JceKeyStore.java	Thu Feb 06 01:43:16 2020 +0000
@@ -43,6 +43,7 @@
 import java.security.cert.CertificateException;
 import javax.crypto.SealedObject;
 
+import sun.misc.IOUtils;
 import sun.misc.ObjectInputFilter;
 
 /**
@@ -70,7 +71,7 @@
     private static final class PrivateKeyEntry {
         Date date; // the creation date of this entry
         byte[] protectedKey;
-        Certificate chain[];
+        Certificate[] chain;
     };
 
     // Secret key
@@ -738,23 +739,11 @@
                         entry.date = new Date(dis.readLong());
 
                         // read the private key
-                        try {
-                            entry.protectedKey = new byte[dis.readInt()];
-                        } catch (OutOfMemoryError e) {
-                            throw new IOException("Keysize too big");
-                        }
-                        dis.readFully(entry.protectedKey);
+                        entry.protectedKey = IOUtils.readExactlyNBytes(dis, dis.readInt());
 
                         // read the certificate chain
                         int numOfCerts = dis.readInt();
-                        try {
-                            if (numOfCerts > 0) {
-                                entry.chain = new Certificate[numOfCerts];
-                            }
-                        } catch (OutOfMemoryError e) {
-                            throw new IOException("Too many certificates in "
-                                                  + "chain");
-                        }
+                        List<Certificate> tmpCerts = new ArrayList<>();
                         for (int j = 0; j < numOfCerts; j++) {
                             if (xVersion == 2) {
                                 // read the certificate type, and instantiate a
@@ -762,27 +751,24 @@
                                 // existing factory if possible)
                                 String certType = dis.readUTF();
                                 if (cfs.containsKey(certType)) {
-                                // reuse certificate factory
+                                    // reuse certificate factory
                                     cf = cfs.get(certType);
                                 } else {
-                                // create new certificate factory
+                                    // create new certificate factory
                                     cf = CertificateFactory.getInstance(
                                         certType);
-                                // store the certificate factory so we can
-                                // reuse it later
+                                    // store the certificate factory so we can
+                                    // reuse it later
                                     cfs.put(certType, cf);
                                 }
                             }
                             // instantiate the certificate
-                            try {
-                                encoded = new byte[dis.readInt()];
-                            } catch (OutOfMemoryError e) {
-                                throw new IOException("Certificate too big");
-                            }
-                            dis.readFully(encoded);
+                            encoded = IOUtils.readExactlyNBytes(dis, dis.readInt());
                             bais = new ByteArrayInputStream(encoded);
-                            entry.chain[j] = cf.generateCertificate(bais);
+                            tmpCerts.add(cf.generateCertificate(bais));
                         }
+                        entry.chain = tmpCerts.toArray(
+                                new Certificate[numOfCerts]);
 
                         // Add the entry to the list
                         entries.put(alias, entry);
@@ -814,12 +800,7 @@
                                 cfs.put(certType, cf);
                             }
                         }
-                        try {
-                            encoded = new byte[dis.readInt()];
-                        } catch (OutOfMemoryError e) {
-                            throw new IOException("Certificate too big");
-                        }
-                        dis.readFully(encoded);
+                        encoded = IOUtils.readExactlyNBytes(dis, dis.readInt());
                         bais = new ByteArrayInputStream(encoded);
                         entry.cert = cf.generateCertificate(bais);
 
@@ -872,16 +853,14 @@
                  * with
                  */
                 if (password != null) {
-                    byte computed[], actual[];
-                    computed = md.digest();
-                    actual = new byte[computed.length];
-                    dis.readFully(actual);
-                    for (int i = 0; i < computed.length; i++) {
-                        if (computed[i] != actual[i]) {
-                            throw new IOException(
+                    byte[] computed = md.digest();
+                    byte[] actual = IOUtils.readExactlyNBytes(dis, computed.length);
+                    if (!MessageDigest.isEqual(computed, actual)) {
+                        throw new IOException(
                                 "Keystore was tampered with, or "
-                                + "password was incorrect");
-                        }
+                                + "password was incorrect",
+                                new UnrecoverableKeyException(
+                                        "Password verification failed"));
                     }
                 }
             }  finally {
--- a/src/share/classes/com/sun/java/util/jar/pack/ClassReader.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/com/sun/java/util/jar/pack/ClassReader.java	Thu Feb 06 01:43:16 2020 +0000
@@ -118,6 +118,13 @@
         return e;
     }
 
+    private Entry checkValid(Entry e) {
+         if (e == INVALID_ENTRY) {
+            throw new IllegalStateException("Invalid constant pool reference");
+        }
+         return e;
+    }
+
     private Entry readRefOrNull(byte tag) throws IOException {
         Entry e = readRef();
         assert(e == null || e.tagMatches(tag));
@@ -194,6 +201,29 @@
         return null;  // OK
     }
 
+    // use this identity for invalid references
+    private static final Entry INVALID_ENTRY = new Entry((byte) -1) {
+        @Override
+        public boolean equals(Object o) {
+            throw new IllegalStateException("Should not call this");
+        }
+
+        @Override
+        protected int computeValueHash() {
+            throw new IllegalStateException("Should not call this");
+        }
+
+        @Override
+        public int compareTo(Object o) {
+            throw new IllegalStateException("Should not call this");
+        }
+
+        @Override
+        public String stringValue() {
+            throw new IllegalStateException("Should not call this");
+        }
+    };
+
     void readConstantPool() throws IOException {
         int length = in.readUnsignedShort();
         //System.err.println("reading CP, length="+length);
@@ -202,7 +232,7 @@
         int fptr = 0;
 
         Entry[] cpMap = new Entry[length];
-        cpMap[0] = null;
+        cpMap[0] = INVALID_ENTRY;
         for (int i = 1; i < length; i++) {
             //System.err.println("reading CP elt, i="+i);
             int tag = in.readByte();
@@ -223,13 +253,13 @@
                 case CONSTANT_Long:
                     {
                         cpMap[i] = ConstantPool.getLiteralEntry(in.readLong());
-                        cpMap[++i] = null;
+                        cpMap[++i] = INVALID_ENTRY;
                     }
                     break;
                 case CONSTANT_Double:
                     {
                         cpMap[i] = ConstantPool.getLiteralEntry(in.readDouble());
-                        cpMap[++i] = null;
+                        cpMap[++i] = INVALID_ENTRY;
                     }
                     break;
 
@@ -270,7 +300,7 @@
                 int ref2 = fixups[fi++];
                 if (verbose > 3)
                     Utils.log.fine("  cp["+cpi+"] = "+ConstantPool.tagName(tag)+"{"+ref+","+ref2+"}");
-                if (cpMap[ref] == null || ref2 >= 0 && cpMap[ref2] == null) {
+                if (checkValid(cpMap[ref]) == null || ref2 >= 0 && checkValid(cpMap[ref2]) == null) {
                     // Defer.
                     fixups[fptr++] = cpi;
                     fixups[fptr++] = tag;
--- a/src/share/classes/com/sun/jndi/ldap/Connection.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/com/sun/jndi/ldap/Connection.java	Thu Feb 06 01:43:16 2020 +0000
@@ -47,8 +47,6 @@
 import javax.net.ssl.SSLParameters;
 import javax.net.ssl.SSLSocket;
 
-import sun.misc.IOUtils;
-
 /**
   * A thread that creates a connection to an LDAP server.
   * After the connection, the thread reads from the connection.
@@ -929,7 +927,7 @@
                     }
 
                     // read in seqlen bytes
-                    byte[] left = IOUtils.readFully(in, seqlen, false);
+                    byte[] left = readFully(in, seqlen);
                     inbuf = Arrays.copyOf(inbuf, offset + left.length);
                     System.arraycopy(left, 0, inbuf, offset, left.length);
                     offset += left.length;
@@ -1024,6 +1022,31 @@
         }
     }
 
+    private static byte[] readFully(InputStream is, int length)
+        throws IOException
+    {
+        byte[] buf = new byte[Math.min(length, 8192)];
+        int nread = 0;
+        while (nread < length) {
+            int bytesToRead;
+            if (nread >= buf.length) {  // need to allocate a larger buffer
+                bytesToRead = Math.min(length - nread, buf.length + 8192);
+                if (buf.length < nread + bytesToRead) {
+                    buf = Arrays.copyOf(buf, nread + bytesToRead);
+                }
+            } else {
+                bytesToRead = buf.length - nread;
+            }
+            int count = is.read(buf, nread, bytesToRead);
+            if (count < 0) {
+                if (buf.length != nread)
+                    buf = Arrays.copyOf(buf, nread);
+                break;
+            }
+            nread += count;
+        }
+        return buf;
+    }
 
     // This code must be uncommented to run the LdapAbandonTest.
     /*public void sendSearchReqs(String dn, int numReqs) {
--- a/src/share/classes/com/sun/security/auth/module/Krb5LoginModule.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/com/sun/security/auth/module/Krb5LoginModule.java	Thu Feb 06 01:43:16 2020 +0000
@@ -121,8 +121,9 @@
  * be returned.</dd>
  *  <P>
  * <dt><b><code>renewTGT</code></b>:</dt>
- * <dd>Set this to true, if you want to renew
- * the TGT. If this is set, <code>useTicketCache</code> must also be
+ * <dd>Set this to true, if you want to renew the TGT when it's more than
+ * half-way expired (the time until expiration is less than the time
+ * since start time). If this is set, {@code useTicketCache} must also be
  * set to true; otherwise a configuration error will be returned.</dd>
  * <p>
  * <dt><b><code>doNotPrompt</code></b>:</dt>
@@ -636,17 +637,19 @@
                     (principal, ticketCacheName);
 
                 if (cred != null) {
-                    // check to renew credentials
+                    if (renewTGT && isOld(cred)) {
+                        // renew if ticket is old.
+                        Credentials newCred = renewCredentials(cred);
+                        if (newCred != null) {
+                            cred = newCred;
+                        }
+                    }
                     if (!isCurrent(cred)) {
-                        if (renewTGT) {
-                            cred = renewCredentials(cred);
-                        } else {
-                            // credentials have expired
-                            cred = null;
-                            if (debug)
-                                System.out.println("Credentials are" +
-                                                " no longer valid");
-                        }
+                        // credentials have expired
+                        cred = null;
+                        if (debug)
+                            System.out.println("Credentials are" +
+                                    " no longer valid");
                     }
                 }
 
@@ -940,7 +943,7 @@
                  + " true or renewTGT should be false");
     }
 
-    private boolean isCurrent(Credentials creds)
+    private static boolean isCurrent(Credentials creds)
     {
         Date endTime = creds.getEndTime();
         if (endTime != null) {
@@ -949,6 +952,23 @@
         return true;
     }
 
+    private static boolean isOld(Credentials creds)
+    {
+        Date endTime = creds.getEndTime();
+        if (endTime != null) {
+            Date authTime = creds.getAuthTime();
+            long now = System.currentTimeMillis();
+            if (authTime != null) {
+                // pass the mid between auth and end
+                return now - authTime.getTime() > endTime.getTime() - now;
+            } else {
+                // will expire in less than 2 hours
+                return now <= endTime.getTime() - 1000*3600*2L;
+            }
+        }
+        return false;
+    }
+
     private Credentials renewCredentials(Credentials creds)
     {
         Credentials lcreds;
@@ -956,6 +976,10 @@
             if (!creds.isRenewable())
                 throw new RefreshFailedException("This ticket" +
                                 " is not renewable");
+            if (creds.getRenewTill() == null) {
+                // Renewable ticket without renew-till. Illegal and ignored.
+                return creds;
+            }
             if (System.currentTimeMillis() > cred.getRenewTill().getTime())
                 throw new RefreshFailedException("This ticket is past "
                                              + "its last renewal time.");
--- a/src/share/classes/com/sun/security/sasl/gsskerb/GssKrb5Base.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/com/sun/security/sasl/gsskerb/GssKrb5Base.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -73,8 +73,12 @@
         }
 
         try {
-            MessageProp msgProp = new MessageProp(JGSS_QOP, privacy);
+            MessageProp msgProp = new MessageProp(JGSS_QOP, false);
             byte[] answer = secCtx.unwrap(incoming, start, len, msgProp);
+            if (privacy && !msgProp.getPrivacy()) {
+                throw new SaslException("Privacy not protected");
+            }
+            checkMessageProp("", msgProp);
             if (logger.isLoggable(Level.FINEST)) {
                 traceOutput(myClassName, "KRB501:Unwrap", "incoming: ",
                     incoming, start, len);
@@ -128,4 +132,20 @@
     protected void finalize() throws Throwable {
         dispose();
     }
+
+    void checkMessageProp(String label, MessageProp msgProp)
+            throws SaslException {
+        if (msgProp.isDuplicateToken()) {
+            throw new SaslException(label + "Duplicate token");
+        }
+        if (msgProp.isGapToken()) {
+            throw new SaslException(label + "Gap token");
+        }
+        if (msgProp.isOldToken()) {
+            throw new SaslException(label + "Old token");
+        }
+        if (msgProp.isUnseqToken()) {
+            throw new SaslException(label + "Token not in sequence");
+        }
+    }
 }
--- a/src/share/classes/com/sun/security/sasl/gsskerb/GssKrb5Client.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/com/sun/security/sasl/gsskerb/GssKrb5Client.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -230,8 +230,10 @@
 
             // Received S1 (security layer, server max recv size)
 
+            MessageProp msgProp = new MessageProp(false);
             byte[] gssOutToken = secCtx.unwrap(challengeData, 0,
-                challengeData.length, new MessageProp(0, false));
+                challengeData.length, msgProp);
+            checkMessageProp("Handshake failure: ", msgProp);
 
             // First octet is a bit-mask specifying the protections
             // supported by the server
--- a/src/share/classes/com/sun/security/sasl/gsskerb/GssKrb5Server.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/com/sun/security/sasl/gsskerb/GssKrb5Server.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -227,8 +227,10 @@
         try {
             // Expecting 4 octets from client selected protection
             // and client's receive buffer size
+            MessageProp msgProp = new MessageProp(false);
             byte[] gssOutToken = secCtx.unwrap(responseData, 0,
-                responseData.length, new MessageProp(0, false));
+                responseData.length, msgProp);
+            checkMessageProp("Handshake failure: ", msgProp);
 
             if (logger.isLoggable(Level.FINER)) {
                 traceOutput(MY_CLASS_NAME, "doHandshake2",
--- a/src/share/classes/java/awt/color/ICC_Profile.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/java/awt/color/ICC_Profile.java	Thu Feb 06 01:43:16 2020 +0000
@@ -42,7 +42,9 @@
 import sun.java2d.cmm.ProfileDeferralMgr;
 import sun.java2d.cmm.ProfileDeferralInfo;
 import sun.java2d.cmm.ProfileActivator;
+import sun.misc.IOUtils;
 
+import java.io.BufferedInputStream;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
@@ -1019,42 +1021,25 @@
 
 
     static byte[] getProfileDataFromStream(InputStream s) throws IOException {
-    byte profileData[];
-    int profileSize;
-
-        byte header[] = new byte[128];
-        int bytestoread = 128;
-        int bytesread = 0;
-        int n;
 
-        while (bytestoread != 0) {
-            if ((n = s.read(header, bytesread, bytestoread)) < 0) {
-                return null;
-            }
-            bytesread += n;
-            bytestoread -= n;
-        }
+        BufferedInputStream bis = new BufferedInputStream(s);
+        bis.mark(128);
+
+        byte[] header = IOUtils.readNBytes(bis, 128);
         if (header[36] != 0x61 || header[37] != 0x63 ||
             header[38] != 0x73 || header[39] != 0x70) {
             return null;   /* not a valid profile */
         }
-        profileSize = ((header[0] & 0xff) << 24) |
-                      ((header[1] & 0xff) << 16) |
-                      ((header[2] & 0xff) <<  8) |
-                       (header[3] & 0xff);
-        profileData = new byte[profileSize];
-        System.arraycopy(header, 0, profileData, 0, 128);
-        bytestoread = profileSize - 128;
-        bytesread = 128;
-        while (bytestoread != 0) {
-            if ((n = s.read(profileData, bytesread, bytestoread)) < 0) {
-                return null;
-            }
-            bytesread += n;
-            bytestoread -= n;
+        int profileSize = ((header[0] & 0xff) << 24) |
+                          ((header[1] & 0xff) << 16) |
+                          ((header[2] & 0xff) << 8) |
+                          (header[3] & 0xff);
+        bis.reset();
+        try {
+            return IOUtils.readNBytes(bis, profileSize);
+        } catch (OutOfMemoryError e) {
+            throw new IOException("Color profile is too big");
         }
-
-        return profileData;
     }
 
 
--- a/src/share/classes/java/beans/beancontext/BeanContextSupport.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/java/beans/beancontext/BeanContextSupport.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -1024,18 +1024,8 @@
         int count = serializable;
 
         while (count-- > 0) {
-            Object                      child = null;
-            BeanContextSupport.BCSChild bscc  = null;
-
-            try {
-                child = ois.readObject();
-                bscc  = (BeanContextSupport.BCSChild)ois.readObject();
-            } catch (IOException ioe) {
-                continue;
-            } catch (ClassNotFoundException cnfe) {
-                continue;
-            }
-
+            Object child = ois.readObject();
+            BCSChild bscc = (BCSChild) ois.readObject();
 
             synchronized(child) {
                 BeanContextChild bcc = null;
--- a/src/share/classes/java/io/EOFException.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/java/io/EOFException.java	Thu Feb 06 01:43:16 2020 +0000
@@ -32,7 +32,6 @@
  * This exception is mainly used by data input streams to signal end of
  * stream. Note that many other input operations return a special value on
  * end of stream rather than throwing an exception.
- * <p>
  *
  * @author  Frank Yellin
  * @see     java.io.DataInputStream
--- a/src/share/classes/java/io/FilePermission.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/java/io/FilePermission.java	Thu Feb 06 01:43:16 2020 +0000
@@ -46,8 +46,11 @@
  * the file separator character, <code>File.separatorChar</code>) indicates
  * all the files and directories contained in that directory. A pathname
  * that ends with "/-" indicates (recursively) all files
- * and subdirectories contained in that directory. A pathname consisting of
- * the special token "&lt;&lt;ALL FILES&gt;&gt;" matches <b>any</b> file.
+ * and subdirectories contained in that directory. Such a pathname is called
+ * a wildcard pathname. Otherwise, it's a simple pathname.
+ * <P>
+ * A pathname consisting of the special token {@literal "<<ALL FILES>>"}
+ * matches <b>any</b> file.
  * <P>
  * Note: A pathname consisting of a single "*" indicates all the files
  * in the current directory, while a pathname consisting of a single "-"
@@ -80,7 +83,7 @@
  * <P>
  * Be careful when granting FilePermissions. Think about the implications
  * of granting read and especially write access to various files and
- * directories. The "&lt;&lt;ALL FILES>>" permission with write action is
+ * directories. The {@literal "<<ALL FILES>>"} permission with write action is
  * especially dangerous. This grants permission to write to the entire
  * file system. One thing this effectively allows is replacement of the
  * system binary, including the JVM runtime environment.
@@ -156,6 +159,7 @@
 
     private transient String cpath;
 
+    private transient boolean allFiles; // whether this is <<ALL FILES>>
     private transient boolean invalid;  // whether input path is invalid
 
     // static Strings used by init(int mask)
@@ -209,6 +213,7 @@
         this.mask = mask;
 
         if (cpath.equals("<<ALL FILES>>")) {
+            allFiles = true;
             directory = true;
             recursive = true;
             cpath = "";
@@ -340,6 +345,23 @@
      *      "/tmp/*" encompasses all files in the "/tmp" directory,
      *      including the one named "foo".
      * </ul>
+     * <P>
+     * Precisely, a simple pathname implies another simple pathname
+     * if and only if they are equal. A simple pathname never implies
+     * a wildcard pathname. A wildcard pathname implies another wildcard
+     * pathname if and only if all simple pathnames implied by the latter
+     * are implied by the former. A wildcard pathname implies a simple
+     * pathname if and only if
+     * <ul>
+     *     <li>if the wildcard flag is "*", the simple pathname's path
+     *     must be right inside the wildcard pathname's path.
+     *     <li>if the wildcard flag is "-", the simple pathname's path
+     *     must be recursively inside the wildcard pathname's path.
+     * </ul>
+     * <P>
+     * {@literal "<<ALL FILES>>"} implies every other pathname. No pathname,
+     * except for {@literal "<<ALL FILES>>"} itself, implies
+     * {@literal "<<ALL FILES>>"}.
      *
      * @param p the permission to check against.
      *
@@ -372,9 +394,15 @@
         if (this == that) {
             return true;
         }
+        if (allFiles) {
+            return true;
+        }
         if (this.invalid || that.invalid) {
             return false;
         }
+        if (that.allFiles) {
+            return false;
+        }
         if (this.directory) {
             if (this.recursive) {
                 // make sure that.path is longer then path so
@@ -420,7 +448,11 @@
     /**
      * Checks two FilePermission objects for equality. Checks that <i>obj</i> is
      * a FilePermission, and has the same pathname and actions as this object.
-     * <P>
+     *
+     * @implNote More specifically, two pathnames are the same if and only if
+     * they have the same wildcard flag and their
+     * {@code npath} are equal. Or they are both {@literal "<<ALL FILES>>"}.
+     *
      * @param obj the object we are testing for equality with this object.
      * @return <code>true</code> if obj is a FilePermission, and has the same
      *          pathname and actions as this FilePermission object,
@@ -439,6 +471,7 @@
             return false;
         }
         return (this.mask == that.mask) &&
+            (this.allFiles == that.allFiles) &&
             this.cpath.equals(that.cpath) &&
             (this.directory == that.directory) &&
             (this.recursive == that.recursive);
--- a/src/share/classes/java/io/ObjectInputStream.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/java/io/ObjectInputStream.java	Thu Feb 06 01:43:16 2020 +0000
@@ -42,6 +42,7 @@
 import java.util.Objects;
 import static java.io.ObjectStreamClass.processQueue;
 import sun.misc.JavaObjectInputStreamAccess;
+import sun.misc.JavaObjectInputStreamReadString;
 import sun.misc.JavaOISAccess;
 import sun.misc.ObjectInputFilter;
 import sun.misc.ObjectStreamClassValidator;
@@ -416,16 +417,50 @@
      * @throws  IOException Any of the usual Input/Output related exceptions.
      */
     public final Object readObject()
+        throws IOException, ClassNotFoundException {
+        return readObject(Object.class);
+    }
+
+    /**
+     * Reads a String and only a string.
+     *
+     * @return  the String read
+     * @throws  EOFException If end of file is reached.
+     * @throws  IOException If other I/O error has occurred.
+     */
+    private String readString() throws IOException {
+        try {
+            return (String) readObject(String.class);
+        } catch (ClassNotFoundException cnf) {
+            throw new IllegalStateException(cnf);
+        }
+    }
+
+    /**
+     * Internal method to read an object from the ObjectInputStream of the expected type.
+     * Called only from {@code readObject()} and {@code readString()}.
+     * Only {@code Object.class} and {@code String.class} are supported.
+     *
+     * @param type the type expected; either Object.class or String.class
+     * @return an object of the type
+     * @throws  IOException Any of the usual Input/Output related exceptions.
+     * @throws  ClassNotFoundException Class of a serialized object cannot be
+     *          found.
+     */
+    private final Object readObject(Class<?> type)
         throws IOException, ClassNotFoundException
     {
         if (enableOverride) {
             return readObjectOverride();
         }
 
+        if (! (type == Object.class || type == String.class))
+            throw new AssertionError("internal error");
+
         // if nested read, passHandle contains handle of enclosing object
         int outerHandle = passHandle;
         try {
-            Object obj = readObject0(false);
+            Object obj = readObject0(type, false);
             handles.markDependency(outerHandle, passHandle);
             ClassNotFoundException ex = handles.lookupException(passHandle);
             if (ex != null) {
@@ -515,7 +550,7 @@
         // if nested read, passHandle contains handle of enclosing object
         int outerHandle = passHandle;
         try {
-            Object obj = readObject0(true);
+            Object obj = readObject0(Object.class, true);
             handles.markDependency(outerHandle, passHandle);
             ClassNotFoundException ex = handles.lookupException(passHandle);
             if (ex != null) {
@@ -1514,8 +1549,10 @@
 
     /**
      * Underlying readObject implementation.
+     * @param type a type expected to be deserialized; non-null
+     * @param unshared true if the object can not be a reference to a shared object, otherwise false
      */
-    private Object readObject0(boolean unshared) throws IOException {
+    private Object readObject0(Class<?> type, boolean unshared) throws IOException {
         boolean oldMode = bin.getBlockDataMode();
         if (oldMode) {
             int remain = bin.currentBlockRemaining();
@@ -1547,13 +1584,20 @@
                     return readNull();
 
                 case TC_REFERENCE:
-                    return readHandle(unshared);
+                    // check the type of the existing object
+                    return type.cast(readHandle(unshared));
 
                 case TC_CLASS:
+                    if (type == String.class) {
+                        throw new ClassCastException("Cannot cast a class to java.lang.String");
+                    }
                     return readClass(unshared);
 
                 case TC_CLASSDESC:
                 case TC_PROXYCLASSDESC:
+                    if (type == String.class) {
+                        throw new ClassCastException("Cannot cast a class to java.lang.String");
+                    }
                     return readClassDesc(unshared);
 
                 case TC_STRING:
@@ -1561,15 +1605,27 @@
                     return checkResolve(readString(unshared));
 
                 case TC_ARRAY:
+                    if (type == String.class) {
+                        throw new ClassCastException("Cannot cast an array to java.lang.String");
+                    }
                     return checkResolve(readArray(unshared));
 
                 case TC_ENUM:
+                    if (type == String.class) {
+                        throw new ClassCastException("Cannot cast an enum to java.lang.String");
+                    }
                     return checkResolve(readEnum(unshared));
 
                 case TC_OBJECT:
+                    if (type == String.class) {
+                        throw new ClassCastException("Cannot cast an object to java.lang.String");
+                    }
                     return checkResolve(readOrdinaryObject(unshared));
 
                 case TC_EXCEPTION:
+                    if (type == String.class) {
+                        throw new ClassCastException("Cannot cast an exception to java.lang.String");
+                    }
                     IOException ex = readFatalException();
                     throw new WriteAbortedException("writing aborted", ex);
 
@@ -1944,7 +2000,7 @@
 
         if (ccl == null) {
             for (int i = 0; i < len; i++) {
-                readObject0(false);
+                readObject0(Object.class, false);
             }
         } else if (ccl.isPrimitive()) {
             if (ccl == Integer.TYPE) {
@@ -1969,7 +2025,7 @@
         } else {
             Object[] oa = (Object[]) array;
             for (int i = 0; i < len; i++) {
-                oa[i] = readObject0(false);
+                oa[i] = readObject0(Object.class, false);
                 handles.markDependency(arrayHandle, passHandle);
             }
         }
@@ -2245,7 +2301,7 @@
                     return;
 
                 default:
-                    readObject0(false);
+                    readObject0(Object.class, false);
                     break;
             }
         }
@@ -2279,7 +2335,7 @@
         int numPrimFields = fields.length - objVals.length;
         for (int i = 0; i < objVals.length; i++) {
             ObjectStreamField f = fields[numPrimFields + i];
-            objVals[i] = readObject0(f.isUnshared());
+            objVals[i] = readObject0(Object.class, f.isUnshared());
             if (f.getField() != null) {
                 handles.markDependency(objHandle, passHandle);
             }
@@ -2300,7 +2356,7 @@
             throw new InternalError();
         }
         clear();
-        return (IOException) readObject0(false);
+        return (IOException) readObject0(Object.class, false);
     }
 
     /**
@@ -2444,7 +2500,7 @@
             int numPrimFields = fields.length - objVals.length;
             for (int i = 0; i < objVals.length; i++) {
                 objVals[i] =
-                    readObject0(fields[numPrimFields + i].isUnshared());
+                    readObject0(Object.class, fields[numPrimFields + i].isUnshared());
                 objHandles[i] = passHandle;
             }
             passHandle = oldHandle;
@@ -3917,5 +3973,11 @@
                 ObjectInputStream.setValidator(ois, validator);
             }
         });
+        SharedSecrets.setJavaObjectInputStreamReadString(new JavaObjectInputStreamReadString() {
+            @Override
+            public String readString(ObjectInputStream ois) throws IOException {
+                return ois.readString();
+            }
+        });
     }
 }
--- a/src/share/classes/java/lang/System.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/java/lang/System.java	Thu Feb 06 01:43:16 2020 +0000
@@ -40,6 +40,8 @@
 import sun.security.util.SecurityConstants;
 import sun.reflect.annotation.AnnotationType;
 
+import jdk.internal.util.StaticProperty;
+
 /**
  * The <code>System</code> class contains several useful class fields
  * and methods. It cannot be instantiated.
@@ -1136,6 +1138,7 @@
 
 
         lineSeparator = props.getProperty("line.separator");
+        StaticProperty.jdkSerialFilter();   // Load StaticProperty to cache the property values
         sun.misc.Version.init();
 
         FileInputStream fdIn = new FileInputStream(FileDescriptor.in);
--- a/src/share/classes/java/net/URL.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/java/net/URL.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1450,7 +1450,9 @@
     }
 
     boolean isBuiltinStreamHandler(URLStreamHandler handler) {
-       return isBuiltinStreamHandler(handler.getClass().getName());
+        Class<?> handlerClass = handler.getClass();
+        return isBuiltinStreamHandler(handlerClass.getName()) ||
+                handlerClass.getClassLoader() == Object.class.getClassLoader();
     }
 
     private boolean isBuiltinStreamHandler(String handlerClassName) {
--- a/src/share/classes/java/nio/channels/AsynchronousChannelGroup.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/java/nio/channels/AsynchronousChannelGroup.java	Thu Feb 06 01:43:16 2020 +0000
@@ -66,7 +66,6 @@
  *     <th>Description</th>
  *   </tr>
  *   <tr>
- *   <tr>
  *     <td> {@code java.nio.channels.DefaultThreadPool.threadFactory} </td>
  *     <td> The value of this property is taken to be the fully-qualified name
  *     of a concrete {@link java.util.concurrent.ThreadFactory ThreadFactory}
--- a/src/share/classes/java/nio/channels/AsynchronousFileChannel.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/java/nio/channels/AsynchronousFileChannel.java	Thu Feb 06 01:43:16 2020 +0000
@@ -178,7 +178,7 @@
      *   written synchronously to the underlying storage device. (see <a
      *   href="../file/package-summary.html#integrity"> Synchronized I/O file
      *   integrity</a>). </td>
-     * <tr>
+     * </tr>
      * <tr>
      *   <td> {@link StandardOpenOption#DSYNC DSYNC} </td>
      *   <td> Requires that every update to the file's content be written
--- a/src/share/classes/java/nio/channels/FileChannel.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/java/nio/channels/FileChannel.java	Thu Feb 06 01:43:16 2020 +0000
@@ -229,7 +229,7 @@
      *   written synchronously to the underlying storage device. (see <a
      *   href="../file/package-summary.html#integrity"> Synchronized I/O file
      *   integrity</a>). </td>
-     * <tr>
+     * </tr>
      * <tr>
      *   <td> {@link StandardOpenOption#DSYNC DSYNC} </td>
      *   <td> Requires that every update to the file's content be written
--- a/src/share/classes/java/nio/channels/SelectableChannel.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/java/nio/channels/SelectableChannel.java	Thu Feb 06 01:43:16 2020 +0000
@@ -121,7 +121,7 @@
     //   keySet, may be empty but is never null, typ. a tiny array
     //   boolean isRegistered, protected by key set
     //   regLock, lock object to prevent duplicate registrations
-    //   boolean isBlocking, protected by regLock
+    //   blocking mode, protected by regLock
 
     /**
      * Tells whether or not this channel is currently registered with any
--- a/src/share/classes/java/nio/channels/package-info.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/java/nio/channels/package-info.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -31,7 +31,7 @@
  * <a name="channels"></a>
  *
  * <blockquote><table cellspacing=1 cellpadding=0 summary="Lists channels and their descriptions">
- * <tr><th><p align="left">Channels</p></th><th><p align="left">Description</p></th></tr>
+ * <tr><th align="left">Channels</th><th align="left">Description</th></tr>
  * <tr><td valign=top><tt><i>{@link java.nio.channels.Channel}</i></tt></td>
  *     <td>A nexus for I/O operations</td></tr>
  * <tr><td valign=top><tt>&nbsp;&nbsp;<i>{@link java.nio.channels.ReadableByteChannel}</i></tt></td>
@@ -110,7 +110,7 @@
  * write them to a given writable byte channel.
  *
  * <blockquote><table cellspacing=1 cellpadding=0 summary="Lists file channels and their descriptions">
- * <tr><th><p align="left">File channels</p></th><th><p align="left">Description</p></th></tr>
+ * <tr><th align="left">File channels</th><th align="left">Description</th></tr>
  * <tr><td valign=top><tt>{@link java.nio.channels.FileChannel}</tt></td>
  *     <td>Reads, writes, maps, and manipulates files</td></tr>
  * <tr><td valign=top><tt>{@link java.nio.channels.FileLock}</tt></td>
@@ -138,7 +138,7 @@
  *
  * <a name="multiplex"></a>
  * <blockquote><table cellspacing=1 cellpadding=0 summary="Lists multiplexed, non-blocking channels and their descriptions">
- * <tr><th><p align="left">Multiplexed, non-blocking I/O</p></th><th><p align="left">Description</p></th></tr>
+ * <tr><th align="left">Multiplexed, non-blocking I/O</th><th align="left"><p>Description</th></tr>
  * <tr><td valign=top><tt>{@link java.nio.channels.SelectableChannel}</tt></td>
  *     <td>A channel that can be multiplexed</td></tr>
  * <tr><td valign=top><tt>&nbsp;&nbsp;{@link java.nio.channels.DatagramChannel}</tt></td>
@@ -225,7 +225,7 @@
  * <a name="async"></a>
  *
  * <blockquote><table cellspacing=1 cellpadding=0 summary="Lists asynchronous channels and their descriptions">
- * <tr><th><p align="left">Asynchronous I/O</p></th><th><p align="left">Description</p></th></tr>
+ * <tr><th align="left">Asynchronous I/O</th><th align="left">Description</th></tr>
  * <tr><td valign=top><tt>{@link java.nio.channels.AsynchronousFileChannel}</tt></td>
  *     <td>An asynchronous channel for reading, writing, and manipulating a file</td></tr>
  * <tr><td valign=top><tt>{@link java.nio.channels.AsynchronousSocketChannel}</tt></td>
--- a/src/share/classes/java/nio/channels/spi/AbstractSelectableChannel.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/java/nio/channels/spi/AbstractSelectableChannel.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,7 +26,14 @@
 package java.nio.channels.spi;
 
 import java.io.IOException;
-import java.nio.channels.*;
+import java.nio.channels.CancelledKeyException;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.ClosedSelectorException;
+import java.nio.channels.IllegalBlockingModeException;
+import java.nio.channels.IllegalSelectorException;
+import java.nio.channels.SelectableChannel;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.Selector;
 
 
 /**
@@ -67,8 +74,8 @@
     // Lock for registration and configureBlocking operations
     private final Object regLock = new Object();
 
-    // Blocking mode, protected by regLock
-    boolean blocking = true;
+    // True when non-blocking, need regLock to change;
+    private volatile boolean nonBlocking;
 
     /**
      * Initializes a new instance of this class.
@@ -194,7 +201,7 @@
                 throw new ClosedChannelException();
             if ((ops & ~validOps()) != 0)
                 throw new IllegalArgumentException();
-            if (blocking)
+            if (isBlocking())
                 throw new IllegalBlockingModeException();
             SelectionKey k = findKey(sel);
             if (k != null) {
@@ -258,9 +265,7 @@
     // -- Blocking --
 
     public final boolean isBlocking() {
-        synchronized (regLock) {
-            return blocking;
-        }
+        return !nonBlocking;
     }
 
     public final Object blockingLock() {
@@ -281,12 +286,13 @@
         synchronized (regLock) {
             if (!isOpen())
                 throw new ClosedChannelException();
-            if (blocking == block)
-                return this;
-            if (block && haveValidKeys())
-                throw new IllegalBlockingModeException();
-            implConfigureBlocking(block);
-            blocking = block;
+            boolean blocking = !nonBlocking;
+            if (block != blocking) {
+                if (block && haveValidKeys())
+                    throw new IllegalBlockingModeException();
+                implConfigureBlocking(block);
+                nonBlocking = !block;
+            }
         }
         return this;
     }
--- a/src/share/classes/java/nio/charset/Charset.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/java/nio/charset/Charset.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -65,7 +65,7 @@
  * concurrent threads.
  *
  *
- * <a name="names"><a name="charenc">
+ * <a name="names"></a><a name="charenc"></a>
  * <h4>Charset names</h4>
  *
  * <p> Charsets are named by strings composed of the following characters:
@@ -111,21 +111,17 @@
  * The aliases of a charset are returned by the {@link #aliases() aliases}
  * method.
  *
- * <a name="hn">
- *
- * <p> Some charsets have an <i>historical name</i> that is defined for
- * compatibility with previous versions of the Java platform.  A charset's
+ * <p><a name="hn">Some charsets have an <i>historical name</i> that is defined for
+ * compatibility with previous versions of the Java platform.</a>  A charset's
  * historical name is either its canonical name or one of its aliases.  The
  * historical name is returned by the <tt>getEncoding()</tt> methods of the
  * {@link java.io.InputStreamReader#getEncoding InputStreamReader} and {@link
  * java.io.OutputStreamWriter#getEncoding OutputStreamWriter} classes.
  *
- * <a name="iana">
- *
- * <p> If a charset listed in the <a
+ * <p><a name="iana"> </a>If a charset listed in the <a
  * href="http://www.iana.org/assignments/character-sets"><i>IANA Charset
  * Registry</i></a> is supported by an implementation of the Java platform then
- * its canonical name must be the name listed in the registry.  Many charsets
+ * its canonical name must be the name listed in the registry. Many charsets
  * are given more than one name in the registry, in which case the registry
  * identifies one of the names as <i>MIME-preferred</i>.  If a charset has more
  * than one registry name then its canonical name must be the MIME-preferred
@@ -142,15 +138,15 @@
  *
  * <h4>Standard charsets</h4>
  *
- * <a name="standard">
+ *
  *
- * <p> Every implementation of the Java platform is required to support the
- * following standard charsets.  Consult the release documentation for your
+ * <p><a name="standard">Every implementation of the Java platform is required to support the
+ * following standard charsets.</a>  Consult the release documentation for your
  * implementation to see if any other charsets are supported.  The behavior
  * of such optional charsets may differ between implementations.
  *
  * <blockquote><table width="80%" summary="Description of standard charsets">
- * <tr><th><p align="left">Charset</p></th><th><p align="left">Description</p></th></tr>
+ * <tr><th align="left">Charset</th><th align="left">Description</th></tr>
  * <tr><td valign=top><tt>US-ASCII</tt></td>
  *     <td>Seven-bit ASCII, a.k.a. <tt>ISO646-US</tt>,
  *         a.k.a. the Basic Latin block of the Unicode character set</td></tr>
--- a/src/share/classes/java/nio/charset/MalformedInputException.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/java/nio/charset/MalformedInputException.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -42,14 +42,27 @@
 
     private int inputLength;
 
+    /**
+     * Constructs an {@code MalformedInputException} with the given
+     * length.
+     * @param inputLength the length of the input
+     */
     public MalformedInputException(int inputLength) {
         this.inputLength = inputLength;
     }
 
+    /**
+     * Returns the length of the input.
+     * @return the length of the input
+     */
     public int getInputLength() {
         return inputLength;
     }
 
+    /**
+     * Returns the message.
+     * @return the message
+     */
     public String getMessage() {
         return "Input length = " + inputLength;
     }
--- a/src/share/classes/java/nio/charset/UnmappableCharacterException.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/java/nio/charset/UnmappableCharacterException.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -42,14 +42,27 @@
 
     private int inputLength;
 
+    /**
+     * Constructs an {@code UnmappableCharacterException} with the
+     * given length.
+     * @param inputLength the length of the input
+     */
     public UnmappableCharacterException(int inputLength) {
         this.inputLength = inputLength;
     }
 
+    /**
+     * Returns the length of the input.
+     * @return the length of the input
+     */
     public int getInputLength() {
         return inputLength;
     }
 
+    /**
+     * Returns the message.
+     * @return the message
+     */
     public String getMessage() {
         return "Input length = " + inputLength;
     }
--- a/src/share/classes/java/nio/file/FileSystem.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/java/nio/file/FileSystem.java	Thu Feb 06 01:43:16 2020 +0000
@@ -325,7 +325,6 @@
      *   <td>Matches file names containing a dot</td>
      * </tr>
      * <tr>
-     * <tr>
      *   <td>{@code *.{java,class}}</td>
      *   <td>Matches file names ending with {@code .java} or {@code .class}</td>
      * </tr>
--- a/src/share/classes/java/nio/file/Files.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/java/nio/file/Files.java	Thu Feb 06 01:43:16 2020 +0000
@@ -240,7 +240,7 @@
      *   written synchronously to the underlying storage device. (see <a
      *   href="package-summary.html#integrity"> Synchronized I/O file
      *   integrity</a>). </td>
-     * <tr>
+     * </tr>
      * <tr>
      *   <td> {@link StandardOpenOption#DSYNC DSYNC} </td>
      *   <td> Requires that every update to the file's content be written
@@ -3201,8 +3201,8 @@
         // ensure lines is not null before opening file
         Objects.requireNonNull(lines);
         CharsetEncoder encoder = cs.newEncoder();
-        OutputStream out = newOutputStream(path, options);
-        try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out, encoder))) {
+        try (OutputStream out = newOutputStream(path, options);
+             BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out, encoder))) {
             for (CharSequence line: lines) {
                 writer.append(line);
                 writer.newLine();
--- a/src/share/classes/java/nio/file/package-info.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/java/nio/file/package-info.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -33,8 +33,8 @@
  * package is used by service provider implementors wishing to extend the
  * platform default provider, or to construct other provider implementations. </p>
  *
- * <a name="links"><h3>Symbolic Links</h3></a>
- * Many operating systems and file systems support for <em>symbolic links</em>.
+ * <h3><a name="links">Symbolic Links</a></h3>
+ * <p> Many operating systems and file systems support for <em>symbolic links</em>.
  * A symbolic link is a special file that serves as a reference to another file.
  * For the most part, symbolic links are transparent to applications and
  * operations on symbolic links are automatically redirected to the <em>target</em>
@@ -45,8 +45,8 @@
  * that are semantically close but support for these other types of links is
  * not included in this package. </p>
  *
- * <a name="interop"><h3>Interoperability</h3></a>
- * The {@link java.io.File} class defines the {@link java.io.File#toPath
+ * <h3><a name="interop">Interoperability</a></h3>
+ * <p> The {@link java.io.File} class defines the {@link java.io.File#toPath
  * toPath} method to construct a {@link java.nio.file.Path} by converting
  * the abstract path represented by the {@code java.io.File} object. The resulting
  * {@code Path} can be used to operate on the same file as the {@code File}
@@ -55,7 +55,7 @@
  * and {@code java.io.File} objects. </p>
  *
  * <h3>Visibility</h3>
- * The view of the files and file system provided by classes in this package are
+ * <p> The view of the files and file system provided by classes in this package are
  * guaranteed to be consistent with other views provided by other instances in the
  * same Java virtual machine.  The view may or may not, however, be consistent with
  * the view of the file system as seen by other concurrently running programs due
@@ -65,8 +65,8 @@
  * or on some other machine.  The exact nature of any such inconsistencies are
  * system-dependent and are therefore unspecified. </p>
  *
- * <a name="integrity"><h3>Synchronized I/O File Integrity</h3></a>
- * The {@link java.nio.file.StandardOpenOption#SYNC SYNC} and {@link
+ * <h3><a name="integrity">Synchronized I/O File Integrity</a></h3>
+ * <p> The {@link java.nio.file.StandardOpenOption#SYNC SYNC} and {@link
  * java.nio.file.StandardOpenOption#DSYNC DSYNC} options are used when opening a file
  * to require that updates to the file are written synchronously to the underlying
  * storage device. In the case of the default provider, and the file resides on
@@ -83,7 +83,7 @@
  * specific. </p>
  *
  * <h3>General Exceptions</h3>
- * Unless otherwise noted, passing a {@code null} argument to a constructor
+ * <p> Unless otherwise noted, passing a {@code null} argument to a constructor
  * or method of any class or interface in this package will cause a {@link
  * java.lang.NullPointerException NullPointerException} to be thrown. Additionally,
  * invoking a method with a collection containing a {@code null} element will
--- a/src/share/classes/java/nio/package.html	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/java/nio/package.html	Thu Feb 06 01:43:16 2020 +0000
@@ -62,7 +62,7 @@
 implementations.
 
 
-<a name="buffers">
+<a name="buffers"> </a>
 
 <blockquote><table cellspacing=1 cellpadding=0 summary="Description of the various buffers">
   <tr><th><p align="left">Buffers</p></th><th><p align="left">Description</p></th></tr> 
@@ -115,7 +115,7 @@
   best effort to perform native I/O operations directly upon it.  </p></li>
 
   <li><p> A byte buffer can be created by {@link
-  java.nio.channels.FileChannel#map </code><i>mapping</i><code>} a region of a
+  java.nio.channels.FileChannel#map <i>mapping</i>} a region of a
   file directly into memory, in which case a few additional file-related
   operations defined in the {@link java.nio.MappedByteBuffer} class are
   available.  </p></li>
--- a/src/share/classes/java/rmi/server/RemoteObjectInvocationHandler.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/java/rmi/server/RemoteObjectInvocationHandler.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -29,6 +29,7 @@
 import java.lang.reflect.Method;
 import java.lang.reflect.Proxy;
 import java.rmi.Remote;
+import java.rmi.RemoteException;
 import java.rmi.UnexpectedException;
 import java.rmi.activation.Activatable;
 import java.security.PrivilegedAction;
@@ -224,6 +225,13 @@
                 throw new IllegalArgumentException(
                     "proxy not Remote instance");
             }
+
+            // Verify that the method is declared on an interface that extends Remote
+            Class<?> decl = method.getDeclaringClass();
+            if (!Remote.class.isAssignableFrom(decl)) {
+                throw new RemoteException("Method is not Remote: " + decl + "::" + method);
+            }
+
             return ref.invoke((Remote) proxy, method, args,
                               getMethodHash(method));
         } catch (Exception e) {
--- a/src/share/classes/java/security/CodeSource.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/java/security/CodeSource.java	Thu Feb 06 01:43:16 2020 +0000
@@ -564,7 +564,7 @@
                 cfs.put(certType, cf);
             }
             // parse the certificate
-            byte[] encoded = IOUtils.readNBytes(ois, ois.readInt());
+            byte[] encoded = IOUtils.readExactlyNBytes(ois, ois.readInt());
             ByteArrayInputStream bais = new ByteArrayInputStream(encoded);
             try {
                 certList.add(cf.generateCertificate(bais));
--- a/src/share/classes/java/security/Key.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/java/security/Key.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -63,7 +63,7 @@
  * </pre>
  *
  * For more information, see
- * <a href="http://www.ietf.org/rfc/rfc3280.txt">RFC 3280:
+ * <a href="http://tools.ietf.org/html/rfc5280">RFC 5280:
  * Internet X.509 Public Key Infrastructure Certificate and CRL Profile</a>.
  *
  * <LI>A Format
--- a/src/share/classes/java/security/UnresolvedPermission.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/java/security/UnresolvedPermission.java	Thu Feb 06 01:43:16 2020 +0000
@@ -590,7 +590,7 @@
                 cfs.put(certType, cf);
             }
             // parse the certificate
-            byte[] encoded = IOUtils.readNBytes(ois, ois.readInt());
+            byte[] encoded = IOUtils.readExactlyNBytes(ois, ois.readInt());
             ByteArrayInputStream bais = new ByteArrayInputStream(encoded);
             try {
                 certList.add(cf.generateCertificate(bais));
--- a/src/share/classes/java/security/cert/CRLReason.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/java/security/cert/CRLReason.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,8 +27,8 @@
 
 /**
  * The CRLReason enumeration specifies the reason that a certificate
- * is revoked, as defined in <a href="http://www.ietf.org/rfc/rfc3280.txt">
- * RFC 3280: Internet X.509 Public Key Infrastructure Certificate and CRL
+ * is revoked, as defined in <a href="http://tools.ietf.org/html/rfc5280">
+ * RFC 5280: Internet X.509 Public Key Infrastructure Certificate and CRL
  * Profile</a>.
  *
  * @author Sean Mullan
--- a/src/share/classes/java/security/cert/CertificateRevokedException.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/java/security/cert/CertificateRevokedException.java	Thu Feb 06 01:43:16 2020 +0000
@@ -239,7 +239,7 @@
         for (int i = 0; i < size; i++) {
             String oid = (String) ois.readObject();
             boolean critical = ois.readBoolean();
-            byte[] extVal = IOUtils.readNBytes(ois, ois.readInt());
+            byte[] extVal = IOUtils.readExactlyNBytes(ois, ois.readInt());
             Extension ext = sun.security.x509.Extension.newExtension
                 (new ObjectIdentifier(oid), critical, extVal);
             extensions.put(oid, ext);
--- a/src/share/classes/java/security/cert/PKIXReason.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/java/security/cert/PKIXReason.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,7 +28,7 @@
 /**
  * The {@code PKIXReason} enumerates the potential PKIX-specific reasons
  * that an X.509 certification path may be invalid according to the PKIX
- * (RFC 3280) standard. These reasons are in addition to those of the
+ * (RFC 5280) standard. These reasons are in addition to those of the
  * {@code CertPathValidatorException.BasicReason} enumeration.
  *
  * @since 1.7
--- a/src/share/classes/java/security/cert/TrustAnchor.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/java/security/cert/TrustAnchor.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -78,7 +78,7 @@
      * The name constraints are specified as a byte array. This byte array
      * should contain the DER encoded form of the name constraints, as they
      * would appear in the NameConstraints structure defined in
-     * <a href="http://www.ietf.org/rfc/rfc3280">RFC 3280</a>
+     * <a href="http://tools.ietf.org/html/rfc5280">RFC 5280</a>
      * and X.509. The ASN.1 definition of this structure appears below.
      *
      * <pre>{@code
@@ -140,7 +140,7 @@
      * <p>
      * The name constraints are specified as a byte array. This byte array
      * contains the DER encoded form of the name constraints, as they
-     * would appear in the NameConstraints structure defined in RFC 3280
+     * would appear in the NameConstraints structure defined in RFC 5280
      * and X.509. The ASN.1 notation for this structure is supplied in the
      * documentation for
      * {@link #TrustAnchor(X509Certificate, byte[])
@@ -179,7 +179,7 @@
      * <p>
      * The name constraints are specified as a byte array. This byte array
      * contains the DER encoded form of the name constraints, as they
-     * would appear in the NameConstraints structure defined in RFC 3280
+     * would appear in the NameConstraints structure defined in RFC 5280
      * and X.509. The ASN.1 notation for this structure is supplied in the
      * documentation for
      * {@link #TrustAnchor(X509Certificate, byte[])
@@ -294,7 +294,7 @@
      * <p>
      * The name constraints are returned as a byte array. This byte array
      * contains the DER encoded form of the name constraints, as they
-     * would appear in the NameConstraints structure defined in RFC 3280
+     * would appear in the NameConstraints structure defined in RFC 5280
      * and X.509. The ASN.1 notation for this structure is supplied in the
      * documentation for
      * {@link #TrustAnchor(X509Certificate, byte[])
--- a/src/share/classes/java/security/cert/X509CRL.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/java/security/cert/X509CRL.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -68,7 +68,7 @@
  * </pre>
  * <p>
  * More information can be found in
- * <a href="http://www.ietf.org/rfc/rfc3280.txt">RFC 3280: Internet X.509
+ * <a href="http://tools.ietf.org/html/rfc5280">RFC 5280: Internet X.509
  * Public Key Infrastructure Certificate and CRL Profile</a>.
  * <p>
  * The ASN.1 definition of {@code tbsCertList} is:
--- a/src/share/classes/java/security/cert/X509CRLSelector.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/java/security/cert/X509CRLSelector.java	Thu Feb 06 01:43:16 2020 +0000
@@ -52,7 +52,7 @@
  * {@link CertStore#getCRLs CertStore.getCRLs} or some similar
  * method.
  * <p>
- * Please refer to <a href="http://www.ietf.org/rfc/rfc3280.txt">RFC 3280:
+ * Please refer to <a href="http://tools.ietf.org/html/rfc5280">RFC 5280:
  * Internet X.509 Public Key Infrastructure Certificate and CRL Profile</a>
  * for definitions of the X.509 CRL fields and extensions mentioned below.
  * <p>
--- a/src/share/classes/java/security/cert/X509CertSelector.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/java/security/cert/X509CertSelector.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -65,7 +65,7 @@
  * number. Other unique combinations include the issuer, subject,
  * subjectKeyIdentifier and/or the subjectPublicKey criteria.
  * <p>
- * Please refer to <a href="http://www.ietf.org/rfc/rfc3280.txt">RFC 3280:
+ * Please refer to <a href="http://tools.ietf.org/html/rfc5280">RFC 5280:
  * Internet X.509 Public Key Infrastructure Certificate and CRL Profile</a> for
  * definitions of the X.509 certificate extensions mentioned below.
  * <p>
@@ -728,7 +728,7 @@
      * The name is provided in string format.
      * <a href="http://www.ietf.org/rfc/rfc822.txt">RFC 822</a>, DNS, and URI
      * names use the well-established string formats for those types (subject to
-     * the restrictions included in RFC 3280). IPv4 address names are
+     * the restrictions included in RFC 5280). IPv4 address names are
      * supplied using dotted quad notation. OID address names are represented
      * as a series of nonnegative integers separated by periods. And
      * directory names (distinguished names) are supplied in RFC 2253 format.
@@ -746,7 +746,7 @@
      * String form of some distinguished names.
      *
      * @param type the name type (0-8, as specified in
-     *             RFC 3280, section 4.2.1.7)
+     *             RFC 5280, section 4.2.1.6)
      * @param name the name in string form (not {@code null})
      * @throws IOException if a parsing error occurs
      */
@@ -770,7 +770,7 @@
      * <p>
      * The name is provided as a byte array. This byte array should contain
      * the DER encoded name, as it would appear in the GeneralName structure
-     * defined in RFC 3280 and X.509. The encoded byte array should only contain
+     * defined in RFC 5280 and X.509. The encoded byte array should only contain
      * the encoded value of the name, and should not include the tag associated
      * with the name in the GeneralName structure. The ASN.1 definition of this
      * structure appears below.
@@ -806,7 +806,7 @@
      * must contain the specified subjectAlternativeName.
      *
      * @param type the name type (0-8, as specified in
-     *             RFC 3280, section 4.2.1.7)
+     *             RFC 5280, section 4.2.1.6)
      * @param name the name in string or byte array form
      * @throws IOException if a parsing error occurs
      */
@@ -995,7 +995,7 @@
      * <p>
      * The name constraints are specified as a byte array. This byte array
      * should contain the DER encoded form of the name constraints, as they
-     * would appear in the NameConstraints structure defined in RFC 3280
+     * would appear in the NameConstraints structure defined in RFC 5280
      * and X.509. The ASN.1 definition of this structure appears below.
      *
      * <pre>{@code
@@ -1197,7 +1197,7 @@
      * <p>
      * The name is provided in string format. RFC 822, DNS, and URI names
      * use the well-established string formats for those types (subject to
-     * the restrictions included in RFC 3280). IPv4 address names are
+     * the restrictions included in RFC 5280). IPv4 address names are
      * supplied using dotted quad notation. OID address names are represented
      * as a series of nonnegative integers separated by periods. And
      * directory names (distinguished names) are supplied in RFC 2253 format.
@@ -1214,7 +1214,7 @@
      * String form of some distinguished names.
      *
      * @param type the name type (0-8, as specified in
-     *             RFC 3280, section 4.2.1.7)
+     *             RFC 5280, section 4.2.1.6)
      * @param name the name in string form
      * @throws IOException if a parsing error occurs
      */
@@ -1234,7 +1234,7 @@
      * <p>
      * The name is provided as a byte array. This byte array should contain
      * the DER encoded name, as it would appear in the GeneralName structure
-     * defined in RFC 3280 and X.509. The ASN.1 definition of this structure
+     * defined in RFC 5280 and X.509. The ASN.1 definition of this structure
      * appears in the documentation for
      * {@link #addSubjectAlternativeName(int type, byte [] name)
      * addSubjectAlternativeName(int type, byte [] name)}.
@@ -1243,7 +1243,7 @@
      * subsequent modifications.
      *
      * @param type the name type (0-8, as specified in
-     *             RFC 3280, section 4.2.1.7)
+     *             RFC 5280, section 4.2.1.6)
      * @param name a byte array containing the name in ASN.1 DER encoded form
      * @throws IOException if a parsing error occurs
      */
@@ -1258,7 +1258,7 @@
      * the specified pathToName.
      *
      * @param type the name type (0-8, as specified in
-     *             RFC 3280, section 4.2.1.7)
+     *             RFC 5280, section 4.2.1.6)
      * @param name the name in string or byte array form
      * @throws IOException if an encoding error occurs (incorrect form for DN)
      */
@@ -1715,7 +1715,7 @@
      * <p>
      * The name constraints are returned as a byte array. This byte array
      * contains the DER encoded form of the name constraints, as they
-     * would appear in the NameConstraints structure defined in RFC 3280
+     * would appear in the NameConstraints structure defined in RFC 5280
      * and X.509. The ASN.1 notation for this structure is supplied in the
      * documentation for
      * {@link #setNameConstraints(byte [] bytes) setNameConstraints(byte [] bytes)}.
--- a/src/share/classes/java/security/cert/X509Certificate.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/java/security/cert/X509Certificate.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -64,7 +64,7 @@
  * CA such as a "root" CA.
  * <p>
  * More information can be found in
- * <a href="http://www.ietf.org/rfc/rfc3280.txt">RFC 3280: Internet X.509
+ * <a href="http://tools.ietf.org/html/rfc5280">RFC 5280: Internet X.509
  * Public Key Infrastructure Certificate and CRL Profile</a>.
  * <p>
  * The ASN.1 definition of {@code tbsCertificate} is:
@@ -404,7 +404,7 @@
      * Gets the {@code issuerUniqueID} value from the certificate.
      * The issuer unique identifier is present in the certificate
      * to handle the possibility of reuse of issuer names over time.
-     * RFC 3280 recommends that names not be reused and that
+     * RFC 5280 recommends that names not be reused and that
      * conforming certificates not make use of unique identifiers.
      * Applications conforming to that profile should be capable of
      * parsing unique identifiers and making comparisons.
@@ -453,7 +453,7 @@
      *     encipherOnly            (7),
      *     decipherOnly            (8) }
      * </pre>
-     * RFC 3280 recommends that when used, this be marked
+     * RFC 5280 recommends that when used, this be marked
      * as a critical extension.
      *
      * @return the KeyUsage extension of this certificate, represented as
@@ -566,7 +566,7 @@
      * <a href="http://www.ietf.org/rfc/rfc822.txt">RFC 822</a>, DNS, and URI
      * names are returned as {@code String}s,
      * using the well-established string formats for those types (subject to
-     * the restrictions included in RFC 3280). IPv4 address names are
+     * the restrictions included in RFC 5280). IPv4 address names are
      * returned using dotted quad notation. IPv6 address names are returned
      * in the form "a1:a2:...:a8", where a1-a8 are hexadecimal values
      * representing the eight 16-bit pieces of the address. OID names are
--- a/src/share/classes/java/util/jar/JarFile.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/java/util/jar/JarFile.java	Thu Feb 06 01:43:16 2020 +0000
@@ -387,7 +387,12 @@
      */
     private byte[] getBytes(ZipEntry ze) throws IOException {
         try (InputStream is = super.getInputStream(ze)) {
-            return IOUtils.readFully(is, (int)ze.getSize(), true);
+            int len = (int)ze.getSize();
+            byte[] b = IOUtils.readAllBytes(is);
+            if (len != -1 && b.length != len)
+                throw new EOFException("Expected:" + len + ", read:" + b.length);
+
+            return b;
         }
     }
 
--- a/src/share/classes/javax/security/auth/kerberos/KerberosTicket.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/javax/security/auth/kerberos/KerberosTicket.java	Thu Feb 06 01:43:16 2020 +0000
@@ -301,11 +301,7 @@
         } else
            this.flags = new boolean[NUM_FLAGS];
 
-        if (this.flags[RENEWABLE_TICKET_FLAG]) {
-           if (renewTill == null)
-                throw new IllegalArgumentException("The renewable period "
-                       + "end time cannot be null for renewable tickets.");
-
+        if (this.flags[RENEWABLE_TICKET_FLAG] && renewTill != null) {
            this.renewTill = new Date(renewTill.getTime());
         }
 
@@ -377,7 +373,7 @@
      * @return true if this ticket is forwardable, false if not.
      */
     public final boolean isForwardable() {
-        return flags[FORWARDABLE_TICKET_FLAG];
+        return flags == null? false: flags[FORWARDABLE_TICKET_FLAG];
     }
 
     /**
@@ -389,7 +385,7 @@
      * false otherwise.
      */
     public final boolean isForwarded() {
-        return flags[FORWARDED_TICKET_FLAG];
+        return flags == null? false: flags[FORWARDED_TICKET_FLAG];
     }
 
     /**
@@ -398,7 +394,7 @@
      * @return true if this ticket is proxiable, false if not.
      */
     public final boolean isProxiable() {
-        return flags[PROXIABLE_TICKET_FLAG];
+        return flags == null? false: flags[PROXIABLE_TICKET_FLAG];
     }
 
     /**
@@ -407,7 +403,7 @@
      * @return true if this ticket is a proxy-ticket, false if not.
      */
     public final boolean isProxy() {
-        return flags[PROXY_TICKET_FLAG];
+        return flags == null? false: flags[PROXY_TICKET_FLAG];
     }
 
 
@@ -417,7 +413,7 @@
      * @return true if this ticket is post-dated, false if not.
      */
     public final boolean isPostdated() {
-        return flags[POSTDATED_TICKET_FLAG];
+        return flags == null? false: flags[POSTDATED_TICKET_FLAG];
     }
 
     /**
@@ -428,7 +424,7 @@
      * @return true if this ticket is renewable, false if not.
      */
     public final boolean isRenewable() {
-        return flags[RENEWABLE_TICKET_FLAG];
+        return flags == null? false: flags[RENEWABLE_TICKET_FLAG];
     }
 
     /**
@@ -439,7 +435,7 @@
      * protocol, false if not.
      */
     public final boolean isInitial() {
-        return flags[INITIAL_TICKET_FLAG];
+        return flags == null? false: flags[INITIAL_TICKET_FLAG];
     }
 
     /**
@@ -479,7 +475,7 @@
      * @return the expiration time for this ticket's validity period.
      */
     public final java.util.Date getEndTime() {
-        return (Date) endTime.clone();
+        return (endTime == null) ? null : (Date) endTime.clone();
     }
 
     /**
@@ -515,7 +511,7 @@
 
     /** Determines if this ticket is still current.  */
     public boolean isCurrent() {
-        return (System.currentTimeMillis() <= getEndTime().getTime());
+        return endTime == null? false: (System.currentTimeMillis() <= endTime.getTime());
     }
 
     /**
@@ -546,6 +542,11 @@
         if (!isRenewable())
             throw new RefreshFailedException("This ticket is not renewable");
 
+        if (getRenewTill() == null) {
+            // Renewable ticket without renew-till. Illegal and ignored.
+            return;
+        }
+
         if (System.currentTimeMillis() > getRenewTill().getTime())
             throw new RefreshFailedException("This ticket is past "
                                              + "its last renewal time.");
--- a/src/share/classes/javax/security/auth/x500/X500Principal.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/javax/security/auth/x500/X500Principal.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -41,13 +41,13 @@
  * of the distinguished name, or by using the ASN.1 DER encoded byte
  * representation of the distinguished name.  The current specification
  * for the string representation of a distinguished name is defined in
- * <a href="http://www.ietf.org/rfc/rfc2253.txt">RFC 2253: Lightweight
+ * <a href="http://tools.ietf.org/html/rfc2253">RFC 2253: Lightweight
  * Directory Access Protocol (v3): UTF-8 String Representation of
  * Distinguished Names</a>. This class, however, accepts string formats from
- * both RFC 2253 and <a href="http://www.ietf.org/rfc/rfc1779.txt">RFC 1779:
+ * both RFC 2253 and <a href="http://tools.ietf.org/html/rfc1779">RFC 1779:
  * A String Representation of Distinguished Names</a>, and also recognizes
  * attribute type keywords whose OIDs (Object Identifiers) are defined in
- * <a href="http://www.ietf.org/rfc/rfc3280.txt">RFC 3280: Internet X.509
+ * <a href="http://tools.ietf.org/html/rfc5280">RFC 5280: Internet X.509
  * Public Key Infrastructure Certificate and CRL Profile</a>.
  *
  * <p> The string representation for this {@code X500Principal}
@@ -108,7 +108,7 @@
      * (and listed in {@link #getName(String format) getName(String format)}),
      * as well as the T, DNQ or DNQUALIFIER, SURNAME, GIVENNAME, INITIALS,
      * GENERATION, EMAILADDRESS, and SERIALNUMBER keywords whose OIDs are
-     * defined in RFC 3280 and its successor.
+     * defined in RFC 5280.
      * Any other attribute type must be specified as an OID.
      *
      * @param name an X.500 distinguished name in RFC 1779 or RFC 2253 format
@@ -442,7 +442,7 @@
      * (obtained via the {@code getName(X500Principal.CANONICAL)} method)
      * of this object and <i>o</i> are equal.
      *
-     * <p> This implementation is compliant with the requirements of RFC 3280.
+     * <p> This implementation is compliant with the requirements of RFC 5280.
      *
      * @param o Object to be compared for equality with this
      *          {@code X500Principal}
--- a/src/share/classes/javax/security/auth/x500/package-info.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/javax/security/auth/x500/package-info.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -31,15 +31,15 @@
  * <h2>Package Specification</h2>
  *
  * <ul>
- *   <li><a href="http://www.ietf.org/rfc/rfc1779.txt">
+ *   <li><a href="http://tools.ietf.org/html/rfc1779">
  *     RFC 1779: A String Representation of Distinguished Names</a></li>
- *   <li><a href="http://www.ietf.org/rfc/rfc2253.txt">
+ *   <li><a href="http://tools.ietf.org/html/rfc2253">
  *     RFC 2253: Lightweight Directory Access Protocol (v3):
  *     UTF-8 String Representation of Distinguished Names</a></li>
- *   <li><a href="http://www.ietf.org/rfc/rfc3280.txt">
- *     RFC 3280: Internet X.509 Public Key Infrastructure
+ *   <li><a href="http://tools.ietf.org/html/rfc5280">
+ *     RFC 5280: Internet X.509 Public Key Infrastructure
  *     Certificate and Certificate Revocation List (CRL) Profile</a></li>
- *   <li><a href="http://www.ietf.org/rfc/rfc4512.txt">
+ *   <li><a href="http://tools.ietf.org/html/rfc4512">
  *     RFC 4512: Lightweight Directory Access Protocol (LDAP):
  *     Directory Information Models</a></li>
  * </ul>
--- a/src/share/classes/javax/security/sasl/Sasl.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/javax/security/sasl/Sasl.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,15 +26,20 @@
 package javax.security.sasl;
 
 import javax.security.auth.callback.CallbackHandler;
-
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.ArrayList;
 import java.util.Enumeration;
 import java.util.Iterator;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.HashSet;
 import java.util.Collections;
 import java.security.Provider;
 import java.security.Security;
+import java.util.logging.Level;
+import java.util.logging.Logger;
 
 /**
  * A static class for creating SASL clients and servers.
@@ -62,6 +67,33 @@
  * @author Rob Weltman
  */
 public class Sasl {
+
+    private static List<String> disabledMechanisms = new ArrayList<>();
+
+    static {
+        String prop = AccessController.doPrivileged(new PrivilegedAction<String>() {
+            @Override
+            public String run() {
+                return Security.getProperty("jdk.sasl.disabledMechanisms");
+            }
+        });
+
+        if (prop != null) {
+            for (String s : prop.split("\\s*,\\s*")) {
+                if (!s.isEmpty()) {
+                    disabledMechanisms.add(s);
+                }
+            }
+        }
+    }
+
+    private static final String SASL_LOGGER_NAME = "javax.security.sasl";
+
+    /**
+     * Logger for debug messages
+     */
+    private static final Logger logger = Logger.getLogger(SASL_LOGGER_NAME);
+
     // Cannot create one of these
     private Sasl() {
     }
@@ -294,6 +326,9 @@
      * "Java Cryptography Architecture API Specification &amp; Reference"
      * for information about how to install and configure security service
      *  providers.
+     * <p>
+     * If a mechanism is listed in the {@code jdk.sasl.disabledMechanisms}
+     * security property, it will be ignored and won't be negotiated.
      *
      * @param mechanisms The non-null list of mechanism names to try. Each is the
      * IANA-registered name of a SASL mechanism. (e.g. "GSSAPI", "CRAM-MD5").
@@ -357,6 +392,10 @@
                     "Mechanism name cannot be null");
             } else if (mechName.length() == 0) {
                 continue;
+            } else if (isDisabled(mechName)) {
+                logger.log(Level.FINE,
+                        "Disabled " + mechName + " mechanism ignored");
+                continue;
             }
             String mechFilter = "SaslClientFactory." + mechName;
             Provider[] provs = Security.getProviders(mechFilter);
@@ -444,6 +483,9 @@
      * "Java Cryptography Architecture API Specification &amp; Reference"
      * for information about how to install and configure security
      * service providers.
+     * <p>
+     * If {@code mechanism} is listed in the {@code jdk.sasl.disabledMechanisms}
+     * security property, it will be ignored and this method returns {@code null}.
      *
      * @param mechanism The non-null mechanism name. It must be an
      * IANA-registered name of a SASL mechanism. (e.g. "GSSAPI", "CRAM-MD5").
@@ -494,6 +536,10 @@
             throw new NullPointerException("Mechanism name cannot be null");
         } else if (mechanism.length() == 0) {
             return null;
+        } else if (isDisabled(mechanism)) {
+            logger.log(Level.FINE,
+                    "Disabled " + mechanism + " mechanism ignored");
+            return null;
         }
 
         String mechFilter = "SaslServerFactory." + mechanism;
@@ -603,4 +649,8 @@
         }
         return Collections.unmodifiableSet(result);
     }
+
+    private static boolean isDisabled(String name) {
+        return disabledMechanisms.contains(name);
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/jdk/internal/util/StaticProperty.java	Thu Feb 06 01:43:16 2020 +0000
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.internal.util;
+
+/**
+ * System Property access for internal use only.
+ * Read-only access to System property values initialized during Phase 1
+ * are cached.  Setting, clearing, or modifying the value using
+ * {@link System#setProperty) or {@link System#getProperties()} is ignored.
+ * <strong>{@link SecurityManager#checkPropertyAccess} is NOT checked
+ * in these access methods. The caller of these methods should take care to ensure
+ * that the returned property is not made accessible to untrusted code.</strong>
+ */
+public final class StaticProperty {
+
+    // The class static initialization is triggered to initialize these final
+    // fields during init Phase 1 and before a security manager is set.
+    private static final String JDK_SERIAL_FILTER = System.getProperty("jdk.serialFilter");
+
+    private StaticProperty() {}
+
+    /**
+     *
+     * Return the {@code jdk.serialFilter} system property.
+     *
+     * <strong>{@link SecurityManager#checkPropertyAccess} is NOT checked
+     * in this method. The caller of this method should take care to ensure
+     * that the returned property is not made accessible to untrusted code.</strong>
+     *
+     * @return the {@code user.name} system property
+     */
+    public static String jdkSerialFilter() {
+        return JDK_SERIAL_FILTER;
+    }
+}
--- a/src/share/classes/sun/applet/AppletClassLoader.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/applet/AppletClassLoader.java	Thu Feb 06 01:43:16 2020 +0000
@@ -33,6 +33,7 @@
 import java.net.MalformedURLException;
 import java.net.InetAddress;
 import java.net.UnknownHostException;
+import java.io.EOFException;
 import java.io.File;
 import java.io.FilePermission;
 import java.io.IOException;
@@ -332,7 +333,9 @@
 
         byte[] b;
         try {
-            b = IOUtils.readFully(in, len, true);
+            b = IOUtils.readAllBytes(in);
+            if (len != -1 && b.length != len)
+                throw new EOFException("Expected:" + len + ", read:" + b.length);
         } finally {
             in.close();
         }
--- a/src/share/classes/sun/misc/IOUtils.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/misc/IOUtils.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -32,67 +32,282 @@
 import java.io.EOFException;
 import java.io.IOException;
 import java.io.InputStream;
+
+import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.List;
+import java.util.Objects;
 
 public class IOUtils {
 
+    private static final int DEFAULT_BUFFER_SIZE = 8192;
+
     /**
-     * Read up to {@code length} of bytes from {@code in}
-     * until EOF is detected.
+     * The maximum size of array to allocate.
+     * Some VMs reserve some header words in an array.
+     * Attempts to allocate larger arrays may result in
+     * OutOfMemoryError: Requested array size exceeds VM limit
+     */
+    private static final int MAX_BUFFER_SIZE = Integer.MAX_VALUE - 8;
+
+    /**
+     * Read exactly {@code length} of bytes from {@code in}.
+     *
+     * <p> Note that this method is safe to be called with unknown large
+     * {@code length} argument. The memory used is proportional to the
+     * actual bytes available. An exception is thrown if there are not
+     * enough bytes in the stream.
+     *
      * @param is input stream, must not be null
-     * @param length number of bytes to read, -1 or Integer.MAX_VALUE means
-     *        read as much as possible
-     * @param readAll if true, an EOFException will be thrown if not enough
-     *        bytes are read. Ignored when length is -1 or Integer.MAX_VALUE
+     * @param length number of bytes to read
      * @return bytes read
-     * @throws IOException Any IO error or a premature EOF is detected
+     * @throws EOFException if there are not enough bytes in the stream
+     * @throws IOException if an I/O error occurs or {@code length} is negative
+     * @throws OutOfMemoryError if an array of the required size cannot be
+     *         allocated.
      */
-    public static byte[] readFully(InputStream is, int length, boolean readAll)
+    public static byte[] readExactlyNBytes(InputStream is, int length)
             throws IOException {
-        byte[] output = {};
-        if (length == -1) length = Integer.MAX_VALUE;
-        int pos = 0;
-        while (pos < length) {
-            int bytesToRead;
-            if (pos >= output.length) { // Only expand when there's no room
-                bytesToRead = Math.min(length - pos, output.length + 1024);
-                if (output.length < pos + bytesToRead) {
-                    output = Arrays.copyOf(output, pos + bytesToRead);
-                }
-            } else {
-                bytesToRead = output.length - pos;
-            }
-            int cc = is.read(output, pos, bytesToRead);
-            if (cc < 0) {
-                if (readAll && length != Integer.MAX_VALUE) {
-                    throw new EOFException("Detect premature EOF");
-                } else {
-                    if (output.length != pos) {
-                        output = Arrays.copyOf(output, pos);
-                    }
-                    break;
-                }
-            }
-            pos += cc;
+        if (length < 0) {
+            throw new IOException("length cannot be negative: " + length);
+        }
+        byte[] data = readNBytes(is, length);
+        if (data.length < length) {
+            throw new EOFException();
         }
-        return output;
+        return data;
+    }
+
+    /**
+     * Reads all remaining bytes from the input stream. This method blocks until
+     * all remaining bytes have been read and end of stream is detected, or an
+     * exception is thrown. This method does not close the input stream.
+     *
+     * <p> When this stream reaches end of stream, further invocations of this
+     * method will return an empty byte array.
+     *
+     * <p> Note that this method is intended for simple cases where it is
+     * convenient to read all bytes into a byte array. It is not intended for
+     * reading input streams with large amounts of data.
+     *
+     * <p> The behavior for the case where the input stream is <i>asynchronously
+     * closed</i>, or the thread interrupted during the read, is highly input
+     * stream specific, and therefore not specified.
+     *
+     * <p> If an I/O error occurs reading from the input stream, then it may do
+     * so after some, but not all, bytes have been read. Consequently the input
+     * stream may not be at end of stream and may be in an inconsistent state.
+     * It is strongly recommended that the stream be promptly closed if an I/O
+     * error occurs.
+     *
+     * @implSpec
+     * This method invokes {@link #readNBytes(int)} with a length of
+     * {@link Integer#MAX_VALUE}.
+     *
+     * @param is input stream, must not be null
+     * @return a byte array containing the bytes read from this input stream
+     * @throws IOException if an I/O error occurs
+     * @throws OutOfMemoryError if an array of the required size cannot be
+     *         allocated.
+     *
+     * @since 1.9
+     */
+    public static byte[] readAllBytes(InputStream is) throws IOException {
+        return readNBytes(is, Integer.MAX_VALUE);
     }
 
     /**
-     * Read {@code length} of bytes from {@code in}. An exception is
-     * thrown if there are not enough bytes in the stream.
+     * Reads up to a specified number of bytes from the input stream. This
+     * method blocks until the requested number of bytes have been read, end
+     * of stream is detected, or an exception is thrown. This method does not
+     * close the input stream.
+     *
+     * <p> The length of the returned array equals the number of bytes read
+     * from the stream. If {@code len} is zero, then no bytes are read and
+     * an empty byte array is returned. Otherwise, up to {@code len} bytes
+     * are read from the stream. Fewer than {@code len} bytes may be read if
+     * end of stream is encountered.
+     *
+     * <p> When this stream reaches end of stream, further invocations of this
+     * method will return an empty byte array.
+     *
+     * <p> Note that this method is intended for simple cases where it is
+     * convenient to read the specified number of bytes into a byte array. The
+     * total amount of memory allocated by this method is proportional to the
+     * number of bytes read from the stream which is bounded by {@code len}.
+     * Therefore, the method may be safely called with very large values of
+     * {@code len} provided sufficient memory is available.
+     *
+     * <p> The behavior for the case where the input stream is <i>asynchronously
+     * closed</i>, or the thread interrupted during the read, is highly input
+     * stream specific, and therefore not specified.
+     *
+     * <p> If an I/O error occurs reading from the input stream, then it may do
+     * so after some, but not all, bytes have been read. Consequently the input
+     * stream may not be at end of stream and may be in an inconsistent state.
+     * It is strongly recommended that the stream be promptly closed if an I/O
+     * error occurs.
+     *
+     * @implNote
+     * The number of bytes allocated to read data from this stream and return
+     * the result is bounded by {@code 2*(long)len}, inclusive.
      *
      * @param is input stream, must not be null
-     * @param length number of bytes to read, must not be negative
+     * @param len the maximum number of bytes to read
+     * @return a byte array containing the bytes read from this input stream
+     * @throws IllegalArgumentException if {@code length} is negative
+     * @throws IOException if an I/O error occurs
+     * @throws OutOfMemoryError if an array of the required size cannot be
+     *         allocated.
+     *
+     * @since 11
+     */
+    public static byte[] readNBytes(InputStream is, int len) throws IOException {
+        if (len < 0) {
+            throw new IllegalArgumentException("len < 0");
+        }
+
+        List<byte[]> bufs = null;
+        byte[] result = null;
+        int total = 0;
+        int remaining = len;
+        int n;
+        do {
+            byte[] buf = new byte[Math.min(remaining, DEFAULT_BUFFER_SIZE)];
+            int nread = 0;
+
+            // read to EOF which may read more or less than buffer size
+            while ((n = is.read(buf, nread,
+                    Math.min(buf.length - nread, remaining))) > 0) {
+                nread += n;
+                remaining -= n;
+            }
+
+            if (nread > 0) {
+                if (MAX_BUFFER_SIZE - total < nread) {
+                    throw new OutOfMemoryError("Required array size too large");
+                }
+                total += nread;
+                if (result == null) {
+                    result = buf;
+                } else {
+                    if (bufs == null) {
+                        bufs = new ArrayList<>();
+                        bufs.add(result);
+                    }
+                    bufs.add(buf);
+                }
+            }
+            // if the last call to read returned -1 or the number of bytes
+            // requested have been read then break
+        } while (n >= 0 && remaining > 0);
+
+        if (bufs == null) {
+            if (result == null) {
+                return new byte[0];
+            }
+            return result.length == total ?
+                result : Arrays.copyOf(result, total);
+        }
+
+        result = new byte[total];
+        int offset = 0;
+        remaining = total;
+        for (byte[] b : bufs) {
+            int count = Math.min(b.length, remaining);
+            System.arraycopy(b, 0, result, offset, count);
+            offset += count;
+            remaining -= count;
+        }
+
+        return result;
+    }
+
+    /**
+     * Reads the requested number of bytes from the input stream into the given
+     * byte array. This method blocks until {@code len} bytes of input data have
+     * been read, end of stream is detected, or an exception is thrown. The
+     * number of bytes actually read, possibly zero, is returned. This method
+     * does not close the input stream.
+     *
+     * <p> In the case where end of stream is reached before {@code len} bytes
+     * have been read, then the actual number of bytes read will be returned.
+     * When this stream reaches end of stream, further invocations of this
+     * method will return zero.
+     *
+     * <p> If {@code len} is zero, then no bytes are read and {@code 0} is
+     * returned; otherwise, there is an attempt to read up to {@code len} bytes.
+     *
+     * <p> The first byte read is stored into element {@code b[off]}, the next
+     * one in to {@code b[off+1]}, and so on. The number of bytes read is, at
+     * most, equal to {@code len}. Let <i>k</i> be the number of bytes actually
+     * read; these bytes will be stored in elements {@code b[off]} through
+     * {@code b[off+}<i>k</i>{@code -1]}, leaving elements {@code b[off+}<i>k</i>
+     * {@code ]} through {@code b[off+len-1]} unaffected.
+     *
+     * <p> The behavior for the case where the input stream is <i>asynchronously
+     * closed</i>, or the thread interrupted during the read, is highly input
+     * stream specific, and therefore not specified.
+     *
+     * <p> If an I/O error occurs reading from the input stream, then it may do
+     * so after some, but not all, bytes of {@code b} have been updated with
+     * data from the input stream. Consequently the input stream and {@code b}
+     * may be in an inconsistent state. It is strongly recommended that the
+     * stream be promptly closed if an I/O error occurs.
+     *
+     * @param  is input stream, must not be null
+     * @param  b the byte array into which the data is read
+     * @param  off the start offset in {@code b} at which the data is written
+     * @param  len the maximum number of bytes to read
+     * @return the actual number of bytes read into the buffer
+     * @throws IOException if an I/O error occurs
+     * @throws NullPointerException if {@code b} is {@code null}
+     * @throws IndexOutOfBoundsException If {@code off} is negative, {@code len}
+     *         is negative, or {@code len} is greater than {@code b.length - off}
+     *
+     * @since 1.9
+     */
+    public static int readNBytes(InputStream is, byte[] b, int off, int len) throws IOException {
+        Objects.requireNonNull(b);
+        if (off < 0 || len < 0 || len > b.length - off)
+            throw new IndexOutOfBoundsException();
+        int n = 0;
+        while (n < len) {
+            int count = is.read(b, off + n, len - n);
+            if (count < 0)
+                break;
+            n += count;
+        }
+        return n;
+    }
+
+    /**
+     * Compatibility wrapper for third party users of
+     * {@code sun.misc.IOUtils.readFully} following its
+     * removal in JDK-8231139.
+     *
+     * Read up to {@code length} of bytes from {@code in}
+     * until EOF is detected.
+     *
+     * @param is input stream, must not be null
+     * @param length number of bytes to read
+     * @param readAll if true, an EOFException will be thrown if not enough
+     *        bytes are read.
      * @return bytes read
-     * @throws IOException if any IO error or a premature EOF is detected, or
-     *      if {@code length} is negative since this length is usually also
-     *      read from {@code is}.
+     * @throws EOFException if there are not enough bytes in the stream
+     * @throws IOException if an I/O error occurs or {@code length} is negative
+     * @throws OutOfMemoryError if an array of the required size cannot be
+     *         allocated.
      */
-    public static byte[] readNBytes(InputStream is, int length) throws IOException {
+    public static byte[] readFully(InputStream is, int length, boolean readAll)
+             throws IOException {
         if (length < 0) {
             throw new IOException("length cannot be negative: " + length);
         }
-        return readFully(is, length, true);
+        if (readAll) {
+            return readExactlyNBytes(is, length);
+        } else {
+            return readNBytes(is, length);
+        }
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/sun/misc/JavaObjectInputStreamReadString.java	Thu Feb 06 01:43:16 2020 +0000
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.misc;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+
+/**
+ * Interface to specify methods for accessing {@code ObjectInputStream}.
+ */
+public interface JavaObjectInputStreamReadString {
+    String readString(ObjectInputStream ois) throws IOException;
+}
+
--- a/src/share/classes/sun/misc/ObjectInputFilter.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/misc/ObjectInputFilter.java	Thu Feb 06 01:43:16 2020 +0000
@@ -36,6 +36,8 @@
 
 import sun.util.logging.PlatformLogger;
 
+import jdk.internal.util.StaticProperty;
+
 /**
  * Filter classes, array lengths, and graph metrics during deserialization.
  * If set on an {@link ObjectInputStream}, the {@link #checkInput checkInput(FilterInfo)}
@@ -247,7 +249,7 @@
                     .doPrivileged(new PrivilegedAction<ObjectInputFilter>() {
                         @Override
                         public ObjectInputFilter run() {
-                            String props = System.getProperty(SERIAL_FILTER_PROPNAME);
+                            String props = StaticProperty.jdkSerialFilter();
                             if (props == null) {
                                 props = Security.getProperty(SERIAL_FILTER_PROPNAME);
                             }
--- a/src/share/classes/sun/misc/SharedSecrets.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/misc/SharedSecrets.java	Thu Feb 06 01:43:16 2020 +0000
@@ -67,6 +67,7 @@
     private static JavaUtilCalendarAccess javaUtilCalendarAccess;
     private static JavaSecurityKeyStoreAccess javaSecurityKeyStoreAccess;
     private static JavaxCryptoSealedObjectAccess javaxCryptoSealedObjectAccess;
+    private static JavaObjectInputStreamReadString javaObjectInputStreamReadString;
 
     public static JavaUtilJarAccess javaUtilJarAccess() {
         if (javaUtilJarAccess == null) {
@@ -233,6 +234,17 @@
         return javaxCryptoSealedObjectAccess;
     }
 
+    public static JavaObjectInputStreamReadString getJavaObjectInputStreamReadString() {
+        if (javaObjectInputStreamReadString == null) {
+            unsafe.ensureClassInitialized(ObjectInputStream.class);
+        }
+        return javaObjectInputStreamReadString;
+    }
+
+    public static void setJavaObjectInputStreamReadString(JavaObjectInputStreamReadString access) {
+        javaObjectInputStreamReadString = access;
+    }
+
     public static JavaObjectInputStreamAccess getJavaObjectInputStreamAccess() {
         if (javaObjectInputStreamAccess == null) {
             unsafe.ensureClassInitialized(ObjectInputStream.class);
--- a/src/share/classes/sun/nio/ch/AbstractPollArrayWrapper.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/nio/ch/AbstractPollArrayWrapper.java	Thu Feb 06 01:43:16 2020 +0000
@@ -37,14 +37,6 @@
 
 abstract class AbstractPollArrayWrapper {
 
-    // Event masks
-    static final short POLLIN       = 0x0001;
-    static final short POLLOUT      = 0x0004;
-    static final short POLLERR      = 0x0008;
-    static final short POLLHUP      = 0x0010;
-    static final short POLLNVAL     = 0x0020;
-    static final short POLLREMOVE   = 0x0800;
-
     // Miscellaneous constants
     static final short SIZE_POLLFD   = 8;
     static final short FD_OFFSET     = 0;
--- a/src/share/classes/sun/nio/ch/DatagramChannelImpl.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/nio/ch/DatagramChannelImpl.java	Thu Feb 06 01:43:16 2020 +0000
@@ -50,9 +50,6 @@
 
     // Our file descriptor
     private final FileDescriptor fd;
-
-    // fd value needed for dev/poll. This value will remain valid
-    // even after the value in the file descriptor object has been set to -1
     private final int fdVal;
 
     // The protocol family of the socket
@@ -104,7 +101,6 @@
 
     // -- End of fields protected by stateLock
 
-
     public DatagramChannelImpl(SelectorProvider sp)
         throws IOException
     {
@@ -139,16 +135,27 @@
                 throw new UnsupportedOperationException("IPv6 not available");
             }
         }
-        this.family = family;
-        this.fd = Net.socket(family, false);
-        this.fdVal = IOUtil.fdVal(fd);
-        this.state = ST_UNCONNECTED;
+
+        ResourceManager.beforeUdpCreate();
+        try {
+            this.family = family;
+            this.fd = Net.socket(family, false);
+            this.fdVal = IOUtil.fdVal(fd);
+            this.state = ST_UNCONNECTED;
+        } catch (IOException ioe) {
+            ResourceManager.afterUdpClose();
+            throw ioe;
+        }
     }
 
     public DatagramChannelImpl(SelectorProvider sp, FileDescriptor fd)
         throws IOException
     {
         super(sp);
+
+        // increment UDP count to match decrement when closing
+        ResourceManager.beforeUdpCreate();
+
         this.family = Net.isIPv6Available() ?
             StandardProtocolFamily.INET6 : StandardProtocolFamily.INET;
         this.fd = fd;
@@ -742,10 +749,9 @@
                     localAddress = Net.localAddress(fd);
 
                     // flush any packets already received.
-                    boolean blocking = false;
                     synchronized (blockingLock()) {
+                        boolean blocking = isBlocking();
                         try {
-                            blocking = isBlocking();
                             // remainder of each packet thrown away
                             ByteBuffer tmpBuf = ByteBuffer.allocate(1);
                             if (blocking) {
@@ -1051,25 +1057,24 @@
         int oldOps = sk.nioReadyOps();
         int newOps = initialOps;
 
-        if ((ops & PollArrayWrapper.POLLNVAL) != 0) {
+        if ((ops & Net.POLLNVAL) != 0) {
             // This should only happen if this channel is pre-closed while a
             // selection operation is in progress
             // ## Throw an error if this channel has not been pre-closed
             return false;
         }
 
-        if ((ops & (PollArrayWrapper.POLLERR
-                    | PollArrayWrapper.POLLHUP)) != 0) {
+        if ((ops & (Net.POLLERR | Net.POLLHUP)) != 0) {
             newOps = intOps;
             sk.nioReadyOps(newOps);
             return (newOps & ~oldOps) != 0;
         }
 
-        if (((ops & PollArrayWrapper.POLLIN) != 0) &&
+        if (((ops & Net.POLLIN) != 0) &&
             ((intOps & SelectionKey.OP_READ) != 0))
             newOps |= SelectionKey.OP_READ;
 
-        if (((ops & PollArrayWrapper.POLLOUT) != 0) &&
+        if (((ops & Net.POLLOUT) != 0) &&
             ((intOps & SelectionKey.OP_WRITE) != 0))
             newOps |= SelectionKey.OP_WRITE;
 
@@ -1085,6 +1090,28 @@
         return translateReadyOps(ops, 0, sk);
     }
 
+    // package-private
+    int poll(int events, long timeout) throws IOException {
+        assert Thread.holdsLock(blockingLock()) && !isBlocking();
+
+        synchronized (readLock) {
+            int n = 0;
+            try {
+                begin();
+                synchronized (stateLock) {
+                    if (!isOpen())
+                        return 0;
+                    readerThread = NativeThread.current();
+                }
+                n = Net.poll(fd, events, timeout);
+            } finally {
+                readerThread = 0;
+                end(n > 0);
+            }
+            return n;
+        }
+    }
+
     /**
      * Translates an interest operation set into a native poll event set
      */
@@ -1092,11 +1119,11 @@
         int newOps = 0;
 
         if ((ops & SelectionKey.OP_READ) != 0)
-            newOps |= PollArrayWrapper.POLLIN;
+            newOps |= Net.POLLIN;
         if ((ops & SelectionKey.OP_WRITE) != 0)
-            newOps |= PollArrayWrapper.POLLOUT;
+            newOps |= Net.POLLOUT;
         if ((ops & SelectionKey.OP_CONNECT) != 0)
-            newOps |= PollArrayWrapper.POLLIN;
+            newOps |= Net.POLLIN;
         sk.selector.putEventOps(sk, newOps);
     }
 
--- a/src/share/classes/sun/nio/ch/DatagramSocketAdaptor.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/nio/ch/DatagramSocketAdaptor.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,10 +25,22 @@
 
 package sun.nio.ch;
 
-import java.io.*;
-import java.net.*;
-import java.nio.*;
-import java.nio.channels.*;
+import java.io.IOException;
+import java.net.DatagramPacket;
+import java.net.DatagramSocket;
+import java.net.DatagramSocketImpl;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.NetworkInterface;
+import java.net.SocketAddress;
+import java.net.SocketException;
+import java.net.SocketOption;
+import java.net.SocketTimeoutException;
+import java.net.StandardSocketOptions;
+import java.nio.ByteBuffer;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.DatagramChannel;
+import java.nio.channels.IllegalBlockingModeException;
 
 
 // Make a datagram-socket channel look like a datagram socket.
@@ -176,40 +188,29 @@
             return dc.receive(bb);
         }
 
-        // Implement timeout with a selector
-        SelectionKey sk = null;
-        Selector sel = null;
         dc.configureBlocking(false);
         try {
-            int n;
             SocketAddress sender;
             if ((sender = dc.receive(bb)) != null)
                 return sender;
-            sel = Util.getTemporarySelector(dc);
-            sk = dc.register(sel, SelectionKey.OP_READ);
             long to = timeout;
             for (;;) {
                 if (!dc.isOpen())
                      throw new ClosedChannelException();
                 long st = System.currentTimeMillis();
-                int ns = sel.select(to);
-                if (ns > 0 && sk.isReadable()) {
+                int result = dc.poll(Net.POLLIN, to);
+                if (result > 0 && ((result & Net.POLLIN) != 0)) {
                     if ((sender = dc.receive(bb)) != null)
                         return sender;
                 }
-                sel.selectedKeys().remove(sk);
                 to -= System.currentTimeMillis() - st;
                 if (to <= 0)
                     throw new SocketTimeoutException();
-
             }
         } finally {
-            if (sk != null)
-                sk.cancel();
-            if (dc.isOpen())
+            try {
                 dc.configureBlocking(true);
-            if (sel != null)
-                Util.releaseTemporarySelector(sel);
+            } catch (ClosedChannelException e) { }
         }
     }
 
--- a/src/share/classes/sun/nio/ch/Net.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/nio/ch/Net.java	Thu Feb 06 01:43:16 2020 +0000
@@ -529,6 +529,9 @@
                                              int level, int opt, int arg, boolean isIPv6)
         throws IOException;
 
+    static native int poll(FileDescriptor fd, int events, long timeout)
+        throws IOException;
+
     // -- Multicast support --
 
 
@@ -627,9 +630,34 @@
 
     private static native void initIDs();
 
+    /**
+     * Event masks for the various poll system calls.
+     * They will be set platform dependant in the static initializer below.
+     */
+    public static final short POLLIN;
+    public static final short POLLOUT;
+    public static final short POLLERR;
+    public static final short POLLHUP;
+    public static final short POLLNVAL;
+    public static final short POLLCONN;
+
+    static native short pollinValue();
+    static native short polloutValue();
+    static native short pollerrValue();
+    static native short pollhupValue();
+    static native short pollnvalValue();
+    static native short pollconnValue();
+
     static {
         IOUtil.load();
         initIDs();
+
+        POLLIN     = pollinValue();
+        POLLOUT    = polloutValue();
+        POLLERR    = pollerrValue();
+        POLLHUP    = pollhupValue();
+        POLLNVAL   = pollnvalValue();
+        POLLCONN   = pollconnValue();
     }
 
     static {
--- a/src/share/classes/sun/nio/ch/ServerSocketAdaptor.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/nio/ch/ServerSocketAdaptor.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,9 +25,20 @@
 
 package sun.nio.ch;
 
-import java.io.*;
-import java.net.*;
-import java.nio.channels.*;
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.SocketAddress;
+import java.net.SocketException;
+import java.net.SocketTimeoutException;
+import java.net.StandardSocketOptions;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.IllegalBlockingModeException;
+import java.nio.channels.NotYetBoundException;
+import java.nio.channels.ServerSocketChannel;
+import java.nio.channels.SocketChannel;
 
 
 // Make a server-socket channel look like a server socket.
@@ -37,7 +48,7 @@
 // class.
 //
 
-public class ServerSocketAdaptor                        // package-private
+class ServerSocketAdaptor                        // package-private
     extends ServerSocket
 {
 
@@ -97,45 +108,38 @@
                 throw new IllegalBlockingModeException();
             try {
                 if (timeout == 0) {
+                    // for compatibility reasons: accept connection if available
+                    // when configured non-blocking
                     SocketChannel sc = ssc.accept();
                     if (sc == null && !ssc.isBlocking())
                         throw new IllegalBlockingModeException();
                     return sc.socket();
                 }
 
-                // Implement timeout with a selector
-                SelectionKey sk = null;
-                Selector sel = null;
+                if (!ssc.isBlocking())
+                    throw new IllegalBlockingModeException();
                 ssc.configureBlocking(false);
                 try {
                     SocketChannel sc;
                     if ((sc = ssc.accept()) != null)
                         return sc.socket();
-                    sel = Util.getTemporarySelector(ssc);
-                    sk = ssc.register(sel, SelectionKey.OP_ACCEPT);
                     long to = timeout;
                     for (;;) {
                         if (!ssc.isOpen())
                             throw new ClosedChannelException();
                         long st = System.currentTimeMillis();
-                        int ns = sel.select(to);
-                        if (ns > 0 &&
-                            sk.isAcceptable() && ((sc = ssc.accept()) != null))
+                        int result = ssc.poll(Net.POLLIN, to);
+                        if (result > 0 && ((sc = ssc.accept()) != null))
                             return sc.socket();
-                        sel.selectedKeys().remove(sk);
                         to -= System.currentTimeMillis() - st;
                         if (to <= 0)
                             throw new SocketTimeoutException();
                     }
                 } finally {
-                    if (sk != null)
-                        sk.cancel();
-                    if (ssc.isOpen())
+                    try {
                         ssc.configureBlocking(true);
-                    if (sel != null)
-                        Util.releaseTemporarySelector(sel);
+                    } catch (ClosedChannelException e) { }
                 }
-
             } catch (Exception x) {
                 Net.translateException(x);
                 assert false;
@@ -189,8 +193,7 @@
         if (!isBound())
             return "ServerSocket[unbound]";
         return "ServerSocket[addr=" + getInetAddress() +
-            //          ",port=" + getPort() +
-                ",localport=" + getLocalPort()  + "]";
+               ",localport=" + getLocalPort()  + "]";
     }
 
     public void setReceiveBufferSize(int size) throws SocketException {
--- a/src/share/classes/sun/nio/ch/ServerSocketChannelImpl.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/nio/ch/ServerSocketChannelImpl.java	Thu Feb 06 01:43:16 2020 +0000
@@ -48,10 +48,7 @@
 
     // Our file descriptor
     private final FileDescriptor fd;
-
-    // fd value needed for dev/poll. This value will remain valid
-    // even after the value in the file descriptor object has been set to -1
-    private int fdVal;
+    private final int fdVal;
 
     // ID of native thread currently blocked in this channel, for signalling
     private volatile long thread = 0;
@@ -318,21 +315,20 @@
         int oldOps = sk.nioReadyOps();
         int newOps = initialOps;
 
-        if ((ops & PollArrayWrapper.POLLNVAL) != 0) {
+        if ((ops & Net.POLLNVAL) != 0) {
             // This should only happen if this channel is pre-closed while a
             // selection operation is in progress
             // ## Throw an error if this channel has not been pre-closed
             return false;
         }
 
-        if ((ops & (PollArrayWrapper.POLLERR
-                    | PollArrayWrapper.POLLHUP)) != 0) {
+        if ((ops & (Net.POLLERR | Net.POLLHUP)) != 0) {
             newOps = intOps;
             sk.nioReadyOps(newOps);
             return (newOps & ~oldOps) != 0;
         }
 
-        if (((ops & PollArrayWrapper.POLLIN) != 0) &&
+        if (((ops & Net.POLLIN) != 0) &&
             ((intOps & SelectionKey.OP_ACCEPT) != 0))
                 newOps |= SelectionKey.OP_ACCEPT;
 
@@ -348,6 +344,28 @@
         return translateReadyOps(ops, 0, sk);
     }
 
+    // package-private
+    int poll(int events, long timeout) throws IOException {
+        assert Thread.holdsLock(blockingLock()) && !isBlocking();
+
+        synchronized (lock) {
+            int n = 0;
+            try {
+                begin();
+                synchronized (stateLock) {
+                    if (!isOpen())
+                        return 0;
+                    thread = NativeThread.current();
+                }
+                n = Net.poll(fd, events, timeout);
+            } finally {
+                thread = 0;
+                end(n > 0);
+            }
+            return n;
+        }
+    }
+
     /**
      * Translates an interest operation set into a native poll event set
      */
@@ -356,7 +374,7 @@
 
         // Translate ops
         if ((ops & SelectionKey.OP_ACCEPT) != 0)
-            newOps |= PollArrayWrapper.POLLIN;
+            newOps |= Net.POLLIN;
         // Place ops into pollfd array
         sk.selector.putEventOps(sk, newOps);
     }
--- a/src/share/classes/sun/nio/ch/SocketAdaptor.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/nio/ch/SocketAdaptor.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,11 +25,23 @@
 
 package sun.nio.ch;
 
-import java.io.*;
-import java.lang.ref.*;
-import java.net.*;
-import java.nio.*;
-import java.nio.channels.*;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import java.net.SocketAddress;
+import java.net.SocketException;
+import java.net.SocketImpl;
+import java.net.SocketOption;
+import java.net.SocketTimeoutException;
+import java.net.StandardSocketOptions;
+import java.nio.ByteBuffer;
+import java.nio.channels.Channels;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.IllegalBlockingModeException;
+import java.nio.channels.SocketChannel;
 import java.security.AccessController;
 import java.security.PrivilegedExceptionAction;
 import java.util.*;
@@ -49,7 +61,7 @@
 // java.net.Socket so as to simplify tracking future changes to that class.
 //
 
-public class SocketAdaptor
+class SocketAdaptor
     extends Socket
 {
 
@@ -93,31 +105,24 @@
                 throw new IllegalBlockingModeException();
 
             try {
-
                 if (timeout == 0) {
                     sc.connect(remote);
                     return;
                 }
 
-                // Implement timeout with a selector
-                SelectionKey sk = null;
-                Selector sel = null;
                 sc.configureBlocking(false);
                 try {
                     if (sc.connect(remote))
                         return;
-                    sel = Util.getTemporarySelector(sc);
-                    sk = sc.register(sel, SelectionKey.OP_CONNECT);
                     long to = timeout;
                     for (;;) {
                         if (!sc.isOpen())
                             throw new ClosedChannelException();
                         long st = System.currentTimeMillis();
-                        int ns = sel.select(to);
-                        if (ns > 0 &&
-                            sk.isConnectable() && sc.finishConnect())
+
+                        int result = sc.poll(Net.POLLCONN, to);
+                        if (result > 0 && sc.finishConnect())
                             break;
-                        sel.selectedKeys().remove(sk);
                         to -= System.currentTimeMillis() - st;
                         if (to <= 0) {
                             try {
@@ -127,12 +132,9 @@
                         }
                     }
                 } finally {
-                    if (sk != null)
-                        sk.cancel();
-                    if (sc.isOpen())
+                    try {
                         sc.configureBlocking(true);
-                    if (sel != null)
-                        Util.releaseTemporarySelector(sel);
+                    } catch (ClosedChannelException e) { }
                 }
 
             } catch (Exception x) {
@@ -199,31 +201,26 @@
             synchronized (sc.blockingLock()) {
                 if (!sc.isBlocking())
                     throw new IllegalBlockingModeException();
+
                 if (timeout == 0)
                     return sc.read(bb);
 
-                // Implement timeout with a selector
-                SelectionKey sk = null;
-                Selector sel = null;
                 sc.configureBlocking(false);
                 int n = 0;
                 Object traceContext = IoTrace.socketReadBegin();
                 try {
                     if ((n = sc.read(bb)) != 0)
                         return n;
-                    sel = Util.getTemporarySelector(sc);
-                    sk = sc.register(sel, SelectionKey.OP_READ);
                     long to = timeout;
                     for (;;) {
                         if (!sc.isOpen())
                             throw new ClosedChannelException();
                         long st = System.currentTimeMillis();
-                        int ns = sel.select(to);
-                        if (ns > 0 && sk.isReadable()) {
+                        int result = sc.poll(Net.POLLIN, to);
+                        if (result > 0) {
                             if ((n = sc.read(bb)) != 0)
                                 return n;
                         }
-                        sel.selectedKeys().remove(sk);
                         to -= System.currentTimeMillis() - st;
                         if (to <= 0)
                             throw new SocketTimeoutException();
@@ -231,14 +228,10 @@
                 } finally {
                     IoTrace.socketReadEnd(traceContext, getInetAddress(),
                                           getPort(), timeout, n > 0 ? n : 0);
-                    if (sk != null)
-                        sk.cancel();
-                    if (sc.isOpen())
+                    try {
                         sc.configureBlocking(true);
-                    if (sel != null)
-                        Util.releaseTemporarySelector(sel);
+                    } catch (ClosedChannelException e) { }
                 }
-
             }
         }
     }
--- a/src/share/classes/sun/nio/ch/SocketChannelImpl.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/nio/ch/SocketChannelImpl.java	Thu Feb 06 01:43:16 2020 +0000
@@ -50,9 +50,6 @@
 
     // Our file descriptor object
     private final FileDescriptor fd;
-
-    // fd value needed for dev/poll. This value will remain valid
-    // even after the value in the file descriptor object has been set to -1
     private final int fdVal;
 
     // IDs of native threads doing reads and writes, for signalling
@@ -920,15 +917,14 @@
         int oldOps = sk.nioReadyOps();
         int newOps = initialOps;
 
-        if ((ops & PollArrayWrapper.POLLNVAL) != 0) {
+        if ((ops & Net.POLLNVAL) != 0) {
             // This should only happen if this channel is pre-closed while a
             // selection operation is in progress
             // ## Throw an error if this channel has not been pre-closed
             return false;
         }
 
-        if ((ops & (PollArrayWrapper.POLLERR
-                    | PollArrayWrapper.POLLHUP)) != 0) {
+        if ((ops & (Net.POLLERR | Net.POLLHUP)) != 0) {
             newOps = intOps;
             sk.nioReadyOps(newOps);
             // No need to poll again in checkConnect,
@@ -937,19 +933,19 @@
             return (newOps & ~oldOps) != 0;
         }
 
-        if (((ops & PollArrayWrapper.POLLIN) != 0) &&
+        if (((ops & Net.POLLIN) != 0) &&
             ((intOps & SelectionKey.OP_READ) != 0) &&
             (state == ST_CONNECTED))
             newOps |= SelectionKey.OP_READ;
 
-        if (((ops & PollArrayWrapper.POLLCONN) != 0) &&
+        if (((ops & Net.POLLCONN) != 0) &&
             ((intOps & SelectionKey.OP_CONNECT) != 0) &&
             ((state == ST_UNCONNECTED) || (state == ST_PENDING))) {
             newOps |= SelectionKey.OP_CONNECT;
             readyToConnect = true;
         }
 
-        if (((ops & PollArrayWrapper.POLLOUT) != 0) &&
+        if (((ops & Net.POLLOUT) != 0) &&
             ((intOps & SelectionKey.OP_WRITE) != 0) &&
             (state == ST_CONNECTED))
             newOps |= SelectionKey.OP_WRITE;
@@ -966,17 +962,39 @@
         return translateReadyOps(ops, 0, sk);
     }
 
+    // package-private
+    int poll(int events, long timeout) throws IOException {
+        assert Thread.holdsLock(blockingLock()) && !isBlocking();
+
+        synchronized (readLock) {
+            int n = 0;
+            try {
+                begin();
+                synchronized (stateLock) {
+                    if (!isOpen())
+                        return 0;
+                    readerThread = NativeThread.current();
+                }
+                n = Net.poll(fd, events, timeout);
+            } finally {
+                readerCleanup();
+                end(n > 0);
+            }
+            return n;
+        }
+    }
+
     /**
      * Translates an interest operation set into a native poll event set
      */
     public void translateAndSetInterestOps(int ops, SelectionKeyImpl sk) {
         int newOps = 0;
         if ((ops & SelectionKey.OP_READ) != 0)
-            newOps |= PollArrayWrapper.POLLIN;
+            newOps |= Net.POLLIN;
         if ((ops & SelectionKey.OP_WRITE) != 0)
-            newOps |= PollArrayWrapper.POLLOUT;
+            newOps |= Net.POLLOUT;
         if ((ops & SelectionKey.OP_CONNECT) != 0)
-            newOps |= PollArrayWrapper.POLLCONN;
+            newOps |= Net.POLLCONN;
         sk.selector.putEventOps(sk, newOps);
     }
 
--- a/src/share/classes/sun/nio/ch/Util.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/nio/ch/Util.java	Thu Feb 06 01:43:16 2020 +0000
@@ -218,66 +218,6 @@
         ((DirectBuffer)buf).cleaner().clean();
     }
 
-    private static class SelectorWrapper {
-        private Selector sel;
-        private SelectorWrapper (Selector sel) {
-            this.sel = sel;
-            Cleaner.create(this, new Closer(sel));
-        }
-        private static class Closer implements Runnable {
-            private Selector sel;
-            private Closer (Selector sel) {
-                this.sel = sel;
-            }
-            public void run () {
-                try {
-                    sel.close();
-                } catch (Throwable th) {
-                    throw new Error(th);
-                }
-            }
-        }
-        public Selector get() { return sel;}
-    }
-
-    // Per-thread cached selector
-    private static ThreadLocal<SoftReference<SelectorWrapper>> localSelector
-        = new ThreadLocal<SoftReference<SelectorWrapper>>();
-    // Hold a reference to the selWrapper object to prevent it from
-    // being cleaned when the temporary selector wrapped is on lease.
-    private static ThreadLocal<SelectorWrapper> localSelectorWrapper
-        = new ThreadLocal<SelectorWrapper>();
-
-    // When finished, invoker must ensure that selector is empty
-    // by cancelling any related keys and explicitly releasing
-    // the selector by invoking releaseTemporarySelector()
-    static Selector getTemporarySelector(SelectableChannel sc)
-        throws IOException
-    {
-        SoftReference<SelectorWrapper> ref = localSelector.get();
-        SelectorWrapper selWrapper = null;
-        Selector sel = null;
-        if (ref == null
-            || ((selWrapper = ref.get()) == null)
-            || ((sel = selWrapper.get()) == null)
-            || (sel.provider() != sc.provider())) {
-            sel = sc.provider().openSelector();
-            selWrapper = new SelectorWrapper(sel);
-            localSelector.set(new SoftReference<SelectorWrapper>(selWrapper));
-        }
-        localSelectorWrapper.set(selWrapper);
-        return sel;
-    }
-
-    static void releaseTemporarySelector(Selector sel)
-        throws IOException
-    {
-        // Selector should be empty
-        sel.selectNow();                // Flush cancelled keys
-        assert sel.keys().isEmpty() : "Temporary selector not empty";
-        localSelectorWrapper.set(null);
-    }
-
 
     // -- Random stuff --
 
--- a/src/share/classes/sun/nio/cs/ext/DoubleByteDecoder.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/nio/cs/ext/DoubleByteDecoder.java	Thu Feb 06 01:43:16 2020 +0000
@@ -209,9 +209,9 @@
         if (bugLevel == null) {
             if (!sun.misc.VM.isBooted())
                 return false;
-            java.security.PrivilegedAction pa =
+            java.security.PrivilegedAction<String> pa =
                 new GetPropertyAction("sun.nio.cs.bugLevel");
-            String value = (String)AccessController.doPrivileged(pa);
+            String value = AccessController.doPrivileged(pa);
             bugLevel = (value != null) ? value : "";
         }
         return bugLevel.equals(bl);
--- a/src/share/classes/sun/reflect/misc/MethodUtil.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/reflect/misc/MethodUtil.java	Thu Feb 06 01:43:16 2020 +0000
@@ -25,6 +25,7 @@
 
 package sun.reflect.misc;
 
+import java.io.EOFException;
 import java.security.AllPermission;
 import java.security.AccessController;
 import java.security.PermissionCollection;
@@ -42,9 +43,9 @@
 import java.lang.reflect.Modifier;
 import java.util.HashMap;
 import java.util.Map;
+
 import sun.misc.IOUtils;
 
-
 class Trampoline {
     static {
         if (Trampoline.class.getClassLoader() == null) {
@@ -382,15 +383,12 @@
             }
         }
         int len = uc.getContentLength();
-        InputStream in = new BufferedInputStream(uc.getInputStream());
-
-        byte[] b;
-        try {
-            b = IOUtils.readFully(in, len, true);
-        } finally {
-            in.close();
+        try (InputStream in = new BufferedInputStream(uc.getInputStream())) {
+            byte[] b = IOUtils.readAllBytes(in);
+            if (len != -1 && b.length != len)
+                throw new EOFException("Expected:" + len + ", read:" + b.length);
+            return b;
         }
-        return b;
     }
 
 
--- a/src/share/classes/sun/rmi/registry/RegistryImpl_Skel.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/rmi/registry/RegistryImpl_Skel.java	Thu Feb 06 01:43:16 2020 +0000
@@ -27,7 +27,9 @@
 package sun.rmi.registry;
 
 import java.io.IOException;
+import java.io.ObjectInputStream;
 
+import sun.misc.SharedSecrets;
 import sun.rmi.transport.StreamRemoteCall;
 
 /**
@@ -83,8 +85,9 @@
                 java.lang.String $param_String_1;
                 java.rmi.Remote $param_Remote_2;
                 try {
-                    java.io.ObjectInput in = call.getInputStream();
-                    $param_String_1 = (java.lang.String) in.readObject();
+                    ObjectInputStream in = (ObjectInputStream)call.getInputStream();
+                    $param_String_1 =
+                            SharedSecrets.getJavaObjectInputStreamReadString().readString(in);
                     $param_Remote_2 = (java.rmi.Remote) in.readObject();
                 } catch (ClassCastException | IOException | ClassNotFoundException e) {
                     call.discardPendingRefs();
@@ -118,9 +121,10 @@
             {
                 java.lang.String $param_String_1;
                 try {
-                    java.io.ObjectInput in = call.getInputStream();
-                    $param_String_1 = (java.lang.String) in.readObject();
-                } catch (ClassCastException | IOException | ClassNotFoundException e) {
+                    ObjectInputStream in = (ObjectInputStream)call.getInputStream();
+                    $param_String_1 =
+                            SharedSecrets.getJavaObjectInputStreamReadString().readString(in);
+                } catch (ClassCastException | IOException e) {
                     call.discardPendingRefs();
                     throw new java.rmi.UnmarshalException("error unmarshalling arguments", e);
                 } finally {
@@ -144,8 +148,9 @@
                 java.lang.String $param_String_1;
                 java.rmi.Remote $param_Remote_2;
                 try {
-                    java.io.ObjectInput in = call.getInputStream();
-                    $param_String_1 = (java.lang.String) in.readObject();
+                    ObjectInputStream in = (ObjectInputStream)call.getInputStream();
+                    $param_String_1 =
+                            SharedSecrets.getJavaObjectInputStreamReadString().readString(in);
                     $param_Remote_2 = (java.rmi.Remote) in.readObject();
                 } catch (ClassCastException | IOException | java.lang.ClassNotFoundException e) {
                     call.discardPendingRefs();
@@ -169,9 +174,10 @@
 
                 java.lang.String $param_String_1;
                 try {
-                    java.io.ObjectInput in = call.getInputStream();
-                    $param_String_1 = (java.lang.String) in.readObject();
-                } catch (ClassCastException | IOException | ClassNotFoundException e) {
+                    ObjectInputStream in = (ObjectInputStream)call.getInputStream();
+                    $param_String_1 =
+                            SharedSecrets.getJavaObjectInputStreamReadString().readString(in);
+                } catch (ClassCastException | IOException e) {
                     call.discardPendingRefs();
                     throw new java.rmi.UnmarshalException("error unmarshalling arguments", e);
                 } finally {
--- a/src/share/classes/sun/rmi/server/UnicastRef.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/rmi/server/UnicastRef.java	Thu Feb 06 01:43:16 2020 +0000
@@ -27,6 +27,7 @@
 
 import java.io.IOException;
 import java.io.ObjectInput;
+import java.io.ObjectInputStream;
 import java.io.ObjectOutput;
 import java.lang.reflect.Method;
 import java.rmi.MarshalException;
@@ -38,6 +39,8 @@
 import java.rmi.server.RemoteObject;
 import java.rmi.server.RemoteRef;
 import java.security.AccessController;
+
+import sun.misc.SharedSecrets;
 import sun.rmi.runtime.Log;
 import sun.rmi.transport.Connection;
 import sun.rmi.transport.LiveRef;
@@ -318,6 +321,8 @@
             } else {
                 throw new Error("Unrecognized primitive type: " + type);
             }
+        } else if (type == String.class && in instanceof ObjectInputStream) {
+            return SharedSecrets.getJavaObjectInputStreamReadString().readString((ObjectInputStream)in);
         } else {
             return in.readObject();
         }
--- a/src/share/classes/sun/rmi/transport/tcp/TCPEndpoint.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/rmi/transport/tcp/TCPEndpoint.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -29,6 +29,7 @@
 import java.io.IOException;
 import java.io.ObjectInput;
 import java.io.ObjectOutput;
+import java.lang.reflect.Proxy;
 import java.net.InetAddress;
 import java.net.ServerSocket;
 import java.net.Socket;
@@ -553,6 +554,9 @@
             host = in.readUTF();
             port = in.readInt();
             csf = (RMIClientSocketFactory) in.readObject();
+            if (csf != null && Proxy.isProxyClass(csf.getClass())) {
+                throw new IOException("Invalid SocketFactory");
+            }
           break;
 
           default:
--- a/src/share/classes/sun/security/action/GetPropertyAction.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/security/action/GetPropertyAction.java	Thu Feb 06 01:43:16 2020 +0000
@@ -108,4 +108,27 @@
                     new GetPropertyAction(theProp));
         }
     }
+
+    /**
+     * Convenience method to get a property without going through doPrivileged
+     * if no security manager is present. This is unsafe for inclusion in a
+     * public API but allowable here since this class is now encapsulated.
+     *
+     * Note that this method performs a privileged action using caller-provided
+     * inputs. The caller of this method should take care to ensure that the
+     * inputs are not tainted and the returned property is not made accessible
+     * to untrusted code if it contains sensitive information.
+     *
+     * @param theProp the name of the system property.
+     * @param defaultVal the default value.
+     */
+    public static String privilegedGetProperty(String theProp,
+            String defaultVal) {
+        if (System.getSecurityManager() == null) {
+            return System.getProperty(theProp, defaultVal);
+        } else {
+            return AccessController.doPrivileged(
+                    new GetPropertyAction(theProp, defaultVal));
+        }
+    }
 }
--- a/src/share/classes/sun/security/jgss/krb5/AcceptSecContextToken.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/security/jgss/krb5/AcceptSecContextToken.java	Thu Feb 06 01:43:16 2020 +0000
@@ -27,9 +27,10 @@
 
 import org.ietf.jgss.*;
 import java.io.InputStream;
-import java.io.OutputStream;
 import java.io.IOException;
-import java.io.ByteArrayInputStream;
+import java.security.AccessController;
+
+import sun.security.action.GetBooleanAction;
 import sun.security.krb5.*;
 
 class AcceptSecContextToken extends InitialToken {
@@ -42,23 +43,19 @@
      */
     public AcceptSecContextToken(Krb5Context context,
                                  KrbApReq apReq)
-        throws KrbException, IOException {
+        throws KrbException, IOException, GSSException {
 
-        /*
-         * RFC 1964, section 1.2 states:
-         *  (1) context key: uses Kerberos session key (or subkey, if
-         *  present in authenticator emitted by context initiator) directly
-         *
-         * This does not mention context acceptor. Hence we will not
-         * generate a subkey on the acceptor side. Note: Our initiator will
-         * still allow another acceptor to generate a subkey, even though
-         * our acceptor does not do so.
-         */
-        boolean useSubkey = false;
+        boolean useSubkey = AccessController.doPrivileged(
+                new GetBooleanAction("sun.security.krb5.acceptor.subkey"));
 
         boolean useSequenceNumber = true;
 
-        apRep = new KrbApRep(apReq, useSequenceNumber, useSubkey);
+        EncryptionKey subKey = null;
+        if (useSubkey) {
+            subKey = new EncryptionKey(apReq.getCreds().getSessionKey());
+            context.setKey(Krb5Context.ACCEPTOR_SUBKEY, subKey);
+        }
+        apRep = new KrbApRep(apReq, useSequenceNumber, subKey);
 
         context.resetMySequenceNumber(apRep.getSeqNumber().intValue());
 
--- a/src/share/classes/sun/security/jgss/krb5/CipherHelper.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/security/jgss/krb5/CipherHelper.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -44,6 +44,7 @@
 import sun.security.krb5.internal.crypto.Aes128;
 import sun.security.krb5.internal.crypto.Aes256;
 import sun.security.krb5.internal.crypto.ArcFourHmac;
+import sun.security.krb5.internal.crypto.EType;
 
 class CipherHelper {
 
@@ -77,10 +78,6 @@
     private int sgnAlg, sealAlg;
     private byte[] keybytes;
 
-    // new token format from draft-ietf-krb-wg-gssapi-cfx-07
-    // proto is used to determine new GSS token format for "newer" etypes
-    private int proto = 0;
-
     CipherHelper(EncryptionKey key) throws GSSException {
         etype = key.getEType();
         keybytes = key.getBytes();
@@ -106,7 +103,6 @@
         case EncryptedData.ETYPE_AES256_CTS_HMAC_SHA1_96:
             sgnAlg = -1;
             sealAlg = -1;
-            proto = 1;
             break;
 
         default:
@@ -123,8 +119,10 @@
         return sealAlg;
     }
 
+    // new token format from draft-ietf-krb-wg-gssapi-cfx-07
+    // proto is used to determine new GSS token format for "newer" etypes
     int getProto() {
-        return proto;
+        return EType.isNewer(etype) ? 1 : 0;
     }
 
     int getEType() {
--- a/src/share/classes/sun/security/jgss/krb5/InitSecContextToken.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/security/jgss/krb5/InitSecContextToken.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -29,6 +29,8 @@
 import org.ietf.jgss.*;
 import java.io.InputStream;
 import java.io.IOException;
+
+import sun.security.action.GetPropertyAction;
 import sun.security.krb5.*;
 import java.net.InetAddress;
 import sun.security.krb5.internal.AuthorizationData;
@@ -36,6 +38,33 @@
 
 class InitSecContextToken extends InitialToken {
 
+    // If non-mutual authentication is requested, there is no AP-REP message.
+    // The acceptor thus has no chance to send the seq-number field to the
+    // initiator. In this case, the initiator and acceptor should has an
+    // agreement to derive acceptor's initial seq-number if the acceptor wishes
+    // to send messages to the initiator.
+
+    // If this flag is true, it will the same as the initiator's initial
+    // seq-number (as MIT krb5 and Windows SSPI do). Otherwise, it will be zero
+    // (as Heimdal does). The default value is true.
+    private static final boolean ACCEPTOR_USE_INITIATOR_SEQNUM;
+
+    static {
+        // The ACCEPTOR_USE_INITIATOR_SEQNUM value is determined by the system
+        // property "sun.security.krb5.acceptor.sequence.number.nonmutual",
+        // which can be set to "initiator", "zero" or "0".
+        String propName = "sun.security.krb5.acceptor.sequence.number.nonmutual";
+        String s = GetPropertyAction.privilegedGetProperty(propName, "initiator");
+        if (s.equals("initiator")) {
+            ACCEPTOR_USE_INITIATOR_SEQNUM = true;
+        } else if (s.equals("zero") || s.equals("0")) {
+            ACCEPTOR_USE_INITIATOR_SEQNUM = false;
+        } else {
+            throw new AssertionError("Unrecognized value for " + propName
+                    + ": " + s);
+        }
+    }
+
     private KrbApReq apReq = null;
 
     /**
@@ -79,7 +108,10 @@
             context.setKey(Krb5Context.SESSION_KEY, serviceTicket.getSessionKey());
 
         if (!mutualRequired)
-            context.resetPeerSequenceNumber(0);
+            context.resetPeerSequenceNumber(
+                    ACCEPTOR_USE_INITIATOR_SEQNUM
+                    ? apReq.getSeqNumber().intValue()
+                    : 0);
     }
 
     /**
@@ -144,10 +176,12 @@
                              apReqSeqNumber.intValue() :
                              0);
         context.resetPeerSequenceNumber(peerSeqNumber);
-        if (!context.getMutualAuthState())
-            // Use the same sequence number as the peer
-            // (Behaviour exhibited by the Windows SSPI server)
-            context.resetMySequenceNumber(peerSeqNumber);
+        if (!context.getMutualAuthState()) {
+            context.resetMySequenceNumber(
+                    ACCEPTOR_USE_INITIATOR_SEQNUM
+                            ? peerSeqNumber
+                            : 0);
+        }
         context.setAuthTime(
                 new KerberosTime(apReq.getCreds().getAuthTime()).toString());
         context.setTktFlags(apReq.getCreds().getFlags());
--- a/src/share/classes/sun/security/jgss/krb5/Krb5InitCredential.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/security/jgss/krb5/Krb5InitCredential.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -234,11 +234,13 @@
      * @exception GSSException may be thrown
      */
     public int getInitLifetime() throws GSSException {
-        int retVal = 0;
-        retVal = (int)(getEndTime().getTime()
-                       - (new Date().getTime()));
+        Date d = getEndTime();
+        if (d == null) {
+            return 0;
+        }
 
-        return retVal/1000;
+        long retVal = d.getTime() - System.currentTimeMillis();
+        return (int)(retVal/1000);
     }
 
     /**
--- a/src/share/classes/sun/security/jgss/krb5/MessageToken_v2.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/security/jgss/krb5/MessageToken_v2.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -499,11 +499,11 @@
      */
     class MessageTokenHeader {
 
-         private int tokenId;
-         private byte[] bytes = new byte[TOKEN_HEADER_SIZE];
+        private int tokenId;
+        private byte[] bytes = new byte[TOKEN_HEADER_SIZE];
 
-         // Writes a new token header
-         public MessageTokenHeader(int tokenId, boolean conf) throws GSSException {
+        // Writes a new token header
+        public MessageTokenHeader(int tokenId, boolean conf) throws GSSException {
 
             this.tokenId = tokenId;
 
@@ -609,7 +609,7 @@
             prop.setQOP(0);
 
             // sequence number
-            seqNumber = readBigEndian(bytes, 0, 8);
+            seqNumber = readBigEndian(bytes, 12, 4);
         }
 
         /**
--- a/src/share/classes/sun/security/krb5/Checksum.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/security/krb5/Checksum.java	Thu Feb 06 01:43:16 2020 +0000
@@ -69,136 +69,120 @@
     // draft-brezak-win2k-krb-rc4-hmac-04.txt
     public static final int CKSUMTYPE_HMAC_MD5_ARCFOUR = -138;
 
+    // default checksum type, -1 if not set
     static int CKSUMTYPE_DEFAULT;
     static int SAFECKSUMTYPE_DEFAULT;
 
     private static boolean DEBUG = Krb5.DEBUG;
     static {
+        initStatic();
+    }
+
+    public static void initStatic() {
         String temp = null;
         Config cfg = null;
         try {
             cfg = Config.getInstance();
-            temp = cfg.getDefault("default_checksum", "libdefaults");
-            if (temp != null)
-                {
-                    CKSUMTYPE_DEFAULT = cfg.getType(temp);
-                } else {
-                    /*
-                     * If the default checksum is not
-                     * specified in the configuration we
-                     * set it to RSA_MD5. We follow the MIT and
-                     * SEAM implementation.
-                     */
-                    CKSUMTYPE_DEFAULT = CKSUMTYPE_RSA_MD5;
-                }
+            temp = cfg.get("libdefaults", "default_checksum");
+            if (temp != null) {
+                CKSUMTYPE_DEFAULT = Config.getType(temp);
+            } else {
+                CKSUMTYPE_DEFAULT = -1;
+            }
         } catch (Exception exc) {
             if (DEBUG) {
                 System.out.println("Exception in getting default checksum "+
-                                   "value from the configuration " +
-                                   "Setting default checksum to be RSA-MD5");
+                                   "value from the configuration. " +
+                                   "No default checksum set.");
                 exc.printStackTrace();
             }
-            CKSUMTYPE_DEFAULT = CKSUMTYPE_RSA_MD5;
+            CKSUMTYPE_DEFAULT = -1;
         }
 
 
         try {
-            temp = cfg.getDefault("safe_checksum_type", "libdefaults");
+            temp = cfg.get("libdefaults", "safe_checksum_type");
             if (temp != null)
                 {
-                    SAFECKSUMTYPE_DEFAULT = cfg.getType(temp);
+                    SAFECKSUMTYPE_DEFAULT = Config.getType(temp);
                 } else {
-                    SAFECKSUMTYPE_DEFAULT = CKSUMTYPE_RSA_MD5_DES;
+                    SAFECKSUMTYPE_DEFAULT = -1;
                 }
         } catch (Exception exc) {
             if (DEBUG) {
                 System.out.println("Exception in getting safe default " +
                                    "checksum value " +
-                                   "from the configuration Setting  " +
-                                   "safe default checksum to be RSA-MD5");
+                                   "from the configuration Setting.  " +
+                                   "No safe default checksum set.");
                 exc.printStackTrace();
             }
-            SAFECKSUMTYPE_DEFAULT = CKSUMTYPE_RSA_MD5_DES;
+            SAFECKSUMTYPE_DEFAULT = -1;
         }
     }
 
     /**
      * Constructs a new Checksum using the raw data and type.
+     *
+     * This constructor is only used by Authenticator Checksum
+     * {@link sun.security.jgss.krb5.InitialToken.OverloadedChecksum}
+     * where the checksum type must be 0x8003
+     * (see https://tools.ietf.org/html/rfc4121#section-4.1.1)
+     * and checksum field/value is used to convey service flags,
+     * channel bindings, and optional delegation information.
+     * This special type does NOT have a {@link CksumType} and has its
+     * own calculating and verification rules. It does has the same
+     * ASN.1 encoding though.
+     *
      * @data the byte array of checksum.
      * @new_cksumType the type of checksum.
-     *
      */
-         // used in InitialToken
     public Checksum(byte[] data, int new_cksumType) {
         cksumType = new_cksumType;
         checksum = data;
     }
 
     /**
-     * Constructs a new Checksum by calculating the checksum over the data
-     * using specified checksum type.
-     * @new_cksumType the type of checksum.
-     * @data the data that needs to be performed a checksum calculation on.
+     * Constructs a new Checksum by calculating over the data using
+     * the specified checksum type. If the checksum is unkeyed, key
+     * and usage are ignored.
+     *
+     * @param new_cksumType the type of checksum. If set to -1, the
+     *      {@linkplain EType#checksumType() mandatory checksum type}
+     *      for the encryption type of {@code key} will be used
+     * @param data the data that needs to be performed a checksum calculation on
+     * @param key the key used by a keyed checksum
+     * @param usage the usage used by a keyed checksum
      */
-    public Checksum(int new_cksumType, byte[] data)
-        throws KdcErrException, KrbCryptoException {
-
-        cksumType = new_cksumType;
-        CksumType cksumEngine = CksumType.getInstance(cksumType);
-        if (!cksumEngine.isSafe()) {
-            checksum = cksumEngine.calculateChecksum(data, data.length);
+    public Checksum(int new_cksumType, byte[] data,
+                    EncryptionKey key, int usage)
+            throws KdcErrException, KrbApErrException, KrbCryptoException {
+        if (new_cksumType == -1) {
+            cksumType = EType.getInstance(key.getEType()).checksumType();
         } else {
-            throw new KdcErrException(Krb5.KRB_AP_ERR_INAPP_CKSUM);
+            cksumType = new_cksumType;
         }
-    }
-
-    /**
-     * Constructs a new Checksum by calculating the keyed checksum
-     * over the data using specified checksum type.
-     * @new_cksumType the type of checksum.
-     * @data the data that needs to be performed a checksum calculation on.
-     */
-         // KrbSafe, KrbTgsReq
-    public Checksum(int new_cksumType, byte[] data,
-                        EncryptionKey key, int usage)
-        throws KdcErrException, KrbApErrException, KrbCryptoException {
-        cksumType = new_cksumType;
-        CksumType cksumEngine = CksumType.getInstance(cksumType);
-        if (!cksumEngine.isSafe())
-            throw new KrbApErrException(Krb5.KRB_AP_ERR_INAPP_CKSUM);
-        checksum =
-            cksumEngine.calculateKeyedChecksum(data,
-                data.length,
-                key.getBytes(),
-                usage);
+        checksum = CksumType.getInstance(cksumType).calculateChecksum(
+                    data, data.length, key.getBytes(), usage);
     }
 
     /**
      * Verifies the keyed checksum over the data passed in.
      */
-    public boolean verifyKeyedChecksum(byte[] data, EncryptionKey key,
-                                        int usage)
-        throws KdcErrException, KrbApErrException, KrbCryptoException {
+    public boolean verifyKeyedChecksum(byte[] data, EncryptionKey key, int usage)
+            throws KdcErrException, KrbApErrException, KrbCryptoException {
         CksumType cksumEngine = CksumType.getInstance(cksumType);
-        if (!cksumEngine.isSafe())
+        if (!cksumEngine.isKeyed()) {
             throw new KrbApErrException(Krb5.KRB_AP_ERR_INAPP_CKSUM);
-        return cksumEngine.verifyKeyedChecksum(data,
-                                               data.length,
-                                               key.getBytes(),
-                                               checksum,
-            usage);
+        } else {
+            return cksumEngine.verifyChecksum(
+                    data, data.length, key.getBytes(), checksum, usage);
+        }
     }
 
-    /*
-    public Checksum(byte[] data) throws KdcErrException, KrbCryptoException {
-        this(Checksum.CKSUMTYPE_DEFAULT, data);
-    }
-    */
-
     boolean isEqual(Checksum cksum) throws KdcErrException {
-        if (cksumType != cksum.cksumType)
+        if (cksumType != cksum.cksumType) {
             return false;
-        CksumType cksumEngine = CksumType.getInstance(cksumType);
+        }
         return CksumType.isChecksumEqual(checksum, cksum.checksum);
     }
 
--- a/src/share/classes/sun/security/krb5/Config.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/security/krb5/Config.java	Thu Feb 06 01:43:16 2020 +0000
@@ -30,20 +30,20 @@
  */
 package sun.security.krb5;
 
-import java.io.File;
-import java.io.FileInputStream;
-import java.util.Hashtable;
-import java.util.Vector;
-import java.util.ArrayList;
-import java.io.BufferedReader;
-import java.io.InputStreamReader;
-import java.io.IOException;
-import java.util.Enumeration;
-import java.util.StringTokenizer;
+import java.io.*;
 import java.net.InetAddress;
 import java.net.UnknownHostException;
+import java.security.AccessController;
+import java.security.PrivilegedExceptionAction;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Hashtable;
 import java.util.List;
 import java.util.Locale;
+import java.util.StringTokenizer;
+import java.util.Vector;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 import sun.net.dns.ResolverConfiguration;
 import sun.security.krb5.internal.crypto.EType;
 import sun.security.krb5.internal.Krb5;
@@ -63,7 +63,7 @@
     /*
      * Hashtable used to store configuration information.
      */
-    private Hashtable<String,Object> stanzaTable;
+    private Hashtable<String,Object> stanzaTable = new Hashtable<>();
 
     private static boolean DEBUG = sun.security.krb5.internal.Krb5.DEBUG;
 
@@ -101,7 +101,9 @@
     /**
      * Refresh and reload the Configuration. This could involve,
      * for example reading the Configuration file again or getting
-     * the java.security.krb5.* system properties again.
+     * the java.security.krb5.* system properties again. This method
+     * also tries its best to update static fields in other classes
+     * that depend on the configuration.
      *
      * @exception KrbException if error occurs when constructing a Config
      * instance. Possible causes would be either of java.security.krb5.realm or
@@ -111,6 +113,8 @@
     public static synchronized void refresh() throws KrbException {
         singleton = new Config();
         KdcComm.initStatic();
+        EType.initStatic();
+        Checksum.initStatic();
     }
 
 
@@ -164,7 +168,7 @@
 
         // Always read the Kerberos configuration file
         try {
-            Vector<String> configFile;
+            List<String> configFile;
             String fileName = getJavaFileName();
             if (fileName != null) {
                 configFile = loadConfigFile(fileName);
@@ -195,236 +199,48 @@
                 }
             }
         } catch (IOException ioe) {
-            // No krb5.conf, no problem. We'll use DNS or system property etc.
-        }
-    }
-
-    /**
-     * Gets the default int value for the specified name.
-     * @param name the name.
-     * @return the default Integer, null is returned if no such name and
-     * value are found in configuration file, or error occurs when parsing
-     * string to integer.
-     */
-    public int getDefaultIntValue(String name) {
-        String result = null;
-        int value = Integer.MIN_VALUE;
-        result = getDefault(name);
-        if (result != null) {
-            try {
-                value = parseIntValue(result);
-            } catch (NumberFormatException e) {
-                if (DEBUG) {
-                    System.out.println("Exception in getting value of " +
-                                       name + " " +
-                                       e.getMessage());
-                    System.out.println("Setting " + name +
-                                       " to minimum value");
-                }
-                value = Integer.MIN_VALUE;
-            }
-        }
-        return value;
-    }
-
-    /**
-     * Gets the default int value for the specified name in the specified
-     * section. <br>This method is quicker by using section name as the
-     * search key.
-     * @param name the name.
-     * @param sectio the name string of the section.
-     * @return the default Integer, null is returned if no such name and
-     * value are found in configuration file, or error occurs when parsing
-     * string to integer.
-     */
-    public int getDefaultIntValue(String name, String section) {
-        String result = null;
-        int value = Integer.MIN_VALUE;
-        result = getDefault(name, section);
-        if (result != null) {
-            try {
-                value = parseIntValue(result);
-            } catch (NumberFormatException e) {
-                if (DEBUG) {
-                    System.out.println("Exception in getting value of " +
-                                       name +" in section " +
-                                       section + " "  + e.getMessage());
-                    System.out.println("Setting " + name +
-                                       " to minimum value");
-                }
-                value = Integer.MIN_VALUE;
-            }
-        }
-        return value;
-    }
-
-    /**
-     * Gets the default string value for the specified name.
-     * @param name the name.
-     * @return the default value, null is returned if it cannot be found.
-     */
-    public String getDefault(String name) {
-        if (stanzaTable == null) {
-            return null;
-        } else {
-            return getDefault(name, stanzaTable);
+            // I/O error, mostly like krb5.conf missing.
+            // No problem. We'll use DNS or system property etc.
         }
     }
 
     /**
-     * This method does the real job to recursively search through the
-     * stanzaTable.
-     * @param k the key string.
-     * @param t stanzaTable or sub hashtable within it.
-     * @return the value found in config file, returns null if no value
-     * matched with the key is found.
+     * Gets the last-defined string value for the specified keys.
+     * @param keys the keys, as an array from section name, sub-section names
+     * (if any), to value name.
+     * @return the value. When there are multiple values for the same key,
+     * returns the last one. {@code null} is returned if not all the keys are
+     * defined. For example, {@code get("libdefaults", "forwardable")} will
+     * return null if "forwardable" is not defined in [libdefaults], and
+     * {@code get("realms", "R", "kdc")} will return null if "R" is not
+     * defined in [realms] or "kdc" is not defined for "R".
+     * @throws IllegalArgumentException if any of the keys is illegal, either
+     * because a key not the last one is not a (sub)section name or the last
+     * key is still a section name. For example, {@code get("libdefaults")}
+     * throws this exception because [libdefaults] is a section name instead of
+     * a value name, and {@code get("libdefaults", "forwardable", "tail")}
+     * also throws this exception because "forwardable" is already a value name
+     * and has no sub-key at all (given "forwardable" is defined, otherwise,
+     * this method has no knowledge if it's a value name or a section name),
      */
-    private String getDefault(String k, Hashtable<String, Object> t) {
-        String result = null;
-        String key;
-        if (stanzaTable != null) {
-            for (Enumeration<String> e = t.keys(); e.hasMoreElements(); ) {
-                key = e.nextElement();
-                Object ob = t.get(key);
-                if (ob instanceof Hashtable) {
-                    @SuppressWarnings("unchecked") // Checked with an instanceof check
-                    Hashtable<String, Object> table =
-                            (Hashtable<String, Object>)ob;
-                    result = getDefault(k, table);
-                    if (result != null) {
-                        return result;
-                    }
-                } else if (key.equalsIgnoreCase(k)) {
-                    if (ob instanceof String) {
-                        return (String)(t.get(key));
-                    } else if (ob instanceof Vector) {
-                        result = "";
-                        int length = ((Vector)ob).size();
-                        for (int i = 0; i < length; i++) {
-                            if (i == length -1) {
-                                result +=
-                                    (String)(((Vector)ob).elementAt(i));
-                            } else {
-                                result +=
-                                    (String)(((Vector)ob).elementAt(i)) + " ";
-                            }
-                        }
-                        return result;
-                    }
-                }
-            }
-        }
-        return result;
+    public String get(String... keys) {
+        Vector<String> v = getString0(keys);
+        if (v == null) return null;
+        return v.lastElement();
     }
 
     /**
-     * Gets the default string value for the specified name in the
-     * specified section.
-     * <br>This method is quicker by using the section name as the search key.
-     * @param name the name.
-     * @param section the name of the section.
-     * @return the default value, null is returned if it cannot be found.
-     */
-    // stanzaTable leads to a lot of unchecked casts since its value type is
-    // STANZATABLE = String | Hashtable<String, STANZATABLE>
-    @SuppressWarnings("unchecked")
-    public String getDefault(String name, String section) {
-        String stanzaName;
-        String result = null;
-        Hashtable<String, Object> subTable;
-
-        if (stanzaTable != null) {
-            for (Enumeration<String> e = stanzaTable.keys();
-                 e.hasMoreElements(); ) {
-                stanzaName = e.nextElement();
-                subTable = (Hashtable<String, Object>)
-                        stanzaTable.get(stanzaName);
-                if (stanzaName.equalsIgnoreCase(section)) {
-                    if (subTable.containsKey(name)) {
-                        return (String)(subTable.get(name));
-                    }
-                } else if (subTable.containsKey(section)) {
-                    Object ob = subTable.get(section);
-                    if (ob instanceof Hashtable) {
-                        Hashtable<String, Object> temp =
-                                (Hashtable<String, Object>)ob;
-                        if (temp.containsKey(name)) {
-                            Object object = temp.get(name);
-                            if (object instanceof Vector) {
-                                result = "";
-                                int length = ((Vector)object).size();
-                                for (int i = 0; i < length; i++) {
-                                    if (i == length - 1)  {
-                                        result +=
-                                        (String)(((Vector)object).elementAt(i));
-                                    } else {
-                                        result +=
-                                        (String)(((Vector)object).elementAt(i))
-                                                + " ";
-                                    }
-                                }
-                            } else {
-                                result = (String)object;
-                            }
-                        }
-                    }
-                }
-            }
-        }
-        return result;
-    }
-
-    /**
-     * Gets the default boolean value for the specified name.
-     * @param name the name.
-     * @return the default boolean value, false is returned if it cannot be
-     * found.
-     */
-    public boolean getDefaultBooleanValue(String name) {
-        String val = null;
-        if (stanzaTable == null) {
-            val = null;
-        } else {
-            val = getDefault(name, stanzaTable);
-        }
-        if (val != null && val.equalsIgnoreCase("true")) {
-            return true;
-        } else {
-            return false;
-        }
-    }
-
-    /**
-     * Gets the default boolean value for the specified name in the
-     * specified section.
-     * <br>This method is quicker by using the section name as the search key.
-     * @param name the name.
-     * @param section the name of the section.
-     * @return the default boolean value, false is returned if it cannot be
-     * found.
-     */
-    public boolean getDefaultBooleanValue(String name, String section) {
-        String val = getDefault(name, section);
-        if (val != null && val.equalsIgnoreCase("true")) {
-            return true;
-        } else {
-            return false;
-        }
-    }
-
-    /**
-     * Gets the default boolean value for the specified name in the
-     * specified section.  Returns TRUE if the
+     * Gets the boolean value for the specified keys. Returns TRUE if the
      * string value is "yes", or "true", FALSE if "no", or "false", or null
      * if otherwise or not defined. The comparision is case-insensitive.
-     * @param name the name.
-     * @param section the name of the section.
+     *
+     * @param keys the keys, see {@link #get(String...)}
      * @return the boolean value, or null if there is no value defined or the
      * value does not look like a boolean value.
      * @throws IllegalArgumentException see {@link #get(String...)}
      */
-    private Boolean getDefaultBooleanObject(String name, String section) {
-        String s = getDefault(name, section);
+    private Boolean getBooleanObject(String... keys) {
+        String s = get(keys);
         if (s == null) {
             return null;
         }
@@ -439,6 +255,179 @@
     }
 
     /**
+     * Gets all values (at least one) for the specified keys separated by
+     * a whitespace, or null if there is no such keys.
+     * The values can either be provided on a single line, or on multiple lines
+     * using the same key. When provided on a single line, the value can be
+     * comma or space separated.
+     * @throws IllegalArgumentException if any of the keys is illegal
+     *         (See {@link #get})
+     */
+    public String getAll(String... keys) {
+        Vector<String> v = getString0(keys);
+        if (v == null) return null;
+        StringBuilder sb = new StringBuilder();
+        boolean first = true;
+        for (String s: v) {
+            s = s.replaceAll("[\\s,]+", " ");
+            if (first) {
+                sb.append(s);
+                first = false;
+            } else {
+                sb.append(' ').append(s);
+            }
+        }
+        return sb.toString();
+    }
+
+    /**
+     * Returns true if keys exists, can be either final string(s) or sub-stanza
+     * @throws IllegalArgumentException if any of the keys is illegal
+     *         (See {@link #get})
+     */
+    public boolean exists(String... keys) {
+        return get0(keys) != null;
+    }
+
+    // Returns final string value(s) for given keys.
+    @SuppressWarnings("unchecked")
+    private Vector<String> getString0(String... keys) {
+        try {
+            return (Vector<String>)get0(keys);
+        } catch (ClassCastException cce) {
+            throw new IllegalArgumentException(cce);
+        }
+    }
+
+    // Internal method. Returns the value for keys, which can be a sub-stanza
+    // or final string value(s).
+    // The only method (except for toString) that reads stanzaTable directly.
+    @SuppressWarnings("unchecked")
+    private Vector<String> get0(String... keys) {
+        Object current = stanzaTable;
+        try {
+            for (String key: keys) {
+                current = ((Hashtable<String,Object>)current).get(key);
+                if (current == null) return null;
+            }
+            return (Vector<String>)current;
+        } catch (ClassCastException cce) {
+            throw new IllegalArgumentException(cce);
+        }
+    }
+
+    /**
+     * Translates a duration value into seconds.
+     *
+     * The format can be one of "h:m[:s]", "NdNhNmNs", and "N". See
+     * http://web.mit.edu/kerberos/krb5-devel/doc/basic/date_format.html#duration
+     * for definitions.
+     *
+     * @param s the string duration
+     * @return time in seconds
+     * @throw KrbException if format is illegal
+     */
+    public static int duration(String s) throws KrbException {
+
+        if (s.isEmpty()) {
+            throw new KrbException("Duration cannot be empty");
+        }
+
+        // N
+        if (s.matches("\\d+")) {
+            return Integer.parseInt(s);
+        }
+
+        // h:m[:s]
+        Matcher m = Pattern.compile("(\\d+):(\\d+)(:(\\d+))?").matcher(s);
+        if (m.matches()) {
+            int hr = Integer.parseInt(m.group(1));
+            int min = Integer.parseInt(m.group(2));
+            if (min >= 60) {
+                throw new KrbException("Illegal duration format " + s);
+            }
+            int result = hr * 3600 + min * 60;
+            if (m.group(4) != null) {
+                int sec = Integer.parseInt(m.group(4));
+                if (sec >= 60) {
+                    throw new KrbException("Illegal duration format " + s);
+                }
+                result += sec;
+            }
+            return result;
+        }
+
+        // NdNhNmNs
+        // 120m allowed. Maybe 1h120m is not good, but still allowed
+        m = Pattern.compile(
+                    "((\\d+)d)?\\s*((\\d+)h)?\\s*((\\d+)m)?\\s*((\\d+)s)?",
+                Pattern.CASE_INSENSITIVE).matcher(s);
+        if (m.matches()) {
+            int result = 0;
+            if (m.group(2) != null) {
+                result += 86400 * Integer.parseInt(m.group(2));
+            }
+            if (m.group(4) != null) {
+                result += 3600 * Integer.parseInt(m.group(4));
+            }
+            if (m.group(6) != null) {
+                result += 60 * Integer.parseInt(m.group(6));
+            }
+            if (m.group(8) != null) {
+                result += Integer.parseInt(m.group(8));
+            }
+            return result;
+        }
+
+        throw new KrbException("Illegal duration format " + s);
+    }
+
+    /**
+     * Gets the int value for the specified keys.
+     * @param keys the keys
+     * @return the int value, Integer.MIN_VALUE is returned if it cannot be
+     * found or the value is not a legal integer.
+     * @throw IllegalArgumentException if any of the keys is illegal
+     * @see #get(java.lang.String[])
+     */
+    public int getIntValue(String... keys) {
+        String result = get(keys);
+        int value = Integer.MIN_VALUE;
+        if (result != null) {
+            try {
+                value = parseIntValue(result);
+            } catch (NumberFormatException e) {
+                if (DEBUG) {
+                    System.out.println("Exception in getting value of " +
+                                       Arrays.toString(keys) + " " +
+                                       e.getMessage());
+                    System.out.println("Setting " + Arrays.toString(keys) +
+                                       " to minimum value");
+                }
+                value = Integer.MIN_VALUE;
+            }
+        }
+        return value;
+    }
+
+    /**
+     * Gets the boolean value for the specified keys.
+     * @param keys the keys
+     * @return the boolean value, false is returned if it cannot be
+     * found or the value is not "true" (case insensitive).
+     * @throw IllegalArgumentException if any of the keys is illegal
+     * @see #get(java.lang.String[])
+     */
+    public boolean getBooleanValue(String... keys) {
+        String val = get(keys);
+        if (val != null && val.equalsIgnoreCase("true")) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    /**
      * Parses a string to an integer. The convertible strings include the
      * string representations of positive integers, negative integers, and
      * hex decimal integers.  Valid inputs are, e.g., -1234, +1234,
@@ -555,29 +544,14 @@
     }
 
     /**
-     * Finds the matching value in the hashtable.
-     */
-    private String find(String key1, String key2) {
-        String result;
-        if ((stanzaTable != null) &&
-            ((result = (String)
-                (((Hashtable)(stanzaTable.get(key1))).get(key2))) != null)) {
-            return result;
-        } else {
-            return "";
-        }
-    }
-
-    /**
-     * Reads name/value pairs to the memory from the configuration
-     * file. The default location of the configuration file is in java home
-     * directory.
+     * Reads lines to the memory from the configuration file.
      *
      * Configuration file contains information about the default realm,
      * ticket parameters, location of the KDC and the admin server for
      * known realms, etc. The file is divided into sections. Each section
      * contains one or more name/value pairs with one pair per line. A
      * typical file would be:
+     * <pre>
      * [libdefaults]
      *          default_realm = EXAMPLE.COM
      *          default_tgs_enctypes = des-cbc-md5
@@ -595,128 +569,177 @@
      * [domain_realm]
      *          blue.sample.com = TEST.SAMPLE.COM
      *          .backup.com     = EXAMPLE.COM
-     *
-     * @params fileName the conf file, cannot be null
-     * @return the content, null if fileName is empty
-     * @throws IOException if there is an I/O or format error
+     * </pre>
+     * @return an ordered list of strings representing the config file after
+     * some initial processing, including:<ol>
+     * <li> Comment lines and empty lines are removed
+     * <li> "{" not at the end of a line is appended to the previous line
+     * <li> The content of a section is also placed between "{" and "}".
+     * <li> Lines are trimmed</ol>
+     * @throws IOException if there is an I/O error
+     * @throws KrbException if there is a file format error
      */
-    private Vector<String> loadConfigFile(final String fileName) throws IOException {
+    private List<String> loadConfigFile(final String fileName)
+            throws IOException, KrbException {
         try {
-            if (!fileName.equals("")) {
-                BufferedReader br = new BufferedReader(new InputStreamReader(
-                java.security.AccessController.doPrivileged(
-                new java.security.PrivilegedExceptionAction<FileInputStream> () {
-                public FileInputStream run() throws IOException {
-                    return new FileInputStream(fileName);
-                }
-                })));
-                String Line;
-                Vector<String> v = new Vector<>();
+            List<String> v = new ArrayList<>();
+            try (BufferedReader br = new BufferedReader(new InputStreamReader(
+                AccessController.doPrivileged(
+                    new PrivilegedExceptionAction<FileInputStream> () {
+                        public FileInputStream run() throws IOException {
+                            return new FileInputStream(fileName);
+                        }
+                    })))) {
+                String line;
                 String previous = null;
-                while ((Line = br.readLine()) != null) {
-                    // ignore comments and blank line in the configuration file.
-                    // Comments start with #.
-                    if (!(Line.startsWith("#") || Line.trim().isEmpty())) {
-                        String current = Line.trim();
-                        // In practice, a subsection might look like:
-                        //      EXAMPLE.COM =
-                        //      {
-                        //              kdc = kerberos.example.com
-                        //              ...
-                        //      }
-                        // Before parsed into stanza table, it needs to be
-                        // converted into formal style:
-                        //      EXAMPLE.COM = {
-                        //              kdc = kerberos.example.com
-                        //              ...
-                        //      }
-                        //
-                        // So, if a line is "{", adhere to the previous line.
-                        if (current.equals("{")) {
-                            if (previous == null) {
-                                throw new IOException(
-                                    "Config file should not start with \"{\"");
-                            }
-                            previous += " " + current;
-                        } else {
-                            if (previous != null) {
-                                v.addElement(previous);
-                            }
-                            previous = current;
+                while ((line = br.readLine()) != null) {
+                    line = line.trim();
+                    if (line.startsWith("#") || line.isEmpty()) {
+                        // ignore comments and blank line
+                        // Comments start with #.
+                        continue;
+                    }
+                    // In practice, a subsection might look like:
+                    //      [realms]
+                    //      EXAMPLE.COM =
+                    //      {
+                    //          kdc = kerberos.example.com
+                    //          ...
+                    //      }
+                    // Before parsed into stanza table, it needs to be
+                    // converted into a canonicalized style (no indent):
+                    //      realms = {
+                    //          EXAMPLE.COM = {
+                    //              kdc = kerberos.example.com
+                    //              ...
+                    //          }
+                    //      }
+                    //
+                    if (line.startsWith("[")) {
+                        if (!line.endsWith("]")) {
+                            throw new KrbException("Illegal config content:"
+                                    + line);
+                        }
+                        if (previous != null) {
+                            v.add(previous);
+                            v.add("}");
+                        }
+                        String title = line.substring(
+                                1, line.length()-1).trim();
+                        if (title.isEmpty()) {
+                            throw new KrbException("Illegal config content:"
+                                    + line);
+                        }
+                        previous = title + " = {";
+                    } else if (line.startsWith("{")) {
+                        if (previous == null) {
+                            throw new KrbException(
+                                "Config file should not start with \"{\"");
+                        }
+                        previous += " {";
+                        if (line.length() > 1) {
+                            // { and content on the same line
+                            v.add(previous);
+                            previous = line.substring(1).trim();
+                        }
+                    } else {
+                        // Lines before the first section are ignored
+                        if (previous != null) {
+                            v.add(previous);
+                            previous = line;
                         }
                     }
                 }
                 if (previous != null) {
-                    v.addElement(previous);
+                    v.add(previous);
+                    v.add("}");
                 }
-
-                br.close();
-                return v;
             }
-            return null;
+            return v;
         } catch (java.security.PrivilegedActionException pe) {
             throw (IOException)pe.getException();
         }
     }
 
-
     /**
      * Parses stanza names and values from configuration file to
      * stanzaTable (Hashtable). Hashtable key would be stanza names,
      * (libdefaults, realms, domain_realms, etc), and the hashtable value
      * would be another hashtable which contains the key-value pairs under
-     * a stanza name.
+     * a stanza name. The value of this sub-hashtable can be another hashtable
+     * containing another sub-sub-section or a vector of strings for
+     * final values (even if there is only one value defined).
+     * <p>
+     * For duplicates section names, the latter overwrites the former. For
+     * duplicate value names, the values are in a vector in its appearing order.
+     * </ol>
+     * Please note that this behavior is Java traditional. and it is
+     * not the same as the MIT krb5 behavior, where:<ol>
+     * <li>Duplicated root sections will be merged
+     * <li>For duplicated sub-sections, the former overwrites the latter
+     * <li>Duplicate keys for values are always saved in a vector
+     * </ol>
+     * @param v the strings in the file, never null, might be empty
+     * @throws KrbException if there is a file format error
      */
-    private Hashtable<String,Object> parseStanzaTable(Vector<String> v) throws KrbException {
-        if (v == null) {
-            throw new KrbException("I/O error while reading" +
-                        " configuration file.");
-        }
-        Hashtable<String,Object> table = new Hashtable<>();
-        for (int i = 0; i < v.size(); i++) {
-            String line = v.elementAt(i).trim();
-            if (line.equalsIgnoreCase("[realms]")) {
-                for (int count = i + 1; count < v.size() + 1; count++) {
-                    // find the next stanza name
-                    if ((count == v.size()) ||
-                        (v.elementAt(count).startsWith("["))) {
-                        Hashtable<String,Hashtable<String,Vector<String>>> temp =
-                            new Hashtable<>();
-                        temp = parseRealmField(v, i + 1, count);
-                        table.put("realms", temp);
-                        i = count - 1;
-                        break;
-                    }
+    @SuppressWarnings("unchecked")
+    private Hashtable<String,Object> parseStanzaTable(List<String> v)
+            throws KrbException {
+        Hashtable<String,Object> current = stanzaTable;
+        for (String line: v) {
+            // There are 3 kinds of lines
+            // 1. a = b
+            // 2. a = {
+            // 3. }
+            if (line.equals("}")) {
+                // Go back to parent, see below
+                current = (Hashtable<String,Object>)current.remove(" PARENT ");
+                if (current == null) {
+                    throw new KrbException("Unmatched close brace");
                 }
-            } else if (line.equalsIgnoreCase("[capaths]")) {
-                for (int count = i + 1; count < v.size() + 1; count++) {
-                    // find the next stanza name
-                    if ((count == v.size()) ||
-                        (v.elementAt(count).startsWith("["))) {
-                        Hashtable<String,Hashtable<String,Vector<String>>> temp =
-                            new Hashtable<>();
-                        temp = parseRealmField(v, i + 1, count);
-                        table.put("capaths", temp);
-                        i = count - 1;
-                        break;
-                    }
+            } else {
+                int pos = line.indexOf('=');
+                if (pos < 0) {
+                    throw new KrbException("Illegal config content:" + line);
                 }
-            } else if (line.startsWith("[") && line.endsWith("]")) {
-                String key = line.substring(1, line.length() - 1);
-                for (int count = i + 1; count < v.size() + 1; count++) {
-                    // find the next stanza name
-                    if ((count == v.size()) ||
-                        (v.elementAt(count).startsWith("["))) {
-                        Hashtable<String,String> temp =
-                            parseField(v, i + 1, count);
-                        table.put(key, temp);
-                        i = count - 1;
-                        break;
+                String key = line.substring(0, pos).trim();
+                String value = trimmed(line.substring(pos+1));
+                if (value.equals("{")) {
+                    Hashtable<String,Object> subTable;
+                    if (current == stanzaTable) {
+                        key = key.toLowerCase(Locale.US);
                     }
+                    subTable = new Hashtable<>();
+                    current.put(key, subTable);
+                    // A special entry for its parent. Put whitespaces around,
+                    // so will never be confused with a normal key
+                    subTable.put(" PARENT ", current);
+                    current = subTable;
+                } else {
+                    Vector<String> values;
+                    if (current.containsKey(key)) {
+                        Object obj = current.get(key);
+                        // If a key first shows as a section and then a value,
+                        // this is illegal. However, we haven't really forbid
+                        // first value then section, which the final result
+                        // is a section.
+                        if (!(obj instanceof Vector)) {
+                            throw new KrbException("Key " + key
+                                    + "used for both value and section");
+                        }
+                        values = (Vector<String>)current.get(key);
+                    } else {
+                        values = new Vector<String>();
+                        current.put(key, values);
+                    }
+                    values.add(value);
                 }
             }
         }
-        return table;
+        if (current != stanzaTable) {
+            throw new KrbException("Not closed");
+        }
+        return current;
     }
 
     /**
@@ -842,171 +865,33 @@
         }
         return s;
     }
-    /**
-     * Parses key-value pairs under a stanza name.
-     */
-    private Hashtable<String,String>  parseField(Vector<String> v, int start, int end) {
-        Hashtable<String,String> table = new Hashtable<>();
-        String line;
-        for (int i = start; i < end; i++) {
-            line = v.elementAt(i);
-            for (int j = 0; j < line.length(); j++) {
-                if (line.charAt(j) == '=') {
-                    String key = (line.substring(0, j)).trim();
-                    String value = trimmed(line.substring(j + 1));
-                    table.put(key, value);
-                    break;
-                }
-            }
-        }
-        return table;
-    }
-
-    /**
-     * Parses key-value pairs under [realms].  The key would be the realm
-     * name, the value would be another hashtable which contains
-     * information for the realm given within a pair of braces.
-     */
-    private Hashtable<String,Hashtable<String,Vector<String>>> parseRealmField(Vector<String> v, int start, int end) {
-        Hashtable<String,Hashtable<String,Vector<String>>> table = new Hashtable<>();
-        String line;
-        for (int i = start; i < end; i++) {
-            line = v.elementAt(i).trim();
-            if (line.endsWith("{")) {
-                String key = "";
-                for (int j = 0; j < line.length(); j++) {
-                    if (line.charAt(j) == '=') {
-                        key = line.substring(0, j).trim();
-                        // get the key
-                        break;
-                    }
-                }
-                for (int k = i + 1; k < end; k++) {
-                    boolean found = false;
-                    line = v.elementAt(k).trim();
-                    for (int l = 0; l < line.length(); l++) {
-                        if (line.charAt(l) == '}') {
-                            found = true;
-                            break;
-                        }
-                    }
-                    if (found == true) {
-                        Hashtable<String,Vector<String>> temp = parseRealmFieldEx(v, i + 1, k);
-                        table.put(key, temp);
-                        i = k;
-                        found = false;
-                        break;
-                    }
-
-                }
-            }
-        }
-        return table;
-    }
-
-    /**
-     * Parses key-value pairs within each braces under [realms].
-     */
-    private Hashtable<String,Vector<String>> parseRealmFieldEx(Vector<String> v, int start, int end) {
-        Hashtable<String,Vector<String>> table = new Hashtable<>();
-        Vector<String> keyVector = new Vector<>();
-        Vector<String> nameVector = new Vector<>();
-        String line = "";
-        String key;
-        for (int i = start; i < end; i++) {
-            line = v.elementAt(i);
-            for (int j = 0; j < line.length(); j++) {
-                if (line.charAt(j) == '=') {
-                    int index;
-                    key = line.substring(0, j).trim();
-                    if (! exists(key, keyVector)) {
-                        keyVector.addElement(key);
-                        nameVector = new Vector<String> ();
-                    } else {
-                        nameVector = table.get(key);
-                    }
-                    nameVector.addElement(trimmed(line.substring(j + 1)));
-                    table.put(key, nameVector);
-                    break;
-                }
-            }
-        }
-        return table;
-    }
-
-    /**
-     * Compares the key with the known keys to see if it exists.
-     */
-    private boolean exists(String key, Vector<String> v) {
-        boolean exists = false;
-        for (int i = 0; i < v.size(); i++) {
-            if (v.elementAt(i).equals(key)) {
-                exists = true;
-            }
-        }
-        return exists;
-    }
 
     /**
      * For testing purpose. This method lists all information being parsed from
      * the configuration file to the hashtable.
      */
     public void listTable() {
-        listTable(stanzaTable);
-    }
-
-    // stanzaTable leads to a lot of unchecked casts since its value type is
-    // STANZATABLE = String | Hashtable<String, STANZATABLE>
-    @SuppressWarnings("unchecked")
-    private void listTable(Hashtable<String, Object> table) {
-        Vector<String> v = new Vector<String>();
-        String key;
-        if (stanzaTable != null) {
-            for (Enumeration<String> e = table.keys(); e.hasMoreElements(); ) {
-                key = e.nextElement();
-                Object object = table.get(key);
-                if (table == stanzaTable) {
-                    System.out.println("[" + key + "]");
-                }
-                if (object instanceof Hashtable) {
-                    if (table != stanzaTable)
-                        System.out.println("\t" + key + " = {");
-                    listTable((Hashtable<String, Object>)object);
-                    if (table != stanzaTable)
-                        System.out.println("\t}");
-
-                } else if (object instanceof String) {
-                    System.out.println("\t" + key + " = " +
-                                (String)table.get(key));
-                } else if (object instanceof Vector) {
-                    v = (Vector<String>)object;
-                    for (int i = 0; i < v.size(); i++) {
-                        System.out.println("\t" + key + " = " + v.elementAt(i));
-                    }
-                }
-            }
-        } else {
-            System.out.println("Configuration file not found.");
-        }
+        System.out.println(this);
     }
 
     /**
-     * Returns the default encryption types.
-     *
+     * Returns all etypes specified in krb5.conf for the given configName,
+     * or all the builtin defaults. This result is always non-empty.
+     * If no etypes are found, an exception is thrown.
      */
-    public int[] defaultEtype(String enctypes) {
+    public int[] defaultEtype(String configName) throws KrbException {
         String default_enctypes;
-        default_enctypes = getDefault(enctypes, "libdefaults");
-        String delim = " ";
-        StringTokenizer st;
+        default_enctypes = get("libdefaults", configName);
         int[] etype;
         if (default_enctypes == null) {
             if (DEBUG) {
                 System.out.println("Using builtin default etypes for " +
-                    enctypes);
+                    configName);
             }
             etype = EType.getBuiltInDefaults();
         } else {
+            String delim = " ";
+            StringTokenizer st;
             for (int j = 0; j < default_enctypes.length(); j++) {
                 if (default_enctypes.substring(j, j + 1).equals(",")) {
                     // only two delimiters are allowed to use
@@ -1020,18 +905,14 @@
             ArrayList<Integer> ls = new ArrayList<>(len);
             int type;
             for (int i = 0; i < len; i++) {
-                type = getType(st.nextToken());
-                if ((type != -1) &&
-                    (EType.isSupported(type))) {
+                type = Config.getType(st.nextToken());
+                if (type != -1 && EType.isSupported(type)) {
                     ls.add(type);
                 }
             }
             if (ls.isEmpty()) {
-                if (DEBUG) {
-                    System.out.println(
-                        "no supported default etypes for " + enctypes);
-                }
-                return null;
+                throw new KrbException("no supported default etypes for "
+                        + configName);
             } else {
                 etype = new int[ls.size()];
                 for (int i = 0; i < etype.length; i++) {
@@ -1041,7 +922,7 @@
         }
 
         if (DEBUG) {
-            System.out.print("default etypes for " + enctypes + ":");
+            System.out.print("default etypes for " + configName + ":");
             for (int i = 0; i < etype.length; i++) {
                 System.out.print(" " + etype[i]);
             }
@@ -1061,7 +942,7 @@
      * checksum type to int value that can be later used by EType and
      * Checksum classes.
      */
-    public int getType(String input) {
+    public static int getType(String input) {
         int result = -1;
         if (input == null) {
             return result;
@@ -1143,11 +1024,11 @@
     public boolean useAddresses() {
         boolean useAddr = false;
         // use addresses if "no_addresses" is set to false
-        String value = getDefault("no_addresses", "libdefaults");
+        String value = get("libdefaults", "no_addresses");
         useAddr = (value != null && value.equalsIgnoreCase("false"));
         if (useAddr == false) {
             // use addresses if "noaddresses" is set to false
-            value = getDefault("noaddresses", "libdefaults");
+            value = get("libdefaults", "noaddresses");
             useAddr = (value != null && value.equalsIgnoreCase("false"));
         }
         return useAddr;
@@ -1157,11 +1038,11 @@
      * Check if need to use DNS to locate Kerberos services
      */
     private boolean useDNS(String name, boolean defaultValue) {
-        Boolean value = getDefaultBooleanObject(name, "libdefaults");
+        Boolean value = getBooleanObject("libdefaults", name);
         if (value != null) {
             return value.booleanValue();
         }
-        value = getDefaultBooleanObject("dns_fallback", "libdefaults");
+        value = getBooleanObject("libdefaults", "dns_fallback");
         if (value != null) {
             return value.booleanValue();
         }
@@ -1171,14 +1052,14 @@
     /**
      * Check if need to use DNS to locate the KDC
      */
-    public boolean useDNS_KDC() {
+    private boolean useDNS_KDC() {
         return useDNS("dns_lookup_kdc", true);
     }
 
     /*
      * Check if need to use DNS to locate the Realm
      */
-    public boolean useDNS_Realm() {
+    private boolean useDNS_Realm() {
         return useDNS("dns_lookup_realm", false);
     }
 
@@ -1192,7 +1073,7 @@
             return defaultRealm;
         }
         Exception cause = null;
-        String realm = getDefault("default_realm", "libdefaults");
+        String realm = get("libdefaults", "default_realm");
         if ((realm == null) && useDNS_Realm()) {
             // use DNS to locate Kerberos realm
             try {
@@ -1239,7 +1120,7 @@
             return defaultKDC;
         }
         Exception cause = null;
-        String kdcs = getDefault("kdc", realm);
+        String kdcs = getAll("realms", realm, "kdc");
         if ((kdcs == null) && useDNS_KDC()) {
             // use DNS to locate KDC
             try {
--- a/src/share/classes/sun/security/krb5/Credentials.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/security/krb5/Credentials.java	Thu Feb 06 01:43:16 2020 +0000
@@ -423,9 +423,11 @@
                 if (DEBUG) {
                     System.out.println(">> Acquire default native Credentials");
                 }
-                int[] etypes = EType.getDefaults("default_tkt_enctypes");
-                if (etypes != null) {
-                    result = acquireDefaultNativeCreds(etypes);
+                try {
+                    result = acquireDefaultNativeCreds(
+                            EType.getDefaults("default_tkt_enctypes"));
+                } catch (KrbException ke) {
+                    // when there is no default_tkt_enctypes.
                 }
             }
         }
@@ -512,4 +514,23 @@
         return buffer.toString();
     }
 
+    public sun.security.krb5.internal.ccache.Credentials toCCacheCreds() {
+        return new sun.security.krb5.internal.ccache.Credentials(
+                getClient(), getServer(),
+                getSessionKey(),
+                date2kt(getAuthTime()),
+                date2kt(getStartTime()),
+                date2kt(getEndTime()),
+                date2kt(getRenewTill()),
+                false,
+                flags,
+                new HostAddresses(getClientAddresses()),
+                getAuthzData(),
+                getTicket(),
+                null);
+    }
+
+    private static KerberosTime date2kt(Date d) {
+        return d == null ? null : new KerberosTime(d);
+    }
 }
--- a/src/share/classes/sun/security/krb5/EncryptedData.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/security/krb5/EncryptedData.java	Thu Feb 06 01:43:16 2020 +0000
@@ -160,8 +160,6 @@
         kvno = key.getKeyVersionNumber();
     }
     */
-
-    // currently destructive on cipher
     public byte[] decrypt(
                           EncryptionKey key, int usage)
         throws KdcErrException, KrbApErrException, KrbCryptoException {
@@ -175,7 +173,8 @@
 
             EType etypeEngine = EType.getInstance(eType);
             plain = etypeEngine.decrypt(cipher, key.getBytes(), usage);
-            cipher = null;
+            // The raw ticket is still needed for the replay cache.
+            //cipher = null;
             return etypeEngine.decryptedData(plain);
         }
 
--- a/src/share/classes/sun/security/krb5/EncryptionKey.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/security/krb5/EncryptionKey.java	Thu Feb 06 01:43:16 2020 +0000
@@ -98,36 +98,6 @@
     }
 
     /**
-     * Obtains the latest version of the secret key of
-     * the principal from a keytab.
-     *
-     * @param princ the principal whose secret key is desired
-     * @param keytab the path to the keytab file. A value of null
-     * will be accepted to indicate that the default path should be
-     * searched.
-     * @returns the secret key or null if none was found.
-     */
-    /*
-    // Replaced by acquireSecretKeys
-    public static EncryptionKey acquireSecretKey(PrincipalName princ,
-                                                 String keytab)
-        throws KrbException, IOException {
-
-        if (princ == null) {
-            throw new IllegalArgumentException(
-                "Cannot have null pricipal name to look in keytab.");
-        }
-
-        KeyTab ktab = KeyTab.getInstance(keytab);
-
-        if (ktab == null)
-            return null;
-
-        return ktab.readServiceKey(princ);
-    }
-    */
-
-    /**
      * Obtains all versions of the secret key of the principal from a
      * keytab.
      *
@@ -208,9 +178,6 @@
             String salt) throws KrbException {
 
         int[] etypes = EType.getDefaults("default_tkt_enctypes");
-        if (etypes == null) {
-            etypes = EType.getBuiltInDefaults();
-        }
 
         EncryptionKey[] encKeys = new EncryptionKey[etypes.length];
         for (int i = 0; i < etypes.length; i++) {
@@ -330,9 +297,11 @@
 
     /**
      * Generates a sub-sessionkey from a given session key.
+     *
+     * Used in AcceptSecContextToken and KrbApReq by acceptor- and initiator-
+     * side respectively.
      */
-     // Used in KrbApRep, KrbApReq
-    EncryptionKey(EncryptionKey key) throws KrbCryptoException {
+    public EncryptionKey(EncryptionKey key) throws KrbCryptoException {
         // generate random sub-session key
         keyValue = Confounder.bytes(key.keyValue.length);
         for (int i = 0; i < keyValue.length; i++) {
--- a/src/share/classes/sun/security/krb5/KdcComm.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/security/krb5/KdcComm.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -142,11 +142,12 @@
 
         try {
             Config cfg = Config.getInstance();
-            String temp = cfg.getDefault("kdc_timeout", "libdefaults");
-            timeout = parsePositiveIntString(temp);
-            temp = cfg.getDefault("max_retries", "libdefaults");
+            String temp = cfg.get("libdefaults", "kdc_timeout");
+            timeout = parseTimeString(temp);
+
+            temp = cfg.get("libdefaults", "max_retries");
             max_retries = parsePositiveIntString(temp);
-            temp = cfg.getDefault("udp_preference_limit", "libdefaults");
+            temp = cfg.get("libdefaults", "udp_preference_limit");
             udf_pref_limit = parsePositiveIntString(temp);
         } catch (Exception exc) {
            // ignore any exceptions; use default values
@@ -406,6 +407,25 @@
     }
 
     /**
+     * Parses a time value string. If it ends with "s", parses as seconds.
+     * Otherwise, parses as milliseconds.
+     * @param s the time string
+     * @return the integer value in milliseconds, or -1 if input is null or
+     * has an invalid format
+     */
+    private static int parseTimeString(String s) {
+        if (s == null) {
+            return -1;
+        }
+        if (s.endsWith("s")) {
+            int seconds = parsePositiveIntString(s.substring(0, s.length()-1));
+            return (seconds < 0) ? -1 : (seconds*1000);
+        } else {
+            return parsePositiveIntString(s);
+        }
+    }
+
+    /**
      * Returns krb5.conf setting of {@code key} for a specific realm,
      * which can be:
      * 1. defined in the sub-stanza for the given realm inside [realms], or
@@ -425,8 +445,12 @@
         int temp = -1;
         try {
             String value =
-               Config.getInstance().getDefault(key, realm);
-            temp = parsePositiveIntString(value);
+               Config.getInstance().get("realms", realm, key);
+            if (key.equals("kdc_timeout")) {
+                temp = parseTimeString(value);
+            } else {
+                temp = parsePositiveIntString(value);
+            }
         } catch (Exception exc) {
             // Ignored, defValue will be picked up
         }
--- a/src/share/classes/sun/security/krb5/KrbApRep.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/security/krb5/KrbApRep.java	Thu Feb 06 01:43:16 2020 +0000
@@ -53,12 +53,10 @@
      */
      // Used in AcceptSecContextToken
     public KrbApRep(KrbApReq incomingReq,
-                    boolean useSeqNumber,
-        boolean useSubKey) throws KrbException, IOException {
+                     boolean useSeqNumber,
+                     EncryptionKey subKey)
+            throws KrbException, IOException {
 
-        EncryptionKey subKey =
-            (useSubKey?
-             new EncryptionKey(incomingReq.getCreds().getSessionKey()):null);
         SeqNumber seqNum = new LocalSeqNumber();
 
         init(incomingReq, subKey, seqNum);
--- a/src/share/classes/sun/security/krb5/KrbApReq.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/security/krb5/KrbApReq.java	Thu Feb 06 01:43:16 2020 +0000
@@ -33,11 +33,13 @@
 
 import sun.security.krb5.internal.*;
 import sun.security.krb5.internal.crypto.*;
-import sun.security.krb5.internal.rcache.*;
 import java.net.InetAddress;
 import sun.security.util.*;
 import java.io.IOException;
 import java.util.Arrays;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import sun.security.krb5.internal.rcache.AuthTimeWithHash;
 
 /**
  * This class encapsulates a KRB-AP-REQ that a client sends to a
@@ -52,11 +54,23 @@
     private Credentials creds;
     private APReq apReqMessg;
 
-    private static CacheTable table = new CacheTable();
+    // Used by acceptor side
+    private static ReplayCache rcache = ReplayCache.getInstance();
     private static boolean DEBUG = Krb5.DEBUG;
+    private static final char[] hexConst = "0123456789ABCDEF".toCharArray();
+
+    private static final MessageDigest md;
+
+    static {
+        try {
+            md = MessageDigest.getInstance("MD5");
+        } catch (NoSuchAlgorithmException ex) {
+            throw new RuntimeException("Impossible");
+        }
+    }
 
     /**
-     * Contructs a AP-REQ message to send to the peer.
+     * Constructs an AP-REQ message to send to the peer.
      * @param tgsCred the <code>Credentials</code> to be used to construct the
      *          AP Request  protocol message.
      * @param mutualRequired Whether mutual authentication is required
@@ -80,7 +94,7 @@
 */
 
     /**
-     * Contructs a AP-REQ message to send to the peer.
+     * Constructs an AP-REQ message to send to the peer.
      * @param tgsCred the <code>Credentials</code> to be used to construct the
      *          AP Request  protocol message.
      * @param mutualRequired Whether mutual authentication is required
@@ -124,7 +138,7 @@
     }
 
     /**
-     * Contructs a AP-REQ message from the bytes received from the
+     * Constructs an AP-REQ message from the bytes received from the
      * peer.
      * @param message The message received from the peer
      * @param keys <code>EncrtyptionKey</code>s to decrypt the message;
@@ -145,7 +159,7 @@
     }
 
     /**
-     * Contructs a AP-REQ message from the bytes received from the
+     * Constructs an AP-REQ message from the bytes received from the
      * peer.
      * @param value The <code>DerValue</code> that contains the
      *              DER enoded AP-REQ protocol message
@@ -203,7 +217,7 @@
         int usage)
         throws KrbException, IOException {
 
-        ctime = new KerberosTime(KerberosTime.NOW);
+        ctime = KerberosTime.now();
         init(options,
              tgs_creds.ticket,
              tgs_creds.key,
@@ -285,24 +299,28 @@
         authenticator = new Authenticator(temp2);
         ctime = authenticator.ctime;
         cusec = authenticator.cusec;
-        authenticator.ctime.setMicroSeconds(authenticator.cusec);
+        authenticator.ctime =
+                authenticator.ctime.withMicroSeconds(authenticator.cusec);
 
         if (!authenticator.cname.equals(enc_ticketPart.cname))
             throw new KrbApErrException(Krb5.KRB_AP_ERR_BADMATCH);
 
-        KerberosTime currTime = new KerberosTime(KerberosTime.NOW);
-        if (!authenticator.ctime.inClockSkew(currTime))
+        if (!authenticator.ctime.inClockSkew())
             throw new KrbApErrException(Krb5.KRB_AP_ERR_SKEW);
 
-        // start to check if it is a replay attack.
-        AuthTime time =
-            new AuthTime(authenticator.ctime.getTime(), authenticator.cusec);
-        String client = authenticator.cname.toString();
-        if (table.get(time, authenticator.cname.toString()) != null) {
-            throw new KrbApErrException(Krb5.KRB_AP_ERR_REPEAT);
-        } else {
-            table.put(client, time, currTime.getTime());
+        byte[] hash = md.digest(apReqMessg.authenticator.cipher);
+        char[] h = new char[hash.length * 2];
+        for (int i=0; i<hash.length; i++) {
+            h[2*i] = hexConst[(hash[i]&0xff)>>4];
+            h[2*i+1] = hexConst[hash[i]&0xf];
         }
+        AuthTimeWithHash time = new AuthTimeWithHash(
+                authenticator.cname.toString(),
+                apReqMessg.ticket.sname.toString(),
+                authenticator.ctime.getSeconds(),
+                authenticator.cusec,
+                new String(h));
+        rcache.checkAndStore(KerberosTime.now(), time);
 
         if (initiator != null) {
             // sender host address
@@ -326,7 +344,7 @@
         // else
         //    save authenticator to check for later
 
-        KerberosTime now = new KerberosTime(KerberosTime.NOW);
+        KerberosTime now = KerberosTime.now();
 
         if ((enc_ticketPart.starttime != null &&
              enc_ticketPart.starttime.greaterThanWRTClockSkew(now)) ||
@@ -487,10 +505,6 @@
      // Check that key is one of the permitted types
      private static void checkPermittedEType(int target) throws KrbException {
         int[] etypes = EType.getDefaults("permitted_enctypes");
-        if (etypes == null) {
-            throw new KrbException(
-                "No supported encryption types listed in permitted_enctypes");
-        }
         if (!EType.isSupported(target, etypes)) {
             throw new KrbException(EType.toString(target) +
                 " encryption type not in permitted_enctypes list");
--- a/src/share/classes/sun/security/krb5/KrbAppMessage.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/security/krb5/KrbAppMessage.java	Thu Feb 06 01:43:16 2020 +0000
@@ -71,12 +71,18 @@
         }
 
         if (packetTimestamp != null) {
-            packetTimestamp.setMicroSeconds(packetUsec);
-            if (!packetTimestamp.inClockSkew())
+            if (packetUsec != null) {
+                packetTimestamp =
+                    packetTimestamp.withMicroSeconds(packetUsec.intValue());
+            }
+            if (!packetTimestamp.inClockSkew()) {
                 throw new KrbApErrException(Krb5.KRB_AP_ERR_SKEW);
-        } else
-            if (timestampRequired)
+            }
+        } else {
+            if (timestampRequired) {
                 throw new KrbApErrException(Krb5.KRB_AP_ERR_SKEW);
+            }
+        }
 
         // XXX check replay cache
         // if (rcache.repeated(packetTimestamp, packetUsec, packetSAddress))
--- a/src/share/classes/sun/security/krb5/KrbAsReq.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/security/krb5/KrbAsReq.java	Thu Feb 06 01:43:16 2020 +0000
@@ -34,7 +34,9 @@
 import sun.security.krb5.internal.*;
 import sun.security.krb5.internal.crypto.Nonce;
 import sun.security.krb5.internal.crypto.KeyUsage;
+
 import java.io.IOException;
+import java.util.Calendar;
 
 /**
  * This class encapsulates the KRB-AS-REQ message that the client
@@ -64,7 +66,6 @@
         if (options == null) {
             options = new KDCOptions();
         }
-
         // check if they are valid arguments. The optional fields should be
         // consistent with settings in KDCOptions. Mar 17 2000
         if (options.get(KDCOptions.FORWARDED) ||
@@ -82,12 +83,6 @@
         } else {
             if (from != null)  from = null;
         }
-        if (options.get(KDCOptions.RENEWABLE)) {
-            //  if (rtime == null)
-            //          throw new KrbException(Krb5.KRB_AP_ERR_REQ_OPTIONS);
-        } else {
-            if (rtime != null)  rtime = null;
-        }
 
         PAData[] paData = null;
         if (pakey != null) {
@@ -109,8 +104,10 @@
             System.out.println(">>> KrbAsReq creating message");
         }
 
+        Config cfg = Config.getInstance();
+
         // check to use addresses in tickets
-        if (addresses == null && Config.getInstance().useAddresses()) {
+        if (addresses == null && cfg.useAddresses()) {
             addresses = HostAddresses.getLocalAddresses();
         }
 
@@ -120,7 +117,30 @@
         }
 
         if (till == null) {
-            till = new KerberosTime(0); // Choose KDC maximum allowed
+            String d = cfg.get("libdefaults", "ticket_lifetime");
+            if (d != null) {
+                Calendar cal = Calendar.getInstance();
+                cal.add(Calendar.SECOND, Config.duration(d));
+                till = new KerberosTime(cal.getTime());
+            } else {
+                till = new KerberosTime(0); // Choose KDC maximum allowed
+            }
+        }
+
+        if (rtime == null) {
+            String d = cfg.get("libdefaults", "renew_lifetime");
+            if (d != null) {
+                Calendar cal = Calendar.getInstance();
+                cal.add(Calendar.SECOND, Config.duration(d));
+                rtime = new KerberosTime(cal.getTime());
+            }
+        }
+
+        if (rtime != null) {
+            options.set(KDCOptions.RENEWABLE, true);
+            if (till.greaterThan(rtime)) {
+                rtime = till;
+            }
         }
 
         // enc-authorization-data and additional-tickets never in AS-REQ
--- a/src/share/classes/sun/security/krb5/KrbAsReqBuilder.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/security/krb5/KrbAsReqBuilder.java	Thu Feb 06 01:43:16 2020 +0000
@@ -224,6 +224,16 @@
         this.options = options;
     }
 
+    public void setTill(KerberosTime till) {
+        checkState(State.INIT, "Cannot specify till");
+        this.till = till;
+    }
+
+    public void setRTime(KerberosTime rtime) {
+        checkState(State.INIT, "Cannot specify rtime");
+        this.rtime = rtime;
+    }
+
     /**
      * Sets or clears target. If cleared, KrbAsReq might choose krbtgt
      * for cname realm
--- a/src/share/classes/sun/security/krb5/KrbCred.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/security/krb5/KrbCred.java	Thu Feb 06 01:43:16 2020 +0000
@@ -34,6 +34,7 @@
 import sun.security.krb5.internal.*;
 import sun.security.krb5.internal.crypto.KeyUsage;
 import java.io.IOException;
+
 import sun.security.util.DerValue;
 
 /**
@@ -62,7 +63,6 @@
 
         PrincipalName client = tgt.getClient();
         PrincipalName tgService = tgt.getServer();
-        PrincipalName server = serviceTicket.getServer();
         if (!serviceTicket.getClient().equals(client))
             throw new KrbException(Krb5.KRB_ERR_GENERIC,
                                 "Client principal does not match");
@@ -75,14 +75,10 @@
         options.set(KDCOptions.FORWARDED, true);
         options.set(KDCOptions.FORWARDABLE, true);
 
-        HostAddresses sAddrs = null;
-        // XXX Also NT_GSS_KRB5_PRINCIPAL can be a host based principal
-        // GSSName.NT_HOSTBASED_SERVICE should display with KRB_NT_SRV_HST
-        if (server.getNameType() == PrincipalName.KRB_NT_SRV_HST)
-            sAddrs=  new HostAddresses(server);
-
         KrbTgsReq tgsReq = new KrbTgsReq(options, tgt, tgService,
-                                         null, null, null, null, sAddrs, null, null, null);
+                null, null, null, null,
+                null,   // No easy way to get addresses right
+                null, null, null);
         credMessg = createMessage(tgsReq.sendAndGetCreds(), key);
 
         obuf = credMessg.asn1Encode();
@@ -94,7 +90,6 @@
         EncryptionKey sessionKey
             = delegatedCreds.getSessionKey();
         PrincipalName princ = delegatedCreds.getClient();
-        Realm realm = princ.getRealm();
         PrincipalName tgService = delegatedCreds.getServer();
 
         KrbCredInfo credInfo = new KrbCredInfo(sessionKey,
@@ -103,7 +98,7 @@
                                                delegatedCreds.renewTill, tgService,
                                                delegatedCreds.cAddr);
 
-        timeStamp = new KerberosTime(KerberosTime.NOW);
+        timeStamp = KerberosTime.now();
         KrbCredInfo[] credInfos = {credInfo};
         EncKrbCredPart encPart =
             new EncKrbCredPart(credInfos,
--- a/src/share/classes/sun/security/krb5/KrbKdcRep.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/security/krb5/KrbKdcRep.java	Thu Feb 06 01:43:16 2020 +0000
@@ -69,55 +69,49 @@
             }
         }
 
-        // XXX Can renew a ticket but not ask for a renewable renewed ticket
-        // See impl of Credentials.renew().
-        if (req.reqBody.kdcOptions.get(KDCOptions.RENEWABLE) !=
-            rep.encKDCRepPart.flags.get(KDCOptions.RENEWABLE)) {
+        // Reply to a renewable request should be renewable, but if request does
+        // not contain renewable, KDC is free to issue a renewable ticket (for
+        // example, if ticket_lifetime is too big).
+        if (req.reqBody.kdcOptions.get(KDCOptions.RENEWABLE) &&
+                !rep.encKDCRepPart.flags.get(KDCOptions.RENEWABLE)) {
             throw new KrbApErrException(Krb5.KRB_AP_ERR_MODIFIED);
         }
-        if ((req.reqBody.from == null) || req.reqBody.from.isZero())
+
+        if ((req.reqBody.from == null) || req.reqBody.from.isZero()) {
             // verify this is allowed
             if ((rep.encKDCRepPart.starttime != null) &&
-                !rep.encKDCRepPart.starttime.inClockSkew()) {
+                    !rep.encKDCRepPart.starttime.inClockSkew()) {
                 rep.encKDCRepPart.key.destroy();
                 throw new KrbApErrException(Krb5.KRB_AP_ERR_SKEW);
             }
+        }
 
-        if ((req.reqBody.from != null) && !req.reqBody.from.isZero())
+        if ((req.reqBody.from != null) && !req.reqBody.from.isZero()) {
             // verify this is allowed
             if ((rep.encKDCRepPart.starttime != null) &&
-                !req.reqBody.from.equals(rep.encKDCRepPart.starttime)) {
+                    !req.reqBody.from.equals(rep.encKDCRepPart.starttime)) {
                 rep.encKDCRepPart.key.destroy();
                 throw new KrbApErrException(Krb5.KRB_AP_ERR_MODIFIED);
             }
+        }
 
         if (!req.reqBody.till.isZero() &&
-            rep.encKDCRepPart.endtime.greaterThan(req.reqBody.till)) {
+                rep.encKDCRepPart.endtime.greaterThan(req.reqBody.till)) {
             rep.encKDCRepPart.key.destroy();
             throw new KrbApErrException(Krb5.KRB_AP_ERR_MODIFIED);
         }
 
-        if (req.reqBody.kdcOptions.get(KDCOptions.RENEWABLE))
-            if (req.reqBody.rtime != null && !req.reqBody.rtime.isZero())
-                                // verify this is required
+        if (req.reqBody.kdcOptions.get(KDCOptions.RENEWABLE)) {
+            if (req.reqBody.rtime != null && !req.reqBody.rtime.isZero()) {
+                // verify this is required
                 if ((rep.encKDCRepPart.renewTill == null) ||
-                    rep.encKDCRepPart.renewTill.greaterThan(req.reqBody.rtime)
-                    ) {
+                        rep.encKDCRepPart.renewTill.greaterThan(req.reqBody.rtime)
+                        ) {
                     rep.encKDCRepPart.key.destroy();
                     throw new KrbApErrException(Krb5.KRB_AP_ERR_MODIFIED);
                 }
 
-        if (req.reqBody.kdcOptions.get(KDCOptions.RENEWABLE_OK) &&
-            rep.encKDCRepPart.flags.get(KDCOptions.RENEWABLE))
-            if (!req.reqBody.till.isZero())
-                                // verify this is required
-                if ((rep.encKDCRepPart.renewTill == null) ||
-                    rep.encKDCRepPart.renewTill.greaterThan(req.reqBody.till)
-                    ) {
-                    rep.encKDCRepPart.key.destroy();
-                    throw new KrbApErrException(Krb5.KRB_AP_ERR_MODIFIED);
-                }
+            }
+        }
     }
-
-
 }
--- a/src/share/classes/sun/security/krb5/KrbTgsReq.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/security/krb5/KrbTgsReq.java	Thu Feb 06 01:43:16 2020 +0000
@@ -33,8 +33,10 @@
 
 import sun.security.krb5.internal.*;
 import sun.security.krb5.internal.crypto.*;
+
 import java.io.IOException;
 import java.net.UnknownHostException;
+import java.util.Calendar;
 
 /**
  * This class encapsulates a Kerberos TGS-REQ that is sent from the
@@ -88,8 +90,7 @@
 
         princName = asCreds.client;
         servName = sname;
-        ctime = new KerberosTime(KerberosTime.NOW);
-
+        ctime = KerberosTime.now();
 
         // check if they are valid arguments. The optional fields
         // should be  consistent with settings in KDCOptions.
@@ -222,11 +223,17 @@
                          AuthorizationData authorizationData,
                          Ticket[] additionalTickets,
                          EncryptionKey subKey)
-        throws Asn1Exception, IOException, KdcErrException, KrbApErrException,
-               UnknownHostException, KrbCryptoException {
+        throws IOException, KrbException, UnknownHostException {
         KerberosTime req_till = null;
         if (till == null) {
-            req_till = new KerberosTime(0);
+            String d = Config.getInstance().get("libdefaults", "ticket_lifetime");
+            if (d != null) {
+                Calendar cal = Calendar.getInstance();
+                cal.add(Calendar.SECOND, Config.duration(d));
+                req_till = new KerberosTime(cal.getTime());
+            } else {
+                req_till = new KerberosTime(0); // Choose KDC maximum allowed
+            }
         } else {
             req_till = till;
         }
@@ -245,10 +252,6 @@
         int[] req_eTypes = null;
         if (eTypes == null) {
             req_eTypes = EType.getDefaults("default_tgs_enctypes");
-            if (req_eTypes == null) {
-                throw new KrbCryptoException(
-            "No supported encryption types listed in default_tgs_enctypes");
-            }
         } else {
             req_eTypes = eTypes;
         }
@@ -284,26 +287,8 @@
         byte[] temp = reqBody.asn1Encode(Krb5.KRB_TGS_REQ);
         // if the checksum type is one of the keyed checksum types,
         // use session key.
-        Checksum cksum;
-        switch (Checksum.CKSUMTYPE_DEFAULT) {
-        case Checksum.CKSUMTYPE_RSA_MD4_DES:
-        case Checksum.CKSUMTYPE_DES_MAC:
-        case Checksum.CKSUMTYPE_DES_MAC_K:
-        case Checksum.CKSUMTYPE_RSA_MD4_DES_K:
-        case Checksum.CKSUMTYPE_RSA_MD5_DES:
-        case Checksum.CKSUMTYPE_HMAC_SHA1_DES3_KD:
-        case Checksum.CKSUMTYPE_HMAC_MD5_ARCFOUR:
-        case Checksum.CKSUMTYPE_HMAC_SHA1_96_AES128:
-        case Checksum.CKSUMTYPE_HMAC_SHA1_96_AES256:
-            cksum = new Checksum(Checksum.CKSUMTYPE_DEFAULT, temp, key,
+        Checksum cksum  = new Checksum(Checksum.CKSUMTYPE_DEFAULT, temp, key,
                 KeyUsage.KU_PA_TGS_REQ_CKSUM);
-            break;
-        case Checksum.CKSUMTYPE_CRC32:
-        case Checksum.CKSUMTYPE_RSA_MD4:
-        case Checksum.CKSUMTYPE_RSA_MD5:
-        default:
-            cksum = new Checksum(Checksum.CKSUMTYPE_DEFAULT, temp);
-        }
 
         // Usage will be KeyUsage.KU_PA_TGS_REQ_AUTHENTICATOR
 
--- a/src/share/classes/sun/security/krb5/PrincipalName.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/security/krb5/PrincipalName.java	Thu Feb 06 01:43:16 2020 +0000
@@ -663,19 +663,19 @@
         try {
             String subname = null;
             Config c = Config.getInstance();
-            if ((result = c.getDefault(name, "domain_realm")) != null)
+            if ((result = c.get("domain_realm", name)) != null)
                 return result;
             else {
                 for (int i = 1; i < name.length(); i++) {
                     if ((name.charAt(i) == '.') && (i != name.length() - 1)) { //mapping could be .ibm.com = AUSTIN.IBM.COM
                         subname = name.substring(i);
-                        result = c.getDefault(subname, "domain_realm");
+                        result = c.get("domain_realm", subname);
                         if (result != null) {
                             break;
                         }
                         else {
                             subname = name.substring(i + 1);      //or mapping could be ibm.com = AUSTIN.IBM.COM
-                            result = c.getDefault(subname, "domain_realm");
+                            result = c.get("domain_realm", subname);
                             if (result != null) {
                                 break;
                             }
--- a/src/share/classes/sun/security/krb5/Realm.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/security/krb5/Realm.java	Thu Feb 06 01:43:16 2020 +0000
@@ -366,7 +366,7 @@
             return null;
         }
 
-        String intermediaries = cfg.getDefault(sRealm, cRealm);
+        String intermediaries = cfg.getAll("capaths", cRealm, sRealm);
 
         if (intermediaries == null) {
             if (DEBUG) {
@@ -379,7 +379,7 @@
 
         String head = sRealm;
         while (true) {
-            String value = cfg.getDefault(head, cRealm);
+            String value = cfg.getAll("capaths", cRealm, head);
             if (value == null) {
                 break;
             }
--- a/src/share/classes/sun/security/krb5/SCDynamicStoreConfig.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/security/krb5/SCDynamicStoreConfig.java	Thu Feb 06 01:43:16 2020 +0000
@@ -34,13 +34,25 @@
 public class SCDynamicStoreConfig {
     private static native void installNotificationCallback();
     private static native Hashtable<String, Object> getKerberosConfig();
+    private static boolean DEBUG = sun.security.krb5.internal.Krb5.DEBUG;
 
     static {
-        java.security.AccessController.doPrivileged(new sun.security.action.LoadLibraryAction("osx"));
-        installNotificationCallback();
+        boolean isMac = java.security.AccessController.doPrivileged(
+            new java.security.PrivilegedAction<Boolean>() {
+                public Boolean run() {
+                    String osname = System.getProperty("os.name");
+                    if (osname.contains("OS X")) {
+                        System.loadLibrary("osx");
+                        return true;
+                    }
+                    return false;
+                }
+            });
+        if (isMac) installNotificationCallback();
     }
 
-    private static Vector<String> unwrapHost(Collection<Hashtable<String, String>> c) {
+    private static Vector<String> unwrapHost(
+            Collection<Hashtable<String, String>> c) {
         Vector<String> vector = new Vector<String>();
         for (Hashtable<String, String> m : c) {
             vector.add(m.get("host"));
@@ -54,20 +66,25 @@
      * are wrapped inside Hashtables
      */
     @SuppressWarnings("unchecked")
-    private static Hashtable<String, Object> convertRealmConfigs(Hashtable<String, ?> configs) {
+    private static Hashtable<String, Object>
+            convertRealmConfigs(Hashtable<String, ?> configs) {
         Hashtable<String, Object> realmsTable = new Hashtable<String, Object>();
 
         for (String realm : configs.keySet()) {
             // get the kdc
-            Hashtable<String, Collection<?>> map = (Hashtable<String, Collection<?>>) configs.get(realm);
-            Collection<Hashtable<String, String>> kdc = (Collection<Hashtable<String, String>>) map.get("kdc");
+            Hashtable<String, Collection<?>> map =
+                    (Hashtable<String, Collection<?>>) configs.get(realm);
+            Hashtable<String, Vector<String>> realmMap =
+                    new Hashtable<String, Vector<String>>();
 
             // put the kdc into the realmMap
-            Hashtable<String, Vector<String>> realmMap = new Hashtable<String, Vector<String>>();
+            Collection<Hashtable<String, String>> kdc =
+                    (Collection<Hashtable<String, String>>) map.get("kdc");
             if (kdc != null) realmMap.put("kdc", unwrapHost(kdc));
 
             // put the admin server into the realmMap
-            Collection<Hashtable<String, String>> kadmin = (Collection<Hashtable<String, String>>) map.get("kadmin");
+            Collection<Hashtable<String, String>> kadmin =
+                    (Collection<Hashtable<String, String>>) map.get("kadmin");
             if (kadmin != null) realmMap.put("admin_server", unwrapHost(kadmin));
 
             // add the full entry to the realmTable
@@ -84,23 +101,44 @@
      * @return
      * @throws IOException
      */
-    @SuppressWarnings("unchecked")
     public static Hashtable<String, Object> getConfig() throws IOException {
         Hashtable<String, Object> stanzaTable = getKerberosConfig();
         if (stanzaTable == null) {
-            throw new IOException("Could not load configuration from SCDynamicStore");
+            throw new IOException(
+                    "Could not load configuration from SCDynamicStore");
         }
-        //System.out.println("Raw map from JNI: " + stanzaTable);
+        if (DEBUG) System.out.println("Raw map from JNI: " + stanzaTable);
+        return convertNativeConfig(stanzaTable);
+    }
 
+    @SuppressWarnings("unchecked")
+    private static Hashtable<String, Object> convertNativeConfig(
+            Hashtable<String, Object> stanzaTable) {
         // convert SCDynamicStore realm structure to Java realm structure
-        Hashtable<String, ?> realms = (Hashtable<String, ?>) stanzaTable.get("realms");
+        Hashtable<String, ?> realms =
+                (Hashtable<String, ?>) stanzaTable.get("realms");
         if (realms != null) {
             stanzaTable.remove("realms");
             Hashtable<String, Object> realmsTable = convertRealmConfigs(realms);
             stanzaTable.put("realms", realmsTable);
         }
+        WrapAllStringInVector(stanzaTable);
+        if (DEBUG) System.out.println("stanzaTable : " + stanzaTable);
+        return stanzaTable;
+    }
 
-       // System.out.println("stanzaTable : " + stanzaTable);
-        return (Hashtable<String, Object>) stanzaTable;
+    @SuppressWarnings("unchecked")
+    private static void WrapAllStringInVector(
+            Hashtable<String, Object> stanzaTable) {
+        for (String s: stanzaTable.keySet()) {
+            Object v = stanzaTable.get(s);
+            if (v instanceof Hashtable) {
+                WrapAllStringInVector((Hashtable<String,Object>)v);
+            } else if (v instanceof String) {
+                Vector<String> vec = new Vector<>();
+                vec.add((String)v);
+                stanzaTable.put(s, vec);
+            }
+        }
     }
 }
--- a/src/share/classes/sun/security/krb5/internal/HostAddress.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/security/krb5/internal/HostAddress.java	Thu Feb 06 01:43:16 2020 +0000
@@ -39,6 +39,7 @@
 import java.net.Inet6Address;
 import java.net.UnknownHostException;
 import java.io.IOException;
+import java.util.Arrays;
 
 /**
  * Implements the ASN.1 HostAddress type.
@@ -295,4 +296,11 @@
         }
     }
 
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append(Arrays.toString(address));
+        sb.append('(').append(addrType).append(')');
+        return sb.toString();
+    }
 }
--- a/src/share/classes/sun/security/krb5/internal/HostAddresses.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/security/krb5/internal/HostAddresses.java	Thu Feb 06 01:43:16 2020 +0000
@@ -31,16 +31,14 @@
 
 package sun.security.krb5.internal;
 
+import sun.security.krb5.Config;
 import sun.security.krb5.PrincipalName;
 import sun.security.krb5.KrbException;
 import sun.security.krb5.Asn1Exception;
 import sun.security.util.*;
-import java.util.Vector;
-import java.util.ArrayList;
-import java.net.InetAddress;
-import java.net.Inet4Address;
-import java.net.Inet6Address;
-import java.net.UnknownHostException;
+
+import java.net.*;
+import java.util.*;
 import java.io.IOException;
 import sun.security.krb5.internal.ccache.CCacheOutputStream;
 
@@ -250,6 +248,10 @@
          */
 
     public void writeAddrs(CCacheOutputStream cos) throws IOException {
+        if (addresses == null || addresses.length == 0) {
+            cos.write32(0);
+            return;
+        }
         cos.write32(addresses.length);
         for (int i = 0; i < addresses.length; i++) {
             cos.write16(addresses[i].addrType);
@@ -289,34 +291,35 @@
      */
     public static HostAddresses getLocalAddresses() throws IOException
     {
-        String hostname = null;
-        InetAddress[] inetAddresses = null;
+        Set<InetAddress> all = new LinkedHashSet<>();
         try {
-            InetAddress localHost = InetAddress.getLocalHost();
-            hostname = localHost.getHostName();
-            inetAddresses = InetAddress.getAllByName(hostname);
-            HostAddress[] hAddresses = new HostAddress[inetAddresses.length];
-            for (int i = 0; i < inetAddresses.length; i++)
-                {
-                    hAddresses[i] = new HostAddress(inetAddresses[i]);
-                }
             if (DEBUG) {
-                System.out.println(">>> KrbKdcReq local addresses for "
-                                   + hostname + " are: ");
-
-                for (int i = 0; i < inetAddresses.length; i++) {
-                    System.out.println("\n\t" + inetAddresses[i]);
-                    if (inetAddresses[i] instanceof Inet4Address)
-                        System.out.println("IPv4 address");
-                    if (inetAddresses[i] instanceof Inet6Address)
-                        System.out.println("IPv6 address");
+                System.out.println(">>> KrbKdcReq local addresses are:");
+            }
+            String extra = Config.getInstance().getAll(
+                    "libdefaults", "extra_addresses");
+            if (extra != null) {
+                for (String s: extra.split("\\s+")) {
+                    all.add(InetAddress.getByName(s));
+                    if (DEBUG) {
+                        System.out.println("   extra_addresses: "
+                                + InetAddress.getByName(s));
+                    }
                 }
             }
-            return (new HostAddresses(hAddresses));
+            for (NetworkInterface ni:
+                    Collections.list(NetworkInterface.getNetworkInterfaces())) {
+                if (DEBUG) {
+                    System.out.println("   NetworkInterface " + ni + ":");
+                    System.out.println("      "
+                            + Collections.list(ni.getInetAddresses()));
+                }
+                all.addAll(Collections.list(ni.getInetAddresses()));
+            }
+            return new HostAddresses(all.toArray(new InetAddress[all.size()]));
         } catch (Exception exc) {
             throw new IOException(exc.toString());
         }
-
     }
 
     /**
@@ -335,4 +338,9 @@
         for (int i = 0; i < inetAddresses.length; i++)
             addresses[i] = new HostAddress(inetAddresses[i]);
     }
+
+    @Override
+    public String toString() {
+        return Arrays.toString(addresses);
+    }
 }
--- a/src/share/classes/sun/security/krb5/internal/KDCOptions.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/security/krb5/internal/KDCOptions.java	Thu Feb 06 01:43:16 2020 +0000
@@ -244,25 +244,23 @@
 
             Config config = Config.getInstance();
 
-            /*
-             * First see if the IBM hex format is being used.
-             * If not, try the Sun's string (boolean) format.
-             */
+            // If key not present, returns Integer.MIN_VALUE, which is
+            // almost all zero.
 
-            int options =config.getDefaultIntValue("kdc_default_options",
-                    "libdefaults");
+            int options = config.getIntValue("libdefaults",
+                    "kdc_default_options");
 
             if ((options & RENEWABLE_OK) == RENEWABLE_OK) {
                 set(RENEWABLE_OK, true);
             } else {
-                if (config.getDefaultBooleanValue("renewable", "libdefaults")) {
+                if (config.getBooleanValue("libdefaults", "renewable")) {
                     set(RENEWABLE_OK, true);
                 }
             }
             if ((options & PROXIABLE) == PROXIABLE) {
                 set(PROXIABLE, true);
             } else {
-                if (config.getDefaultBooleanValue("proxiable", "libdefaults")) {
+                if (config.getBooleanValue("libdefaults", "proxiable")) {
                     set(PROXIABLE, true);
                 }
             }
@@ -270,7 +268,7 @@
             if ((options & FORWARDABLE) == FORWARDABLE) {
                 set(FORWARDABLE, true);
             } else {
-                if (config.getDefaultBooleanValue("forwardable", "libdefaults")) {
+                if (config.getBooleanValue("libdefaults", "forwardable")) {
                     set(FORWARDABLE, true);
                 }
             }
--- a/src/share/classes/sun/security/krb5/internal/KDCReq.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/security/krb5/internal/KDCReq.java	Thu Feb 06 01:43:16 2020 +0000
@@ -59,9 +59,9 @@
 public class KDCReq {
 
     public KDCReqBody reqBody;
+    public PAData[] pAData = null; //optional
     private int pvno;
     private int msgType;
-    private PAData[] pAData = null; //optional
 
     public KDCReq(PAData[] new_pAData, KDCReqBody new_reqBody,
             int req_type) throws IOException {
--- a/src/share/classes/sun/security/krb5/internal/KerberosTime.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/security/krb5/internal/KerberosTime.java	Thu Feb 06 01:43:16 2020 +0000
@@ -30,18 +30,20 @@
 
 package sun.security.krb5.internal;
 
-import java.util.TimeZone;
-import sun.security.util.*;
+import sun.security.krb5.Asn1Exception;
 import sun.security.krb5.Config;
 import sun.security.krb5.KrbException;
-import sun.security.krb5.Asn1Exception;
+import sun.security.util.DerInputStream;
+import sun.security.util.DerOutputStream;
+import sun.security.util.DerValue;
+
+import java.io.IOException;
+import java.util.Calendar;
 import java.util.Date;
-import java.util.GregorianCalendar;
-import java.util.Calendar;
-import java.io.IOException;
+import java.util.TimeZone;
 
 /**
- * Implements the ASN.1 KerberosTime type.
+ * Implements the ASN.1 KerberosTime type. This is an immutable class.
  *
  * <xmp>
  * KerberosTime    ::= GeneralizedTime -- with no fractional seconds
@@ -62,55 +64,38 @@
  * same class can be used as a precise timestamp in Authenticator etc.
  */
 
-public class KerberosTime implements Cloneable {
+public class KerberosTime {
 
-    private long kerberosTime; // milliseconds since epoch, a Date.getTime() value
-    private int  microSeconds; // the last three digits of the microsecond value
+    private final long kerberosTime; // milliseconds since epoch, Date.getTime()
+    private final int  microSeconds; // last 3 digits of the real microsecond
 
     // The time when this class is loaded. Used in setNow()
     private static long initMilli = System.currentTimeMillis();
     private static long initMicro = System.nanoTime() / 1000;
 
-    private static long syncTime;
     private static boolean DEBUG = Krb5.DEBUG;
 
-    public static final boolean NOW = true;
-    public static final boolean UNADJUSTED_NOW = false;
-
-    public KerberosTime(long time) {
-        kerberosTime = time;
-    }
-
+    // Do not make this public. It's a little confusing that micro
+    // is only the last 3 digits of microsecond.
     private KerberosTime(long time, int micro) {
         kerberosTime = time;
         microSeconds = micro;
     }
 
-    public Object clone() {
-        return new KerberosTime(kerberosTime, microSeconds);
+    /**
+     * Creates a KerberosTime object from milliseconds since epoch.
+     */
+    public KerberosTime(long time) {
+        this(time, 0);
     }
 
     // This constructor is used in the native code
     // src/windows/native/sun/security/krb5/NativeCreds.c
     public KerberosTime(String time) throws Asn1Exception {
-        kerberosTime = toKerberosTime(time);
-    }
-
-    /**
-     * Constructs a KerberosTime object.
-     * @param encoding a DER-encoded data.
-     * @exception Asn1Exception if an error occurs while decoding an ASN1 encoded data.
-     * @exception IOException if an I/O error occurs while reading encoded data.
-     */
-    public KerberosTime(DerValue encoding) throws Asn1Exception, IOException {
-        GregorianCalendar calendar = new GregorianCalendar();
-        Date temp = encoding.getGeneralizedTime();
-        kerberosTime = temp.getTime();
+        this(toKerberosTime(time), 0);
     }
 
     private static long toKerberosTime(String time) throws Asn1Exception {
-        // this method only used by KerberosTime class.
-
         // ASN.1 GeneralizedTime format:
 
         // "19700101000000Z"
@@ -133,30 +118,34 @@
                      Integer.parseInt(time.substring(8, 10)),
                      Integer.parseInt(time.substring(10, 12)),
                      Integer.parseInt(time.substring(12, 14)));
+        return calendar.getTimeInMillis();
+    }
 
-        //The Date constructor assumes the setting are local relative
-        //and converts the time to UTC before storing it.  Since we
-        //want the internal representation to correspond to local
-        //and not UTC time we subtract the UTC time offset.
-        return (calendar.getTime().getTime());
-
+    /**
+     * Creates a KerberosTime object from a Date object.
+     */
+    public KerberosTime(Date time) {
+        this(time.getTime(), 0);
     }
 
-    // should be moved to sun.security.krb5.util class
-    public static String zeroPad(String s, int length) {
-        StringBuffer temp = new StringBuffer(s);
-        while (temp.length() < length)
-            temp.insert(0, '0');
-        return temp.toString();
-    }
-
-    public KerberosTime(Date time) {
-        kerberosTime = time.getTime(); // (time.getTimezoneOffset() * 60000L);
-    }
-
-    public KerberosTime(boolean initToNow) {
-        if (initToNow) {
-            setNow();
+    /**
+     * Creates a KerberosTime object for now. It uses System.nanoTime()
+     * to get a more precise time than "new Date()".
+     */
+    public static KerberosTime now() {
+        long newMilli = System.currentTimeMillis();
+        long newMicro = System.nanoTime() / 1000;
+        long microElapsed = newMicro - initMicro;
+        long calcMilli = initMilli + microElapsed/1000;
+        if (calcMilli - newMilli > 100 || newMilli - calcMilli > 100) {
+            if (DEBUG) {
+                System.out.println("System time adjusted");
+            }
+            initMilli = newMilli;
+            initMicro = newMicro;
+            return new KerberosTime(newMilli, 0);
+        } else {
+            return new KerberosTime(calcMilli, (int)(microElapsed % 1000));
         }
     }
 
@@ -169,13 +158,13 @@
         calendar.clear();
 
         calendar.setTimeInMillis(kerberosTime);
-        return zeroPad(Integer.toString(calendar.get(Calendar.YEAR)), 4) +
-            zeroPad(Integer.toString(calendar.get(Calendar.MONTH) + 1), 2) +
-            zeroPad(Integer.toString(calendar.get(Calendar.DAY_OF_MONTH)), 2) +
-            zeroPad(Integer.toString(calendar.get(Calendar.HOUR_OF_DAY)), 2) +
-            zeroPad(Integer.toString(calendar.get(Calendar.MINUTE)), 2) +
-            zeroPad(Integer.toString(calendar.get(Calendar.SECOND)), 2) + 'Z';
-
+        return String.format("%04d%02d%02d%02d%02d%02dZ",
+                calendar.get(Calendar.YEAR),
+                calendar.get(Calendar.MONTH) + 1,
+                calendar.get(Calendar.DAY_OF_MONTH),
+                calendar.get(Calendar.HOUR_OF_DAY),
+                calendar.get(Calendar.MINUTE),
+                calendar.get(Calendar.SECOND));
     }
 
     /**
@@ -194,40 +183,8 @@
         return kerberosTime;
     }
 
-
-    public void setTime(Date time) {
-        kerberosTime = time.getTime(); // (time.getTimezoneOffset() * 60000L);
-        microSeconds = 0;
-    }
-
-    public void setTime(long time) {
-        kerberosTime = time;
-        microSeconds = 0;
-    }
-
     public Date toDate() {
-        Date temp = new Date(kerberosTime);
-        temp.setTime(temp.getTime());
-        return temp;
-    }
-
-    public void setNow() {
-        long newMilli = System.currentTimeMillis();
-        long newMicro = System.nanoTime() / 1000;
-        long microElapsed = newMicro - initMicro;
-        long calcMilli = initMilli + microElapsed/1000;
-        if (calcMilli - newMilli > 100 || newMilli - calcMilli > 100) {
-            if (DEBUG) {
-                System.out.println("System time adjusted");
-            }
-            initMilli = newMilli;
-            initMicro = newMicro;
-            setTime(newMilli);
-            microSeconds = 0;
-        } else {
-            setTime(calcMilli);
-            microSeconds = (int)(microElapsed % 1000);
-        }
+        return new Date(kerberosTime);
     }
 
     public int getMicroSeconds() {
@@ -235,45 +192,25 @@
         return temp_long.intValue() + microSeconds;
     }
 
-    public void setMicroSeconds(int usec) {
-        microSeconds = usec % 1000;
-        Integer temp_int = new Integer(usec);
-        long temp_long = temp_int.longValue() / 1000L;
-        kerberosTime = kerberosTime - (kerberosTime % 1000L) + temp_long;
+    /**
+     * Returns a new KerberosTime object with the original seconds
+     * and the given microseconds.
+     */
+    public KerberosTime withMicroSeconds(int usec) {
+        return new KerberosTime(
+                kerberosTime - kerberosTime%1000L + usec/1000L,
+                usec%1000);
     }
 
-    public void setMicroSeconds(Integer usec) {
-        if (usec != null) {
-            microSeconds = usec.intValue() % 1000;
-            long temp_long = usec.longValue() / 1000L;
-            kerberosTime = kerberosTime - (kerberosTime % 1000L) + temp_long;
-        }
-    }
-
-    public boolean inClockSkew(int clockSkew) {
-        KerberosTime now = new KerberosTime(KerberosTime.NOW);
-
-        if (java.lang.Math.abs(kerberosTime - now.kerberosTime) >
-            clockSkew * 1000L)
-            return false;
-        return true;
+    private boolean inClockSkew(int clockSkew) {
+        return java.lang.Math.abs(kerberosTime - System.currentTimeMillis())
+                <= clockSkew * 1000L;
     }
 
     public boolean inClockSkew() {
         return inClockSkew(getDefaultSkew());
     }
 
-    public boolean inClockSkew(int clockSkew, KerberosTime now) {
-        if (java.lang.Math.abs(kerberosTime - now.kerberosTime) >
-            clockSkew * 1000L)
-            return false;
-        return true;
-    }
-
-    public boolean inClockSkew(KerberosTime time) {
-        return inClockSkew(getDefaultSkew(), time);
-    }
-
     public boolean greaterThanWRTClockSkew(KerberosTime time, int clockSkew) {
         if ((kerberosTime - time.kerberosTime) > clockSkew * 1000L)
             return true;
@@ -317,24 +254,22 @@
         return temp_long.intValue();
     }
 
-    public void setSeconds(int sec) {
-        Integer temp_int = new Integer(sec);
-        kerberosTime = temp_int.longValue() * 1000L;
-    }
-
     /**
      * Parse (unmarshal) a kerberostime from a DER input stream.  This form
      * parsing might be used when expanding a value which is part of
      * a constructed sequence and uses explicitly tagged type.
      *
      * @exception Asn1Exception on error.
-     * @param data the Der input stream value, which contains one or more marshaled value.
+     * @param data the Der input stream value, which contains
+     *             one or more marshaled value.
      * @param explicitTag tag number.
      * @param optional indicates if this data field is optional
      * @return an instance of KerberosTime.
      *
      */
-    public static KerberosTime parse(DerInputStream data, byte explicitTag, boolean optional) throws Asn1Exception, IOException {
+    public static KerberosTime parse(
+            DerInputStream data, byte explicitTag, boolean optional)
+            throws Asn1Exception, IOException {
         if ((optional) && (((byte)data.peekByte() & (byte)0x1F)!= explicitTag))
             return null;
         DerValue der = data.getDerValue();
@@ -343,16 +278,17 @@
         }
         else {
             DerValue subDer = der.getData().getDerValue();
-            return new KerberosTime(subDer);
+            Date temp = subDer.getGeneralizedTime();
+            return new KerberosTime(temp.getTime(), 0);
         }
     }
 
     public static int getDefaultSkew() {
         int tdiff = Krb5.DEFAULT_ALLOWABLE_CLOCKSKEW;
         try {
-            Config c = Config.getInstance();
-            if ((tdiff = c.getDefaultIntValue("clockskew",
-                                              "libdefaults")) == Integer.MIN_VALUE) {   //value is not defined
+            if ((tdiff = Config.getInstance().getIntValue(
+                    "libdefaults", "clockskew"))
+                        == Integer.MIN_VALUE) {   //value is not defined
                 tdiff = Krb5.DEFAULT_ALLOWABLE_CLOCKSKEW;
             }
         } catch (KrbException e) {
--- a/src/share/classes/sun/security/krb5/internal/KrbCredInfo.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/security/krb5/internal/KrbCredInfo.java	Thu Feb 06 01:43:16 2020 +0000
@@ -187,14 +187,10 @@
             kcred.pname = (PrincipalName)pname.clone();
         if (flags != null)
             kcred.flags = (TicketFlags)flags.clone();
-        if (authtime != null)
-            kcred.authtime = (KerberosTime)authtime.clone();
-        if (starttime != null)
-            kcred.starttime = (KerberosTime)starttime.clone();
-        if (endtime != null)
-            kcred.endtime = (KerberosTime)endtime.clone();
-        if (renewTill != null)
-            kcred.renewTill = (KerberosTime)renewTill.clone();
+        kcred.authtime = authtime;
+        kcred.starttime = starttime;
+        kcred.endtime = endtime;
+        kcred.renewTill = renewTill;
         if (sname != null)
             kcred.sname = (PrincipalName)sname.clone();
         if (caddr != null)
--- a/src/share/classes/sun/security/krb5/internal/LastReqEntry.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/security/krb5/internal/LastReqEntry.java	Thu Feb 06 01:43:16 2020 +0000
@@ -90,7 +90,7 @@
     public Object clone() {
         LastReqEntry newEntry = new LastReqEntry();
         newEntry.lrType = lrType;
-        newEntry.lrValue = (KerberosTime)lrValue.clone();
+        newEntry.lrValue = lrValue;
         return newEntry;
     }
 }
--- a/src/share/classes/sun/security/krb5/internal/NetClient.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/security/krb5/internal/NetClient.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -103,7 +103,7 @@
         }
 
         try {
-            return IOUtils.readFully(in, len, true);
+            return IOUtils.readExactlyNBytes(in, len);
         } catch (IOException ioe) {
             if (Krb5.DEBUG) {
                 System.out.println(
--- a/src/share/classes/sun/security/krb5/internal/PAData.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/security/krb5/internal/PAData.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,4 +1,5 @@
 /*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -30,7 +31,7 @@
 
 package sun.security.krb5.internal;
 
-import sun.security.krb5.KrbException;
+import sun.security.krb5.internal.crypto.EType;
 import sun.security.util.*;
 import sun.security.krb5.Asn1Exception;
 import java.io.IOException;
@@ -169,8 +170,8 @@
             while (d2.data.available() > 0) {
                 DerValue value = d2.data.getDerValue();
                 ETypeInfo2 tmp = new ETypeInfo2(value);
-                if (tmp.getParams() == null) {
-                    // we don't support non-null s2kparams
+                if (EType.isNewer(tmp.getEType()) || tmp.getParams() == null) {
+                    // we don't support non-null s2kparams for old etypes
                     return tmp.getEType();
                 }
             }
@@ -236,8 +237,9 @@
             while (d2.data.available() > 0) {
                 DerValue value = d2.data.getDerValue();
                 ETypeInfo2 tmp = new ETypeInfo2(value);
-                if (tmp.getParams() == null && tmp.getEType() == eType) {
-                    // we don't support non-null s2kparams
+                if (tmp.getEType() == eType &&
+                        (EType.isNewer(eType) || tmp.getParams() == null)) {
+                    // we don't support non-null s2kparams for old etypes
                     return new SaltAndParams(tmp.getSalt(), tmp.getParams());
                 }
             }
--- a/src/share/classes/sun/security/krb5/internal/PAEncTSEnc.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/security/krb5/internal/PAEncTSEnc.java	Thu Feb 06 01:43:16 2020 +0000
@@ -65,7 +65,7 @@
     }
 
     public PAEncTSEnc() {
-        KerberosTime now = new KerberosTime(KerberosTime.NOW);
+        KerberosTime now = KerberosTime.now();
         pATimeStamp = now;
         pAUSec = new Integer(now.getMicroSeconds());
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/sun/security/krb5/internal/ReplayCache.java	Thu Feb 06 01:43:16 2020 +0000
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.security.krb5.internal;
+
+import sun.security.action.GetPropertyAction;
+import sun.security.krb5.internal.rcache.AuthTimeWithHash;
+import sun.security.krb5.internal.rcache.MemoryCache;
+import sun.security.krb5.internal.rcache.DflCache;
+
+import java.security.AccessController;
+
+/**
+ * Models the replay cache of an acceptor as described in
+ * RFC 4120 3.2.3.
+ * @since 1.8
+ */
+public abstract class ReplayCache {
+    public static ReplayCache getInstance(String type) {
+        if (type == null) {
+            return new MemoryCache();
+        } else if (type.equals("dfl") || type.startsWith("dfl:")) {
+            return new DflCache(type);
+        } else if (type.equals("none")) {
+            return new ReplayCache() {
+                @Override
+                public void checkAndStore(KerberosTime currTime, AuthTimeWithHash time)
+                        throws KrbApErrException {
+                    // no check at all
+                }
+            };
+        } else {
+            throw new IllegalArgumentException("Unknown type: " + type);
+        }
+    }
+    public static ReplayCache getInstance() {
+        String type = AccessController.doPrivileged(
+                new GetPropertyAction("sun.security.krb5.rcache"));
+        return getInstance(type);
+    }
+
+    /**
+     * Accepts or rejects an AuthTime.
+     * @param currTime the current time
+     * @param time AuthTimeWithHash object calculated from authenticator
+     * @throws KrbApErrException if the authenticator is a replay
+     */
+    public abstract void checkAndStore(KerberosTime currTime, AuthTimeWithHash time)
+            throws KrbApErrException;
+}
--- a/src/share/classes/sun/security/krb5/internal/ccache/CCacheInputStream.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/security/krb5/internal/ccache/CCacheInputStream.java	Thu Feb 06 01:43:16 2020 +0000
@@ -128,7 +128,7 @@
             length--;
         for (int i = 0; i <= length; i++) {
             namelength = readLength4();
-            byte[] bytes = IOUtils.readFully(this, namelength, true);
+            byte[] bytes = IOUtils.readExactlyNBytes(this, namelength);
             result.add(new String(bytes));
         }
         if (result.isEmpty()) {
@@ -186,7 +186,7 @@
         if (version == KRB5_FCC_FVNO_3)
             read(2); /* keytype recorded twice in fvno 3 */
         keyLen = readLength4();
-        byte[] bytes = IOUtils.readFully(this, keyLen, true);
+        byte[] bytes = IOUtils.readExactlyNBytes(this, keyLen);
         return new EncryptionKey(bytes, keyType, new Integer(version));
     }
 
@@ -239,7 +239,7 @@
             for (int i = 0; i < num; i++) {
                 adtype = read(2);
                 adlength = readLength4();
-                data = IOUtils.readFully(this, adlength, true);
+                data = IOUtils.readExactlyNBytes(this, adlength);
                 auData.add(new AuthorizationDataEntry(adtype, data));
             }
             return auData.toArray(new AuthorizationDataEntry[auData.size()]);
@@ -253,7 +253,7 @@
         if (length == 0) {
             return null;
         } else {
-            return IOUtils.readFully(this, length, true);
+            return IOUtils.readExactlyNBytes(this, length);
         }
     }
 
--- a/src/share/classes/sun/security/krb5/internal/ccache/Credentials.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/security/krb5/internal/ccache/Credentials.java	Thu Feb 06 01:43:16 2020 +0000
@@ -68,14 +68,11 @@
         sname = (PrincipalName) new_sname.clone();
         key = (EncryptionKey) new_key.clone();
 
-        authtime = (KerberosTime) new_authtime.clone();
-        if (new_starttime != null) {
-            starttime = (KerberosTime) new_starttime.clone();
-        }
-        endtime = (KerberosTime) new_endtime.clone();
-        if (new_renewTill != null) {
-            renewTill = (KerberosTime) new_renewTill.clone();
-        }
+        authtime = new_authtime;
+        starttime = new_starttime;
+        endtime = new_endtime;
+        renewTill = new_renewTill;
+
         if (new_caddr != null) {
             caddr = (HostAddresses) new_caddr.clone();
         }
@@ -104,14 +101,11 @@
         ticket = (Ticket) kdcRep.ticket.clone();
         key = (EncryptionKey) kdcRep.encKDCRepPart.key.clone();
         flags = (TicketFlags) kdcRep.encKDCRepPart.flags.clone();
-        authtime = (KerberosTime) kdcRep.encKDCRepPart.authtime.clone();
-        if (kdcRep.encKDCRepPart.starttime != null) {
-            starttime = (KerberosTime) kdcRep.encKDCRepPart.starttime.clone();
-        }
-        endtime = (KerberosTime) kdcRep.encKDCRepPart.endtime.clone();
-        if (kdcRep.encKDCRepPart.renewTill != null) {
-            renewTill = (KerberosTime) kdcRep.encKDCRepPart.renewTill.clone();
-        }
+        authtime = kdcRep.encKDCRepPart.authtime;
+        starttime = kdcRep.encKDCRepPart.starttime;
+        endtime = kdcRep.encKDCRepPart.endtime;
+        renewTill = kdcRep.encKDCRepPart.renewTill;
+
         sname = (PrincipalName) kdcRep.encKDCRepPart.sname.clone();
         caddr = (HostAddresses) kdcRep.encKDCRepPart.caddr.clone();
         secondTicket = (Ticket) new_secondTicket.clone();
@@ -128,18 +122,10 @@
         sname = (PrincipalName) kdcRep.encKDCRepPart.sname.clone();
         cname = (PrincipalName) kdcRep.cname.clone();
         key = (EncryptionKey) kdcRep.encKDCRepPart.key.clone();
-        authtime = (KerberosTime) kdcRep.encKDCRepPart.authtime.clone();
-        if (kdcRep.encKDCRepPart.starttime != null) {
-            starttime = (KerberosTime) kdcRep.encKDCRepPart.starttime.clone();
-        } else {
-            starttime = null;
-        }
-        endtime = (KerberosTime) kdcRep.encKDCRepPart.endtime.clone();
-        if (kdcRep.encKDCRepPart.renewTill != null) {
-            renewTill = (KerberosTime) kdcRep.encKDCRepPart.renewTill.clone();
-        } else {
-            renewTill = null;
-        }
+        authtime = kdcRep.encKDCRepPart.authtime;
+        starttime = kdcRep.encKDCRepPart.starttime;
+        endtime = kdcRep.encKDCRepPart.endtime;
+        renewTill = kdcRep.encKDCRepPart.renewTill;
         // if (kdcRep.msgType == Krb5.KRB_AS_REP) {
         //    isEncInSKey = false;
         //    secondTicket = null;
@@ -188,6 +174,10 @@
                 cname, sname, key, flags, authtime, starttime, endtime, renewTill, caddr);
     }
 
+    public KerberosTime getStartTime() {
+        return starttime;
+    }
+
     public KerberosTime getAuthTime() {
         return authtime;
     }
@@ -196,6 +186,10 @@
         return endtime;
     }
 
+    public KerberosTime getRenewTill() {
+        return renewTill;
+    }
+
     public TicketFlags getTicketFlags() {
         return flags;
     }
@@ -203,4 +197,8 @@
     public int getEType() {
         return key.getEType();
     }
+
+    public int getTktEType() {
+        return ticket.encPart.getEType();
+    }
 }
--- a/src/share/classes/sun/security/krb5/internal/crypto/CksumType.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/security/krb5/internal/crypto/CksumType.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -31,10 +31,7 @@
 
 package sun.security.krb5.internal.crypto;
 
-import sun.security.krb5.Config;
 import sun.security.krb5.Checksum;
-import sun.security.krb5.EncryptedData;
-import sun.security.krb5.KrbException;
 import sun.security.krb5.KrbCryptoException;
 import sun.security.krb5.internal.*;
 
@@ -81,6 +78,7 @@
             cksumTypeName =
                 "sun.security.krb5.internal.crypto.HmacSha1Aes128CksumType";
             break;
+
         case Checksum.CKSUMTYPE_HMAC_SHA1_96_AES256:
             cksumType = new HmacSha1Aes256CksumType();
             cksumTypeName =
@@ -117,32 +115,11 @@
         return cksumType;
     }
 
-
-    /**
-     * Returns default checksum type.
-     */
-    public static CksumType getInstance() throws KdcErrException {
-        // this method provided for Kerberos applications.
-        int cksumType = Checksum.CKSUMTYPE_RSA_MD5; // default
-        try {
-            Config c = Config.getInstance();
-            if ((cksumType = (c.getType(c.getDefault("ap_req_checksum_type",
-                                "libdefaults")))) == - 1) {
-                if ((cksumType = c.getType(c.getDefault("checksum_type",
-                                "libdefaults"))) == -1) {
-                    cksumType = Checksum.CKSUMTYPE_RSA_MD5; // default
-                }
-            }
-        } catch (KrbException e) {
-        }
-        return getInstance(cksumType);
-    }
-
     public abstract int confounderSize();
 
     public abstract int cksumType();
 
-    public abstract boolean isSafe();
+    public abstract boolean isKeyed();
 
     public abstract int cksumSize();
 
@@ -150,13 +127,12 @@
 
     public abstract int keySize();
 
-    public abstract byte[] calculateChecksum(byte[] data, int size)
-        throws KrbCryptoException;
-
-    public abstract byte[] calculateKeyedChecksum(byte[] data, int size,
+    // Note: key and usage will be ignored for an unkeyed checksum.
+    public abstract byte[] calculateChecksum(byte[] data, int size,
         byte[] key, int usage) throws KrbCryptoException;
 
-    public abstract boolean verifyKeyedChecksum(byte[] data, int size,
+    // Note: key and usage will be ignored for an unkeyed checksum.
+    public abstract boolean verifyChecksum(byte[] data, int size,
         byte[] key, byte[] checksum, int usage) throws KrbCryptoException;
 
     public static boolean isChecksumEqual(byte[] cksum1, byte[] cksum2) {
--- a/src/share/classes/sun/security/krb5/internal/crypto/Crc32CksumType.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/security/krb5/internal/crypto/Crc32CksumType.java	Thu Feb 06 01:43:16 2020 +0000
@@ -32,7 +32,6 @@
 
 import sun.security.krb5.*;
 import sun.security.krb5.internal.*;
-import java.util.zip.CRC32;
 
 public class Crc32CksumType extends CksumType {
 
@@ -47,7 +46,7 @@
         return Checksum.CKSUMTYPE_CRC32;
     }
 
-    public boolean isSafe() {
+    public boolean isKeyed() {
         return false;
     }
 
@@ -63,18 +62,15 @@
         return 0;
     }
 
-    public byte[] calculateChecksum(byte[] data, int size) {
+    public byte[] calculateChecksum(byte[] data, int size,
+            byte[] key, int usage) {
         return crc32.byte2crc32sum_bytes(data, size);
     }
 
-    public byte[] calculateKeyedChecksum(byte[] data, int size,
-                                         byte[] key, int usage) {
-                                             return null;
-                                         }
-
-    public boolean verifyKeyedChecksum(byte[] data, int size,
-                                       byte[] key, byte[] checksum, int usage) {
-        return false;
+    public boolean verifyChecksum(byte[] data, int size,
+            byte[] key, byte[] checksum, int usage) {
+        return CksumType.isChecksumEqual(checksum,
+                crc32.byte2crc32sum_bytes(data));
     }
 
     public static byte[] int2quad(long input) {
--- a/src/share/classes/sun/security/krb5/internal/crypto/DesCbcCrcEType.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/security/krb5/internal/crypto/DesCbcCrcEType.java	Thu Feb 06 01:43:16 2020 +0000
@@ -53,7 +53,7 @@
     }
 
     public int checksumType() {
-        return Checksum.CKSUMTYPE_CRC32;
+        return Checksum.CKSUMTYPE_RSA_MD5;
     }
 
     public int checksumSize() {
--- a/src/share/classes/sun/security/krb5/internal/crypto/DesMacCksumType.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/security/krb5/internal/crypto/DesMacCksumType.java	Thu Feb 06 01:43:16 2020 +0000
@@ -49,7 +49,7 @@
         return Checksum.CKSUMTYPE_DES_MAC;
     }
 
-    public boolean isSafe() {
+    public boolean isKeyed() {
         return true;
     }
 
@@ -65,10 +65,6 @@
         return 8;
     }
 
-    public byte[] calculateChecksum(byte[] data, int size) {
-        return null;
-    }
-
     /**
      * Calculates keyed checksum.
      * @param data the data used to generate the checksum.
@@ -78,7 +74,7 @@
      *
      * @modified by Yanni Zhang, 12/08/99.
      */
-    public byte[] calculateKeyedChecksum(byte[] data, int size, byte[] key,
+    public byte[] calculateChecksum(byte[] data, int size, byte[] key,
         int usage) throws KrbCryptoException {
         byte[] new_data = new byte[size + confounderSize()];
         byte[] conf = Confounder.bytes(confounderSize());
@@ -130,7 +126,7 @@
      *
      * @modified by Yanni Zhang, 12/08/99.
      */
-    public boolean verifyKeyedChecksum(byte[] data, int size,
+    public boolean verifyChecksum(byte[] data, int size,
         byte[] key, byte[] checksum, int usage) throws KrbCryptoException {
         byte[] cksum = decryptKeyedChecksum(checksum, key);
 
--- a/src/share/classes/sun/security/krb5/internal/crypto/DesMacKCksumType.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/security/krb5/internal/crypto/DesMacKCksumType.java	Thu Feb 06 01:43:16 2020 +0000
@@ -48,7 +48,7 @@
         return Checksum.CKSUMTYPE_DES_MAC_K;
     }
 
-    public boolean isSafe() {
+    public boolean isKeyed() {
         return true;
     }
 
@@ -64,10 +64,6 @@
         return 8;
     }
 
-    public byte[] calculateChecksum(byte[] data, int size) {
-        return null;
-    }
-
     /**
      * Calculates keyed checksum.
      * @param data the data used to generate the checksum.
@@ -77,7 +73,7 @@
      *
      * @modified by Yanni Zhang, 12/08/99.
      */
-    public byte[] calculateKeyedChecksum(byte[] data, int size, byte[] key,
+    public byte[] calculateChecksum(byte[] data, int size, byte[] key,
         int usage) throws KrbCryptoException {
         //check for weak keys
         try {
@@ -93,9 +89,9 @@
         return cksum;
     }
 
-    public boolean verifyKeyedChecksum(byte[] data, int size,
+    public boolean verifyChecksum(byte[] data, int size,
         byte[] key, byte[] checksum, int usage) throws KrbCryptoException {
-        byte[] new_cksum = calculateKeyedChecksum(data, data.length, key, usage);
+        byte[] new_cksum = calculateChecksum(data, data.length, key, usage);
         return isChecksumEqual(checksum, new_cksum);
     }
 
--- a/src/share/classes/sun/security/krb5/internal/crypto/EType.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/security/krb5/internal/crypto/EType.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -48,14 +48,18 @@
 public abstract class EType {
 
     private static final boolean DEBUG = Krb5.DEBUG;
-    private static final boolean ALLOW_WEAK_CRYPTO;
+    private static boolean allowWeakCrypto;
 
     static {
-        boolean allowed = true;
+        initStatic();
+    }
+
+    public static void initStatic() {
+        boolean allowed = false;
         try {
             Config cfg = Config.getInstance();
-            String temp = cfg.getDefault("allow_weak_crypto", "libdefaults");
-            if (temp != null && temp.equals("false")) allowed = false;
+            String temp = cfg.get("libdefaults", "allow_weak_crypto");
+            if (temp != null && temp.equals("true")) allowed = true;
         } catch (Exception exc) {
             if (DEBUG) {
                 System.out.println ("Exception in getting allow_weak_crypto, " +
@@ -63,7 +67,7 @@
                                     exc.getMessage());
             }
         }
-        ALLOW_WEAK_CRYPTO = allowed;
+        allowWeakCrypto = allowed;
     }
 
     public static EType getInstance  (int eTypeConst)
@@ -216,7 +220,7 @@
         } else {
             result = BUILTIN_ETYPES;
         }
-        if (!ALLOW_WEAK_CRYPTO) {
+        if (!allowWeakCrypto) {
             // The last 2 etypes are now weak ones
             return Arrays.copyOfRange(result, 0, result.length - 2);
         }
@@ -226,11 +230,14 @@
     /**
      * Retrieves the default etypes from the configuration file, or
      * if that's not available, return the built-in list of default etypes.
+     * This result is always non-empty. If no etypes are found,
+     * an exception is thrown.
      */
-    // used in KrbAsReq, KeyTab
-    public static int[] getDefaults(String configName) {
+    public static int[] getDefaults(String configName)
+            throws KrbException {
+        Config config = null;
         try {
-            return Config.getInstance().defaultEtype(configName);
+            config = Config.getInstance();
         } catch (KrbException exc) {
             if (DEBUG) {
                 System.out.println("Exception while getting " +
@@ -239,6 +246,7 @@
             }
             return getBuiltInDefaults();
         }
+        return config.defaultEtype(configName);
     }
 
     /**
@@ -250,12 +258,8 @@
      * we have keys.
      */
     public static int[] getDefaults(String configName, EncryptionKey[] keys)
-        throws KrbException {
+            throws KrbException {
         int[] answer = getDefaults(configName);
-        if (answer == null) {
-            throw new KrbException("No supported encryption types listed in "
-                + configName);
-        }
 
         List<Integer> list = new ArrayList<>(answer.length);
         for (int i = 0; i < answer.length; i++) {
@@ -297,6 +301,26 @@
         return isSupported(eTypeConst, enabledETypes);
     }
 
+    /**
+     * https://tools.ietf.org/html/rfc4120#section-3.1.3:
+     *
+     *                 A "newer" enctype is any enctype first officially
+     * specified concurrently with or subsequent to the issue of this RFC.
+     * The enctypes DES, 3DES, or RC4 and any defined in [RFC1510] are not
+     * "newer" enctypes.
+     *
+     * @param eTypeConst the encryption type
+     * @return true if "newer"
+     */
+    public static boolean isNewer(int eTypeConst) {
+        return eTypeConst != EncryptedData.ETYPE_DES_CBC_CRC &&
+                eTypeConst != EncryptedData.ETYPE_DES_CBC_MD4 &&
+                eTypeConst != EncryptedData.ETYPE_DES_CBC_MD5 &&
+                eTypeConst != EncryptedData.ETYPE_DES3_CBC_HMAC_SHA1_KD &&
+                eTypeConst != EncryptedData.ETYPE_ARCFOUR_HMAC &&
+                eTypeConst != EncryptedData.ETYPE_ARCFOUR_HMAC_EXP;
+    }
+
     public static String toString(int type) {
         switch (type) {
         case 0:
--- a/src/share/classes/sun/security/krb5/internal/crypto/HmacMd5ArcFourCksumType.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/security/krb5/internal/crypto/HmacMd5ArcFourCksumType.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,8 +28,6 @@
 import sun.security.krb5.Checksum;
 import sun.security.krb5.KrbCryptoException;
 import sun.security.krb5.internal.*;
-import javax.crypto.spec.DESKeySpec;
-import java.security.InvalidKeyException;
 import java.security.GeneralSecurityException;
 
 /**
@@ -51,7 +49,7 @@
         return Checksum.CKSUMTYPE_HMAC_MD5_ARCFOUR;
     }
 
-    public boolean isSafe() {
+    public boolean isKeyed() {
         return true;
     }
 
@@ -67,10 +65,6 @@
         return 16;   // bytes
     }
 
-    public byte[] calculateChecksum(byte[] data, int size) {
-        return null;
-    }
-
     /**
      * Calculates keyed checksum.
      * @param data the data used to generate the checksum.
@@ -78,7 +72,7 @@
      * @param key the key used to encrypt the checksum.
      * @return keyed checksum.
      */
-    public byte[] calculateKeyedChecksum(byte[] data, int size, byte[] key,
+    public byte[] calculateChecksum(byte[] data, int size, byte[] key,
         int usage) throws KrbCryptoException {
 
          try {
@@ -98,7 +92,7 @@
      * @param checksum
      * @return true if verification is successful.
      */
-    public boolean verifyKeyedChecksum(byte[] data, int size,
+    public boolean verifyChecksum(byte[] data, int size,
         byte[] key, byte[] checksum, int usage) throws KrbCryptoException {
 
          try {
--- a/src/share/classes/sun/security/krb5/internal/crypto/HmacSha1Aes128CksumType.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/security/krb5/internal/crypto/HmacSha1Aes128CksumType.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,8 +28,6 @@
 import sun.security.krb5.Checksum;
 import sun.security.krb5.KrbCryptoException;
 import sun.security.krb5.internal.*;
-import javax.crypto.spec.DESKeySpec;
-import java.security.InvalidKeyException;
 import java.security.GeneralSecurityException;
 
 /*
@@ -51,7 +49,7 @@
         return Checksum.CKSUMTYPE_HMAC_SHA1_96_AES128;
     }
 
-    public boolean isSafe() {
+    public boolean isKeyed() {
         return true;
     }
 
@@ -67,10 +65,6 @@
         return 16;   // bytes
     }
 
-    public byte[] calculateChecksum(byte[] data, int size) {
-        return null;
-    }
-
     /**
      * Calculates keyed checksum.
      * @param data the data used to generate the checksum.
@@ -78,7 +72,7 @@
      * @param key the key used to encrypt the checksum.
      * @return keyed checksum.
      */
-    public byte[] calculateKeyedChecksum(byte[] data, int size, byte[] key,
+    public byte[] calculateChecksum(byte[] data, int size, byte[] key,
         int usage) throws KrbCryptoException {
 
          try {
@@ -98,7 +92,7 @@
      * @param checksum
      * @return true if verification is successful.
      */
-    public boolean verifyKeyedChecksum(byte[] data, int size,
+    public boolean verifyChecksum(byte[] data, int size,
         byte[] key, byte[] checksum, int usage) throws KrbCryptoException {
 
          try {
--- a/src/share/classes/sun/security/krb5/internal/crypto/HmacSha1Aes256CksumType.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/security/krb5/internal/crypto/HmacSha1Aes256CksumType.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,8 +28,6 @@
 import sun.security.krb5.Checksum;
 import sun.security.krb5.KrbCryptoException;
 import sun.security.krb5.internal.*;
-import javax.crypto.spec.DESKeySpec;
-import java.security.InvalidKeyException;
 import java.security.GeneralSecurityException;
 
 /*
@@ -51,7 +49,7 @@
         return Checksum.CKSUMTYPE_HMAC_SHA1_96_AES256;
     }
 
-    public boolean isSafe() {
+    public boolean isKeyed() {
         return true;
     }
 
@@ -67,10 +65,6 @@
         return 32;   // bytes
     }
 
-    public byte[] calculateChecksum(byte[] data, int size) {
-        return null;
-    }
-
     /**
      * Calculates keyed checksum.
      * @param data the data used to generate the checksum.
@@ -78,7 +72,7 @@
      * @param key the key used to encrypt the checksum.
      * @return keyed checksum.
      */
-    public byte[] calculateKeyedChecksum(byte[] data, int size, byte[] key,
+    public byte[] calculateChecksum(byte[] data, int size, byte[] key,
         int usage) throws KrbCryptoException {
 
          try {
@@ -98,7 +92,7 @@
      * @param checksum
      * @return true if verification is successful.
      */
-    public boolean verifyKeyedChecksum(byte[] data, int size,
+    public boolean verifyChecksum(byte[] data, int size,
         byte[] key, byte[] checksum, int usage) throws KrbCryptoException {
 
          try {
--- a/src/share/classes/sun/security/krb5/internal/crypto/HmacSha1Des3KdCksumType.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/security/krb5/internal/crypto/HmacSha1Des3KdCksumType.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,8 +28,6 @@
 import sun.security.krb5.Checksum;
 import sun.security.krb5.KrbCryptoException;
 import sun.security.krb5.internal.*;
-import javax.crypto.spec.DESKeySpec;
-import java.security.InvalidKeyException;
 import java.security.GeneralSecurityException;
 
 public class HmacSha1Des3KdCksumType extends CksumType {
@@ -45,7 +43,7 @@
         return Checksum.CKSUMTYPE_HMAC_SHA1_DES3_KD;
     }
 
-    public boolean isSafe() {
+    public boolean isKeyed() {
         return true;
     }
 
@@ -61,10 +59,6 @@
         return 24;   // bytes
     }
 
-    public byte[] calculateChecksum(byte[] data, int size) {
-        return null;
-    }
-
     /**
      * Calculates keyed checksum.
      * @param data the data used to generate the checksum.
@@ -72,7 +66,7 @@
      * @param key the key used to encrypt the checksum.
      * @return keyed checksum.
      */
-    public byte[] calculateKeyedChecksum(byte[] data, int size, byte[] key,
+    public byte[] calculateChecksum(byte[] data, int size, byte[] key,
         int usage) throws KrbCryptoException {
 
          try {
@@ -92,7 +86,7 @@
      * @param checksum
      * @return true if verification is successful.
      */
-    public boolean verifyKeyedChecksum(byte[] data, int size,
+    public boolean verifyChecksum(byte[] data, int size,
         byte[] key, byte[] checksum, int usage) throws KrbCryptoException {
 
          try {
--- a/src/share/classes/sun/security/krb5/internal/crypto/RsaMd5CksumType.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/security/krb5/internal/crypto/RsaMd5CksumType.java	Thu Feb 06 01:43:16 2020 +0000
@@ -33,8 +33,6 @@
 import sun.security.krb5.KrbCryptoException;
 import sun.security.krb5.internal.*;
 import java.security.MessageDigest;
-import java.security.Provider;
-import java.security.Security;
 
 public final class RsaMd5CksumType extends CksumType {
 
@@ -49,7 +47,7 @@
         return Checksum.CKSUMTYPE_RSA_MD5;
     }
 
-    public boolean isSafe() {
+    public boolean isKeyed() {
         return false;
     }
 
@@ -74,7 +72,8 @@
      * @modified by Yanni Zhang, 12/08/99.
      */
 
-    public byte[] calculateChecksum(byte[] data, int size) throws KrbCryptoException{
+    public byte[] calculateChecksum(byte[] data, int size,
+            byte[] key, int usage) throws KrbCryptoException{
         MessageDigest md5;
         byte[] result = null;
         try {
@@ -91,14 +90,15 @@
         return result;
     }
 
-    public byte[] calculateKeyedChecksum(byte[] data, int size,
-        byte[] key, int usage) throws KrbCryptoException {
-                                             return null;
-                                         }
-
-    public boolean verifyKeyedChecksum(byte[] data, int size,
-        byte[] key, byte[] checksum, int usage) throws KrbCryptoException {
-        return false;
+    @Override
+    public boolean verifyChecksum(byte[] data, int size,
+            byte[] key, byte[] checksum, int usage)
+            throws KrbCryptoException {
+        try {
+            byte[] calculated = MessageDigest.getInstance("MD5").digest(data);
+            return CksumType.isChecksumEqual(calculated, checksum);
+        } catch (Exception e) {
+            return false;
+        }
     }
-
 }
--- a/src/share/classes/sun/security/krb5/internal/crypto/RsaMd5DesCksumType.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/security/krb5/internal/crypto/RsaMd5DesCksumType.java	Thu Feb 06 01:43:16 2020 +0000
@@ -33,12 +33,8 @@
 import sun.security.krb5.Confounder;
 import sun.security.krb5.KrbCryptoException;
 import sun.security.krb5.internal.*;
-import javax.crypto.Cipher;
-import javax.crypto.SecretKey;
 import javax.crypto.spec.DESKeySpec;
 import java.security.MessageDigest;
-import java.security.Provider;
-import java.security.Security;
 import java.security.InvalidKeyException;
 
 public final class RsaMd5DesCksumType extends CksumType {
@@ -54,7 +50,7 @@
         return Checksum.CKSUMTYPE_RSA_MD5_DES;
     }
 
-    public boolean isSafe() {
+    public boolean isKeyed() {
         return true;
     }
 
@@ -79,7 +75,7 @@
      *
      * @modified by Yanni Zhang, 12/08/99.
      */
-    public byte[] calculateKeyedChecksum(byte[] data, int size, byte[] key,
+    public byte[] calculateChecksum(byte[] data, int size, byte[] key,
         int usage) throws KrbCryptoException {
         //prepend confounder
         byte[] new_data = new byte[size + confounderSize()];
@@ -88,7 +84,7 @@
         System.arraycopy(data, 0, new_data, confounderSize(), size);
 
         //calculate md5 cksum
-        byte[] mdc_cksum = calculateChecksum(new_data, new_data.length);
+        byte[] mdc_cksum = calculateRawChecksum(new_data, new_data.length);
         byte[] cksum = new byte[cksumSize()];
         System.arraycopy(conf, 0, cksum, 0, confounderSize());
         System.arraycopy(mdc_cksum, 0, cksum, confounderSize(),
@@ -125,7 +121,7 @@
      *
      * @modified by Yanni Zhang, 12/08/99.
      */
-    public boolean verifyKeyedChecksum(byte[] data, int size,
+    public boolean verifyChecksum(byte[] data, int size,
         byte[] key, byte[] checksum, int usage) throws KrbCryptoException {
         //decrypt checksum
         byte[] cksum = decryptKeyedChecksum(checksum, key);
@@ -135,7 +131,7 @@
         System.arraycopy(cksum, 0, new_data, 0, confounderSize());
         System.arraycopy(data, 0, new_data, confounderSize(), size);
 
-        byte[] new_cksum = calculateChecksum(new_data, new_data.length);
+        byte[] new_cksum = calculateRawChecksum(new_data, new_data.length);
         //extract original cksum value
         byte[] orig_cksum = new byte[cksumSize() - confounderSize()];
         System.arraycopy(cksum,  confounderSize(), orig_cksum, 0,
@@ -181,7 +177,7 @@
      *
      * @modified by Yanni Zhang, 12/08/99.
      */
-    public byte[] calculateChecksum(byte[] data, int size) throws KrbCryptoException{
+    private byte[] calculateRawChecksum(byte[] data, int size) throws KrbCryptoException{
         MessageDigest md5;
         byte[] result = null;
         try {
@@ -197,5 +193,4 @@
         }
         return result;
     }
-
 }
--- a/src/share/classes/sun/security/krb5/internal/ktab/KeyTab.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/security/krb5/internal/ktab/KeyTab.java	Thu Feb 06 01:43:16 2020 +0000
@@ -186,8 +186,8 @@
         } else {
             String kname = null;
             try {
-                String keytab_names = Config.getInstance().getDefault
-                    ("default_keytab_name", "libdefaults");
+                String keytab_names = Config.getInstance().get
+                        ("libdefaults", "default_keytab_name");
                 if (keytab_names != null) {
                     StringTokenizer st = new StringTokenizer(keytab_names, " ");
                     while (st.hasMoreTokens()) {
@@ -269,8 +269,7 @@
 
     /**
      * Reads all keys for a service from the keytab file that have
-     * etypes that have been configured for use. If there are multiple
-     * keys with same etype, the one with the highest kvno is returned.
+     * etypes that have been configured for use.
      * @param service the PrincipalName of the requested service
      * @return an array containing all the service keys, never null
      */
@@ -300,35 +299,12 @@
         size = keys.size();
         EncryptionKey[] retVal = keys.toArray(new EncryptionKey[size]);
 
-        // Sort keys according to default_tkt_enctypes
-        if (DEBUG) {
-            System.out.println("Ordering keys wrt default_tkt_enctypes list");
-        }
-
-        final int[] etypes = EType.getDefaults("default_tkt_enctypes");
-
-        // Sort the keys, k1 is preferred than k2 if:
-        // 1. k1's etype appears earlier in etypes than k2's
-        // 2. If same, k1's KVNO is higher
+        // Sort the keys by kvno. Sometimes we must choose a single key (say,
+        // generate encrypted timestamp in AS-REQ). A key with a higher KVNO
+        // sounds like a newer one.
         Arrays.sort(retVal, new Comparator<EncryptionKey>() {
             @Override
             public int compare(EncryptionKey o1, EncryptionKey o2) {
-                if (etypes != null) {
-                    int o1EType = o1.getEType();
-                    int o2EType = o2.getEType();
-                    if (o1EType != o2EType) {
-                        for (int i=0; i<etypes.length; i++) {
-                            if (etypes[i] == o1EType) {
-                                return -1;
-                            } else if (etypes[i] == o2EType) {
-                                return 1;
-                            }
-                        }
-                        // Neither o1EType nor o2EType in default_tkt_enctypes,
-                        // therefore won't be used in AS-REQ. We do not care
-                        // about their order, use kvno is OK.
-                    }
-                }
                 return o2.getKeyVersionNumber().intValue()
                         - o1.getKeyVersionNumber().intValue();
             }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/sun/security/krb5/internal/rcache/AuthList.java	Thu Feb 06 01:43:16 2020 +0000
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ *
+ *  (C) Copyright IBM Corp. 1999 All Rights Reserved.
+ *  Copyright 1997 The Open Group Research Institute.  All rights reserved.
+ */
+
+package sun.security.krb5.internal.rcache;
+
+import sun.security.krb5.internal.Krb5;
+
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.ListIterator;
+import sun.security.krb5.internal.KerberosTime;
+import sun.security.krb5.internal.KrbApErrException;
+
+/**
+ * This class provides an efficient caching mechanism to store AuthTimeWithHash
+ * from client authenticators. The cache minimizes the memory usage by doing
+ * self-cleanup of expired items in the cache.
+ *
+ * AuthTimeWithHash objects inside a cache are always sorted from big (new) to
+ * small (old) as determined by {@see AuthTimeWithHash#compareTo}. In the most
+ * common case a newcomer should be newer than the first element.
+ *
+ * @author Yanni Zhang
+ */
+public class AuthList {
+
+    private final LinkedList<AuthTimeWithHash> entries;
+    private final int lifespan;
+
+    // entries.getLast().ctime, updated after each cleanup.
+    private volatile int oldestTime = Integer.MIN_VALUE;
+
+    /**
+     * Constructs a AuthList.
+     */
+    public AuthList(int lifespan) {
+        this.lifespan = lifespan;
+        entries = new LinkedList<>();
+    }
+
+    /**
+     * Puts the authenticator timestamp into the cache in descending order,
+     * and throw an exception if it's already there.
+     */
+    public synchronized void put(AuthTimeWithHash t, KerberosTime currentTime)
+            throws KrbApErrException {
+
+        if (entries.isEmpty()) {
+            entries.addFirst(t);
+            oldestTime = t.ctime;
+            return;
+        } else {
+            AuthTimeWithHash temp = entries.getFirst();
+            int cmp = temp.compareTo(t);
+            if (cmp < 0) {
+                // This is the most common case, newly received authenticator
+                // has larger timestamp.
+                entries.addFirst(t);
+            } else if (cmp == 0) {
+                throw new KrbApErrException(Krb5.KRB_AP_ERR_REPEAT);
+            } else {
+                //unless client clock being re-adjusted.
+                ListIterator<AuthTimeWithHash> it = entries.listIterator(1);
+                boolean found = false;
+                while (it.hasNext()) {
+                    temp = it.next();
+                    cmp = temp.compareTo(t);
+                    if (cmp < 0) {
+                        // Find an older one, put in front of it
+                        entries.add(entries.indexOf(temp), t);
+                        found = true;
+                        break;
+                    } else if (cmp == 0) {
+                        throw new KrbApErrException(Krb5.KRB_AP_ERR_REPEAT);
+                    }
+                }
+                if (!found) {
+                    // All is newer than the newcomer. Sigh.
+                    entries.addLast(t);
+                }
+            }
+        }
+
+        // let us cleanup while we are here
+        long timeLimit = currentTime.getSeconds() - lifespan;
+
+        // Only trigger a cleanup when the earliest entry is
+        // lifespan + 5 sec ago. This ensures a cleanup is done
+        // at most every 5 seconds so that we don't always
+        // addLast(removeLast).
+        if (oldestTime > timeLimit - 5) {
+            return;
+        }
+
+        // and we remove the *enough* old ones (1 lifetime ago)
+        while (!entries.isEmpty()) {
+            AuthTimeWithHash removed = entries.removeLast();
+            if (removed.ctime >= timeLimit) {
+                entries.addLast(removed);
+                oldestTime = removed.ctime;
+                return;
+            }
+        }
+
+        oldestTime = Integer.MIN_VALUE;
+    }
+
+    public boolean isEmpty() {
+        return entries.isEmpty();
+    }
+
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        Iterator<AuthTimeWithHash> iter = entries.descendingIterator();
+        int pos = entries.size();
+        while (iter.hasNext()) {
+            AuthTimeWithHash at = iter.next();
+            sb.append('#').append(pos--).append(": ")
+                    .append(at.toString()).append('\n');
+        }
+        return sb.toString();
+    }
+}
--- a/src/share/classes/sun/security/krb5/internal/rcache/AuthTime.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/security/krb5/internal/rcache/AuthTime.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,4 +1,5 @@
 /*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -30,54 +31,126 @@
 
 package sun.security.krb5.internal.rcache;
 
-import sun.security.krb5.internal.KerberosTime;
+import java.io.IOException;
+import java.nio.BufferUnderflowException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.channels.SeekableByteChannel;
+import java.nio.charset.StandardCharsets;
+import java.util.StringTokenizer;
 
 /**
- * The class represents the timestamp in authenticator.
+ * The class represents an old style replay cache entry. It is only used in
+ * a dfl file.
  *
+ * @author Sun/Oracle
  * @author Yanni Zhang
  */
 public class AuthTime {
-    long kerberosTime;
-    int cusec;
+    final int ctime;
+    final int cusec;
+    final String client;
+    final String server;
+
+    /**
+     * Constructs an <code>AuthTime</code>.
+     */
+    public AuthTime(String client, String server,
+            int ctime, int cusec) {
+        this.ctime = ctime;
+        this.cusec = cusec;
+        this.client = client;
+        this.server = server;
+    }
+
+    @Override
+    public String toString() {
+        return String.format("%d/%06d/----/%s", ctime, cusec, client);
+    }
+
+    // Methods used when saved in a dfl file. See DflCache.java
 
     /**
-     * Constructs a new <code>AuthTime</code>.
-     * @param time time from the <code>Authenticator</code>.
-     * @param cusec microsecond field from the <code>Authenticator</code>.
+     * Reads an LC style string from a channel, which is a int32 length
+     * plus a UTF-8 encoded string possibly ends with \0.
+     * @throws IOException if there is a format error
+     * @throws BufferUnderflowException if goes beyond the end
      */
-    public AuthTime(long time, int c) {
-        kerberosTime = time;
-        cusec = c;
+    private static String readStringWithLength(SeekableByteChannel chan)
+            throws IOException {
+        ByteBuffer bb = ByteBuffer.allocate(4);
+        bb.order(ByteOrder.nativeOrder());
+        chan.read(bb);
+        bb.flip();
+        int len = bb.getInt();
+        if (len > 1024) {
+            // Memory attack? The string should be fairly short.
+            throw new IOException("Invalid string length");
+        }
+        bb = ByteBuffer.allocate(len);
+        if (chan.read(bb) != len) {
+            throw new IOException("Not enough string");
+        }
+        byte[] data = bb.array();
+        return (data[len-1] == 0)?
+                new String(data, 0, len-1, StandardCharsets.UTF_8):
+                new String(data, StandardCharsets.UTF_8);
     }
 
     /**
-     * Compares if an object equals to an <code>AuthTime</code> object.
-     * @param o an object.
-     * @return true if two objects are equivalent, otherwise, return false.
+     * Reads an AuthTime or AuthTimeWithHash object from a channel.
+     * @throws IOException if there is a format error
+     * @throws BufferUnderflowException if goes beyond the end
      */
-    public boolean equals(Object o) {
-        if (o instanceof AuthTime) {
-            if ((((AuthTime)o).kerberosTime == kerberosTime)
-                && (((AuthTime)o).cusec == cusec)) {
-                return true;
+    public static AuthTime readFrom(SeekableByteChannel chan)
+            throws IOException {
+        String client = readStringWithLength(chan);
+        String server = readStringWithLength(chan);
+        ByteBuffer bb = ByteBuffer.allocate(8);
+        chan.read(bb);
+        bb.order(ByteOrder.nativeOrder());
+        int cusec = bb.getInt(0);
+        int ctime = bb.getInt(4);
+        if (client.isEmpty()) {
+            StringTokenizer st = new StringTokenizer(server, " :");
+            if (st.countTokens() != 6) {
+                throw new IOException("Incorrect rcache style");
             }
+            st.nextToken();
+            String hash = st.nextToken();
+            st.nextToken();
+            client = st.nextToken();
+            st.nextToken();
+            server = st.nextToken();
+            return new AuthTimeWithHash(
+                    client, server, ctime, cusec, hash);
+        } else {
+            return new AuthTime(
+                    client, server, ctime, cusec);
         }
-        return false;
     }
 
     /**
-     * Returns a hash code for this <code>AuthTime</code> object.
-     *
-     * @return  a <code>hash code</code> value for this object.
+     * Encodes to be used in a dfl file
      */
-    public int hashCode() {
-        int result = 17;
-
-        result = 37 * result + (int)(kerberosTime ^ (kerberosTime >>> 32));
-        result = 37 * result + cusec;
-
-        return result;
+    protected byte[] encode0(String cstring, String sstring) {
+        byte[] c = cstring.getBytes(StandardCharsets.UTF_8);;
+        byte[] s = sstring.getBytes(StandardCharsets.UTF_8);;
+        byte[] zero = new byte[1];
+        int len = 4 + c.length + 1 + 4 + s.length + 1 + 4 + 4;
+        ByteBuffer bb = ByteBuffer.allocate(len)
+                .order(ByteOrder.nativeOrder());
+        bb.putInt(c.length+1).put(c).put(zero)
+                .putInt(s.length+1).put(s).put(zero)
+                .putInt(cusec).putInt(ctime);
+        return bb.array();
     }
 
+    /**
+     * Encodes to be used in a dfl file
+     * @param withHash useless here
+     */
+    public byte[] encode(boolean withHash) {
+        return encode0(client, server);
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/sun/security/krb5/internal/rcache/AuthTimeWithHash.java	Thu Feb 06 01:43:16 2020 +0000
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.security.krb5.internal.rcache;
+
+import java.util.Objects;
+
+/**
+ * The class represents a new style replay cache entry. It can be either used
+ * inside memory or in a dfl file.
+ */
+public class AuthTimeWithHash extends AuthTime
+        implements Comparable<AuthTimeWithHash> {
+
+    final String hash;
+
+    /**
+     * Constructs a new <code>AuthTimeWithHash</code>.
+     */
+    public AuthTimeWithHash(String client, String server,
+            int ctime, int cusec, String hash) {
+        super(client, server, ctime, cusec);
+        this.hash = hash;
+    }
+
+    /**
+     * Compares if an object equals to an <code>AuthTimeWithHash</code> object.
+     * @param o an object.
+     * @return true if two objects are equivalent, otherwise, return false.
+     */
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (!(o instanceof AuthTimeWithHash)) return false;
+        AuthTimeWithHash that = (AuthTimeWithHash)o;
+        return Objects.equals(hash, that.hash)
+                && Objects.equals(client, that.client)
+                && Objects.equals(server, that.server)
+                && ctime == that.ctime
+                && cusec == that.cusec;
+    }
+
+    /**
+     * Returns a hash code for this <code>AuthTimeWithHash</code> object.
+     */
+    @Override
+    public int hashCode() {
+        return Objects.hash(hash);
+    }
+
+    @Override
+    public String toString() {
+        return String.format("%d/%06d/%s/%s", ctime, cusec, hash, client);
+    }
+
+    @Override
+    public int compareTo(AuthTimeWithHash other) {
+        int cmp = 0;
+        if (ctime != other.ctime) {
+            cmp = Integer.compare(ctime, other.ctime);
+        } else if (cusec != other.cusec) {
+            cmp = Integer.compare(cusec, other.cusec);
+        } else {
+            cmp = hash.compareTo(other.hash);
+        }
+        return cmp;
+    }
+
+    /**
+     * Compares with a possibly old style object. Used
+     * in DflCache$Storage#loadAndCheck.
+     * @return true if all AuthTime fields are the same
+     */
+    public boolean isSameIgnoresHash(AuthTime old) {
+        return  client.equals(old.client) &&
+                server.equals(old.server) &&
+                ctime == old.ctime &&
+                cusec == old.cusec;
+    }
+
+    // Methods used when saved in a dfl file. See DflCache.java
+
+    /**
+     * Encodes to be used in a dfl file
+     * @param withHash write new style if true
+     */
+    @Override
+    public byte[] encode(boolean withHash) {
+        String cstring;
+        String sstring;
+        if (withHash) {
+            cstring = "";
+            sstring = String.format("HASH:%s %d:%s %d:%s", hash,
+                    client.length(), client,
+                    server.length(), server);
+        } else {
+            cstring = client;
+            sstring = server;
+        }
+        return encode0(cstring, sstring);
+    }
+}
--- a/src/share/classes/sun/security/krb5/internal/rcache/CacheTable.java	Wed Nov 20 06:36:47 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,90 +0,0 @@
-/*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- *
- *  (C) Copyright IBM Corp. 1999 All Rights Reserved.
- *  Copyright 1997 The Open Group Research Institute.  All rights reserved.
- */
-
-package sun.security.krb5.internal.rcache;
-
-import java.util.Hashtable;
-import sun.security.krb5.internal.KerberosTime;
-
-
-/**
- * This class implements Hashtable to store the replay caches.
- *
- * @author Yanni Zhang
- */
-public class CacheTable extends Hashtable<String,ReplayCache> {
-
-    private static final long serialVersionUID = -4695501354546664910L;
-
-    private boolean DEBUG = sun.security.krb5.internal.Krb5.DEBUG;
-    public CacheTable () {
-    }
-
-    /**
-     * Puts the client timestamp in replay cache.
-     * @params principal the client's principal name.
-     * @params time authenticator timestamp.
-     */
-    public synchronized void put(String principal, AuthTime time, long currTime) {
-        ReplayCache rc = super.get(principal);
-        if (rc == null) {
-            if (DEBUG) {
-                System.out.println("replay cache for " + principal + " is null.");
-            }
-            rc = new ReplayCache(principal, this);
-            rc.put(time, currTime);
-            super.put(principal, rc);
-        }
-        else {
-            rc.put(time, currTime);
-            // re-insert the entry, since rc.put could have removed the entry
-            super.put(principal, rc);
-            if (DEBUG) {
-                System.out.println("replay cache found.");
-            }
-        }
-
-    }
-
-    /**
-     * This method tests if replay cache keeps a record of the authenticator's time stamp.
-     * If there is a record (replay attack detected), the server should reject the client request.
-     * @params principal the client's principal name.
-     * @params time authenticator timestamp.
-     * @return null if no record found, else return an <code>AuthTime</code> object.
-     */
-    public Object get(AuthTime time, String principal) {
-        ReplayCache rc = super.get(principal);
-        if ((rc != null) && (rc.contains(time))) {
-            return time;
-        }
-        return null;
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/sun/security/krb5/internal/rcache/DflCache.java	Thu Feb 06 01:43:16 2020 +0000
@@ -0,0 +1,365 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+package sun.security.krb5.internal.rcache;
+
+import java.io.*;
+import java.nio.BufferUnderflowException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.channels.SeekableByteChannel;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.StandardCopyOption;
+import java.nio.file.StandardOpenOption;
+import java.nio.file.attribute.PosixFilePermission;
+import java.security.AccessController;
+import java.util.*;
+
+import sun.security.action.GetPropertyAction;
+import sun.security.krb5.internal.KerberosTime;
+import sun.security.krb5.internal.Krb5;
+import sun.security.krb5.internal.KrbApErrException;
+import sun.security.krb5.internal.ReplayCache;
+
+
+/**
+ * A dfl file is used to sustores AuthTime entries when the system property
+ * sun.security.krb5.rcache is set to
+ *
+ *    dfl(|:path/|:path/name|:name)
+ *
+ * The file will be path/name. If path is not given, it will be
+ *
+ *    System.getProperty("java.io.tmpdir")
+ *
+ * If name is not given, it will be
+ *
+ *    service_euid
+ *
+ * Java does not have a method to get euid, so uid is used instead. This
+ * should normally to be since a Java program is seldom used as a setuid app.
+ *
+ * The file has a header:
+ *
+ *    i16 0x0501 (KRB5_RC_VNO) in network order
+ *    i32 number of seconds for lifespan (in native order, same below)
+ *
+ * followed by cache entries concatenated, which can be encoded in
+ * 2 styles:
+ *
+ * The traditional style is:
+ *
+ *    LC of client principal
+ *    LC of server principal
+ *    i32 cusec of Authenticator
+ *    i32 ctime of Authenticator
+ *
+ * The new style has a hash:
+ *
+ *    LC of ""
+ *    LC of "HASH:%s %lu:%s %lu:%s" of (hash, clientlen, client, serverlen,
+ *          server) where msghash is 32 char (lower case) text mode md5sum
+ *          of the ciphertext of authenticator.
+ *    i32 cusec of Authenticator
+ *    i32 ctime of Authenticator
+ *
+ * where LC of a string means
+ *
+ *    i32 strlen(string) + 1
+ *    octets of string, with the \0x00 ending
+ *
+ * The old style block is always created by MIT krb5 used even if a new style
+ * is available, which means there can be 2 entries for a single Authenticator.
+ * Java also does this way.
+ *
+ * See src/lib/krb5/rcache/rc_io.c and src/lib/krb5/rcache/rc_dfl.c.
+ */
+public class DflCache extends ReplayCache {
+
+    private static final int KRB5_RV_VNO = 0x501;
+    private static final int EXCESSREPS = 30;   // if missed-hit>this, recreate
+
+    private final String source;
+
+    private static int uid;
+    static {
+        try {
+            // Available on Solaris, Linux and Mac. Otherwise, no _euid suffix
+            Class<?> clazz = Class.forName("com.sun.security.auth.module.UnixSystem");
+            uid = (int)(long)(Long)
+                    clazz.getMethod("getUid").invoke(clazz.newInstance());
+        } catch (Exception e) {
+            uid = -1;
+        }
+    }
+
+    public DflCache (String source) {
+        this.source = source;
+    }
+
+    private static String defaultPath() {
+        return AccessController.doPrivileged(
+                new GetPropertyAction("java.io.tmpdir"));
+    }
+
+    private static String defaultFile(String server) {
+        // service/host@REALM -> service
+        int slash = server.indexOf('/');
+        if (slash == -1) {
+            // A normal principal? say, dummy@REALM
+            slash = server.indexOf('@');
+        }
+        if (slash != -1) {
+            // Should not happen, but be careful
+            server= server.substring(0, slash);
+        }
+        if (uid != -1) {
+            server += "_" + uid;
+        }
+        return server;
+    }
+
+    private static Path getFileName(String source, String server) {
+        String path, file;
+        if (source.equals("dfl")) {
+            path = defaultPath();
+            file = defaultFile(server);
+        } else if (source.startsWith("dfl:")) {
+            source = source.substring(4);
+            int pos = source.lastIndexOf('/');
+            int pos1 = source.lastIndexOf('\\');
+            if (pos1 > pos) pos = pos1;
+            if (pos == -1) {
+                // Only file name
+                path = defaultPath();
+                file = source;
+            } else if (new File(source).isDirectory()) {
+                // Only path
+                path = source;
+                file = defaultFile(server);
+            } else {
+                // Full pathname
+                path = null;
+                file = source;
+            }
+        } else {
+            throw new IllegalArgumentException();
+        }
+        return new File(path, file).toPath();
+    }
+
+    @Override
+    public void checkAndStore(KerberosTime currTime, AuthTimeWithHash time)
+            throws KrbApErrException {
+        try {
+            checkAndStore0(currTime, time);
+        } catch (IOException ioe) {
+            KrbApErrException ke = new KrbApErrException(Krb5.KRB_ERR_GENERIC);
+            ke.initCause(ioe);
+            throw ke;
+        }
+    }
+
+    private synchronized void checkAndStore0(KerberosTime currTime, AuthTimeWithHash time)
+            throws IOException, KrbApErrException {
+        Path p = getFileName(source, time.server);
+        int missed = 0;
+        try (Storage s = new Storage()) {
+            try {
+                missed = s.loadAndCheck(p, time, currTime);
+            } catch (IOException ioe) {
+                // Non-existing or invalid file
+                Storage.create(p);
+                missed = s.loadAndCheck(p, time, currTime);
+            }
+            s.append(time);
+        }
+        if (missed > EXCESSREPS) {
+            Storage.expunge(p, currTime);
+        }
+    }
+
+
+    private static class Storage implements Closeable {
+        // Static methods
+        @SuppressWarnings("try")
+        private static void create(Path p) throws IOException {
+            try (SeekableByteChannel newChan = createNoClose(p)) {
+                // Do nothing, wait for close
+            }
+            makeMine(p);
+        }
+
+        private static void makeMine(Path p) throws IOException {
+            // chmod to owner-rw only, otherwise MIT krb5 rejects
+            try {
+                Set<PosixFilePermission> attrs = new HashSet<>();
+                attrs.add(PosixFilePermission.OWNER_READ);
+                attrs.add(PosixFilePermission.OWNER_WRITE);
+                Files.setPosixFilePermissions(p, attrs);
+            } catch (UnsupportedOperationException uoe) {
+                // No POSIX permission. That's OK.
+            }
+        }
+
+        private static SeekableByteChannel createNoClose(Path p)
+                throws IOException {
+            SeekableByteChannel newChan = Files.newByteChannel(
+                    p, StandardOpenOption.CREATE,
+                        StandardOpenOption.TRUNCATE_EXISTING,
+                        StandardOpenOption.WRITE);
+            ByteBuffer buffer = ByteBuffer.allocate(6);
+            buffer.putShort((short)KRB5_RV_VNO);
+            buffer.order(ByteOrder.nativeOrder());
+            buffer.putInt(KerberosTime.getDefaultSkew());
+            buffer.flip();
+            newChan.write(buffer);
+            return newChan;
+        }
+
+        private static void expunge(Path p, KerberosTime currTime)
+                throws IOException {
+            Path p2 = Files.createTempFile(p.getParent(), "rcache", null);
+            try (SeekableByteChannel oldChan = Files.newByteChannel(p);
+                    SeekableByteChannel newChan = createNoClose(p2)) {
+                long timeLimit = currTime.getSeconds() - readHeader(oldChan);
+                while (true) {
+                    try {
+                        AuthTime at = AuthTime.readFrom(oldChan);
+                        if (at.ctime > timeLimit) {
+                            ByteBuffer bb = ByteBuffer.wrap(at.encode(true));
+                            newChan.write(bb);
+                        }
+                    } catch (BufferUnderflowException e) {
+                        break;
+                    }
+                }
+            }
+            makeMine(p2);
+            Files.move(p2, p,
+                    StandardCopyOption.REPLACE_EXISTING,
+                    StandardCopyOption.ATOMIC_MOVE);
+        }
+
+        // Instance methods
+        SeekableByteChannel chan;
+        private int loadAndCheck(Path p, AuthTimeWithHash time,
+                KerberosTime currTime)
+                throws IOException, KrbApErrException {
+            int missed = 0;
+            if (Files.isSymbolicLink(p)) {
+                throw new IOException("Symlink not accepted");
+            }
+            try {
+                Set<PosixFilePermission> perms =
+                        Files.getPosixFilePermissions(p);
+                if (uid != -1 &&
+                        (Integer)Files.getAttribute(p, "unix:uid") != uid) {
+                    throw new IOException("Not mine");
+                }
+                if (perms.contains(PosixFilePermission.GROUP_READ) ||
+                        perms.contains(PosixFilePermission.GROUP_WRITE) ||
+                        perms.contains(PosixFilePermission.GROUP_EXECUTE) ||
+                        perms.contains(PosixFilePermission.OTHERS_READ) ||
+                        perms.contains(PosixFilePermission.OTHERS_WRITE) ||
+                        perms.contains(PosixFilePermission.OTHERS_EXECUTE)) {
+                    throw new IOException("Accessible by someone else");
+                }
+            } catch (UnsupportedOperationException uoe) {
+                // No POSIX permissions? Ignore it.
+            }
+            chan = Files.newByteChannel(p, StandardOpenOption.WRITE,
+                    StandardOpenOption.READ);
+
+            long timeLimit = currTime.getSeconds() - readHeader(chan);
+
+            long pos = 0;
+            boolean seeNewButNotSame = false;
+            while (true) {
+                try {
+                    pos = chan.position();
+                    AuthTime a = AuthTime.readFrom(chan);
+                    if (a instanceof AuthTimeWithHash) {
+                        if (time.equals(a)) {
+                            // Exact match, must be a replay
+                            throw new KrbApErrException(Krb5.KRB_AP_ERR_REPEAT);
+                        } else if (time.isSameIgnoresHash(a)) {
+                            // Two different authenticators in the same second.
+                            // Remember it
+                            seeNewButNotSame = true;
+                        }
+                    } else {
+                        if (time.isSameIgnoresHash(a)) {
+                            // Two authenticators in the same second. Considered
+                            // same if we haven't seen a new style version of it
+                            if (!seeNewButNotSame) {
+                                throw new KrbApErrException(Krb5.KRB_AP_ERR_REPEAT);
+                            }
+                        }
+                    }
+                    if (a.ctime < timeLimit) {
+                        missed++;
+                    } else {
+                        missed--;
+                    }
+                } catch (BufferUnderflowException e) {
+                    // Half-written file?
+                    chan.position(pos);
+                    break;
+                }
+            }
+            return missed;
+        }
+
+        private static int readHeader(SeekableByteChannel chan)
+                throws IOException {
+            ByteBuffer bb = ByteBuffer.allocate(6);
+            chan.read(bb);
+            if (bb.getShort(0) != KRB5_RV_VNO) {
+                throw new IOException("Not correct rcache version");
+            }
+            bb.order(ByteOrder.nativeOrder());
+            return bb.getInt(2);
+        }
+
+        private void append(AuthTimeWithHash at) throws IOException {
+            // Write an entry with hash, to be followed by one without it,
+            // for the benefit of old implementations.
+            ByteBuffer bb;
+            bb = ByteBuffer.wrap(at.encode(true));
+            chan.write(bb);
+            bb = ByteBuffer.wrap(at.encode(false));
+            chan.write(bb);
+        }
+
+        @Override
+        public void close() throws IOException {
+            if (chan != null) chan.close();
+            chan = null;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/sun/security/krb5/internal/rcache/MemoryCache.java	Thu Feb 06 01:43:16 2020 +0000
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ *
+ *  (C) Copyright IBM Corp. 1999 All Rights Reserved.
+ *  Copyright 1997 The Open Group Research Institute.  All rights reserved.
+ */
+
+package sun.security.krb5.internal.rcache;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import sun.security.krb5.internal.KerberosTime;
+import sun.security.krb5.internal.KrbApErrException;
+import sun.security.krb5.internal.ReplayCache;
+
+
+/**
+ * This class stores replay caches. AuthTimeWithHash objects are categorized
+ * into AuthLists keyed by the names of client and server.
+ *
+ * @author Yanni Zhang
+ */
+public class MemoryCache extends ReplayCache {
+
+    // TODO: One day we'll need to read dynamic krb5.conf.
+    private static final int lifespan = KerberosTime.getDefaultSkew();
+    private static final boolean DEBUG = sun.security.krb5.internal.Krb5.DEBUG;
+
+    private final ConcurrentMap<String,AuthList> content = new ConcurrentHashMap<>();
+
+    @Override
+    public synchronized void checkAndStore(KerberosTime currTime, AuthTimeWithHash time)
+            throws KrbApErrException {
+        String key = time.client + "|" + time.server;
+        AuthList newAuthList = new AuthList(lifespan);
+        AuthList authList = content.putIfAbsent(key, newAuthList);
+        if (authList == null) {
+            authList = newAuthList;
+        }
+        authList.put(time, currTime);
+        if (DEBUG) {
+            System.out.println("MemoryCache: add " + time + " to " + key);
+        }
+        // TODO: clean up AuthList entries with only expired AuthTimeWithHash objects.
+    }
+
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        for (AuthList rc: content.values()) {
+            sb.append(rc.toString());
+        }
+        return sb.toString();
+    }
+}
--- a/src/share/classes/sun/security/krb5/internal/rcache/ReplayCache.java	Wed Nov 20 06:36:47 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,143 +0,0 @@
-/*
- * Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- *
- *  (C) Copyright IBM Corp. 1999 All Rights Reserved.
- *  Copyright 1997 The Open Group Research Institute.  All rights reserved.
- */
-
-package sun.security.krb5.internal.rcache;
-
-import sun.security.krb5.internal.Krb5;
-import java.util.LinkedList;
-import java.util.ListIterator;
-import sun.security.krb5.internal.KerberosTime;
-
-/**
- * This class provides an efficient caching mechanism to store the timestamp of client authenticators.
- * The cache minimizes the memory usage by doing self-cleanup of expired items in the cache.
- *
- * @author Yanni Zhang
- */
-public class ReplayCache extends LinkedList<AuthTime> {
-
-    private static final long serialVersionUID = 2997933194993803994L;
-
-    // These 3 fields are now useless, keep for serialization compatibility
-    private String principal;
-    private CacheTable table;
-    private int nap = 10 * 60 * 1000; //10 minutes break
-
-    private boolean DEBUG = Krb5.DEBUG;
-
-    /**
-     * Constructs a ReplayCache for a client principal in specified <code>CacheTable</code>.
-     * @param p client principal name.
-     * @param ct CacheTable.
-     */
-    public ReplayCache (String p, CacheTable ct) {
-        principal = p;
-        table = ct;
-    }
-
-    /**
-     * Puts the authenticator timestamp into the cache in descending order.
-     * @param t <code>AuthTime</code>
-     */
-    public synchronized void put(AuthTime t, long currentTime) {
-
-        if (this.size() == 0) {
-            addFirst(t);
-        }
-        else {
-            AuthTime temp = getFirst();
-            if (temp.kerberosTime < t.kerberosTime) {
-                // in most cases, newly received authenticator has
-                // larger timestamp.
-                addFirst(t);
-            }
-            else if (temp.kerberosTime == t.kerberosTime) {
-                if (temp.cusec < t.cusec) {
-                    addFirst(t);
-                }
-            }
-            else {
-                //unless client clock being re-adjusted.
-                ListIterator<AuthTime> it = listIterator(1);
-                while (it.hasNext()) {
-                    temp = it.next();
-                    if (temp.kerberosTime < t.kerberosTime) {
-                        add(indexOf(temp), t);
-                        break;
-                        //we always put the bigger timestamp at the front.
-                    }
-                    else if (temp.kerberosTime == t.kerberosTime) {
-                        if (temp.cusec < t.cusec) {
-                            add(indexOf(temp), t);
-                            break;
-                        }
-                    }
-                }
-            }
-        }
-
-        // let us cleanup while we are here
-        long timeLimit = currentTime - KerberosTime.getDefaultSkew() * 1000L;
-        ListIterator<AuthTime> it = listIterator(0);
-        AuthTime temp = null;
-        int index = -1;
-        while (it.hasNext()) {
-            //search expired timestamps.
-            temp = it.next();
-            if (temp.kerberosTime < timeLimit) {
-                index = indexOf(temp);
-                break;
-            }
-        }
-        if (index > -1) {
-            do {
-                //remove expired timestamps from the list.
-                removeLast();
-            } while(size() > index);
-        }
-        if (DEBUG) {
-            printList();
-        }
-    }
-
-
-    /**
-     * Prints out the debug message.
-     */
-    private void printList() {
-        Object[] total = toArray();
-        for (int i = 0; i < total.length; i++) {
-            System.out.println("object " + i + ": " + ((AuthTime)total[i]).kerberosTime + "/"
-                               + ((AuthTime)total[i]).cusec);
-        }
-    }
-
-}
--- a/src/share/classes/sun/security/pkcs11/P11KeyStore.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/security/pkcs11/P11KeyStore.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -752,6 +752,21 @@
             } else {
                 login(new PasswordCallbackHandler(password));
             }
+        } catch(LoginException e) {
+            Throwable cause = e.getCause();
+            if (cause instanceof PKCS11Exception) {
+                PKCS11Exception pe = (PKCS11Exception) cause;
+                if (pe.getErrorCode() == CKR_PIN_INCORRECT) {
+                    // if password is wrong, the cause of the IOException
+                    // should be an UnrecoverableKeyException
+                    throw new IOException("load failed",
+                            new UnrecoverableKeyException().initCause(e));
+                }
+            }
+            throw new IOException("load failed", e);
+        }
+
+        try {
             if (mapLabels() == true) {
                 // CKA_LABELs are shared by multiple certs
                 writeDisabled = true;
@@ -759,7 +774,7 @@
             if (debug != null) {
                 dumpTokenMap();
             }
-        } catch (LoginException | KeyStoreException | PKCS11Exception e) {
+        } catch (KeyStoreException | PKCS11Exception e) {
             throw new IOException("load failed", e);
         }
     }
--- a/src/share/classes/sun/security/pkcs12/PKCS12KeyStore.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/security/pkcs12/PKCS12KeyStore.java	Thu Feb 06 01:43:16 2020 +0000
@@ -2016,7 +2016,7 @@
                 }
 
                 if (!MessageDigest.isEqual(macData.getDigest(), macResult)) {
-                   throw new SecurityException("Failed PKCS12" +
+                   throw new UnrecoverableKeyException("Failed PKCS12" +
                                         " integrity checking");
                 }
             } catch (Exception e) {
--- a/src/share/classes/sun/security/provider/JavaKeyStore.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/security/provider/JavaKeyStore.java	Thu Feb 06 01:43:16 2020 +0000
@@ -691,7 +691,7 @@
 
                     // Read the private key
                     entry.protectedPrivKey =
-                            IOUtils.readFully(dis, dis.readInt(), true);
+                            IOUtils.readExactlyNBytes(dis, dis.readInt());
 
                     // Read the certificate chain
                     int numOfCerts = dis.readInt();
@@ -716,7 +716,7 @@
                                 }
                             }
                             // instantiate the certificate
-                            encoded = IOUtils.readFully(dis, dis.readInt(), true);
+                            encoded = IOUtils.readExactlyNBytes(dis, dis.readInt());
                             bais = new ByteArrayInputStream(encoded);
                             certs.add(cf.generateCertificate(bais));
                             bais.close();
@@ -755,7 +755,7 @@
                             cfs.put(certType, cf);
                         }
                     }
-                    encoded = IOUtils.readFully(dis, dis.readInt(), true);
+                    encoded = IOUtils.readExactlyNBytes(dis, dis.readInt());
                     bais = new ByteArrayInputStream(encoded);
                     entry.cert = cf.generateCertificate(bais);
                     bais.close();
@@ -776,16 +776,13 @@
             if (password != null) {
                 byte computed[], actual[];
                 computed = md.digest();
-                actual = new byte[computed.length];
-                dis.readFully(actual);
-                for (int i = 0; i < computed.length; i++) {
-                    if (computed[i] != actual[i]) {
-                        Throwable t = new UnrecoverableKeyException
+                actual = IOUtils.readExactlyNBytes(dis, computed.length);
+                if (!MessageDigest.isEqual(computed, actual)) {
+                    Throwable t = new UnrecoverableKeyException
                             ("Password verification failed");
-                        throw (IOException)new IOException
+                    throw (IOException) new IOException
                             ("Keystore was tampered with, or "
-                            + "password was incorrect").initCause(t);
-                    }
+                                    + "password was incorrect").initCause(t);
                 }
             }
         }
--- a/src/share/classes/sun/security/provider/SunEntries.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/security/provider/SunEntries.java	Thu Feb 06 01:43:16 2020 +0000
@@ -63,7 +63,7 @@
  *   and CRLs. Aliases for X.509 are X509.
  *
  * - PKIX is the certification path validation algorithm described
- *   in RFC 3280. The ValidationAlgorithm attribute notes the
+ *   in RFC 5280. The ValidationAlgorithm attribute notes the
  *   specification that this provider implements.
  *
  * - LDAP is the CertStore type for LDAP repositories. The
@@ -233,7 +233,7 @@
         map.put("CertPathBuilder.PKIX",
             "sun.security.provider.certpath.SunCertPathBuilder");
         map.put("CertPathBuilder.PKIX ValidationAlgorithm",
-            "RFC3280");
+            "RFC5280");
 
         /*
          * CertPathValidator
@@ -241,7 +241,7 @@
         map.put("CertPathValidator.PKIX",
             "sun.security.provider.certpath.PKIXCertPathValidator");
         map.put("CertPathValidator.PKIX ValidationAlgorithm",
-            "RFC3280");
+            "RFC5280");
 
         /*
          * CertStores
--- a/src/share/classes/sun/security/provider/certpath/PolicyChecker.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/security/provider/certpath/PolicyChecker.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -578,7 +578,7 @@
     }
 
     /**
-     * Rewrite leaf nodes at the end of validation as described in RFC 3280
+     * Rewrite leaf nodes at the end of validation as described in RFC 5280
      * section 6.1.5: Step (g)(iii). Leaf nodes with anyPolicy are replaced
      * by nodes explicitly representing initial policies not already
      * represented by leaf nodes.
--- a/src/share/classes/sun/security/provider/certpath/PolicyNodeImpl.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/security/provider/certpath/PolicyNodeImpl.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -56,7 +56,7 @@
     private PolicyNodeImpl mParent;
     private HashSet<PolicyNodeImpl> mChildren;
 
-    // the 4 fields specified by RFC 3280
+    // the 4 fields specified by RFC 5280
     private String mValidPolicy;
     private HashSet<PolicyQualifierInfo> mQualifierSet;
     private boolean mCriticalityIndicator;
--- a/src/share/classes/sun/security/timestamp/HttpTimestamper.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/security/timestamp/HttpTimestamper.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,6 +27,7 @@
 
 import java.io.BufferedInputStream;
 import java.io.DataOutputStream;
+import java.io.EOFException;
 import java.io.IOException;
 import java.net.URI;
 import java.net.URL;
@@ -68,12 +69,15 @@
     /**
      * Creates a timestamper that connects to the specified TSA.
      *
-     * @param tsa The location of the TSA. It must be an HTTP URI.
-     * @throws IllegalArgumentException if tsaURI is not an HTTP URI
+     * @param tsa The location of the TSA. It must be an HTTP or HTTPS URI.
+     * @throws IllegalArgumentException if tsaURI is not an HTTP or HTTPS URI
      */
     public HttpTimestamper(URI tsaURI) {
-        if (!tsaURI.getScheme().equalsIgnoreCase("http"))
-            throw new IllegalArgumentException("TSA must be an HTTP URI");
+        if (!tsaURI.getScheme().equalsIgnoreCase("http") &&
+                !tsaURI.getScheme().equalsIgnoreCase("https")) {
+            throw new IllegalArgumentException(
+                    "TSA must be an HTTP or HTTPS URI");
+        }
         this.tsaURI = tsaURI;
     }
 
@@ -144,13 +148,15 @@
             }
             verifyMimeType(connection.getContentType());
 
-            int total = 0;
-            int contentLength = connection.getContentLength();
-            replyBuffer = IOUtils.readFully(input, contentLength, false);
+            int clen = connection.getContentLength();
+            replyBuffer = IOUtils.readAllBytes(input);
+            if (clen != -1 && replyBuffer.length != clen)
+                throw new EOFException("Expected:" + clen +
+                                       ", read:" + replyBuffer.length);
 
             if (debug != null) {
                 debug.println("received timestamp response (length=" +
-                        total + ")");
+                        replyBuffer.length + ")");
             }
         } finally {
             if (input != null) {
--- a/src/share/classes/sun/security/tools/jarsigner/TimestampedSigner.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/security/tools/jarsigner/TimestampedSigner.java	Thu Feb 06 01:43:16 2020 +0000
@@ -144,7 +144,7 @@
 
     /**
      * Examine the certificate for a Subject Information Access extension
-     * (<a href="http://www.ietf.org/rfc/rfc3280.txt">RFC 3280</a>).
+     * (<a href="http://tools.ietf.org/html/rfc5280">RFC 5280</a>).
      * The extension's <tt>accessMethod</tt> field should contain the object
      * identifier defined for timestamping: 1.3.6.1.5.5.7.48.3 and its
      * <tt>accessLocation</tt> field should contain an HTTP or HTTPS URL.
--- a/src/share/classes/sun/security/util/DerInputBuffer.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/security/util/DerInputBuffer.java	Thu Feb 06 01:43:16 2020 +0000
@@ -300,7 +300,7 @@
          *       YYMMDDhhmmss-hhmm
          * UTC Time is broken in storing only two digits of year.
          * If YY < 50, we assume 20YY;
-         * if YY >= 50, we assume 19YY, as per RFC 3280.
+         * if YY >= 50, we assume 19YY, as per RFC 5280.
          *
          * Generalized time has a four-digit year and allows any
          * precision specified in ISO 8601. However, for our purposes,
--- a/src/share/classes/sun/security/util/DerOutputStream.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/security/util/DerOutputStream.java	Thu Feb 06 01:43:16 2020 +0000
@@ -461,7 +461,7 @@
      * Marshals a DER UTC time/date value.
      *
      * <P>YYMMDDhhmmss{Z|+hhmm|-hhmm} ... emits only using Zulu time
-     * and with seconds (even if seconds=0) as per RFC 3280.
+     * and with seconds (even if seconds=0) as per RFC 5280.
      */
     public void putUTCTime(Date d) throws IOException {
         putTime(d, DerValue.tag_UtcTime);
@@ -471,7 +471,7 @@
      * Marshals a DER Generalized Time/date value.
      *
      * <P>YYYYMMDDhhmmss{Z|+hhmm|-hhmm} ... emits only using Zulu time
-     * and with seconds (even if seconds=0) as per RFC 3280.
+     * and with seconds (even if seconds=0) as per RFC 5280.
      */
     public void putGeneralizedTime(Date d) throws IOException {
         putTime(d, DerValue.tag_GeneralizedTime);
--- a/src/share/classes/sun/security/util/DerValue.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/security/util/DerValue.java	Thu Feb 06 01:43:16 2020 +0000
@@ -45,8 +45,8 @@
  * (such as PKCS #10 certificate requests, and some kinds of PKCS #7 data).
  *
  * A note with respect to T61/Teletex strings: From RFC 1617, section 4.1.3
- * and RFC 3280, section 4.1.2.4., we assume that this kind of string will
- * contain ISO-8859-1 characters only.
+ * and RFC 5280, section 8, we assume that this kind of string will contain
+ * ISO-8859-1 characters only.
  *
  *
  * @author David Brownell
@@ -409,7 +409,7 @@
         if (fullyBuffered && in.available() != length)
             throw new IOException("extra data given to DerValue constructor");
 
-        byte[] bytes = IOUtils.readFully(in, length, true);
+        byte[] bytes = IOUtils.readExactlyNBytes(in, length);
 
         buffer = new DerInputBuffer(bytes, allowBER);
         return new DerInputStream(buffer);
--- a/src/share/classes/sun/security/validator/PKIXValidator.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/security/validator/PKIXValidator.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -32,6 +32,7 @@
 
 import javax.security.auth.x500.X500Principal;
 import sun.security.action.GetBooleanAction;
+import sun.security.action.GetPropertyAction;
 import sun.security.provider.certpath.AlgorithmChecker;
 import sun.security.provider.certpath.PKIXExtendedParameters;
 
@@ -64,6 +65,18 @@
     // enable use of the validator if possible
     private final static boolean TRY_VALIDATOR = true;
 
+    /**
+     * System property that if set (or set to "true"), allows trust anchor
+     * certificates to be used if they do not have the proper CA extensions.
+     * Set to false if prop is not set, or set to any other value.
+     */
+    private static final boolean ALLOW_NON_CA_ANCHOR = allowNonCaAnchor();
+    private static boolean allowNonCaAnchor() {
+        String prop = GetPropertyAction
+            .privilegedGetProperty("jdk.security.allowNonCaAnchor");
+        return prop != null && (prop.isEmpty() || prop.equalsIgnoreCase("true"));
+    }
+
     private final Set<X509Certificate> trustedCerts;
     private final PKIXBuilderParameters parameterTemplate;
     private int certPathLength = -1;
@@ -209,6 +222,7 @@
                 ("null or zero-length certificate chain");
         }
 
+
         // Use PKIXExtendedParameters for timestamp and variant additions
         PKIXBuilderParameters pkixParameters = null;
         try {
@@ -234,29 +248,30 @@
             for (int i = 0; i < chain.length; i++) {
                 X509Certificate cert = chain[i];
                 X500Principal dn = cert.getSubjectX500Principal();
-                if (i != 0 &&
-                    !dn.equals(prevIssuer)) {
-                    // chain is not ordered correctly, call builder instead
-                    return doBuild(chain, otherCerts, pkixParameters);
-                }
 
-                // Check if chain[i] is already trusted. It may be inside
-                // trustedCerts, or has the same dn and public key as a cert
-                // inside trustedCerts. The latter happens when a CA has
-                // updated its cert with a stronger signature algorithm in JRE
-                // but the weak one is still in circulation.
-
-                if (trustedCerts.contains(cert) ||          // trusted cert
-                        (trustedSubjects.containsKey(dn) && // replacing ...
-                         trustedSubjects.get(dn).contains(  // ... weak cert
-                            cert.getPublicKey()))) {
-                    if (i == 0) {
+                if (i == 0) {
+                    if (trustedCerts.contains(cert)) {
                         return new X509Certificate[] {chain[0]};
                     }
-                    // Remove and call validator on partial chain [0 .. i-1]
-                    X509Certificate[] newChain = new X509Certificate[i];
-                    System.arraycopy(chain, 0, newChain, 0, i);
-                    return doValidate(newChain, pkixParameters);
+                } else {
+                    if (!dn.equals(prevIssuer)) {
+                        // chain is not ordered correctly, call builder instead
+                        return doBuild(chain, otherCerts, pkixParameters);
+                    }
+                    // Check if chain[i] is already trusted. It may be inside
+                    // trustedCerts, or has the same dn and public key as a cert
+                    // inside trustedCerts. The latter happens when a CA has
+                    // updated its cert with a stronger signature algorithm in JRE
+                    // but the weak one is still in circulation.
+                    if (trustedCerts.contains(cert) ||          // trusted cert
+                            (trustedSubjects.containsKey(dn) && // replacing ...
+                             trustedSubjects.get(dn).contains(  // ... weak cert
+                                cert.getPublicKey()))) {
+                        // Remove and call validator on partial chain [0 .. i-1]
+                        X509Certificate[] newChain = new X509Certificate[i];
+                        System.arraycopy(chain, 0, newChain, 0, i);
+                        return doValidate(newChain, pkixParameters);
+                    }
                 }
                 prevIssuer = cert.getIssuerX500Principal();
             }
@@ -320,15 +335,18 @@
 
     private static X509Certificate[] toArray(CertPath path, TrustAnchor anchor)
             throws CertificateException {
-        List<? extends java.security.cert.Certificate> list =
-                                                path.getCertificates();
-        X509Certificate[] chain = new X509Certificate[list.size() + 1];
-        list.toArray(chain);
         X509Certificate trustedCert = anchor.getTrustedCert();
         if (trustedCert == null) {
             throw new ValidatorException
                 ("TrustAnchor must be specified as certificate");
         }
+
+        verifyTrustAnchor(trustedCert);
+
+        List<? extends java.security.cert.Certificate> list =
+                                                path.getCertificates();
+        X509Certificate[] chain = new X509Certificate[list.size() + 1];
+        list.toArray(chain);
         chain[chain.length - 1] = trustedCert;
         return chain;
     }
@@ -362,6 +380,41 @@
         }
     }
 
+    /**
+     * Verify that a trust anchor certificate is a CA certificate.
+     */
+    private static void verifyTrustAnchor(X509Certificate trustedCert)
+        throws ValidatorException {
+
+        // skip check if jdk.security.allowNonCAAnchor system property is set
+        if (ALLOW_NON_CA_ANCHOR) {
+            return;
+        }
+
+        // allow v1 trust anchor certificates
+        if (trustedCert.getVersion() < 3) {
+            return;
+        }
+
+        // check that the BasicConstraints cA field is not set to false
+        if (trustedCert.getBasicConstraints() == -1) {
+            throw new ValidatorException
+                ("TrustAnchor with subject \"" +
+                 trustedCert.getSubjectX500Principal() +
+                 "\" is not a CA certificate");
+        }
+
+        // check that the KeyUsage extension, if included, asserts the
+        // keyCertSign bit
+        boolean[] keyUsageBits = trustedCert.getKeyUsage();
+        if (keyUsageBits != null && !keyUsageBits[5]) {
+            throw new ValidatorException
+                ("TrustAnchor with subject \"" +
+                 trustedCert.getSubjectX500Principal() +
+                 "\" does not have keyCertSign bit set in KeyUsage extension");
+        }
+    }
+
     private X509Certificate[] doBuild(X509Certificate[] chain,
         Collection<X509Certificate> otherCerts,
         PKIXBuilderParameters params) throws CertificateException {
--- a/src/share/classes/sun/security/x509/AVA.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/security/x509/AVA.java	Thu Feb 06 01:43:16 2020 +0000
@@ -42,7 +42,7 @@
  * X.500 Attribute-Value-Assertion (AVA):  an attribute, as identified by
  * some attribute ID, has some particular value.  Values are as a rule ASN.1
  * printable strings.  A conventional set of type IDs is recognized when
- * parsing (and generating) RFC 1779 or RFC 2253 syntax strings.
+ * parsing (and generating) RFC 1779, 2253 or 4514 syntax strings.
  *
  * <P>AVAs are components of X.500 relative names.  Think of them as being
  * individual fields of a database record.  The attribute ID is how you
@@ -92,18 +92,20 @@
      * Leading and trailing spaces, also multiple internal spaces, also
      * call for quoting the whole string.
      */
-    private static final String specialChars = ",+=\n<>#;";
+    private static final String specialChars1779 = ",=\n+<>#;\\\"";
 
     /*
      * In RFC2253, if the value has any of these characters in it, it
      * must be quoted by a preceding \.
      */
-    private static final String specialChars2253 = ",+\"\\<>;";
+    private static final String specialChars2253 = ",=+<>#;\\\"";
 
     /*
-     * includes special chars from RFC1779 and RFC2253, as well as ' '
+     * includes special chars from RFC1779 and RFC2253, as well as ' ' from
+     * RFC 4514.
      */
-    private static final String specialCharsAll = ",=\n+<>#;\\\" ";
+    private static final String specialCharsDefault = ",=\n+<>#;\\\" ";
+    private static final String escapedDefault = ",+<>;\"";
 
     /*
      * Values that aren't printable strings are emitted as BER-encoded
@@ -120,26 +122,26 @@
     }
 
     /**
-     * Parse an RFC 1779 or RFC 2253 style AVA string:  CN=fee fie foe fum
+     * Parse an RFC 1779, 2253 or 4514 style AVA string:  CN=fee fie foe fum
      * or perhaps with quotes.  Not all defined AVA tags are supported;
      * of current note are X.400 related ones (PRMD, ADMD, etc).
      *
      * This terminates at unescaped AVA separators ("+") or RDN
-     * separators (",", ";"), or DN terminators (">"), and removes
-     * cosmetic whitespace at the end of values.
+     * separators (",", ";"), and removes cosmetic whitespace at the end of
+     * values.
      */
     AVA(Reader in) throws IOException {
         this(in, DEFAULT);
     }
 
     /**
-     * Parse an RFC 1779 or RFC 2253 style AVA string:  CN=fee fie foe fum
+     * Parse an RFC 1779, 2253 or 4514 style AVA string:  CN=fee fie foe fum
      * or perhaps with quotes. Additional keywords can be specified in the
      * keyword/OID map.
      *
      * This terminates at unescaped AVA separators ("+") or RDN
-     * separators (",", ";"), or DN terminators (">"), and removes
-     * cosmetic whitespace at the end of values.
+     * separators (",", ";"), and removes cosmetic whitespace at the end of
+     * values.
      */
     AVA(Reader in, Map<String, String> keywordMap) throws IOException {
         this(in, DEFAULT, keywordMap);
@@ -147,9 +149,6 @@
 
     /**
      * Parse an AVA string formatted according to format.
-     *
-     * XXX format RFC1779 should only allow RFC1779 syntax but is
-     * actually DEFAULT with RFC1779 keywords.
      */
     AVA(Reader in, int format) throws IOException {
         this(in, format, Collections.<String, String>emptyMap());
@@ -158,9 +157,6 @@
     /**
      * Parse an AVA string formatted according to format.
      *
-     * XXX format RFC1779 should only allow RFC1779 syntax but is
-     * actually DEFAULT with RFC1779 keywords.
-     *
      * @param in Reader containing AVA String
      * @param format parsing format
      * @param keywordMap a Map where a keyword String maps to a corresponding
@@ -168,11 +164,11 @@
      *   If an entry does not exist, it will fallback to the builtin
      *   keyword/OID mapping.
      * @throws IOException if the AVA String is not valid in the specified
-     *   standard or an OID String from the keywordMap is improperly formatted
+     *   format or an OID String from the keywordMap is improperly formatted
      */
     AVA(Reader in, int format, Map<String, String> keywordMap)
         throws IOException {
-        // assume format is one of DEFAULT, RFC1779, RFC2253
+        // assume format is one of DEFAULT or RFC2253
 
         StringBuilder   temp = new StringBuilder();
         int             c;
@@ -193,7 +189,7 @@
 
         /*
          * Now parse the value.  "#hex", a quoted string, or a string
-         * terminated by "+", ",", ";", ">".  Whitespace before or after
+         * terminated by "+", ",", ";".  Whitespace before or after
          * the value is stripped away unless format is RFC2253.
          */
         temp.setLength(0);
@@ -202,7 +198,7 @@
             c = in.read();
             if (c == ' ') {
                 throw new IOException("Incorrect AVA RFC2253 format - " +
-                                        "leading space must be escaped");
+                                      "leading space must be escaped");
             }
         } else {
             // read next character skipping whitespace
@@ -331,8 +327,7 @@
                     continue;
                 }
 
-                if (c != '\\' && c != '"' &&
-                    specialChars.indexOf((char)c) < 0) {
+                if (specialChars1779.indexOf((char)c) < 0) {
                     throw new IOException
                         ("Invalid escaped character in AVA: " +
                         (char)c);
@@ -386,7 +381,7 @@
     private DerValue parseString
         (Reader in, int c, int format, StringBuilder temp) throws IOException {
 
-        List<Byte> embeddedHex = new ArrayList<Byte>();
+        List<Byte> embeddedHex = new ArrayList<>();
         boolean isPrintableString = true;
         boolean escape = false;
         boolean leadingChar = true;
@@ -413,24 +408,19 @@
                 }
 
                 // check if character was improperly escaped
-                if ((format == DEFAULT &&
-                        specialCharsAll.indexOf((char)c) == -1) ||
-                    (format == RFC1779  &&
-                        specialChars.indexOf((char)c) == -1 &&
-                        c != '\\' && c != '\"')) {
-
+                if (format == DEFAULT &&
+                       specialCharsDefault.indexOf((char)c) == -1) {
                     throw new IOException
                         ("Invalid escaped character in AVA: '" +
                         (char)c + "'");
-
                 } else if (format == RFC2253) {
                     if (c == ' ') {
                         // only leading/trailing space can be escaped
                         if (!leadingChar && !trailingSpace(in)) {
-                                throw new IOException
-                                        ("Invalid escaped space character " +
-                                        "in AVA.  Only a leading or trailing " +
-                                        "space character can be escaped.");
+                            throw new IOException
+                                    ("Invalid escaped space character " +
+                                    "in AVA.  Only a leading or trailing " +
+                                    "space character can be escaped.");
                         }
                     } else if (c == '#') {
                         // only leading '#' can be escaped
@@ -443,18 +433,20 @@
                         throw new IOException
                                 ("Invalid escaped character in AVA: '" +
                                 (char)c + "'");
-
                     }
                 }
-
             } else {
                 // check if character should have been escaped
                 if (format == RFC2253) {
                     if (specialChars2253.indexOf((char)c) != -1) {
                         throw new IOException
                                 ("Character '" + (char)c +
-                                "' in AVA appears without escape");
+                                 "' in AVA appears without escape");
                     }
+                } else if (escapedDefault.indexOf((char)c) != -1) {
+                    throw new IOException
+                            ("Character '" + (char)c +
+                            "' in AVA appears without escape");
                 }
             }
 
@@ -551,7 +543,6 @@
         case ',':
             return true;
         case ';':
-        case '>':
             return format != RFC2253;
         default:
             return false;
@@ -608,7 +599,7 @@
         if (derval.tag != DerValue.tag_Sequence) {
             throw new IOException("AVA not a sequence");
         }
-        oid = X500Name.intern(derval.data.getOID());
+        oid = derval.data.getOID();
         value = derval.data.getDerValue();
 
         if (derval.data.available() != 0) {
@@ -1214,18 +1205,6 @@
      * Get an object identifier representing the specified keyword (or
      * string encoded object identifier) in the given standard.
      *
-     * @throws IOException If the keyword is not valid in the specified standard
-     */
-    static ObjectIdentifier getOID(String keyword, int standard)
-            throws IOException {
-        return getOID
-            (keyword, standard, Collections.<String, String>emptyMap());
-    }
-
-    /**
-     * Get an object identifier representing the specified keyword (or
-     * string encoded object identifier) in the given standard.
-     *
      * @param keywordMap a Map where a keyword String maps to a corresponding
      *   OID String. Each AVA keyword will be mapped to the corresponding OID.
      *   If an entry does not exist, it will fallback to the builtin
@@ -1259,19 +1238,11 @@
             return new ObjectIdentifier(oidString);
         }
 
-        // no keyword found or not standard compliant, check if OID string
+        // no keyword found, check if OID string
+        if (standard == AVA.DEFAULT && keyword.startsWith("OID.")) {
+            keyword = keyword.substring(4);
+        }
 
-        // RFC1779 requires, DEFAULT allows OID. prefix
-        if (standard == AVA.RFC1779) {
-            if (keyword.startsWith("OID.") == false) {
-                throw new IOException("Invalid RFC1779 keyword: " + keyword);
-            }
-            keyword = keyword.substring(4);
-        } else if (standard == AVA.DEFAULT) {
-            if (keyword.startsWith("OID.")) {
-                keyword = keyword.substring(4);
-            }
-        }
         boolean number = false;
         if (keyword.length() != 0) {
             char ch = keyword.charAt(0);
--- a/src/share/classes/sun/security/x509/AuthorityInfoAccessExtension.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/security/x509/AuthorityInfoAccessExtension.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -43,7 +43,7 @@
  * certificate that identifies the specific OCSP Responder to use when
  * performing on-line validation of that certificate.
  * <p>
- * This extension is defined in <a href="http://www.ietf.org/rfc/rfc3280.txt">
+ * This extension is defined in <a href="http://tools.ietf.org/html/rfc5280">
  * Internet X.509 PKI Certificate and Certificate Revocation List
  * (CRL) Profile</a>. The profile permits
  * the extension to be included in end-entity or CA certificates,
--- a/src/share/classes/sun/security/x509/CertificateIssuerExtension.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/security/x509/CertificateIssuerExtension.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -44,7 +44,7 @@
  * <p>
  * If used by conforming CRL issuers, this extension is always
  * critical.  If an implementation ignored this extension it could not
- * correctly attribute CRL entries to certificates.  PKIX (RFC 3280)
+ * correctly attribute CRL entries to certificates.  PKIX (RFC 5280)
  * RECOMMENDS that implementations recognize this extension.
  * <p>
  * The ASN.1 definition for this is:
--- a/src/share/classes/sun/security/x509/DeltaCRLIndicatorExtension.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/security/x509/DeltaCRLIndicatorExtension.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -45,7 +45,7 @@
  *
  * <p>
  * The extension is defined in Section 5.2.4 of
- * <a href="http://www.ietf.org/rfc/rfc3280.txt">Internet X.509 PKI Certific
+ * <a href="http://tools.ietf.org/html/rfc5280">Internet X.509 PKI Certific
 ate and Certificate Revocation List (CRL) Profile</a>.
  *
  * <p>
--- a/src/share/classes/sun/security/x509/ExtendedKeyUsageExtension.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/security/x509/ExtendedKeyUsageExtension.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -94,7 +94,7 @@
     public static final String NAME = "ExtendedKeyUsage";
     public static final String USAGES = "usages";
 
-    // OID defined in RFC 3280 Sections 4.2.1.13
+    // OID defined in RFC 5280 Sections 4.2.1.12
     // more from http://www.alvestrand.no/objectid/1.3.6.1.5.5.7.3.html
     private static final Map <ObjectIdentifier, String> map =
             new HashMap <ObjectIdentifier, String> ();
--- a/src/share/classes/sun/security/x509/FreshestCRLExtension.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/security/x509/FreshestCRLExtension.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -42,7 +42,7 @@
  *
  * <p>
  * The extension is defined in Section 5.2.6 of
- * <a href="http://www.ietf.org/rfc/rfc3280.txt">Internet X.509 PKI Certific
+ * <a href="http://tools.ietf.org/html/rfc5280">Internet X.509 PKI Certific
 ate and Certificate Revocation List (CRL) Profile</a>.
  *
  * <p>
--- a/src/share/classes/sun/security/x509/InvalidityDateExtension.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/security/x509/InvalidityDateExtension.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -33,7 +33,7 @@
 import sun.security.util.*;
 
 /**
- * From RFC 3280:
+ * From RFC 5280:
  * <p>
  * The invalidity date is a non-critical CRL entry extension that
  * provides the date on which it is known or suspected that the private
--- a/src/share/classes/sun/security/x509/IssuingDistributionPointExtension.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/security/x509/IssuingDistributionPointExtension.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -46,7 +46,7 @@
  *
  * <p>
  * The extension is defined in Section 5.2.5 of
- * <a href="http://www.ietf.org/rfc/rfc3280.txt">Internet X.509 PKI Certific
+ * <a href="http://tools.ietf.org/html/rfc5280">Internet X.509 PKI Certific
 ate and Certificate Revocation List (CRL) Profile</a>.
  *
  * <p>
--- a/src/share/classes/sun/security/x509/RDN.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/security/x509/RDN.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -346,7 +346,7 @@
     /*
      * Returns a printable form of this RDN, using RFC 1779 style catenation
      * of attribute/value assertions, and emitting attribute type keywords
-     * from RFCs 1779, 2253, and 3280.
+     * from RFCs 1779, 2253, and 5280.
      */
     public String toString() {
         if (assertion.length == 1) {
--- a/src/share/classes/sun/security/x509/README	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/security/x509/README	Thu Feb 06 01:43:16 2020 +0000
@@ -34,7 +34,7 @@
     Protocol (LDAP) that many organizations are expecting will help
     address online certificate distribution over the Internet.
 
-    RFC 3280, which describes the Internet X.509 Public Key
+    RFC 5280, which describes the Internet X.509 Public Key
     Infrastructure Certificate and CRL Profile.  
 
     RSA DSI has a bunch of "Public Key Cryptography Standards" (PKCS) which
--- a/src/share/classes/sun/security/x509/SubjectInfoAccessExtension.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/security/x509/SubjectInfoAccessExtension.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -48,7 +48,7 @@
  * included in end entity or CA certificates.  Conforming CAs MUST mark
  * this extension as non-critical.
  * <p>
- * This extension is defined in <a href="http://www.ietf.org/rfc/rfc3280.txt">
+ * This extension is defined in <a href="http://tools.ietf.org/html/rfc5280">
  * Internet X.509 PKI Certificate and Certificate Revocation List
  * (CRL) Profile</a>. The profile permits
  * the extension to be included in end-entity or CA certificates,
--- a/src/share/classes/sun/security/x509/URIName.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/security/x509/URIName.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -35,15 +35,15 @@
  * This class implements the URIName as required by the GeneralNames
  * ASN.1 object.
  * <p>
- * [RFC3280] When the subjectAltName extension contains a URI, the name MUST be
+ * [RFC5280] When the subjectAltName extension contains a URI, the name MUST be
  * stored in the uniformResourceIdentifier (an IA5String). The name MUST
  * be a non-relative URL, and MUST follow the URL syntax and encoding
- * rules specified in [RFC 1738].  The name must include both a scheme
+ * rules specified in [RFC 3986].  The name must include both a scheme
  * (e.g., "http" or "ftp") and a scheme-specific-part.  The scheme-
  * specific-part must include a fully qualified domain name or IP
  * address as the host.
  * <p>
- * As specified in [RFC 1738], the scheme name is not case-sensitive
+ * As specified in [RFC 3986], the scheme name is not case-sensitive
  * (e.g., "http" is equivalent to "HTTP").  The host part is also not
  * case-sensitive, but other components of the scheme-specific-part may
  * be case-sensitive. When comparing URIs, conforming implementations
@@ -114,7 +114,7 @@
         }
 
         host = uri.getHost();
-        // RFC 3280 says that the host should be non-null, but we allow it to
+        // RFC 5280 says that the host should be non-null, but we allow it to
         // be null because some widely deployed certificates contain CDP
         // extensions with URIs that have no hostname (see bugs 4802236 and
         // 5107944).
@@ -149,7 +149,7 @@
     /**
      * Create the URIName object with the specified name constraint. URI
      * name constraints syntax is different than SubjectAltNames, etc. See
-     * 4.2.1.11 of RFC 3280.
+     * 4.2.1.10 of RFC 5280.
      *
      * @param value the URI name constraint
      * @throws IOException if name is not a proper URI name constraint
@@ -303,7 +303,7 @@
      * These results are used in checking NameConstraints during
      * certification path verification.
      * <p>
-     * RFC3280: For URIs, the constraint applies to the host part of the name.
+     * RFC5280: For URIs, the constraint applies to the host part of the name.
      * The constraint may specify a host or a domain.  Examples would be
      * "foo.bar.com";  and ".xyz.com".  When the the constraint begins with
      * a period, it may be expanded with one or more subdomains.  That is,
--- a/src/share/classes/sun/security/x509/X500Name.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/security/x509/X500Name.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -142,9 +142,9 @@
     /**
      * Constructs a name from a conventionally formatted string, such
      * as "CN=Dave, OU=JavaSoft, O=Sun Microsystems, C=US".
-     * (RFC 1779 or RFC 2253 style).
+     * (RFC 1779, 2253, or 4514 style).
      *
-     * @param DN X.500 Distinguished Name
+     * @param dname the X.500 Distinguished Name
      */
     public X500Name(String dname) throws IOException {
         this(dname, Collections.<String, String>emptyMap());
@@ -153,9 +153,9 @@
     /**
      * Constructs a name from a conventionally formatted string, such
      * as "CN=Dave, OU=JavaSoft, O=Sun Microsystems, C=US".
-     * (RFC 1779 or RFC 2253 style).
+     * (RFC 1779, 2253, or 4514 style).
      *
-     * @param DN X.500 Distinguished Name
+     * @param dname the X.500 Distinguished Name
      * @param keywordMap an additional keyword/OID map
      */
     public X500Name(String dname, Map<String, String> keywordMap)
@@ -167,10 +167,11 @@
      * Constructs a name from a string formatted according to format.
      * Currently, the formats DEFAULT and RFC2253 are supported.
      * DEFAULT is the default format used by the X500Name(String)
-     * constructor. RFC2253 is format strictly according to RFC2253
+     * constructor. RFC2253 is the format strictly according to RFC2253
      * without extensions.
      *
-     * @param DN X.500 Distinguished Name
+     * @param dname the X.500 Distinguished Name
+     * @param format the specified format of the String DN
      */
     public X500Name(String dname, String format) throws IOException {
         if (dname == null) {
@@ -603,7 +604,7 @@
      * Returns a string form of the X.500 distinguished name.
      * The format of the string is from RFC 1779. The returned string
      * may contain non-standardised keywords for more readability
-     * (keywords from RFCs 1779, 2253, and 3280).
+     * (keywords from RFCs 1779, 2253, and 5280).
      */
     public String toString() {
         if (dn == null) {
@@ -864,8 +865,8 @@
      *     O="Sue, Grabbit and Runn" or
      *     O=Sue\, Grabbit and Runn
      *
-     * This method can parse 1779 or 2253 DNs and non-standard 3280 keywords.
-     * Additional keywords can be specified in the keyword/OID map.
+     * This method can parse RFC 1779, 2253 or 4514 DNs and non-standard 5280
+     * keywords. Additional keywords can be specified in the keyword/OID map.
      */
     private void parseDN(String input, Map<String, String> keywordMap)
         throws IOException {
@@ -874,7 +875,7 @@
             return;
         }
 
-        List<RDN> dnVector = new ArrayList<RDN>();
+        List<RDN> dnVector = new ArrayList<>();
         int dnOffset = 0;
         int rdnEnd;
         String rdnString;
@@ -944,52 +945,51 @@
         if (dnString.length() == 0) {
             names = new RDN[0];
             return;
-        }
-
-        List<RDN> dnVector = new ArrayList<RDN>();
-        int dnOffset = 0;
-        String rdnString;
+         }
 
-        int searchOffset = 0;
-        int rdnEnd = dnString.indexOf(',');
-        while (rdnEnd >=0) {
-            /*
-             * We have encountered an RDN delimiter (comma).
-             * If the comma in the RDN under consideration is
-             * preceded by a backslash (escape), it
-             * is part of the RDN. Otherwise, it is used as a separator, to
-             * delimit the RDN under consideration from any subsequent RDNs.
-             */
-            if (rdnEnd > 0 && !escaped(rdnEnd, searchOffset, dnString)) {
+         List<RDN> dnVector = new ArrayList<>();
+         int dnOffset = 0;
+         String rdnString;
+         int searchOffset = 0;
+         int rdnEnd = dnString.indexOf(',');
+         while (rdnEnd >=0) {
+             /*
+              * We have encountered an RDN delimiter (comma).
+              * If the comma in the RDN under consideration is
+              * preceded by a backslash (escape), it
+              * is part of the RDN. Otherwise, it is used as a separator, to
+              * delimit the RDN under consideration from any subsequent RDNs.
+              */
+             if (rdnEnd > 0 && !escaped(rdnEnd, searchOffset, dnString)) {
 
-                /*
-                 * Comma is a separator
-                 */
-                rdnString = dnString.substring(dnOffset, rdnEnd);
+                 /*
+                  * Comma is a separator
+                  */
+                 rdnString = dnString.substring(dnOffset, rdnEnd);
 
-                // Parse RDN, and store it in vector
-                RDN rdn = new RDN(rdnString, "RFC2253");
-                dnVector.add(rdn);
+                 // Parse RDN, and store it in vector
+                 RDN rdn = new RDN(rdnString, "RFC2253");
+                 dnVector.add(rdn);
 
-                // Increase the offset
-                dnOffset = rdnEnd + 1;
-            }
+                 // Increase the offset
+                 dnOffset = rdnEnd + 1;
+             }
 
-            searchOffset = rdnEnd + 1;
-            rdnEnd = dnString.indexOf(',', searchOffset);
-        }
+             searchOffset = rdnEnd + 1;
+             rdnEnd = dnString.indexOf(',', searchOffset);
+         }
 
-        // Parse last or only RDN, and store it in vector
-        rdnString = dnString.substring(dnOffset);
-        RDN rdn = new RDN(rdnString, "RFC2253");
-        dnVector.add(rdn);
+         // Parse last or only RDN, and store it in vector
+         rdnString = dnString.substring(dnOffset);
+         RDN rdn = new RDN(rdnString, "RFC2253");
+         dnVector.add(rdn);
 
-        /*
-         * Store the vector elements as an array of RDNs
-         * NOTE: It's only on output that little-endian ordering is used.
-         */
-        Collections.reverse(dnVector);
-        names = dnVector.toArray(new RDN[dnVector.size()]);
+         /*
+          * Store the vector elements as an array of RDNs
+          * NOTE: It's only on output that little-endian ordering is used.
+          */
+         Collections.reverse(dnVector);
+         names = dnVector.toArray(new RDN[dnVector.size()]);
     }
 
     /*
@@ -1104,24 +1104,8 @@
     /****************************************************************/
 
     /*
-     * Maybe return a preallocated OID, to reduce storage costs
-     * and speed recognition of common X.500 attributes.
-     */
-    static ObjectIdentifier intern(ObjectIdentifier oid) {
-        ObjectIdentifier interned = internedOIDs.get(oid);
-        if (interned != null) {
-            return interned;
-        }
-        internedOIDs.put(oid, oid);
-        return oid;
-    }
-
-    private static final Map<ObjectIdentifier,ObjectIdentifier> internedOIDs
-                        = new HashMap<ObjectIdentifier,ObjectIdentifier>();
-
-    /*
      * Selected OIDs from X.520
-     * Includes all those specified in RFC 3280 as MUST or SHOULD
+     * Includes all those specified in RFC 5280 as MUST or SHOULD
      * be recognized
      */
     private static final int commonName_data[] = { 2, 5, 4, 3 };
@@ -1146,92 +1130,82 @@
         { 0, 9, 2342, 19200300, 100, 1, 1 };
 
 
-    public static final ObjectIdentifier commonName_oid;
-    public static final ObjectIdentifier countryName_oid;
-    public static final ObjectIdentifier localityName_oid;
-    public static final ObjectIdentifier orgName_oid;
-    public static final ObjectIdentifier orgUnitName_oid;
-    public static final ObjectIdentifier stateName_oid;
-    public static final ObjectIdentifier streetAddress_oid;
-    public static final ObjectIdentifier title_oid;
-    public static final ObjectIdentifier DNQUALIFIER_OID;
-    public static final ObjectIdentifier SURNAME_OID;
-    public static final ObjectIdentifier GIVENNAME_OID;
-    public static final ObjectIdentifier INITIALS_OID;
-    public static final ObjectIdentifier GENERATIONQUALIFIER_OID;
-    public static final ObjectIdentifier ipAddress_oid;
-    public static final ObjectIdentifier DOMAIN_COMPONENT_OID;
-    public static final ObjectIdentifier userid_oid;
-    public static final ObjectIdentifier SERIALNUMBER_OID;
+    // OID for the "CN=" attribute, denoting a person's common name.
+    public static final ObjectIdentifier commonName_oid =
+            ObjectIdentifier.newInternal(commonName_data);
+
+    // OID for the "SERIALNUMBER=" attribute, denoting a serial number for.
+    // a name. Do not confuse with PKCS#9 issuerAndSerialNumber or the
+    // certificate serial number.
+    public static final ObjectIdentifier SERIALNUMBER_OID =
+            ObjectIdentifier.newInternal(SERIALNUMBER_DATA);
+
+    // OID for the "C=" attribute, denoting a country.
+    public static final ObjectIdentifier countryName_oid =
+            ObjectIdentifier.newInternal(countryName_data);
+
+    // OID for the "L=" attribute, denoting a locality (such as a city).
+    public static final ObjectIdentifier localityName_oid =
+            ObjectIdentifier.newInternal(localityName_data);
 
-    static {
-    /** OID for the "CN=" attribute, denoting a person's common name. */
-        commonName_oid = intern(ObjectIdentifier.newInternal(commonName_data));
+    // OID for the "O=" attribute, denoting an organization name.
+    public static final ObjectIdentifier orgName_oid =
+            ObjectIdentifier.newInternal(orgName_data);
 
-    /** OID for the "SERIALNUMBER=" attribute, denoting a serial number for.
-        a name. Do not confuse with PKCS#9 issuerAndSerialNumber or the
-        certificate serial number. */
-        SERIALNUMBER_OID = intern(ObjectIdentifier.newInternal(SERIALNUMBER_DATA));
-
-    /** OID for the "C=" attribute, denoting a country. */
-        countryName_oid = intern(ObjectIdentifier.newInternal(countryName_data));
+    // OID for the "OU=" attribute, denoting an organizational unit name.
+    public static final ObjectIdentifier orgUnitName_oid =
+            ObjectIdentifier.newInternal(orgUnitName_data);
 
-    /** OID for the "L=" attribute, denoting a locality (such as a city) */
-        localityName_oid = intern(ObjectIdentifier.newInternal(localityName_data));
-
-    /** OID for the "O=" attribute, denoting an organization name */
-        orgName_oid = intern(ObjectIdentifier.newInternal(orgName_data));
+    // OID for the "S=" attribute, denoting a state (such as Delaware).
+    public static final ObjectIdentifier stateName_oid =
+            ObjectIdentifier.newInternal(stateName_data);
 
-    /** OID for the "OU=" attribute, denoting an organizational unit name */
-        orgUnitName_oid = intern(ObjectIdentifier.newInternal(orgUnitName_data));
+    // OID for the "STREET=" attribute, denoting a street address.
+    public static final ObjectIdentifier streetAddress_oid =
+            ObjectIdentifier.newInternal(streetAddress_data);
 
-    /** OID for the "S=" attribute, denoting a state (such as Delaware) */
-        stateName_oid = intern(ObjectIdentifier.newInternal(stateName_data));
+    // OID for the "T=" attribute, denoting a person's title.
+    public static final ObjectIdentifier title_oid =
+            ObjectIdentifier.newInternal(title_data);
 
-    /** OID for the "STREET=" attribute, denoting a street address. */
-        streetAddress_oid = intern(ObjectIdentifier.newInternal(streetAddress_data));
-
-    /** OID for the "T=" attribute, denoting a person's title. */
-        title_oid = intern(ObjectIdentifier.newInternal(title_data));
+    // OID for the "DNQUALIFIER=" or "DNQ=" attribute, denoting DN
+    // disambiguating information.
+    public static final ObjectIdentifier DNQUALIFIER_OID =
+            ObjectIdentifier.newInternal(DNQUALIFIER_DATA);
 
-    /** OID for the "DNQUALIFIER=" or "DNQ=" attribute, denoting DN
-        disambiguating information.*/
-        DNQUALIFIER_OID = intern(ObjectIdentifier.newInternal(DNQUALIFIER_DATA));
+    // OID for the "SURNAME=" attribute, denoting a person's surname.
+    public static final ObjectIdentifier SURNAME_OID =
+            ObjectIdentifier.newInternal(SURNAME_DATA);
 
-    /** OID for the "SURNAME=" attribute, denoting a person's surname.*/
-        SURNAME_OID = intern(ObjectIdentifier.newInternal(SURNAME_DATA));
+    // OID for the "GIVENNAME=" attribute, denoting a person's given name.
+    public static final ObjectIdentifier GIVENNAME_OID =
+            ObjectIdentifier.newInternal(GIVENNAME_DATA);
 
-    /** OID for the "GIVENNAME=" attribute, denoting a person's given name.*/
-        GIVENNAME_OID = intern(ObjectIdentifier.newInternal(GIVENNAME_DATA));
-
-    /** OID for the "INITIALS=" attribute, denoting a person's initials.*/
-        INITIALS_OID = intern(ObjectIdentifier.newInternal(INITIALS_DATA));
+    // OID for the "INITIALS=" attribute, denoting a person's initials.
+    public static final ObjectIdentifier INITIALS_OID =
+            ObjectIdentifier.newInternal(INITIALS_DATA);
 
-    /** OID for the "GENERATION=" attribute, denoting Jr., II, etc.*/
-        GENERATIONQUALIFIER_OID =
-            intern(ObjectIdentifier.newInternal(GENERATIONQUALIFIER_DATA));
+    // OID for the "GENERATION=" attribute, denoting Jr., II, etc.
+    public static final ObjectIdentifier GENERATIONQUALIFIER_OID =
+            ObjectIdentifier.newInternal(GENERATIONQUALIFIER_DATA);
 
-    /*
-     * OIDs from other sources which show up in X.500 names we
-     * expect to deal with often
-     */
-    /** OID for "IP=" IP address attributes, used with SKIP. */
-        ipAddress_oid = intern(ObjectIdentifier.newInternal(ipAddress_data));
+    // OIDs from other sources which show up in X.500 names we
+    // expect to deal with often.
+    //
+    // OID for "IP=" IP address attributes, used with SKIP.
+    public static final ObjectIdentifier ipAddress_oid =
+            ObjectIdentifier.newInternal(ipAddress_data);
 
-    /*
-     * Domain component OID from RFC 1274, RFC 2247, RFC 3280
-     */
+    // Domain component OID from RFC 1274, RFC 2247, RFC 5280.
+    //
+    // OID for "DC=" domain component attributes, used with DNSNames in DN
+    // format.
+    public static final ObjectIdentifier DOMAIN_COMPONENT_OID =
+            ObjectIdentifier.newInternal(DOMAIN_COMPONENT_DATA);
 
-    /*
-     * OID for "DC=" domain component attributes, used with DNS names in DN
-     * format
-     */
-        DOMAIN_COMPONENT_OID =
-            intern(ObjectIdentifier.newInternal(DOMAIN_COMPONENT_DATA));
-
-    /** OID for "UID=" denoting a user id, defined in RFCs 1274 & 2798. */
-        userid_oid = intern(ObjectIdentifier.newInternal(userid_data));
-    }
+    // OID for "UID=" denoting a user id, defined in RFCs 1274 & 2798.
+    public static final ObjectIdentifier userid_oid =
+            ObjectIdentifier.newInternal(userid_data);
 
     /**
      * Return constraint type:<ul>
--- a/src/share/classes/sun/security/x509/X509CRLImpl.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/security/x509/X509CRLImpl.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -62,7 +62,7 @@
  *     signature            BIT STRING  }
  * </pre>
  * More information can be found in
- * <a href="http://www.ietf.org/rfc/rfc3280.txt">RFC 3280: Internet X.509
+ * <a href="http://tools.ietf.org/html/rfc5280">RFC 5280: Internet X.509
  * Public Key Infrastructure Certificate and CRL Profile</a>.
  * <p>
  * The ASN.1 definition of <code>tbsCertList</code> is:
--- a/src/share/classes/sun/security/x509/X509CertInfo.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/classes/sun/security/x509/X509CertInfo.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -740,7 +740,7 @@
     }
 
     /*
-     * Verify if X.509 V3 Certificate is compliant with RFC 3280.
+     * Verify if X.509 V3 Certificate is compliant with RFC 5280.
      */
     private void verifyCert(CertificateSubjectName subject,
         CertificateExtensions extensions)
--- a/src/share/lib/security/java.security-linux	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/lib/security/java.security-linux	Thu Feb 06 01:43:16 2020 +0000
@@ -278,7 +278,7 @@
 # By default, the location of the OCSP responder is determined implicitly
 # from the certificate being validated. This property explicitly specifies
 # the location of the OCSP responder. The property is used when the
-# Authority Information Access extension (defined in RFC 3280) is absent
+# Authority Information Access extension (defined in RFC 5280) is absent
 # from the certificate or when it requires overriding.
 #
 # Example,
@@ -798,8 +798,8 @@
 # Patterns are separated by ";" (semicolon).
 # Whitespace is significant and is considered part of the pattern.
 #
-# If the system property jdk.serialFilter is also specified, it supersedes
-# the security property value defined here.
+# If the system property jdk.serialFilter is also specified on the command
+# line, it supersedes the security property value defined here.
 #
 # If a pattern includes a "=", it sets a limit.
 # If a limit appears more than once the last value is used.
@@ -898,6 +898,24 @@
   java.security.KeyRep$Type;javax.crypto.spec.SecretKeySpec;!*
 
 #
+# Disabled mechanisms for the Simple Authentication and Security Layer (SASL)
+#
+# Disabled mechanisms will not be negotiated by both SASL clients and servers.
+# These mechanisms will be ignored if they are specified in the "mechanisms"
+# argument of "Sasl.createSaslClient" or the "mechanism" argument of
+# "Sasl.createSaslServer".
+#
+# The value of this property is a comma-separated list of SASL mechanisms.
+# The mechanisms are case-sensitive. Whitespaces around the commas are ignored.
+#
+# Note: This property is currently used by the JDK Reference implementation.
+# It is not guaranteed to be examined and used by other implementations.
+#
+# Example:
+#   jdk.sasl.disabledMechanisms=PLAIN, CRAM-MD5, DIGEST-MD5
+jdk.sasl.disabledMechanisms=
+
+#
 # Policies for distrusting Certificate Authorities (CAs).
 #
 # This is a comma separated value of one or more case-sensitive strings, each
--- a/src/share/lib/security/java.security-macosx	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/lib/security/java.security-macosx	Thu Feb 06 01:43:16 2020 +0000
@@ -283,7 +283,7 @@
 # By default, the location of the OCSP responder is determined implicitly
 # from the certificate being validated. This property explicitly specifies
 # the location of the OCSP responder. The property is used when the
-# Authority Information Access extension (defined in RFC 3280) is absent
+# Authority Information Access extension (defined in RFC 5280) is absent
 # from the certificate or when it requires overriding.
 #
 # Example,
@@ -803,8 +803,8 @@
 # Patterns are separated by ";" (semicolon).
 # Whitespace is significant and is considered part of the pattern.
 #
-# If the system property jdk.serialFilter is also specified, it supersedes
-# the security property value defined here.
+# If the system property jdk.serialFilter is also specified on the command
+# line, it supersedes the security property value defined here.
 #
 # If a pattern includes a "=", it sets a limit.
 # If a limit appears more than once the last value is used.
@@ -897,6 +897,24 @@
   java.security.KeyRep$Type;javax.crypto.spec.SecretKeySpec;!*
 
 #
+# Disabled mechanisms for the Simple Authentication and Security Layer (SASL)
+#
+# Disabled mechanisms will not be negotiated by both SASL clients and servers.
+# These mechanisms will be ignored if they are specified in the "mechanisms"
+# argument of "Sasl.createSaslClient" or the "mechanism" argument of
+# "Sasl.createSaslServer".
+#
+# The value of this property is a comma-separated list of SASL mechanisms.
+# The mechanisms are case-sensitive. Whitespaces around the commas are ignored.
+#
+# Note: This property is currently used by the JDK Reference implementation.
+# It is not guaranteed to be examined and used by other implementations.
+#
+# Example:
+#   jdk.sasl.disabledMechanisms=PLAIN, CRAM-MD5, DIGEST-MD5
+jdk.sasl.disabledMechanisms=
+
+#
 # Policies for distrusting Certificate Authorities (CAs).
 #
 # This is a comma separated value of one or more case-sensitive strings, each
--- a/src/share/lib/security/java.security-solaris	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/lib/security/java.security-solaris	Thu Feb 06 01:43:16 2020 +0000
@@ -282,7 +282,7 @@
 # By default, the location of the OCSP responder is determined implicitly
 # from the certificate being validated. This property explicitly specifies
 # the location of the OCSP responder. The property is used when the
-# Authority Information Access extension (defined in RFC 3280) is absent
+# Authority Information Access extension (defined in RFC 5280) is absent
 # from the certificate or when it requires overriding.
 #
 # Example,
@@ -802,8 +802,8 @@
 # Patterns are separated by ";" (semicolon).
 # Whitespace is significant and is considered part of the pattern.
 #
-# If the system property jdk.serialFilter is also specified, it supersedes
-# the security property value defined here.
+# If the system property jdk.serialFilter is also specified on the command
+# line, it supersedes the security property value defined here.
 #
 # If a pattern includes a "=", it sets a limit.
 # If a limit appears more than once the last value is used.
@@ -896,6 +896,24 @@
   java.security.KeyRep$Type;javax.crypto.spec.SecretKeySpec;!*
 
 #
+# Disabled mechanisms for the Simple Authentication and Security Layer (SASL)
+#
+# Disabled mechanisms will not be negotiated by both SASL clients and servers.
+# These mechanisms will be ignored if they are specified in the "mechanisms"
+# argument of "Sasl.createSaslClient" or the "mechanism" argument of
+# "Sasl.createSaslServer".
+#
+# The value of this property is a comma-separated list of SASL mechanisms.
+# The mechanisms are case-sensitive. Whitespaces around the commas are ignored.
+#
+# Note: This property is currently used by the JDK Reference implementation.
+# It is not guaranteed to be examined and used by other implementations.
+#
+# Example:
+#   jdk.sasl.disabledMechanisms=PLAIN, CRAM-MD5, DIGEST-MD5
+jdk.sasl.disabledMechanisms=
+
+#
 # Policies for distrusting Certificate Authorities (CAs).
 #
 # This is a comma separated value of one or more case-sensitive strings, each
--- a/src/share/lib/security/java.security-windows	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/lib/security/java.security-windows	Thu Feb 06 01:43:16 2020 +0000
@@ -283,7 +283,7 @@
 # By default, the location of the OCSP responder is determined implicitly
 # from the certificate being validated. This property explicitly specifies
 # the location of the OCSP responder. The property is used when the
-# Authority Information Access extension (defined in RFC 3280) is absent
+# Authority Information Access extension (defined in RFC 5280) is absent
 # from the certificate or when it requires overriding.
 #
 # Example,
@@ -803,8 +803,8 @@
 # Patterns are separated by ";" (semicolon).
 # Whitespace is significant and is considered part of the pattern.
 #
-# If the system property jdk.serialFilter is also specified, it supersedes
-# the security property value defined here.
+# If the system property jdk.serialFilter is also specified on the command
+# line, it supersedes the security property value defined here.
 #
 # If a pattern includes a "=", it sets a limit.
 # If a limit appears more than once the last value is used.
@@ -897,6 +897,24 @@
   java.security.KeyRep$Type;javax.crypto.spec.SecretKeySpec;!*
 
 #
+# Disabled mechanisms for the Simple Authentication and Security Layer (SASL)
+#
+# Disabled mechanisms will not be negotiated by both SASL clients and servers.
+# These mechanisms will be ignored if they are specified in the "mechanisms"
+# argument of "Sasl.createSaslClient" or the "mechanism" argument of
+# "Sasl.createSaslServer".
+#
+# The value of this property is a comma-separated list of SASL mechanisms.
+# The mechanisms are case-sensitive. Whitespaces around the commas are ignored.
+#
+# Note: This property is currently used by the JDK Reference implementation.
+# It is not guaranteed to be examined and used by other implementations.
+#
+# Example:
+#   jdk.sasl.disabledMechanisms=PLAIN, CRAM-MD5, DIGEST-MD5
+jdk.sasl.disabledMechanisms=
+
+#
 # Policies for distrusting Certificate Authorities (CAs).
 #
 # This is a comma separated value of one or more case-sensitive strings, each
--- a/src/share/native/sun/font/freetypeScaler.c	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/share/native/sun/font/freetypeScaler.c	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -168,7 +168,7 @@
      */
 
     if (numBytes == 0) {
-        if (offset >= scalerInfo->fileSize) {
+        if (offset > scalerInfo->fileSize) {
             return -1;
         } else {
             return 0;
@@ -438,10 +438,18 @@
     return errCode;
 }
 
-/* ftsynth.c uses (0x10000, 0x06000, 0x0, 0x10000) matrix to get oblique
-   outline.  Therefore x coordinate will change by 0x06000*y.
-   Note that y coordinate does not change. */
-#define OBLIQUE_MODIFIER(y)  (context->doItalize ? ((y)*6/16) : 0)
+/* ftsynth.c uses (0x10000, 0x0366A, 0x0, 0x10000) matrix to get oblique
+   outline.  Therefore x coordinate will change by 0x0366A*y.
+   Note that y coordinate does not change. These values are based on
+   libfreetype version 2.9.1. */
+#define OBLIQUE_MODIFIER(y)  (context->doItalize ? ((y)*0x366A/0x10000) : 0)
+
+/* FT_GlyphSlot_Embolden (ftsynth.c) uses FT_MulFix(units_per_EM, y_scale) / 24
+ * strength value when glyph format is FT_GLYPH_FORMAT_OUTLINE. This value has
+ * been taken from libfreetype version 2.6 and remain valid at least up to
+ * 2.9.1. */
+#define BOLD_MODIFIER(units_per_EM, y_scale) \
+    (context->doBold ? FT_MulFix(units_per_EM, y_scale) / 24 : 0)
 
 /*
  * Class:     sun_font_FreetypeFontScaler
@@ -491,9 +499,13 @@
 
     /**** Note: only some metrics are affected by styling ***/
 
+    /* See https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=657854 */
 #define FT_MulFixFloatShift6(a, b) (((float) (a)) * ((float) (b)) / 65536.0 / 64.0)
 
-    /* See FreeType source code: src/base/ftobjs.c ft_recompute_scaled_metrics() */
+    /*
+     * See FreeType source code: src/base/ftobjs.c ft_recompute_scaled_metrics()
+     * http://icedtea.classpath.org/bugzilla/show_bug.cgi?id=1659
+     */
     /* ascent */
     ax = 0;
     ay = -(jfloat) (FT_MulFixFloatShift6(
@@ -516,7 +528,9 @@
     /* max advance */
     mx = (jfloat) FT26Dot6ToFloat(
                      scalerInfo->face->size->metrics.max_advance +
-                     OBLIQUE_MODIFIER(scalerInfo->face->size->metrics.height));
+                     OBLIQUE_MODIFIER(scalerInfo->face->size->metrics.height) +
+                     BOLD_MODIFIER(scalerInfo->face->units_per_EM,
+                             scalerInfo->face->size->metrics.y_scale));
     my = 0;
 
     metrics = (*env)->NewObject(env,
@@ -589,10 +603,14 @@
                                  pScalerContext, pScaler, glyphCode);
      info = (GlyphInfo*) jlong_to_ptr(image);
 
-     (*env)->SetFloatField(env, metrics, sunFontIDs.xFID, info->advanceX);
-     (*env)->SetFloatField(env, metrics, sunFontIDs.yFID, info->advanceY);
-
-     free(info);
+     if (info != NULL) {
+         (*env)->SetFloatField(env, metrics, sunFontIDs.xFID, info->advanceX);
+         (*env)->SetFloatField(env, metrics, sunFontIDs.yFID, info->advanceY);
+         free(info);
+     } else {
+         (*env)->SetFloatField(env, metrics, sunFontIDs.xFID, 0.0f);
+         (*env)->SetFloatField(env, metrics, sunFontIDs.yFID, 0.0f);
+     }
 }
 
 
@@ -878,7 +896,7 @@
     int glyph_index;
     FT_GlyphSlot ftglyph;
 #ifndef IMPROVED_FONT_RENDERING
-    int renderFlags = FT_LOAD_RENDER, target;
+    int renderFlags = FT_LOAD_DEFAULT, target;
 #endif
 
     FTScalerContext* context =
--- a/src/solaris/classes/sun/nio/ch/AixPollPort.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/solaris/classes/sun/nio/ch/AixPollPort.java	Thu Feb 06 01:43:16 2020 +0000
@@ -148,7 +148,7 @@
         try {
             socketpair(sv);
             // register one end with pollset
-            pollsetCtl(pollset, PS_ADD, sv[0], POLLIN);
+            pollsetCtl(pollset, PS_ADD, sv[0], Net.POLLIN);
         } catch (IOException x) {
             pollsetDestroy(pollset);
             throw x;
@@ -160,7 +160,7 @@
         try {
             socketpair(sv);
             // register one end with pollset
-            pollsetCtl(pollset, PS_ADD, sv[0], POLLIN);
+            pollsetCtl(pollset, PS_ADD, sv[0], Net.POLLIN);
         } catch (IOException x) {
             pollsetDestroy(pollset);
             throw x;
@@ -353,7 +353,7 @@
 
                                 // This is the only file descriptor without
                                 // one shot semantic => register it again.
-                                pollsetCtl(pollset, PS_ADD, sp[0], POLLIN);
+                                pollsetCtl(pollset, PS_ADD, sp[0], Net.POLLIN);
 
                                 // queue special event if there are more events
                                 // to handle.
@@ -370,7 +370,7 @@
                                     drain1(ctlSp[0]);
                                     // This file descriptor does not have
                                     // one shot semantic => register it again.
-                                    pollsetCtl(pollset, PS_ADD, ctlSp[0], POLLIN);
+                                    pollsetCtl(pollset, PS_ADD, ctlSp[0], Net.POLLIN);
                                     processControlQueue();
                                 }
                                 continue;
--- a/src/solaris/classes/sun/nio/ch/EPollPort.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/solaris/classes/sun/nio/ch/EPollPort.java	Thu Feb 06 01:43:16 2020 +0000
@@ -93,7 +93,7 @@
         try {
             socketpair(sv);
             // register one end with epoll
-            epollCtl(epfd, EPOLL_CTL_ADD, sv[0], POLLIN);
+            epollCtl(epfd, EPOLL_CTL_ADD, sv[0], Net.POLLIN);
         } catch (IOException x) {
             close0(epfd);
             throw x;
--- a/src/solaris/classes/sun/nio/ch/KQueuePort.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/solaris/classes/sun/nio/ch/KQueuePort.java	Thu Feb 06 01:43:16 2020 +0000
@@ -172,9 +172,9 @@
         // TBD: Measure cost of EV_ONESHOT vs. EV_CLEAR, either will do here.
         int err = 0;
         int flags = (EV_ADD|EV_ONESHOT);
-        if ((events & Port.POLLIN) > 0)
+        if ((events & Net.POLLIN) > 0)
             err = keventRegister(kqfd, fd, EVFILT_READ, flags);
-        if (err == 0 && (events & Port.POLLOUT) > 0)
+        if (err == 0 && (events & Net.POLLOUT) > 0)
             err = keventRegister(kqfd, fd, EVFILT_WRITE, flags);
         if (err != 0)
             throw new InternalError("kevent failed: " + err);  // should not happen
@@ -227,9 +227,9 @@
                                 int filter = getFilter(keventAddress);
                                 int events = 0;
                                 if (filter == EVFILT_READ)
-                                    events = Port.POLLIN;
+                                    events = Net.POLLIN;
                                 else if (filter == EVFILT_WRITE)
-                                    events = Port.POLLOUT;
+                                    events = Net.POLLOUT;
 
                                 Event ev = new Event(channel, events);
 
--- a/src/solaris/classes/sun/nio/ch/PollArrayWrapper.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/solaris/classes/sun/nio/ch/PollArrayWrapper.java	Thu Feb 06 01:43:16 2020 +0000
@@ -43,8 +43,6 @@
 
 class PollArrayWrapper extends AbstractPollArrayWrapper {
 
-    static final short POLLCONN = POLLOUT;
-
     // File descriptor to write for interrupt
     int interruptFD;
 
@@ -58,7 +56,7 @@
     void initInterrupt(int fd0, int fd1) {
         interruptFD = fd1;
         putDescriptor(0, fd0);
-        putEventOps(0, POLLIN);
+        putEventOps(0, Net.POLLIN);
         putReventOps(0, 0);
     }
 
--- a/src/solaris/classes/sun/nio/ch/Port.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/solaris/classes/sun/nio/ch/Port.java	Thu Feb 06 01:43:16 2020 +0000
@@ -40,10 +40,6 @@
  */
 
 abstract class Port extends AsynchronousChannelGroupImpl {
-    static final short POLLIN       = 0x0001;
-    static final short POLLOUT      = 0x0004;
-    static final short POLLERR      = 0x0008;
-    static final short POLLHUP      = 0x0010;
 
     /**
      * Implemented by clients registered with this port.
--- a/src/solaris/classes/sun/nio/ch/SctpChannelImpl.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/solaris/classes/sun/nio/ch/SctpChannelImpl.java	Thu Feb 06 01:43:16 2020 +0000
@@ -584,15 +584,14 @@
         int oldOps = sk.nioReadyOps();
         int newOps = initialOps;
 
-        if ((ops & PollArrayWrapper.POLLNVAL) != 0) {
+        if ((ops & Net.POLLNVAL) != 0) {
             /* This should only happen if this channel is pre-closed while a
              * selection operation is in progress
              * ## Throw an error if this channel has not been pre-closed */
             return false;
         }
 
-        if ((ops & (PollArrayWrapper.POLLERR
-                    | PollArrayWrapper.POLLHUP)) != 0) {
+        if ((ops & (Net.POLLERR | Net.POLLHUP)) != 0) {
             newOps = intOps;
             sk.nioReadyOps(newOps);
             /* No need to poll again in checkConnect,
@@ -601,19 +600,19 @@
             return (newOps & ~oldOps) != 0;
         }
 
-        if (((ops & PollArrayWrapper.POLLIN) != 0) &&
+        if (((ops & Net.POLLIN) != 0) &&
             ((intOps & SelectionKey.OP_READ) != 0) &&
             isConnected())
             newOps |= SelectionKey.OP_READ;
 
-        if (((ops & PollArrayWrapper.POLLCONN) != 0) &&
+        if (((ops & Net.POLLCONN) != 0) &&
             ((intOps & SelectionKey.OP_CONNECT) != 0) &&
             ((state == ChannelState.UNCONNECTED) || (state == ChannelState.PENDING))) {
             newOps |= SelectionKey.OP_CONNECT;
             readyToConnect = true;
         }
 
-        if (((ops & PollArrayWrapper.POLLOUT) != 0) &&
+        if (((ops & Net.POLLOUT) != 0) &&
             ((intOps & SelectionKey.OP_WRITE) != 0) &&
             isConnected())
             newOps |= SelectionKey.OP_WRITE;
@@ -637,11 +636,11 @@
     public void translateAndSetInterestOps(int ops, SelectionKeyImpl sk) {
         int newOps = 0;
         if ((ops & SelectionKey.OP_READ) != 0)
-            newOps |= PollArrayWrapper.POLLIN;
+            newOps |= Net.POLLIN;
         if ((ops & SelectionKey.OP_WRITE) != 0)
-            newOps |= PollArrayWrapper.POLLOUT;
+            newOps |= Net.POLLOUT;
         if ((ops & SelectionKey.OP_CONNECT) != 0)
-            newOps |= PollArrayWrapper.POLLCONN;
+            newOps |= Net.POLLCONN;
         sk.selector.putEventOps(sk, newOps);
     }
 
--- a/src/solaris/classes/sun/nio/ch/SctpMultiChannelImpl.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/solaris/classes/sun/nio/ch/SctpMultiChannelImpl.java	Thu Feb 06 01:43:16 2020 +0000
@@ -312,25 +312,24 @@
         int oldOps = sk.nioReadyOps();
         int newOps = initialOps;
 
-        if ((ops & PollArrayWrapper.POLLNVAL) != 0) {
+        if ((ops & Net.POLLNVAL) != 0) {
             /* This should only happen if this channel is pre-closed while a
              * selection operation is in progress
              * ## Throw an error if this channel has not been pre-closed */
             return false;
         }
 
-        if ((ops & (PollArrayWrapper.POLLERR
-                    | PollArrayWrapper.POLLHUP)) != 0) {
+        if ((ops & (Net.POLLERR | Net.POLLHUP)) != 0) {
             newOps = intOps;
             sk.nioReadyOps(newOps);
             return (newOps & ~oldOps) != 0;
         }
 
-        if (((ops & PollArrayWrapper.POLLIN) != 0) &&
+        if (((ops & Net.POLLIN) != 0) &&
             ((intOps & SelectionKey.OP_READ) != 0))
             newOps |= SelectionKey.OP_READ;
 
-        if (((ops & PollArrayWrapper.POLLOUT) != 0) &&
+        if (((ops & Net.POLLOUT) != 0) &&
             ((intOps & SelectionKey.OP_WRITE) != 0))
             newOps |= SelectionKey.OP_WRITE;
 
@@ -352,9 +351,9 @@
     public void translateAndSetInterestOps(int ops, SelectionKeyImpl sk) {
         int newOps = 0;
         if ((ops & SelectionKey.OP_READ) != 0)
-            newOps |= PollArrayWrapper.POLLIN;
+            newOps |= Net.POLLIN;
         if ((ops & SelectionKey.OP_WRITE) != 0)
-            newOps |= PollArrayWrapper.POLLOUT;
+            newOps |= Net.POLLOUT;
         sk.selector.putEventOps(sk, newOps);
     }
 
--- a/src/solaris/classes/sun/nio/ch/SctpServerChannelImpl.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/solaris/classes/sun/nio/ch/SctpServerChannelImpl.java	Thu Feb 06 01:43:16 2020 +0000
@@ -305,21 +305,20 @@
         int oldOps = sk.nioReadyOps();
         int newOps = initialOps;
 
-        if ((ops & PollArrayWrapper.POLLNVAL) != 0) {
+        if ((ops & Net.POLLNVAL) != 0) {
             /* This should only happen if this channel is pre-closed while a
              * selection operation is in progress
              * ## Throw an error if this channel has not been pre-closed */
             return false;
         }
 
-        if ((ops & (PollArrayWrapper.POLLERR
-                    | PollArrayWrapper.POLLHUP)) != 0) {
+        if ((ops & (Net.POLLERR | Net.POLLHUP)) != 0) {
             newOps = intOps;
             sk.nioReadyOps(newOps);
             return (newOps & ~oldOps) != 0;
         }
 
-        if (((ops & PollArrayWrapper.POLLIN) != 0) &&
+        if (((ops & Net.POLLIN) != 0) &&
             ((intOps & SelectionKey.OP_ACCEPT) != 0))
                 newOps |= SelectionKey.OP_ACCEPT;
 
@@ -343,7 +342,7 @@
 
         /* Translate ops */
         if ((ops & SelectionKey.OP_ACCEPT) != 0)
-            newOps |= PollArrayWrapper.POLLIN;
+            newOps |= Net.POLLIN;
         /* Place ops into pollfd array */
         sk.selector.putEventOps(sk, newOps);
 
--- a/src/solaris/classes/sun/nio/ch/SinkChannelImpl.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/solaris/classes/sun/nio/ch/SinkChannelImpl.java	Thu Feb 06 01:43:16 2020 +0000
@@ -118,17 +118,16 @@
         int oldOps = sk.nioReadyOps();
         int newOps = initialOps;
 
-        if ((ops & PollArrayWrapper.POLLNVAL) != 0)
+        if ((ops & Net.POLLNVAL) != 0)
             throw new Error("POLLNVAL detected");
 
-        if ((ops & (PollArrayWrapper.POLLERR
-                    | PollArrayWrapper.POLLHUP)) != 0) {
+        if ((ops & (Net.POLLERR | Net.POLLHUP)) != 0) {
             newOps = intOps;
             sk.nioReadyOps(newOps);
             return (newOps & ~oldOps) != 0;
         }
 
-        if (((ops & PollArrayWrapper.POLLOUT) != 0) &&
+        if (((ops & Net.POLLOUT) != 0) &&
             ((intOps & SelectionKey.OP_WRITE) != 0))
             newOps |= SelectionKey.OP_WRITE;
 
@@ -146,7 +145,7 @@
 
     public void translateAndSetInterestOps(int ops, SelectionKeyImpl sk) {
         if (ops == SelectionKey.OP_WRITE)
-            ops = PollArrayWrapper.POLLOUT;
+            ops = Net.POLLOUT;
         sk.selector.putEventOps(sk, ops);
     }
 
--- a/src/solaris/classes/sun/nio/ch/SourceChannelImpl.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/solaris/classes/sun/nio/ch/SourceChannelImpl.java	Thu Feb 06 01:43:16 2020 +0000
@@ -118,17 +118,16 @@
         int oldOps = sk.nioReadyOps();
         int newOps = initialOps;
 
-        if ((ops & PollArrayWrapper.POLLNVAL) != 0)
+        if ((ops & Net.POLLNVAL) != 0)
             throw new Error("POLLNVAL detected");
 
-        if ((ops & (PollArrayWrapper.POLLERR
-                    | PollArrayWrapper.POLLHUP)) != 0) {
+        if ((ops & (Net.POLLERR | Net.POLLHUP)) != 0) {
             newOps = intOps;
             sk.nioReadyOps(newOps);
             return (newOps & ~oldOps) != 0;
         }
 
-        if (((ops & PollArrayWrapper.POLLIN) != 0) &&
+        if (((ops & Net.POLLIN) != 0) &&
             ((intOps & SelectionKey.OP_READ) != 0))
             newOps |= SelectionKey.OP_READ;
 
@@ -146,7 +145,7 @@
 
     public void translateAndSetInterestOps(int ops, SelectionKeyImpl sk) {
         if (ops == SelectionKey.OP_READ)
-            ops = PollArrayWrapper.POLLIN;
+            ops = Net.POLLIN;
         sk.selector.putEventOps(sk, ops);
     }
 
--- a/src/solaris/classes/sun/nio/ch/UnixAsynchronousServerSocketChannelImpl.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/solaris/classes/sun/nio/ch/UnixAsynchronousServerSocketChannelImpl.java	Thu Feb 06 01:43:16 2020 +0000
@@ -148,7 +148,7 @@
                 synchronized (updateLock) {
                     acceptPending = true;
                 }
-                port.startPoll(fdVal, Port.POLLIN);
+                port.startPoll(fdVal, Net.POLLIN);
                 return;
             }
 
@@ -299,7 +299,7 @@
                 }
 
                 // register for connections
-                port.startPoll(fdVal, Port.POLLIN);
+                port.startPoll(fdVal, Net.POLLIN);
                 return result;
             }
         } catch (Throwable x) {
--- a/src/solaris/classes/sun/nio/ch/UnixAsynchronousSocketChannelImpl.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/solaris/classes/sun/nio/ch/UnixAsynchronousSocketChannelImpl.java	Thu Feb 06 01:43:16 2020 +0000
@@ -142,9 +142,9 @@
         assert Thread.holdsLock(updateLock);
         int events = 0;
         if (readPending)
-            events |= Port.POLLIN;
+            events |= Net.POLLIN;
         if (connectPending || writePending)
-            events |= Port.POLLOUT;
+            events |= Net.POLLOUT;
         if (events != 0)
             port.startPoll(fdVal, events);
     }
@@ -204,9 +204,9 @@
      */
     @Override
     public void onEvent(int events, boolean mayInvokeDirect) {
-        boolean readable = (events & Port.POLLIN) > 0;
-        boolean writable = (events & Port.POLLOUT) > 0;
-        if ((events & (Port.POLLERR | Port.POLLHUP)) > 0) {
+        boolean readable = (events & Net.POLLIN) > 0;
+        boolean writable = (events & Net.POLLOUT) > 0;
+        if ((events & (Net.POLLERR | Net.POLLHUP)) > 0) {
             readable = true;
             writable = true;
         }
--- a/src/solaris/classes/sun/nio/fs/BsdFileStore.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/solaris/classes/sun/nio/fs/BsdFileStore.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -62,22 +62,14 @@
         }
 
         // step 2: find mount point
-        UnixPath parent = path.getParent();
-        while (parent != null) {
-            UnixFileAttributes attrs = null;
-            try {
-                attrs = UnixFileAttributes.get(parent, true);
-            } catch (UnixException x) {
-                x.rethrowAsIOException(parent);
-            }
-            if (attrs.dev() != dev())
-                break;
-            path = parent;
-            parent = parent.getParent();
+        byte[] dir = null;
+        try {
+            dir = BsdNativeDispatcher.getmntonname(path);
+        } catch (UnixException x) {
+            x.rethrowAsIOException(path);
         }
 
         // step 3: lookup mounted file systems
-        byte[] dir = path.asByteArray();
         for (UnixMountEntry entry: fs.getMountEntries()) {
             if (Arrays.equals(dir, entry.dir()))
                 return entry;
--- a/src/solaris/classes/sun/nio/fs/BsdNativeDispatcher.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/solaris/classes/sun/nio/fs/BsdNativeDispatcher.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -51,6 +51,20 @@
     */
     static native void endfsstat(long iter) throws UnixException;
 
+    /**
+     * int statfs(const char *path, struct statfs *buf);
+     * returns buf->f_mntonname (directory on which mounted)
+     */
+    static byte[] getmntonname(UnixPath path) throws UnixException {
+        NativeBuffer pathBuffer = copyToNativeBuffer(path);
+        try {
+            return getmntonname0(pathBuffer.address());
+        } finally {
+            pathBuffer.release();
+        }
+    }
+    static native byte[] getmntonname0(long pathAddress) throws UnixException;
+
     // initialize field IDs
     private static native void initIDs();
 
--- a/src/solaris/classes/sun/nio/fs/UnixNativeDispatcher.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/solaris/classes/sun/nio/fs/UnixNativeDispatcher.java	Thu Feb 06 01:43:16 2020 +0000
@@ -36,7 +36,7 @@
     protected UnixNativeDispatcher() { }
 
     // returns a NativeBuffer containing the given path
-    private static NativeBuffer copyToNativeBuffer(UnixPath path) {
+    static NativeBuffer copyToNativeBuffer(UnixPath path) {
         byte[] cstr = path.getByteArrayForSysCalls();
         int size = cstr.length + 1;
         NativeBuffer buffer = NativeBuffers.getNativeBufferFromCache(size);
--- a/src/solaris/native/sun/java2d/x11/X11SurfaceData.c	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/solaris/native/sun/java2d/x11/X11SurfaceData.c	Thu Feb 06 01:43:16 2020 +0000
@@ -81,6 +81,7 @@
 static XImage * X11SD_GetImage(JNIEnv *env, X11SDOps *xsdo,
                                SurfaceDataBounds *bounds,
                                jint lockFlags);
+static int X11SD_GetBitmapPad(int pixelStride);
 
 extern jfieldID validID;
 
@@ -456,11 +457,33 @@
         xsdo->drawable = drawable;
         xsdo->isPixmap = JNI_FALSE;
     } else {
+        jboolean sizeIsInvalid = JNI_FALSE;
+        jlong scan = 0;
+
         /*
          * width , height must be nonzero otherwise XCreatePixmap
          * generates BadValue in error_handler
          */
         if (width <= 0 || height <= 0 || width > 32767 || height > 32767) {
+            sizeIsInvalid = JNI_TRUE;
+        } else {
+            XImage* tmpImg = NULL;
+
+            AWT_LOCK();
+            tmpImg = XCreateImage(awt_display,
+                xsdo->configData->awt_visInfo.visual,
+                depth, ZPixmap, 0, NULL, width, height,
+                X11SD_GetBitmapPad(xsdo->configData->pixelStride), 0);
+            if (tmpImg) {
+                scan = (jlong) tmpImg->bytes_per_line;
+                XDestroyImage(tmpImg);
+                tmpImg = NULL;
+            }
+            AWT_UNLOCK();
+            JNU_CHECK_EXCEPTION_RETURN(env, JNI_FALSE);
+        }
+
+        if (sizeIsInvalid || (scan * height > 0x7FFFFFFFL)) {
             JNU_ThrowOutOfMemoryError(env,
                                   "Can't create offscreen surface");
             return JNI_FALSE;
@@ -475,7 +498,7 @@
         xsdo->pmHeight = height;
 
 #ifdef MITSHM
-        xsdo->shmPMData.pmSize = width * height * depth;
+        xsdo->shmPMData.pmSize = (jlong) width * height * depth;
         xsdo->shmPMData.pixelsReadThreshold = width * height / 8;
         if (forceSharedPixmaps) {
             AWT_LOCK();
@@ -575,7 +598,7 @@
         return NULL;
     }
     shminfo->shmid =
-        shmget(IPC_PRIVATE, height * img->bytes_per_line,
+        shmget(IPC_PRIVATE, (size_t) height * img->bytes_per_line,
                IPC_CREAT|mitShmPermissionMask);
     if (shminfo->shmid < 0) {
         J2dRlsTraceLn1(J2D_TRACE_ERROR,
@@ -637,7 +660,7 @@
         XSync(awt_display, False);
         retImage = cachedXImage;
         cachedXImage = (XImage *)NULL;
-    } else if (width * height * xsdo->depth > 0x10000) {
+    } else if ((jlong) width * height * xsdo->depth > 0x10000) {
         retImage = X11SD_CreateSharedImage(xsdo, width, height);
     }
     return retImage;
@@ -994,7 +1017,7 @@
             int scan = xpriv->img->bytes_per_line;
             xpriv->x = x;
             xpriv->y = y;
-            pRasInfo->rasBase = xpriv->img->data - x * mult - y * scan;
+            pRasInfo->rasBase = xpriv->img->data - x * mult - (intptr_t) y * scan;
             pRasInfo->pixelStride = mult;
             pRasInfo->pixelBitOffset = 0;
             pRasInfo->scanStride = scan;
@@ -1264,8 +1287,8 @@
 
 static void
 X11SD_SwapBytes(X11SDOps *xsdo, XImage * img, int depth, int bpp) {
-    int lengthInBytes = img->height * img->bytes_per_line;
-    int i;
+    jlong lengthInBytes = (jlong) img->height * img->bytes_per_line;
+    jlong i;
 
     switch (depth) {
     case 12:
@@ -1338,7 +1361,7 @@
     Drawable drawable;
     int depth = xsdo->depth;
     int mult = xsdo->configData->pixelStride;
-    int pad = (mult == 3) ? 32 : mult * 8; // pad must be 8, 16, or 32
+    int pad = X11SD_GetBitmapPad(mult);
     jboolean readBits = lockFlags & SD_LOCK_NEED_PIXELS;
 
     x = bounds->x1;
@@ -1404,7 +1427,7 @@
             }
 
             scan = img->bytes_per_line;
-            img->data = malloc(h * scan);
+            img->data = malloc((size_t) h * scan);
             if (img->data == NULL) {
                 XFree(img);
                 return NULL;
@@ -1439,7 +1462,7 @@
                     int i;
 
                     img_addr = img->data +
-                        (temp.y1 - y) * scan + (temp.x1 - x) * mult;
+                        (intptr_t) (temp.y1 - y) * scan + (temp.x1 - x) * mult;
                     temp_scan = temp_image->bytes_per_line;
                     temp_addr = temp_image->data;
                     bytes_to_copy = (temp.x2 - temp.x1) * mult;
@@ -1473,7 +1496,7 @@
                 return NULL;
             }
 
-            img->data = malloc(h * img->bytes_per_line);
+            img->data = malloc((size_t) h * img->bytes_per_line);
             if (img->data == NULL) {
                 XFree(img);
                 return NULL;
@@ -1656,6 +1679,11 @@
 #endif /* MITSHM */
 }
 
+static int X11SD_GetBitmapPad(int pixelStride) {
+    // pad must be 8, 16, or 32
+    return (pixelStride == 3) ? 32 : pixelStride * 8;
+}
+
 #endif /* !HEADLESS */
 
 /*
--- a/src/solaris/native/sun/java2d/x11/X11SurfaceData.h	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/solaris/native/sun/java2d/x11/X11SurfaceData.h	Thu Feb 06 01:43:16 2020 +0000
@@ -77,7 +77,7 @@
     XShmSegmentInfo     *shmSegInfo;    /* Shared Memory Segment Info */
     jint                bytesPerLine;   /* needed for ShMem lock */
     jboolean            xRequestSent;   /* true if x request is sent w/o XSync */
-    jint                pmSize;
+    jlong               pmSize;
 
     jboolean            usingShmPixmap;
     Drawable            pixmap;
--- a/src/solaris/native/sun/nio/ch/IOUtil.c	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/solaris/native/sun/nio/ch/IOUtil.c	Thu Feb 06 01:43:16 2020 +0000
@@ -170,7 +170,6 @@
     return (jint)iov_max;
 }
 
-
 /* Declared in nio_util.h for use elsewhere in NIO */
 
 jlong
--- a/src/solaris/native/sun/nio/ch/Net.c	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/solaris/native/sun/nio/ch/Net.c	Thu Feb 06 01:43:16 2020 +0000
@@ -23,6 +23,7 @@
  * questions.
  */
 
+#include <sys/poll.h>
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <string.h>
@@ -38,6 +39,7 @@
 #include "net_util_md.h"
 #include "nio_util.h"
 #include "nio.h"
+#include "sun_nio_ch_PollArrayWrapper.h"
 
 #ifdef AIX
 #include <sys/utsname.h>
@@ -747,6 +749,62 @@
         handleSocketError(env, errno);
 }
 
+JNIEXPORT jint JNICALL
+Java_sun_nio_ch_Net_poll(JNIEnv* env, jclass this, jobject fdo, jint events, jlong timeout)
+{
+    struct pollfd pfd;
+    int rv;
+    pfd.fd = fdval(env, fdo);
+    pfd.events = events;
+    rv = poll(&pfd, 1, timeout);
+
+    if (rv >= 0) {
+        return pfd.revents;
+    } else if (errno == EINTR) {
+        return IOS_INTERRUPTED;
+    } else if (rv < 0) {
+        handleSocketError(env, errno);
+        return IOS_THROWN;
+    }
+}
+
+JNIEXPORT jshort JNICALL
+Java_sun_nio_ch_Net_pollinValue(JNIEnv *env, jclass this)
+{
+    return (jshort)POLLIN;
+}
+
+JNIEXPORT jshort JNICALL
+Java_sun_nio_ch_Net_polloutValue(JNIEnv *env, jclass this)
+{
+    return (jshort)POLLOUT;
+}
+
+JNIEXPORT jshort JNICALL
+Java_sun_nio_ch_Net_pollerrValue(JNIEnv *env, jclass this)
+{
+    return (jshort)POLLERR;
+}
+
+JNIEXPORT jshort JNICALL
+Java_sun_nio_ch_Net_pollhupValue(JNIEnv *env, jclass this)
+{
+    return (jshort)POLLHUP;
+}
+
+JNIEXPORT jshort JNICALL
+Java_sun_nio_ch_Net_pollnvalValue(JNIEnv *env, jclass this)
+{
+    return (jshort)POLLNVAL;
+}
+
+JNIEXPORT jshort JNICALL
+Java_sun_nio_ch_Net_pollconnValue(JNIEnv *env, jclass this)
+{
+    return (jshort)POLLOUT;
+}
+
+
 /* Declared in nio_util.h */
 
 jint
--- a/src/solaris/native/sun/nio/fs/BsdNativeDispatcher.c	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/solaris/native/sun/nio/fs/BsdNativeDispatcher.c	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -202,3 +202,24 @@
     }
 }
 
+JNIEXPORT jbyteArray JNICALL
+Java_sun_nio_fs_BsdNativeDispatcher_getmntonname0(JNIEnv *env, jclass this,
+    jlong pathAddress)
+{
+    struct statfs buf;
+    const char* path = (const char*)jlong_to_ptr(pathAddress);
+
+    if (statfs(path, &buf) != 0) {
+        throwUnixException(env, errno);
+    }
+
+    jsize len = strlen(buf.f_mntonname);
+    jbyteArray mntonname = (*env)->NewByteArray(env, len);
+    if (mntonname != NULL) {
+        (*env)->SetByteArrayRegion(env, mntonname, 0, len,
+            (jbyte*)buf.f_mntonname);
+    }
+
+    return mntonname;
+}
+
--- a/src/windows/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/windows/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -194,7 +194,17 @@
         }
     }
 
-    static native boolean isTrustedSite(String url);
+    private static final boolean isTrustedSiteAvailable = isTrustedSiteAvailable();
+
+    private static native boolean isTrustedSiteAvailable();
+
+    private static boolean isTrustedSite(String url) {
+        if (isTrustedSiteAvailable)
+            return isTrustedSite0(url);
+        return false;
+    }
+
+    private static native boolean isTrustedSite0(String url);
 
     /**
      * Not supported. Must use the setHeaders() method
--- a/src/windows/classes/sun/nio/ch/PollArrayWrapper.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/windows/classes/sun/nio/ch/PollArrayWrapper.java	Thu Feb 06 01:43:16 2020 +0000
@@ -51,15 +51,6 @@
 
     static short SIZE_POLLFD = 8; // sizeof pollfd struct
 
-    // events masks
-    static final short POLLIN     = AbstractPollArrayWrapper.POLLIN;
-    static final short POLLOUT    = AbstractPollArrayWrapper.POLLOUT;
-    static final short POLLERR    = AbstractPollArrayWrapper.POLLERR;
-    static final short POLLHUP    = AbstractPollArrayWrapper.POLLHUP;
-    static final short POLLNVAL   = AbstractPollArrayWrapper.POLLNVAL;
-    static final short POLLREMOVE = AbstractPollArrayWrapper.POLLREMOVE;
-    static final short POLLCONN   = 0x0002;
-
     private int size; // Size of the pollArray
 
     PollArrayWrapper(int newSize) {
@@ -117,6 +108,6 @@
     // Adds Windows wakeup socket at a given index.
     void addWakeupSocket(int fdVal, int index) {
         putDescriptor(index, fdVal);
-        putEventOps(index, POLLIN);
+        putEventOps(index, Net.POLLIN);
     }
 }
--- a/src/windows/classes/sun/nio/ch/SinkChannelImpl.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/windows/classes/sun/nio/ch/SinkChannelImpl.java	Thu Feb 06 01:43:16 2020 +0000
@@ -78,17 +78,16 @@
         int oldOps = sk.nioReadyOps();
         int newOps = initialOps;
 
-        if ((ops & PollArrayWrapper.POLLNVAL) != 0)
+        if ((ops & Net.POLLNVAL) != 0)
             throw new Error("POLLNVAL detected");
 
-        if ((ops & (PollArrayWrapper.POLLERR
-                    | PollArrayWrapper.POLLHUP)) != 0) {
+        if ((ops & (Net.POLLERR | Net.POLLHUP)) != 0) {
             newOps = intOps;
             sk.nioReadyOps(newOps);
             return (newOps & ~oldOps) != 0;
         }
 
-        if (((ops & PollArrayWrapper.POLLOUT) != 0) &&
+        if (((ops & Net.POLLOUT) != 0) &&
             ((intOps & SelectionKey.OP_WRITE) != 0))
             newOps |= SelectionKey.OP_WRITE;
 
@@ -106,7 +105,7 @@
 
     public void translateAndSetInterestOps(int ops, SelectionKeyImpl sk) {
         if ((ops & SelectionKey.OP_WRITE) != 0)
-            ops = PollArrayWrapper.POLLOUT;
+            ops = Net.POLLOUT;
         sk.selector.putEventOps(sk, ops);
     }
 
--- a/src/windows/classes/sun/nio/ch/SourceChannelImpl.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/windows/classes/sun/nio/ch/SourceChannelImpl.java	Thu Feb 06 01:43:16 2020 +0000
@@ -77,17 +77,16 @@
         int oldOps = sk.nioReadyOps();
         int newOps = initialOps;
 
-        if ((ops & PollArrayWrapper.POLLNVAL) != 0)
+        if ((ops & Net.POLLNVAL) != 0)
             throw new Error("POLLNVAL detected");
 
-        if ((ops & (PollArrayWrapper.POLLERR
-                    | PollArrayWrapper.POLLHUP)) != 0) {
+        if ((ops & (Net.POLLERR | Net.POLLHUP)) != 0) {
             newOps = intOps;
             sk.nioReadyOps(newOps);
             return (newOps & ~oldOps) != 0;
         }
 
-        if (((ops & PollArrayWrapper.POLLIN) != 0) &&
+        if (((ops & Net.POLLIN) != 0) &&
             ((intOps & SelectionKey.OP_READ) != 0))
             newOps |= SelectionKey.OP_READ;
 
@@ -105,7 +104,7 @@
 
     public void translateAndSetInterestOps(int ops, SelectionKeyImpl sk) {
         if ((ops & SelectionKey.OP_READ) != 0)
-            ops = PollArrayWrapper.POLLIN;
+            ops = Net.POLLIN;
         sk.selector.putEventOps(sk, ops);
     }
 
--- a/src/windows/classes/sun/nio/ch/WindowsSelectorImpl.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/windows/classes/sun/nio/ch/WindowsSelectorImpl.java	Thu Feb 06 01:43:16 2020 +0000
@@ -313,16 +313,16 @@
         private int processSelectedKeys(long updateCount) {
             int numKeysUpdated = 0;
             numKeysUpdated += processFDSet(updateCount, readFds,
-                                           PollArrayWrapper.POLLIN,
+                                           Net.POLLIN,
                                            false);
             numKeysUpdated += processFDSet(updateCount, writeFds,
-                                           PollArrayWrapper.POLLCONN |
-                                           PollArrayWrapper.POLLOUT,
+                                           Net.POLLCONN |
+                                           Net.POLLOUT,
                                            false);
             numKeysUpdated += processFDSet(updateCount, exceptFds,
-                                           PollArrayWrapper.POLLIN |
-                                           PollArrayWrapper.POLLCONN |
-                                           PollArrayWrapper.POLLOUT,
+                                           Net.POLLIN |
+                                           Net.POLLCONN |
+                                           Net.POLLOUT,
                                            true);
             return numKeysUpdated;
         }
--- a/src/windows/classes/sun/security/krb5/internal/tools/Kinit.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/windows/classes/sun/security/krb5/internal/tools/Kinit.java	Thu Feb 06 01:43:16 2020 +0000
@@ -36,7 +36,6 @@
 import sun.security.krb5.internal.ccache.*;
 import java.io.IOException;
 import java.util.Arrays;
-import javax.security.auth.kerberos.KerberosPrincipal;
 import sun.security.util.Password;
 import javax.security.auth.kerberos.KeyTab;
 
@@ -53,22 +52,9 @@
 
     /**
      * The main method is used to accept user command line input for ticket
-     * request.
-     * <p>
-     * Usage: kinit [-A] [-f] [-p] [-c cachename] [[-k [-t keytab_file_name]]
-     * [principal] [password]
-     * <ul>
-     * <li>    -A        do not include addresses
-     * <li>    -f        forwardable
-     * <li>    -p        proxiable
-     * <li>    -c        cache name (i.e., FILE://c:\temp\mykrb5cc)
-     * <li>    -k        use keytab
-     * <li>    -t        keytab file name
-     * <li>    principal the principal name (i.e., duke@java.sun.com)
-     * <li>    password  the principal's Kerberos password
-     * </ul>
-     * <p>
-     * Use java sun.security.krb5.tools.Kinit -help to bring up help menu.
+     * request. Read {@link KinitOptions#printHelp} for usages or call
+     *    java sun.security.krb5.internal.tools.Kinit -help
+     * to bring up help menu.
      * <p>
      * We currently support only file-based credentials cache to
      * store the tickets obtained from the KDC.
@@ -146,6 +132,49 @@
         } else {
             options = new KinitOptions(args);
         }
+        switch (options.action) {
+            case 1:
+                acquire();
+                break;
+            case 2:
+                renew();
+                break;
+            default:
+                throw new KrbException("kinit does not support action "
+                        + options.action);
+        }
+    }
+
+    private void renew()
+            throws IOException, RealmException, KrbException {
+
+        PrincipalName principal = options.getPrincipal();
+        String realm = principal.getRealmAsString();
+        CredentialsCache cache = CredentialsCache.getInstance(options.cachename);
+
+        if (cache == null) {
+            throw new IOException("Unable to find existing cache file " +
+                    options.cachename);
+        }
+        sun.security.krb5.internal.ccache.Credentials credentials =
+                cache.getCreds(PrincipalName.tgsService(realm, realm));
+
+        credentials = credentials.setKrbCreds()
+                .renew()
+                .toCCacheCreds();
+
+        cache = CredentialsCache.create(principal, options.cachename);
+        if (cache == null) {
+            throw new IOException("Unable to create the cache file " +
+                    options.cachename);
+        }
+        cache.update(credentials);
+        cache.save();
+    }
+
+    private void acquire()
+            throws IOException, RealmException, KrbException {
+
         String princName = null;
         PrincipalName principal = options.getPrincipal();
         if (principal != null) {
@@ -216,6 +245,9 @@
         if (options.getAddressOption())
             builder.setAddresses(HostAddresses.getLocalAddresses());
 
+        builder.setTill(options.lifetime);
+        builder.setRTime(options.renewable_lifetime);
+
         builder.action();
 
         sun.security.krb5.internal.ccache.Credentials credentials =
--- a/src/windows/classes/sun/security/krb5/internal/tools/KinitOptions.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/windows/classes/sun/security/krb5/internal/tools/KinitOptions.java	Thu Feb 06 01:43:16 2020 +0000
@@ -33,12 +33,8 @@
 import sun.security.krb5.*;
 import sun.security.krb5.internal.*;
 import sun.security.krb5.internal.ccache.*;
-import java.io.File;
 import java.io.IOException;
-import java.util.StringTokenizer;
-import java.util.Vector;
-import java.io.BufferedReader;
-import java.io.InputStreamReader;
+import java.time.Instant;
 import java.io.FileInputStream;
 
 /**
@@ -49,14 +45,15 @@
  * @author Ram Marti
  */
 class KinitOptions {
-    public boolean validate = false;
+
+    // 1. acquire, 2. renew, 3. validate
+    public int action = 1;
 
     // forwardable and proxiable flags have two states:
     // -1 - flag set to be not forwardable or proxiable;
     // 1 - flag set to be forwardable or proxiable.
-    public short forwardable = -1;
-    public short proxiable = -1;
-    public boolean renew = false;
+    public short forwardable = 0;
+    public short proxiable = 0;
     public KerberosTime lifetime;
     public KerberosTime renewable_lifetime;
     public String target_service;
@@ -134,6 +131,12 @@
                 }
 
                 useKeytab = true;
+            } else if (args[i].equals("-R")) {
+                action = 2;
+            } else if (args[i].equals("-l")) {
+                lifetime = getTime(Config.duration(args[++i]));
+            } else if (args[i].equals("-r")) {
+                renewable_lifetime = getTime(Config.duration(args[++i]));
             } else if (args[i].equalsIgnoreCase("-help")) {
                 printHelp();
                 System.exit(0);
@@ -223,23 +226,28 @@
 
 
     void printHelp() {
-        System.out.println("Usage: kinit " +
-                           "[-A] [-f] [-p] [-c cachename] " +
-                           "[[-k [-t keytab_file_name]] [principal] " +
+        System.out.println("Usage:\n\n1. Initial ticket request:\n" +
+                "    kinit [-A] [-f] [-p] [-c cachename] " +
+                "[-l lifetime] [-r renewable_time]\n" +
+                "          [[-k [-t keytab_file_name]] [principal] " +
                            "[password]");
-        System.out.println("\tavailable options to " +
+        System.out.println("2. Renew a ticket:\n" +
+                "    kinit -R [-c cachename] [principal]");
+        System.out.println("\nAvailable options to " +
                            "Kerberos 5 ticket request:");
-        System.out.println("\t    -A   do not include addresses");
-        System.out.println("\t    -f   forwardable");
-        System.out.println("\t    -p   proxiable");
-        System.out.println("\t    -c   cache name " +
-                           "(i.e., FILE:\\d:\\myProfiles\\mykrb5cache)");
-        System.out.println("\t    -k   use keytab");
-        System.out.println("\t    -t   keytab file name");
-        System.out.println("\t    principal   the principal name "+
-                           "(i.e., qweadf@ATHENA.MIT.EDU qweadf)");
-        System.out.println("\t    password   " +
-                           "the principal's Kerberos password");
+        System.out.println("\t-A   do not include addresses");
+        System.out.println("\t-f   forwardable");
+        System.out.println("\t-p   proxiable");
+        System.out.println("\t-c   cache name " +
+                "(i.e., FILE:\\d:\\myProfiles\\mykrb5cache)");
+        System.out.println("\t-l   lifetime");
+        System.out.println("\t-r   renewable time " +
+                "(total lifetime a ticket can be renewed)");
+        System.out.println("\t-k   use keytab");
+        System.out.println("\t-t   keytab file name");
+        System.out.println("\tprincipal   the principal name "+
+                "(i.e., qweadf@ATHENA.MIT.EDU qweadf)");
+        System.out.println("\tpassword    the principal's Kerberos password");
     }
 
     public boolean getAddressOption() {
@@ -257,4 +265,8 @@
     public PrincipalName getPrincipal() {
         return principal;
     }
+
+    private KerberosTime getTime(int s) {
+        return new KerberosTime(Instant.now().plusSeconds(s));
+    }
 }
--- a/src/windows/classes/sun/security/krb5/internal/tools/Klist.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/windows/classes/sun/security/krb5/internal/tools/Klist.java	Thu Feb 06 01:43:16 2020 +0000
@@ -207,7 +207,7 @@
                 }
                 if (options[2] == 't') {
                     System.out.println("\t Time stamp: " +
-                            reformat(entries[i].getTimeStamp().toDate().toString()));
+                            format(entries[i].getTimeStamp()));
                 }
             }
         }
@@ -234,30 +234,39 @@
             System.out.println("\nDefault principal: " +
                                defaultPrincipal + ", " +
                                creds.length + " entries found.\n");
-        String starttime = null;
-        String endtime = null;
-        String servicePrincipal = null;
-        String etype = null;
         if (creds != null) {
             for (int i = 0; i < creds.length; i++) {
                 try {
-                    starttime =
-                        reformat(creds[i].getAuthTime().toDate().toString());
-                    endtime =
-                        reformat(creds[i].getEndTime().toDate().toString());
+                    String starttime;
+                    String endtime;
+                    String renewTill;
+                    String servicePrincipal;
+                    if (creds[i].getStartTime() != null) {
+                        starttime = format(creds[i].getStartTime());
+                    } else {
+                        starttime = format(creds[i].getAuthTime());
+                    }
+                    endtime = format(creds[i].getEndTime());
                     servicePrincipal =
                         creds[i].getServicePrincipal().toString();
                     System.out.println("[" + (i + 1) + "] " +
                                        " Service Principal:  " +
                                        servicePrincipal);
-                    System.out.println("     Valid starting:  " + starttime);
-                    System.out.println("     Expires:         " + endtime);
+                    System.out.println("     Valid starting:     " + starttime);
+                    System.out.println("     Expires:            " + endtime);
+                    if (creds[i].getRenewTill() != null) {
+                        renewTill = format(creds[i].getRenewTill());
+                        System.out.println(
+                                "     Renew until:        " + renewTill);
+                    }
                     if (options[0] == 'e') {
-                        etype = EType.toString(creds[i].getEType());
-                        System.out.println("     Encryption type: " + etype);
+                        String eskey = EType.toString(creds[i].getEType());
+                        String etkt = EType.toString(creds[i].getTktEType());
+                        System.out.println("     EType (skey, tkt):  "
+                                + eskey + ", " + etkt);
                     }
                     if (options[1] == 'f') {
-                        System.out.println("     Flags:           " +
+                        System.out.println("     Flags:              " +
                                            creds[i].getTicketFlags().toString());
                     }
                     if (options[2] == 'a') {
@@ -312,13 +321,14 @@
      * and yyyy is the year.
      * @param date the string form of Date object.
      */
-    String reformat(String date) {
+    private String format(KerberosTime kt) {
+        String date = kt.toDate().toString();
         return (date.substring(4, 7) + " " + date.substring(8, 10) +
                 ", " + date.substring(24)
-                + " " + date.substring(11, 16));
+                + " " + date.substring(11, 19));
     }
     /**
-     * Printes out the help information.
+     * Prints out the help information.
      */
     void printHelp() {
         System.out.println("\nUsage: klist " +
--- a/src/windows/native/sun/net/www/protocol/http/ntlm/NTLMAuthentication.c	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/windows/native/sun/net/www/protocol/http/ntlm/NTLMAuthentication.c	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,11 +26,34 @@
 #include <jni.h>
 #include <windows.h>
 #include "jni_util.h"
+#include "jdk_util.h"
 #include <urlmon.h>
 
-JNIEXPORT jboolean JNICALL Java_sun_net_www_protocol_http_ntlm_NTLMAuthentication_isTrustedSite(JNIEnv *env, jclass clazz, jstring url )
+typedef HRESULT (WINAPI *CoInternetCreateSecurityManagerType)
+        (IServiceProvider*,IInternetSecurityManager**,DWORD);
+
+static CoInternetCreateSecurityManagerType fn_CoInternetCreateSecurityManager;
+
+JNIEXPORT jboolean JNICALL
+Java_sun_net_www_protocol_http_ntlm_NTLMAuthentication_isTrustedSiteAvailable
+  (JNIEnv *env, jclass clazz)
 {
+    HMODULE libUrlmon = JDK_LoadSystemLibrary("urlmon.dll");
+    if (libUrlmon != NULL) {
+        fn_CoInternetCreateSecurityManager = (CoInternetCreateSecurityManagerType)
+                GetProcAddress(libUrlmon, "CoInternetCreateSecurityManager");
+        if (fn_CoInternetCreateSecurityManager != NULL) {
+            return JNI_TRUE;
+        }
+    }
+    return JNI_FALSE;
+}
 
+
+JNIEXPORT jboolean JNICALL
+Java_sun_net_www_protocol_http_ntlm_NTLMAuthentication_isTrustedSite0
+  (JNIEnv *env, jclass clazz, jstring url)
+{
     HRESULT hr;
     DWORD dwZone;
     DWORD  pPolicy = 0;
@@ -38,8 +61,11 @@
     jboolean ret;
     LPCWSTR bstrURL;
 
+    if (fn_CoInternetCreateSecurityManager == NULL)
+        return JNI_FALSE;
+
     // Create IInternetSecurityManager
-    hr = CoInternetCreateSecurityManager(NULL, &spSecurityManager, (DWORD)0);
+    hr = fn_CoInternetCreateSecurityManager(NULL, &spSecurityManager, (DWORD)0);
     if (FAILED(hr)) {
         return JNI_FALSE;
     }
--- a/src/windows/native/sun/nio/ch/Net.c	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/windows/native/sun/nio/ch/Net.c	Thu Feb 06 01:43:16 2020 +0000
@@ -35,6 +35,7 @@
 #include "net_util.h"
 
 #include "sun_nio_ch_Net.h"
+#include "sun_nio_ch_PollArrayWrapper.h"
 
 /**
  * Definitions to allow for building with older SDK include files.
@@ -555,3 +556,85 @@
         NET_ThrowNew(env, WSAGetLastError(), "shutdown");
     }
 }
+
+JNIEXPORT jint JNICALL
+Java_sun_nio_ch_Net_poll(JNIEnv* env, jclass this, jobject fdo, jint events, jlong timeout)
+{
+    int rv;
+    int revents = 0;
+    struct timeval t;
+    int lastError = 0;
+    fd_set rd, wr, ex;
+    jint fd = fdval(env, fdo);
+
+    t.tv_sec = timeout / 1000;
+    t.tv_usec = (timeout % 1000) * 1000;
+
+    FD_ZERO(&rd);
+    FD_ZERO(&wr);
+    FD_ZERO(&ex);
+    if (events & POLLIN) {
+        FD_SET(fd, &rd);
+    }
+    if (events & POLLOUT ||
+        events & POLLCONN) {
+        FD_SET(fd, &wr);
+    }
+    FD_SET(fd, &ex);
+
+    rv = select(fd+1, &rd, &wr, &ex, &t);
+
+    /* save last winsock error */
+    if (rv == SOCKET_ERROR) {
+        handleSocketError(env, lastError);
+        return IOS_THROWN;
+    } else if (rv >= 0) {
+        rv = 0;
+        if (FD_ISSET(fd, &rd)) {
+            rv |= POLLIN;
+        }
+        if (FD_ISSET(fd, &wr)) {
+            rv |= POLLOUT;
+        }
+        if (FD_ISSET(fd, &ex)) {
+            rv |= POLLERR;
+        }
+    }
+    return rv;
+}
+
+JNIEXPORT jshort JNICALL
+Java_sun_nio_ch_Net_pollinValue(JNIEnv *env, jclass this)
+{
+    return (jshort)POLLIN;
+}
+
+JNIEXPORT jshort JNICALL
+Java_sun_nio_ch_Net_polloutValue(JNIEnv *env, jclass this)
+{
+    return (jshort)POLLOUT;
+}
+
+JNIEXPORT jshort JNICALL
+Java_sun_nio_ch_Net_pollerrValue(JNIEnv *env, jclass this)
+{
+    return (jshort)POLLERR;
+}
+
+JNIEXPORT jshort JNICALL
+Java_sun_nio_ch_Net_pollhupValue(JNIEnv *env, jclass this)
+{
+    return (jshort)POLLHUP;
+}
+
+JNIEXPORT jshort JNICALL
+Java_sun_nio_ch_Net_pollnvalValue(JNIEnv *env, jclass this)
+{
+    return (jshort)POLLNVAL;
+}
+
+JNIEXPORT jshort JNICALL
+Java_sun_nio_ch_Net_pollconnValue(JNIEnv *env, jclass this)
+{
+    return (jshort)POLLCONN;
+}
--- a/src/windows/native/sun/nio/ch/WindowsSelectorImpl.c	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/windows/native/sun/nio/ch/WindowsSelectorImpl.c	Thu Feb 06 01:43:16 2020 +0000
@@ -33,13 +33,15 @@
 #define FD_SETSIZE 1024
 
 #include <stdlib.h>
+#include <winsock2.h>
+
 #include "jvm.h"
 #include "jni.h"
 #include "jni_util.h"
 #include "sun_nio_ch_WindowsSelectorImpl.h"
 #include "sun_nio_ch_PollArrayWrapper.h"
-#include "winsock2.h"
 
+#include "nio_util.h" /* Needed for POLL* constants (includes "winsock2.h") */
 
 typedef struct {
     jint fd;
@@ -79,12 +81,11 @@
 
     /* Set FD_SET structures required for select */
     for (i = 0; i < numfds; i++) {
-        if (fds[i].events & sun_nio_ch_PollArrayWrapper_POLLIN) {
+        if (fds[i].events & POLLIN) {
            readfds.fd_array[read_count] = fds[i].fd;
            read_count++;
         }
-        if (fds[i].events & (sun_nio_ch_PollArrayWrapper_POLLOUT |
-                             sun_nio_ch_PollArrayWrapper_POLLCONN))
+        if (fds[i].events & (POLLOUT | POLLCONN))
         {
            writefds.fd_array[write_count] = fds[i].fd;
            write_count++;
@@ -110,12 +111,11 @@
             /* prepare select structures for the i-th socket */
             errreadfds.fd_count = 0;
             errwritefds.fd_count = 0;
-            if (fds[i].events & sun_nio_ch_PollArrayWrapper_POLLIN) {
+            if (fds[i].events & POLLIN) {
                errreadfds.fd_array[0] = fds[i].fd;
                errreadfds.fd_count = 1;
             }
-            if (fds[i].events & (sun_nio_ch_PollArrayWrapper_POLLOUT |
-                                 sun_nio_ch_PollArrayWrapper_POLLCONN))
+            if (fds[i].events & (POLLOUT | POLLCONN))
             {
                 errwritefds.fd_array[0] = fds[i].fd;
                 errwritefds.fd_count = 1;
--- a/src/windows/native/sun/nio/ch/nio_util.h	Wed Nov 20 06:36:47 2019 +0000
+++ b/src/windows/native/sun/nio/ch/nio_util.h	Thu Feb 06 01:43:16 2020 +0000
@@ -23,6 +23,8 @@
  * questions.
  */
 
+#include <winsock2.h>
+
 #include "jni.h"
 
 /**
@@ -55,3 +57,19 @@
 };
 
 #endif
+
+#ifndef POLLIN
+    /* WSAPoll()/WSAPOLLFD and the corresponding constants are only defined   */
+    /* in Windows Vista / Windows Server 2008 and later. If we are on an      */
+    /* older release we just use the Solaris constants as this was previously */
+    /* done in PollArrayWrapper.java.                                         */
+    #define POLLIN       0x0001
+    #define POLLOUT      0x0004
+    #define POLLERR      0x0008
+    #define POLLHUP      0x0010
+    #define POLLNVAL     0x0020
+    #define POLLCONN     0x0002
+#else
+    /* POLLCONN must not equal any of the other constants (see winsock2.h).   */
+    #define POLLCONN     0x2000
+#endif
--- a/test/ProblemList.txt	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/ProblemList.txt	Thu Feb 06 01:43:16 2020 +0000
@@ -114,6 +114,9 @@
 
 # jdk_awt
 
+# 8221305
+java/awt/FontMetrics/MaxAdvanceIsMax.java             solaris-all,macosx-all
+
 ############################################################################
 
 # jdk_beans
@@ -233,6 +236,9 @@
 # 8026393
 sun/security/tools/jarsigner/warnings/BadKeyUsageTest.java      generic-all
 
+# 8158827
+sun/security/krb5/auto/tools/KinitConfPlusProps.java                       windows-all
+
 ############################################################################
 
 # jdk_other
--- a/test/com/sun/crypto/provider/Cipher/DES/PerformanceTest.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/com/sun/crypto/provider/Cipher/DES/PerformanceTest.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,12 +24,9 @@
 /*
  * @test
  * @bug 0000000
- * @ignore run main/timeout=900 PerformanceTest
- * @summary PerformanceTest
+ * @summary This test checks performance of various ciphers.
  * @author Jan Luehe
- *
- * ignore since this test exists for performance
- * purpose and can be run separately if needed.
+ * @run main/manual PerformanceTest
  */
 import java.security.*;
 import java.security.spec.*;
--- a/test/com/sun/security/auth/callback/TextCallbackHandler/Default.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/com/sun/security/auth/callback/TextCallbackHandler/Default.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,8 +25,7 @@
  * @test
  * @bug 4470717
  * @summary fix default handling and other misc
- *
- * @ignore run these by hand
+ * @run main/manual Default
  */
 
 import com.sun.security.auth.callback.TextCallbackHandler;
--- a/test/com/sun/security/auth/callback/TextCallbackHandler/Password.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/com/sun/security/auth/callback/TextCallbackHandler/Password.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,7 +25,7 @@
  * @test
  * @bug 6825240
  * @summary Password.readPassword() echos the input when System.Console is null
- * @ignore run these by hand
+ * @run main/manual Password
  */
 
 import com.sun.security.auth.callback.TextCallbackHandler;
--- a/test/com/sun/security/sasl/gsskerb/AuthOnly.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/com/sun/security/sasl/gsskerb/AuthOnly.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,11 +25,14 @@
  * @test
  * @bug 4634892
  * @summary Ensure authentication via GSS-API/Kerberos v5 works.
- * @ignore see runwjaas.csh for instructions for how to run this test
+ * @run main/manual AuthOnly
  */
+
 /*
- * Can set logging to FINEST to view exchange.
+ * Set logging to FINEST to view exchange.
+ * See runwjaas.csh for instructions for how to run this test.
  */
+
 import javax.security.sasl.*;
 import javax.security.auth.callback.*;
 import java.security.*;
--- a/test/com/sun/security/sasl/gsskerb/ConfSecurityLayer.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/com/sun/security/sasl/gsskerb/ConfSecurityLayer.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,12 +25,15 @@
  * @test
  * @bug 5014493
  * @summary SaslServer.wrap throws NullPointerException when security
- *    layer negotiated
- * @ignore see run-conf-wjaas.csh for instructions for how to run this test
+ *    layer negotiated.
+ * @run main/manual ConfSecurityLayer
  */
+
 /*
- * Can set logging to FINEST to view exchange.
+ * Set logging to FINEST to view exchange.
+ * See run-conf-wjaas.csh for instructions for how to run this test.
  */
+
 import javax.security.sasl.*;
 import javax.security.auth.callback.*;
 import java.security.*;
--- a/test/com/sun/security/sasl/gsskerb/NoSecurityLayer.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/com/sun/security/sasl/gsskerb/NoSecurityLayer.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,13 +24,16 @@
 /*
  * @test
  * @bug 4873552
- * @summary GSS-API/krb5 SASL mechanism should throw IllegalStateException for auth-only
-
- * @ignore see run-nosec-wjaas.csh for instructions for how to run this test
+ * @summary GSS-API/krb5 SASL mechanism should throw IllegalStateException
+ *     for auth-only
+ * @run main/manual NoSecurityLayer
  */
+
 /*
- * Can set logging to FINEST to view exchange.
+ * Set logging to FINEST to view exchange.
+ * See run-nosec-wjaas.csh for instructions for how to run this test.
  */
+
 import javax.security.sasl.*;
 import javax.security.auth.callback.*;
 import java.security.*;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/awt/FontMetrics/MaxAdvanceIsMax.java	Thu Feb 06 01:43:16 2020 +0000
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2019, Red Hat, Inc.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8218854
+ * @run main/othervm MaxAdvanceIsMax
+ */
+
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Graphics2D;
+import java.awt.GraphicsEnvironment;
+import java.awt.RenderingHints;
+import java.awt.image.BufferedImage;
+
+public class MaxAdvanceIsMax {
+
+    private static boolean debug = true;
+
+    private static final class AntialiasHint {
+        private Object aaHint;
+        private String asString = "";
+
+        AntialiasHint(Object aaHint) {
+            if (aaHint.equals(
+                    RenderingHints.VALUE_TEXT_ANTIALIAS_OFF)) {
+                asString += "FT_LOAD_TARGET_MONO";
+            } else if (aaHint.equals(
+                    RenderingHints.VALUE_TEXT_ANTIALIAS_ON)) {
+                asString += "FT_LOAD_TARGET_NORMAL";
+            } else if (aaHint.equals(
+                    RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB)) {
+                asString += "FT_LOAD_TARGET_LCD";
+            } else if (aaHint.equals(
+                    RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_VRGB)) {
+                asString += "FT_LOAD_TARGET_LCD_V";
+            }
+            this.aaHint = aaHint;
+        }
+
+        public Object getHint() {
+            return aaHint;
+        }
+
+        public String toString() {
+            return asString;
+        }
+    }
+
+    private static final AntialiasHint[] antialiasHints = {
+            new AntialiasHint(RenderingHints.VALUE_TEXT_ANTIALIAS_OFF),
+            new AntialiasHint(RenderingHints.VALUE_TEXT_ANTIALIAS_ON),
+            new AntialiasHint(RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB),
+            new AntialiasHint(RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_VRGB)
+    };
+
+    private static final class StyleAndSize {
+        int style;
+        float size;
+        public StyleAndSize(int style, float size) {
+            this.style = style;
+            this.size = size;
+        }
+    };
+
+    private static final StyleAndSize[] stylesAndSizes = new StyleAndSize[] {
+        new StyleAndSize(Font.BOLD | Font.ITALIC, 10)
+    };
+
+    public static void main(String[] args) throws Exception {
+        GraphicsEnvironment e =
+                GraphicsEnvironment.getLocalGraphicsEnvironment();
+        Font[] fonts = e.getAllFonts();
+        BufferedImage bi = new BufferedImage(500, 500,
+                BufferedImage.TYPE_INT_RGB);
+        for (AntialiasHint antialiasHint : antialiasHints) {
+            for (Font f : fonts) {
+                for (StyleAndSize styleAndSize : stylesAndSizes) {
+                    f = f.deriveFont(styleAndSize.style, styleAndSize.size);
+                    Graphics2D g2d = bi.createGraphics();
+                    g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
+                            antialiasHint.getHint());
+                    FontMetrics fm = g2d.getFontMetrics(f);
+                    int[] width;
+                    int maxWidth = -1;
+                    int maxAdvance = fm.getMaxAdvance();
+                    if (debug) {
+                        System.out.println("Testing " + f + " in " +
+                                antialiasHint);
+                        System.out.println("getMaxAdvance: " + maxAdvance);
+                    }
+                    if (maxAdvance != -1) {
+                        String failureMessage = null;
+                        width = fm.getWidths();
+                        for (int j = 0; j < width.length; j++) {
+                            if (width[j] > maxWidth) {
+                                maxWidth = width[j];
+                            }
+                            if (width[j] > maxAdvance) {
+                                failureMessage = "FAILED: getMaxAdvance is " +
+                                                 "not max for font: " +
+                                                 f.toString() +
+                                                 " getMaxAdvance(): " +
+                                                 maxAdvance +
+                                                 " getWidths()[" + j + "]: " +
+                                                 width[j];
+                                throw new Exception(failureMessage);
+                            }
+                        }
+                    }
+                    if (debug) {
+                        System.out.println("Max char width: " + maxWidth);
+                        System.out.println("PASSED");
+                        System.out.println(".........................");
+                    }
+                }
+            }
+        }
+        System.out.println("TEST PASS - OK");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/awt/FontMetrics/SpaceAdvance.java	Thu Feb 06 01:43:16 2020 +0000
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8227662
+ */
+
+import java.awt.Font;
+import java.awt.FontMetrics ;
+import java.awt.Graphics2D;
+import java.awt.image.BufferedImage;
+
+public class SpaceAdvance {
+    public static void main(String[] args) throws Exception {
+
+        BufferedImage bi = new BufferedImage(1,1,1);
+        Graphics2D g2d = bi.createGraphics();
+        Font font = new Font(Font.DIALOG, Font.PLAIN, 12);
+        if (!font.canDisplay(' ')) {
+            return;
+        }
+        g2d.setFont(font);
+        FontMetrics fm = g2d.getFontMetrics();
+        if (fm.charWidth(' ') == 0) {
+            throw new RuntimeException("Space has char width of 0");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/awt/font/TextLayout/FontGlyphCompare.java	Thu Feb 06 01:43:16 2020 +0000
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+/* @test
+ * @bug 8214002
+ * @requires (os.family == "windows")
+ * @summary verify MS Mincho's Plain & Italic style
+ */
+
+import java.awt.Font;
+import java.awt.Color;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.RenderingHints;
+import java.awt.image.BufferedImage;
+
+public class FontGlyphCompare {
+
+    static BufferedImage getFontImage(Font font, String text) {
+        int x = 1;
+        int y = 15;
+        int w = 10;
+        int h = 18;
+        BufferedImage bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
+        Graphics2D g = (Graphics2D)bi.getGraphics();
+        g.setColor(Color.black);
+        g.fillRect(0, 0, w, h);
+        g.setColor(Color.white);
+        g.setFont(font);
+        g.drawString(text, x, y);
+        return bi;
+    }
+
+    public static void main(String[] args) throws Exception {
+        String osName = System.getProperty("os.name");
+        System.out.println("OS is " + osName);
+        osName = osName.toLowerCase();
+        if (!osName.startsWith("windows")) {
+            return;
+        }
+        Font msMincho = new Font("MS Mincho", Font.PLAIN, 16);
+        String family = msMincho.getFamily(java.util.Locale.ENGLISH);
+        if (!family.equalsIgnoreCase("MS Mincho")) {
+            System.out.println("Japanese fonts not installed");
+            return;
+        }
+        String s = "|";
+        BufferedImage bi1 = getFontImage(new Font("MS Mincho", Font.PLAIN, 16), s);
+        int h1 = bi1.getHeight();
+        int w1 = bi1.getWidth();
+        BufferedImage bi2 = getFontImage(new Font("MS Mincho", Font.ITALIC, 16), s);
+        int h2 = bi2.getHeight();
+        int w2 = bi2.getWidth();
+        if ((h1 == h2) && (w1 == w2)) {
+            int cnt = 0;
+            for(int yy = 0; yy < h1; yy++) {
+                for(int xx = 0; xx < w1; xx++) {
+                    if (bi1.getRGB(xx, yy) != bi2.getRGB(xx, yy)) {
+                        cnt++;
+                    }
+                }
+            }
+            if (cnt == 0) {
+                throw new Exception("Test failed");
+            }
+        }
+    }
+}
--- a/test/java/io/Serializable/serialFilter/GlobalFilterTest.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/java/io/Serializable/serialFilter/GlobalFilterTest.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -42,9 +42,11 @@
 import sun.misc.ObjectInputFilter;
 
 /* @test
+ * @bug 8231422
  * @build GlobalFilterTest SerialFilterTest
  * @run testng/othervm GlobalFilterTest
- * @run testng/othervm -Djdk.serialFilter=java.** GlobalFilterTest
+ * @run testng/othervm -Djdk.serialFilter=java.**
+ *          -Dexpected-jdk.serialFilter=java.** GlobalFilterTest
  * @run testng/othervm/policy=security.policy GlobalFilterTest
  * @run testng/othervm/policy=security.policy
  *        -Djava.security.properties=${test.src}/java.security-extra1
@@ -54,6 +56,10 @@
  */
 @Test
 public class GlobalFilterTest {
+    private static final String serialPropName = "jdk.serialFilter";
+    private static final String badSerialFilter = "java.lang.StringBuffer;!*";
+    private static final String origSerialFilterProperty =
+            System.setProperty(serialPropName, badSerialFilter);
 
     /**
      * DataProvider of patterns and objects derived from the configured process-wide filter.
@@ -62,8 +68,8 @@
     @DataProvider(name="globalPatternElements")
     Object[][] globalPatternElements() {
         String globalFilter =
-                System.getProperty("jdk.serialFilter",
-                        Security.getProperty("jdk.serialFilter"));
+                System.getProperty("expected-" + serialPropName,
+                        Security.getProperty(serialPropName));
         if (globalFilter == null) {
             return new Object[0][];
         }
@@ -100,12 +106,20 @@
      */
     @Test()
     static void globalFilter() {
+        ObjectInputFilter filter = ObjectInputFilter.Config.getSerialFilter();
+
+        // Check that the System.setProperty(jdk.serialFilter) DOES NOT affect the filter.
+        String asSetSystemProp = System.getProperty(serialPropName,
+                Security.getProperty(serialPropName));
+        Assert.assertNotEquals(Objects.toString(filter, null), asSetSystemProp,
+                "System.setProperty(\"jdk.serialfilter\", ...) should not change filter: " +
+                asSetSystemProp);
+
         String pattern =
-                System.getProperty("jdk.serialFilter",
-                        Security.getProperty("jdk.serialFilter"));
-        ObjectInputFilter filter = ObjectInputFilter.Config.getSerialFilter();
+               System.getProperty("expected-" + serialPropName,
+                       Security.getProperty(serialPropName));
         System.out.printf("global pattern: %s, filter: %s%n", pattern, filter);
-        Assert.assertEquals(pattern, Objects.toString(filter, null),
+        Assert.assertEquals(Objects.toString(filter, null), pattern,
                 "process-wide filter pattern does not match");
     }
 
--- a/test/java/io/Serializable/serialFilter/security.policy	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/java/io/Serializable/serialFilter/security.policy	Thu Feb 06 01:43:16 2020 +0000
@@ -3,7 +3,7 @@
         // Specific permission under test
         permission java.security.SerializablePermission "serialFilter";
         // Permissions needed to run the test
-        permission java.util.PropertyPermission "*", "read";
+        permission java.util.PropertyPermission "*", "read,write";
         permission java.io.FilePermission "<<ALL FILES>>", "read,write,delete";
         permission java.lang.reflect.ReflectPermission "suppressAccessChecks";
         permission java.security.SecurityPermission "*";
--- a/test/java/lang/annotation/AnnotationType/AnnotationTypeRuntimeAssumptionTest.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/java/lang/annotation/AnnotationType/AnnotationTypeRuntimeAssumptionTest.java	Thu Feb 06 01:43:16 2020 +0000
@@ -26,16 +26,19 @@
  * @bug 7122142
  * @summary Test consistent parsing of ex-RUNTIME annotations that
  *          were changed and separately compiled to have CLASS retention
+ * @library /lib/testlibrary
+ * @build jdk.testlibrary.IOUtils
+ * @run main AnnotationTypeRuntimeAssumptionTest
  */
 
-import sun.misc.IOUtils;
-
 import java.io.IOException;
 import java.io.InputStream;
 import java.lang.annotation.Annotation;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 
+import jdk.testlibrary.IOUtils;
+
 import static java.lang.annotation.RetentionPolicy.CLASS;
 import static java.lang.annotation.RetentionPolicy.RUNTIME;
 
@@ -148,7 +151,7 @@
                 String altPath = altName.replace('.', '/').concat(".class");
                 try (InputStream is = getResourceAsStream(altPath)) {
                     if (is != null) {
-                        byte[] bytes = IOUtils.readFully(is, -1, true);
+                        byte[] bytes = IOUtils.readFully(is);
                         // patch class bytes to contain original name
                         for (int i = 0; i < bytes.length - 2; i++) {
                             if (bytes[i] == '_' &&
@@ -171,7 +174,7 @@
                 String path = name.replace('.', '/').concat(".class");
                 try (InputStream is = getResourceAsStream(path)) {
                     if (is != null) {
-                        byte[] bytes = IOUtils.readFully(is, -1, true);
+                        byte[] bytes = IOUtils.readFully(is);
                         return defineClass(name, bytes, 0, bytes.length);
                     }
                     else {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/nio/channels/etc/AdaptorCloseAndInterrupt.java	Thu Feb 06 01:43:16 2020 +0000
@@ -0,0 +1,221 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @bug 7184932
+ * @summary Test asynchronous close and interrupt of timed socket adapter methods
+ */
+
+import java.io.*;
+import java.nio.*;
+import java.nio.channels.*;
+import java.nio.channels.spi.AbstractSelectableChannel;
+import java.net.*;
+import java.util.concurrent.Callable;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+import java.util.Random;
+
+
+public class AdaptorCloseAndInterrupt {
+    private static final ScheduledExecutorService pool =
+        Executors.newScheduledThreadPool(1);
+    final ServerSocketChannel listener;
+    final DatagramChannel peer;
+    final int port;
+
+    public AdaptorCloseAndInterrupt() {
+        listener = null;
+        peer = null;
+        port = -1;
+    }
+
+    public AdaptorCloseAndInterrupt(ServerSocketChannel listener) {
+        this.listener = listener;
+        this.port = listener.socket().getLocalPort();
+        this.peer = null;
+    }
+
+    public AdaptorCloseAndInterrupt(DatagramChannel listener) {
+        this.peer = listener;
+        this.port = peer.socket().getLocalPort();
+        this.listener = null;
+    }
+
+    public static void main(String args[]) throws Exception {
+        try {
+            try (ServerSocketChannel listener = ServerSocketChannel.open()) {
+                listener.socket().bind(null);
+                new AdaptorCloseAndInterrupt(listener).scReadAsyncClose();
+                new AdaptorCloseAndInterrupt(listener).scReadAsyncInterrupt();
+            }
+
+            try (DatagramChannel peer = DatagramChannel.open()) {
+                peer.socket().bind(null);
+                new AdaptorCloseAndInterrupt(peer).dcReceiveAsyncClose();
+                new AdaptorCloseAndInterrupt(peer).dcReceiveAsyncInterrupt();
+            }
+
+            new AdaptorCloseAndInterrupt().ssAcceptAsyncClose();
+            new AdaptorCloseAndInterrupt().ssAcceptAsyncInterrupt();
+        } finally {
+            pool.shutdown();
+        }
+        System.out.println("Test Passed");
+    }
+
+    void scReadAsyncClose() throws IOException {
+        try {
+            SocketChannel sc = SocketChannel.open(new InetSocketAddress(
+                "127.0.0.1", port));
+            sc.socket().setSoTimeout(30*1000);
+
+            doAsyncClose(sc);
+
+            try {
+                sc.socket().getInputStream().read(new byte[100]);
+                throw new RuntimeException("read should not have completed");
+            } catch (ClosedChannelException expected) {}
+
+            if (!sc.socket().isClosed())
+                throw new RuntimeException("socket is not closed");
+        } finally {
+            // accept connection and close it.
+            listener.accept().close();
+        }
+    }
+
+    void scReadAsyncInterrupt() throws IOException {
+        try {
+            final SocketChannel sc = SocketChannel.open(new InetSocketAddress(
+                "127.0.0.1", port));
+            sc.socket().setSoTimeout(30*1000);
+
+            doAsyncInterrupt();
+
+            try {
+                sc.socket().getInputStream().read(new byte[100]);
+                throw new RuntimeException("read should not have completed");
+            } catch (ClosedByInterruptException expected) {
+                Thread.currentThread().interrupted();
+            }
+
+            if (!sc.socket().isClosed())
+                throw new RuntimeException("socket is not closed");
+        } finally {
+            // accept connection and close it.
+            listener.accept().close();
+        }
+    }
+
+    void dcReceiveAsyncClose() throws IOException {
+        DatagramChannel dc = DatagramChannel.open();
+        dc.connect(new InetSocketAddress(
+            "127.0.0.1", port));
+        dc.socket().setSoTimeout(30*1000);
+
+        doAsyncClose(dc);
+
+        try {
+            dc.socket().receive(new DatagramPacket(new byte[100], 100));
+            throw new RuntimeException("receive should not have completed");
+        } catch (ClosedChannelException expected) {}
+
+        if (!dc.socket().isClosed())
+            throw new RuntimeException("socket is not closed");
+    }
+
+    void dcReceiveAsyncInterrupt() throws IOException {
+        DatagramChannel dc = DatagramChannel.open();
+        dc.connect(new InetSocketAddress(
+            "127.0.0.1", port));
+        dc.socket().setSoTimeout(30*1000);
+
+        doAsyncInterrupt();
+
+        try {
+            dc.socket().receive(new DatagramPacket(new byte[100], 100));
+            throw new RuntimeException("receive should not have completed");
+        } catch (ClosedByInterruptException expected) {
+            Thread.currentThread().interrupted();
+        }
+
+        if (!dc.socket().isClosed())
+            throw new RuntimeException("socket is not closed");
+    }
+
+    void ssAcceptAsyncClose() throws IOException {
+        ServerSocketChannel ssc = ServerSocketChannel.open();
+        ssc.socket().bind(null);
+        ssc.socket().setSoTimeout(30*1000);
+
+        doAsyncClose(ssc);
+
+        try {
+            ssc.socket().accept();
+            throw new RuntimeException("accept should not have completed");
+        } catch (ClosedChannelException expected) {}
+
+        if (!ssc.socket().isClosed())
+            throw new RuntimeException("socket is not closed");
+    }
+
+    void ssAcceptAsyncInterrupt() throws IOException {
+        ServerSocketChannel ssc = ServerSocketChannel.open();
+        ssc.socket().bind(null);
+        ssc.socket().setSoTimeout(30*1000);
+
+        doAsyncInterrupt();
+
+        try {
+            ssc.socket().accept();
+            throw new RuntimeException("accept should not have completed");
+        } catch (ClosedByInterruptException expected) {
+            Thread.currentThread().interrupted();
+        }
+
+        if (!ssc.socket().isClosed())
+            throw new RuntimeException("socket is not closed");
+    }
+
+    void doAsyncClose(final AbstractSelectableChannel sc) {
+        AdaptorCloseAndInterrupt.pool.schedule(new Callable<Void>() {
+            public Void call() throws Exception {
+                sc.close();
+                return null;
+            }
+        }, new Random().nextInt(1000), TimeUnit.MILLISECONDS);
+    }
+
+    void doAsyncInterrupt() {
+        final Thread current = Thread.currentThread();
+        AdaptorCloseAndInterrupt.pool.schedule(new Callable<Void>() {
+            public Void call() throws Exception {
+                current.interrupt();
+                return null;
+            }
+        }, new Random().nextInt(1000), TimeUnit.MILLISECONDS);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/rmi/server/RMISocketFactory/useSocketFactory/unicast/TCPEndpointReadBug.java	Thu Feb 06 01:43:16 2020 +0000
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+import java.io.IOException;
+import java.io.Serializable;
+import java.io.ObjectInputStream;
+import java.net.Socket;
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+import java.rmi.server.RMIClientSocketFactory;
+import java.rmi.server.RMISocketFactory;
+import java.rmi.server.UnicastRemoteObject;
+
+/* @test
+ * @bug 8237368
+ * @summary Allow custom socket factory to be null in TCPEndpoint.
+ * @run main/othervm TCPEndpointReadBug
+ */
+public class TCPEndpointReadBug {
+
+    public static void main(String[] args) throws Exception {
+        final I implC = new C();
+        final I remoteC = (I)UnicastRemoteObject.exportObject(
+                implC, 0, new CSF(), RMISocketFactory.getDefaultSocketFactory());
+
+        // Pass a remote object with a custom socket factory as an argument
+        remoteC.echo(remoteC);
+
+        // Pass nothing and get an object with a custom socket factory in return
+        remoteC.echo(null);
+    }
+
+    interface I extends Remote {
+        I echo(I intf) throws RemoteException;
+    }
+
+    static class C implements I {
+        @Override
+        public I echo(I intf) {
+            try {
+                return  (I)UnicastRemoteObject
+                    .exportObject(new C(),0, new CSF(), RMISocketFactory.getDefaultSocketFactory());
+            } catch (RemoteException e) {
+                e.printStackTrace();
+            }
+            return null;
+        }
+    }
+
+    /**
+     * A configurable socket factory in which for test purposes supplies null.
+     */
+    static class CSF implements Serializable, RMIClientSocketFactory {
+        private static final long serialVersionUID = 1;
+
+        @Override
+        public boolean equals(Object object) {
+            return object instanceof CSF;
+        }
+
+        @Override
+        public int hashCode() {
+            return 424242;
+        }
+
+        @Override
+        public Socket createSocket(String host, int port)
+            throws IOException {
+
+            final RMIClientSocketFactory defaultFactory =
+                RMISocketFactory.getDefaultSocketFactory();
+            return defaultFactory.createSocket(host, port);
+        }
+
+        /**
+         * Use writeReplace to use a different client socket factory. In the
+         * problematic case, the replacement is null.
+         */
+        private Object writeReplace() {
+            return null;
+        }
+
+        /**
+         * Instances of this class should never be deserialized because they
+         * are always replaced during serialization.
+         */
+        @SuppressWarnings("unused")
+        private void readObject(ObjectInputStream in) {
+            throw new AssertionError();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/security/KeyStore/TestKeyStoreBasic.java	Thu Feb 06 01:43:16 2020 +0000
@@ -0,0 +1,283 @@
+/*
+ * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.BufferedInputStream;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.KeyFactory;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchProviderException;
+import java.security.PrivateKey;
+import java.security.UnrecoverableKeyException;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateFactory;
+import java.security.spec.KeySpec;
+import java.security.spec.PKCS8EncodedKeySpec;
+
+import sun.misc.BASE64Decoder;
+
+/*
+ * @test
+ * @bug 8048621 8133090
+ * @summary Test basic operations with keystores (jks, jceks, pkcs12)
+ * @author Yu-Ching Valerie PENG
+ */
+public class TestKeyStoreBasic {
+
+    private static final String PRIVATE_KEY_PKCS8_BASE64 = ""
+        + "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCpyz97liuWPDYcLH9TX8BiT78o"
+        + "lCmAfmevvch6ncXUVuCzbdaKuKXwn4EVbDszsVJLoK5zdtP+X3iDhutj+IgKmLhuczF3M9VIcWr+"
+        + "JJUyTH4+3h/RT8cjCDZOmk9iXkb5ifruVsLqzb9g+Vp140Oz7leikne7KmclHvTfvFd0WDI7Gb9v"
+        + "o4f5rT717BXJ/n+M6pNk8DLpLiEu6eziYvXRv5x+t5Go3x0eCXdaxEQUf2j876Wfr2qHRJK7lDfF"
+        + "e1DDsMg/KpKGiILYZ+g2qtVMZSxtp5BZEtfB5qV/IE5kWO+mCIAGpXSZIdbERR6pZUq8GLEe1T9e"
+        + "+sO6H24w2F19AgMBAAECggEBAId/12187dO6wUPCjumuJA1QrrBnbKdKONyai36uoc1Od4s5QFj7"
+        + "+hEIeS7rbGNYQuBvnkgusAbzkW0FIpxpHce3EJez/emux6pEOKoP77BwMt9gy+txyu0+BHi91FQg"
+        + "AGvrnQDO5EYVY4Cz/WjOsJzKu8zVLg+DS0Toa2qRFwmUe9mVAXPNOCZ3Oae/Q6tCDsaINNw0fmjj"
+        + "jn6uohPbS+n6xENG3FkQXB36getXy310xTGED2J27cmAQH6gLR6Kl2iROzNPbbpBqbuemI9kbcld"
+        + "EwBS1jRfZWeaPstYA1niVrE9UgUBzemnoh4TDkG076sYthHMr5QFGjPswnwtJ4ECgYEA0sURQ5+v"
+        + "baH4tdaemI3qpnknXTlzSpuZZmAoyvY0Id0mlduwKwmZ3Y5989wHfnnhFfyNO4IkTKjI2Wp97qP5"
+        + "4eqUNpA7FtNU7KUzMcFDTtwtNZuRYMrKlqo2lLbA+gVrAYpYZFL4b7tcwtX4DnYorDsmude6W8sG"
+        + "4Mx2VdFJC9UCgYEAzjsdXCYH5doWUHb0dvn9ID7IikffEMRM720MRjrnnnVbpzx6ACntkPDNZg7p"
+        + "TRE/mx7iBz81ZaUWE+V0wd0JvCHEdpAz3mksyvDFhU4Bgs6xzf2pSul5muhsx3hHcvvPezz5Bnxs"
+        + "faJlzkxfwotyGmvWN15GA/pyfsZjsbbTpwkCgYAO6NnbysQCIV8SnegCKqfatt9N/O5m7LLhRxQb"
+        + "p2bwrlA4cZ34rWkw/w9x3LK7A6wkfgUPnJkswxPSLXJTG05l6M4rPfCwIKr1Qopojp9QSMr569NQ"
+        + "4YeLOOc7heIIzbFQHpU6I5Rncv2Q2sn9W+ZsqJKIuvX34FjQNiZ406EzMQKBgHSxOGS61D84DuZK"
+        + "2Ps1awhC3kB4eHzJRms3vflDPWoJJ+pSKwpKrzUTPHXiPBqyhtYkPGszVeiE6CAr9sv3YZnFVaBs"
+        + "6hyQUJsob+uE/w/gGvXe8VsFDx0bJOodYfhrCbTHBHWqE81nBcocpxayxsayfAzqWB3KKd0YLrMR"
+        + "K2PZAoGAcZa8915R2m0KZ6HVJUt/JDR85jCbN71kcVDFY2XSFkOJvOdFoHNfRckfLzjq9Y2MSSTV"
+        + "+QDWbDo2doUQCejJUTaN8nP79tfyir24X5uVPvQaeVoGTKYb+LfUqK0F60lStmjuddIGSZH55y3v"
+        + "+9XjmxbVERtd1lqgQg3VlmKlEXY=";
+
+    /*
+     * Certificate:
+     * Data:
+     *     Version: 3 (0x2)
+     *     Serial Number: 7 (0x7)
+     * Signature Algorithm: sha512WithRSAEncryption
+     *     Issuer: CN=Root
+     *     Validity
+     *         Not Before: Sep  1 18:03:59 2015 GMT
+     *         Not After : Jan 17 18:03:59 2043 GMT
+     *     Subject: CN=EE
+     */
+    private static final String CERTIFICATE = ""
+        + "-----BEGIN CERTIFICATE-----\n"
+        + "MIIDHTCCAgWgAwIBAgIBBzANBgkqhkiG9w0BAQ0FADAPMQ0wCwYDVQQDDARSb290\n"
+        + "MB4XDTE1MDkwMTE4MDM1OVoXDTQzMDExNzE4MDM1OVowDTELMAkGA1UEAwwCRUUw\n"
+        + "ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCpyz97liuWPDYcLH9TX8Bi\n"
+        + "T78olCmAfmevvch6ncXUVuCzbdaKuKXwn4EVbDszsVJLoK5zdtP+X3iDhutj+IgK\n"
+        + "mLhuczF3M9VIcWr+JJUyTH4+3h/RT8cjCDZOmk9iXkb5ifruVsLqzb9g+Vp140Oz\n"
+        + "7leikne7KmclHvTfvFd0WDI7Gb9vo4f5rT717BXJ/n+M6pNk8DLpLiEu6eziYvXR\n"
+        + "v5x+t5Go3x0eCXdaxEQUf2j876Wfr2qHRJK7lDfFe1DDsMg/KpKGiILYZ+g2qtVM\n"
+        + "ZSxtp5BZEtfB5qV/IE5kWO+mCIAGpXSZIdbERR6pZUq8GLEe1T9e+sO6H24w2F19\n"
+        + "AgMBAAGjgYUwgYIwNAYDVR0fBC0wKzApoCegJYYjbGRhcDovL2xkYXAuaG9zdC5m\n"
+        + "b3IuY3JsZHAvbWFpbi5jcmwwSgYIKwYBBQUHAQEEPjA8MDoGCCsGAQUFBzAChi5s\n"
+        + "ZGFwOi8vbGRhcC5ob3N0LmZvci5haWEvZGM9Um9vdD9jQUNlcnRpZmljYXRlMA0G\n"
+        + "CSqGSIb3DQEBDQUAA4IBAQBWDfZHpuUx0yn5d3+BuztFqoks1MkGdk+USlH0TB1/\n"
+        + "gWWBd+4S4PCKlpSur0gj2rMW4fP5HQfNlHci8JV8/bG4KuKRAXW56dg1818Hl3pc\n"
+        + "iIrUSRn8uUjH3p9qb+Rb/u3mmVQRyJjN2t/zceNsO8/+Dd808OB9aEwGs8lMT0nn\n"
+        + "ZYaaAqYz1GIY/Ecyx1vfEZEQ1ljo6i/r70C3igbypBUShxSiGsleiVTLOGNA+MN1\n"
+        + "/a/Qh0bkaQyTGqK3bwvzzMeQVqWu2EWTBD/PmND5ExkpRICdv8LBVXfLnpoBr4lL\n"
+        + "hnxn9+e0Ah+t8dS5EKfn44w5bI5PCu2bqxs6RCTxNjcY\n"
+        + "-----END CERTIFICATE-----\n";
+
+    private static final char[] PASSWD2 = new char[] {
+            'b', 'o', 'r', 'e', 'd'
+    };
+    private static final char[] PASSWDK = "cannot be null"
+            .toCharArray();
+    private static final String[] KS_Type = {
+            "jks", "jceks", "pkcs12", "PKCS11KeyStore"
+    };
+    private static final String[] PROVIDERS = {
+            "SUN", "SunJCE", "SunJSSE", "SunPKCS11-Solaris"
+    };
+    private static final String ALIAS_HEAD = "test";
+
+    public static void main(String args[]) throws Exception {
+        TestKeyStoreBasic jstest = new TestKeyStoreBasic();
+        jstest.run();
+    }
+
+    public void run() throws Exception {
+        for (String provider : PROVIDERS) {
+            try {
+                runTest(provider);
+                System.out.println("Test with provider " + provider + "passed");
+            } catch (java.security.KeyStoreException e) {
+                if (provider.equals("SunPKCS11-Solaris")) {
+                    System.out.println("KeyStoreException is expected: "
+                            + "PKCS11KeyStore is invalid keystore type: " + e);
+                } else {
+                    throw e;
+                }
+            } catch (NoSuchProviderException e) {
+                String osName = System.getProperty("os.name");
+                if (provider.equals("SunPKCS11-Solaris")
+                        && !osName.equals("SunOS")) {
+                    System.out.println("Skip SunPKCS11-Solaris provider on "
+                            + osName);
+                } else {
+                    throw e;
+                }
+            }
+        }
+    }
+
+    public void runTest(String provider) throws Exception {
+
+        // load private key
+        // all keystore types should support private keys
+        KeySpec spec = new PKCS8EncodedKeySpec(
+                new BASE64Decoder().decodeBuffer(PRIVATE_KEY_PKCS8_BASE64));
+        PrivateKey privateKey = KeyFactory.getInstance("RSA")
+                .generatePrivate(spec);
+
+        // load x509 certificate
+        Certificate cert;
+        try (InputStream is = new BufferedInputStream(
+                new ByteArrayInputStream(CERTIFICATE.getBytes()))) {
+            cert = CertificateFactory.getInstance("X.509")
+                    .generateCertificate(is);
+        }
+
+        int numEntries = 5;
+        String type = null;
+        for (int i = 0; i < PROVIDERS.length; i++) {
+            if (provider.compareTo(PROVIDERS[i]) == 0) {
+                type = KS_Type[i];
+                break;
+            }
+        }
+
+        System.out.printf("Test %s provider and %s keystore%n", provider, type);
+        KeyStore ks = KeyStore.getInstance(type, provider);
+        KeyStore ks2 = KeyStore.getInstance(type, ks.getProvider().getName());
+
+        // create an empty key store
+        ks.load(null, null);
+
+        // store the secret keys
+        for (int j = 0; j < numEntries; j++) {
+            ks.setKeyEntry(ALIAS_HEAD + j, privateKey, PASSWDK,
+                    new Certificate[] { cert });
+        }
+
+        // initialize the 2nd key store object with the 1st one
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        ks.store(baos, PASSWDK);
+        byte[] bArr = baos.toByteArray();
+        ByteArrayInputStream bais = new ByteArrayInputStream(bArr);
+        ks2.load(bais, null);
+
+        // check 2nd key store type
+        checkType(ks2, type);
+        // check the existing aliases for the 2nd key store
+        checkAlias(ks2, numEntries);
+
+        // compare the creation date of the 2 key stores for all aliases
+        compareCreationDate(ks, ks2, numEntries);
+        // remove the last entry from the 2nd key store
+        numEntries--;
+        ks2.deleteEntry(ALIAS_HEAD + numEntries);
+
+        // re-initialize the 1st key store with the 2nd key store
+        baos.reset();
+        ks2.store(baos, PASSWD2);
+        bais = new ByteArrayInputStream(baos.toByteArray());
+        try {
+            // expect an exception since the password is incorrect
+            ks.load(bais, PASSWDK);
+            throw new RuntimeException(
+                    "ERROR: passed the loading with incorrect password");
+        } catch (IOException ex) {
+            System.out.println("Expected exception: " + ex);
+            if (!causedBy(ex, UnrecoverableKeyException.class)) {
+                ex.printStackTrace(System.out);
+                throw new RuntimeException("Unexpected cause");
+            }
+            System.out.println("Expected cause: "
+                    + UnrecoverableKeyException.class.getName());
+
+            bais.reset();
+            ks.load(bais, PASSWD2);
+            bais.reset();
+            ks.load(bais, null);
+        }
+
+        // check key store type
+        checkType(ks, type);
+
+        // check the existing aliases
+        checkAlias(ks, numEntries);
+
+        // compare the creation date of the 2 key stores for all aliases
+        compareCreationDate(ks, ks2, numEntries);
+
+    }
+
+    // check key store type
+    private void checkType(KeyStore obj, String type) {
+        if (!obj.getType().equals(type)) {
+            throw new RuntimeException("ERROR: wrong key store type");
+        }
+    }
+
+    // check the existing aliases
+    private void checkAlias(KeyStore obj, int range) throws KeyStoreException {
+        for (int k = 0; k < range; k++) {
+            if (!obj.containsAlias(ALIAS_HEAD + k)) {
+                throw new RuntimeException("ERROR: alias (" + k
+                        + ") should exist");
+            }
+        }
+    }
+
+    // compare the creation dates - true if all the same
+    private void compareCreationDate(KeyStore o1, KeyStore o2, int range)
+            throws KeyStoreException {
+        String alias;
+        for (int k = 0; k < range; k++) {
+            alias = ALIAS_HEAD + k;
+            if (!o1.getCreationDate(alias).equals(o2.getCreationDate(alias))) {
+                throw new RuntimeException("ERROR: entry creation time (" + k
+                        + ") differs");
+            }
+        }
+    }
+
+    // checks if an exception was caused by specified exception class
+    private static boolean causedBy(Exception e, Class klass) {
+        Throwable cause = e;
+        while ((cause = cause.getCause()) != null) {
+            if (cause.getClass().equals(klass)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+}
--- a/test/java/security/Policy/Root/Root.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/java/security/Policy/Root/Root.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,12 +25,13 @@
  *
  * @bug 4619757
  * @summary User Policy Setting is not recognized on Netscape 6
- *              when invoked as root
- * @ignore - must run test as root
- *
- * place Root.policy in the root home directory (/), as /.java.policy
- * run this test as root:
- *      java Root
+ *          when invoked as root.
+ * @run main/manual Root
+ */
+
+/*
+ * Place Root.policy in the root home directory (/),
+ * as /.java.policy and run as test as root user.
  */
 
 import java.security.*;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/security/testlibrary/Proc.java	Thu Feb 06 01:43:16 2020 +0000
@@ -0,0 +1,338 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.security.Permission;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import sun.misc.BASE64Decoder;
+import sun.misc.BASE64Encoder;
+
+/**
+ * This is a test library that makes writing a Java test that spawns multiple
+ * Java processes easily.
+ *
+ * Usage:
+ *
+ *    Proc.create("Clazz")      // The class to launch
+ *        .args("x")            // with args
+ *        .env("env", "value")  // and an environment variable
+ *        .prop("key","value")  // and a system property
+ *        .perm(perm)           // with granted permissions
+ *        .start();             // and start
+ *
+ * create/start must be called, args/env/prop/perm can be called zero or
+ * multiple times between create and start.
+ *
+ * The controller can call inheritIO to share its I/O to the process.
+ * Otherwise, it can send data into a proc's stdin with write/println, and
+ * read its stdout with readLine. stderr is always redirected to DFILE
+ * unless nodump() is called. A protocol is designed to make
+ * data exchange among the controller and the processes super easy, in which
+ * useful data are always printed with a special prefix ("PROCISFUN:").
+ * If the data is binary, make it BASE64.
+ *
+ * For example:
+ *
+ * - A producer Proc calls Proc.binOut() or Proc.textOut() to send out data.
+ *   This method would prints to the stdout something like
+ *
+ *      PROCISFUN:[raw text or base64 binary]
+ *
+ * - The controller calls producer.readData() to get the content. This method
+ *   ignores all other output and only reads lines starting with "PROCISFUN:".
+ *
+ * - The controller does not care if the context is text or base64, it simply
+ *   feeds the data to a consumer Proc by calling consumer.println(data).
+ *   This will be printed into System.in of the consumer process.
+ *
+ * - The consumer Proc calls Proc.binIn() or Proc.textIn() to read the data.
+ *   The first method de-base64 the input and return a byte[] block.
+ *
+ * Please note only plain ASCII is supported in raw text at the moment.
+ *
+ * As the Proc objects are hidden so deeply, two static methods, d(String) and
+ * d(Throwable) are provided to output info into stderr, where they will
+ * normally be appended messages to DFILE (unless nodump() is called).
+ * Developers can view the messages in real time by calling
+ *
+ *    tail -f proc.debug
+ *
+ * TODO:
+ *
+ * . launch java tools, say, keytool
+ * . launch another version of java
+ * . start in another directory
+ * . start and finish using one method
+ *
+ * This is not a test, but is the core of
+ * JDK-8009977: A test library to launch multiple Java processes
+ */
+public class Proc {
+    private Process p;
+    private BufferedReader br;      // the stdout of a process
+    private String launcher;        // Optional: the java program
+
+    private List<Permission> perms = new ArrayList<>();
+    private List<String> args = new ArrayList<>();
+    private Map<String,String> env = new HashMap<>();
+    private Map<String,String> prop = new HashMap();
+    private boolean inheritIO = false;
+    private boolean noDump = false;
+
+    private String clazz;           // Class to launch
+    private String debug;           // debug flag, controller will show data
+                                    // transfer between procs
+
+    final private static String PREFIX = "PROCISFUN:";
+    final private static String DFILE = "proc.debug";
+
+    // The following methods are called by controllers
+
+    // Creates a Proc by the Java class name, launcher is an optional
+    // argument to specify the java program
+    public static Proc create(String clazz, String... launcher) {
+        Proc pc = new Proc();
+        pc.clazz = clazz;
+        if (launcher.length > 0) {
+            pc.launcher = launcher[0];
+        }
+        return pc;
+    }
+    // Sets inheritIO flag to proc. If set, proc will same I/O channels as
+    // teh controller. Otherwise, its stdin/stdout is untouched, and its
+    // stderr is redirected to DFILE.
+    public Proc inheritIO() {
+        inheritIO = true;
+        return this;
+    }
+    // When called, stderr inherits parent stderr, otherwise, append to a file
+    public Proc nodump() {
+        noDump = true;
+        return this;
+    }
+    // Specifies some args. Can be called multiple times.
+    public Proc args(String... args) {
+        for (String c: args) {
+            this.args.add(c);
+        }
+        return this;
+    }
+    // Returns debug prefix
+    public String debug() {
+        return debug;
+    }
+    // Enables debug with prefix
+    public Proc debug(String title) {
+        debug = title;
+        return this;
+    }
+    // Specifies an env var. Can be called multiple times.
+    public Proc env(String a, String b) {
+        env.put(a, b);
+        return this;
+    }
+    // Specifies a Java system property. Can be called multiple times.
+    public Proc prop(String a, String b) {
+        prop.put(a, b);
+        return this;
+    }
+    // Adds a perm to policy. Can be called multiple times. In order to make it
+    // effective, please also call prop("java.security.manager", "").
+    public Proc perm(Permission p) {
+        perms.add(p);
+        return this;
+    }
+    // Starts the proc
+    public Proc start() throws IOException {
+        List<String> cmd = new ArrayList<>();
+        if (launcher != null) {
+            cmd.add(launcher);
+        } else {
+            cmd.add(new File(new File(System.getProperty("java.home"), "bin"),
+                        "java").getPath());
+        }
+        cmd.add("-cp");
+        StringBuilder cp = new StringBuilder();
+        for (URL url: ((URLClassLoader)Proc.class.getClassLoader()).getURLs()) {
+            if (cp.length() != 0) {
+                cp.append(File.pathSeparatorChar);
+            }
+            cp.append(url.getFile());
+        }
+        cmd.add(cp.toString());
+        for (Entry<String,String> e: prop.entrySet()) {
+            cmd.add("-D" + e.getKey() + "=" + e.getValue());
+        }
+        if (!perms.isEmpty()) {
+            Path p = Files.createTempFile(
+                    Paths.get(".").toAbsolutePath(), "policy", null);
+            StringBuilder sb = new StringBuilder();
+            sb.append("grant {\n");
+            for (Permission perm: perms) {
+                // Sometimes a permission has no name or actions.
+                // but it's safe to use an empty string.
+                String s = String.format("%s \"%s\", \"%s\"",
+                        perm.getClass().getCanonicalName(),
+                        perm.getName()
+                                .replace("\\", "\\\\").replace("\"", "\\\""),
+                        perm.getActions());
+                sb.append("    permission ").append(s).append(";\n");
+            }
+            sb.append("};\n");
+            Files.write(p, sb.toString().getBytes());
+            cmd.add("-Djava.security.policy=" + p.toString());
+        }
+        cmd.add(clazz);
+        for (String s: args) {
+            cmd.add(s);
+        }
+        if (debug != null) {
+            System.out.println("PROC: " + debug + " cmdline: " + cmd);
+        }
+        ProcessBuilder pb = new ProcessBuilder(cmd);
+        for (Entry<String,String> e: env.entrySet()) {
+            pb.environment().put(e.getKey(), e.getValue());
+        }
+        if (inheritIO) {
+            pb.inheritIO();
+        } else if (noDump) {
+            pb.redirectError(ProcessBuilder.Redirect.INHERIT);
+        } else {
+            pb.redirectError(ProcessBuilder.Redirect.appendTo(new File(DFILE)));
+        }
+        p = pb.start();
+        br = new BufferedReader(new InputStreamReader(p.getInputStream()));
+        return this;
+    }
+    String getId(String suffix) {
+        if (debug != null) {
+            return debug + "." + suffix;
+        } else {
+            return System.identityHashCode(this) + "." + suffix;
+        }
+    }
+    // Reads a line from stdout of proc
+    public String readLine() throws IOException {
+        String s = br.readLine();
+        if (debug != null) {
+            System.out.println("PROC: " + debug + " readline: " +
+                    (s == null ? "<EOF>" : s));
+        }
+        return s;
+    }
+    // Reads a special line from stdout of proc
+    public String readData() throws Exception {
+        while (true) {
+            String s = readLine();
+            if (s == null) {
+                if (p.waitFor() != 0) {
+                    throw new Exception("Proc abnormal end");
+                } else {
+                    return s;
+                }
+            }
+            if (s.startsWith(PREFIX)) {
+                return s.substring(PREFIX.length());
+            }
+        }
+    }
+    // Writes text into stdin of proc
+    public void println(String s) throws IOException {
+        if (debug != null) {
+            System.out.println("PROC: " + debug + " println: " + s);
+        }
+        write((s + "\n").getBytes());
+    }
+    // Writes data into stdin of proc
+    public void write(byte[] b) throws IOException {
+        p.getOutputStream().write(b);
+        p.getOutputStream().flush();
+    }
+    // Reads all output and wait for process end
+    public int waitFor() throws Exception {
+        while (true) {
+            String s = readLine();
+            if (s == null) {
+                break;
+            }
+        }
+        return p.waitFor();
+    }
+
+    // The following methods are used inside a proc
+
+    // Writes out a BASE64 binary with a prefix
+    public static void binOut(byte[] data) {
+        System.out.println(PREFIX + new BASE64Encoder().encode(data));
+    }
+    // Reads in a line of BASE64 binary
+    public static byte[] binIn() throws Exception {
+        return new BASE64Decoder().decodeBuffer(textIn());
+    }
+    // Writes out a text with a prefix
+    public static void textOut(String data) {
+        System.out.println(PREFIX + data);
+    }
+    // Reads in a line of text
+    public static String textIn() throws Exception {
+        StringBuilder sb = new StringBuilder();
+        boolean isEmpty = true;
+        while (true) {
+            int i = System.in.read();
+            if (i == -1) {
+                break;
+            }
+            isEmpty = false;
+            if (i == '\n') {
+                break;
+            }
+            if (i != 13) {
+                // Force it to a char, so only simple ASCII works.
+                sb.append((char)i);
+            }
+        }
+        return isEmpty ? null : sb.toString();
+    }
+    // Sends string to stderr. If inheritIO is not called, they will
+    // be collected into DFILE
+    public static void d(String s) throws IOException {
+        System.err.println(s);
+    }
+    // Sends an exception to stderr
+    public static void d(Throwable e) throws IOException {
+        e.printStackTrace();
+    }
+}
--- a/test/java/util/TimeZone/TimeZoneTest.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/java/util/TimeZone/TimeZoneTest.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,8 +24,7 @@
 /*
  * @test
  * @bug 4028006 4044013 4096694 4107276 4107570 4112869 4130885 7039469 7126465 7158483
- *      8008577 8077685 8098547 8133321 8138716 8148446 8151876
- * @modules java.base/sun.util.resources
+ *      8008577 8077685 8098547 8133321 8138716 8148446 8151876 8228469
  * @library /java/text/testlib
  * @summary test TimeZone
  */
@@ -113,7 +112,7 @@
             new ZoneDescriptor("PRT", -240, false),
             new ZoneDescriptor("CNT", -210, true),
             new ZoneDescriptor("AGT", -180, false),
-            new ZoneDescriptor("BET", -180, true),
+            new ZoneDescriptor("BET", -180, false),
             // new ZoneDescriptor("CAT", -60, false), // Wrong:
             // As of bug 4130885, fix CAT (Central Africa)
             new ZoneDescriptor("CAT", 120, false), // Africa/Harare
--- a/test/javax/security/auth/kerberos/KerberosHashEqualsTest.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/javax/security/auth/kerberos/KerberosHashEqualsTest.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,7 +25,11 @@
  * @test
  * @bug 4641821
  * @summary hashCode() and equals() for KerberosKey and KerberosTicket
- * @ignore Must set up KDC and setup Kerberos configuration file
+ * @run main/manual KerberosHashEqualsTest
+ */
+
+/*
+ * Must setup KDC and Kerberos configuration file
  */
 
 import java.net.InetAddress;
--- a/test/javax/security/auth/kerberos/KerberosTixDateTest.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/javax/security/auth/kerberos/KerberosTixDateTest.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,15 +23,22 @@
 
 /*
  * @test
- * @bug 6659990
- * @summary test the immutability of the Date fields in KerberosTicket class.
- * @ignore Must set up KDC and setup Kerberos configuration file
+ * @bug 6659990 8147772
+ * @summary test the immutability of the Date fields in KerberosTicket class,
+ *          serialization, and behavior after being destroyed.
+ * @run main/manual KerberosTixDateTest
  */
 
-import java.net.InetAddress;
+/*
+ * Must setup KDC and Kerberos configuration file
+ */
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
 import java.util.Date;
 import java.io.*;
-import javax.security.auth.kerberos.KerberosKey;
+import javax.security.auth.RefreshFailedException;
 import javax.security.auth.kerberos.KerberosPrincipal;
 import javax.security.auth.kerberos.KerberosTicket;
 import sun.misc.BASE64Decoder;
@@ -75,6 +82,7 @@
 
         testDateImmutability(t, originalTime);
         testS11nCompatibility(t); // S11n: Serialization
+        testDestroy(t);
     }
 
     private static void checkTime(KerberosTicket kt, long timeValue) {
@@ -137,4 +145,30 @@
 
         System.out.println("S11nCompatibility Test Passed");
     }
+
+    private static void testDestroy(KerberosTicket t) throws Exception {
+        t.destroy();
+        if (!t.isDestroyed()) {
+            throw new RuntimeException("ticket should have been destroyed");
+        }
+        // Although these methods are meaningless, they can be called
+        for (Method m: KerberosTicket.class.getDeclaredMethods()) {
+            if (Modifier.isPublic(m.getModifiers())
+                    && m.getParameterTypes().length == 0) {
+                System.out.println("Testing " + m.getName() + "...");
+                try {
+                    m.invoke(t);
+                } catch (InvocationTargetException e) {
+                    Throwable cause = e.getCause();
+                    if (cause instanceof RefreshFailedException ||
+                            cause instanceof IllegalStateException) {
+                        // this is OK
+                    } else {
+                        throw e;
+                    }
+                }
+            }
+        }
+        System.out.println("Destroy Test Passed");
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/javax/security/auth/x500/X500Principal/Parse.java	Thu Feb 06 01:43:16 2020 +0000
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 7024771
+ * @summary various X500Principal DN parsing tests
+ */
+
+import javax.security.auth.x500.X500Principal;
+
+public class Parse {
+
+    private static TestCase[] testCases = {
+        new TestCase("CN=prefix\\<>suffix", false)
+    };
+
+    public static void main(String args[]) throws Exception {
+        for (int i = 0; i < testCases.length; i++) {
+            testCases[i].run();
+        }
+        System.out.println("Test completed ok.");
+    }
+}
+
+class TestCase {
+
+     private String name;
+     private boolean expectedResult;
+
+     TestCase(String name, boolean expectedResult) {
+         this.name = name;
+         this.expectedResult = expectedResult;
+     }
+
+     void run() throws Exception {
+         Exception f = null;
+         try {
+             System.out.println("Parsing: \"" + name + "\"");
+             new X500Principal(name);
+             if (expectedResult == false) {
+                 f = new Exception("Successfully parsed invalid name");
+             }
+         } catch (IllegalArgumentException e) {
+             if (expectedResult == true) {
+                 throw e;
+             }
+         }
+         if (f != null) {
+             throw f;
+         }
+     }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/javax/security/sasl/Sasl/DisabledMechanisms.java	Thu Feb 06 01:43:16 2020 +0000
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8200400
+ * @library /lib/testlibrary
+ * @run main/othervm DisabledMechanisms
+ *      DIGEST-MD5 DIGEST-MD5
+ * @run main/othervm -DdisabledMechanisms= DisabledMechanisms
+ *      DIGEST-MD5 DIGEST-MD5
+ * @run main/othervm -DdisabledMechanisms=DIGEST-MD5,NTLM DisabledMechanisms
+ *      null null
+ * @run main/othervm -DdisabledMechanisms=DIGEST-MD5 DisabledMechanisms
+ *      NTLM null
+ * @run main/othervm -DdisabledMechanisms=NTLM DisabledMechanisms
+ *      DIGEST-MD5 DIGEST-MD5
+ */
+
+import java.security.Security;
+import java.util.Collections;
+import java.util.Map;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.sasl.Sasl;
+import javax.security.sasl.SaslClient;
+import javax.security.sasl.SaslServer;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+
+import jdk.testlibrary.Asserts;
+
+public class DisabledMechanisms {
+
+    public static void main(String[] args) throws Exception {
+
+        String authorizationId = "username";
+        String protocol = "ldap";
+        String serverName = "server1";
+        Map props = Collections.emptyMap();
+
+        String disabled = System.getProperty("disabledMechanisms");
+        if (disabled != null) {
+            Security.setProperty("jdk.sasl.disabledMechanisms", disabled);
+        }
+
+        CallbackHandler callbackHandler = new CallbackHandler() {
+            @Override
+            public void handle(Callback[] callbacks) {
+                for (Callback cb : callbacks) {
+                    if (cb instanceof PasswordCallback) {
+                        ((PasswordCallback) cb).setPassword("password".toCharArray());
+                    }
+                }
+            }
+        };
+
+        SaslClient client = Sasl.createSaslClient(
+                new String[]{"DIGEST-MD5", "NTLM"}, authorizationId,
+                protocol, serverName, props, callbackHandler);
+        Asserts.assertEQ(client == null ? null : client.getMechanismName(),
+                args[0].equals("null") ? null : args[0]);
+
+        SaslServer server = Sasl.createSaslServer(
+                "DIGEST-MD5", protocol, serverName, props, callbackHandler);
+        Asserts.assertEQ(server == null ? null : server.getMechanismName(),
+                args[1].equals("null") ? null : args[1]);
+    }
+}
--- a/test/lib/testlibrary/jdk/testlibrary/FileUtils.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/lib/testlibrary/jdk/testlibrary/FileUtils.java	Thu Feb 06 01:43:16 2020 +0000
@@ -191,4 +191,3 @@
         return excs;
     }
 }
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/testlibrary/jdk/testlibrary/IOUtils.java	Thu Feb 06 01:43:16 2020 +0000
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.testlibrary;
+
+/**
+ * Defines useful I/O methods.
+ */
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Arrays;
+
+public final class IOUtils {
+
+    /*
+     * Prevent instantiation.
+     */
+    private IOUtils() {}
+
+    /**
+     * Read all bytes from <code>in</code>
+     * until EOF is detected.
+     * @param in input stream, must not be null
+     * @return bytes read
+     * @throws IOException Any IO error.
+     */
+    public static byte[] readFully(InputStream is) throws IOException {
+        byte[] output = {};
+        int pos = 0;
+        while (true) {
+            int bytesToRead;
+            if (pos >= output.length) { // Only expand when there's no room
+                bytesToRead = output.length + 1024;
+                if (output.length < pos + bytesToRead) {
+                    output = Arrays.copyOf(output, pos + bytesToRead);
+                }
+            } else {
+                bytesToRead = output.length - pos;
+            }
+            int cc = is.read(output, pos, bytesToRead);
+            if (cc < 0) {
+                if (output.length != pos) {
+                    output = Arrays.copyOf(output, pos);
+                }
+                break;
+            }
+            pos += cc;
+        }
+        return output;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/testlibrary/jdk/testlibrary/net/URIBuilder.java	Thu Feb 06 01:43:16 2020 +0000
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, Google and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.testlibrary.net;
+
+import java.net.InetAddress;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+
+public class URIBuilder {
+
+    public static URIBuilder newBuilder() {
+        return new URIBuilder();
+    }
+
+    private String scheme;
+    private String userInfo;
+    private String host;
+    private int port;
+    private String path;
+    private String query;
+    private String fragment;
+
+    private URIBuilder() {}
+
+    public URIBuilder scheme(String scheme) {
+        this.scheme = scheme;
+        return this;
+    }
+
+    public URIBuilder userInfo(String userInfo) {
+        this.userInfo = userInfo;
+        return this;
+    }
+
+    public URIBuilder host(String host) {
+        this.host = host;
+        return this;
+    }
+
+    public URIBuilder loopback() {
+        return host(InetAddress.getLoopbackAddress().getHostAddress());
+    }
+
+    public URIBuilder port(int port) {
+        this.port = port;
+        return this;
+    }
+
+    public URIBuilder path(String path) {
+        this.path = path;
+        return this;
+    }
+
+    public URIBuilder query(String query) {
+        this.query = query;
+        return this;
+    }
+
+    public URIBuilder fragment(String fragment) {
+        this.fragment = fragment;
+        return this;
+    }
+
+    public URI build() throws URISyntaxException {
+        return new URI(scheme, userInfo, host, port, path, query, fragment);
+    }
+
+    public URI buildUnchecked() {
+        try {
+            return build();
+        } catch (URISyntaxException e) {
+            throw new IllegalArgumentException(e);
+        }
+    }
+
+    public URL toURL() throws URISyntaxException, MalformedURLException {
+        return build().toURL();
+    }
+
+    public URL toURLUnchecked() {
+        try {
+            return toURL();
+        } catch (URISyntaxException | MalformedURLException e) {
+            throw new IllegalArgumentException(e);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/misc/IOUtils/ReadAllBytes.java	Thu Feb 06 01:43:16 2020 +0000
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.ByteArrayInputStream;
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Arrays;
+import java.util.Random;
+
+import jdk.testlibrary.RandomFactory;
+
+import sun.misc.IOUtils;
+
+/*
+ * @test
+ * @bug 8080835 8193832
+ * @library /lib/testlibrary
+ * @build jdk.testlibrary.*
+ * @run main ReadAllBytes
+ * @summary Basic test for IOUtils.readAllBytes
+ * @key randomness
+ */
+
+public class ReadAllBytes {
+
+    private static Random generator = RandomFactory.getRandom();
+
+    public static void main(String[] args) throws IOException {
+        test(new byte[]{});
+        test(new byte[]{1, 2, 3});
+        test(createRandomBytes(1024));
+        for (int shift : new int[] {13, 14, 15, 17}) {
+            for (int offset : new int[] {-1, 0, 1}) {
+                test(createRandomBytes((1 << shift) + offset));
+            }
+        }
+    }
+
+    static void test(byte[] expectedBytes) throws IOException {
+        int expectedLength = expectedBytes.length;
+        WrapperInputStream in = new WrapperInputStream(new ByteArrayInputStream(expectedBytes));
+        byte[] readBytes = IOUtils.readAllBytes(in);
+
+        int x;
+        byte[] tmp = new byte[10];
+        check((x = in.read()) == -1,
+              "Expected end of stream from read(), got " + x);
+        check((x = in.read(tmp)) == -1,
+              "Expected end of stream from read(byte[]), got " + x);
+        check((x = in.read(tmp, 0, tmp.length)) == -1,
+              "Expected end of stream from read(byte[], int, int), got " + x);
+        check(IOUtils.readAllBytes(in).length == 0,
+              "Expected readAllBytes to return empty byte array");
+        check(expectedLength == readBytes.length,
+              "Expected length " + expectedLength + ", got " + readBytes.length);
+        check(Arrays.equals(expectedBytes, readBytes),
+              "Expected[" + expectedBytes + "], got:[" + readBytes + "]");
+        check(!in.isClosed(), "Stream unexpectedly closed");
+    }
+
+    static byte[] createRandomBytes(int size) {
+        byte[] bytes = new byte[size];
+        generator.nextBytes(bytes);
+        return bytes;
+    }
+
+    static void check(boolean cond, Object ... failedArgs) {
+        if (cond)
+            return;
+        StringBuilder sb = new StringBuilder();
+        for (Object o : failedArgs)
+            sb.append(o);
+        throw new RuntimeException(sb.toString());
+    }
+
+    static class WrapperInputStream extends FilterInputStream {
+        private boolean closed;
+        WrapperInputStream(InputStream in) { super(in); }
+        @Override public void close() throws IOException { closed = true; in.close(); }
+        boolean isClosed() { return closed; }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/misc/IOUtils/ReadNBytes.java	Thu Feb 06 01:43:16 2020 +0000
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.ByteArrayInputStream;
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Arrays;
+import java.util.Random;
+import jdk.testlibrary.RandomFactory;
+
+import sun.misc.IOUtils;
+
+/*
+ * @test
+ * @bug 8080835 8139206
+ * @library /lib/testlibrary
+ * @build jdk.testlibrary.*
+ * @run main ReadNBytes
+ * @summary Basic test for IOUtils.readNBytes
+ * @key randomness
+ */
+
+public class ReadNBytes {
+
+    private static Random generator = RandomFactory.getRandom();
+
+    public static void main(String[] args) throws IOException {
+        test(new byte[]{1, 2, 3});
+        test(createRandomBytes(1024));
+        for (int shift : new int[] {13, 15, 17}) {
+            for (int offset : new int[] {-1, 0, 1}) {
+                test(createRandomBytes((1 << shift) + offset));
+            }
+        }
+
+        test(-1);
+        test(0);
+        for (int shift : new int[] {13, 15, 17}) {
+            for (int offset : new int[] {-1, 0, 1}) {
+                test((1 << shift) + offset);
+            }
+        }
+    }
+
+    static void test(byte[] inputBytes) throws IOException {
+        int length = inputBytes.length;
+        WrapperInputStream in = new WrapperInputStream(new ByteArrayInputStream(inputBytes));
+        byte[] readBytes = new byte[(length / 2) + 1];
+        int nread = IOUtils.readNBytes(in, readBytes, 0, readBytes.length);
+
+        int x;
+        byte[] tmp;
+        check(nread == readBytes.length,
+              "Expected number of bytes read: " + readBytes.length + ", got: " + nread);
+        check(Arrays.equals((tmp = Arrays.copyOf(inputBytes, nread)), readBytes),
+              "Expected[" + tmp + "], got:[" + readBytes + "]");
+        check(!in.isClosed(), "Stream unexpectedly closed");
+
+        // Read again
+        nread = IOUtils.readNBytes(in, readBytes, 0, readBytes.length);
+
+        check(nread == length - readBytes.length,
+              "Expected number of bytes read: " + (length - readBytes.length) + ", got: " + nread);
+        check(Arrays.equals((tmp = Arrays.copyOfRange(inputBytes, readBytes.length, length)),
+                            Arrays.copyOf(readBytes, nread)),
+              "Expected[" + tmp + "], got:[" + readBytes + "]");
+        // Expect end of stream
+        check((x = in.read()) == -1,
+              "Expected end of stream from read(), got " + x);
+        check((x = in.read(tmp)) == -1,
+              "Expected end of stream from read(byte[]), got " + x);
+        check((x = in.read(tmp, 0, tmp.length)) == -1,
+              "Expected end of stream from read(byte[], int, int), got " + x);
+        check((x = IOUtils.readNBytes(in, tmp, 0, tmp.length)) == 0,
+              "Expected end of stream, 0, from readNBytes(byte[], int, int), got " + x);
+        check(!in.isClosed(), "Stream unexpectedly closed");
+    }
+
+    static void test(int max) throws IOException {
+        byte[] subset1, subset2;
+        byte[] inputBytes = max <= 0 ? new byte[0] : createRandomBytes(max);
+        WrapperInputStream in =
+            new WrapperInputStream(new ByteArrayInputStream(inputBytes));
+
+        if (max < 0) {
+            try {
+                IOUtils.readNBytes(in, max);
+                check(false, "Expected IllegalArgumentException not thrown");
+            } catch (IllegalArgumentException iae) {
+                return;
+            }
+        } else if (max == 0) {
+            int x;
+            check((x = IOUtils.readNBytes(in, max).length) == 0,
+                  "Expected zero bytes, got " + x);
+            return;
+        }
+
+        int off = toIntExact(in.skip(generator.nextInt(max/2)));
+        int len = generator.nextInt(max - 1 - off);
+        byte[] readBytes = IOUtils.readNBytes(in, len);
+        check(readBytes.length == len,
+              "Expected " + len + " bytes, got " + readBytes.length);
+        subset1 = Arrays.copyOfRange(inputBytes, off, off + len);
+        subset2 = Arrays.copyOfRange(readBytes, 0, len);
+        check(Arrays.equals(subset1, subset2), "Expected[" + subset1 +
+              "], got:[" + readBytes + "]");
+
+        int remaining = max - (off + len);
+        readBytes = IOUtils.readNBytes(in, remaining);
+        check(readBytes.length == remaining,
+              "Expected " + remaining + "bytes, got " + readBytes.length);
+        subset1 = Arrays.copyOfRange(inputBytes, off + len, max);
+        subset2 = Arrays.copyOfRange(readBytes, 0, remaining);
+        check(Arrays.equals(subset1, subset2), "Expected[" + subset1 +
+          "], got:[" + readBytes + "]");
+
+        check(!in.isClosed(), "Stream unexpectedly closed");
+    }
+
+    static byte[] createRandomBytes(int size) {
+        byte[] bytes = new byte[size];
+        generator.nextBytes(bytes);
+        return bytes;
+    }
+
+    static void check(boolean cond, Object ... failedArgs) {
+        if (cond)
+            return;
+        StringBuilder sb = new StringBuilder();
+        for (Object o : failedArgs)
+            sb.append(o);
+        throw new RuntimeException(sb.toString());
+    }
+
+
+    static class WrapperInputStream extends FilterInputStream {
+        private boolean closed;
+        WrapperInputStream(InputStream in) { super(in); }
+        @Override public void close() throws IOException { closed = true; in.close(); }
+        boolean isClosed() { return closed; }
+    }
+
+    /**
+     * Returns the value of the {@code long} argument;
+     * throwing an exception if the value overflows an {@code int}.
+     *
+     * @param value the long value
+     * @return the argument as an int
+     * @throws ArithmeticException if the {@code argument} overflows an int
+     * @since 1.8
+     */
+    public static int toIntExact(long value) {
+        if ((int)value != value) {
+            throw new ArithmeticException("integer overflow");
+        }
+        return (int)value;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/net/www/protocol/http/TestTransparentNTLM.java	Thu Feb 06 01:43:16 2020 +0000
@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8225425
+ * @summary Verifies that transparent NTLM (on Windows) is not used by default,
+ *          and is used only when the relevant property is set.
+ * @requires os.family == "windows"
+ * @library ../../../../../lib/testlibrary
+ * @run testng/othervm
+ *      -Dtest.auth.succeed=false
+ *      TestTransparentNTLM
+ * @run testng/othervm
+ *      -Djdk.http.ntlm.transparentAuth=allHosts
+ *      -Dtest.auth.succeed=true
+ *      TestTransparentNTLM
+ * @run testng/othervm
+ *      -Djdk.http.ntlm.transparentAuth=blahblah
+ *      -Dtest.auth.succeed=false
+ *      TestTransparentNTLM
+ * @run testng/othervm
+ *      -Djdk.http.ntlm.transparentAuth=trustedHosts
+ *      -Dtest.auth.succeed=false
+ *      TestTransparentNTLM
+ */
+
+// Run with `trustedHosts` to exercise the native code, nothing more.
+
+import java.io.BufferedReader;
+import java.io.Closeable;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.HttpURLConnection;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.URL;
+import jdk.testlibrary.net.URIBuilder;
+import org.testng.annotations.AfterTest;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+import org.testng.SkipException;
+import static java.lang.System.out;
+import static java.net.Proxy.NO_PROXY;
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.fail;
+
+public class TestTransparentNTLM {
+
+    boolean succeed;  // true if authentication is expected to succeed
+    Server server;
+    URL url;
+
+    @Test
+    public void testNTLM() throws IOException {
+        out.println("connecting to url: " + url);
+        HttpURLConnection uc = (HttpURLConnection)url.openConnection(NO_PROXY);
+        int respCode = uc.getResponseCode();
+        out.println("received: " + respCode);
+
+        if (succeed) {
+            assertEquals(respCode, HttpURLConnection.HTTP_OK);
+            InputStream is = uc.getInputStream();
+            BufferedReader r = new BufferedReader(new InputStreamReader(is, UTF_8));
+            String body = r.readLine();
+            out.print("received body: ");
+            do {
+                out.print(body);
+                body = r.readLine();
+            } while (body != null);
+        } else {
+            assertEquals(respCode, HttpURLConnection.HTTP_UNAUTHORIZED);
+        }
+    }
+
+    static class Server extends Thread implements  Closeable {
+
+        static final InetAddress LOOPBACK = InetAddress.getLoopbackAddress();
+        final ServerSocket serverSocket;
+        final boolean expectAuthToSucceed;
+
+        Server(boolean expectAuthToSucceed) throws IOException {
+            super("TestTransparentNTLM-Server");
+            serverSocket = new ServerSocket();
+            serverSocket.bind(new InetSocketAddress(LOOPBACK, 0));
+            this.expectAuthToSucceed = expectAuthToSucceed;
+        }
+
+        int port() {
+            return serverSocket.getLocalPort();
+        }
+
+        static final String AUTH_REQUIRED =
+                "HTTP/1.1 401 Unauthorized\r\n" +
+                "Content-Length: 0\r\n" +
+                "Connection: close\r\n" +
+                "WWW-Authenticate: NTLM\r\n\r\n";
+
+        static final String AUTH_STAGE_TWO =
+                "HTTP/1.1 401 Unauthorized\r\n" +
+                "Content-Length: 0\r\n" +
+                "WWW-Authenticate: NTLM TlRMTVNTUAACAAAAAAAAACgAAAABggAAU3J2Tm9uY2UAAAAAAAAAAA==\r\n\r\n";
+
+        static final String AUTH_SUCCESSFUL =
+                "HTTP/1.1 200 OK\r\n" +
+                "Content-Length: 11\r\n\r\n" +
+                "Hello world";
+
+        @Override
+        public void run() {
+            try {
+                try (Socket s = serverSocket.accept()) {
+                    out.println("Server accepted connection - 1");
+                    readRequestHeaders(s.getInputStream());
+                    s.getOutputStream().write(AUTH_REQUIRED.getBytes(UTF_8));
+                }
+
+                if (expectAuthToSucceed) {
+                    // await the second follow up connection
+                    try (Socket s = serverSocket.accept()) {
+                        out.println("Server accepted connection - 2");
+                        readRequestHeaders(s.getInputStream());
+                        s.getOutputStream().write(AUTH_STAGE_TWO.getBytes(UTF_8));
+                        readRequestHeaders(s.getInputStream());
+                        s.getOutputStream().write(AUTH_SUCCESSFUL.getBytes(UTF_8));
+                    }
+                }
+            } catch (IOException e) {
+                fail("Unexpected exception", e);
+            }
+        }
+
+        @Override
+        public void close() throws IOException {
+            serverSocket.close();
+        }
+
+        static final byte[] REQUEST_END = new byte[] {'\r', '\n', '\r', '\n'};
+
+        // Read until the end of the HTTP request headers
+        static void readRequestHeaders(InputStream is) throws IOException {
+            int requestEndCount = 0, r;
+            while ((r = is.read()) != -1) {
+                if (r == REQUEST_END[requestEndCount]) {
+                    requestEndCount++;
+                    if (requestEndCount == 4) {
+                        break;
+                    }
+                } else {
+                    requestEndCount = 0;
+                }
+            }
+        }
+    }
+
+    @BeforeTest
+    public void setup() throws Exception {
+        succeed = System.getProperty("test.auth.succeed").equals("true");
+        if (succeed)
+            out.println("Expect client to succeed, with 200 Ok");
+        else
+            out.println("Expect client to fail, with 401 Unauthorized");
+
+        server = new Server(succeed);
+        server.start();
+        url = URIBuilder.newBuilder()
+                .scheme("http")
+                .loopback()
+                .port(server.port())
+                .path("/xxyyzz")
+                .toURL();
+    }
+
+    @AfterTest
+    public void teardown() throws Exception {
+        server.close();
+        server.join();
+    }
+}
--- a/test/sun/security/krb5/ConfPlusProp.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/sun/security/krb5/ConfPlusProp.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,6 +25,7 @@
  * @bug 6857795
  * @bug 6858589
  * @bug 6972005
+ * @compile -XDignore.symbol.file ConfPlusProp.java
  * @run main/othervm ConfPlusProp
  * @summary krb5.conf ignored if system properties on realm and kdc are provided
  */
@@ -81,7 +82,7 @@
         check("R1", "k1");
         check("R2", "old");
         check("R3", null);
-        if (!config.getDefault("forwardable", "libdefaults").equals("well")) {
+        if (!config.get("libdefaults", "forwardable").equals("well")) {
             throw new Exception("Extra config error");
         }
 
@@ -95,7 +96,7 @@
         check("R2", "old");
         check("R3", null);
 
-        if (config.getDefault("forwardable", "libdefaults") != null) {
+        if (config.get("libdefaults", "forwardable") != null) {
             throw new Exception("Extra config error");
         }
 
@@ -112,7 +113,7 @@
         check("R1", "k1");
         check("R2", "k2");
         check("R3", "k2");
-        if (!config.getDefault("forwardable", "libdefaults").equals("well")) {
+        if (!config.get("libdefaults", "forwardable").equals("well")) {
             throw new Exception("Extra config error");
         }
 
@@ -126,7 +127,7 @@
         check("R2", "k2");
         check("R3", "k2");
 
-        if (config.getDefault("forwardable", "libdefaults") != null) {
+        if (config.get("libdefaults", "forwardable") != null) {
             throw new Exception("Extra config error");
         }
     }
--- a/test/sun/security/krb5/DnsFallback.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/sun/security/krb5/DnsFallback.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,12 +27,23 @@
  * @summary fix dns_fallback parse error, and use dns by default
  */
 
-import sun.security.krb5.*;
 import java.io.*;
+import java.lang.reflect.Method;
+import sun.security.krb5.Config;
 
 public class DnsFallback {
+
+    static Method useDNS_Realm;
+    static Method useDNS_KDC;
+
     public static void main(String[] args) throws Exception {
 
+        useDNS_Realm = Config.class.getDeclaredMethod("useDNS_Realm");
+        useDNS_Realm.setAccessible(true);
+        useDNS_KDC = Config.class.getDeclaredMethod("useDNS_KDC");
+        useDNS_KDC.setAccessible(true);
+
+
         // for 6673164
         check("true", "true", true, true);
         check("false", "true", false, false);
@@ -59,24 +70,30 @@
      * @param k expected useDNS_KDC
      */
     static void check(String u, String f, boolean r, boolean k)
-             throws Exception {
-        FileOutputStream fo = new FileOutputStream("dnsfallback.conf");
-        StringBuffer sb = new StringBuffer();
-        sb.append("[libdefaults]\n");
-	if (u != null) {
-	    sb.append("dns_lookup_realm=" + u);
-	    sb.append("dns_lookup_kdc=" + u);
+            throws Exception {
+
+        try (PrintStream ps =
+                new PrintStream(new FileOutputStream("dnsfallback.conf"))) {
+            ps.println("[libdefaults]\n");
+            if (u != null) {
+                ps.println("dns_lookup_realm=" + u);
+                ps.println("dns_lookup_kdc=" + u);
+            }
+            if (f != null) {
+                ps.println("dns_fallback=" + f);
+            }
         }
-	if (f != null) {
-	    sb.append("dns_fallback=" + f);
-        }
-        fo.write(sb.toString().getBytes());
-        fo.close();
+
         System.setProperty("java.security.krb5.conf", "dnsfallback.conf");
         Config.refresh();
         System.out.println("Testing " + u + ", " + f + ", " + r + ", " + k);
-        if (Config.getInstance().useDNS_Realm() != output) {
-            throw new Exception("Fail");
+
+        if (!useDNS_Realm.invoke(Config.getInstance()).equals(r)) {
+            throw new Exception("useDNS_Realm Fail");
+        }
+
+        if (!useDNS_KDC.invoke(Config.getInstance()).equals(k)) {
+            throw new Exception("useDNS_KDC Fail");
         }
     }
 }
--- a/test/sun/security/krb5/MicroTime.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/sun/security/krb5/MicroTime.java	Thu Feb 06 01:43:16 2020 +0000
@@ -22,7 +22,7 @@
  */
 /*
  * @test
- * @bug 6882687
+ * @bug 6882687 8011124
  * @summary KerberosTime too imprecise
  */
 
@@ -32,11 +32,11 @@
     public static void main(String[] args) throws Exception {
         // We count how many different KerberosTime values
         // can be acquired within one second.
-        KerberosTime t1 = new KerberosTime(true);
+        KerberosTime t1 = KerberosTime.now();
         KerberosTime last = t1;
         int count = 0;
         while (true) {
-            KerberosTime t2 = new KerberosTime(true);
+            KerberosTime t2 = KerberosTime.now();
             if (t2.getTime() - t1.getTime() > 1000) break;
             if (!last.equals(t2)) {
                 last = t2;
--- a/test/sun/security/krb5/ParseConfig.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/sun/security/krb5/ParseConfig.java	Thu Feb 06 01:43:16 2020 +0000
@@ -23,6 +23,7 @@
 /*
  * @test
  * @bug 6319046 8055045
+ * @compile -XDignore.symbol.file ParseConfig.java
  * @run main/othervm ParseConfig
  * @summary Problem with parsing krb5.conf
  */
@@ -38,7 +39,7 @@
 
         String sample = "kdc.example.com kdc2.example.com";
         for ( int i = 0; i < 4; i++ ) {
-            String expected = config.getDefault("kdc", "EXAMPLE_" + i + ".COM");
+            String expected = config.getAll("realms", "EXAMPLE_" + i + ".COM", "kdc");
             if (!sample.equals(expected)) {
                 throw new Exception("krb5.conf: unexpected kdc value \"" +
                         expected + "\"");
@@ -46,9 +47,9 @@
         }
 
         // JDK-8055045: IOOBE when reading an empty value
-        config.getDefault("empty1", "NOVAL.COM");
-        config.getDefault("empty2", "NOVAL.COM");
-        config.getDefault("quote1", "NOVAL.COM");
-        config.getDefault("quote2", "NOVAL.COM");
+        config.get("empty1", "NOVAL.COM");
+        config.get("empty2", "NOVAL.COM");
+        config.get("quote1", "NOVAL.COM");
+        config.get("quote2", "NOVAL.COM");
     }
 }
--- a/test/sun/security/krb5/auto/AcceptorSubKey.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/sun/security/krb5/auto/AcceptorSubKey.java	Thu Feb 06 01:43:16 2020 +0000
@@ -26,10 +26,10 @@
  * @bug 7077646
  * @summary gssapi wrap for CFX per-message tokens always set FLAG_ACCEPTOR_SUBKEY
  * @compile -XDignore.symbol.file AcceptorSubKey.java
- * @run main/othervm AcceptorSubKey
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock AcceptorSubKey 0
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock AcceptorSubKey 4
  */
 
-import java.util.Arrays;
 import sun.security.jgss.GSSUtil;
 
 // The basic krb5 test skeleton you can copy from
@@ -37,8 +37,14 @@
 
     public static void main(String[] args) throws Exception {
 
+        int expected = Integer.parseInt(args[0]);
+
         new OneKDC(null).writeJAASConf();
 
+        if (expected != 0) {
+            System.setProperty("sun.security.krb5.acceptor.subkey", "true");
+        }
+
         Context c, s;
         c = Context.fromJAAS("client");
         s = Context.fromJAAS("server");
@@ -53,8 +59,8 @@
 
         // FLAG_ACCEPTOR_SUBKEY is 4
         int flagOn = wrapped[2] & 4;
-        if (flagOn != 0) {
-            throw new Exception("Java GSS should not have set acceptor subkey");
+        if (flagOn != expected) {
+            throw new Exception("not expected");
         }
 
         s.dispose();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/security/krb5/auto/Addresses.java	Thu Feb 06 01:43:16 2020 +0000
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8031111
+ * @summary fix krb5 caddr
+ * @compile -XDignore.symbol.file Addresses.java
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock Addresses
+ */
+
+import sun.security.krb5.Config;
+
+import javax.security.auth.kerberos.KerberosTicket;
+import java.net.Inet4Address;
+import java.net.InetAddress;
+
+public class Addresses {
+
+    public static void main(String[] args) throws Exception {
+
+        KDC.saveConfig(OneKDC.KRB5_CONF, new OneKDC(null),
+                "noaddresses = false",
+                "extra_addresses = 10.0.0.10, 10.0.0.11 10.0.0.12");
+        Config.refresh();
+
+        KerberosTicket ticket =
+                Context.fromUserPass(OneKDC.USER, OneKDC.PASS, false)
+                        .s().getPrivateCredentials(KerberosTicket.class)
+                        .iterator().next();
+
+        InetAddress loopback = InetAddress.getLoopbackAddress();
+        InetAddress extra1 = InetAddress.getByName("10.0.0.10");
+        InetAddress extra2 = InetAddress.getByName("10.0.0.11");
+        InetAddress extra3 = InetAddress.getByName("10.0.0.12");
+
+        boolean loopbackFound = false;
+        boolean extra1Found = false;
+        boolean extra2Found = false;
+        boolean extra3Found = false;
+        boolean networkFound = false;
+
+        for (InetAddress ia: ticket.getClientAddresses()) {
+            System.out.println(ia);
+            if (ia.equals(loopback)) {
+                loopbackFound = true;
+                System.out.println("  loopback found");
+            } else if (ia.equals(extra1)) {
+                extra1Found = true;
+                System.out.println("  extra1 found");
+            } else if (ia.equals(extra2)) {
+                extra2Found = true;
+                System.out.println("  extra2 found");
+            } else if (ia.equals(extra3)) {
+                extra3Found = true;
+                System.out.println("  extra3 found");
+            } else if (ia instanceof Inet4Address) {
+                networkFound = true;
+                System.out.println("  another address (" + ia +
+                        "), assumed real network");
+            }
+        }
+
+        if (!loopbackFound || !networkFound
+                || !extra1Found || !extra2Found || !extra3Found ) {
+            throw new Exception();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/security/krb5/auto/AddressesAndNameType.java	Thu Feb 06 01:43:16 2020 +0000
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4501327 4868379 8039132
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock AddressesAndNameType 1
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock AddressesAndNameType 2
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock AddressesAndNameType 3
+ * @summary noaddresses settings and server name type
+ */
+
+import java.net.InetAddress;
+import java.util.Set;
+import sun.security.krb5.Config;
+
+import javax.security.auth.kerberos.KerberosPrincipal;
+import javax.security.auth.kerberos.KerberosTicket;
+
+public class AddressesAndNameType {
+
+    public static void main(String[] args)
+            throws Exception {
+
+        OneKDC kdc = new OneKDC(null);
+        kdc.writeJAASConf();
+
+        String extraLine;
+        switch (args[0]) {
+            case "1": extraLine = "noaddresses = false"; break;
+            case "2": extraLine = "noaddresses = true"; break;
+            default: extraLine = ""; break;
+        }
+
+        KDC.saveConfig(OneKDC.KRB5_CONF, kdc,
+                extraLine);
+        Config.refresh();
+
+        Context c = Context.fromUserPass(OneKDC.USER, OneKDC.PASS, false);
+        Set<KerberosTicket> tickets =
+                c.s().getPrivateCredentials(KerberosTicket.class);
+
+        if (tickets.isEmpty()) throw new Exception();
+        KerberosTicket ticket = tickets.iterator().next();
+        InetAddress[] addresses = ticket.getClientAddresses();
+
+        switch (args[0]) {
+            case "1":
+                if (addresses == null || addresses.length == 0) {
+                    throw new Exception("No addresses");
+                }
+                if (ticket.getServer().getNameType()
+                        != KerberosPrincipal.KRB_NT_SRV_INST) {
+                    throw new Exception(
+                            "Wrong type: " + ticket.getServer().getNameType());
+                }
+                break;
+            default:
+                if (addresses != null && addresses.length != 0) {
+                    throw new Exception("See addresses");
+                }
+                break;
+        }
+    }
+}
--- a/test/sun/security/krb5/auto/BadKdc1.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/sun/security/krb5/auto/BadKdc1.java	Thu Feb 06 01:43:16 2020 +0000
@@ -24,7 +24,7 @@
 /*
  * @test
  * @bug 6843127
- * @run main/othervm/timeout=300 BadKdc1
+ * @run main/othervm/timeout=300 -Dsun.net.spi.nameservice.provider.1=ns,mock BadKdc1
  * @summary krb5 should not try to access unavailable kdc too often
  */
 
--- a/test/sun/security/krb5/auto/BadKdc2.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/sun/security/krb5/auto/BadKdc2.java	Thu Feb 06 01:43:16 2020 +0000
@@ -24,7 +24,7 @@
 /*
  * @test
  * @bug 6843127
- * @run main/othervm/timeout=300 BadKdc2
+ * @run main/othervm/timeout=300 -Dsun.net.spi.nameservice.provider.1=ns,mock BadKdc2
  * @summary krb5 should not try to access unavailable kdc too often
  */
 
--- a/test/sun/security/krb5/auto/BadKdc3.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/sun/security/krb5/auto/BadKdc3.java	Thu Feb 06 01:43:16 2020 +0000
@@ -24,7 +24,7 @@
 /*
  * @test
  * @bug 6843127
- * @run main/othervm/timeout=300 BadKdc3
+ * @run main/othervm/timeout=300 -Dsun.net.spi.nameservice.provider.1=ns,mock BadKdc3
  * @summary krb5 should not try to access unavailable kdc too often
  */
 
--- a/test/sun/security/krb5/auto/BadKdc4.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/sun/security/krb5/auto/BadKdc4.java	Thu Feb 06 01:43:16 2020 +0000
@@ -24,7 +24,7 @@
 /*
  * @test
  * @bug 6843127
- * @run main/othervm/timeout=300 BadKdc4
+ * @run main/othervm/timeout=300 -Dsun.net.spi.nameservice.provider.1=ns,mock BadKdc4
  * @summary krb5 should not try to access unavailable kdc too often
  */
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/security/krb5/auto/Basic.java	Thu Feb 06 01:43:16 2020 +0000
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 7152176 8201627
+ * @summary More krb5 tests
+ * @compile -XDignore.symbol.file Basic.java
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock
+ *      -Dsun.security.krb5.acceptor.sequence.number.nonmutual=zero
+ *      Basic
+ */
+
+import sun.security.jgss.GSSUtil;
+
+// The basic krb5 test skeleton you can copy from
+public class Basic {
+
+    public static void main(String[] args) throws Exception {
+
+        new OneKDC(null).writeJAASConf();
+
+        Context c, s;
+        c = Context.fromJAAS("client");
+        s = Context.fromJAAS("server");
+
+        c.startAsClient(OneKDC.SERVER, GSSUtil.GSS_KRB5_MECH_OID);
+        c.x().requestMutualAuth(false);
+        s.startAsServer(GSSUtil.GSS_KRB5_MECH_OID);
+
+        Context.handshake(c, s);
+
+        Context.transmit("i say high --", c, s);
+        Context.transmit("   you say low", s, c);
+
+        s.dispose();
+        c.dispose();
+    }
+}
--- a/test/sun/security/krb5/auto/BasicKrb5Test.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/sun/security/krb5/auto/BasicKrb5Test.java	Thu Feb 06 01:43:16 2020 +0000
@@ -25,39 +25,41 @@
  * @test
  * @bug 6706974
  * @summary Add krb5 test infrastructure
- * @run main/othervm BasicKrb5Test
- * @run main/othervm BasicKrb5Test des-cbc-crc
- * @run main/othervm BasicKrb5Test des-cbc-md5
- * @run main/othervm BasicKrb5Test des3-cbc-sha1
- * @run main/othervm BasicKrb5Test aes128-cts
- * @run main/othervm BasicKrb5Test aes256-cts
- * @run main/othervm BasicKrb5Test rc4-hmac
- * @run main/othervm BasicKrb5Test -s
- * @run main/othervm BasicKrb5Test des-cbc-crc -s
- * @run main/othervm BasicKrb5Test des-cbc-md5 -s
- * @run main/othervm BasicKrb5Test des3-cbc-sha1 -s
- * @run main/othervm BasicKrb5Test aes128-cts -s
- * @run main/othervm BasicKrb5Test aes256-cts -s
- * @run main/othervm BasicKrb5Test rc4-hmac -s
- * @run main/othervm BasicKrb5Test -C
- * @run main/othervm BasicKrb5Test des-cbc-crc -C
- * @run main/othervm BasicKrb5Test des-cbc-md5 -C
- * @run main/othervm BasicKrb5Test des3-cbc-sha1 -C
- * @run main/othervm BasicKrb5Test aes128-cts -C
- * @run main/othervm BasicKrb5Test aes256-cts -C
- * @run main/othervm BasicKrb5Test rc4-hmac -C
- * @run main/othervm BasicKrb5Test -s -C
- * @run main/othervm BasicKrb5Test des-cbc-crc -s -C
- * @run main/othervm BasicKrb5Test des-cbc-md5 -s -C
- * @run main/othervm BasicKrb5Test des3-cbc-sha1 -s -C
- * @run main/othervm BasicKrb5Test aes128-cts -s -C
- * @run main/othervm BasicKrb5Test aes256-cts -s -C
- * @run main/othervm BasicKrb5Test rc4-hmac -s -C
+ * @compile -XDignore.symbol.file BasicKrb5Test.java
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock BasicKrb5Test
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock BasicKrb5Test des-cbc-crc
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock BasicKrb5Test des-cbc-md5
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock BasicKrb5Test des3-cbc-sha1
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock BasicKrb5Test aes128-cts
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock BasicKrb5Test aes256-cts
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock BasicKrb5Test rc4-hmac
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock BasicKrb5Test -s
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock BasicKrb5Test des-cbc-crc -s
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock BasicKrb5Test des-cbc-md5 -s
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock BasicKrb5Test des3-cbc-sha1 -s
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock BasicKrb5Test aes128-cts -s
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock BasicKrb5Test aes256-cts -s
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock BasicKrb5Test rc4-hmac -s
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock BasicKrb5Test -C
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock BasicKrb5Test des-cbc-crc -C
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock BasicKrb5Test des-cbc-md5 -C
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock BasicKrb5Test des3-cbc-sha1 -C
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock BasicKrb5Test aes128-cts -C
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock BasicKrb5Test aes256-cts -C
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock BasicKrb5Test rc4-hmac -C
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock BasicKrb5Test -s -C
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock BasicKrb5Test des-cbc-crc -s -C
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock BasicKrb5Test des-cbc-md5 -s -C
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock BasicKrb5Test des3-cbc-sha1 -s -C
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock BasicKrb5Test aes128-cts -s -C
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock BasicKrb5Test aes256-cts -s -C
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock BasicKrb5Test rc4-hmac -s -C
  */
 
 import org.ietf.jgss.GSSName;
 import sun.security.jgss.GSSUtil;
 import sun.security.krb5.Config;
+import sun.security.krb5.KrbException;
 import sun.security.krb5.internal.crypto.EType;
 
 /**
@@ -77,18 +79,16 @@
         String etype = null;
         for (String arg: args) {
             if (arg.equals("-s")) Context.usingStream = true;
-            else if(arg.equals("-C")) conf = false;
+            else if (arg.equals("-C")) conf = false;
             else etype = arg;
         }
 
         // Creates and starts the KDC. This line must be put ahead of etype check
         // since the check needs a krb5.conf.
-        new OneKDC(etype).writeJAASConf();
-
-        System.out.println("Testing etype " + etype);
-        if (etype != null && !EType.isSupported(Config.getInstance().getType(etype))) {
-            // aes256 is not enabled on all systems
-            System.out.println("Not supported.");
+        try {
+            new OneKDC(etype).writeJAASConf();
+        } catch (KrbException ke) {
+            System.out.println("Testing etype " + etype + "Not supported.");
             return;
         }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/security/krb5/auto/BasicProc.java	Thu Feb 06 01:43:16 2020 +0000
@@ -0,0 +1,328 @@
+/*
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8009977 8186884 8201627
+ * @summary A test to launch multiple Java processes using either Java GSS
+ *          or native GSS
+ * @library ../../../../java/security/testlibrary /lib/testlibrary
+ * @compile -XDignore.symbol.file BasicProc.java
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock BasicProc launcher
+ */
+
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.nio.file.attribute.PosixFilePermission;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.PropertyPermission;
+import java.util.Set;
+
+import jdk.testlibrary.Asserts;
+import org.ietf.jgss.Oid;
+import sun.security.krb5.Config;
+
+import javax.security.auth.PrivateCredentialPermission;
+
+/**
+ * Run this test automatically and test Java GSS with embedded KDC.
+ *
+ * Run with customized native.krb5.libs to test interop between Java GSS
+ * and native GSS, and native.kdc.path with a native KDC. For example,
+ * run the following command to test interop among Java, default native,
+ * MIT, and Heimdal krb5 libraries with the Heimdal KDC:
+ *
+ *    jtreg -Dnative.krb5.libs=j=,
+ *                             n=,
+ *                             k=/usr/local/krb5/lib/libgssapi_krb5.so,
+ *                             h=/space/install/heimdal/lib/libgssapi.so \
+ *          -Dnative.kdc.path=/usr/local/heimdal \
+ *          BasicProc.java
+ *
+ * Note: The first 4 lines should be concatenated to make a long system
+ * property value with no blank around ",". This comma-separated value
+ * has each element being name=libpath. The special name "j" means the
+ * Java library and libpath is ignored. Otherwise it means a native library,
+ * and libpath (can be empty) will be the value for the sun.security.jgss.lib
+ * system property. If this system property is not set, only the Java
+ * library will be tested.
+ */
+
+public class BasicProc {
+
+    private static final String CONF = "krb5.conf";
+    private static final String KTAB_S = "server.ktab";
+    private static final String KTAB_B = "backend.ktab";
+
+    private static final String HOST = "localhost";
+    private static final String SERVER = "server/" + HOST;
+    private static final String BACKEND = "backend/" + HOST;
+    private static final String USER = "user";
+    private static final char[] PASS = "password".toCharArray();
+    private static final String REALM = "REALM";
+
+    private static final int MSGSIZE = 1024;
+    private static final byte[] MSG = new byte[MSGSIZE];
+
+    public static void main(String[] args) throws Exception {
+
+        Oid oid = new Oid("1.2.840.113554.1.2.2");
+        byte[] token, msg;
+
+        switch (args[0]) {
+            case "launcher":
+                KDC kdc = KDC.create(REALM, HOST, 0, true);
+                try {
+                    kdc.addPrincipal(USER, PASS);
+                    kdc.addPrincipalRandKey("krbtgt/" + REALM);
+                    kdc.addPrincipalRandKey(SERVER);
+                    kdc.addPrincipalRandKey(BACKEND);
+
+                    // Native lib might do some name lookup
+                    KDC.saveConfig(CONF, kdc,
+                            "dns_lookup_kdc = no",
+                            "ticket_lifetime = 1h",
+                            "dns_lookup_realm = no",
+                            "dns_canonicalize_hostname = false",
+                            "forwardable = true");
+                    System.setProperty("java.security.krb5.conf", CONF);
+                    Config.refresh();
+                    kdc.writeKtab(KTAB_S, false, SERVER);
+                    kdc.writeKtab(KTAB_B, false, BACKEND);
+
+                    String[] tmp = System.getProperty("native.krb5.libs", "j=")
+                            .split(",");
+
+                    // Library paths. The 1st one is always null which means
+                    // Java, "" means the default native lib.
+                    String[] libs = new String[tmp.length];
+
+                    // Names for each lib above. Use in file names.
+                    String[] names = new String[tmp.length];
+
+                    boolean hasNative = false;
+
+                    for (int i = 0; i < tmp.length; i++) {
+                        if (tmp[i].isEmpty()) {
+                            throw new Exception("Invalid native.krb5.libs");
+                        }
+                        String[] pair = tmp[i].split("=", 2);
+                        names[i] = pair[0];
+                        if (!pair[0].equals("j")) {
+                            libs[i] = pair.length > 1 ? pair[1] : "";
+                            hasNative = true;
+                        }
+                    }
+
+                    if (hasNative) {
+                        kdc.kinit(USER, "base.ccache");
+                    }
+
+                    // Try the same lib first
+                    for (int i = 0; i < libs.length; i++) {
+                        once(names[i] + names[i] + names[i],
+                                libs[i], libs[i], libs[i]);
+                    }
+
+                    for (int i = 0; i < libs.length; i++) {
+                        for (int j = 0; j < libs.length; j++) {
+                            for (int k = 0; k < libs.length; k++) {
+                                if (i != j || i != k) {
+                                    once(names[i] + names[j] + names[k],
+                                            libs[i], libs[j], libs[k]);
+                                }
+                            }
+                        }
+                    }
+                } finally {
+                    kdc.terminate();
+                }
+                break;
+            case "client":
+                Context c = args[1].equals("n") ?
+                        Context.fromThinAir() :
+                        Context.fromUserPass(USER, PASS, false);
+                c.startAsClient(SERVER, oid);
+                c.x().requestCredDeleg(true);
+                c.x().requestMutualAuth(true);
+                Proc.binOut(c.take(new byte[0])); // AP-REQ
+                c.take(Proc.binIn()); // AP-REP
+                Proc.binOut(c.wrap(MSG, true));
+                Proc.binOut(c.getMic(MSG));
+                break;
+            case "server":
+                Context s = args[1].equals("n") ?
+                        Context.fromThinAir() :
+                        Context.fromUserKtab(SERVER, KTAB_S, true);
+                s.startAsServer(oid);
+                token = Proc.binIn(); // AP-REQ
+                Proc.binOut(s.take(token)); // AP-REP
+                msg = s.unwrap(Proc.binIn(), true);
+                Asserts.assertTrue(Arrays.equals(msg, MSG));
+                s.verifyMic(Proc.binIn(), msg);
+                Context s2 = s.delegated();
+                s2.startAsClient(BACKEND, oid);
+                s2.x().requestMutualAuth(false);
+                Proc.binOut(s2.take(new byte[0])); // AP-REQ
+                msg = s2.unwrap(Proc.binIn(), true);
+                Asserts.assertTrue(Arrays.equals(msg, MSG));
+                s2.verifyMic(Proc.binIn(), msg);
+                break;
+            case "backend":
+                Context b = args[1].equals("n") ?
+                        Context.fromThinAir() :
+                        Context.fromUserKtab(BACKEND, KTAB_B, true);
+                b.startAsServer(oid);
+                token = b.take(Proc.binIn()); // AP-REQ
+                Asserts.assertTrue(token == null);
+                Proc.binOut(b.wrap(MSG, true));
+                Proc.binOut(b.getMic(MSG));
+                break;
+        }
+    }
+
+    /**
+     * One test run.
+     *
+     * @param label test label
+     * @param lc lib of client
+     * @param ls lib of server
+     * @param lb lib of backend
+     */
+    private static void once(String label, String lc, String ls, String lb)
+            throws Exception {
+
+        Proc pc = proc(lc)
+                .args("client", lc == null ? "j" : "n")
+                .perm(new javax.security.auth.kerberos.ServicePermission(
+                        "krbtgt/" + REALM + "@" + REALM, "initiate"))
+                .perm(new javax.security.auth.kerberos.ServicePermission(
+                        SERVER + "@" + REALM, "initiate"))
+                .perm(new javax.security.auth.kerberos.DelegationPermission(
+                        "\"" + SERVER + "@" + REALM + "\" " +
+                                "\"krbtgt/" + REALM + "@" + REALM + "\""))
+                .debug(label + "-C");
+        if (lc == null) {
+            // for Krb5LoginModule::promptForName
+            pc.perm(new PropertyPermission("user.name", "read"));
+        } else {
+            Files.copy(Paths.get("base.ccache"), Paths.get(label + ".ccache"));
+            Set<PosixFilePermission> perms = new HashSet<>();
+            perms.add(PosixFilePermission.OWNER_READ);
+            perms.add(PosixFilePermission.OWNER_WRITE);
+            Files.setPosixFilePermissions(Paths.get(label + ".ccache"),
+                                          Collections.unmodifiableSet(perms));
+            pc.env("KRB5CCNAME", label + ".ccache");
+            // Do not try system ktab if ccache fails
+            pc.env("KRB5_KTNAME", "none");
+        }
+        pc.start();
+
+        Proc ps = proc(ls)
+                .args("server", ls == null ? "j" : "n")
+                .perm(new javax.security.auth.kerberos.ServicePermission(
+                        SERVER + "@" + REALM, "accept"))
+                .perm(new javax.security.auth.kerberos.ServicePermission(
+                        BACKEND + "@" + REALM, "initiate"))
+                .debug(label + "-S");
+        if (ls == null) {
+            ps.perm(new PrivateCredentialPermission(
+                    "javax.security.auth.kerberos.KeyTab * \"*\"", "read"))
+                .perm(new java.io.FilePermission(KTAB_S, "read"));
+        } else {
+            ps.env("KRB5_KTNAME", KTAB_S);
+        }
+        ps.start();
+
+        Proc pb = proc(lb)
+                .args("backend", lb == null ? "j" : "n")
+                .perm(new javax.security.auth.kerberos.ServicePermission(
+                        BACKEND + "@" + REALM, "accept"))
+                .debug(label + "-B");
+        if (lb == null) {
+            pb.perm(new PrivateCredentialPermission(
+                    "javax.security.auth.kerberos.KeyTab * \"*\"", "read"))
+                .perm(new java.io.FilePermission(KTAB_B, "read"));
+        } else {
+            pb.env("KRB5_KTNAME", KTAB_B);
+        }
+        pb.start();
+
+        // Client and server
+        ps.println(pc.readData()); // AP-REQ
+        pc.println(ps.readData()); // AP-REP
+
+        ps.println(pc.readData()); // KRB-PRIV
+        ps.println(pc.readData()); // KRB-SAFE
+
+        // Server and backend
+        pb.println(ps.readData()); // AP-REQ
+
+        ps.println(pb.readData()); // KRB-PRIV
+        ps.println(pb.readData()); // KRB-SAFE
+
+        if ((pc.waitFor() | ps.waitFor() | pb.waitFor()) != 0) {
+            throw new Exception("Process failed");
+        }
+    }
+
+    /**
+     * A Proc for a child process.
+     *
+     * @param lib the library. Null is Java. "" is default native lib.
+     */
+    private static Proc proc(String lib) throws Exception {
+        Proc p = Proc.create("BasicProc")
+                .prop("java.security.manager", "")
+                .prop("sun.net.spi.nameservice.provider.1", "ns,mock")
+                .perm(new javax.security.auth.AuthPermission("doAs"));
+        if (lib != null) {
+            p.env("KRB5_CONFIG", CONF)
+                    .env("KRB5_TRACE", "/dev/stderr")
+                    .prop("sun.security.jgss.native", "true")
+                    .prop("sun.security.jgss.lib", lib)
+                    .prop("javax.security.auth.useSubjectCredsOnly", "false")
+                    .prop("sun.security.nativegss.debug", "true");
+            int pos = lib.lastIndexOf('/');
+            if (pos > 0) {
+                p.env("LD_LIBRARY_PATH", lib.substring(0, pos));
+                p.env("DYLD_LIBRARY_PATH", lib.substring(0, pos));
+            }
+        } else {
+            p.perm(new java.util.PropertyPermission(
+                            "sun.security.krb5.principal", "read"))
+                            // For Krb5LoginModule::login.
+                    .perm(new java.lang.RuntimePermission(
+                            "accessClassInPackage.sun.net.spi.nameservice"))
+                    .perm(new javax.security.auth.AuthPermission(
+                            "modifyPrincipals"))
+                    .perm(new javax.security.auth.AuthPermission(
+                            "modifyPrivateCredentials"))
+                    .prop("sun.security.krb5.debug", "true")
+                    .prop("java.security.krb5.conf", CONF);
+        }
+        return p;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/security/krb5/auto/BogusKDC.java	Thu Feb 06 01:43:16 2020 +0000
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.HashMap;
+import java.util.Map;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.login.LoginContext;
+import javax.security.auth.login.LoginException;
+
+/*
+ * @test
+ * @bug 4515853 8075297
+ * @summary Checks that Kerberos client tries slave KDC
+ *          if master KDC is not responding
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock BogusKDC
+ */
+public class BogusKDC {
+
+    static final String TEST_SRC = System.getProperty("test.src", ".");
+    static final String HOST = "localhost";
+    static final String NOT_EXISTING_HOST = "not.existing.host";
+    static final String REALM = "TEST.REALM";
+    static final String USER = "USER";
+    static final String USER_PRINCIPAL = USER + "@" + REALM;
+    static final String USER_PASSWORD = "password";
+    static final String KRBTGT_PRINCIPAL = "krbtgt/" + REALM;
+    static final String KRB5_CONF = "krb5.conf";
+    static final int WRONG_KDC_PORT = 21;
+
+    static final String KRB5_CONF_TEMPLATE = ""
+            + "[libdefaults]\n"
+            + "default_realm = TEST.REALM\n"
+            + "max_retries = 1\n"
+            + "\n"
+            + "[realms]\n"
+            + "TEST.REALM = {\n"
+            + "    kdc = %s\n"
+            + "    kdc = localhost:%d\n"
+            + "}";
+
+    public static void main(String[] args) throws LoginException, IOException {
+        Map<String, String> principals = new HashMap<>();
+        principals.put(USER_PRINCIPAL, USER_PASSWORD);
+        principals.put(KRBTGT_PRINCIPAL, null);
+
+        System.setProperty("java.security.krb5.conf", KRB5_CONF);
+
+        // start a local KDC
+        KDC kdc = KDC.startKDC(HOST, KRB5_CONF, REALM, principals, null, null);
+
+        System.setProperty("java.security.auth.login.config",
+                TEST_SRC + File.separator + "refreshKrb5Config.jaas");
+
+        CallbackHandler handler = new Helper.UserPasswordHandler(
+                USER, USER_PASSWORD);
+
+        // create a krb5 config with non-existing host for master KDC,
+        // and wrong port for slave KDC
+        try (PrintWriter w = new PrintWriter(new FileWriter(KRB5_CONF))) {
+            w.write(String.format(KRB5_CONF_TEMPLATE,
+                    KDC.KDCNameService.NOT_EXISTING_HOST, WRONG_KDC_PORT));
+            w.flush();
+        }
+
+        // login with not-refreshable config
+        try {
+            new LoginContext("NotRefreshable", handler).login();
+            throw new RuntimeException("Expected exception not thrown");
+        } catch (LoginException le) {
+            System.out.println("Expected login failure: " + le);
+        }
+
+        // create a krb5 config with non-existing host for master KDC,
+        // but correct port for slave KDC
+        try (PrintWriter w = new PrintWriter(new FileWriter(KRB5_CONF))) {
+            w.write(String.format(KRB5_CONF_TEMPLATE,
+                    KDC.KDCNameService.NOT_EXISTING_HOST, kdc.getPort()));
+            w.flush();
+        }
+
+        // login with not-refreshable config
+        try {
+            new LoginContext("NotRefreshable", handler).login();
+            throw new RuntimeException("Expected exception not thrown");
+        } catch (LoginException le) {
+            System.out.println("Expected login failure: " + le);
+        }
+
+        // login with refreshable config
+        new LoginContext("Refreshable", handler).login();
+
+        System.out.println("Test passed");
+    }
+}
--- a/test/sun/security/krb5/auto/CleanState.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/sun/security/krb5/auto/CleanState.java	Thu Feb 06 01:43:16 2020 +0000
@@ -24,7 +24,8 @@
 /*
  * @test
  * @bug 6716534
- * @run main/othervm CleanState
+ * @compile -XDignore.symbol.file CleanState.java
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock CleanState
  * @summary Krb5LoginModule has not cleaned temp info between authentication attempts
  */
 import com.sun.security.auth.module.Krb5LoginModule;
--- a/test/sun/security/krb5/auto/Context.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/sun/security/krb5/auto/Context.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -22,13 +22,20 @@
  */
 
 import com.sun.security.auth.module.Krb5LoginModule;
+import java.io.IOException;
 import java.security.Key;
 import java.security.PrivilegedActionException;
 import java.security.PrivilegedExceptionAction;
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.Set;
 import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
 import javax.security.auth.kerberos.KerberosKey;
 import javax.security.auth.kerberos.KerberosTicket;
 import javax.security.auth.login.LoginContext;
@@ -39,6 +46,10 @@
 import org.ietf.jgss.GSSName;
 import org.ietf.jgss.MessageProp;
 import org.ietf.jgss.Oid;
+import sun.security.jgss.krb5.Krb5Util;
+import sun.security.krb5.Credentials;
+import sun.security.krb5.internal.ccache.CredentialsCache;
+
 import com.sun.security.jgss.ExtendedGSSContext;
 import com.sun.security.jgss.InquireType;
 import com.sun.security.jgss.AuthorizationDataEntry;
@@ -96,6 +107,15 @@
     }
 
     /**
+     * No JAAS login at all, can be used to test JGSS without JAAS
+     */
+    public static Context fromThinAir() throws Exception {
+        Context out = new Context();
+        out.s = new Subject();
+        return out;
+    }
+
+    /**
      * Logins with a JAAS login config entry name
      */
     public static Context fromJAAS(final String name) throws Exception {
@@ -111,12 +131,15 @@
             String user, char[] pass, boolean storeKey) throws Exception {
         return fromUserPass(null, user, pass, storeKey);
     }
+
     /**
      * Logins with a username and a password, using Krb5LoginModule directly
+     * @param s existing subject, test multiple princ & creds for single subj
      * @param storeKey true if key should be saved, used on acceptor side
      */
     public static Context fromUserPass(Subject s,
-            String user, char[] pass, boolean storeKey) throws Exception {
+            final String user, final char[] pass,
+            boolean storeKey) throws Exception {
         Context out = new Context();
         out.name = user;
         out.s = s == null ? new Subject() : s;
@@ -124,24 +147,36 @@
         Map<String, String> map = new HashMap<>();
         Map<String, Object> shared = new HashMap<>();
 
+        if (storeKey) {
+            map.put("storeKey", "true");
+        }
+
         if (pass != null) {
-            map.put("useFirstPass", "true");
-            shared.put("javax.security.auth.login.name", user);
-            shared.put("javax.security.auth.login.password", pass);
+            krb5.initialize(out.s, new CallbackHandler() {
+                @Override
+                public void handle(Callback[] callbacks)
+                        throws IOException, UnsupportedCallbackException {
+                    for (Callback cb: callbacks) {
+                        if (cb instanceof NameCallback) {
+                            ((NameCallback)cb).setName(user);
+                        } else if (cb instanceof PasswordCallback) {
+                            ((PasswordCallback)cb).setPassword(pass);
+                        }
+                    }
+                }
+            }, shared, map);
         } else {
             map.put("doNotPrompt", "true");
             map.put("useTicketCache", "true");
             if (user != null) {
                 map.put("principal", user);
             }
-        }
-        if (storeKey) {
-            map.put("storeKey", "true");
+            krb5.initialize(out.s, null, shared, map);
         }
 
-        krb5.initialize(out.s, null, shared, map);
         krb5.login();
         krb5.commit();
+
         return out;
     }
 
@@ -157,6 +192,7 @@
         Krb5LoginModule krb5 = new Krb5LoginModule();
         Map<String, String> map = new HashMap<>();
 
+        map.put("isInitiator", "false");
         map.put("doNotPrompt", "true");
         map.put("useTicketCache", "false");
         map.put("useKeyTab", "true");
@@ -388,18 +424,21 @@
                     out = me.x.wrap(input, 0, input.length, p1);
                 }
                 System.out.println(printProp(p1));
+                if ((x.getConfState() && privacy) != p1.getPrivacy()) {
+                    throw new Exception("unexpected privacy status");
+                }
                 return out;
             }
         }, t);
     }
 
-    public byte[] unwrap(byte[] t, final boolean privacy)
+    public byte[] unwrap(byte[] t, final boolean privacyExpected)
             throws Exception {
         return doAs(new Action() {
             @Override
             public byte[] run(Context me, byte[] input) throws Exception {
-                System.out.printf("unwrap %s privacy from %s: ", privacy?"with":"without", me.name);
-                MessageProp p1 = new MessageProp(0, privacy);
+                System.out.printf("unwrap from %s", me.name);
+                MessageProp p1 = new MessageProp(0, true);
                 byte[] bytes;
                 if (usingStream) {
                     ByteArrayOutputStream os = new ByteArrayOutputStream();
@@ -409,6 +448,9 @@
                     bytes = me.x.unwrap(input, 0, input.length, p1);
                 }
                 System.out.println(printProp(p1));
+                if (p1.getPrivacy() != privacyExpected) {
+                    throw new Exception("Unexpected privacy: " + p1.getPrivacy());
+                }
                 return bytes;
             }
         }, t);
@@ -450,6 +492,10 @@
                             p1);
                 }
                 System.out.println(printProp(p1));
+                if (p1.isUnseqToken() || p1.isOldToken()
+                        || p1.isDuplicateToken() || p1.isGapToken()) {
+                    throw new Exception("Wrong sequence number detected");
+                }
                 return null;
             }
         }, t);
@@ -465,13 +511,27 @@
      * @param s2 the receiver
      * @throws java.lang.Exception If anything goes wrong
      */
-    static public void transmit(final String message, final Context s1,
+    static public void transmit(String message, final Context s1,
+                                final Context s2) throws Exception {
+        transmit(message.getBytes(), s1, s2);
+    }
+
+    /**
+     * Transmits a message from one Context to another. The sender wraps the
+     * message and sends it to the receiver. The receiver unwraps it, creates
+     * a MIC of the clear text and sends it back to the sender. The sender
+     * verifies the MIC against the message sent earlier.
+     * @param messageBytes the message
+     * @param s1 the sender
+     * @param s2 the receiver
+     * @throws java.lang.Exception If anything goes wrong
+     */
+    static public void transmit(byte[] messageBytes, final Context s1,
             final Context s2) throws Exception {
-        final byte[] messageBytes = message.getBytes();
         System.out.printf("-------------------- TRANSMIT from %s to %s------------------------\n",
                 s1.name, s2.name);
         byte[] wrapped = s1.wrap(messageBytes, true);
-        byte[] unwrapped = s2.unwrap(wrapped, true);
+        byte[] unwrapped = s2.unwrap(wrapped, s2.x.getConfState());
         if (!Arrays.equals(messageBytes, unwrapped)) {
             throw new Exception("wrap/unwrap mismatch");
         }
@@ -523,6 +583,32 @@
     }
 
     /**
+     * Saves the tickets to a ccache file.
+     *
+     * @param file pathname of the ccache file
+     * @return true if created, false otherwise.
+     */
+    public boolean ccache(String file) throws Exception {
+        Set<KerberosTicket> tickets
+                = s.getPrivateCredentials(KerberosTicket.class);
+        if (tickets != null && !tickets.isEmpty()) {
+            CredentialsCache cc = null;
+            for (KerberosTicket t : tickets) {
+                Credentials cred = Krb5Util.ticketToCreds(t);
+                if (cc == null) {
+                    cc = CredentialsCache.create(cred.getClient(), file);
+                }
+                cc.update(cred.toCCacheCreds());
+            }
+            if (cc != null) {
+                cc.save();
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
      * Handshake (security context establishment process) between two Contexts
      * @param c the initiator
      * @param s the acceptor
@@ -530,9 +616,10 @@
      */
     static public void handshake(final Context c, final Context s) throws Exception {
         byte[] t = new byte[0];
-        while (!c.x.isEstablished() || !s.x.isEstablished()) {
-            t = c.take(t);
-            t = s.take(t);
+        while (true) {
+            if (t != null || !c.x.isEstablished()) t = c.take(t);
+            if (t != null || !s.x.isEstablished()) t = s.take(t);
+            if (c.x.isEstablished() && s.x.isEstablished()) break;
         }
     }
 }
--- a/test/sun/security/krb5/auto/CrossRealm.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/sun/security/krb5/auto/CrossRealm.java	Thu Feb 06 01:43:16 2020 +0000
@@ -24,7 +24,8 @@
 /*
  * @test
  * @bug 6706974
- * @run main/othervm CrossRealm
+ * @compile -XDignore.symbol.file CrossRealm.java
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock CrossRealm
  * @summary Add krb5 test infrastructure
  */
 import java.io.File;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/security/krb5/auto/DiffSaltParams.java	Thu Feb 06 01:43:16 2020 +0000
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8186831
+ * @summary Kerberos ignores PA-DATA with a non-null s2kparams
+ * @compile -XDignore.symbol.file DiffSaltParams.java
+ * @run main/othervm -Dsun.security.krb5.debug=true -Dsun.net.spi.nameservice.provider.1=ns,mock DiffSaltParams
+ */
+
+public class DiffSaltParams {
+
+    public static void main(String[] args) throws Exception {
+
+        OneKDC kdc = new OneKDC(null).writeJAASConf();
+        kdc.addPrincipal("user1", "user1pass".toCharArray(),
+                "hello", new byte[]{0, 0, 1, 0});
+        kdc.addPrincipal("user2", "user2pass".toCharArray(),
+                "hello", null);
+        kdc.addPrincipal("user3", "user3pass".toCharArray(),
+                null, new byte[]{0, 0, 1, 0});
+        kdc.addPrincipal("user4", "user4pass".toCharArray());
+
+        Context.fromUserPass("user1", "user1pass".toCharArray(), true);
+        Context.fromUserPass("user2", "user2pass".toCharArray(), true);
+        Context.fromUserPass("user3", "user3pass".toCharArray(), true);
+        Context.fromUserPass("user4", "user4pass".toCharArray(), true);
+    }
+}
--- a/test/sun/security/krb5/auto/DupEtypes.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/sun/security/krb5/auto/DupEtypes.java	Thu Feb 06 01:43:16 2020 +0000
@@ -26,14 +26,15 @@
  * @bug 7067974
  * @summary multiple ETYPE-INFO-ENTRY with same etype and different salt
  * @compile -XDignore.symbol.file DupEtypes.java
- * @run main/othervm DupEtypes 1
- * @run main/othervm DupEtypes 2
- * @run main/othervm/fail DupEtypes 3
- * @run main/othervm DupEtypes 4
- * @run main/othervm DupEtypes 5
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock DupEtypes 1
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock DupEtypes 2
+ * @run main/othervm/fail -Dsun.net.spi.nameservice.provider.1=ns,mock DupEtypes 3
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock DupEtypes 4
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock DupEtypes 5
  */
 
 import sun.security.jgss.GSSUtil;
+import sun.security.krb5.Config;
 
 public class DupEtypes {
 
@@ -42,6 +43,14 @@
         OneKDC kdc = new OneKDC(null);
         kdc.writeJAASConf();
 
+        KDC.saveConfig(OneKDC.KRB5_CONF, kdc,
+                "default_keytab_name = " + OneKDC.KTAB,
+                "allow_weak_crypto = true");
+        Config.refresh();
+
+        // Rewrite to include DES keys
+        kdc.writeKtab(OneKDC.KTAB);
+
         // Different test cases, read KDC.processAsReq for details
         kdc.setOption(KDC.Option.DUP_ETYPE, Integer.parseInt(args[0]));
 
--- a/test/sun/security/krb5/auto/DynamicKeytab.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/sun/security/krb5/auto/DynamicKeytab.java	Thu Feb 06 01:43:16 2020 +0000
@@ -24,7 +24,8 @@
 /*
  * @test
  * @bug 6894072
- * @run main/othervm DynamicKeytab
+ * @compile -XDignore.symbol.file DynamicKeytab.java
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock DynamicKeytab
  * @summary always refresh keytab
  */
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/security/krb5/auto/EmptyPassword.java	Thu Feb 06 01:43:16 2020 +0000
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 6879540
+ * @summary enable empty password for kerberos 5
+ * @compile -XDignore.symbol.file EmptyPassword.java
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock EmptyPassword
+ */
+
+public class EmptyPassword {
+
+    public static void main(String[] args)
+            throws Exception {
+
+        OneKDC kdc = new OneKDC("aes128-cts");
+        kdc.addPrincipal("empty", "".toCharArray());
+
+        Context c = Context.fromUserPass("empty", "".toCharArray(), false);
+        c.status();
+    }
+}
+
--- a/test/sun/security/krb5/auto/FileKeyTab.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/sun/security/krb5/auto/FileKeyTab.java	Thu Feb 06 01:43:16 2020 +0000
@@ -26,7 +26,7 @@
  * @bug 7152121
  * @summary Krb5LoginModule no longer handles keyTabNames with "file:" prefix
  * @compile -XDignore.symbol.file FileKeyTab.java
- * @run main/othervm FileKeyTab
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock FileKeyTab
  */
 
 import java.io.File;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/security/krb5/auto/Forwarded.java	Thu Feb 06 01:43:16 2020 +0000
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8031111
+ * @summary fix krb5 caddr
+ * @compile -XDignore.symbol.file Forwarded.java
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock Forwarded
+ */
+
+import sun.security.jgss.GSSUtil;
+import sun.security.krb5.internal.KDCOptions;
+import sun.security.krb5.internal.KDCReqBody;
+import sun.security.krb5.internal.TGSReq;
+
+public class Forwarded {
+
+    public static void main(String[] args) throws Exception {
+
+        new OneKDC(null).setOption(KDC.Option.CHECK_ADDRESSES, true);
+
+        Context c;
+        c = Context.fromUserPass(OneKDC.USER, OneKDC.PASS, false);
+
+        c.startAsClient(OneKDC.SERVER, GSSUtil.GSS_KRB5_MECH_OID);
+        c.x().requestCredDeleg(true);
+
+        c.take(new byte[0]);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/security/krb5/auto/GSS.java	Thu Feb 06 01:43:16 2020 +0000
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 7152176
+ * @summary More krb5 tests
+ * @compile -XDignore.symbol.file GSS.java
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock GSS
+ */
+
+import sun.security.jgss.GSSUtil;
+
+// Testing JGSS without JAAS
+public class GSS {
+
+    public static void main(String[] args) throws Exception {
+
+        new OneKDC(null).writeJAASConf();
+
+        Context c, s;
+        c = Context.fromThinAir();
+        s = Context.fromThinAir();
+
+        // This is the only setting needed for JGSS without JAAS. The default
+        // JAAS config entries are already created by OneKDC.
+        System.setProperty("javax.security.auth.useSubjectCredsOnly", "false");
+
+        c.startAsClient(OneKDC.SERVER, GSSUtil.GSS_KRB5_MECH_OID);
+        s.startAsServer(GSSUtil.GSS_KRB5_MECH_OID);
+
+        Context.handshake(c, s);
+
+        Context.transmit("i say high --", c, s);
+        Context.transmit("   you say low", s, c);
+
+        s.dispose();
+        c.dispose();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/security/krb5/auto/Helper.java	Thu Feb 06 01:43:16 2020 +0000
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+
+public class Helper {
+
+    static class UserPasswordHandler implements CallbackHandler {
+
+        private final String name;
+        private final String password;
+
+        UserPasswordHandler(String name, String password) {
+            this.name = name;
+            this.password = password;
+        }
+
+        @Override
+        public void handle(Callback[] callbacks)
+                throws UnsupportedCallbackException {
+            for (Callback callback : callbacks) {
+                if (callback instanceof PasswordCallback) {
+                    ((PasswordCallback) callback).setPassword(
+                            password.toCharArray());
+                } else if (callback instanceof NameCallback) {
+                    ((NameCallback)callback).setName(name);
+                } else {
+                    throw new UnsupportedCallbackException(callback);
+                }
+            }
+        }
+    }
+}
--- a/test/sun/security/krb5/auto/HttpNegotiateServer.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/sun/security/krb5/auto/HttpNegotiateServer.java	Thu Feb 06 01:43:16 2020 +0000
@@ -24,7 +24,7 @@
 /*
  * @test
  * @bug 6578647 6829283
- * @run main/othervm HttpNegotiateServer
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock HttpNegotiateServer
  * @summary Undefined requesting URL in java.net.Authenticator.getPasswordAuthentication()
  * @summary HTTP/Negotiate: Authenticator triggered again when user cancels the first one
  */
--- a/test/sun/security/krb5/auto/IgnoreChannelBinding.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/sun/security/krb5/auto/IgnoreChannelBinding.java	Thu Feb 06 01:43:16 2020 +0000
@@ -24,7 +24,7 @@
 /*
  * @test
  * @bug 6851973
- * @run main/othervm IgnoreChannelBinding
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock IgnoreChannelBinding
  * @summary ignore incoming channel binding if acceptor does not set one
  */
 
--- a/test/sun/security/krb5/auto/KDC.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/sun/security/krb5/auto/KDC.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,22 +27,33 @@
 import java.net.*;
 import java.io.*;
 import java.lang.reflect.Method;
-import java.security.SecureRandom;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Paths;
 import java.util.*;
 import java.util.concurrent.*;
+
 import sun.net.spi.nameservice.NameService;
 import sun.net.spi.nameservice.NameServiceDescriptor;
 import sun.security.krb5.*;
 import sun.security.krb5.internal.*;
 import sun.security.krb5.internal.ccache.CredentialsCache;
+import sun.security.krb5.internal.crypto.EType;
 import sun.security.krb5.internal.crypto.KeyUsage;
 import sun.security.krb5.internal.ktab.KeyTab;
 import sun.security.util.DerInputStream;
 import sun.security.util.DerOutputStream;
 import sun.security.util.DerValue;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 /**
  * A KDC server.
+ *
+ * Note: By setting the system property native.kdc.path to a native
+ * krb5 installation, this class starts a native KDC with the
+ * given realm and host. It can also add new principals and save keytabs.
+ * Other features might not be available.
  * <p>
  * Features:
  * <ol>
@@ -67,10 +78,6 @@
  * <ul>
  * <li>test.kdc.save.ccache
  * </ul>
- * Support policies:
- * <ul>
- * <li>ok-as-delegate
- * </ul>
  * Issues and TODOs:
  * <ol>
  * <li> Generates krb5.conf to be used on another machine, currently the kdc is
@@ -124,10 +131,21 @@
  */
 public class KDC {
 
-    // Under the hood.
+    public static final int DEFAULT_LIFETIME = 39600;
+    public static final int DEFAULT_RENEWTIME = 86400;
+
+    // What etypes the KDC supports. Comma-separated strings. Null for all.
+    // Please note native KDCs might use different names.
+    private static final String SUPPORTED_ETYPES
+            = System.getProperty("kdc.supported.enctypes");
 
-    // The random generator to generate random keys (including session keys)
-    private static SecureRandom secureRandom = new SecureRandom();
+    // The native KDC
+    private final NativeKdc nativeKdc;
+
+    // The native KDC process
+    private Process kdcProc = null;
+
+    // Under the hood.
 
     // Principal db. principal -> pass. A case-insensitive TreeMap is used
     // so that even if the client provides a name with different case, the KDC
@@ -135,6 +153,17 @@
     private TreeMap<String,char[]> passwords = new TreeMap<>
             (String.CASE_INSENSITIVE_ORDER);
 
+    // Non default salts. Precisely, there should be different salts for
+    // different etypes, pretend they are the same at the moment.
+    private TreeMap<String,String> salts = new TreeMap<>
+            (String.CASE_INSENSITIVE_ORDER);
+
+    // Non default s2kparams for newer etypes. Precisely, there should be
+    // different s2kparams for different etypes, pretend they are the same
+    // at the moment.
+    private TreeMap<String,byte[]> s2kparamses = new TreeMap<>
+            (String.CASE_INSENSITIVE_ORDER);
+
     // Realm name
     private String realm;
     // KDC
@@ -145,11 +174,15 @@
     private BlockingQueue<Job> q = new ArrayBlockingQueue<>(100);
     // Options
     private Map<Option,Object> options = new HashMap<>();
+    // Realm-specific krb5.conf settings
+    private List<String> conf = new ArrayList<>();
 
     private Thread thread1, thread2, thread3;
     DatagramSocket u1 = null;
     ServerSocket t1 = null;
 
+    public static enum KtabMode { APPEND, EXISTING };
+
     /**
      * Option names, to be expanded forever.
      */
@@ -178,17 +211,26 @@
          * Multiple ETYPE-INFO-ENTRY with same etype but different salt
          */
         DUP_ETYPE,
+        /**
+         * What backend server can be delegated to
+         */
+        OK_AS_DELEGATE,
+        /**
+         * If true, will check if TGS-REQ contains a non-null addresses field.
+         */
+        CHECK_ADDRESSES,
     };
 
-    static {
-        System.setProperty("sun.net.spi.nameservice.provider.1", "ns,mock");
-    }
+    //static {
+    //    System.setProperty("sun.net.spi.nameservice.provider.1", "ns,mock");
+    //}
 
     /**
      * A standalone KDC server.
      */
     public static void main(String[] args) throws Exception {
-        KDC kdc = create("RABBIT.HOLE", "kdc.rabbit.hole", 0, false);
+        int port = args.length > 0 ? Integer.parseInt(args[0]) : 0;
+        KDC kdc = create("RABBIT.HOLE", "kdc.rabbit.hole", port, false);
         kdc.addPrincipal("dummy", "bogus".toCharArray());
         kdc.addPrincipal("foo", "bar".toCharArray());
         kdc.addPrincipalRandKey("krbtgt/RABBIT.HOLE");
@@ -222,94 +264,114 @@
      * @return the running KDC instance
      * @throws java.io.IOException for any socket creation error
      */
-    public static KDC create(String realm, String kdc, int port, boolean asDaemon) throws IOException {
+    public static KDC create(String realm, String kdc, int port,
+                             boolean asDaemon) throws IOException {
         return new KDC(realm, kdc, port, asDaemon);
     }
 
     /**
      * Sets an option
      * @param key the option name
-     * @param obj the value
+     * @param value the value
      */
     public void setOption(Option key, Object value) {
-        options.put(key, value);
+        if (value == null) {
+            options.remove(key);
+        } else {
+            options.put(key, value);
+        }
     }
 
     /**
-     * Writes or appends KDC keys into a keytab. See doc for writeMultiKtab.
-     * @param append true if append, otherwise, overwrite.
-     */
-    private static void writeKtab0(String tab, boolean append, KDC... kdcs)
-            throws IOException, KrbException {
-        KeyTab ktab = append ? KeyTab.getInstance(tab) : KeyTab.create(tab);
-        for (KDC kdc: kdcs) {
-            for (String name : kdc.passwords.keySet()) {
-                char[] pass = kdc.passwords.get(name);
-                int kvno = 0;
-                if (Character.isDigit(pass[pass.length-1])) {
-                    kvno = pass[pass.length-1] - '0';
-                }
-                ktab.addEntry(new PrincipalName(name,
-                        name.indexOf('/') < 0 ?
-                            PrincipalName.KRB_NT_UNKNOWN :
-                            PrincipalName.KRB_NT_SRV_HST),
-                            pass,
-                            kvno,
-                            true);
-            }
-        }
-        ktab.save();
-    }
-
-    /**
-     * Writes all principals' keys from multiple KDCs into one keytab file.
-     * Note that the keys for the krbtgt principals will not be written.
+     * Writes or appends keys into a keytab.
      * <p>
-     * Attention: This method references krb5.conf settings. If you need to
-     * setup krb5.conf later, please call <code>Config.refresh()</code> after
-     * the new setting. For example:
+     * Attention: This is the most basic one of a series of methods below on
+     * keytab creation or modification. All these methods reference krb5.conf
+     * settings. If you need to modify krb5.conf or switch to another krb5.conf
+     * later, please call <code>Config.refresh()</code> again. For example:
      * <pre>
-     * KDC.writeKtab("/etc/kdc/ktab", kdc);  // Config is initialized,
+     * kdc.writeKtab("/etc/kdc/ktab", true);  // Config is initialized,
      * System.setProperty("java.security.krb5.conf", "/home/mykrb5.conf");
      * Config.refresh();
      * </pre>
-     *
      * Inside this method there are 2 places krb5.conf is used:
      * <ol>
      * <li> (Fatal) Generating keys: EncryptionKey.acquireSecretKeys
      * <li> (Has workaround) Creating PrincipalName
      * </ol>
-     * @param tab The keytab filename to write to.
+     * @param tab the keytab file name
+     * @param append true if append, otherwise, overwrite.
+     * @param names the names to write into, write all if names is empty
+     */
+    public void writeKtab(String tab, boolean append, String... names)
+            throws IOException, KrbException {
+        KeyTab ktab = null;
+        if (nativeKdc == null) {
+            ktab = append ? KeyTab.getInstance(tab) : KeyTab.create(tab);
+        }
+        Iterable<String> entries =
+                (names.length != 0) ? Arrays.asList(names): passwords.keySet();
+        for (String name : entries) {
+            if (name.indexOf('@') < 0) {
+                name = name + "@" + realm;
+            }
+            if (nativeKdc == null) {
+                char[] pass = passwords.get(name);
+                int kvno = 0;
+                if (Character.isDigit(pass[pass.length - 1])) {
+                    kvno = pass[pass.length - 1] - '0';
+                }
+                PrincipalName pn = new PrincipalName(name,
+                        name.indexOf('/') < 0 ?
+                                PrincipalName.KRB_NT_UNKNOWN :
+                                PrincipalName.KRB_NT_SRV_HST);
+                ktab.addEntry(pn,
+                              pass,
+                              kvno,
+                              true);
+            } else {
+                nativeKdc.ktadd(name, tab);
+            }
+        }
+        if (nativeKdc == null) {
+            ktab.save();
+        }
+    }
+
+    /**
+     * Writes all principals' keys from multiple KDCs into one keytab file.
      * @throws java.io.IOException for any file output error
      * @throws sun.security.krb5.KrbException for any realm and/or principal
      *         name error.
      */
     public static void writeMultiKtab(String tab, KDC... kdcs)
             throws IOException, KrbException {
-        writeKtab0(tab, false, kdcs);
+        KeyTab.create(tab).save();      // Empty the old keytab
+        appendMultiKtab(tab, kdcs);
     }
 
     /**
      * Appends all principals' keys from multiple KDCs to one keytab file.
-     * See writeMultiKtab for details.
      */
     public static void appendMultiKtab(String tab, KDC... kdcs)
             throws IOException, KrbException {
-        writeKtab0(tab, true, kdcs);
+        for (KDC kdc: kdcs) {
+            kdc.writeKtab(tab, true);
+        }
     }
 
     /**
      * Write a ktab for this KDC.
      */
     public void writeKtab(String tab) throws IOException, KrbException {
-        KDC.writeMultiKtab(tab, this);
+        writeKtab(tab, false);
     }
 
     /**
      * Appends keys in this KDC to a ktab.
      */
     public void appendKtab(String tab) throws IOException, KrbException {
-        KDC.appendMultiKtab(tab, this);
+        writeKtab(tab, true);
     }
 
     /**
@@ -319,10 +381,36 @@
      * @param pass the password for the principal
      */
     public void addPrincipal(String user, char[] pass) {
+        addPrincipal(user, pass, null, null);
+    }
+
+    /**
+     * Adds a new principal to this realm with a given password.
+     * @param user the principal's name. For a service principal, use the
+     *        form of host/f.q.d.n
+     * @param pass the password for the principal
+     * @param salt the salt, or null if a default value will be used
+     * @param s2kparams the s2kparams, or null if a default value will be used
+     */
+    public void addPrincipal(
+            String user, char[] pass, String salt, byte[] s2kparams) {
         if (user.indexOf('@') < 0) {
             user = user + "@" + realm;
         }
-        passwords.put(user, pass);
+        if (nativeKdc != null) {
+            if (!user.equals("krbtgt/" + realm)) {
+                nativeKdc.addPrincipal(user, new String(pass));
+            }
+            passwords.put(user, new char[0]);
+        } else {
+            passwords.put(user, pass);
+            if (salt != null) {
+                salts.put(user, salt);
+            }
+            if (s2kparams != null) {
+                s2kparamses.put(user, s2kparams);
+            }
+        }
     }
 
     /**
@@ -351,6 +439,13 @@
     }
 
     /**
+     * Add realm-specific krb5.conf setting
+     */
+    public void addConf(String s) {
+        conf.add(s);
+    }
+
+    /**
      * Writes a krb5.conf for one or more KDC that includes KDC locations for
      * each realm and the default realm name. You can also add extra strings
      * into the file. The method should be called like:
@@ -375,6 +470,7 @@
      * [realms]
      *   REALM.NAME = {
      *     kdc = host:port_number
+     *     # realm-specific settings
      *   }
      * </pre>
      *
@@ -410,27 +506,24 @@
      */
     public static void saveConfig(String file, KDC kdc, Object... more)
             throws IOException {
-        File f = new File(file);
         StringBuffer sb = new StringBuffer();
         sb.append("[libdefaults]\ndefault_realm = ");
         sb.append(kdc.realm);
         sb.append("\n");
-        for (Object o: more) {
+        for (Object o : more) {
             if (o instanceof String) {
                 sb.append(o);
                 sb.append("\n");
             }
         }
         sb.append("\n[realms]\n");
-        sb.append(realmLineForKDC(kdc));
-        for (Object o: more) {
+        sb.append(kdc.realmLine());
+        for (Object o : more) {
             if (o instanceof KDC) {
-                sb.append(realmLineForKDC((KDC)o));
+                sb.append(((KDC) o).realmLine());
             }
         }
-        FileOutputStream fos = new FileOutputStream(f);
-        fos.write(sb.toString().getBytes());
-        fos.close();
+        Files.write(Paths.get(file), sb.toString().getBytes());
     }
 
     /**
@@ -450,6 +543,7 @@
     private KDC(String realm, String kdc) {
         this.realm = realm;
         this.kdc = kdc;
+        this.nativeKdc = null;
     }
 
     /**
@@ -457,7 +551,9 @@
      */
     protected KDC(String realm, String kdc, int port, boolean asDaemon)
             throws IOException {
-        this(realm, kdc);
+        this.realm = realm;
+        this.kdc = kdc;
+        this.nativeKdc = NativeKdc.get(this);
         startServer(port, asDaemon);
     }
     /**
@@ -466,8 +562,9 @@
      */
     private static char[] randomPassword() {
         char[] pass = new char[32];
+        Random r = new Random();
         for (int i=0; i<31; i++)
-            pass[i] = (char)secureRandom.nextInt();
+            pass[i] = (char)('a' + r.nextInt(26));
         // The last char cannot be a number, otherwise, keyForUser()
         // believes it's a sign of kvno
         pass[31] = 'Z';
@@ -529,6 +626,9 @@
         if (p.getRealmString() == null) {
             pn = pn + "@" + getRealm();
         }
+        if (salts.containsKey(pn)) {
+            return salts.get(pn);
+        }
         if (passwords.containsKey(pn)) {
             try {
                 // Find the principal name with correct case.
@@ -546,6 +646,29 @@
     }
 
     /**
+     * Returns the s2kparams for the principal given the etype.
+     * @param p principal
+     * @param etype encryption type
+     * @return the s2kparams, might be null
+     */
+    protected byte[] getParams(PrincipalName p, int etype) {
+        switch (etype) {
+            case EncryptedData.ETYPE_AES128_CTS_HMAC_SHA1_96:
+            case EncryptedData.ETYPE_AES256_CTS_HMAC_SHA1_96:
+                String pn = p.toString();
+                if (p.getRealmString() == null) {
+                    pn = pn + "@" + getRealm();
+                }
+                if (s2kparamses.containsKey(pn)) {
+                    return s2kparamses.get(pn);
+                }
+                return new byte[] {0, 0, 0x10, 0};
+            default:
+                return null;
+        }
+    }
+
+    /**
      * Returns the key for a given principal of the given encryption type
      * @param p the principal
      * @param etype the encryption type
@@ -553,7 +676,7 @@
      * @return the key
      * @throws sun.security.krb5.KrbException for unknown/unsupported etype
      */
-    private EncryptionKey keyForUser(PrincipalName p, int etype, boolean server)
+    EncryptionKey keyForUser(PrincipalName p, int etype, boolean server)
             throws KrbException {
         try {
             // Do not call EncryptionKey.acquireSecretKeys(), otherwise
@@ -568,7 +691,7 @@
                 }
             }
             return new EncryptionKey(EncryptionKeyDotStringToKey(
-                    getPassword(p, server), getSalt(p), null, etype),
+                    getPassword(p, server), getSalt(p), getParams(p, etype), etype),
                     etype, kvno);
         } catch (KrbException ke) {
             throw ke;
@@ -577,53 +700,15 @@
         }
     }
 
-    private Map<String,String> policies = new HashMap<>();
-
-    public void setPolicy(String rule, String value) {
-        if (value == null) {
-            policies.remove(rule);
-        } else {
-            policies.put(rule, value);
-        }
-    }
     /**
-     * If the provided client/server pair matches a rule
-     *
-     * A system property named test.kdc.policy.RULE will be consulted.
-     * If it's unset, returns false. If its value is "", any pair is
-     * matched. Otherwise, it should contains the server name matched.
+     * Returns a KerberosTime.
      *
-     * TODO: client name is not used currently.
-     *
-     * @param c client name
-     * @param s server name
-     * @param rule rule name
-     * @return if a match is found
+     * @param offset offset from NOW in seconds
      */
-    private boolean configMatch(String c, String s, String rule) {
-        String policy = policies.get(rule);
-        boolean result = false;
-        if (policy == null) {
-            result = false;
-        } else if (policy.length() == 0) {
-            result = true;
-        } else {
-            String[] names = policy.split("\\s+");
-            for (String name: names) {
-                if (name.equals(s)) {
-                    result = true;
-                    break;
-                }
-            }
-        }
-        if (result) {
-            System.out.printf(">>>> Policy match result (%s vs %s on %s) %b\n",
-                    c, s, rule, result);
-        }
-        return result;
+    private static KerberosTime timeAfter(int offset) {
+        return new KerberosTime(new Date().getTime() + offset * 1000L);
     }
 
-
     /**
      * Processes an incoming request and generates a response.
      * @param in the request
@@ -655,11 +740,14 @@
                     " sends TGS-REQ for " +
                     service);
             KDCReqBody body = tgsReq.reqBody;
-            int[] eTypes = KDCReqBodyDotEType(body);
+            int[] eTypes = filterSupported(KDCReqBodyDotEType(body));
+            if (eTypes.length == 0) {
+                throw new KrbException(Krb5.KDC_ERR_ETYPE_NOSUPP);
+            }
             int e2 = eTypes[0];     // etype for outgoing session key
             int e3 = eTypes[0];     // etype for outgoing ticket
 
-            PAData[] pas = kDCReqDotPAData(tgsReq);
+            PAData[] pas = tgsReq.pAData;
 
             Ticket tkt = null;
             EncTicketPart etp = null;
@@ -669,7 +757,6 @@
                 for (PAData pa: pas) {
                     if (pa.getType() == Krb5.PA_TGS_REQ) {
                         APReq apReq = new APReq(pa.getValue());
-                        EncryptedData ed = apReq.authenticator;
                         tkt = apReq.ticket;
                         int te = tkt.encPart.getEType();
                         EncryptionKey kkey = keyForUser(tkt.sname, te, true);
@@ -691,24 +778,38 @@
             EncryptionKey key = generateRandomKey(e2);
 
             // Check time, TODO
+            KerberosTime from = body.from;
             KerberosTime till = body.till;
+            if (from == null || from.isZero()) {
+                from = timeAfter(0);
+            }
+            KerberosTime rtime = body.rtime;
             if (till == null) {
                 throw new KrbException(Krb5.KDC_ERR_NEVER_VALID); // TODO
             } else if (till.isZero()) {
-                till = new KerberosTime(new Date().getTime() + 1000 * 3600 * 11);
+                till = timeAfter(DEFAULT_LIFETIME);
+            }
+            if (rtime == null && body.kdcOptions.get(KDCOptions.RENEWABLE)) {
+                rtime = timeAfter(DEFAULT_RENEWTIME);
             }
 
             boolean[] bFlags = new boolean[Krb5.TKT_OPTS_MAX+1];
             if (body.kdcOptions.get(KDCOptions.FORWARDABLE)) {
                 bFlags[Krb5.TKT_OPTS_FORWARDABLE] = true;
             }
+            // We do not request for addresses for FORWARDED tickets
+            if (options.containsKey(Option.CHECK_ADDRESSES)
+                    && body.kdcOptions.get(KDCOptions.FORWARDED)
+                    && body.addresses != null) {
+                throw new KrbException(Krb5.KDC_ERR_BADOPTION);
+            }
             if (body.kdcOptions.get(KDCOptions.FORWARDED) ||
                     etp.flags.get(Krb5.TKT_OPTS_FORWARDED)) {
                 bFlags[Krb5.TKT_OPTS_FORWARDED] = true;
             }
             if (body.kdcOptions.get(KDCOptions.RENEWABLE)) {
                 bFlags[Krb5.TKT_OPTS_RENEWABLE] = true;
-                //renew = new KerberosTime(new Date().getTime() + 1000 * 3600 * 24 * 7);
+                //renew = timeAfter(3600 * 24 * 7);
             }
             if (body.kdcOptions.get(KDCOptions.PROXIABLE)) {
                 bFlags[Krb5.TKT_OPTS_PROXIABLE] = true;
@@ -720,24 +821,37 @@
                 bFlags[Krb5.TKT_OPTS_MAY_POSTDATE] = true;
             }
 
-            if (configMatch("", service.getNameString(), "ok-as-delegate")) {
+            String okAsDelegate = (String)options.get(Option.OK_AS_DELEGATE);
+            if (okAsDelegate != null && (
+                    okAsDelegate.isEmpty() ||
+                    okAsDelegate.contains(service.getNameString()))) {
                 bFlags[Krb5.TKT_OPTS_DELEGATE] = true;
             }
             bFlags[Krb5.TKT_OPTS_INITIAL] = true;
 
+            KerberosTime renewTill = etp.renewTill;
+            if (renewTill != null && body.kdcOptions.get(KDCOptions.RENEW)) {
+                // till should never pass renewTill
+                if (till.greaterThan(renewTill)) {
+                    till = renewTill;
+                }
+                if (System.getProperty("test.set.null.renew") != null) {
+                    // Testing 8186576, see NullRenewUntil.java.
+                    renewTill = null;
+                }
+            }
+
             TicketFlags tFlags = new TicketFlags(bFlags);
             EncTicketPart enc = new EncTicketPart(
                     tFlags,
                     key,
                     etp.cname,
                     new TransitedEncoding(1, new byte[0]),  // TODO
-                    new KerberosTime(new Date()),
-                    body.from,
-                    till, body.rtime,
-                    body.addresses != null  // always set caddr
-                            ? body.addresses
-                            : new HostAddresses(
-                                new InetAddress[]{InetAddress.getLocalHost()}),
+                    timeAfter(0),
+                    from,
+                    till, renewTill,
+                    body.addresses != null ? body.addresses
+                            : etp.caddr,
                     null);
             EncryptionKey skey = keyForUser(service, e3, true);
             if (skey == null) {
@@ -751,23 +865,21 @@
             );
             EncTGSRepPart enc_part = new EncTGSRepPart(
                     key,
-                    new LastReq(new LastReqEntry[]{
-                        new LastReqEntry(0, new KerberosTime(new Date().getTime() - 10000))
+                    new LastReq(new LastReqEntry[] {
+                        new LastReqEntry(0, timeAfter(-10))
                     }),
                     body.getNonce(),    // TODO: detect replay
-                    new KerberosTime(new Date().getTime() + 1000 * 3600 * 24),
+                    timeAfter(3600 * 24),
                     // Next 5 and last MUST be same with ticket
                     tFlags,
-                    new KerberosTime(new Date()),
-                    body.from,
-                    till, body.rtime,
+                    timeAfter(0),
+                    from,
+                    till, renewTill,
                     service,
-                    body.addresses != null  // always set caddr
-                            ? body.addresses
-                            : new HostAddresses(
-                                new InetAddress[]{InetAddress.getLocalHost()})
+                    body.addresses
                     );
-            EncryptedData edata = new EncryptedData(ckey, enc_part.asn1Encode(), KeyUsage.KU_ENC_TGS_REP_PART_SESSKEY);
+            EncryptedData edata = new EncryptedData(ckey, enc_part.asn1Encode(),
+                    KeyUsage.KU_ENC_TGS_REP_PART_SESSKEY);
             TGSRep tgsRep = new TGSRep(null,
                     etp.cname,
                     t,
@@ -787,7 +899,7 @@
                     + " " +ke.returnCodeMessage());
             if (kerr == null) {
                 kerr = new KRBError(null, null, null,
-                        new KerberosTime(new Date()),
+                        timeAfter(0),
                         0,
                         ke.returnCode(),
                         body.cname,
@@ -823,7 +935,10 @@
 
             KDCReqBody body = asReq.reqBody;
 
-            eTypes = KDCReqBodyDotEType(body);
+            eTypes = filterSupported(KDCReqBodyDotEType(body));
+            if (eTypes.length == 0) {
+                throw new KrbException(Krb5.KDC_ERR_ETYPE_NOSUPP);
+            }
             int eType = eTypes[0];
 
             EncryptionKey ckey = keyForUser(body.cname, eType, false);
@@ -853,11 +968,29 @@
             // Session key
             EncryptionKey key = generateRandomKey(eType);
             // Check time, TODO
+            KerberosTime from = body.from;
             KerberosTime till = body.till;
+            KerberosTime rtime = body.rtime;
+            if (from == null || from.isZero()) {
+                from = timeAfter(0);
+            }
             if (till == null) {
                 throw new KrbException(Krb5.KDC_ERR_NEVER_VALID); // TODO
             } else if (till.isZero()) {
-                till = new KerberosTime(new Date().getTime() + 1000 * 3600 * 11);
+                String ttlsVal = System.getProperty("test.kdc.ttl.value");
+                if (ttlsVal != null){
+                    till = timeAfter(duration(ttlsVal));
+                    if (till.greaterThan(timeAfter(24 * 3600)) &&
+                        (System.getProperty("test.kdc.force.till") == null)) {
+                        till = timeAfter(DEFAULT_LIFETIME);
+                        body.kdcOptions.set(KDCOptions.RENEWABLE, true);
+                    }
+                } else {
+                    till = timeAfter(DEFAULT_LIFETIME);
+                }
+            }
+            if (rtime == null && body.kdcOptions.get(KDCOptions.RENEWABLE)) {
+                rtime = timeAfter(DEFAULT_RENEWTIME);
             }
             //body.from
             boolean[] bFlags = new boolean[Krb5.TKT_OPTS_MAX+1];
@@ -866,7 +999,7 @@
             }
             if (body.kdcOptions.get(KDCOptions.RENEWABLE)) {
                 bFlags[Krb5.TKT_OPTS_RENEWABLE] = true;
-                //renew = new KerberosTime(new Date().getTime() + 1000 * 3600 * 24 * 7);
+                //renew = timeAfter(3600 * 24 * 7);
             }
             if (body.kdcOptions.get(KDCOptions.PROXIABLE)) {
                 bFlags[Krb5.TKT_OPTS_PROXIABLE] = true;
@@ -888,7 +1021,8 @@
                         pas2 = new DerValue[] {
                             new DerValue(new ETypeInfo2(1, null, null).asn1Encode()),
                             new DerValue(new ETypeInfo2(1, "", null).asn1Encode()),
-                            new DerValue(new ETypeInfo2(1, OneKDC.REALM, new byte[]{1}).asn1Encode()),
+                            new DerValue(new ETypeInfo2(
+                                    1, OneKDC.REALM, new byte[]{1}).asn1Encode()),
                         };
                         pas = new DerValue[] {
                             new DerValue(new ETypeInfo(1, null).asn1Encode()),
@@ -949,7 +1083,7 @@
                             epas[i],
                             epas[i] == EncryptedData.ETYPE_ARCFOUR_HMAC ?
                                 null : getSalt(body.cname),
-                            null).asn1Encode());
+                            getParams(body.cname, epas[i])).asn1Encode());
                 }
                 boolean allOld = true;
                 for (int i: eTypes) {
@@ -983,7 +1117,7 @@
                 outPAs.add(new PAData(Krb5.PA_ETYPE_INFO, eid.toByteArray()));
             }
 
-            PAData[] inPAs = kDCReqDotPAData(asReq);
+            PAData[] inPAs = asReq.pAData;
             if (inPAs == null || inPAs.length == 0) {
                 Object preauth = options.get(Option.PREAUTH_REQUIRED);
                 if (preauth == null || preauth.equals(Boolean.TRUE)) {
@@ -991,11 +1125,14 @@
                 }
             } else {
                 try {
-                    EncryptedData data = newEncryptedData(new DerValue(inPAs[0].getValue()));
+                    EncryptedData data = newEncryptedData(
+                            new DerValue(inPAs[0].getValue()));
                     EncryptionKey pakey = keyForUser(body.cname, data.getEType(), false);
                     data.decrypt(pakey, KeyUsage.KU_PA_ENC_TS);
                 } catch (Exception e) {
-                    throw new KrbException(Krb5.KDC_ERR_PREAUTH_FAILED);
+                    KrbException ke = new KrbException(Krb5.KDC_ERR_PREAUTH_FAILED);
+                    ke.initCause(e);
+                    throw ke;
                 }
                 bFlags[Krb5.TKT_OPTS_PRE_AUTHENT] = true;
             }
@@ -1006,9 +1143,9 @@
                     key,
                     body.cname,
                     new TransitedEncoding(1, new byte[0]),
-                    new KerberosTime(new Date()),
-                    body.from,
-                    till, body.rtime,
+                    timeAfter(0),
+                    from,
+                    till, rtime,
                     body.addresses,
                     null);
             Ticket t = new Ticket(
@@ -1018,19 +1155,20 @@
             EncASRepPart enc_part = new EncASRepPart(
                     key,
                     new LastReq(new LastReqEntry[]{
-                        new LastReqEntry(0, new KerberosTime(new Date().getTime() - 10000))
+                        new LastReqEntry(0, timeAfter(-10))
                     }),
                     body.getNonce(),    // TODO: detect replay?
-                    new KerberosTime(new Date().getTime() + 1000 * 3600 * 24),
+                    timeAfter(3600 * 24),
                     // Next 5 and last MUST be same with ticket
                     tFlags,
-                    new KerberosTime(new Date()),
-                    body.from,
-                    till, body.rtime,
+                    timeAfter(0),
+                    from,
+                    till, rtime,
                     service,
                     body.addresses
                     );
-            EncryptedData edata = new EncryptedData(ckey, enc_part.asn1Encode(), KeyUsage.KU_ENC_AS_REP_PART);
+            EncryptedData edata = new EncryptedData(ckey, enc_part.asn1Encode(),
+                    KeyUsage.KU_ENC_AS_REP_PART);
             ASRep asRep = new ASRep(
                     outPAs.toArray(new PAData[outPAs.size()]),
                     body.cname,
@@ -1084,7 +1222,7 @@
                     eData = temp.toByteArray();
                 }
                 kerr = new KRBError(null, null, null,
-                        new KerberosTime(new Date()),
+                        timeAfter(0),
                         0,
                         ke.returnCode(),
                         body.cname,
@@ -1097,15 +1235,112 @@
     }
 
     /**
-     * Generates a line for a KDC to put inside [realms] of krb5.conf
-     * @param kdc the KDC
-     * @return REALM.NAME = { kdc = host:port }
+     * Translates a duration value into seconds.
+     *
+     * The format can be one of "h:m[:s]", "NdNhNmNs", and "N". See
+     * http://web.mit.edu/kerberos/krb5-devel/doc/basic/date_format.html#duration
+     * for definitions.
+     *
+     * @param s the string duration
+     * @return time in seconds
+     * @throw KrbException if format is illegal
      */
-    private static String realmLineForKDC(KDC kdc) {
-        return String.format("  %s = {\n    kdc = %s:%d\n  }\n",
-                kdc.realm,
-                kdc.kdc,
-                kdc.port);
+    public static int duration(String s) throws KrbException {
+
+        if (s.isEmpty()) {
+            throw new KrbException("Duration cannot be empty");
+        }
+
+        // N
+        if (s.matches("\\d+")) {
+            return Integer.parseInt(s);
+        }
+
+        // h:m[:s]
+        Matcher m = Pattern.compile("(\\d+):(\\d+)(:(\\d+))?").matcher(s);
+        if (m.matches()) {
+            int hr = Integer.parseInt(m.group(1));
+            int min = Integer.parseInt(m.group(2));
+            if (min >= 60) {
+                throw new KrbException("Illegal duration format " + s);
+            }
+            int result = hr * 3600 + min * 60;
+            if (m.group(4) != null) {
+                int sec = Integer.parseInt(m.group(4));
+                if (sec >= 60) {
+                    throw new KrbException("Illegal duration format " + s);
+                }
+                result += sec;
+            }
+            return result;
+        }
+
+        // NdNhNmNs
+        // 120m allowed. Maybe 1h120m is not good, but still allowed
+        m = Pattern.compile(
+                    "((\\d+)d)?\\s*((\\d+)h)?\\s*((\\d+)m)?\\s*((\\d+)s)?",
+                Pattern.CASE_INSENSITIVE).matcher(s);
+        if (m.matches()) {
+            int result = 0;
+            if (m.group(2) != null) {
+                result += 86400 * Integer.parseInt(m.group(2));
+            }
+            if (m.group(4) != null) {
+                result += 3600 * Integer.parseInt(m.group(4));
+            }
+            if (m.group(6) != null) {
+                result += 60 * Integer.parseInt(m.group(6));
+            }
+            if (m.group(8) != null) {
+                result += Integer.parseInt(m.group(8));
+            }
+            return result;
+        }
+
+        throw new KrbException("Illegal duration format " + s);
+    }
+
+    private int[] filterSupported(int[] input) {
+        int count = 0;
+        for (int i = 0; i < input.length; i++) {
+            if (!EType.isSupported(input[i])) {
+                continue;
+            }
+            if (SUPPORTED_ETYPES != null) {
+                boolean supported = false;
+                for (String se : SUPPORTED_ETYPES.split(",")) {
+                    if (Config.getType(se) == input[i]) {
+                        supported = true;
+                        break;
+                    }
+                }
+                if (!supported) {
+                    continue;
+                }
+            }
+            if (count != i) {
+                input[count] = input[i];
+            }
+            count++;
+        }
+        if (count != input.length) {
+            input = Arrays.copyOf(input, count);
+        }
+        return input;
+    }
+
+    /**
+     * Generates a line for a KDC to put inside [realms] of krb5.conf
+     * @return REALM.NAME = { kdc = host:port etc }
+     */
+    private String realmLine() {
+        StringBuilder sb = new StringBuilder();
+        sb.append(realm).append(" = {\n    kdc = ")
+                .append(kdc).append(':').append(port).append('\n');
+        for (String s: conf) {
+            sb.append("    ").append(s).append('\n');
+        }
+        return sb.append("}\n").toString();
     }
 
     /**
@@ -1118,6 +1353,20 @@
      * @throws java.io.IOException for any communication error
      */
     protected void startServer(int port, boolean asDaemon) throws IOException {
+        if (nativeKdc != null) {
+            startNativeServer(port, asDaemon);
+        } else {
+            startJavaServer(port, asDaemon);
+        }
+    }
+
+    private void startNativeServer(int port, boolean asDaemon) throws IOException {
+        nativeKdc.prepare();
+        nativeKdc.init();
+        kdcProc = nativeKdc.kdc();
+    }
+
+    private void startJavaServer(int port, boolean asDaemon) throws IOException {
         if (port > 0) {
             u1 = new DatagramSocket(port, InetAddress.getByName("127.0.0.1"));
             t1 = new ServerSocket(port);
@@ -1198,17 +1447,103 @@
         thread3.start();
     }
 
+    public void kinit(String user, String ccache) throws Exception {
+        if (user.indexOf('@') < 0) {
+            user = user + "@" + realm;
+        }
+        if (nativeKdc != null) {
+            nativeKdc.kinit(user, ccache);
+        } else {
+            Context.fromUserPass(user, passwords.get(user), false)
+                    .ccache(ccache);
+        }
+    }
+
     public void terminate() {
-        try {
-            thread1.stop();
-            thread2.stop();
-            thread3.stop();
-            u1.close();
-            t1.close();
-        } catch (Exception e) {
-            // OK
+        if (nativeKdc != null) {
+            System.out.println("Killing kdc...");
+            kdcProc.destroy();
+            System.out.println("Done");
+        } else {
+            try {
+                thread1.stop();
+                thread2.stop();
+                thread3.stop();
+                u1.close();
+                t1.close();
+            } catch (Exception e) {
+                // OK
+            }
         }
     }
+
+    public static KDC startKDC(final String host, final String krbConfFileName,
+            final String realm, final Map<String, String> principals,
+            final String ktab, final KtabMode mode) {
+
+        KDC kdc;
+        try {
+            kdc = KDC.create(realm, host, 0, true);
+            kdc.setOption(KDC.Option.PREAUTH_REQUIRED, Boolean.FALSE);
+            if (krbConfFileName != null) {
+                KDC.saveConfig(krbConfFileName, kdc);
+            }
+
+            // Add principals
+            if (principals != null) {
+                for (Map.Entry<String, String> entry : principals.entrySet()) {
+                    String name = entry.getKey();
+                    String password = entry.getValue();
+                    if (password == null || password.isEmpty()) {
+                        System.out.println(String.format(
+                                "KDC:add a principal '%s' with a random " +
+                                        "password", name));
+                        kdc.addPrincipalRandKey(name);
+                    } else {
+                        System.out.println(String.format(
+                                "KDC:add a principal '%s' with '%s' password",
+                                name, password));
+                        kdc.addPrincipal(name, password.toCharArray());
+                    }
+                }
+            }
+
+            // Create or append keys to existing keytab file
+            if (ktab != null) {
+                File ktabFile = new File(ktab);
+                switch(mode) {
+                    case APPEND:
+                        if (ktabFile.exists()) {
+                            System.out.println(String.format(
+                                    "KDC:append keys to an exising keytab "
+                                    + "file %s", ktab));
+                            kdc.appendKtab(ktab);
+                        } else {
+                            System.out.println(String.format(
+                                    "KDC:create a new keytab file %s", ktab));
+                            kdc.writeKtab(ktab);
+                        }
+                        break;
+                    case EXISTING:
+                        System.out.println(String.format(
+                                "KDC:use an existing keytab file %s", ktab));
+                        break;
+                    default:
+                        throw new RuntimeException(String.format(
+                                "KDC:unsupported keytab mode: %s", mode));
+                }
+            }
+
+            System.out.println(String.format(
+                    "KDC: started on %s:%s with '%s' realm",
+                    host, kdc.getPort(), realm));
+        } catch (Exception e) {
+            throw new RuntimeException("KDC: unexpected exception", e);
+        }
+
+        return kdc;
+    }
+
     /**
      * Helper class to encapsulate a job in a KDC.
      */
@@ -1256,13 +1591,20 @@
     }
 
     public static class KDCNameService implements NameServiceDescriptor {
+
+        public static String NOT_EXISTING_HOST = "not.existing.host";
+
         @Override
         public NameService createNameService() throws Exception {
             NameService ns = new NameService() {
                 @Override
                 public InetAddress[] lookupAllHostAddr(String host)
                         throws UnknownHostException {
-                    // Everything is localhost
+                    // Everything is localhost except NOT_EXISTING_HOST
+                    if (NOT_EXISTING_HOST.equals(host)) {
+                        throw new UnknownHostException("Unknown host name: "
+                                + NOT_EXISTING_HOST);
+                    }
                     return new InetAddress[]{
                         InetAddress.getByAddress(host, new byte[]{127,0,0,1})
                     };
@@ -1288,8 +1630,279 @@
         }
     }
 
+    /**
+     * A native KDC using the binaries in nativePath. Attention:
+     * this is using binaries, not an existing KDC instance.
+     * An implementation of this takes care of configuration,
+     * principal db managing and KDC startup.
+     */
+    static abstract class NativeKdc {
+
+        protected Map<String,String> env;
+        protected String nativePath;
+        protected String base;
+        protected String realm;
+        protected int port;
+
+        NativeKdc(String nativePath, KDC kdc) {
+            if (kdc.port == 0) {
+                kdc.port = 8000 + new java.util.Random().nextInt(10000);
+            }
+            this.nativePath = nativePath;
+            this.realm = kdc.realm;
+            this.port = kdc.port;
+            this.base = Paths.get("" + port).toAbsolutePath().toString();
+        }
+
+        // Add a new principal
+        abstract void addPrincipal(String user, String pass);
+        // Add a keytab entry
+        abstract void ktadd(String user, String ktab);
+        // Initialize KDC
+        abstract void init();
+        // Start kdc
+        abstract Process kdc();
+        // Configuration
+        abstract void prepare();
+        // Fill ccache
+        abstract void kinit(String user, String ccache);
+
+        static NativeKdc get(KDC kdc) {
+            String prop = System.getProperty("native.kdc.path");
+            if (prop == null) {
+                return null;
+            } else if (Files.exists(Paths.get(prop, "sbin/krb5kdc"))) {
+                return new MIT(true, prop, kdc);
+            } else if (Files.exists(Paths.get(prop, "kdc/krb5kdc"))) {
+                return new MIT(false, prop, kdc);
+            } else if (Files.exists(Paths.get(prop, "libexec/kdc"))) {
+                return new Heimdal(prop, kdc);
+            } else {
+                throw new IllegalArgumentException("Strange " + prop);
+            }
+        }
+
+        Process run(boolean wait, String... cmd) {
+            try {
+                System.out.println("Running " + cmd2str(env, cmd));
+                ProcessBuilder pb = new ProcessBuilder();
+                pb.inheritIO();
+                pb.environment().putAll(env);
+                Process p = pb.command(cmd).start();
+                if (wait) {
+                    if (p.waitFor() < 0) {
+                        throw new RuntimeException("exit code is not null");
+                    }
+                    return null;
+                } else {
+                    return p;
+                }
+            } catch (Exception e) {
+                throw new RuntimeException(e);
+            }
+        }
+
+        private String cmd2str(Map<String,String> env, String... cmd) {
+            StringBuilder sb = new StringBuilder();
+            for (Map.Entry<String,String> e : env.entrySet()) {
+                sb.append(e.getKey()+"="+e.getValue());
+                sb.append(" ");
+            }
+            for (int a = 0; a < cmd.length; ++a) {
+                sb.append(cmd);
+                if (a < (cmd.length - 1)) {
+                    sb.append(" ");
+                }
+            }
+            return sb.toString();
+        }
+    }
+
+    // Heimdal KDC. Build your own and run "make install" to nativePath.
+    static class Heimdal extends NativeKdc {
+
+        Heimdal(String nativePath, KDC kdc) {
+            super(nativePath, kdc);
+            Map<String, String> environment = new HashMap<>();
+            environment.put("KRB5_CONFIG", base + "/krb5.conf");
+            environment.put("KRB5_TRACE", "/dev/stderr");
+            environment.put("DYLD_LIBRARY_PATH", nativePath + "/lib");
+            environment.put("LD_LIBRARY_PATH", nativePath + "/lib");
+            this.env = Collections.unmodifiableMap(environment);
+        }
+
+        @Override
+        public void addPrincipal(String user, String pass) {
+            run(true, nativePath + "/bin/kadmin", "-l", "-r", realm,
+                    "add", "-p", pass, "--use-defaults", user);
+        }
+
+        @Override
+        public void ktadd(String user, String ktab) {
+            run(true, nativePath + "/bin/kadmin", "-l", "-r", realm,
+                    "ext_keytab", "-k", ktab, user);
+        }
+
+        @Override
+        public void init() {
+            run(true, nativePath + "/bin/kadmin",  "-l",  "-r", realm,
+                    "init", "--realm-max-ticket-life=1day",
+                    "--realm-max-renewable-life=1month", realm);
+        }
+
+        @Override
+        public Process kdc() {
+            return run(false, nativePath + "/libexec/kdc",
+                    "--addresses=127.0.0.1", "-P", "" + port);
+        }
+
+        @Override
+        public void prepare() {
+            try {
+                Files.createDirectory(Paths.get(base));
+                Files.write(Paths.get(base + "/krb5.conf"), Arrays.asList(
+                        "[libdefaults]",
+                        "default_realm = " + realm,
+                        "default_keytab_name = FILE:" + base + "/krb5.keytab",
+                        "forwardable = true",
+                        "dns_lookup_kdc = no",
+                        "dns_lookup_realm = no",
+                        "dns_canonicalize_hostname = false",
+                        "\n[realms]",
+                        realm + " = {",
+                        "  kdc = localhost:" + port,
+                        "}",
+                        "\n[kdc]",
+                        "db-dir = " + base,
+                        "database = {",
+                        "    label = {",
+                        "        dbname = " + base + "/current-db",
+                        "        realm = " + realm,
+                        "        mkey_file = " + base + "/mkey.file",
+                        "        acl_file = " + base + "/heimdal.acl",
+                        "        log_file = " + base + "/current.log",
+                        "    }",
+                        "}",
+                        SUPPORTED_ETYPES == null ? ""
+                                : ("\n[kadmin]\ndefault_keys = "
+                                + (SUPPORTED_ETYPES + ",")
+                                        .replaceAll(",", ":pw-salt ")),
+                        "\n[logging]",
+                        "kdc = 0-/FILE:" + base + "/messages.log",
+                        "krb5 = 0-/FILE:" + base + "/messages.log",
+                        "default = 0-/FILE:" + base + "/messages.log"
+                ), StandardCharsets.UTF_8);
+            } catch (IOException e) {
+                throw new RuntimeException(e);
+            }
+        }
+
+        @Override
+        void kinit(String user, String ccache) {
+            String tmpName = base + "/" + user + "." +
+                    System.identityHashCode(this) + ".keytab";
+            ktadd(user, tmpName);
+            run(true, nativePath + "/bin/kinit",
+                    "-f", "-t", tmpName, "-c", ccache, user);
+        }
+    }
+
+    // MIT krb5 KDC. Make your own exploded (install == false), or
+    // "make install" into nativePath (install == true).
+    static class MIT extends NativeKdc {
+
+        private boolean install; // "make install" or "make"
+
+        MIT(boolean install, String nativePath, KDC kdc) {
+            super(nativePath, kdc);
+            this.install = install;
+            Map<String, String> environment = new HashMap<>();
+            environment.put("KRB5_KDC_PROFILE", base + "/kdc.conf");
+            environment.put("KRB5_CONFIG", base + "/krb5.conf");
+            environment.put("KRB5_TRACE", "/dev/stderr");
+            environment.put("DYLD_LIBRARY_PATH", nativePath + "/lib");
+            environment.put("LD_LIBRARY_PATH", nativePath + "/lib");
+            this.env = Collections.unmodifiableMap(environment);
+        }
+
+        @Override
+        public void addPrincipal(String user, String pass) {
+            run(true, nativePath +
+                    (install ? "/sbin/" : "/kadmin/cli/") + "kadmin.local",
+                    "-q", "addprinc -pw " + pass + " " + user);
+        }
+
+        @Override
+        public void ktadd(String user, String ktab) {
+            run(true, nativePath +
+                    (install ? "/sbin/" : "/kadmin/cli/") + "kadmin.local",
+                    "-q", "ktadd -k " + ktab + " -norandkey " + user);
+        }
+
+        @Override
+        public void init() {
+            run(true, nativePath +
+                    (install ? "/sbin/" : "/kadmin/dbutil/") + "kdb5_util",
+                    "create", "-s", "-W", "-P", "olala");
+        }
+
+        @Override
+        public Process kdc() {
+            return run(false, nativePath +
+                    (install ? "/sbin/" : "/kdc/") + "krb5kdc",
+                    "-n");
+        }
+
+        @Override
+        public void prepare() {
+            try {
+                Files.createDirectory(Paths.get(base));
+                Files.write(Paths.get(base + "/kdc.conf"), Arrays.asList(
+                        "[kdcdefaults]",
+                        "\n[realms]",
+                        realm + "= {",
+                        "  kdc_listen = " + this.port,
+                        "  kdc_tcp_listen = " + this.port,
+                        "  database_name = " + base + "/principal",
+                        "  key_stash_file = " + base + "/.k5.ATHENA.MIT.EDU",
+                        SUPPORTED_ETYPES == null ? ""
+                                : ("  supported_enctypes = "
+                                + (SUPPORTED_ETYPES + ",")
+                                        .replaceAll(",", ":normal ")),
+                        "}"
+                ), StandardCharsets.UTF_8);
+                Files.write(Paths.get(base + "/krb5.conf"), Arrays.asList(
+                        "[libdefaults]",
+                        "default_realm = " + realm,
+                        "default_keytab_name = FILE:" + base + "/krb5.keytab",
+                        "forwardable = true",
+                        "dns_lookup_kdc = no",
+                        "dns_lookup_realm = no",
+                        "dns_canonicalize_hostname = false",
+                        "\n[realms]",
+                        realm + " = {",
+                        "  kdc = localhost:" + port,
+                        "}",
+                        "\n[logging]",
+                        "kdc = FILE:" + base + "/krb5kdc.log"
+                ), StandardCharsets.UTF_8);
+            } catch (IOException e) {
+                throw new RuntimeException(e);
+            }
+        }
+
+        @Override
+        void kinit(String user, String ccache) {
+            String tmpName = base + "/" + user + "." +
+                    System.identityHashCode(this) + ".keytab";
+            ktadd(user, tmpName);
+            run(true, nativePath +
+                    (install ? "/bin/" : "/clients/kinit/") + "kinit",
+                    "-f", "-t", tmpName, "-c", ccache, user);
+        }
+    }
+
     // Calling private methods thru reflections
-    private static final Field getPADataField;
     private static final Field getEType;
     private static final Constructor<EncryptedData> ctorEncryptedData;
     private static final Method stringToKey;
@@ -1298,8 +1911,6 @@
         try {
             ctorEncryptedData = EncryptedData.class.getDeclaredConstructor(DerValue.class);
             ctorEncryptedData.setAccessible(true);
-            getPADataField = KDCReq.class.getDeclaredField("pAData");
-            getPADataField.setAccessible(true);
             getEType = KDCReqBody.class.getDeclaredField("eType");
             getEType.setAccessible(true);
             stringToKey = EncryptionKey.class.getDeclaredMethod(
@@ -1319,13 +1930,6 @@
             throw new AssertionError(e);
         }
     }
-    private static PAData[] kDCReqDotPAData(KDCReq req) {
-        try {
-            return (PAData[])getPADataField.get(req);
-        } catch (Exception e) {
-            throw new AssertionError(e);
-        }
-    }
     private static int[] KDCReqBodyDotEType(KDCReqBody body) {
         try {
             return (int[]) getEType.get(body);
--- a/test/sun/security/krb5/auto/KerberosHashEqualsTest.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/sun/security/krb5/auto/KerberosHashEqualsTest.java	Thu Feb 06 01:43:16 2020 +0000
@@ -24,7 +24,7 @@
 /*
  * @test
  * @bug 4641821
- * @run main/othervm KerberosHashEqualsTest
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock KerberosHashEqualsTest
  * @summary hashCode() and equals() for KerberosKey and KerberosTicket
  */
 
--- a/test/sun/security/krb5/auto/KeyPermissions.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/sun/security/krb5/auto/KeyPermissions.java	Thu Feb 06 01:43:16 2020 +0000
@@ -26,7 +26,7 @@
  * @bug 8004488
  * @summary wrong permissions checked in krb5
  * @compile -XDignore.symbol.file KeyPermissions.java
- * @run main/othervm KeyPermissions
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock KeyPermissions
  */
 
 import java.security.AccessControlException;
--- a/test/sun/security/krb5/auto/KeyTabCompat.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/sun/security/krb5/auto/KeyTabCompat.java	Thu Feb 06 01:43:16 2020 +0000
@@ -26,7 +26,7 @@
  * @bug 6894072
  * @bug 8004488
  * @compile -XDignore.symbol.file KeyTabCompat.java
- * @run main/othervm KeyTabCompat
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock KeyTabCompat
  * @summary always refresh keytab
  */
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/security/krb5/auto/KrbTicket.java	Thu Feb 06 01:43:16 2020 +0000
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import javax.security.auth.RefreshFailedException;
+import javax.security.auth.Subject;
+import javax.security.auth.kerberos.KerberosTicket;
+import javax.security.auth.login.LoginContext;
+
+/*
+ * @test
+ * @bug 6857795 8075299
+ * @summary Checks Kerberos ticket properties
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock KrbTicket
+ */
+public class KrbTicket {
+
+    private static final String REALM = "TEST.REALM";
+    private static final String HOST = "localhost";
+    private static final String USER = "TESTER";
+    private static final String USER_PRINCIPAL = USER + "@" + REALM;
+    private static final String PASSWORD = "password";
+    private static final String KRBTGT_PRINCIPAL = "krbtgt/" + REALM;
+    private static final String KRB5_CONF_FILENAME = "krb5.conf";
+    private static final String JAAS_CONF = "jaas.conf";
+    private static final long TICKET_LIFTETIME = 5 * 60 * 1000; // 5 mins
+
+    public static void main(String[] args) throws Exception {
+        // define principals
+        Map<String, String> principals = new HashMap<>();
+        principals.put(USER_PRINCIPAL, PASSWORD);
+        principals.put(KRBTGT_PRINCIPAL, null);
+
+        System.setProperty("java.security.krb5.conf", KRB5_CONF_FILENAME);
+
+        // start a local KDC instance
+        KDC kdc = KDC.startKDC(HOST, null, REALM, principals, null, null);
+        KDC.saveConfig(KRB5_CONF_FILENAME, kdc,
+                "forwardable = true", "proxiable = true");
+
+        // create JAAS config
+        Files.write(Paths.get(JAAS_CONF), Arrays.asList(
+                "Client {",
+                "    com.sun.security.auth.module.Krb5LoginModule required;",
+                "};"
+        ), StandardCharsets.UTF_8);
+        System.setProperty("java.security.auth.login.config", JAAS_CONF);
+        System.setProperty("javax.security.auth.useSubjectCredsOnly", "false");
+
+        long startTime = new Date().getTime();
+
+        LoginContext lc = new LoginContext("Client",
+                new Helper.UserPasswordHandler(USER, PASSWORD));
+        lc.login();
+
+        Subject subject = lc.getSubject();
+        System.out.println("subject: " + subject);
+
+        Set creds = subject.getPrivateCredentials(
+                KerberosTicket.class);
+
+        if (creds.size() > 1) {
+            throw new RuntimeException("Multiple credintials found");
+        }
+
+        Object o = creds.iterator().next();
+        if (!(o instanceof KerberosTicket)) {
+            throw new RuntimeException("Instance of KerberosTicket expected");
+        }
+        KerberosTicket krbTkt = (KerberosTicket) o;
+
+        System.out.println("forwardable = " + krbTkt.isForwardable());
+        System.out.println("proxiable   = " + krbTkt.isProxiable());
+        System.out.println("renewable   = " + krbTkt.isRenewable());
+        System.out.println("current     = " + krbTkt.isCurrent());
+
+        if (!krbTkt.isForwardable()) {
+            throw new RuntimeException("Forwardable ticket expected");
+        }
+
+        if (!krbTkt.isProxiable()) {
+            throw new RuntimeException("Proxiable ticket expected");
+        }
+
+        if (!krbTkt.isCurrent()) {
+            throw new RuntimeException("Ticket is not current");
+        }
+
+        if (krbTkt.isRenewable()) {
+            throw new RuntimeException("Not renewable ticket expected");
+        }
+        try {
+            krbTkt.refresh();
+            throw new RuntimeException(
+                    "Expected RefreshFailedException not thrown");
+        } catch(RefreshFailedException e) {
+            System.out.println("Expected exception: " + e);
+        }
+
+        if (!checkTime(krbTkt, startTime)) {
+            throw new RuntimeException("Wrong ticket life time");
+        }
+
+        krbTkt.destroy();
+        if (!krbTkt.isDestroyed()) {
+            throw new RuntimeException("Ticket not destroyed");
+        }
+
+        System.out.println("Test passed");
+    }
+
+    private static boolean checkTime(KerberosTicket krbTkt, long startTime) {
+        long ticketEndTime = krbTkt.getEndTime().getTime();
+        long roughLifeTime = ticketEndTime - startTime;
+        System.out.println("start time            = " + startTime);
+        System.out.println("end time              = " + ticketEndTime);
+        System.out.println("rough life time       = " + roughLifeTime);
+        return roughLifeTime >= TICKET_LIFTETIME;
+    }
+}
--- a/test/sun/security/krb5/auto/KvnoNA.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/sun/security/krb5/auto/KvnoNA.java	Thu Feb 06 01:43:16 2020 +0000
@@ -25,7 +25,7 @@
  * @test
  * @bug 7197159
  * @compile -XDignore.symbol.file KvnoNA.java
- * @run main/othervm KvnoNA
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock KvnoNA
  * @summary accept different kvno if there no match
  */
 
--- a/test/sun/security/krb5/auto/LifeTimeInSeconds.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/sun/security/krb5/auto/LifeTimeInSeconds.java	Thu Feb 06 01:43:16 2020 +0000
@@ -24,7 +24,7 @@
 /*
  * @test
  * @bug 6857802
- * @run main/othervm LifeTimeInSeconds
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock LifeTimeInSeconds
  * @summary GSS getRemainingInitLifetime method returns milliseconds not seconds
  */
 import org.ietf.jgss.GSSCredential;
@@ -40,7 +40,7 @@
         int time = cred.getRemainingLifetime();
         int time2 = cred.getRemainingInitLifetime(null);
         // The test KDC issues a TGT with a default lifetime of 11 hours
-        int elevenhrs = 11*3600;
+        int elevenhrs = KDC.DEFAULT_LIFETIME;
         if (time > elevenhrs+60 || time < elevenhrs-60) {
             throw new Exception("getRemainingLifetime returns wrong value.");
         }
--- a/test/sun/security/krb5/auto/LoginModuleOptions.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/sun/security/krb5/auto/LoginModuleOptions.java	Thu Feb 06 01:43:16 2020 +0000
@@ -24,7 +24,7 @@
 /*
  * @test
  * @bug 6765491
- * @run main/othervm LoginModuleOptions
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock LoginModuleOptions
  * @summary Krb5LoginModule a little too restrictive, and the doc is not clear.
  */
 import com.sun.security.auth.module.Krb5LoginModule;
--- a/test/sun/security/krb5/auto/LoginNoPass.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/sun/security/krb5/auto/LoginNoPass.java	Thu Feb 06 01:43:16 2020 +0000
@@ -26,7 +26,7 @@
  * @bug 8028351
  * @summary JWS doesn't get authenticated when using kerberos auth proxy
  * @compile -XDignore.symbol.file LoginNoPass.java
- * @run main/othervm LoginNoPass
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock LoginNoPass
  */
 
 import sun.security.jgss.GSSUtil;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/security/krb5/auto/LongLife.java	Thu Feb 06 01:43:16 2020 +0000
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8131051 8187218
+ * @summary KDC might issue a renewable ticket even if not requested
+ * @compile -XDignore.symbol.file LongLife.java
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock LongLife
+ */
+
+import org.ietf.jgss.GSSCredential;
+import org.ietf.jgss.GSSManager;
+import sun.security.krb5.Config;
+import javax.security.auth.Subject;
+import javax.security.auth.kerberos.KerberosTicket;
+import java.security.PrivilegedExceptionAction;
+
+public class LongLife {
+
+    public static void main(String[] args) throws Exception {
+
+        OneKDC kdc = new OneKDC(null).writeJAASConf();
+
+        test(kdc, "10h", false, 36000, false);
+        test(kdc, "2d", false, KDC.DEFAULT_LIFETIME, true);
+        test(kdc, "2d", true, 2 * 24 * 3600, false);
+
+        // 8187218: getRemainingLifetime() is negative if lifetime
+        // is longer than 30 days.
+        test(kdc, "30d", true, 30 * 24 * 3600, false);
+    }
+
+    static void test(
+            KDC kdc,
+            String ticketLifetime,
+            boolean forceTill, // if true, KDC will not try RENEWABLE
+            int expectedLifeTime,
+            boolean expectedRenewable) throws Exception {
+
+        KDC.saveConfig(OneKDC.KRB5_CONF, kdc);
+        Config.refresh();
+
+        System.setProperty("test.kdc.ttl.value", ticketLifetime);
+
+        if (forceTill) {
+            System.setProperty("test.kdc.force.till", "");
+        } else {
+            System.clearProperty("test.kdc.force.till");
+        }
+
+        Context c = Context.fromJAAS("client");
+
+        GSSCredential cred = Subject.doAs(c.s(),
+            new PrivilegedExceptionAction<GSSCredential>() {
+                @Override
+                public GSSCredential run() throws Exception {
+                    GSSManager m = GSSManager.getInstance();
+                    return m.createCredential(GSSCredential.INITIATE_ONLY);
+                }
+            });
+
+        KerberosTicket tgt = c.s().getPrivateCredentials(KerberosTicket.class)
+                .iterator().next();
+        System.out.println(tgt);
+
+        int actualLifeTime = cred.getRemainingLifetime();
+        if (actualLifeTime < (expectedLifeTime - 60 )
+                || actualLifeTime > (expectedLifeTime + 60)) {
+            throw new Exception("actualLifeTime is " + actualLifeTime +
+                      " ExpectedLifeTime is " + expectedLifeTime);
+        }
+
+        if (tgt.isRenewable() != expectedRenewable) {
+            throw new Exception("TGT's RENEWABLE flag is " + tgt.isRenewable());
+        }
+    }
+}
--- a/test/sun/security/krb5/auto/MSOID2.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/sun/security/krb5/auto/MSOID2.java	Thu Feb 06 01:43:16 2020 +0000
@@ -26,7 +26,7 @@
  * @bug 8078439
  * @summary SPNEGO auth fails if client proposes MS krb5 OID
  * @compile -XDignore.symbol.file MSOID2.java
- * @run main/othervm MSOID2
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock MSOID2
  */
 
 import sun.security.jgss.GSSUtil;
--- a/test/sun/security/krb5/auto/MaxRetries.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/sun/security/krb5/auto/MaxRetries.java	Thu Feb 06 01:43:16 2020 +0000
@@ -25,7 +25,7 @@
  * @test
  * @bug 6844193
  * @compile -XDignore.symbol.file MaxRetries.java
- * @run main/othervm/timeout=300 MaxRetries
+ * @run main/othervm/timeout=300 -Dsun.net.spi.nameservice.provider.1=ns,mock MaxRetries
  * @summary support max_retries in krb5.conf
  */
 
--- a/test/sun/security/krb5/auto/MoreKvno.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/sun/security/krb5/auto/MoreKvno.java	Thu Feb 06 01:43:16 2020 +0000
@@ -24,7 +24,7 @@
 /*
  * @test
  * @bug 6893158 6907425 7197159
- * @run main/othervm MoreKvno
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock MoreKvno
  * @summary AP_REQ check should use key version number
  */
 
--- a/test/sun/security/krb5/auto/NewSalt.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/sun/security/krb5/auto/NewSalt.java	Thu Feb 06 01:43:16 2020 +0000
@@ -25,9 +25,9 @@
  * @test
  * @bug 6960894
  * @summary Better AS-REQ creation and processing
- * @run main/othervm NewSalt
- * @run main/othervm -Dnopreauth NewSalt
- * @run main/othervm -Donlyonepreauth NewSalt
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock NewSalt
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock -Dnopreauth NewSalt
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock -Donlyonepreauth NewSalt
  */
 
 import sun.security.jgss.GSSUtil;
--- a/test/sun/security/krb5/auto/NoAddresses.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/sun/security/krb5/auto/NoAddresses.java	Thu Feb 06 01:43:16 2020 +0000
@@ -24,9 +24,9 @@
 /*
  * @test
  * @bug 7032354
- * @run main/othervm NoAddresses 1
- * @run main/othervm NoAddresses 2
- * @run main/othervm/fail NoAddresses 3
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock NoAddresses 1
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock NoAddresses 2
+ * @run main/othervm/fail -Dsun.net.spi.nameservice.provider.1=ns,mock NoAddresses 3
  * @summary no-addresses should not be used on acceptor side
  */
 
--- a/test/sun/security/krb5/auto/NoInitNoKeytab.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/sun/security/krb5/auto/NoInitNoKeytab.java	Thu Feb 06 01:43:16 2020 +0000
@@ -26,7 +26,7 @@
  * @bug 7089889
  * @summary Krb5LoginModule.login() throws an exception if used without a keytab
  * @compile -XDignore.symbol.file NoInitNoKeytab.java
- * @run main/othervm NoInitNoKeytab
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock NoInitNoKeytab
  */
 
 import java.io.FileOutputStream;
--- a/test/sun/security/krb5/auto/NonMutualSpnego.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/sun/security/krb5/auto/NonMutualSpnego.java	Thu Feb 06 01:43:16 2020 +0000
@@ -24,7 +24,7 @@
 /*
  * @test
  * @bug 6733095
- * @run main/othervm NonMutualSpnego
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock NonMutualSpnego
  * @summary Failure when SPNEGO request non-Mutual
  */
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/security/krb5/auto/NoneReplayCacheTest.java	Thu Feb 06 01:43:16 2020 +0000
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2013 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 8001326
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock NoneReplayCacheTest
+ * @summary the replaycache type none cannot stop an authenticator replay,
+ * but it can stop a message replay when s.s.k.acceptor.subkey is true.
+ * You should not really use none in production environment. This test merely
+ * shows there can be other protections when replay cache is not working fine.
+ */
+
+import org.ietf.jgss.GSSException;
+import sun.security.jgss.GSSUtil;
+
+public class NoneReplayCacheTest {
+
+    public static void main(String[] args)
+            throws Exception {
+
+        new OneKDC(null);
+
+        System.setProperty("sun.security.krb5.rcache", "none");
+        System.setProperty("sun.security.krb5.acceptor.subkey", "true");
+
+        Context c, s;
+        c = Context.fromUserPass(OneKDC.USER, OneKDC.PASS, false);
+        s = Context.fromUserKtab(OneKDC.SERVER, OneKDC.KTAB, true);
+
+        c.startAsClient(OneKDC.SERVER, GSSUtil.GSS_KRB5_MECH_OID);
+        s.startAsServer(GSSUtil.GSS_KRB5_MECH_OID);
+
+        byte[] first = c.take(new byte[0]);
+
+        c.take(s.take(first));
+
+        byte[] msg = c.wrap("hello".getBytes(), true);
+        s.unwrap(msg, true);
+
+        s.startAsServer(GSSUtil.GSS_KRB5_MECH_OID);
+        s.take(first);  // apreq replay not detectable
+        try {
+            s.unwrap(msg, true);    // msg replay detectable
+            throw new Exception("This method should fail");
+        } catch (GSSException gsse) {
+            gsse.printStackTrace();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/security/krb5/auto/NullRenewUntil.java	Thu Feb 06 01:43:16 2020 +0000
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8186576
+ * @summary KerberosTicket does not properly handle renewable tickets
+ *          at the end of their lifetime
+ * @library /lib/testlibrary/
+ * @compile -XDignore.symbol.file NullRenewUntil.java
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock -Dtest.set.null.renew NullRenewUntil
+ */
+
+import jdk.testlibrary.Asserts;
+import sun.security.krb5.Config;
+
+import javax.security.auth.kerberos.KerberosTicket;
+
+public class NullRenewUntil {
+
+    public static void main(String[] args) throws Exception {
+
+        OneKDC kdc = new OneKDC(null);
+
+        KDC.saveConfig(OneKDC.KRB5_CONF, kdc,
+                "ticket_lifetime = 10s",
+                "renew_lifetime = 11s");
+        Config.refresh();
+
+        KerberosTicket ticket = Context
+                .fromUserPass(OneKDC.USER, OneKDC.PASS, false).s()
+                .getPrivateCredentials(KerberosTicket.class).iterator().next();
+
+        System.out.println(ticket);
+        Asserts.assertTrue(ticket.getRenewTill() != null, ticket.toString());
+
+        Thread.sleep(2000);
+
+        ticket.refresh();
+        System.out.println(ticket);
+        Asserts.assertTrue(ticket.getRenewTill() == null, ticket.toString());
+
+        Thread.sleep(2000);
+        ticket.refresh();
+        System.out.println(ticket);
+    }
+}
--- a/test/sun/security/krb5/auto/OkAsDelegate.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/sun/security/krb5/auto/OkAsDelegate.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -21,6 +21,32 @@
  * questions.
  */
 
+/*
+ * @test
+ * @bug 6853328 7172701
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock OkAsDelegate false true true false false false
+ *      FORWARDABLE ticket not allowed, always fail
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock OkAsDelegate true false false false false false
+ *      Service ticket no OK-AS-DELEGATE. Request nothing, gain nothing
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock OkAsDelegate true false true false false false
+ *      Service ticket no OK-AS-DELEGATE. Request deleg policy, gain nothing
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock OkAsDelegate true true false true false true
+ *      Service ticket no OK-AS-DELEGATE. Request deleg, granted
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock OkAsDelegate true true true true false true
+ *      Service ticket no OK-AS-DELEGATE. Request deleg and deleg policy, granted, with info not by policy
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock -Dtest.kdc.policy.ok-as-delegate OkAsDelegate true false true true true true
+ *      Service ticket has OK-AS-DELEGATE. Request deleg policy, granted
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock -Dtest.kdc.policy.ok-as-delegate OkAsDelegate true true true true true true
+ *      Service ticket has OK-AS-DELEGATE. granted, with info by policy
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock -Dtest.spnego OkAsDelegate false true true false false false
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock -Dtest.spnego OkAsDelegate true false false false false false
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock -Dtest.spnego OkAsDelegate true false true false false false
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock -Dtest.spnego OkAsDelegate true true false true false true
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock -Dtest.spnego OkAsDelegate true true true true false true
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock -Dtest.spnego -Dtest.kdc.policy.ok-as-delegate OkAsDelegate true false true true true true
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock -Dtest.spnego -Dtest.kdc.policy.ok-as-delegate OkAsDelegate true true true true true true
+ * @summary Support OK-AS-DELEGATE flag
+ */
 import com.sun.security.jgss.ExtendedGSSContext;
 import org.ietf.jgss.GSSCredential;
 import org.ietf.jgss.GSSException;
@@ -52,7 +78,7 @@
             boolean delegated
             ) throws Exception {
         OneKDC kdc = new OneKDC(null);
-        kdc.setPolicy("ok-as-delegate",
+        kdc.setOption(KDC.Option.OK_AS_DELEGATE,
                 System.getProperty("test.kdc.policy.ok-as-delegate"));
         kdc.writeJAASConf();
         if (!forwardable) {
--- a/test/sun/security/krb5/auto/OkAsDelegateXRealm.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/sun/security/krb5/auto/OkAsDelegateXRealm.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -21,8 +21,19 @@
  * questions.
  */
 
-import com.sun.security.jgss.ExtendedGSSContext;
-import java.io.File;
+/*
+ * @test
+ * @bug 6853328 7172701
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock OkAsDelegateXRealm false
+ *      KDC no OK-AS-DELEGATE, fail
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock -Dtest.kdc.policy.ok-as-delegate OkAsDelegateXRealm true
+ *      KDC set OK-AS-DELEGATE for all, succeed
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock -Dtest.kdc.policy.ok-as-delegate=host/host.r3.local OkAsDelegateXRealm false
+ *      KDC set OK-AS-DELEGATE for host/host.r3.local only, fail
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock -Dtest.kdc.policy.ok-as-delegate=host/host.r3.local,krbtgt/R2,krbtgt/R3 OkAsDelegateXRealm true
+ *      KDC set OK-AS-DELEGATE for all three, succeed
+ * @summary Support OK-AS-DELEGATE flag
+ */
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.security.Security;
@@ -31,11 +42,7 @@
 import javax.security.auth.callback.NameCallback;
 import javax.security.auth.callback.PasswordCallback;
 import javax.security.auth.callback.UnsupportedCallbackException;
-import org.ietf.jgss.GSSContext;
-import org.ietf.jgss.GSSCredential;
 import org.ietf.jgss.GSSException;
-import org.ietf.jgss.GSSManager;
-import org.ietf.jgss.GSSName;
 import sun.security.jgss.GSSUtil;
 import sun.security.krb5.Config;
 
@@ -50,21 +57,21 @@
         // Create and start the KDCs. Here we have 3 realms: R1, R2 and R3.
         // R1 is trusted by R2, and R2 trusted by R3.
         KDC kdc1 = KDC.create("R1");
-        kdc1.setPolicy("ok-as-delegate",
+        kdc1.setOption(KDC.Option.OK_AS_DELEGATE,
                 System.getProperty("test.kdc.policy.ok-as-delegate"));
         kdc1.addPrincipal("dummy", "bogus".toCharArray());
         kdc1.addPrincipalRandKey("krbtgt/R1");
         kdc1.addPrincipal("krbtgt/R2@R1", "r1->r2".toCharArray());
 
         KDC kdc2 = KDC.create("R2");
-        kdc2.setPolicy("ok-as-delegate",
+        kdc2.setOption(KDC.Option.OK_AS_DELEGATE,
                 System.getProperty("test.kdc.policy.ok-as-delegate"));
         kdc2.addPrincipalRandKey("krbtgt/R2");
         kdc2.addPrincipal("krbtgt/R2@R1", "r1->r2".toCharArray());
         kdc2.addPrincipal("krbtgt/R3@R2", "r2->r3".toCharArray());
 
         KDC kdc3 = KDC.create("R3");
-        kdc3.setPolicy("ok-as-delegate",
+        kdc3.setOption(KDC.Option.OK_AS_DELEGATE,
                 System.getProperty("test.kdc.policy.ok-as-delegate"));
         kdc3.addPrincipalRandKey("krbtgt/R3");
         kdc3.addPrincipal("krbtgt/R3@R2", "r2->r3".toCharArray());
--- a/test/sun/security/krb5/auto/OneKDC.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/sun/security/krb5/auto/OneKDC.java	Thu Feb 06 01:43:16 2020 +0000
@@ -67,10 +67,19 @@
         addPrincipalRandKey("krbtgt/" + REALM);
         addPrincipalRandKey(SERVER);
         addPrincipalRandKey(BACKEND);
+
+        String extraConfig = "";
+        if (etype != null) {
+            extraConfig += "default_tkt_enctypes=" + etype
+                    + "\ndefault_tgs_enctypes=" + etype;
+            if (etype.startsWith("des")) {
+                extraConfig += "\nallow_weak_crypto = true";
+            }
+        }
         KDC.saveConfig(KRB5_CONF, this,
                 "forwardable = true",
                 "default_keytab_name = " + KTAB,
-                etype == null ? "" : "default_tkt_enctypes=" + etype + "\ndefault_tgs_enctypes=" + etype);
+                extraConfig);
         System.setProperty("java.security.krb5.conf", KRB5_CONF);
         // Whatever krb5.conf had been loaded before, we reload ours now.
         Config.refresh();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/security/krb5/auto/OnlyDesLogin.java	Thu Feb 06 01:43:16 2020 +0000
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8014310
+ * @summary JAAS/Krb5LoginModule using des encytypes failure with NPE after JDK-8012679
+ * @compile -XDignore.symbol.file OnlyDesLogin.java
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock OnlyDesLogin
+ */
+
+import sun.security.krb5.Config;
+
+import javax.security.auth.login.LoginException;
+
+public class OnlyDesLogin {
+
+    public static void main(String[] args) throws Exception {
+
+        OneKDC kdc = new OneKDC(null);
+        kdc.writeJAASConf();
+
+        KDC.saveConfig(OneKDC.KRB5_CONF, kdc,
+                "default_tkt_enctypes=des-cbc-md5",
+                "default_tgs_enctypes=des-cbc-md5",
+                "permitted_enctypes=des-cbc-md5");
+        Config.refresh();
+
+        try {
+            Context.fromJAAS("client");
+            throw new Exception("What?");
+        } catch (LoginException le) {
+            // This is OK
+        }
+    }
+}
--- a/test/sun/security/krb5/auto/PrincipalNameEquals.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/sun/security/krb5/auto/PrincipalNameEquals.java	Thu Feb 06 01:43:16 2020 +0000
@@ -26,7 +26,7 @@
  * @bug 7061379
  * @summary [Kerberos] Cross-realm authentication fails, due to nameType problem
  * @compile -XDignore.symbol.file PrincipalNameEquals.java
- * @run main/othervm PrincipalNameEquals
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock PrincipalNameEquals
  */
 
 import sun.security.jgss.GSSUtil;
--- a/test/sun/security/krb5/auto/RRC.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/sun/security/krb5/auto/RRC.java	Thu Feb 06 01:43:16 2020 +0000
@@ -26,7 +26,7 @@
  * @bug 7077640
  * @summary gss wrap for cfx doesn't handle rrc != 0
  * @compile -XDignore.symbol.file RRC.java
- * @run main/othervm RRC
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock RRC
  */
 
 import java.util.Arrays;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/security/krb5/auto/RefreshKrb5Config.java	Thu Feb 06 01:43:16 2020 +0000
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.File;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.login.LoginContext;
+import javax.security.auth.login.LoginException;
+
+/*
+ * @test
+ * @bug 4745056 8075297
+ * @summary Checks if refreshKrb5Config is set to true for Krb5LoginModule,
+ *          then configuration will be refreshed before login() method is called
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock RefreshKrb5Config
+ */
+public class RefreshKrb5Config {
+
+    static final String TEST_SRC = System.getProperty("test.src", ".");
+    static final String HOST = "localhost";
+    static final String NOT_EXISTING_HOST = "not.existing.host";
+    static final String REALM = "TEST.REALM";
+    static final String USER = "USER";
+    static final String USER_PRINCIPAL = USER + "@" + REALM;
+    static final String USER_PASSWORD = "password";
+    static final String KRBTGT_PRINCIPAL = "krbtgt/" + REALM;
+    static final String KRB5_CONF_FILENAME = "krb5.conf";
+
+    public static void main(String[] args) throws LoginException, IOException {
+        Map<String, String> principals = new HashMap<>();
+        principals.put(USER_PRINCIPAL, USER_PASSWORD);
+        principals.put(KRBTGT_PRINCIPAL, null);
+
+        System.setProperty("java.security.krb5.conf", KRB5_CONF_FILENAME);
+
+        // start a local KDC, and save krb5 config
+        KDC kdc = KDC.startKDC(HOST, null, REALM, principals, null, null);
+        KDC.saveConfig(KRB5_CONF_FILENAME, kdc, "max_retries = 1");
+
+        System.setProperty("java.security.auth.login.config",
+                TEST_SRC + File.separator + "refreshKrb5Config.jaas");
+
+        CallbackHandler handler = new Helper.UserPasswordHandler(
+                USER, USER_PASSWORD);
+
+        // set incorrect KDC
+        System.out.println("java.security.krb5.kdc = " + NOT_EXISTING_HOST);
+        System.setProperty("java.security.krb5.kdc", NOT_EXISTING_HOST);
+        System.out.println("java.security.krb5.realm = " + REALM);
+        System.setProperty("java.security.krb5.realm", REALM);
+        try {
+            new LoginContext("Refreshable", handler).login();
+            throw new RuntimeException("Expected exception not thrown");
+        } catch (LoginException le) {
+            System.out.println("Expected login failure: " + le);
+        }
+
+        // reset properties
+        System.out.println("Reset java.security.krb5.kdc");
+        System.clearProperty("java.security.krb5.kdc");
+        System.out.println("Reset java.security.krb5.realm");
+        System.clearProperty("java.security.krb5.realm");
+
+        // login with not-refreshable config
+        try {
+            new LoginContext("NotRefreshable", handler).login();
+            throw new RuntimeException("Expected exception not thrown");
+        } catch (LoginException le) {
+            System.out.println("Expected login failure: " + le);
+        }
+
+        // login with refreshable config
+        new LoginContext("Refreshable", handler).login();
+
+        System.out.println("Test passed");
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/security/krb5/auto/Renew.java	Thu Feb 06 01:43:16 2020 +0000
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8058290
+ * @summary JAAS Krb5LoginModule has suspect ticket-renewal logic,
+ *          relies on clockskew grace
+ * @compile -XDignore.symbol.file Renew.java
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock Renew 1
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock Renew 2
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock Renew 3
+ */
+
+import sun.security.krb5.Config;
+
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.Date;
+import javax.security.auth.kerberos.KerberosTicket;
+
+public class Renew {
+
+    public static void main(String[] args) throws Exception {
+
+        // Three test cases:
+        // 1. renewTGT=false
+        // 2. renewTGT=true with a short life time, renew will happen
+        // 3. renewTGT=true with a long life time, renew won't happen
+        int test = Integer.parseInt(args[0]);
+
+        OneKDC k = new OneKDC(null);
+        KDC.saveConfig(OneKDC.KRB5_CONF, k,
+                "renew_lifetime = 1d",
+                "ticket_lifetime = " + (test == 2? "10s": "8h"));
+        Config.refresh();
+        k.writeJAASConf();
+
+        // KDC would save ccache in a file
+        System.setProperty("test.kdc.save.ccache", "cache.here");
+
+        Files.write(Paths.get(OneKDC.JAAS_CONF), Arrays.asList(
+                "first {",
+                "   com.sun.security.auth.module.Krb5LoginModule required;",
+                "};",
+                "second {",
+                "   com.sun.security.auth.module.Krb5LoginModule required",
+                "   doNotPrompt=true",
+                "   renewTGT=" + (test != 1),
+                "   useTicketCache=true",
+                "   ticketCache=cache.here;",
+                "};"
+        ), StandardCharsets.UTF_8);
+
+        Context c;
+
+        // The first login uses username and password
+        c = Context.fromUserPass(OneKDC.USER, OneKDC.PASS, false);
+        Date d1 = c.s().getPrivateCredentials(KerberosTicket.class).iterator().next().getAuthTime();
+
+        // 6s is longer than half of 10s
+        Thread.sleep(6000);
+
+        // The second login uses the cache
+        c = Context.fromJAAS("second");
+        Date d2 = c.s().getPrivateCredentials(KerberosTicket.class).iterator().next().getAuthTime();
+
+        if (test == 2) {
+            if (d1.equals(d2)) {
+                throw new Exception("Ticket not renewed");
+            }
+        } else {
+            if (!d1.equals(d2)) {
+                throw new Exception("Ticket renewed");
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/security/krb5/auto/Renewal.java	Thu Feb 06 01:43:16 2020 +0000
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8044500
+ * @summary Add kinit options and krb5.conf flags that allow users to
+ *          obtain renewable tickets and specify ticket lifetimes
+ * @library ../../../../java/security/testlibrary/
+ * @compile -XDignore.symbol.file Renewal.java
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock Renewal
+ */
+
+import sun.security.jgss.GSSUtil;
+import sun.security.krb5.Config;
+import sun.security.krb5.internal.ccache.Credentials;
+import sun.security.krb5.internal.ccache.FileCredentialsCache;
+
+import javax.security.auth.kerberos.KerberosTicket;
+import java.util.Date;
+import java.util.Random;
+import java.util.Set;
+
+// The basic krb5 test skeleton you can copy from
+public class Renewal {
+
+    static OneKDC kdc;
+    static String clazz = "sun.security.krb5.internal.tools.Kinit";
+
+    public static void main(String[] args) throws Exception {
+
+        kdc = new OneKDC(null);
+        kdc.writeJAASConf();
+        kdc.setOption(KDC.Option.PREAUTH_REQUIRED, false);
+
+        checkLogin(null, null, KDC.DEFAULT_LIFETIME, -1);
+        checkLogin("1h", null, 3600, -1);
+        checkLogin(null, "2d", KDC.DEFAULT_LIFETIME, 86400*2);
+        checkLogin("1h", "10h", 3600, 36000);
+        // When rtime is before till, use till as rtime
+        checkLogin("10h", "1h", 36000, 36000);
+
+        try {
+            Class.forName(clazz);
+        } catch (ClassNotFoundException cnfe) {
+            return;
+        }
+
+        checkKinit(null, null, null, null, KDC.DEFAULT_LIFETIME, -1);
+        checkKinit("1h", "10h", null, null, 3600, 36000);
+        checkKinit(null, null, "30m", "5h", 1800, 18000);
+        checkKinit("1h", "10h", "30m", "5h", 1800, 18000);
+
+        checkKinitRenew();
+    }
+
+    static int count = 0;
+
+    static void checkKinit(
+            String s1,      // ticket_lifetime in krb5.conf, null if none
+            String s2,      // renew_lifetime in krb5.conf, null if none
+            String c1,      // -l on kinit, null if none
+            String c2,      // -r on kinit, null if none
+            int t1, int t2  // expected lifetimes, -1 of unexpected
+                ) throws Exception {
+        KDC.saveConfig(OneKDC.KRB5_CONF, kdc,
+                s1 != null ? ("ticket_lifetime = " + s1) : "",
+                s2 != null ? ("renew_lifetime = " + s2) : "");
+        Proc p = Proc.create(clazz);
+        if (c1 != null) {
+            p.args("-l", c1);
+        }
+        if (c2 != null) {
+            p.args("-r", c2);
+        }
+        count++;
+        p.args(OneKDC.USER, new String(OneKDC.PASS))
+                .inheritIO()
+                .prop("sun.net.spi.nameservice.provider.1", "ns,mock")
+                .prop("java.security.krb5.conf", OneKDC.KRB5_CONF)
+                .env("KRB5CCNAME", "ccache" + count)
+                .start();
+        if (p.waitFor() != 0) {
+            throw new Exception();
+        }
+        FileCredentialsCache fcc =
+                FileCredentialsCache.acquireInstance(null, "ccache" + count);
+        Credentials cred = fcc.getDefaultCreds();
+        checkRough(cred.getEndTime().toDate(), t1);
+        if (cred.getRenewTill() == null) {
+            checkRough(null, t2);
+        } else {
+            checkRough(cred.getRenewTill().toDate(), t2);
+        }
+    }
+
+    static void checkKinitRenew() throws Exception {
+        Proc p = Proc.create(clazz)
+                .args("-R")
+                .inheritIO()
+                .prop("sun.net.spi.nameservice.provider.1", "ns,mock")
+                .prop("java.security.krb5.conf", OneKDC.KRB5_CONF)
+                .env("KRB5CCNAME", "ccache" + count)
+                .start();
+        if (p.waitFor() != 0) {
+            throw new Exception();
+        }
+    }
+
+    static void checkLogin(
+            String s1,      // ticket_lifetime in krb5.conf, null if none
+            String s2,      // renew_lifetime in krb5.conf, null if none
+            int t1, int t2  // expected lifetimes, -1 of unexpected
+                ) throws Exception {
+        KDC.saveConfig(OneKDC.KRB5_CONF, kdc,
+                s1 != null ? ("ticket_lifetime = " + s1) : "",
+                s2 != null ? ("renew_lifetime = " + s2) : "");
+        Config.refresh();
+
+        Context c;
+        c = Context.fromJAAS("client");
+
+        Set<KerberosTicket> tickets =
+                c.s().getPrivateCredentials(KerberosTicket.class);
+        if (tickets.size() != 1) {
+            throw new Exception();
+        }
+        KerberosTicket ticket = tickets.iterator().next();
+
+        checkRough(ticket.getEndTime(), t1);
+        checkRough(ticket.getRenewTill(), t2);
+    }
+
+    static void checkRough(Date t, int duration) throws Exception {
+        Date now = new Date();
+        if (t == null && duration == -1) {
+            return;
+        }
+        long change = (t.getTime() - System.currentTimeMillis()) / 1000;
+        if (change > duration + 20 || change < duration - 20) {
+            throw new Exception(t + " is not " + duration);
+        }
+    }
+}
--- a/test/sun/security/krb5/auto/ReplayCache.java	Wed Nov 20 06:36:47 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,64 +0,0 @@
-/*
- * Copyright 2012 Sun Microsystems, Inc.  All Rights Reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- */
-
-/*
- * @test
- * @bug 7118809
- * @run main/othervm ReplayCache
- * @summary rcache deadlock
- */
-
-import org.ietf.jgss.GSSException;
-import sun.security.jgss.GSSUtil;
-import sun.security.krb5.KrbException;
-import sun.security.krb5.internal.Krb5;
-
-public class ReplayCache {
-
-    public static void main(String[] args)
-            throws Exception {
-
-        new OneKDC(null).writeJAASConf();
-
-        Context c, s;
-        c = Context.fromJAAS("client");
-        s = Context.fromJAAS("server");
-
-        c.startAsClient(OneKDC.SERVER, GSSUtil.GSS_KRB5_MECH_OID);
-        s.startAsServer(GSSUtil.GSS_KRB5_MECH_OID);
-
-        byte[] first = c.take(new byte[0]);
-        s.take(first);
-
-        s.startAsServer(GSSUtil.GSS_KRB5_MECH_OID);
-        try {
-            s.take(first);  // Replay the last token sent
-            throw new Exception("This method should fail");
-        } catch (GSSException gsse) {
-            KrbException ke = (KrbException)gsse.getCause();
-            if (ke.returnCode() != Krb5.KRB_AP_ERR_REPEAT) {
-                throw gsse;
-            }
-        }
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/security/krb5/auto/ReplayCacheExpunge.java	Thu Feb 06 01:43:16 2020 +0000
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+*/
+
+/*
+ * @test
+ * @bug 8001326
+ * @run main/othervm ReplayCacheExpunge 16
+ * @run main/othervm/fail ReplayCacheExpunge 15
+ * @summary when number of expired entries minus number of good entries
+ * is more than 30, expunge occurs, and expired entries are forgotten.
+*/
+
+import java.util.Random;
+import sun.security.krb5.internal.KerberosTime;
+import sun.security.krb5.internal.ReplayCache;
+import sun.security.krb5.internal.rcache.AuthTimeWithHash;
+
+public class ReplayCacheExpunge {
+    static final String client = "dummy@REALM";
+    static final String server = "server/localhost@REALM";
+    static final Random rand = new Random();
+
+    public static void main(String[] args) throws Exception {
+        // Make sure clockskew is default value
+        System.setProperty("java.security.krb5.conf", "nothing");
+
+        int count = Integer.parseInt(args[0]);
+        ReplayCache cache = ReplayCache.getInstance("dfl:./");
+        AuthTimeWithHash a1 =
+                new AuthTimeWithHash(client, server, time(-400), 0, hash("1"));
+        AuthTimeWithHash a2 =
+                new AuthTimeWithHash(client, server, time(0), 0, hash("4"));
+        KerberosTime now = new KerberosTime(time(0)*1000L);
+        KerberosTime then = new KerberosTime(time(-300)*1000L);
+
+        // Once upon a time, we added a lot of events
+        for (int i=0; i<count; i++) {
+            a1 = new AuthTimeWithHash(client, server, time(-400), 0, hash(""));
+            cache.checkAndStore(then, a1);
+        }
+
+        // Now, we add a new one. If some conditions hold, the old ones
+        // will be expunged.
+        cache.checkAndStore(now, a2);
+
+        // and adding an old one will not trigger any error
+        cache.checkAndStore(now, a1);
+    }
+
+    private static String hash(String s) {
+        char[] data = new char[16];
+        for (int i=0; i<16; i++) {
+            if (i < s.length()) data[i] = s.charAt(i);
+            else data[i] = (char)('0' + rand.nextInt(10));
+        }
+        return new String(data);
+    }
+
+    private static int time(int x) {
+        return (int)(System.currentTimeMillis()/1000) + x;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/security/krb5/auto/ReplayCachePrecise.java	Thu Feb 06 01:43:16 2020 +0000
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+*/
+
+/*
+ * @test
+ * @bug 8001326
+ * @run main/othervm ReplayCachePrecise
+ * @summary when there are 2 two AuthTime with the same time but different hash,
+ * it's not a replay.
+*/
+
+import java.nio.ByteBuffer;
+import java.nio.channels.SeekableByteChannel;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.nio.file.StandardOpenOption;
+import java.util.Random;
+import sun.security.krb5.KrbException;
+import sun.security.krb5.internal.KerberosTime;
+import sun.security.krb5.internal.ReplayCache;
+import sun.security.krb5.internal.rcache.AuthTimeWithHash;
+
+public class ReplayCachePrecise {
+    static final String client = "dummy@REALM";
+    static final String server = "server/localhost@REALM";
+    static final Random rand = new Random();
+
+    public static void main(String[] args) throws Exception {
+
+        AuthTimeWithHash a1 = new AuthTimeWithHash(client, server, time(0), 0,
+                "1111111111111111");
+        AuthTimeWithHash a2 = new AuthTimeWithHash(client, server, time(0), 0,
+                "2222222222222222");
+        KerberosTime now = new KerberosTime(time(0)*1000L);
+
+        // When all new styles, must exact match
+        ReplayCache cache = ReplayCache.getInstance("dfl:./c1");
+        cache.checkAndStore(now, a1);
+        cache.checkAndStore(now, a2);
+
+        // When only old style in cache, partial match
+        cache = ReplayCache.getInstance("dfl:./c2");
+        cache.checkAndStore(now, a1);
+        // A small surgery to remove the new style from the cache file
+        SeekableByteChannel ch = Files.newByteChannel(Paths.get("c2"),
+                StandardOpenOption.WRITE,
+                StandardOpenOption.READ);
+        ch.position(6);
+        ch.write(ByteBuffer.wrap(a1.encode(false)));
+        ch.truncate(ch.position());
+        ch.close();
+        try {
+            cache.checkAndStore(now, a2);
+            throw new Exception();
+        } catch (KrbException ke) {
+            // Correct
+            System.out.println(ke);
+        }
+    }
+
+    private static int time(int x) {
+        return (int)(System.currentTimeMillis()/1000) + x;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/security/krb5/auto/ReplayCacheTest.java	Thu Feb 06 01:43:16 2020 +0000
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2012 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 7118809 8001326
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock ReplayCacheTest jvm
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock ReplayCacheTest dfl
+ * @summary rcache deadlock
+ */
+
+import java.io.File;
+import org.ietf.jgss.GSSException;
+import sun.security.jgss.GSSUtil;
+import sun.security.krb5.KrbException;
+import sun.security.krb5.internal.Krb5;
+
+public class ReplayCacheTest {
+
+    public static void main(String[] args)
+            throws Exception {
+
+        new OneKDC(null);
+
+        if (args[0].equals("dfl")) {
+            // Store file in scratch directory
+            args[0] = "dfl:" + System.getProperty("user.dir") + File.separator;
+            System.setProperty("sun.security.krb5.rcache", args[0]);
+        }
+
+        Context c, s;
+        c = Context.fromUserPass(OneKDC.USER, OneKDC.PASS, false);
+        s = Context.fromUserKtab(OneKDC.SERVER, OneKDC.KTAB, true);
+
+        c.startAsClient(OneKDC.SERVER, GSSUtil.GSS_KRB5_MECH_OID);
+        s.startAsServer(GSSUtil.GSS_KRB5_MECH_OID);
+
+        byte[] first = c.take(new byte[0]);
+        c.take(s.take(first));
+
+        s.startAsServer(GSSUtil.GSS_KRB5_MECH_OID);
+        try {
+            s.take(first);  // Replay the last apreq sent
+            throw new Exception("This method should fail");
+        } catch (GSSException gsse) {
+            gsse.printStackTrace();
+            KrbException ke = (KrbException)gsse.getCause();
+            if (ke.returnCode() != Krb5.KRB_AP_ERR_REPEAT) {
+                throw gsse;
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/security/krb5/auto/ReplayCacheTestProc.java	Thu Feb 06 01:43:16 2020 +0000
@@ -0,0 +1,350 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 7152176
+ * @summary More krb5 tests
+ * @library ../../../../java/security/testlibrary/
+ * @compile -XDignore.symbol.file ReplayCacheTestProc.java
+ * @run main/othervm/timeout=100 -Dsun.net.spi.nameservice.provider.1=ns,mock ReplayCacheTestProc
+ */
+
+import java.io.*;
+import java.nio.BufferUnderflowException;
+import java.nio.channels.SeekableByteChannel;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.nio.file.StandardCopyOption;
+import java.nio.file.StandardOpenOption;
+import java.security.MessageDigest;
+import java.util.*;
+
+import sun.misc.BASE64Decoder;
+import sun.security.jgss.GSSUtil;
+import sun.security.krb5.internal.APReq;
+import sun.security.krb5.internal.rcache.AuthTime;
+
+// This test runs multiple acceptor Procs to mimin AP-REQ replays.
+public class ReplayCacheTestProc {
+
+    private static Proc[] ps;
+    private static Proc pc;
+    private static List<Req> reqs = new ArrayList<>();
+    private static String HOST = "localhost";
+
+    // Where should the rcache be saved. It seems KRB5RCACHEDIR is not
+    // recognized on Solaris. Maybe version too low? I see 1.6.
+    private static String cwd =
+            System.getProperty("os.name").startsWith("SunOS") ?
+                "/var/krb5/rcache/" :
+                System.getProperty("user.dir");
+
+
+    private static int uid;
+
+    public static void main0(String[] args) throws Exception {
+        System.setProperty("java.security.krb5.conf", OneKDC.KRB5_CONF);
+        if (args.length == 0) { // The controller
+            int ns = 5;     // number of servers
+            int nu = 5;     // number of users
+            int nx = 50;    // number of experiments
+            int np = 5;     // number of peers (services)
+            int mode = 0;   // native(1), random(0), java(-1)
+            boolean random = true;      // random experiments choreograph
+
+            // Do not test interop with native GSS on some platforms
+            String os = System.getProperty("os.name", "???");
+            if (!os.startsWith("SunOS") && !os.startsWith("Linux")) {
+                mode = -1;
+            }
+
+            try {
+                Class<?> clazz = Class.forName(
+                        "com.sun.security.auth.module.UnixSystem");
+                uid = (int)(long)(Long)
+                        clazz.getMethod("getUid").invoke(clazz.newInstance());
+            } catch (Exception e) {
+                uid = -1;
+            }
+
+            KDC kdc = KDC.create(OneKDC.REALM, HOST, 0, true);
+            for (int i=0; i<nu; i++) {
+                kdc.addPrincipal(user(i), OneKDC.PASS);
+            }
+            kdc.addPrincipalRandKey("krbtgt/" + OneKDC.REALM);
+            for (int i=0; i<np; i++) {
+                kdc.addPrincipalRandKey(peer(i));
+            }
+
+            kdc.writeKtab(OneKDC.KTAB);
+            KDC.saveConfig(OneKDC.KRB5_CONF, kdc);
+
+            if (mode != -1) {
+                // A special native server to check basic sanity
+                if (ns(-1).waitFor() != 0) {
+                    Proc.d("Native mode sanity check failed, revert to java");
+                    mode = -1;
+                }
+            }
+
+            pc = Proc.create("ReplayCacheTestProc").debug("C")
+                    .args("client")
+                    .start();
+            ps = new Proc[ns];
+            Ex[] result = new Ex[nx];
+
+            if (!random) {
+                // 2 experiments, 2 server, 1 peer, 1 user
+                nx = 2; ns = 2; np = 1; nu = 1;
+
+                // Creates reqs from user# to peer#
+                req(0, 0);
+
+                // Creates server#
+                ps[0] = ns(0);
+                ps[1] = js(1);
+
+                // Runs ex# using req# to server# with expected result
+                result[0] = round(0, 0, 0, true);
+                result[1] = round(1, 0, 1, false);
+            } else {
+                Random r = new Random();
+                for (int i=0; i<ns; i++) {
+                    boolean useNative = (mode == 1) ? true
+                            : (mode == -1 ? false : r.nextBoolean());
+                    ps[i] = useNative?ns(i):js(i);
+                }
+                for (int i=0; i<nx; i++) {
+                    result[i] = new Ex();
+                    int old;    // which req to send
+                    boolean expected;
+                    if (reqs.isEmpty() || r.nextBoolean()) {
+                        Proc.d("Console get new AP-REQ");
+                        old = req(r.nextInt(nu), r.nextInt(np));
+                        expected = true;
+                    } else {
+                        Proc.d("Console resue old");
+                        old = r.nextInt(reqs.size());
+                        expected = false;
+                    }
+                    int s = r.nextInt(ns);
+                    Proc.d("Console send to " + s);
+                    result[i] = round(i, old, s, expected);
+                    Proc.d("Console sees " + result[i].actual);
+                }
+            }
+
+            pc.println("END");
+            for (int i=0; i<ns; i++) {
+                ps[i].println("END");
+            }
+            System.out.println("Result\n======");
+            boolean finalOut = true;
+            for (int i=0; i<nx; i++) {
+                boolean out = result[i].expected==result[i].actual;
+                finalOut &= out;
+                System.out.printf("%3d: %s (%2d): u%d h%d %s %s   %s %2d\n",
+                        i,
+                        result[i].expected?"----":"    ",
+                        result[i].old,
+                        result[i].user, result[i].peer, result[i].server,
+                        result[i].actual?"Good":"Bad ",
+                        out?"   ":"xxx",
+                        result[i].csize);
+            }
+            if (!finalOut) throw new Exception();
+        } else if (args[0].equals("N-1")) {
+            // Native mode sanity check
+            Proc.d("Detect start");
+            Context s = Context.fromUserKtab("*", OneKDC.KTAB, true);
+            s.startAsServer(GSSUtil.GSS_KRB5_MECH_OID);
+        } else if (args[0].equals("client")) {
+            while (true) {
+                String title = Proc.textIn();
+                Proc.d("Client see " + title);
+                if (title.equals("END")) break;
+                String[] cas = title.split(" ");
+                Context c = Context.fromUserPass(cas[0], OneKDC.PASS, false);
+                c.startAsClient(cas[1], GSSUtil.GSS_KRB5_MECH_OID);
+                c.x().requestCredDeleg(true);
+                byte[] token = c.take(new byte[0]);
+                Proc.d("Client AP-REQ generated");
+                Proc.binOut(token);
+            }
+        } else {
+            Proc.d("Server start");
+            Context s = Context.fromUserKtab("*", OneKDC.KTAB, true);
+            Proc.d("Server login");
+            while (true) {
+                String title = Proc.textIn();
+                Proc.d("Server " + args[0] + " sees " + title);
+                if (title.equals("END")) break;
+                s.startAsServer(GSSUtil.GSS_KRB5_MECH_OID);
+                byte[] token = Proc.binIn();
+                try {
+                    s.take(token);
+                    Proc.textOut("true");
+                    Proc.d(args[0] + " Good");
+                } catch (Exception e) {
+                    Proc.textOut("false");
+                    Proc.d(args[0] + " Bad");
+                }
+            }
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+        try {
+            main0(args);
+        } catch (Exception e) {
+            Proc.d(e);
+            throw e;
+        }
+    }
+
+    // returns the user name
+    private static String user(int p) {
+        return "USER" + p;
+    }
+    // returns the peer name
+    private static String peer(int p) {
+        return "host" + p + "/" + HOST;
+    }
+    // returns the dfl name for a host
+    private static String dfl(int p) {
+        return cwd + "host" + p + (uid == -1 ? "" : ("_"+uid));
+    }
+    // generates an ap-req and save into reqs, returns the index
+    private static int req(int user, int peer) throws Exception {
+        pc.println(user(user) + " " + peer(peer));
+        Req req = new Req(user, peer, pc.readData());
+        reqs.add(req);
+        return reqs.size() - 1;
+    }
+    // carries out a round of experiment
+    // i: ex#, old: which req, server: which server, expected: result?
+    private static Ex round(int i, int old, int server, boolean expected)
+            throws Exception {
+        ps[server].println("TEST");
+        ps[server].println(reqs.get(old).msg);
+        String reply = ps[server].readData();
+        Ex result = new Ex();
+        result.i = i;
+        result.expected = expected;
+        result.server = ps[server].debug();
+        result.actual = Boolean.valueOf(reply);
+        result.user = reqs.get(old).user;
+        result.peer = reqs.get(old).peer;
+        result.old = old;
+        result.csize = csize(result.peer);
+        result.hash = hash(reqs.get(old).msg);
+        if (new File(dfl(result.peer)).exists()) {
+            Files.copy(Paths.get(dfl(result.peer)), Paths.get(
+                String.format("%03d-USER%d-host%d-%s-%s",
+                    i, result.user, result.peer, result.server,
+                    result.actual)
+                + "-" + result.hash),
+                StandardCopyOption.COPY_ATTRIBUTES);
+        }
+        return result;
+    }
+    // create a native server
+    private static Proc ns(int i) throws Exception {
+        return Proc.create("ReplayCacheTestProc")
+                .args("N"+i)
+                .env("KRB5_CONFIG", OneKDC.KRB5_CONF)
+                .env("KRB5_KTNAME", OneKDC.KTAB)
+                .env("KRB5RCACHEDIR", cwd)
+                .prop("sun.security.jgss.native", "true")
+                .prop("javax.security.auth.useSubjectCredsOnly", "false")
+                .prop("sun.security.nativegss.debug", "true")
+                .prop("sun.net.spi.nameservice.provider.1", "ns,mock")
+                .debug("N"+i)
+                .start();
+    }
+    // creates a java server
+    private static Proc js(int i) throws Exception {
+        return Proc.create("ReplayCacheTestProc")
+                .debug("S"+i)
+                .args("S"+i)
+                .prop("sun.security.krb5.rcache", "dfl")
+                .prop("java.io.tmpdir", cwd)
+                .prop("sun.net.spi.nameservice.provider.1", "ns,mock")
+                .start();
+    }
+    // generates hash of authenticator inside ap-req inside initsectoken
+    private static String hash(String req) throws Exception {
+        byte[] data = new BASE64Decoder().decodeBuffer(req);
+        data = Arrays.copyOfRange(data, 17, data.length);
+        byte[] hash = MessageDigest.getInstance("MD5").digest(new APReq(data).authenticator.getBytes());
+        char[] h = new char[hash.length * 2];
+        char[] hexConst = "0123456789ABCDEF".toCharArray();
+        for (int i=0; i<hash.length; i++) {
+            h[2*i] = hexConst[(hash[i]&0xff)>>4];
+            h[2*i+1] = hexConst[hash[i]&0xf];
+        }
+        return new String(h);
+    }
+    // return size of dfl file, excluding the null hash ones
+    private static int csize(int p) throws Exception {
+        try (SeekableByteChannel chan = Files.newByteChannel(
+                Paths.get(dfl(p)), StandardOpenOption.READ)) {
+            chan.position(6);
+            int cc = 0;
+            while (true) {
+                try {
+                    if (AuthTime.readFrom(chan) != null) cc++;
+                } catch (BufferUnderflowException e) {
+                    break;
+                }
+            }
+            return cc;
+        } catch (IOException ioe) {
+            return 0;
+        }
+    }
+    // models an experiement
+    private static class Ex {
+        int i;              // #
+        boolean expected;   // expected result
+        boolean actual;     // actual output
+        int old;            // which ap-req to send
+        String server;      // which server to send to
+        String hash;        // the hash of req
+        int user;           // which initiator
+        int peer;           // which acceptor
+        int csize;          // size of rcache after test
+    }
+    // models a saved ap-req msg
+    private static class Req {
+        String msg;         // based64-ed req
+        int user;           // which initiator
+        int peer;           // which accceptor
+        Req(int user, int peer, String msg) {
+            this.msg = msg;
+            this.user= user;
+            this.peer = peer;
+        }
+    }
+}
--- a/test/sun/security/krb5/auto/SPNEGO.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/sun/security/krb5/auto/SPNEGO.java	Thu Feb 06 01:43:16 2020 +0000
@@ -26,7 +26,7 @@
  * @bug 7040151
  * @summary SPNEGO GSS code does not parse tokens in accordance to RFC 2478
  * @compile -XDignore.symbol.file SPNEGO.java
- * @run main/othervm SPNEGO
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock SPNEGO
  */
 
 import sun.security.jgss.GSSUtil;
--- a/test/sun/security/krb5/auto/SSL.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/sun/security/krb5/auto/SSL.java	Thu Feb 06 01:43:16 2020 +0000
@@ -25,16 +25,16 @@
  * @test
  * @bug 6894643 6913636
  * @summary Test JSSE Kerberos ciphersuite
- * @run main/othervm SSL TLS_KRB5_WITH_RC4_128_SHA
- * @run main/othervm SSL TLS_KRB5_WITH_RC4_128_MD5
- * @run main/othervm SSL TLS_KRB5_WITH_3DES_EDE_CBC_SHA
- * @run main/othervm SSL TLS_KRB5_WITH_3DES_EDE_CBC_MD5
- * @run main/othervm SSL TLS_KRB5_WITH_DES_CBC_SHA
- * @run main/othervm SSL TLS_KRB5_WITH_DES_CBC_MD5
- * @run main/othervm SSL TLS_KRB5_EXPORT_WITH_RC4_40_SHA
- * @run main/othervm SSL TLS_KRB5_EXPORT_WITH_RC4_40_MD5
- * @run main/othervm SSL TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA
- * @run main/othervm SSL TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock SSL TLS_KRB5_WITH_RC4_128_SHA
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock SSL TLS_KRB5_WITH_RC4_128_MD5
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock SSL TLS_KRB5_WITH_3DES_EDE_CBC_SHA
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock SSL TLS_KRB5_WITH_3DES_EDE_CBC_MD5
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock SSL TLS_KRB5_WITH_DES_CBC_SHA
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock SSL TLS_KRB5_WITH_DES_CBC_MD5
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock SSL TLS_KRB5_EXPORT_WITH_RC4_40_SHA
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock SSL TLS_KRB5_EXPORT_WITH_RC4_40_MD5
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock SSL TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock SSL TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5
  */
 import java.io.*;
 import java.net.InetAddress;
--- a/test/sun/security/krb5/auto/SaslGSS.java	Wed Nov 20 06:36:47 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,137 +0,0 @@
-/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * @test
- * @bug 8012082 8019267
- * @summary SASL: auth-conf negotiated, but unencrypted data is accepted,
-  *         reset to unencrypt
- * @compile -XDignore.symbol.file SaslGSS.java
- * @run main/othervm SaslGSS
- */
-
-import javax.security.auth.callback.Callback;
-import javax.security.auth.callback.CallbackHandler;
-import javax.security.auth.callback.UnsupportedCallbackException;
-import javax.security.sasl.AuthorizeCallback;
-import javax.security.sasl.RealmCallback;
-import javax.security.sasl.Sasl;
-import javax.security.sasl.SaslServer;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.PrintStream;
-import java.util.HashMap;
-import java.util.Locale;
-import java.util.logging.ConsoleHandler;
-import java.util.logging.Handler;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import org.ietf.jgss.*;
-import sun.security.jgss.GSSUtil;
-
-public class SaslGSS {
-
-    public static void main(String[] args) throws Exception {
-
-        String name = "host." + OneKDC.REALM.toLowerCase(Locale.US);
-
-        new OneKDC(null).writeJAASConf();
-        System.setProperty("javax.security.auth.useSubjectCredsOnly", "false");
-
-        // Client in JGSS so that it can control wrap privacy mode
-        GSSManager m = GSSManager.getInstance();
-        GSSContext sc = m.createContext(
-                        m.createName(OneKDC.SERVER, GSSUtil.NT_GSS_KRB5_PRINCIPAL),
-                        GSSUtil.GSS_KRB5_MECH_OID,
-                        null,
-                        GSSContext.DEFAULT_LIFETIME);
-        sc.requestMutualAuth(false);
-
-        // Server in SASL
-        final HashMap props = new HashMap();
-        props.put(Sasl.QOP, "auth-conf");
-        SaslServer ss = Sasl.createSaslServer("GSSAPI", "server",
-                name, props,
-                new CallbackHandler() {
-                    public void handle(Callback[] callbacks)
-                            throws IOException, UnsupportedCallbackException {
-                        for (Callback cb : callbacks) {
-                            if (cb instanceof RealmCallback) {
-                                ((RealmCallback) cb).setText(OneKDC.REALM);
-                            } else if (cb instanceof AuthorizeCallback) {
-                                ((AuthorizeCallback) cb).setAuthorized(true);
-                            }
-                        }
-                    }
-                });
-
-        ByteArrayOutputStream bout = new ByteArrayOutputStream();
-        PrintStream oldErr = System.err;
-        System.setErr(new PrintStream(bout));
-
-        Logger.getLogger("javax.security.sasl").setLevel(Level.ALL);
-        Handler h = new ConsoleHandler();
-        h.setLevel(Level.ALL);
-        Logger.getLogger("javax.security.sasl").addHandler(h);
-
-        byte[] token = new byte[0];
-
-        try {
-            // Handshake
-            token = sc.initSecContext(token, 0, token.length);
-            token = ss.evaluateResponse(token);
-            token = sc.unwrap(token, 0, token.length, new MessageProp(0, false));
-            token[0] = (byte)(((token[0] & 4) != 0) ? 4 : 2);
-            token = sc.wrap(token, 0, token.length, new MessageProp(0, false));
-            ss.evaluateResponse(token);
-        } finally {
-            System.setErr(oldErr);
-        }
-
-        // Talk
-        // 1. Client sends a auth-int message
-        byte[] hello = "hello".getBytes();
-        MessageProp qop = new MessageProp(0, false);
-        token = sc.wrap(hello, 0, hello.length, qop);
-        // 2. Server accepts it anyway
-        ss.unwrap(token, 0, token.length);
-        // 3. Server sends a message
-        token = ss.wrap(hello, 0, hello.length);
-        // 4. Client accepts, should be auth-conf
-        sc.unwrap(token, 0, token.length, qop);
-        if (!qop.getPrivacy()) {
-            throw new Exception();
-        }
-
-        for (String s: bout.toString().split("\\n")) {
-            if (s.contains("KRB5SRV04") && s.contains("NULL")) {
-                return;
-            }
-        }
-        System.out.println("=======================");
-        System.out.println(bout.toString());
-        System.out.println("=======================");
-        throw new Exception("Haven't seen KRB5SRV04 with NULL");
-    }
-}
--- a/test/sun/security/krb5/auto/SpnegoReqFlags.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/sun/security/krb5/auto/SpnegoReqFlags.java	Thu Feb 06 01:43:16 2020 +0000
@@ -24,7 +24,7 @@
 /*
  * @test
  * @bug 6815182
- * @run main/othervm SpnegoReqFlags
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock SpnegoReqFlags
  * @summary GSSAPI/SPNEGO does not work with server using MIT Kerberos library
  */
 
--- a/test/sun/security/krb5/auto/TcpTimeout.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/sun/security/krb5/auto/TcpTimeout.java	Thu Feb 06 01:43:16 2020 +0000
@@ -25,7 +25,7 @@
  * @test
  * @bug 6952519
  * @compile -XDignore.symbol.file TcpTimeout.java
- * @run main/othervm TcpTimeout
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock TcpTimeout
  * @summary kdc_timeout is not being honoured when using TCP
  */
 
--- a/test/sun/security/krb5/auto/Test5653.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/sun/security/krb5/auto/Test5653.java	Thu Feb 06 01:43:16 2020 +0000
@@ -24,7 +24,7 @@
 /*
  * @test
  * @bug 6895424
- * @run main/othervm Test5653
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock Test5653
  * @summary RFC 5653
  */
 
--- a/test/sun/security/krb5/auto/TicketSName.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/sun/security/krb5/auto/TicketSName.java	Thu Feb 06 01:43:16 2020 +0000
@@ -26,7 +26,7 @@
  * @bug 8178794
  * @summary krb5 client should ignore sname in incoming tickets
  * @compile -XDignore.symbol.file TicketSName.java
- * @run main/othervm -Dtest.kdc.diff.sname TicketSName
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock -Dtest.kdc.diff.sname TicketSName
  */
 
 import java.util.Set;
--- a/test/sun/security/krb5/auto/TwoPrinces.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/sun/security/krb5/auto/TwoPrinces.java	Thu Feb 06 01:43:16 2020 +0000
@@ -25,7 +25,7 @@
  * @test
  * @bug 6894072
  * @compile -XDignore.symbol.file TwoPrinces.java
- * @run main/othervm TwoPrinces
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock TwoPrinces
  * @summary always refresh keytab
  */
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/security/krb5/auto/TwoTab.java	Thu Feb 06 01:43:16 2020 +0000
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 7152176
+ * @summary More krb5 tests
+ * @compile -XDignore.symbol.file TwoTab.java
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock TwoTab
+ */
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.nio.file.Files;
+import java.security.Security;
+import sun.security.jgss.GSSUtil;
+import sun.security.krb5.PrincipalName;
+import sun.security.krb5.internal.ktab.KeyTab;
+
+// Two services using their own keytab.
+public class TwoTab {
+
+    public static void main(String[] args) throws Exception {
+
+        KDC k = new OneKDC(null);
+
+        // Write JAAS conf, two service using different keytabs
+        System.setProperty("java.security.auth.login.config", OneKDC.JAAS_CONF);
+        File f = new File(OneKDC.JAAS_CONF);
+        try (FileOutputStream fos = new FileOutputStream(f)) {
+            fos.write((
+                "server {\n" +
+                "    com.sun.security.auth.module.Krb5LoginModule required\n" +
+                "    principal=\"" + OneKDC.SERVER + "\"\n" +
+                "    useKeyTab=true\n" +
+                "    keyTab=server.keytab\n" +
+                "    storeKey=true;\n};\n" +
+                "server2 {\n" +
+                "    com.sun.security.auth.module.Krb5LoginModule required\n" +
+                "    principal=\"" + OneKDC.BACKEND + "\"\n" +
+                "    useKeyTab=true\n" +
+                "    keyTab=backend.keytab\n" +
+                "    storeKey=true;\n};\n"
+                ).getBytes());
+        }
+        f.deleteOnExit();
+
+        k.writeKtab("server.keytab", false, "server/host.rabbit.hole@RABBIT.HOLE");
+        k.writeKtab("backend.keytab", false, "backend/host.rabbit.hole@RABBIT.HOLE");
+
+        Context c, s, s2;
+        c = Context.fromUserPass(OneKDC.USER, OneKDC.PASS, false);
+        s = Context.fromJAAS("server");
+        s2 = Context.fromJAAS("server2");
+
+        c.startAsClient(OneKDC.SERVER, GSSUtil.GSS_KRB5_MECH_OID);
+        s.startAsServer(GSSUtil.GSS_KRB5_MECH_OID);
+
+        Context.handshake(c, s);
+
+        Context.transmit("i say high --", c, s);
+        Context.transmit("   you say low", s, c);
+
+        s.dispose();
+        c.dispose();
+
+        c = Context.fromUserPass(OneKDC.USER, OneKDC.PASS, false);
+        c.startAsClient(OneKDC.BACKEND, GSSUtil.GSS_KRB5_MECH_OID);
+        s2.startAsServer(GSSUtil.GSS_KRB5_MECH_OID);
+
+        Context.handshake(c, s2);
+
+        Context.transmit("i say high --", c, s2);
+        Context.transmit("   you say low", s2, c);
+
+        s2.dispose();
+        c.dispose();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/security/krb5/auto/UdpTcp.java	Thu Feb 06 01:43:16 2020 +0000
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4966382 8039132
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock UdpTcp UDP
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock UdpTcp TCP
+ * @summary udp or tcp
+ */
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+import sun.security.krb5.Config;
+
+public class UdpTcp {
+
+    public static void main(String[] args)
+            throws Exception {
+
+        System.setProperty("sun.security.krb5.debug", "true");
+
+        OneKDC kdc = new OneKDC(null);
+        kdc.writeJAASConf();
+
+        // Two styles of kdc_timeout setting. One global, one realm-specific.
+        if (args[0].equals("UDP")) {
+            KDC.saveConfig(OneKDC.KRB5_CONF, kdc,
+                    "kdc_timeout = 10s");
+        } else {
+            kdc.addConf("kdc_timeout = 10s");
+            KDC.saveConfig(OneKDC.KRB5_CONF, kdc,
+                    "udp_preference_limit = 1");
+        }
+        Config.refresh();
+
+        ByteArrayOutputStream bo = new ByteArrayOutputStream();
+        PrintStream oldout = System.out;
+        System.setOut(new PrintStream(bo));
+        Context.fromUserPass(OneKDC.USER, OneKDC.PASS, false);
+        System.setOut(oldout);
+
+        for (String line: new String(bo.toByteArray()).split("\n")) {
+            if (line.contains(">>> KDCCommunication")) {
+                if (!line.contains(args[0]) || !line.contains("timeout=10000")) {
+                    throw new Exception("No " + args[0] + " in: " + line);
+                }
+            }
+        }
+    }
+}
--- a/test/sun/security/krb5/auto/UseCacheAndStoreKey.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/sun/security/krb5/auto/UseCacheAndStoreKey.java	Thu Feb 06 01:43:16 2020 +0000
@@ -27,7 +27,7 @@
  * @summary Krb5LoginModule shows NPE when both useTicketCache and storeKey
  *          are set to true
  * @compile -XDignore.symbol.file UseCacheAndStoreKey.java
- * @run main/othervm UseCacheAndStoreKey
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock UseCacheAndStoreKey
  */
 
 import java.io.FileOutputStream;
--- a/test/sun/security/krb5/auto/W83.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/sun/security/krb5/auto/W83.java	Thu Feb 06 01:43:16 2020 +0000
@@ -26,8 +26,8 @@
  * @bug 6932525 6951366 6959292
  * @summary kerberos login failure on win2008 with AD set to win2000 compat mode
  * and cannot login if session key and preauth does not use the same etype
- * @run main/othervm -D6932525 W83
- * @run main/othervm -D6959292 W83
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock -D6932525 W83
+ * @run main/othervm -Dsun.net.spi.nameservice.provider.1=ns,mock -D6959292 W83
  */
 import com.sun.security.auth.module.Krb5LoginModule;
 import java.io.File;
--- a/test/sun/security/krb5/auto/ok-as-delegate-xrealm.sh	Wed Nov 20 06:36:47 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,79 +0,0 @@
-#
-# Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#
-
-# @test
-# @bug 6853328
-# @summary Support OK-AS-DELEGATE flag
-# @run shell/timeout=600 ok-as-delegate-xrealm.sh
-#
-
-if [ "${TESTSRC}" = "" ] ; then
-  TESTSRC=`dirname $0`
-fi
-
-if [ "${TESTJAVA}" = "" ] ; then
-  JAVAC_CMD=`which javac`
-  TESTJAVA=`dirname $JAVAC_CMD`/..
-fi
-
-# set platform-dependent variables
-OS=`uname -s`
-case "$OS" in
-  Windows_* )
-    FS="\\"
-    SEP=";"
-    ;;
-  CYGWIN* )
-    FS="/"
-    SEP=";"
-    ;;
-  * )
-    FS="/"
-    SEP=":"
-    ;;
-esac
-
-${TESTJAVA}${FS}bin${FS}javac -XDignore.symbol.file -d . \
-    ${TESTSRC}${FS}OkAsDelegateXRealm.java \
-    ${TESTSRC}${FS}KDC.java \
-    ${TESTSRC}${FS}OneKDC.java \
-    ${TESTSRC}${FS}Action.java \
-    ${TESTSRC}${FS}Context.java \
-    || exit 10
-
-# Add $TESTSRC to classpath so that customized nameservice can be used
-J="${TESTJAVA}${FS}bin${FS}java -cp $TESTSRC${SEP}."
-
-# KDC no OK-AS-DELEGATE, fail
-$J OkAsDelegateXRealm false || exit 1
-
-# KDC set OK-AS-DELEGATE for all, succeed
-$J -Dtest.kdc.policy.ok-as-delegate OkAsDelegateXRealm true || exit 2
-
-# KDC set OK-AS-DELEGATE for host/host.r3.local only, fail
-$J -Dtest.kdc.policy.ok-as-delegate=host/host.r3.local OkAsDelegateXRealm false || exit 3
-
-# KDC set OK-AS-DELEGATE for all, succeed
-$J "-Dtest.kdc.policy.ok-as-delegate=host/host.r3.local krbtgt/R2 krbtgt/R3" OkAsDelegateXRealm true || exit 4
-
-exit 0
--- a/test/sun/security/krb5/auto/ok-as-delegate.sh	Wed Nov 20 06:36:47 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,118 +0,0 @@
-#
-# Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#
-
-# @test
-# @bug 6853328
-# @summary Support OK-AS-DELEGATE flag
-# @run shell/timeout=600 ok-as-delegate.sh
-#
-
-if [ "${TESTSRC}" = "" ] ; then
-  TESTSRC=`dirname $0`
-fi
-
-if [ "${TESTJAVA}" = "" ] ; then
-  JAVAC_CMD=`which javac`
-  TESTJAVA=`dirname $JAVAC_CMD`/..
-fi
-
-# set platform-dependent variables
-OS=`uname -s`
-case "$OS" in
-  Windows_* )
-    FS="\\"
-    SEP=";"
-    ;;
-  CYGWIN* )
-    FS="/"
-    SEP=";"
-    ;;
-  * )
-    FS="/"
-    SEP=":"
-    ;;
-esac
-
-${TESTJAVA}${FS}bin${FS}javac -XDignore.symbol.file -d . \
-    ${TESTSRC}${FS}OkAsDelegate.java \
-    ${TESTSRC}${FS}KDC.java \
-    ${TESTSRC}${FS}OneKDC.java \
-    ${TESTSRC}${FS}Action.java \
-    ${TESTSRC}${FS}Context.java \
-    || exit 10
-
-# Testing Kerberos 5
-
-# Add $TESTSRC to classpath so that customized nameservice can be used
-J="${TESTJAVA}${FS}bin${FS}java -cp $TESTSRC${SEP}. OkAsDelegate"
-JOK="${TESTJAVA}${FS}bin${FS}java -cp $TESTSRC${SEP}. -Dtest.kdc.policy.ok-as-delegate OkAsDelegate"
-
-# FORWARDABLE ticket not allowed, always fail
-$J false true true false false false || exit 1
-
-# Service ticket no OK-AS-DELEGATE
-
-# Request nothing, gain nothing
-$J true false false false false false || exit 2
-# Request deleg policy, gain nothing
-$J true false true false false false || exit 3
-# Request deleg, granted
-$J true true false true false true || exit 4
-# Request deleg and deleg policy, granted, with info not by policy
-$J true true true true false true || exit 5
-
-# Service ticket has OK-AS-DELEGATE
-
-# Request deleg policy, granted
-$JOK true false true true true true || exit 6
-# Request deleg and deleg policy, granted, with info by policy
-$JOK true true true true true true || exit 7
-
-# Testing SPNEGO
-
-# Add $TESTSRC to classpath so that customized nameservice can be used
-J="${TESTJAVA}${FS}bin${FS}java -cp $TESTSRC${SEP}. -Dtest.spnego OkAsDelegate"
-JOK="${TESTJAVA}${FS}bin${FS}java -cp $TESTSRC${SEP}. -Dtest.spnego -Dtest.kdc.policy.ok-as-delegate OkAsDelegate"
-
-# FORWARDABLE ticket not allowed, always fail
-$J false true true false false false || exit 11
-
-# Service ticket no OK-AS-DELEGATE
-
-# Request nothing, gain nothing
-$J true false false false false false || exit 12
-# Request deleg policy, gain nothing
-$J true false true false false false || exit 13
-# Request deleg, granted
-$J true true false true false true || exit 14
-# Request deleg and deleg policy, granted, with info not by policy
-$J true true true true false true || exit 15
-
-# Service ticket has OK-AS-DELEGATE
-
-# Request deleg policy, granted
-$JOK true false true true true true || exit 16
-# Request deleg and deleg policy, granted, with info by policy
-$JOK true true true true true true || exit 17
-
-exit 0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/security/krb5/auto/principalProperty/PrincipalSystemPropTest.java	Thu Feb 06 01:43:16 2020 +0000
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8075301
+ * @library /sun/security/krb5/auto
+ * @summary New test for sun.security.krb5.principal system property.
+ * The principal can set using the system property sun.security.krb5.principal.
+ * This property is checked during login. If this property is not set,
+ * then the principal name from the configuration is used.
+ * @run main/othervm/java.security.policy=principalSystemPropTest.policy
+ * PrincipalSystemPropTest
+ */
+
+import java.io.File;
+import java.security.Principal;
+import java.util.HashMap;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import javax.security.auth.login.LoginException;
+import javax.security.auth.login.LoginContext;
+import com.sun.security.auth.callback.TextCallbackHandler;
+
+public class PrincipalSystemPropTest {
+
+    private static final boolean PASS = Boolean.TRUE;
+    private static final boolean FAIL = Boolean.FALSE;
+    private static final String VALID_PRINCIPAL_JAAS_ENTRY =
+            "ValidPrincipalSystemPropTest";
+    private static final String INVALID_PRINCIPAL_JAAS_ENTRY =
+            "InvalidPrincipalSystemPropTest";
+    private static final String NO_PRINCIPAL_JAAS_ENTRY =
+            "NoPrincipalSystemPropTest";
+    private static final String SAME_PRINCIPAL_JAAS_ENTRY =
+            "SelfPrincipalSystemPropTest";
+    private static final String HOST = "localhost";
+    private static final String KTAB_FILENAME = "krb5.keytab.data";
+    private static final String REALM = "TEST.REALM";
+    private static final String TEST_SRC = System.getProperty("test.src", ".");
+    private static final String USER = "USER";
+    private static final String AVAILABLE_USER = "AVAILABLE";
+    private static final String USER_PASSWORD = "password";
+    private static final String FS = System.getProperty("file.separator");
+    private static final String KRB5_CONF_FILENAME = "krb5.conf";
+    private static final String JAAS_CONF_FILENAME = "jaas.conf";
+    private static final String KRBTGT_PRINCIPAL = "krbtgt/" + REALM;
+    private static final String USER_PRINCIPAL = USER + "@" + REALM;
+    private static final String AVAILABLE_USER_PRINCIPAL =
+            AVAILABLE_USER + "@" + REALM;
+
+    public static void main(String[] args) throws Exception {
+
+        setupTest();
+
+        // Expected result, Jaas Config Entry, Login Principal Expected,
+        // Principal passed through System property
+        runTest(PASS, VALID_PRINCIPAL_JAAS_ENTRY,
+                USER_PRINCIPAL, "USER@TEST.REALM");
+        runTest(PASS, VALID_PRINCIPAL_JAAS_ENTRY,
+                AVAILABLE_USER_PRINCIPAL,  null);
+        runTest(PASS, INVALID_PRINCIPAL_JAAS_ENTRY,
+                USER_PRINCIPAL, "USER@TEST.REALM");
+        runTest(FAIL, INVALID_PRINCIPAL_JAAS_ENTRY, null,  null);
+        runTest(PASS, NO_PRINCIPAL_JAAS_ENTRY,
+                USER_PRINCIPAL, "USER@TEST.REALM");
+        runTest(FAIL, NO_PRINCIPAL_JAAS_ENTRY, null, null);
+        runTest(PASS, SAME_PRINCIPAL_JAAS_ENTRY,
+                USER_PRINCIPAL, "USER@TEST.REALM");
+
+    }
+
+    private static void setupTest() {
+
+        System.setProperty("java.security.krb5.conf", KRB5_CONF_FILENAME);
+        System.setProperty("java.security.auth.login.config",
+                TEST_SRC + FS + JAAS_CONF_FILENAME);
+
+        Map<String, String> principals = new HashMap<>();
+        principals.put(USER_PRINCIPAL, USER_PASSWORD);
+        principals.put(AVAILABLE_USER_PRINCIPAL, USER_PASSWORD);
+        principals.put(KRBTGT_PRINCIPAL, null);
+        KDC.startKDC(HOST, KRB5_CONF_FILENAME, REALM, principals,
+                KTAB_FILENAME, KDC.KtabMode.APPEND);
+
+    }
+
+    private static void runTest(boolean expected, String jaasConfigEntry,
+            String expectedLoginUser, String loginUserBySysProp) {
+
+        if(loginUserBySysProp != null) {
+            System.setProperty("sun.security.krb5.principal",
+                    loginUserBySysProp);
+        } else {
+            System.clearProperty("sun.security.krb5.principal");
+        }
+
+        try {
+            LoginContext lc = new LoginContext(jaasConfigEntry,
+                    new TextCallbackHandler());
+            lc.login();
+            System.out.println(String.format(
+                    "Authentication completed with Subject '%s' ",
+                    lc.getSubject()));
+
+            if (!expected) {
+                throw new RuntimeException(
+                        "TEST FAILED - JAAS login success isn't expected");
+            }
+            if(expectedLoginUser != null) {
+                boolean found = false;
+                for (Principal p : lc.getSubject().getPrincipals()) {
+                    if (expectedLoginUser.equals(p.getName())) {
+                        found = true;
+                    }
+                }
+                if (!found) {
+                    throw new RuntimeException(String.format(
+                        "TEST FAILED - Login principal is not matched "
+                        + "to expected principal '%s'.", expectedLoginUser));
+                }
+            }
+            System.out.println(
+                    "TEST PASSED - JAAS login success is expected.");
+        } catch (LoginException ie) {
+            System.out.println(String.format(
+                    "Authentication failed with exception: %s",
+                    ie.getMessage()));
+            if (expected) {
+                System.out.println(
+                        "TEST FAILED - JAAS login failure isn't expected");
+                throw new RuntimeException(ie);
+            }
+            System.out.println(
+                    "TEST PASSED - JAAS login failure is expected.");
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/security/krb5/auto/principalProperty/jaas.conf	Thu Feb 06 01:43:16 2020 +0000
@@ -0,0 +1,34 @@
+NoPrincipalSystemPropTest {
+	com.sun.security.auth.module.Krb5LoginModule required 
+	useKeyTab = true
+  	keyTab = krb5.keytab.data
+  	doNotPrompt =true
+  	debug=true;
+};
+
+InvalidPrincipalSystemPropTest {
+  	com.sun.security.auth.module.Krb5LoginModule required 
+  	principal="UNAVAILABLE@TEST.REALM"
+  	useKeyTab = true
+  	keyTab = krb5.keytab.data
+  	doNotPrompt =true
+  	debug=true;
+};
+
+ValidPrincipalSystemPropTest {
+  	com.sun.security.auth.module.Krb5LoginModule required 
+  	principal="AVAILABLE@TEST.REALM"
+  	useKeyTab = true
+  	keyTab = krb5.keytab.data
+  	doNotPrompt =true
+  	debug=true;
+};
+
+SelfPrincipalSystemPropTest {
+  	com.sun.security.auth.module.Krb5LoginModule required 
+  	principal="USER@TEST.REALM"
+  	useKeyTab = true
+  	keyTab = krb5.keytab.data
+  	doNotPrompt =true
+  	debug=true;
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/security/krb5/auto/principalProperty/principalSystemPropTest.policy	Thu Feb 06 01:43:16 2020 +0000
@@ -0,0 +1,21 @@
+grant {
+  	permission javax.security.auth.AuthPermission
+    	"createLoginContext.ValidPrincipalSystemPropTest";
+    	permission javax.security.auth.AuthPermission
+    	"createLoginContext.InvalidPrincipalSystemPropTest";
+    	permission javax.security.auth.AuthPermission
+    	"createLoginContext.NoPrincipalSystemPropTest";
+    	permission javax.security.auth.AuthPermission
+    	"createLoginContext.SelfPrincipalSystemPropTest";
+  	permission javax.security.auth.AuthPermission "doAs";
+  	permission javax.security.auth.AuthPermission "modifyPrincipals";
+  	permission javax.security.auth.AuthPermission "getSubject";
+  	permission java.util.PropertyPermission "*", "read,write";
+  	permission java.io.FilePermission "*", "read,write,delete";
+  	permission java.lang.RuntimePermission "accessDeclaredMembers";
+  	permission java.lang.reflect.ReflectPermission "suppressAccessChecks";
+  	permission java.lang.RuntimePermission "accessClassInPackage.*";
+  	permission java.net.SocketPermission "*:*", 
+  		"listen,resolve,accept,connect";
+}; 
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/security/krb5/auto/refreshKrb5Config.jaas	Thu Feb 06 01:43:16 2020 +0000
@@ -0,0 +1,11 @@
+Refreshable {
+    com.sun.security.auth.module.Krb5LoginModule required
+        useTicketCache=false
+        refreshKrb5Config=true;
+};
+
+NotRefreshable {
+    com.sun.security.auth.module.Krb5LoginModule required
+        useTicketCache=false
+        refreshKrb5Config=false;
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/security/krb5/auto/tools/KinitConfPlusProps.java	Thu Feb 06 01:43:16 2020 +0000
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.File;
+import java.net.PortUnreachableException;
+import java.util.HashMap;
+import java.util.Map;
+import jdk.testlibrary.ProcessTools;
+import jdk.testlibrary.OutputAnalyzer;
+
+/*
+ * @test
+ * @bug 6857795 8075299
+ * @summary Checks if kinit uses both krb5 conf file and system properties
+ * @requires os.family == "windows"
+ * @library /lib/testlibrary
+ * @library /sun/security/krb5/auto
+ * @run main/othervm KinitConfPlusProps
+ */
+public class KinitConfPlusProps {
+
+    private static final String KINIT = System.getProperty("java.home")
+            + File.separator + "bin" + File.separator + "kinit";
+    private static final String KLIST = System.getProperty("java.home")
+            + File.separator + "bin" + File.separator + "klist";
+    private static final String REALM = "REALM";
+    private static final String ANOTHER_REALM = "ANOTHER.REALM";
+    private static final String HOST = "localhost";
+    private static final String CC_FILENAME = "krb5cc_test";
+    private static final String USER = "TESTER";
+    private static final String USER_PRINCIPAL = USER + "@" + REALM;
+    private static final String KRBTGT_PRINCIPAL = "krbtgt/" + REALM;
+    private static final String KEYTAB_FILE = "test.keytab";
+    private static final String KRB5_CONF_FILENAME = "krb5.conf";
+
+    public static void main(String[] args) throws Exception {
+        // define principals
+        Map<String, String> principals = new HashMap<>();
+        principals.put(USER_PRINCIPAL, null);
+        principals.put(KRBTGT_PRINCIPAL, null);
+
+        System.setProperty("java.security.krb5.conf", KRB5_CONF_FILENAME);
+
+        // start a local KDC instance
+        KDC kdc = KDC.startKDC(HOST, null, REALM, principals, KEYTAB_FILE,
+                KDC.KtabMode.APPEND);
+        KDC.saveConfig(KRB5_CONF_FILENAME, kdc,
+                "forwardable = true", "proxiable = true");
+
+        boolean success = true;
+
+        /*
+         * kinit should fail since java.security.krb5.kdc
+         * and java.security.krb5.realm properties override correct values
+         * in krb5 conf file
+         */
+        String[] command = {KINIT, "-k",
+            "-J-Djava.security.krb5.realm=" + REALM,
+            "-J-Djava.security.krb5.kdc=" + HOST,   // without port
+            "-J-Djava.security.krb5.conf=" + KRB5_CONF_FILENAME,
+            "-t", KEYTAB_FILE,
+            "-c", CC_FILENAME,
+            USER
+        };
+
+        try {
+            OutputAnalyzer out = ProcessTools.executeCommand(command);
+            out.shouldHaveExitValue(-1);
+            out.shouldContain(PortUnreachableException.class.getName());
+        } catch(Throwable e) {
+            System.out.println("Unexpected exception: " + e);
+            e.printStackTrace(System.out);
+            success = false;
+        }
+
+        /*
+         * kinit should succeed
+         * since realm should be picked up from principal name
+         */
+        command = new String[] {KINIT, "-k",
+            "-J-Djava.security.krb5.realm=" + ANOTHER_REALM,
+            "-J-Djava.security.krb5.kdc=" + HOST,
+            "-J-Djava.security.krb5.conf=" + KRB5_CONF_FILENAME,
+            "-t", KEYTAB_FILE,
+            "-c", CC_FILENAME,
+            USER_PRINCIPAL
+        };
+
+        try {
+            OutputAnalyzer out = ProcessTools.executeCommand(command);
+            out.shouldHaveExitValue(0);
+            out.shouldContain(CC_FILENAME);
+        } catch(Throwable e) {
+            System.out.println("Unexpected exception: " + e);
+            e.printStackTrace(System.out);
+            success = false;
+        }
+
+        success &= checkTicketFlags();
+
+        /*
+         * kinit should succeed
+         * since realm should be picked up from principal name,
+         * and other data should come from krb5 conf file
+         */
+        command = new String[] {KINIT, "-k",
+            "-J-Djava.security.krb5.conf=" + KRB5_CONF_FILENAME,
+            "-t", KEYTAB_FILE,
+            "-c", CC_FILENAME,
+            USER_PRINCIPAL
+        };
+
+        try {
+            OutputAnalyzer out = ProcessTools.executeCommand(command);
+            out.shouldHaveExitValue(0);
+            out.shouldContain(CC_FILENAME);
+        } catch(Throwable e) {
+            System.out.println("Unexpected exception: " + e);
+            e.printStackTrace(System.out);
+            success = false;
+        }
+
+        success &= checkTicketFlags();
+
+        // kinit should succeed even if a principal name doesn't have realm
+        command = new String[] {KINIT, "-k",
+            "-J-Djava.security.krb5.conf=" + KRB5_CONF_FILENAME,
+            "-t", KEYTAB_FILE,
+            "-c", CC_FILENAME,
+            USER
+        };
+
+        try {
+            OutputAnalyzer out = ProcessTools.executeCommand(command);
+            out.shouldHaveExitValue(0);
+            out.shouldContain(CC_FILENAME);
+        } catch(Throwable e) {
+            System.out.println("Unexpected exception: " + e);
+            e.printStackTrace(System.out);
+            success = false;
+        }
+
+        success &= checkTicketFlags();
+
+        if (!success) {
+            throw new RuntimeException("At least one test case failed");
+        }
+        System.out.println("Test passed");
+    }
+
+    // check if a ticket has forwardable and proxiable flags
+    private static boolean checkTicketFlags() {
+        String[] command = new String[] {KLIST, "-f", "-c", CC_FILENAME};
+
+        try {
+            OutputAnalyzer out = ProcessTools.executeCommand(command);
+            out.shouldHaveExitValue(0);
+            out.shouldContain("FORWARDABLE");
+            out.shouldContain("PROXIABLE");
+        } catch(Throwable e) {
+            System.out.println("Unexpected exception: " + e);
+            e.printStackTrace(System.out);
+            return false;
+        }
+
+        return true;
+    }
+}
--- a/test/sun/security/krb5/ccache/EmptyCC.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/sun/security/krb5/ccache/EmptyCC.java	Thu Feb 06 01:43:16 2020 +0000
@@ -26,15 +26,12 @@
  * @bug 7158329
  * @bug 8001208
  * @summary NPE in sun.security.krb5.Credentials.acquireDefaultCreds()
+ * @library ../../../../java/security/testlibrary/
  * @compile -XDignore.symbol.file EmptyCC.java
  * @run main EmptyCC tmpcc
  * @run main EmptyCC FILE:tmpcc
  */
 import java.io.File;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
 import sun.security.krb5.Credentials;
 import sun.security.krb5.PrincipalName;
 import sun.security.krb5.internal.ccache.CredentialsCache;
@@ -48,32 +45,9 @@
             // Main process, write the ccache and launch sub process
             CredentialsCache cache = CredentialsCache.create(pn, ccache);
             cache.save();
-
-            // java -cp $test.classes EmptyCC readcc
-            ProcessBuilder pb = new ProcessBuilder(
-                    new File(new File(System.getProperty("java.home"), "bin"),
-                        "java").getPath(),
-                    "-cp",
-                    System.getProperty("test.classes"),
-                    "EmptyCC",
-                    ccache,
-                    "readcc"
-                    );
-
-            pb.environment().put("KRB5CCNAME", ccache);
-            pb.redirectErrorStream(true);
-
-            Process p = pb.start();
-            try (InputStream ins = p.getInputStream()) {
-                byte[] buf = new byte[8192];
-                int n;
-                while ((n = ins.read(buf)) > 0) {
-                    System.out.write(buf, 0, n);
-                }
-            }
-            if (p.waitFor() != 0) {
-                throw new Exception("Test failed");
-            }
+            Proc p = Proc.create("EmptyCC").args(ccache, "readcc")
+                    .env("KRB5CCNAME", ccache).start();
+            p.waitFor();
         } else {
             // Sub process, read the ccache
             String cc = System.getenv("KRB5CCNAME");
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/security/krb5/config/Duplicates.java	Thu Feb 06 01:43:16 2020 +0000
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+/*
+ * @test
+ * @bug 7184246
+ * @compile -XDignore.symbol.file Duplicates.java
+ * @run main/othervm Duplicates
+ * @summary Simplify Config.get() of krb5
+ */
+
+import sun.security.krb5.Config;
+
+public class Duplicates {
+    public static void main(String[] args) throws Exception {
+        System.setProperty("java.security.krb5.conf",
+                System.getProperty("test.src", ".") +"/k1.conf");
+        Config config = Config.getInstance();
+        config.listTable();
+        String s;
+
+        // Latter overwrites former for root section
+        s = config.get("libdefaults", "default_realm");
+        if (s != null) {
+            throw new Exception();
+        }
+        // Latter overwrites former for strings
+        s = config.get("libdefaults", "default_tkt_enctypes");
+        if (!s.equals("aes256-cts")) {
+            throw new Exception();
+        }
+        // Latter overwrites former for sub-section
+        s = config.get("realms", "R1", "kdc");
+        if (!s.equals("k2")) {
+            throw new Exception(s);
+        }
+        // Duplicate keys in [realms] are merged
+        s = config.getAll("realms", "R2", "kdc");
+        if (!s.equals("k1 k2 k3 k4")) {
+            throw new Exception(s);
+        }
+        // Duplicate keys in [capaths] are merged
+        s = config.getAll("capaths", "R1", "R2");
+        if (!s.equals("R3 R4 R5 R6")) {
+            throw new Exception(s);
+        }
+        // We can be very deep now
+        s = config.get("new", "x", "y", "z", "a", "b", "c");
+        if (!s.equals("d")) {
+            throw new Exception(s);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/security/krb5/config/Duration.java	Thu Feb 06 01:43:16 2020 +0000
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8044500
+ * @summary Add kinit options and krb5.conf flags that allow users to
+ *          obtain renewable tickets and specify ticket lifetimes
+ * @compile -XDignore.symbol.file Duration.java
+ * @run main Duration
+ */
+import sun.security.krb5.Config;
+import sun.security.krb5.KrbException;
+
+public class Duration {
+    public static void main(String[] args) throws Exception {
+        check("123", 123);
+        check("1:1", 3660);
+        check("1:1:1", 3661);
+        check("1d", 86400);
+        check("1h", 3600);
+        check("1h1m", 3660);
+        check("1h 1m", 3660);
+        check("1d 1h 1m 1s", 90061);
+        check("1d1h1m1s", 90061);
+
+        check("", -1);
+        check("abc", -1);
+        check("1ms", -1);
+        check("1d1d", -1);
+        check("1h1d", -1);
+        check("x1h", -1);
+        check("1h x 1m", -1);
+        check(":", -1);
+        check("1:60", -1);
+        check("1:1:1:1", -1);
+        check("1:1:1:", -1);
+    }
+
+    static void check(String s, int ex) throws Exception {
+        System.out.print("\u001b[1;37;41m" +s + " " + ex);
+        System.out.print("\u001b[m\n");
+        try {
+            int result = Config.duration(s);
+            if (result != ex) throw new Exception("for " + s + " is " + result);
+        } catch (KrbException ke) {
+            ke.printStackTrace();
+            if (ex != -1) throw new Exception();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/security/krb5/config/ExtraLines.java	Thu Feb 06 01:43:16 2020 +0000
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+/*
+ * @test
+ * @bug 8036971
+ * @compile -XDignore.symbol.file ExtraLines.java
+ * @run main/othervm ExtraLines
+ * @summary krb5.conf does not accept directive lines before the first section
+ */
+
+import sun.security.krb5.Config;
+import java.nio.file.*;
+import java.util.Objects;
+
+public class ExtraLines {
+    public static void main(String[] args) throws Exception {
+        Path base = Paths.get("krb5.conf");
+        Path include = Paths.get("included.conf");
+        String baseConf = "include " + include.toAbsolutePath().toString()
+                + "\n[x]\na = b\n";
+        String includeConf = "[y]\nc = d\n";
+        Files.write(include, includeConf.getBytes());
+        Files.write(base, baseConf.getBytes());
+
+        System.setProperty("java.security.krb5.conf", base.toString());
+        Config.refresh();
+
+        if (!Objects.equals(Config.getInstance().get("x", "a"), "b")) {
+            throw new Exception("Failed");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/security/krb5/config/SCDynamicConfigTest.java	Thu Feb 06 01:43:16 2020 +0000
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 7184246
+ * @summary Simplify Config.get() of krb5
+ */
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.Hashtable;
+import java.util.Vector;
+import sun.security.krb5.Config;
+import sun.security.krb5.SCDynamicStoreConfig;
+
+public class SCDynamicConfigTest {
+
+    static Vector<Hashtable<String,String>>hosts() {
+        Vector <Hashtable<String,String>> result = new Vector<>();
+        Hashtable<String,String> pair = new Hashtable<>();
+        pair.put("host", "127.0.0.1");
+        result.add(pair);
+        pair = new Hashtable<>();
+        pair.put("host", "127.0.0.2");
+        result.add(pair);
+        return result;
+    }
+
+    public static void main(String[] args) throws Exception {
+        // Reconstruct a typical SCDynamicConfig.getKerberosConfig() output
+        Hashtable<String, Object> conf = new Hashtable<>();
+
+        Hashtable<String, Object> libdefaults = new Hashtable<>();
+        libdefaults.put("default_realm", "REALM.COM");
+        conf.put("libdefaults", libdefaults);
+
+        Hashtable<String, Object> realms = new Hashtable<>();
+        Hashtable<String, Object> thisRealm = new Hashtable<>();
+        realms.put("REALM.COM", thisRealm);
+        thisRealm.put("kpasswd", hosts());
+        thisRealm.put("kadmin", hosts());
+        thisRealm.put("kdc", hosts());
+        conf.put("realms", realms);
+
+        Hashtable<String, Object> domain_realm = new Hashtable<>();
+        domain_realm.put(".realm.com", "REALM.COM");
+        domain_realm.put("realm.com", "REALM.COM");
+        conf.put("domain_realm", domain_realm);
+
+        System.out.println("SCDynamicConfig:\n");
+        System.out.println(conf);
+
+        // Simulate SCDynamicConfig.getConfig() output
+        Method m = SCDynamicStoreConfig.class.getDeclaredMethod(
+                "convertNativeConfig", Hashtable.class);
+        m.setAccessible(true);
+        conf = (Hashtable)m.invoke(null, conf);
+
+        System.out.println("\nkrb5.conf:\n");
+        System.out.println(conf);
+
+        // Feed it into a Config object
+        System.setProperty("java.security.krb5.conf", "not-a-file");
+        Config cf = Config.getInstance();
+        Field f = Config.class.getDeclaredField("stanzaTable");
+        f.setAccessible(true);
+        f.set(cf, conf);
+
+        System.out.println("\nConfig:\n");
+        System.out.println(cf);
+
+        if (!cf.getDefaultRealm().equals("REALM.COM")) {
+            throw new Exception();
+        }
+        if (!cf.getKDCList("REALM.COM").equals("127.0.0.1 127.0.0.2")) {
+            throw new Exception();
+        }
+        if (!cf.get("domain_realm", ".realm.com").equals("REALM.COM")) {
+            throw new Exception();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/security/krb5/config/k1.conf	Thu Feb 06 01:43:16 2020 +0000
@@ -0,0 +1,40 @@
+[libdefaults]
+default_realm = R1
+
+[libdefaults]
+default_tkt_enctypes = aes128-cts
+default_tkt_enctypes = aes256-cts
+
+[realms]
+R1 = {
+    kdc = k1
+}
+R1 = {
+    kdc = k2
+}
+R2 = {
+    kdc = k1
+    kdc = k2 k3
+    admin_server = a1
+    kdc = k4
+}
+
+[capaths]
+R1 = {
+    R2 = R3
+    R2 = R4 R5
+    R2 = R6
+}
+
+[new]
+x = {
+    y = {
+        z = {
+            a = {
+                b = {
+                    c = d
+                }
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/security/krb5/etype/UnsupportedKeyType.java	Thu Feb 06 01:43:16 2020 +0000
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 5006629
+ * @summary Kerberos library should only select keys of types that it supports
+ */
+
+import javax.security.auth.kerberos.KerberosPrincipal;
+import javax.security.auth.kerberos.KeyTab;
+import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+
+public class UnsupportedKeyType {
+
+    // Homemade keytab files:
+    //
+    // String   KVNO Timestamp      Principal (etype)
+    // -------- ---- -------------- -----------------------
+    // camellia    4 4/3/14 9:58 AM u1@K1 (25:camellia128-cts-cmac)
+    // aes         5 4/3/14 9:58 AM u1@K1 (17:aes128-cts-hmac-sha1-96)
+
+    static String aes =
+            "050200000027000100024b310002753100000001533cc04f0500110010e0eab6" +
+            "7f31608df2b2f8fffc6b21cc91";
+    static String camellia =
+            "050200000027000100024b310002753100000001533cc03e0400190010d88678" +
+            "14e478b6b7d2d97375163b971e";
+
+    public static void main(String[] args) throws Exception {
+
+        byte[] data = new byte[aes.length()/2];
+        KerberosPrincipal kp = new KerberosPrincipal("u1@K1");
+
+        // aes128
+        for (int i=0; i<data.length; i++) {
+            data[i] = Integer.valueOf(
+                    aes.substring(2*i,2*i+2), 16).byteValue();
+        }
+        Files.write(Paths.get("aes"), data);
+        if(KeyTab.getInstance(new File("aes")).getKeys(kp).length == 0) {
+            throw new Exception("AES key not read");
+        }
+
+        // camellia128
+        for (int i=0; i<data.length; i++) {
+            data[i] = Integer.valueOf(
+                    camellia.substring(2*i,2*i+2), 16).byteValue();
+        }
+        Files.write(Paths.get("camellia"), data);
+        if(KeyTab.getInstance(new File("camellia")).getKeys(kp).length != 0) {
+            throw new Exception("Unknown key read");
+        }
+    }
+}
--- a/test/sun/security/krb5/etype/WeakCrypto.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/sun/security/krb5/etype/WeakCrypto.java	Thu Feb 06 01:43:16 2020 +0000
@@ -22,29 +22,41 @@
  */
 /*
  * @test
- * @bug 6844909
+ * @bug 6844909 8012679
  * @run main/othervm WeakCrypto
+ * @run main/othervm WeakCrypto true
+ * @run main/othervm WeakCrypto false
  * @summary support allow_weak_crypto in krb5.conf
  */
 
 import java.io.File;
+import java.lang.Exception;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+
 import sun.security.krb5.internal.crypto.EType;
 import sun.security.krb5.EncryptedData;
 
 public class WeakCrypto {
     public static void main(String[] args) throws Exception {
-        System.setProperty("java.security.krb5.conf",
-                System.getProperty("test.src", ".") +
-                File.separator +
-                "weakcrypto.conf");
+        String conf = "[libdefaults]\n" +
+                (args.length > 0 ? ("allow_weak_crypto = " + args[0]) : "");
+        Files.write(Paths.get("krb5.conf"), conf.getBytes());
+        System.setProperty("java.security.krb5.conf", "krb5.conf");
+
+        boolean expected = args.length != 0 && args[0].equals("true");
         int[] etypes = EType.getBuiltInDefaults();
 
+        boolean found = false;
         for (int i=0, length = etypes.length; i<length; i++) {
             if (etypes[i] == EncryptedData.ETYPE_DES_CBC_CRC ||
                     etypes[i] == EncryptedData.ETYPE_DES_CBC_MD4 ||
                     etypes[i] == EncryptedData.ETYPE_DES_CBC_MD5) {
-                throw new Exception("DES should not appear");
+                found = true;
             }
         }
+        if (expected != found) {
+            throw new Exception();
+        }
     }
 }
--- a/test/sun/security/pkcs11/fips/ClientJSSEServerJSSE.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/sun/security/pkcs11/fips/ClientJSSEServerJSSE.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,10 +26,13 @@
  * @bug 6313675 6323647 8028192
  * @summary Verify that all ciphersuites work in FIPS mode
  * @library ..
- * @ignore JSSE supported cipher suites are changed with CR 6916074,
- *     need to update this test case in JDK 7 soon
- * @run main/othervm ClientJSSEServerJSSE
  * @author Andreas Sterbenz
+ * @run main/manual ClientJSSEServerJSSE
+ */
+
+/*
+ * JSSE supported cipher suites are changed with CR 6916074,
+ * need to update this test case in JDK 7 soon
  */
 
 import java.security.*;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/security/provider/DSA/TestMaxLengthDER.java	Thu Feb 06 01:43:16 2020 +0000
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8183591
+ * @summary Test decoding of DER length fields containing Integer.MAX_VALUE
+ * @run main TestMaxLengthDER
+ */
+
+import java.io.*;
+import java.math.*;
+import java.security.*;
+import java.security.spec.*;
+
+public class TestMaxLengthDER {
+
+    public static void main(String[] args) throws Exception {
+
+        String message = "Message";
+        Signature sig = Signature.getInstance("SHA256withDSA");
+        KeyPairGenerator kpg = KeyPairGenerator.getInstance("DSA");
+        SecureRandom rnd = new SecureRandom();
+        rnd.setSeed(1);
+        kpg.initialize(2048, rnd);
+        KeyPair kp = kpg.generateKeyPair();
+        sig.initSign(kp.getPrivate());
+        sig.update(message.getBytes());
+        byte[] sigData = sig.sign();
+
+        // Set the length of the second integer to Integer.MAX_VALUE
+        // First copy all the signature data to the correct location
+        int lengthPos = sigData[3] + 5;
+        byte[] modifiedSigData = new byte[sigData.length + 4];
+        System.arraycopy(sigData, 0, modifiedSigData, 0, lengthPos);
+        System.arraycopy(sigData, lengthPos + 1, modifiedSigData,
+            lengthPos + 5, sigData.length - (lengthPos + 1));
+
+        // Increase the length (in bytes) of the sequence to account for
+        // the larger length field
+        modifiedSigData[1] += 4;
+
+        // Modify the length field
+        modifiedSigData[lengthPos] = (byte) 0x84;
+        modifiedSigData[lengthPos + 1] = (byte) 0x7F;
+        modifiedSigData[lengthPos + 2] = (byte) 0xFF;
+        modifiedSigData[lengthPos + 3] = (byte) 0xFF;
+        modifiedSigData[lengthPos + 4] = (byte) 0xFF;
+
+        sig.initVerify(kp.getPublic());
+        sig.update(message.getBytes());
+
+        try {
+            sig.verify(modifiedSigData);
+            throw new RuntimeException("No exception on misencoded signature");
+        } catch (SignatureException ex) {
+            if (ex.getCause() instanceof EOFException) {
+                // this is expected
+            } else {
+                throw ex;
+            }
+        }
+    }
+}
--- a/test/sun/security/provider/PolicyFile/GrantAllPermToExtWhenNoPolicy.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/sun/security/provider/PolicyFile/GrantAllPermToExtWhenNoPolicy.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,8 +23,7 @@
 
 /*
  * @test
- * @bug 4231980
- * @bug 4233913
+ * @bug 4231980 4233913
  * @summary Make sure that when no system policy and user policy files exist,
  * the built-in default policy will be used, which - amongst other things -
  * grants standard extensions the AllPermission. This regression is for 2
@@ -34,7 +33,7 @@
  *
  * @build SomeExtensionClass
  * @build GrantAllPermToExtWhenNoPolicy
- * @ignore shell GrantAllPermToExtWhenNoPolicy.sh
+ * @run shell/manual GrantAllPermToExtWhenNoPolicy.sh
  */
 
 import java.security.*;
--- a/test/sun/security/provider/PolicyParser/ExtDirs.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/sun/security/provider/PolicyParser/ExtDirs.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,13 +26,16 @@
  * @bug 4215035
  * @summary standard extensions path is hard-coded in default
  *      system policy file
- * @ignore run this by hand
- *
- *      java    -Djava.security.manager \
- *              -Djava.ext.dirs=./ExtDirsA:./ExtDirsB \
- *              -Djava.security.policy==./ExtDirs.policy \
- *              -Djava.security.debug=parser \
- *              ExtDirs
+ * @run main/manual ExtDirs
+ */
+
+/*
+ * Run this test manually with:
+ * java    -Djava.security.manager \
+ *         -Djava.ext.dirs=./ExtDirsA:./ExtDirsB \
+ *         -Djava.security.policy==./ExtDirs.policy \
+ *         -Djava.security.debug=parser \
+ *         ExtDirs
  */
 
 public class ExtDirs {
--- a/test/sun/security/provider/PolicyParser/ExtDirsChange.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/sun/security/provider/PolicyParser/ExtDirsChange.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,16 +26,19 @@
  * @bug 4993819
  * @summary standard extensions path is hard-coded in default
  *      system policy file
- * @ignore run this by hand
- *
- *      javac ExtDirChange
- *      rm ExtDirsA*.class ExtDirsB*.class
- *      java    -Djava.security.manager \
- *              -Dtest.src=. \
- *              -Djava.security.policy=ExtDirsChange.policy \
- *              -Djava.security.debug=parser \
- *              -cp ExtDirsA/a.jar:ExtDirsB/b.jar:. \
- *              ExtDirsChange
+ * @run main/manual ExtDirsChange
+ */
+
+/*
+ * Run this test manually with:
+ * javac ExtDirChange
+ * rm ExtDirsA*.class ExtDirsB*.class
+ * java    -Djava.security.manager \
+ *         -Dtest.src=. \
+ *         -Djava.security.policy=ExtDirsChange.policy \
+ *         -Djava.security.debug=parser \
+ *         -cp ExtDirsA/a.jar:ExtDirsB/b.jar:. \
+ *         ExtDirsChange
  */
 
 import java.io.File;
--- a/test/sun/security/provider/PolicyParser/ExtDirsDefaultPolicy.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/sun/security/provider/PolicyParser/ExtDirsDefaultPolicy.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,22 +26,25 @@
  * @bug 4993819
  * @summary standard extensions path is hard-coded in default
  *      system policy file
- * @ignore run this by hand
- *
- *      java    -Djava.security.manager \
- *              -Djava.ext.dirs=./ExtDirsA:./ExtDirsB \
- *              -Djava.security.debug=parser \
- *              ExtDirsDefaultPolicy
+ * @run main/manual ExtDirsDefaultPolicy
+ */
+
+/*
+ * Run this test manually with:
+ * java    -Djava.security.manager \
+ *         -Djava.ext.dirs=./ExtDirsA:./ExtDirsB \
+ *         -Djava.security.debug=parser \
+ *         ExtDirsDefaultPolicy
  *
  * To test other varients of the ${{java.ext.dirs}} protocol, remove
  * the grant statement for java.ext.dirs in $JAVA_HOME/lib/security/java.policy
  * and then run against the 3 different policy files.
  *
- *      java    -Djava.security.manager \
- *              -Djava.ext.dirs=./ExtDirsA:./ExtDirsB \
- *              -Djava.security.debug=parser \
- *              -Djava.security.policy=ExtDirs{1,2,3}.policy \
- *              ExtDirsDefaultPolicy
+ * java    -Djava.security.manager \
+ *         -Djava.ext.dirs=./ExtDirsA:./ExtDirsB \
+ *         -Djava.security.debug=parser \
+ *         -Djava.security.policy=ExtDirs{1,2,3}.policy \
+ *         ExtDirsDefaultPolicy
  */
 
 public class ExtDirsDefaultPolicy {
--- a/test/sun/security/provider/PolicyParser/PrincipalExpansionError.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/sun/security/provider/PolicyParser/PrincipalExpansionError.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2002, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,56 +25,54 @@
  * @test
  * @bug 4373996
  * @summary parser incorrectly ignores a principal if the principal name
- *      expands to nothing.  this test is a bit complicated.
- *
- *      1) PrincipalExpansionError.java
- *              the test itself.  this test creates a Subject with a
- *              SolarisPrincipal("TestPrincipal") and calls doAs
- *              with a PrincipalExpansionErrorAction.
- *
- *      2) PrincipalExpansionErrorAction
- *              this action tries to read the file, /testfile
+ *      expands to nothing.
+ * @run main/manual PrincipalExpansionError
+ */
+
+/*
+ * This test is a bit complicated.
+ * 1) PrincipalExpansionError.java
+ *         the test itself.  this test creates a Subject with a
+ *         SolarisPrincipal("TestPrincipal") and calls doAs
+ *         with a PrincipalExpansionErrorAction.
+ * 2) PrincipalExpansionErrorAction
+ *         this action tries to read the file, /testfile
+ * 3) to run the test:
+ *         a) jtreg -verbose:all -testjdk:<your_jdk>/build/sparc
+ *                 PrincipalExpansionError.java
+ *         b) PrincipalExpansionError is compiled and put into
+ *                 the "test.classes" directory
+ *         c) PrincipalExpansionErrorAction is compiled and put into
+ *                 the "test.classes"/apackage directory
+ *                 (since it belongs to the 'apackage' package
+ *         d) the PrincipalExpansionError shell script moves
+ *                 test.classes/apackage to test.src/apackage.
+ *                 this guarantees that the test will run
+ *                 with codebase test.classes, and the action
+ *                 will run with codebase test.src.
+ *         e) the test is executed.  permissions to read the file,
+ *                 /testfile, were granted to the PrincipalExpansionError.
+ *                 the policy entry for PrincipalExpansionErrorAction
+ *                 running as SolarisPrincipal("TestPrincipal")
+ *                 was also granted the file permission,
+ *                 but it has a bogus second SolarisPrincipal with
+ *                 a name that can't be property-expanded.
  *
- *      3) to run the test:
- *              a) jtreg -verbose:all -testjdk:<your_jdk>/build/sparc
- *                      PrincipalExpansionError.java
- *              b) PrincipalExpansionError is compiled and put into
- *                      the "test.classes" directory
- *              c) PrincipalExpansionErrorAction is compiled and put into
- *                      the "test.classes"/apackage directory
- *                      (since it belongs to the 'apackage' package
- *              d) the PrincipalExpansionError shell script moves
- *                      test.classes/apackage to test.src/apackage.
- *                      this guarantees that the test will run
- *                      with codebase test.classes, and the action
- *                      will run with codebase test.src.
- *              e) the test is executed.  permissions to read the file,
- *                      /testfile, were granted to the PrincipalExpansionError.
- *                      the policy entry for PrincipalExpansionErrorAction
- *                      running as SolarisPrincipal("TestPrincipal")
- *                      was also granted the file permission,
- *                      but it has a bogus second SolarisPrincipal with
- *                      a name that can't be property-expanded.
- *
- *                      the old behavior of the code would ignore the
- *                      bogus entry and incorrectly grants the file permission
- *                      to SolarisPrincipal("TestPrincipal").
- *                      the new behavior correctly ignores the entire
- *                      policy entry.
- *                      Please note that the jtreg needs to be granted
- *                      allpermissions for this test to succeed. If the codebase
- *                      for jtreg changes, the PrincipalExpansionError.policy
- *                      needs to be updated.
- *
- *              f) original @ tags:
- *                      compile PrincipalExpansionErrorAction.java
- *                      run shell PrincipalExpansionError.sh
- *                      run main/othervm/policy=PrincipalExpansionError.policy
- *                              -Djava.security.debug=access,domain,failure
- *                              PrincipalExpansionError
- *
- * @ignore unable to rely on location or javatest.jar
- *              (so we can grant it AllPermission)
+ *                 the old behavior of the code would ignore the
+ *                 bogus entry and incorrectly grants the file permission
+ *                 to SolarisPrincipal("TestPrincipal").
+ *                 the new behavior correctly ignores the entire
+ *                 policy entry.
+ *                 Please note that the jtreg needs to be granted
+ *                 allpermissions for this test to succeed. If the codebase
+ *                 for jtreg changes, the PrincipalExpansionError.policy
+ *                 needs to be updated.
+ *         f) original @ tags:
+ *                 compile PrincipalExpansionErrorAction.java
+ *                 run shell PrincipalExpansionError.sh
+ *                 run main/othervm/policy=PrincipalExpansionError.policy
+ *                         -Djava.security.debug=access,domain,failure
+ *                         PrincipalExpansionError
  */
 
 import javax.security.auth.*;
--- a/test/sun/security/smartcardio/TestChannel.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/sun/security/smartcardio/TestChannel.java	Thu Feb 06 01:43:16 2020 +0000
@@ -26,10 +26,11 @@
  * @bug 6239117
  * @summary test logical channels work
  * @author Andreas Sterbenz
- * @ignore requires special hardware
- * @run main/manual TestExclusive
+ * @run main/manual TestChannel
  */
 
+// This test requires special hardware.
+
 import javax.smartcardio.Card;
 import javax.smartcardio.CardChannel;
 import javax.smartcardio.CardTerminal;
--- a/test/sun/security/smartcardio/TestConnect.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/sun/security/smartcardio/TestConnect.java	Thu Feb 06 01:43:16 2020 +0000
@@ -26,10 +26,11 @@
  * @bug 6293769 6294527 6309280
  * @summary test connect() works
  * @author Andreas Sterbenz
- * @ignore requires special hardware
  * @run main/manual TestConnect
  */
 
+// This test requires special hardware.
+
 import java.util.List;
 import javax.smartcardio.TerminalFactory;
 import javax.smartcardio.Card;
--- a/test/sun/security/smartcardio/TestConnectAgain.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/sun/security/smartcardio/TestConnectAgain.java	Thu Feb 06 01:43:16 2020 +0000
@@ -26,10 +26,11 @@
  * @bug 6239117
  * @summary test connect works correctly if called multiple times/card removed
  * @author Andreas Sterbenz
- * @ignore requires special hardware
- * @run main/manual TestTransmit
+ * @run main/manual TestConnectAgain
  */
 
+// This test requires special hardware.
+
 import javax.smartcardio.Card;
 import javax.smartcardio.CardException;
 import javax.smartcardio.CardChannel;
--- a/test/sun/security/smartcardio/TestControl.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/sun/security/smartcardio/TestControl.java	Thu Feb 06 01:43:16 2020 +0000
@@ -26,10 +26,11 @@
  * @bug 6239117 6470320
  * @summary test if transmitControlCommand() works
  * @author Andreas Sterbenz
- * @ignore requires special hardware
  * @run main/manual TestControl
  */
 
+// This test requires special hardware.
+
 import javax.smartcardio.Card;
 import javax.smartcardio.CardException;
 import javax.smartcardio.CardTerminal;
--- a/test/sun/security/smartcardio/TestDefault.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/sun/security/smartcardio/TestDefault.java	Thu Feb 06 01:43:16 2020 +0000
@@ -26,10 +26,11 @@
  * @bug 6327047
  * @summary verify that TerminalFactory.getDefault() works
  * @author Andreas Sterbenz
- * @ignore requires special hardware
  * @run main/manual TestDefault
  */
 
+// This test requires special hardware.
+
 import java.util.List;
 import javax.smartcardio.CardTerminal;
 import javax.smartcardio.TerminalFactory;
--- a/test/sun/security/smartcardio/TestExclusive.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/sun/security/smartcardio/TestExclusive.java	Thu Feb 06 01:43:16 2020 +0000
@@ -26,10 +26,11 @@
  * @bug 6239117
  * @summary verify that beginExclusive()/endExclusive() works
  * @author Andreas Sterbenz
- * @ignore requires special hardware
  * @run main/manual TestExclusive
  */
 
+// This test requires special hardware.
+
 import javax.smartcardio.Card;
 import javax.smartcardio.CardChannel;
 import javax.smartcardio.CardException;
--- a/test/sun/security/smartcardio/TestMultiplePresent.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/sun/security/smartcardio/TestMultiplePresent.java	Thu Feb 06 01:43:16 2020 +0000
@@ -26,10 +26,11 @@
  * @bug 6239117 6445367
  * @summary test that CardTerminals.waitForCard() works
  * @author Andreas Sterbenz
- * @ignore requires special hardware
- * @run main/manual TestPresent
+ * @run main/manual TestMultiplePresent
  */
 
+// This test requires special hardware.
+
 import java.util.List;
 import javax.smartcardio.CardTerminal;
 import javax.smartcardio.CardTerminals;
--- a/test/sun/security/smartcardio/TestPresent.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/sun/security/smartcardio/TestPresent.java	Thu Feb 06 01:43:16 2020 +0000
@@ -26,10 +26,11 @@
  * @bug 6293769 6294527
  * @summary test that the isCardPresent()/waitForX() APIs work correctly
  * @author Andreas Sterbenz
- * @ignore requires special hardware
  * @run main/manual TestPresent
  */
 
+// This test requires special hardware.
+
 import java.util.List;
 import javax.smartcardio.CardTerminal;
 import javax.smartcardio.TerminalFactory;
--- a/test/sun/security/smartcardio/TestTransmit.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/sun/security/smartcardio/TestTransmit.java	Thu Feb 06 01:43:16 2020 +0000
@@ -26,10 +26,11 @@
  * @bug 6293769 6294527
  * @summary test transmit() works
  * @author Andreas Sterbenz
- * @ignore requires special hardware
  * @run main/manual TestTransmit
  */
 
+// This test requires special hardware.
+
 import java.io.BufferedReader;
 import java.io.ByteArrayOutputStream;
 import java.io.FileReader;
--- a/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/X509TrustManagerImpl/ClientServer.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/X509TrustManagerImpl/ClientServer.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -21,19 +21,20 @@
  * questions.
  */
 
-//
-// SunJSSE does not support dynamic system properties, no way to re-use
-// system properties in samevm/agentvm mode.
-//
-
 /*
  * @test
  * @bug 4717766
+ * @author Brad Wetmore
  * @summary 1.0.3 JsseX509TrustManager erroneously calls isClientTrusted()
- * @run main/othervm ClientServer
- * @ignore JSSE supports algorithm constraints with CR 6916074,
- *     need to update this test case in JDK 7 soon
- * @author Brad Wetmore
+ * @run main/manual ClientServer
+ */
+
+/*
+ * SunJSSE does not support dynamic system properties, no way to re-use
+ * system properties in samevm/agentvm mode.
+ *
+ * JSSE supports algorithm constraints with CR 6916074, need to update
+ * this test case in JDK 7 soon.
  *
  * This problem didn't exist in JSSE 1.4, only JSSE 1.0.3.  However,
  * this is a useful test, so I decided to include it in 1.4.2.
--- a/test/sun/security/tools/jarsigner/EntriesOrder.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/sun/security/tools/jarsigner/EntriesOrder.java	Thu Feb 06 01:43:16 2020 +0000
@@ -25,6 +25,9 @@
  * @test
  * @bug 8031572
  * @summary jarsigner -verify exits with 0 when a jar file is not properly signed
+ * @library /lib/testlibrary
+ * @build jdk.testlibrary.IOUtils
+ * @run main EntriesOrder
  */
 
 import java.io.FileInputStream;
@@ -39,6 +42,8 @@
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipOutputStream;
 
+import jdk.testlibrary.IOUtils;
+
 public class EntriesOrder {
 
     public static void main(String[] args) throws Exception {
@@ -70,10 +75,10 @@
         if (!m.run("cvf a.jar a META-INF/inf".split(" "))) {
             throw new Exception("jar creation failed");
         }
-        sun.security.tools.KeyTool.main(
+        sun.security.tools.keytool.Main.main(
                 ("-keystore jks -storepass changeit -keypass changeit -dname" +
                         " CN=A -alias a -genkeypair -keyalg rsa").split(" "));
-        sun.security.tools.JarSigner.main(
+        sun.security.tools.jarsigner.Main.main(
                 "-keystore jks -storepass changeit a.jar a".split(" "));
         m = new sun.tools.jar.Main(System.out, System.err, "jar");
         if (!m.run("xvf a.jar".split(" "))) {
@@ -106,7 +111,7 @@
                 Enumeration<JarEntry> jes = jf.entries();
                 while (jes.hasMoreElements()) {
                     JarEntry je = jes.nextElement();
-                    sun.misc.IOUtils.readFully(jf.getInputStream(je), -1, true);
+                    IOUtils.readFully(jf.getInputStream(je));
                     Certificate[] certs = je.getCertificates();
                     if (certs != null && certs.length > 0) {
                         cc++;
@@ -138,7 +143,7 @@
                 while (true) {
                     JarEntry je = jis.getNextJarEntry();
                     if (je == null) break;
-                    sun.misc.IOUtils.readFully(jis, -1, true);
+                    IOUtils.readFully(jis);
                     Certificate[] certs = je.getCertificates();
                     if (certs != null && certs.length > 0) {
                         cc++;
--- a/test/sun/security/tools/jarsigner/TimestampCheck.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/sun/security/tools/jarsigner/TimestampCheck.java	Thu Feb 06 01:43:16 2020 +0000
@@ -749,7 +749,7 @@
         try (JarFile jf = new JarFile(file)) {
             JarEntry je = jf.getJarEntry("META-INF/SIGNER.RSA");
             try (InputStream is = jf.getInputStream(je)) {
-                byte[] content = IOUtils.readFully(is, -1, true);
+                byte[] content = IOUtils.readAllBytes(is);
                 PKCS7 p7 = new PKCS7(content);
                 SignerInfo[] si = p7.getSignerInfos();
                 if (si == null || si.length == 0) {
--- a/test/sun/security/tools/jarsigner/TsacertOptionTest.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/sun/security/tools/jarsigner/TsacertOptionTest.java	Thu Feb 06 01:43:16 2020 +0000
@@ -87,6 +87,7 @@
                 "-storepass", PASSWORD,
                 "-keypass", PASSWORD,
                 "-dname", "CN=CA",
+                "-ext", "bc:c",
                 "-validity", Integer.toString(VALIDITY)).shouldHaveExitValue(0);
         ProcessTools.executeCommand(KEYTOOL,
                 "-genkey",
--- a/test/sun/security/tools/jarsigner/Warning.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/sun/security/tools/jarsigner/Warning.java	Thu Feb 06 01:43:16 2020 +0000
@@ -42,7 +42,7 @@
 
         Files.deleteIfExists(Paths.get("ks"));
 
-        newCert("ca", "-validity 365000");
+        newCert("ca", "-validity 365000", "-ext bc:c");
 
         recreateJar();
 
--- a/test/sun/security/tools/jarsigner/concise_jarsigner.sh	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/sun/security/tools/jarsigner/concise_jarsigner.sh	Thu Feb 06 01:43:16 2020 +0000
@@ -22,7 +22,7 @@
 #
 
 # @test
-# @bug 6802846 8172529
+# @bug 6802846 8172529 8227758
 # @summary jarsigner needs enhanced cert validation(options)
 #
 # @run shell/timeout=240 concise_jarsigner.sh
@@ -204,15 +204,11 @@
 $JARSIGNER -strict -keystore $KS -storepass changeit -certchain certchain a.jar altchain
 [ $? = 0 ] || exit $LINENO
 
-# if ca2 is removed, -certchain still work because altchain is a self-signed entry and
-# it is trusted by jarsigner
+# if ca2 is removed and cert is imported, -certchain won't work because this certificate
+# entry is not trusted
 # save ca2.cert for easy replay
 $KT -exportcert -file ca2.cert -alias ca2
 $KT -delete -alias ca2
-$JARSIGNER -strict -keystore $KS -storepass changeit -certchain certchain a.jar altchain
-[ $? = 0 ] || exit $LINENO
-
-# if cert is imported, -certchain won't work because this certificate entry is not trusted
 $KT -importcert -file certchain -alias altchain -noprompt
 $JARSIGNER -strict -keystore $KS -storepass changeit -certchain certchain a.jar altchain
 [ $? = 4 ] || exit $LINENO
@@ -225,8 +221,8 @@
 # ==========================================================
 
 $KT -genkeypair -alias ee -dname CN=ee
-$KT -genkeypair -alias caone -dname CN=caone
-$KT -genkeypair -alias catwo -dname CN=catwo
+$KT -genkeypair -alias caone -dname CN=caone -ext bc:c
+$KT -genkeypair -alias catwo -dname CN=catwo -ext bc:c
 
 $KT -certreq -alias ee | $KT -gencert -alias catwo -rfc > ee.cert
 $KT -certreq -alias catwo | $KT -gencert -alias caone -sigalg MD5withRSA -rfc > catwo.cert
--- a/test/sun/security/tools/jarsigner/ec.sh	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/sun/security/tools/jarsigner/ec.sh	Thu Feb 06 01:43:16 2020 +0000
@@ -53,7 +53,7 @@
 echo A > A
 $JAR cvf $JFILE A
 
-$KT -alias ca -dname CN=ca -keyalg ec -genkey -validity 300 || exit 11
+$KT -alias ca -dname CN=ca -keyalg ec -genkey -validity 300 -ext bc:c || exit 11
 
 $KT -alias a -dname CN=a -keyalg ec -genkey || exit 11
 $KT -alias a -certreq | $KT -gencert -alias ca -validity 300 | $KT -import -alias a || exit 111
--- a/test/sun/security/tools/jarsigner/onlymanifest.sh	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/sun/security/tools/jarsigner/onlymanifest.sh	Thu Feb 06 01:43:16 2020 +0000
@@ -57,7 +57,7 @@
 echo "Key: Value" > manifest
 $JAR cvfm $JFILE manifest
 
-$KT -alias ca -dname CN=ca -genkey -validity 300 || exit 1
+$KT -alias ca -dname CN=ca -genkey -validity 300 -ext bc:c || exit 1
 $KT -alias a -dname CN=a -genkey -validity 300 || exit 2
 $KT -alias a -certreq | $KT -gencert -alias ca -validity 300 | $KT -import -alias a || exit 3
 $JARSIGNER -keystore $KS -storepass changeit $JFILE a -debug -strict || exit 4
--- a/test/sun/security/tools/jarsigner/warnings/BadExtendedKeyUsageTest.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/sun/security/tools/jarsigner/warnings/BadExtendedKeyUsageTest.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -53,7 +53,7 @@
         // create a certificate whose signer certificate's
         // ExtendedKeyUsage extension doesn't allow code signing
         // create key pair for jar signing
-        createAlias(CA_KEY_ALIAS);
+        createAlias(CA_KEY_ALIAS, "-ext", "bc:c");
         createAlias(KEY_ALIAS);
 
         issueCert(
--- a/test/sun/security/tools/jarsigner/warnings/BadKeyUsageTest.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/sun/security/tools/jarsigner/warnings/BadKeyUsageTest.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -53,7 +53,7 @@
 
         // create a certificate whose signer certificate's KeyUsage extension
         // doesn't allow code signing
-        createAlias(CA_KEY_ALIAS);
+        createAlias(CA_KEY_ALIAS, "-ext", "bc:c");
         createAlias(KEY_ALIAS);
 
         issueCert(
--- a/test/sun/security/tools/jarsigner/warnings/BadNetscapeCertTypeTest.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/sun/security/tools/jarsigner/warnings/BadNetscapeCertTypeTest.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -54,7 +54,7 @@
         // create a certificate whose signer certificate's
         // NetscapeCertType extension doesn't allow code signing
         // create key pair for jar signing
-        createAlias(CA_KEY_ALIAS);
+        createAlias(CA_KEY_ALIAS, "-ext", "bc:c");
         createAlias(KEY_ALIAS);
 
         issueCert(
--- a/test/sun/security/tools/jarsigner/warnings/ChainNotValidatedTest.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/sun/security/tools/jarsigner/warnings/ChainNotValidatedTest.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -54,7 +54,7 @@
         // Root CA is not checked at all. If the intermediate CA has
         // BasicConstraints extension set to true, it will be valid.
         // Otherwise, chain validation will fail.
-        createAlias(CA_KEY_ALIAS);
+        createAlias(CA_KEY_ALIAS, "-ext", "bc:c");
         createAlias(CA2_KEY_ALIAS);
         issueCert(CA2_KEY_ALIAS,
                 "-ext",
--- a/test/sun/security/tools/jarsigner/warnings/HasExpiredCertTest.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/sun/security/tools/jarsigner/warnings/HasExpiredCertTest.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -52,7 +52,7 @@
         JarUtils.createJar(UNSIGNED_JARFILE, FIRST_FILE);
 
         // create key pair for jar signing
-        createAlias(CA_KEY_ALIAS);
+        createAlias(CA_KEY_ALIAS, "-ext", "bc:c");
         createAlias(KEY_ALIAS);
 
         issueCert(
--- a/test/sun/security/tools/jarsigner/warnings/HasExpiringCertTest.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/sun/security/tools/jarsigner/warnings/HasExpiringCertTest.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -52,7 +52,7 @@
         JarUtils.createJar(UNSIGNED_JARFILE, FIRST_FILE);
 
         // create key pair for jar signing
-        createAlias(CA_KEY_ALIAS);
+        createAlias(CA_KEY_ALIAS, "-ext", "bc:c");
         createAlias(KEY_ALIAS);
 
         issueCert(
--- a/test/sun/security/tools/jarsigner/warnings/HasUnsignedEntryTest.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/sun/security/tools/jarsigner/warnings/HasUnsignedEntryTest.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -51,7 +51,7 @@
         JarUtils.createJar(UNSIGNED_JARFILE, FIRST_FILE);
 
         // create key pair for signing
-        createAlias(CA_KEY_ALIAS);
+        createAlias(CA_KEY_ALIAS, "-ext", "bc:c");
         createAlias(KEY_ALIAS);
         issueCert(
                 KEY_ALIAS,
--- a/test/sun/security/tools/jarsigner/warnings/MultipleWarningsTest.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/sun/security/tools/jarsigner/warnings/MultipleWarningsTest.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -54,7 +54,7 @@
         // create a jar file that contains one class file
         JarUtils.createJar(UNSIGNED_JARFILE, FIRST_FILE);
 
-        createAlias(CA_KEY_ALIAS);
+        createAlias(CA_KEY_ALIAS, "-ext", "bc:c");
 
         // create first expired certificate
         // whose ExtendedKeyUsage extension does not allow code signing
--- a/test/sun/security/tools/jarsigner/warnings/NoTimestampTest.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/sun/security/tools/jarsigner/warnings/NoTimestampTest.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -57,7 +57,7 @@
                 * 24 * 60 * 60 * 1000L);
 
         // create key pair
-        createAlias(CA_KEY_ALIAS);
+        createAlias(CA_KEY_ALIAS, "-ext", "bc:c");
         createAlias(KEY_ALIAS);
         issueCert(KEY_ALIAS,
                 "-validity", Integer.toString(VALIDITY));
--- a/test/sun/security/tools/jarsigner/warnings/NotSignedByAliasTest.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/sun/security/tools/jarsigner/warnings/NotSignedByAliasTest.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -49,7 +49,7 @@
         Utils.createFiles(FIRST_FILE);
         JarUtils.createJar(UNSIGNED_JARFILE, FIRST_FILE);
 
-        createAlias(CA_KEY_ALIAS);
+        createAlias(CA_KEY_ALIAS, "-ext", "bc:c");
 
         // create first key pair for signing
         createAlias(FIRST_KEY_ALIAS);
--- a/test/sun/security/tools/jarsigner/warnings/NotYetValidCertTest.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/sun/security/tools/jarsigner/warnings/NotYetValidCertTest.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -50,7 +50,7 @@
         JarUtils.createJar(UNSIGNED_JARFILE, FIRST_FILE);
 
         // create certificate that will be valid only tomorrow
-        createAlias(CA_KEY_ALIAS);
+        createAlias(CA_KEY_ALIAS, "-ext", "bc:c");
         createAlias(KEY_ALIAS);
 
         issueCert(
--- a/test/sun/security/tools/keytool/console.sh	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/sun/security/tools/keytool/console.sh	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2006, 2008, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2006, 2014, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -25,8 +25,6 @@
 # @bug 6418647 8005527
 # @summary Doc bug 5035358 shows sun.security.util.Password.readPassword() is buggy.
 # @author Weijun Wang
-# @ignore unable to test manual tools that have input from stdin,
-#               and output to stderr and stdout
 # @run shell/manual console.sh
 
 if [ "$ALT_PASS" = "" ]; then
--- a/test/sun/security/tools/keytool/i18n.sh	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/sun/security/tools/keytool/i18n.sh	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -25,9 +25,7 @@
 # @bug 4348369 7083664
 # @summary keytool not i18n compliant
 # @author charlie lai
-#
-# @ignore unable to test manual tools that have input from stdin,
-#		and output to stderr and stdout
+# @run shell/manual i18n.sh
 
 # set a few environment variables so that the shell-script can run stand-alone
 # in the source directory
--- a/test/sun/security/util/DerValue/BadValue.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/sun/security/util/DerValue/BadValue.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -35,43 +35,48 @@
 
     public static void main(String[] args) throws Exception {
 
-        // Test IOUtils.readFully
+        // Test IOUtils.
 
         // We have 4 bytes
         InputStream in = new ByteArrayInputStream(new byte[10]);
-        byte[] bs = IOUtils.readFully(in, 4, true);
+        byte[] bs = IOUtils.readExactlyNBytes(in, 4);
         if (bs.length != 4 || in.available() != 6) {
             throw new Exception("First read error");
         }
         // But only 6 left
-        bs = IOUtils.readFully(in, 10, false);
+        bs = IOUtils.readNBytes(in, 10);
         if (bs.length != 6 || in.available() != 0) {
             throw new Exception("Second read error");
         }
-        // MAX read as much as it can
+        // MAX length results in exception
         in = new ByteArrayInputStream(new byte[10]);
-        bs = IOUtils.readFully(in, Integer.MAX_VALUE, true);
-        if (bs.length != 10 || in.available() != 0) {
-            throw new Exception("Second read error");
+        try {
+            bs = IOUtils.readExactlyNBytes(in, Integer.MAX_VALUE);
+            throw new Exception("No exception on MAX_VALUE length");
+        } catch (EOFException ex) {
+            // this is expected
         }
-        // MAX ignore readAll
+        // -1 length results in exception
         in = new ByteArrayInputStream(new byte[10]);
-        bs = IOUtils.readFully(in, Integer.MAX_VALUE, false);
-        if (bs.length != 10 || in.available() != 0) {
-            throw new Exception("Second read error");
+        try {
+            bs = IOUtils.readExactlyNBytes(in, -1);
+            throw new Exception("No exception on -1 length");
+        } catch (IOException ex) {
+            // this is expected
         }
+
         // 20>10, readAll means failure
         in = new ByteArrayInputStream(new byte[10]);
         try {
-            bs = IOUtils.readFully(in, 20, true);
-            throw new Exception("Third read error");
+            bs = IOUtils.readExactlyNBytes(in, 20);
+            throw new Exception("No exception on EOF");
         } catch (EOFException e) {
             // OK
         }
         int bignum = 10 * 1024 * 1024;
-        bs = IOUtils.readFully(new SuperSlowStream(bignum), -1, true);
+        bs = IOUtils.readExactlyNBytes(new SuperSlowStream(bignum), bignum);
         if (bs.length != bignum) {
-            throw new Exception("Fourth read error");
+            throw new Exception("Read returned small array");
         }
 
         // Test DerValue
--- a/test/sun/security/validator/EndEntityExtensionCheck.java	Wed Nov 20 06:36:47 2019 +0000
+++ b/test/sun/security/validator/EndEntityExtensionCheck.java	Thu Feb 06 01:43:16 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,6 +26,7 @@
  * @bug 8076117
  * @summary EndEntityChecker should not process custom extensions
  *          after PKIX validation
+ * @run main/othervm -Djdk.security.allowNonCaAnchor EndEntityExtensionCheck
  */
 
 import java.io.ByteArrayInputStream;