Mercurial > hg > release > icedtea7-forest-2.6 > jdk
changeset 9914:0b1953a9e081
Merge jdk7u251-b02
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 "<<ALL FILES>>" 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 "<<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> <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> {@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 & 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 & 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;