Mercurial > hg > icedtea8-forest > jdk
changeset 12453:7e0b701f3ee0 icedtea-3.3.0pre02
Merge jdk8u121-b13
line wrap: on
line diff
--- a/.hgtags Fri Jan 13 17:09:28 2017 +0000 +++ b/.hgtags Mon Jan 23 16:30:43 2017 +0000 @@ -662,6 +662,10 @@ 32c84f7d918fdb8e501f5a512c8804305ec88286 icedtea-3.2.0pre03 48c99b42383912886c005891c04b5f599adf6722 jdk8u102-b14 222d3ac3aa1f99f16e31c1c4a10f916ce83ff759 jdk8u102-b31 +e3839fe291add6e0ea199457fb31c9312cc5dd77 jdk8u102-b32 +275fcb7d4e3e70a37ac70c33d087a805ba182f1e jdk8u102-b33 +d783f00bb04a6fff7ddf1555572c1f3cdfd21e59 jdk8u102-b34 +958684c9f1e73d9310511559c770823180d33e4b jdk8u102-b35 ebc56c2e803597ef409a5296addc986b390d934d jdk8u111-b00 c4f03717831993e4658b8366810ca4682ece952d jdk8u111-b01 de1d09f09e571e38afdf1fb72984ec210e7c19e6 jdk8u111-b02 @@ -693,4 +697,19 @@ 16c649b70dc3d437ab16ff8125a50125deda2bc9 jdk8u112-b13 d2d8b67021a0f41e0eabd711bfd87a943dc0a8d5 jdk8u112-b14 60767ec3909b3d0cb26dd7b3f952c62053719dda jdk8u112-b15 +5dd7e4bae5c2f1ee4f80c5570e7e3e2f715f7a32 jdk8u112-b16 5ce54ea881947640051a10a1579d4da697b02293 icedtea-3.3.0pre01 +41fac11792c1ee6945f56721ee558a7424395a81 jdk8u112-b31 +ab5ff8f1e52c5e3ca02e988f4d978af63ceca5b8 jdk8u121-b00 +5f0839ac7e0d25dd1ae705df496b12ca76c26d59 jdk8u121-b01 +f91e3aa155b3c6774afb456db15fb358313d5771 jdk8u121-b02 +ecdb635eaf4886829089b987c339e35dfb5ea0e8 jdk8u121-b03 +d54219144844fb358f87f4a37255242aae9782fa jdk8u121-b04 +fb4e3a7375c91e02bd1c0a764dfb53fba3839c18 jdk8u121-b05 +3bc671481026decc460e636e8b2f19a36bfe89af jdk8u121-b06 +a2c2fbc61674869e85d5345804cff4834cc010d1 jdk8u121-b07 +392209fbe127896df2749344ea127f2c0a62da55 jdk8u121-b08 +494d27357b8cfc6b6c4346a814c8717a8502d769 jdk8u121-b09 +d66de7e2f672a1ff6947846818412fa899456972 jdk8u121-b10 +ec72a941be0a50ab77f5375cf710bc06e4f118d3 jdk8u121-b11 +9561afc12df843ef21ecd9d7b3633371e7a2bfc4 jdk8u121-b12
--- a/make/data/tzdata/VERSION Fri Jan 13 17:09:28 2017 +0000 +++ b/make/data/tzdata/VERSION Mon Jan 23 16:30:43 2017 +0000 @@ -21,4 +21,4 @@ # or visit www.oracle.com if you need additional information or have any # questions. # -tzdata2016f +tzdata2016i
--- a/make/data/tzdata/africa Fri Jan 13 17:09:28 2017 +0000 +++ b/make/data/tzdata/africa Mon Jan 23 16:30:43 2017 +0000 @@ -487,7 +487,7 @@ # http://www.libyaherald.com/2013/10/24/correction-no-time-change-tomorrow/ # # From Paul Eggert (2013-10-25): -# For now, assume they're reverting to the pre-2012 rules of permanent UTC+2. +# For now, assume they're reverting to the pre-2012 rules of permanent UT +02. # Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S Rule Libya 1951 only - Oct 14 2:00 1:00 S
--- a/make/data/tzdata/antarctica Fri Jan 13 17:09:28 2017 +0000 +++ b/make/data/tzdata/antarctica Mon Jan 23 16:30:43 2017 +0000 @@ -33,9 +33,7 @@ # http://www.spri.cam.ac.uk/bob/periant.htm # for information. # Unless otherwise specified, we have no time zone information. -# -# Except for the French entries, -# I made up all time zone abbreviations mentioned here; corrections welcome! + # FORMAT is '-00' and GMTOFF is 0 for locations while uninhabited. # Argentina - year-round bases @@ -52,7 +50,7 @@ # previously sealers and scientific personnel wintered # Margaret Turner reports # http://web.archive.org/web/20021204222245/http://www.dstc.qut.edu.au/DST/marg/daylight.html -# (1999-09-30) that they're UTC+5, with no DST; +# (1999-09-30) that they're UT +05, with no DST; # presumably this is when they have visitors. # # year-round bases @@ -89,25 +87,29 @@ # Background: # http://www.timeanddate.com/news/time/antartica-time-changes-2010.html +# From Steffen Thorsen (2016-10-28): +# 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 Antarctica/Casey 0 - -00 1969 - 8:00 - AWST 2009 Oct 18 2:00 - # Australian Western Std Time - 11:00 - CAST 2010 Mar 5 2:00 # Casey Time - 8:00 - AWST 2011 Oct 28 2:00 - 11:00 - CAST 2012 Feb 21 17:00u - 8:00 - AWST + 8:00 - +08 2009 Oct 18 2:00 + 11:00 - +11 2010 Mar 5 2:00 + 8:00 - +08 2011 Oct 28 2:00 + 11:00 - +11 2012 Feb 21 17:00u + 8:00 - +08 2016 Oct 22 + 11:00 - +11 Zone Antarctica/Davis 0 - -00 1957 Jan 13 - 7:00 - DAVT 1964 Nov # Davis Time + 7:00 - +07 1964 Nov 0 - -00 1969 Feb - 7:00 - DAVT 2009 Oct 18 2:00 - 5:00 - DAVT 2010 Mar 10 20:00u - 7:00 - DAVT 2011 Oct 28 2:00 - 5:00 - DAVT 2012 Feb 21 20:00u - 7:00 - DAVT + 7:00 - +07 2009 Oct 18 2:00 + 5:00 - +05 2010 Mar 10 20:00u + 7:00 - +07 2011 Oct 28 2:00 + 5:00 - +05 2012 Feb 21 20:00u + 7:00 - +07 Zone Antarctica/Mawson 0 - -00 1954 Feb 13 - 6:00 - MAWT 2009 Oct 18 2:00 # Mawson Time - 5:00 - MAWT + 6:00 - +06 2009 Oct 18 2:00 + 5:00 - +05 # References: # Casey Weather (1998-02-26) # http://www.antdiv.gov.au/aad/exop/sfo/casey/casey_aws.html @@ -161,7 +163,7 @@ # # Zone NAME GMTOFF RULES FORMAT [UNTIL] Zone Indian/Kerguelen 0 - -00 1950 # Port-aux-Français - 5:00 - TFT # ISO code TF Time + 5:00 - +05 # # year-round base in the main continent # Dumont d'Urville, Île des Pétrels, -6640+14001, since 1956-11 @@ -172,9 +174,9 @@ # # Zone NAME GMTOFF RULES FORMAT [UNTIL] Zone Antarctica/DumontDUrville 0 - -00 1947 - 10:00 - PMT 1952 Jan 14 # Port-Martin Time + 10:00 - +10 1952 Jan 14 0 - -00 1956 Nov - 10:00 - DDUT # Dumont-d'Urville Time + 10:00 - +10 # France & Italy - year-round base # Concordia, -750600+1232000, since 2005 @@ -200,7 +202,7 @@ # station of Japan, it's appropriate for the principal location. # Zone NAME GMTOFF RULES FORMAT [UNTIL] Zone Antarctica/Syowa 0 - -00 1957 Jan 29 - 3:00 - SYOT # Syowa Time + 3:00 - +03 # See: # NIPR Antarctic Research Activities (1999-08-17) # http://www.nipr.ac.jp/english/ara01.html @@ -237,17 +239,17 @@ # correct, but they should be quite close to the actual dates. # # From Paul Eggert (2014-03-21): -# The CET-switching Troll rules require zic from tzcode 2014b or later, so as +# The CET-switching Troll rules require zic from tz 2014b or later, so as # suggested by Bengt-Inge Larsson comment them out for now, and approximate # with only UTC and CEST. Uncomment them when 2014b is more prevalent. # # Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S -#Rule Troll 2005 max - Mar 1 1:00u 1:00 CET -Rule Troll 2005 max - Mar lastSun 1:00u 2:00 CEST -#Rule Troll 2005 max - Oct lastSun 1:00u 1:00 CET -#Rule Troll 2004 max - Nov 7 1:00u 0:00 UTC +#Rule Troll 2005 max - Mar 1 1:00u 1:00 +01 +Rule Troll 2005 max - Mar lastSun 1:00u 2:00 +02 +#Rule Troll 2005 max - Oct lastSun 1:00u 1:00 +01 +#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 UTC +Rule Troll 2004 max - Oct lastSun 1:00u 0:00 +00 # Zone NAME GMTOFF RULES FORMAT [UNTIL] Zone Antarctica/Troll 0 - -00 2005 Feb 12 0:00 Troll %s @@ -288,10 +290,10 @@ # changes during the year and does not necessarily correspond to mean # solar noon. So the Vostok time might have been whatever the clocks # happened to be during their visit. So we still don't really know what time -# it is at Vostok. But we'll guess UTC+6. +# it is at Vostok. But we'll guess +06. # Zone Antarctica/Vostok 0 - -00 1957 Dec 16 - 6:00 - VOST # Vostok time + 6:00 - +06 # S Africa - year-round bases # Marion Island, -4653+03752 @@ -324,7 +326,7 @@ # # Zone NAME GMTOFF RULES FORMAT [UNTIL] Zone Antarctica/Rothera 0 - -00 1976 Dec 1 - -3:00 - ROTT # Rothera time + -3:00 - -03 # Uruguay - year round base # Artigas, King George Island, -621104-0585107
--- a/make/data/tzdata/asia Fri Jan 13 17:09:28 2017 +0000 +++ b/make/data/tzdata/asia Mon Jan 23 16:30:43 2017 +0000 @@ -139,13 +139,11 @@ # http://www.worldtimezone.com/dst_news/dst_news_armenia03.html # Zone NAME GMTOFF RULES FORMAT [UNTIL] Zone Asia/Yerevan 2:58:00 - LMT 1924 May 2 - 3:00 - YERT 1957 Mar # Yerevan Time - 4:00 RussiaAsia YER%sT 1991 Mar 31 2:00s - 3:00 1:00 YERST 1991 Sep 23 # independence - 3:00 RussiaAsia AM%sT 1995 Sep 24 2:00s - 4:00 - AMT 1997 - 4:00 RussiaAsia AM%sT 2012 Feb 9 - 4:00 - AMT + 3:00 - +03 1957 Mar + 4:00 RussiaAsia +04/+05 1991 Mar 31 2:00s + 3:00 RussiaAsia +03/+04 1995 Sep 24 2:00s + 4:00 - +04 1997 + 4:00 RussiaAsia +04/+05 # Azerbaijan @@ -166,13 +164,12 @@ Rule Azer 1997 2015 - Oct lastSun 5:00 0 - # Zone NAME GMTOFF RULES FORMAT [UNTIL] Zone Asia/Baku 3:19:24 - LMT 1924 May 2 - 3:00 - BAKT 1957 Mar # Baku Time - 4:00 RussiaAsia BAK%sT 1991 Mar 31 2:00s - 3:00 1:00 BAKST 1991 Aug 30 # independence - 3:00 RussiaAsia AZ%sT 1992 Sep lastSun 2:00s - 4:00 - AZT 1996 # Azerbaijan Time - 4:00 EUAsia AZ%sT 1997 - 4:00 Azer AZ%sT + 3:00 - +03 1957 Mar + 4:00 RussiaAsia +04/+05 1991 Mar 31 2:00s + 3:00 RussiaAsia +03/+04 1992 Sep lastSun 2:00s + 4:00 - +04 1996 + 4:00 EUAsia +04/+05 1997 + 4:00 Azer +04/+05 # Bahrain # See Asia/Qatar. @@ -291,7 +288,7 @@ # Milne says 6:24:40 was the meridian of the time ball observatory at Rangoon. # Zone NAME GMTOFF RULES FORMAT [UNTIL] -Zone Asia/Rangoon 6:24:40 - LMT 1880 # or Yangon +Zone Asia/Yangon 6:24:40 - LMT 1880 # or Rangoon 6:24:40 - RMT 1920 # Rangoon Mean Time? 6:30 - BURT 1942 May # Burma Time 9:00 - JST 1945 May 3 @@ -406,7 +403,7 @@ # Lewiston (ME) Daily Sun (1939-05-29), p 17, said "Even the time is # different - the occupied districts going by Tokyo time, an hour # ahead of that prevailing in the rest of Shanghai." Guess that the -# Xujiahui Observatory was under French control and stuck with UT+8. +# Xujiahui Observatory was under French control and stuck with UT +08. # # In earlier versions of this file, China had many separate Zone entries, but # this was based on what were apparently incorrect data in Shanks & Pottenger. @@ -415,26 +412,26 @@ # Proposed in 1918 and theoretically in effect until 1949 (although in practice # mainly observed in coastal areas), the five zones were: # -# Changbai Time ("Long-white Time", Long-white = Heilongjiang area) UT+8.5 +# Changbai Time ("Long-white Time", Long-white = Heilongjiang area) UT +08:30 # Asia/Harbin (currently a link to Asia/Shanghai) # Heilongjiang (except Mohe county), Jilin # -# Zhongyuan Time ("Central plain Time") UT+8 +# Zhongyuan Time ("Central plain Time") UT +08 # Asia/Shanghai # most of China # This currently represents most other zones as well, # as apparently these regions have been the same since 1970. # Milne gives 8:05:43.2 for Xujiahui Observatory time; round to nearest. -# Guo says Shanghai switched to UT+8 "from the end of the 19th century". +# Guo says Shanghai switched to UT +08 "from the end of the 19th century". # -# Long-shu Time (probably due to Long and Shu being two names of that area) UT+7 +# Long-shu Time (probably due to Long and Shu being two names of the area) UT +07 # Asia/Chongqing (currently a link to Asia/Shanghai) # Guangxi, Guizhou, Hainan, Ningxia, Sichuan, Shaanxi, and Yunnan; # most of Gansu; west Inner Mongolia; west Qinghai; and the Guangdong # counties Deqing, Enping, Kaiping, Luoding, Taishan, Xinxing, # Yangchun, Yangjiang, Yu'nan, and Yunfu. # -# Xin-zang Time ("Xinjiang-Tibet Time") UT+6 +# Xin-zang Time ("Xinjiang-Tibet Time") UT +06 # Asia/Urumqi # This currently represents Kunlun Time as well, # as apparently the two regions have been the same since 1970. @@ -447,7 +444,7 @@ # Shihezi, Changji, Yanqi, Heshuo, Tuokexun, Tulufan, Shanshan, Hami, # Fukang, Kuitun, Kumukuli, Miquan, Qitai, and Turfan. # -# Kunlun Time UT+5.5 +# Kunlun Time UT +05:30 # Asia/Kashgar (currently a link to Asia/Urumqi) # West Tibet, including Pulan, Aheqi, Shufu, Shule; # West Xinjiang, including Aksu, Atushi, Yining, Hetian, Cele, Luopu, Nileke, @@ -463,7 +460,7 @@ # # On the other hand, ethnic Uyghurs, who make up about half the # population of Xinjiang, typically use "Xinjiang time" which is two -# hours behind Beijing time, or UTC +0600. The government of the Xinjiang +# hours behind Beijing time, or UT +06. The government of the Xinjiang # Uyghur Autonomous Region, (XAUR, or just Xinjiang for short) as well as # local governments such as the Ürümqi city government use both times in # publications, referring to what is popularly called Xinjiang time as @@ -519,8 +516,8 @@ # having the same time as Beijing. # From Paul Eggert (2014-06-30): -# In the early days of the PRC, Tibet was given its own time zone (UT+6) but -# this was withdrawn in 1959 and never reinstated; see Tubten Khétsun, +# In the early days of the PRC, Tibet was given its own time zone (UT +06) +# but this was withdrawn in 1959 and never reinstated; see Tubten Khétsun, # Memories of life in Lhasa under Chinese Rule, Columbia U Press, ISBN # 978-0231142861 (2008), translator's introduction by Matthew Akester, p x. # As this is before our 1970 cutoff, Tibet doesn't need a separate zone. @@ -534,12 +531,12 @@ # Republics, the Soviet Union, the Kuomintang, and the People's Republic of # China, and tracking down all these organizations' timekeeping rules would be # quite a trick. Approximate this lost history by a transition from LMT to -# XJT at the start of 1928, the year of accession of the warlord Jin Shuren, +# UT +06 at the start of 1928, the year of accession of the warlord Jin Shuren, # which happens to be the date given by Shanks & Pottenger (no doubt as a -# guess) as the transition from LMT. Ignore the usage of UT+8 before -# 1986-02-01 under the theory that the transition date to UT+8 is unknown and +# guess) as the transition from LMT. Ignore the usage of +08 before +# 1986-02-01 under the theory that the transition date to +08 is unknown and # that the sort of users who prefer Asia/Urumqi now typically ignored the -# UT+8 mandate back then. +# +08 mandate back then. # Zone NAME GMTOFF RULES FORMAT [UNTIL] # Beijing time, used throughout China; represented by Shanghai. @@ -744,7 +741,7 @@ # be found from historical government announcement database. # From Paul Eggert (2014-07-03): -# As per Yu-Cheng Chuang, say that Taiwan was at UT+9 from 1937-10-01 +# As per Yu-Cheng Chuang, say that Taiwan was at UT +09 from 1937-10-01 # until 1945-09-21 at 01:00, overriding Shanks & Pottenger. # Likewise, use Yu-Cheng Chuang's data for DST in Taiwan. @@ -797,9 +794,19 @@ ############################################################################### # Cyprus -# + # Milne says the Eastern Telegraph Company used 2:14:00. Stick with LMT. +# IATA SSIM (1998-09) has Cyprus using EU rules for the first time. + +# From Paul Eggert (2016-09-09): +# Yesterday's Cyprus Mail reports that Northern Cyprus followed Turkey's +# lead and switched from +02/+03 to +03 year-round. +# http://cyprus-mail.com/2016/09/08/two-time-zones-cyprus-turkey-will-not-turn-clocks-back-next-month/ # +# From Even Scharning (2016-10-31): +# Looks like the time zone split in Cyprus went through last night. +# http://cyprus-mail.com/2016/10/30/cyprus-new-division-two-time-zones-now-reality/ + # Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S Rule Cyprus 1975 only - Apr 13 0:00 1:00 S Rule Cyprus 1975 only - Oct 12 0:00 0 - @@ -814,7 +821,10 @@ Zone Asia/Nicosia 2:13:28 - LMT 1921 Nov 14 2:00 Cyprus EE%sT 1998 Sep 2:00 EUAsia EE%sT -# IATA SSIM (1998-09) has Cyprus using EU rules for the first time. +Zone Asia/Famagusta 2:15:48 - LMT 1921 Nov 14 + 2:00 Cyprus EE%sT 1998 Sep + 2:00 EUAsia EE%sT 2016 Sep 8 + 3:00 - +03 # Classically, Cyprus belongs to Asia; e.g. see Herodotus, Histories, I.72. # However, for various reasons many users expect to find it under Europe. @@ -858,16 +868,15 @@ # Zone NAME GMTOFF RULES FORMAT [UNTIL] Zone Asia/Tbilisi 2:59:11 - LMT 1880 2:59:11 - TBMT 1924 May 2 # Tbilisi Mean Time - 3:00 - TBIT 1957 Mar # Tbilisi Time - 4:00 RussiaAsia TBI%sT 1991 Mar 31 2:00s - 3:00 1:00 TBIST 1991 Apr 9 # independence - 3:00 RussiaAsia GE%sT 1992 # Georgia Time - 3:00 E-EurAsia GE%sT 1994 Sep lastSun - 4:00 E-EurAsia GE%sT 1996 Oct lastSun - 4:00 1:00 GEST 1997 Mar lastSun - 4:00 E-EurAsia GE%sT 2004 Jun 27 - 3:00 RussiaAsia GE%sT 2005 Mar lastSun 2:00 - 4:00 - GET + 3:00 - +03 1957 Mar + 4:00 RussiaAsia +04/+05 1991 Mar 31 2:00s + 3:00 RussiaAsia +03/+04 1992 + 3:00 E-EurAsia +03/+04 1994 Sep lastSun + 4:00 E-EurAsia +04/+05 1996 Oct lastSun + 4:00 1:00 +05 1997 Mar lastSun + 4:00 E-EurAsia +04/+05 2004 Jun 27 + 3:00 RussiaAsia +03/+04 2005 Mar lastSun 2:00 + 4:00 - +04 # East Timor @@ -944,7 +953,7 @@ # These would be the earliest possible times for a change. # Régimes horaires pour le monde entier, by Henri Le Corre, (Éditions # Traditionnelles, 1987, Paris) says that Java and Madura switched -# from JST to UTC+07:30 on 1945-09-23, and gives 1944-09-01 for Jayapura +# from UT +09 to +07:30 on 1945-09-23, and gives 1944-09-01 for Jayapura # (Hollandia). For now, assume all Indonesian locations other than Jayapura # switched on 1945-09-23. # @@ -955,11 +964,11 @@ # summary published by the Time and Frequency Laboratory of the # Research Center for Calibration, Instrumentation and Metrology, # Indonesia, <http://time.kim.lipi.go.id/time-eng.php> (2006-09-29). -# The abbreviations are: +# The time zone abbreviations and UT offsets are: # -# WIB - UTC+7 - Waktu Indonesia Barat (Indonesia western time) -# WITA - UTC+8 - Waktu Indonesia Tengah (Indonesia central time) -# WIT - UTC+9 - Waktu Indonesia Timur (Indonesia eastern time) +# WIB - +07 - Waktu Indonesia Barat (Indonesia western time) +# WITA - +08 - Waktu Indonesia Tengah (Indonesia central time) +# WIT - +09 - Waktu Indonesia Timur (Indonesia eastern time) # # Zone NAME GMTOFF RULES FORMAT [UNTIL] # Java, Sumatra @@ -1848,11 +1857,11 @@ Rule Kyrgyz 1997 2004 - Oct lastSun 2:30 0 - # Zone NAME GMTOFF RULES FORMAT [UNTIL] Zone Asia/Bishkek 4:58:24 - LMT 1924 May 2 - 5:00 - FRUT 1930 Jun 21 # Frunze Time - 6:00 RussiaAsia FRU%sT 1991 Mar 31 2:00s - 5:00 1:00 FRUST 1991 Aug 31 2:00 # independence - 5:00 Kyrgyz KG%sT 2005 Aug 12 # Kyrgyzstan Time - 6:00 - KGT + 5:00 - +05 1930 Jun 21 + 6:00 RussiaAsia +06/+07 1991 Mar 31 2:00s + 5:00 RussiaAsia +05/+06 1991 Aug 31 2:00 + 5:00 Kyrgyz +05/+06 2005 Aug 12 + 6:00 - +06 ############################################################################### @@ -1891,25 +1900,24 @@ Rule ROK 1987 1988 - May Sun>=8 2:00 1:00 D Rule ROK 1987 1988 - Oct Sun>=8 3:00 0 S -# From Paul Eggert (2014-10-30): +# From Paul Eggert (2016-08-23): # The Korean Wikipedia entry gives the following sources for UT offsets: # -# 1908: Official Journal Article No. 3994 (Edict No. 5) +# 1908: Official Journal Article No. 3994 (decree No. 5) # 1912: Governor-General of Korea Official Gazette Issue No. 367 # (Announcement No. 338) # 1954: Presidential Decree No. 876 (1954-03-17) # 1961: Law No. 676 (1961-08-07) -# 1987: Law No. 3919 (1986-12-31) # -# The Wikipedia entry also has confusing information about a change -# to UT+9 in April 1910, but then what would be the point of the later change -# to UT+9 on 1912-01-01? Omit the 1910 change for now. +# (Another source "1987: Law No. 3919 (1986-12-31)" was in the 2014-10-30 +# edition of the Korean Wikipedia entry.) # # I guessed that time zone abbreviations through 1945 followed the same # rules as discussed under Taiwan, with nominal switches from JST to KST # when the respective cities were taken over by the Allies after WWII. # -# For Pyongyang we have no information; guess no changes since World War II. +# For Pyongyang, guess no changes from World War II until 2015, as we +# have no information otherwise. # From Steffen Thorsen (2015-08-07): # According to many news sources, North Korea is going to change to @@ -2069,7 +2077,7 @@ # Bill Bonnet (2005-05-19) reports that the US Embassy in Ulaanbaatar says # there is only one time zone and that DST is observed, citing Microsoft # Windows XP as the source. Risto Nykänen (2005-05-16) reports that -# travelmongolia.org says there are two time zones (UTC+7, UTC+8) with no DST. +# travelmongolia.org says there are two time zones (UT +07, +08) with no DST. # Oscar van Vlijmen (2005-05-20) reports that the Mongolian Embassy in # Washington, DC says there are two time zones, with DST observed. # He also found @@ -2572,11 +2580,6 @@ # From Paul Eggert (2015-03-03): # http://www.timeanddate.com/time/change/west-bank/ramallah?year=2014 # says that the fall 2014 transition was Oct 23 at 24:00. -# For future dates, guess the last Friday in March at 24:00 through -# the first Friday on or after October 21 at 00:00. This is consistent with -# the predictions in today's editions of the following URLs: -# http://www.timeanddate.com/time/change/gaza-strip/gaza -# http://www.timeanddate.com/time/change/west-bank/hebron # From Hannah Kreitem (2016-03-09): # http://www.palestinecabinet.gov.ps/WebSite/ar/ViewDetails?ID=31728 @@ -2586,7 +2589,21 @@ # # From Paul Eggert (2016-03-12): # Predict spring transitions on March's last Saturday at 01:00 from now on. -# Leave fall predictions alone for now. + +# From Sharef Mustafa (2016-10-19): +# [T]he Palestinian cabinet decision (Mar 8th 2016) published on +# http://www.palestinecabinet.gov.ps/WebSite/Upload/Decree/GOV_17/16032016134830.pdf +# states that summer time will end on Oct 29th at 01:00. +# +# From Tim Parenti (2016-10-19): +# Predict fall transitions on October's last Saturday at 01:00 from now on. +# This is consistent with the 2016 transition as well as our spring +# predictions. +# +# From Paul Eggert (2016-10-19): +# It's also consistent with predictions in the following URLs today: +# http://www.timeanddate.com/time/change/gaza-strip/gaza +# http://www.timeanddate.com/time/change/west-bank/hebron # Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S Rule EgyptAsia 1957 only - May 10 0:00 1:00 S @@ -2615,9 +2632,10 @@ Rule Palestine 2012 2014 - Mar lastThu 24:00 1:00 S Rule Palestine 2012 only - Sep 21 1:00 0 - Rule Palestine 2013 only - Sep Fri>=21 0:00 0 - -Rule Palestine 2014 max - Oct 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 lastSat 1:00 1:00 S +Rule Palestine 2016 max - Oct lastSat 1:00 0 - # Zone NAME GMTOFF RULES FORMAT [UNTIL] Zone Asia/Gaza 2:17:52 - LMT 1900 Oct @@ -2705,7 +2723,7 @@ # earlier date. # # Shanks & Pottenger also state that until 1968-05-01 Saudi Arabia had two -# time zones; the other zone, at UTC+4, was in the far eastern part of +# time zones; the other zone, at UT +04, was in the far eastern part of # the country. Ignore this, as it's before our 1970 cutoff. # # Zone NAME GMTOFF RULES FORMAT [UNTIL] @@ -2767,45 +2785,31 @@ # People who live in regions under Tamil control can use [TZ='Asia/Kolkata'], # as that zone has agreed with the Tamil areas since our cutoff date of 1970. -# From K Sethu (2006-04-25): -# I think the abbreviation LKT originated from the world of computers at -# the time of or subsequent to the time zone changes by SL Government -# twice in 1996 and probably SL Government or its standardization -# agencies never declared an abbreviation as a national standard. -# -# I recollect before the recent change the government announcements -# mentioning it as simply changing Sri Lanka Standard Time or Sri Lanka -# Time and no mention was made about the abbreviation. +# From Sadika Sumanapala (2016-10-19): +# According to http://www.sltime.org (maintained by Measurement Units, +# Standards & Services Department, Sri Lanka) abbreviation for Sri Lanka +# standard time is SLST. # -# If we look at Sri Lanka Department of Government's "Official News -# Website of Sri Lanka" ... http://www.news.lk/ we can see that they -# use SLT as abbreviation in time stamp at the beginning of each news -# item.... -# -# Within Sri Lanka I think LKT is well known among computer users and -# administrators. In my opinion SLT may not be a good choice because the -# nation's largest telcom / internet operator Sri Lanka Telcom is well -# known by that abbreviation - simply as SLT (there IP domains are -# slt.lk and sltnet.lk). -# -# But if indeed our government has adopted SLT as standard abbreviation -# (that we have not known so far) then it is better that it be used for -# all computers. - -# From Paul Eggert (2006-04-25): -# One possibility is that we wait for a bit for the dust to settle down -# and then see what people actually say in practice. +# From Paul Eggert (2016-10-18): +# "SLST" seems to be reasonably recent and rarely-used outside time +# zone nerd sources. I searched Google News and found three uses of +# it in the International Business Times of India in February and +# March of this year when discussing cricket match times, but nothing +# since then (though there has been a lot of cricket) and nothing in +# other English-language news sources. Our old abbreviation "LKT" is +# 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 Asia/Colombo 5:19:24 - LMT 1880 5:19:32 - MMT 1906 # Moratuwa Mean Time - 5:30 - IST 1942 Jan 5 - 5:30 0:30 IHST 1942 Sep - 5:30 1:00 IST 1945 Oct 16 2:00 - 5:30 - IST 1996 May 25 0:00 - 6:30 - LKT 1996 Oct 26 0:30 - 6:00 - LKT 2006 Apr 15 0:30 - 5:30 - IST + 5:30 - +0530 1942 Jan 5 + 5:30 0:30 +0530/+06 1942 Sep + 5:30 1:00 +0530/+0630 1945 Oct 16 2:00 + 5:30 - +0530 1996 May 25 0:00 + 6:30 - +0630 1996 Oct 26 0:30 + 6:00 - +06 2006 Apr 15 0:30 + 5:30 - +0530 # Syria # Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S @@ -2974,10 +2978,10 @@ # From Shanks & Pottenger. # Zone NAME GMTOFF RULES FORMAT [UNTIL] Zone Asia/Dushanbe 4:35:12 - LMT 1924 May 2 - 5:00 - DUST 1930 Jun 21 # Dushanbe Time - 6:00 RussiaAsia DUS%sT 1991 Mar 31 2:00s - 5:00 1:00 DUSST 1991 Sep 9 2:00s - 5:00 - TJT # Tajikistan Time + 5:00 - +05 1930 Jun 21 + 6:00 RussiaAsia +06/+07 1991 Mar 31 2:00s + 5:00 1:00 +05/+06 1991 Sep 9 2:00s + 5:00 - +05 # Thailand # Zone NAME GMTOFF RULES FORMAT [UNTIL] @@ -2991,11 +2995,10 @@ # From Shanks & Pottenger. # Zone NAME GMTOFF RULES FORMAT [UNTIL] Zone Asia/Ashgabat 3:53:32 - LMT 1924 May 2 # or Ashkhabad - 4:00 - ASHT 1930 Jun 21 # Ashkhabad Time - 5:00 RussiaAsia ASH%sT 1991 Mar 31 2:00 - 4:00 RussiaAsia ASH%sT 1991 Oct 27 # independence - 4:00 RussiaAsia TM%sT 1992 Jan 19 2:00 - 5:00 - TMT + 4:00 - +04 1930 Jun 21 + 5:00 RussiaAsia +05/+06 1991 Mar 31 2:00 + 4:00 RussiaAsia +04/+05 1992 Jan 19 2:00 + 5:00 - +05 # United Arab Emirates # Zone NAME GMTOFF RULES FORMAT [UNTIL] @@ -3007,20 +3010,18 @@ # Byalokoz 1919 says Uzbekistan was 4:27:53. # Zone NAME GMTOFF RULES FORMAT [UNTIL] Zone Asia/Samarkand 4:27:53 - LMT 1924 May 2 - 4:00 - SAMT 1930 Jun 21 # Samarkand Time - 5:00 - SAMT 1981 Apr 1 - 5:00 1:00 SAMST 1981 Oct 1 - 6:00 - TAST 1982 Apr 1 # Tashkent Time - 5:00 RussiaAsia SAM%sT 1991 Sep 1 # independence - 5:00 RussiaAsia UZ%sT 1992 - 5:00 - UZT + 4:00 - +04 1930 Jun 21 + 5:00 - +05 1981 Apr 1 + 5:00 1:00 +06 1981 Oct 1 + 6:00 - +06 1982 Apr 1 + 5:00 RussiaAsia +05/+06 1992 + 5:00 - +05 # Milne says Tashkent was 4:37:10.8; round to nearest. Zone Asia/Tashkent 4:37:11 - LMT 1924 May 2 - 5:00 - TAST 1930 Jun 21 # Tashkent Time - 6:00 RussiaAsia TAS%sT 1991 Mar 31 2:00 - 5:00 RussiaAsia TAS%sT 1991 Sep 1 # independence - 5:00 RussiaAsia UZ%sT 1992 - 5:00 - UZT + 5:00 - +05 1930 Jun 21 + 6:00 RussiaAsia +06/+07 1991 Mar 31 2:00 + 5:00 RussiaAsia +05/+06 1992 + 5:00 - +05 # Vietnam
--- a/make/data/tzdata/australasia Fri Jan 13 17:09:28 2017 +0000 +++ b/make/data/tzdata/australasia Mon Jan 23 16:30:43 2017 +0000 @@ -373,7 +373,13 @@ # commencing at 2.00 am on Sunday 1st November, 2015 and ending at # 3.00 am on Sunday 17th January, 2016. -# From Paul Eggert (2015-09-01): +# From Raymond Kumar (2016-10-04): +# http://www.fiji.gov.fj/Media-Center/Press-Releases/DAYLIGHT-SAVING-STARTS-ON-6th-NOVEMBER,-2016.aspx +# "Fiji's daylight savings will begin on Sunday, 6 November 2016, when +# clocks go forward an hour at 2am to 3am.... Daylight Saving will +# end at 3.00am on Sunday 15th January 2017." + +# From Paul Eggert (2016-10-03): # For now, guess DST from 02:00 the first Sunday in November to # 03:00 the third Sunday in January. Although ad hoc, it matches # transitions since late 2014 and seems more likely to match future @@ -568,7 +574,7 @@ # Base the Bougainville entry on the Arawa-Kieta region, which appears to have # the most people even though it was devastated in the Bougainville Civil War. # -# Although Shanks gives 1942-03-15 / 1943-11-01 for JST, these dates +# Although Shanks gives 1942-03-15 / 1943-11-01 for UT +09, these dates # are apparently rough guesswork from the starts of military campaigns. # The World War II entries below are instead based on Arawa-Kieta. # The Japanese occupied Kieta in July 1942, @@ -576,8 +582,8 @@ # http://pwencycl.kgbudge.com/B/o/Bougainville.htm # and seem to have controlled it until their 1945-08-21 surrender. # -# The Autonomous Region of Bougainville plans to switch from UTC+10 to UTC+11 -# on 2014-12-28 at 02:00. They call UTC+11 "Bougainville Standard Time"; +# The Autonomous Region of Bougainville switched from UT +10 to +11 +# on 2014-12-28 at 02:00. They call +11 "Bougainville Standard Time"; # abbreviate this as BST. See: # http://www.bougainville24.com/bougainville-issues/bougainville-gets-own-timezone/ # @@ -643,7 +649,7 @@ # From Paul Eggert (2014-06-27): # The International Date Line Act 2011 # http://www.parliament.gov.ws/images/ACTS/International_Date_Line_Act__2011_-_Eng.pdf -# changed Samoa from UTC-11 to UTC+13, effective "12 o'clock midnight, on +# changed Samoa from UT -11 to +13, effective "12 o'clock midnight, on # Thursday 29th December 2011". The International Date Line was adjusted # accordingly. @@ -719,11 +725,13 @@ Rule Tonga 2000 only - Mar 19 2:00s 0 - Rule Tonga 2000 2001 - Nov Sun>=1 2:00 1:00 S Rule Tonga 2001 2002 - Jan lastSun 2:00 0 - +Rule Tonga 2016 max - Nov Sun>=1 2:00 1:00 S +Rule Tonga 2017 max - Jan Sun>=15 3:00 0 - # Zone NAME GMTOFF RULES FORMAT [UNTIL] Zone Pacific/Tongatapu 12:19:20 - LMT 1901 - 12:20 - TOT 1941 # Tonga Time - 13:00 - TOT 1999 - 13:00 Tonga TO%sT + 12:20 - +1220 1941 + 13:00 - +13 1999 + 13:00 Tonga +13/+14 # Tuvalu # Zone NAME GMTOFF RULES FORMAT [UNTIL] @@ -738,7 +746,7 @@ # 1886-1891; Baker was similar but exact dates are not known. # Inhabited by civilians 1935-1942; U.S. military bases 1943-1944; # uninhabited thereafter. -# Howland observed Hawaii Standard Time (UT-10:30) in 1937; +# Howland observed Hawaii Standard Time (UT -10:30) in 1937; # see page 206 of Elgen M. Long and Marie K. Long, # Amelia Earhart: the Mystery Solved, Simon & Schuster (2000). # So most likely Howland and Baker observed Hawaii Time from 1935 @@ -1496,7 +1504,7 @@ # Zealand time. I understand that is the time they keep locally, anyhow." # For now, assume this practice goes back to the introduction of standard time # in New Zealand, as this would make Chatham Islands time almost exactly match -# LMT back when New Zealand was at UTC+11:30; also, assume Chatham Islands did +# LMT back when New Zealand was at UT +11:30; also, assume Chatham Islands did # not observe New Zealand's prewar DST. ############################################################################### @@ -1552,7 +1560,7 @@ # For now, we assume the Ladrones switched at the same time as the Philippines; # see Asia/Manila. -# US Public Law 106-564 (2000-12-23) made UTC+10 the official standard time, +# US Public Law 106-564 (2000-12-23) made UT +10 the official standard time, # under the name "Chamorro Standard Time". There is no official abbreviation, # but Congressman Robert A. Underwood, author of the bill that became law, # wrote in a press release (2000-12-27) that he will seek the use of "ChST". @@ -1564,15 +1572,15 @@ # "I am certain, having lived there for the past decade, that 'Truk' # (now properly known as Chuuk) ... is in the time zone GMT+10." # -# Shanks & Pottenger write that Truk switched from UTC+10 to UTC+11 +# Shanks & Pottenger write that Truk switched from UT +10 to +11 # on 1978-10-01; ignore this for now. # From Paul Eggert (1999-10-29): # The Federated States of Micronesia Visitors Board writes in # The Federated States of Micronesia - Visitor Information (1999-01-26) # http://www.fsmgov.org/info/clocks.html -# that Truk and Yap are UTC+10, and Ponape and Kosrae are UTC+11. -# We don't know when Kosrae switched from UTC+12; assume January 1 for now. +# that Truk and Yap are UT +10, and Ponape and Kosrae are +11. +# We don't know when Kosrae switched from +12; assume January 1 for now. # Midway @@ -1638,11 +1646,11 @@ # ordaining - by a masterpiece of diplomatic flattery - that # the Fourth of July should be celebrated twice in that year." -# Although Shanks & Pottenger says they both switched to UTC-11:30 -# in 1911, and to UTC-11 in 1950. many earlier sources give UTC-11 +# Although Shanks & Pottenger says they both switched to UT -11:30 +# in 1911, and to -11 in 1950. many earlier sources give -11 # for American Samoa, e.g., the US National Bureau of Standards # circular "Standard Time Throughout the World", 1932. -# Assume American Samoa switched to UTC-11 in 1911, not 1950, +# Assume American Samoa switched to -11 in 1911, not 1950, # and that after 1950 they agreed until (western) Samoa skipped a # day in 2011. Assume also that the Samoas follow the US and New # Zealand's "ST"/"DT" style of daylight-saving abbreviations. @@ -1729,9 +1737,17 @@ # of January the standard time in the Kingdom shall be moved backward by one # hour to 1:00am. -# From Pulu 'Anau (2002-11-05): +# From Pulu ʻAnau (2002-11-05): # The law was for 3 years, supposedly to get renewed. It wasn't. +# From Pulu ʻAnau (2016-10-27): +# http://mic.gov.to/news-today/press-releases/6375-daylight-saving-set-to-run-from-6-november-2016-to-15-january-2017 +# Cannot find anyone who knows the rules, has seen the duration or has seen +# the cabinet decision, but it appears we are following Fiji's rule set. +# +# From Tim Parenti (2016-10-26): +# Assume Tonga will observe DST from the first Sunday in November at 02:00 +# through the third Sunday in January at 03:00, like Fiji, for now. # Wake
--- a/make/data/tzdata/backward Fri Jan 13 17:09:28 2017 +0000 +++ b/make/data/tzdata/backward Mon Jan 23 16:30:43 2017 +0000 @@ -59,6 +59,7 @@ Link Asia/Urumqi Asia/Kashgar Link Asia/Kathmandu Asia/Katmandu Link Asia/Macau Asia/Macao +Link Asia/Yangon Asia/Rangoon Link Asia/Ho_Chi_Minh Asia/Saigon Link Asia/Jerusalem Asia/Tel_Aviv Link Asia/Thimphu Asia/Thimbu
--- a/make/data/tzdata/etcetera Fri Jan 13 17:09:28 2017 +0000 +++ b/make/data/tzdata/etcetera Mon Jan 23 16:30:43 2017 +0000 @@ -31,6 +31,13 @@ # need now for the entries that are not on UTC are for ships at sea # that cannot use POSIX TZ settings. +# Starting with POSIX 1003.1-2001, the entries below are all +# unnecessary as settings for the TZ environment variable. E.g., +# instead of TZ='Etc/GMT+4' one can use the POSIX setting TZ='<-04>+4'. +# +# Do not use a POSIX TZ setting like TZ='GMT+4', which is four hours +# behind GMT but uses the completely misleading abbreviation "GMT". + Zone Etc/GMT 0 - GMT Zone Etc/UTC 0 - UTC Zone Etc/UCT 0 - UCT @@ -49,23 +56,13 @@ Link Etc/GMT Etc/GMT+0 Link Etc/GMT Etc/GMT0 -# We use POSIX-style signs in the Zone names and the output abbreviations, +# Be consistent with POSIX TZ settings in the Zone names, # even though this is the opposite of what many people expect. # POSIX has positive signs west of Greenwich, but many people expect # positive signs east of Greenwich. For example, TZ='Etc/GMT+4' uses -# the abbreviation "GMT+4" and corresponds to 4 hours behind UT +# the abbreviation "-04" and corresponds to 4 hours behind UT # (i.e. west of Greenwich) even though many people would expect it to # mean 4 hours ahead of UT (i.e. east of Greenwich). -# -# In the draft 5 of POSIX 1003.1-200x, the angle bracket notation allows for -# TZ='<GMT-4>+4'; if you want time zone abbreviations conforming to -# ISO 8601 you can use TZ='<-0400>+4'. Thus the commonly-expected -# offset is kept within the angle bracket (and is used for display) -# while the POSIX sign is kept outside the angle bracket (and is used -# for calculation). -# -# Do not use a TZ setting like TZ='GMT+4', which is four hours behind -# GMT but uses the completely misleading abbreviation "GMT". # Earlier incarnations of this package were not POSIX-compliant, # and had lines such as @@ -74,30 +71,31 @@ # way does a # zic -l GMT-12 # so we moved the names into the Etc subdirectory. +# Also, the time zone abbreviations are now compatible with %z. -Zone Etc/GMT-14 14 - GMT-14 # 14 hours ahead of GMT -Zone Etc/GMT-13 13 - GMT-13 -Zone Etc/GMT-12 12 - GMT-12 -Zone Etc/GMT-11 11 - GMT-11 -Zone Etc/GMT-10 10 - GMT-10 -Zone Etc/GMT-9 9 - GMT-9 -Zone Etc/GMT-8 8 - GMT-8 -Zone Etc/GMT-7 7 - GMT-7 -Zone Etc/GMT-6 6 - GMT-6 -Zone Etc/GMT-5 5 - GMT-5 -Zone Etc/GMT-4 4 - GMT-4 -Zone Etc/GMT-3 3 - GMT-3 -Zone Etc/GMT-2 2 - GMT-2 -Zone Etc/GMT-1 1 - GMT-1 -Zone Etc/GMT+1 -1 - GMT+1 -Zone Etc/GMT+2 -2 - GMT+2 -Zone Etc/GMT+3 -3 - GMT+3 -Zone Etc/GMT+4 -4 - GMT+4 -Zone Etc/GMT+5 -5 - GMT+5 -Zone Etc/GMT+6 -6 - GMT+6 -Zone Etc/GMT+7 -7 - GMT+7 -Zone Etc/GMT+8 -8 - GMT+8 -Zone Etc/GMT+9 -9 - GMT+9 -Zone Etc/GMT+10 -10 - GMT+10 -Zone Etc/GMT+11 -11 - GMT+11 -Zone Etc/GMT+12 -12 - GMT+12 +Zone Etc/GMT-14 14 - +14 +Zone Etc/GMT-13 13 - +13 +Zone Etc/GMT-12 12 - +12 +Zone Etc/GMT-11 11 - +11 +Zone Etc/GMT-10 10 - +10 +Zone Etc/GMT-9 9 - +09 +Zone Etc/GMT-8 8 - +08 +Zone Etc/GMT-7 7 - +07 +Zone Etc/GMT-6 6 - +06 +Zone Etc/GMT-5 5 - +05 +Zone Etc/GMT-4 4 - +04 +Zone Etc/GMT-3 3 - +03 +Zone Etc/GMT-2 2 - +02 +Zone Etc/GMT-1 1 - +01 +Zone Etc/GMT+1 -1 - -01 +Zone Etc/GMT+2 -2 - -02 +Zone Etc/GMT+3 -3 - -03 +Zone Etc/GMT+4 -4 - -04 +Zone Etc/GMT+5 -5 - -05 +Zone Etc/GMT+6 -6 - -06 +Zone Etc/GMT+7 -7 - -07 +Zone Etc/GMT+8 -8 - -08 +Zone Etc/GMT+9 -9 - -09 +Zone Etc/GMT+10 -10 - -10 +Zone Etc/GMT+11 -11 - -11 +Zone Etc/GMT+12 -12 - -12
--- a/make/data/tzdata/europe Fri Jan 13 17:09:28 2017 +0000 +++ b/make/data/tzdata/europe Mon Jan 23 16:30:43 2017 +0000 @@ -98,8 +98,7 @@ # 1:00 CET CEST CEMT Central Europe # 1:00:14 SET Swedish (1879-1899)* # 2:00 EET EEST Eastern Europe -# 3:00 FET Further-eastern Europe (2011-2014)* -# 3:00 MSK MSD MSM* Minsk, Moscow +# 3:00 MSK MSD Moscow # From Peter Ilieve (1994-12-04), # The original six [EU members]: Belgium, France, (West) Germany, Italy, @@ -606,16 +605,33 @@ Rule E-Eur 1981 max - Mar lastSun 0:00 1:00 S Rule E-Eur 1996 max - Oct lastSun 0:00 0 - + +# Daylight saving time for Russia and the Soviet Union +# +# The 1917-1921 decree URLs are from Alexander Belopolsky (2016-08-23). + # Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S Rule Russia 1917 only - Jul 1 23:00 1:00 MST # Moscow Summer Time +# +# Decree No. 142 (1917-12-22) http://istmat.info/node/28137 Rule Russia 1917 only - Dec 28 0:00 0 MMT # Moscow Mean Time +# +# Decree No. 497 (1918-05-30) http://istmat.info/node/30001 Rule Russia 1918 only - May 31 22:00 2:00 MDST # Moscow Double Summer Time Rule Russia 1918 only - Sep 16 1:00 1:00 MST +# +# Decree No. 258 (1919-05-29) http://istmat.info/node/37949 Rule Russia 1919 only - May 31 23:00 2:00 MDST -Rule Russia 1919 only - Jul 1 2:00 1:00 MSD +# +Rule Russia 1919 only - Jul 1 0:00u 1:00 MSD Rule Russia 1919 only - Aug 16 0:00 0 MSK +# +# Decree No. 63 (1921-02-03) http://istmat.info/node/45840 Rule Russia 1921 only - Feb 14 23:00 1:00 MSD -Rule Russia 1921 only - Mar 20 23:00 2:00 MSM # Midsummer +# +# Decree No. 121 (1921-03-07) http://istmat.info/node/45949 +Rule Russia 1921 only - Mar 20 23:00 2:00 +05 +# Rule Russia 1921 only - Sep 1 0:00 1:00 MSD Rule Russia 1921 only - Oct 1 0:00 0 - # Act No. 925 of the Council of Ministers of the USSR (1980-10-24): @@ -798,8 +814,6 @@ # From Alexander Bokovoy (2014-10-09): # 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 -# From Paul Eggert (2014-10-08): -# Hence Belarus can share time zone abbreviations with Moscow again. # # Zone NAME GMTOFF RULES FORMAT [UNTIL] Zone Europe/Minsk 1:50:16 - LMT 1880 @@ -810,8 +824,7 @@ 3:00 Russia MSK/MSD 1990 3:00 - MSK 1991 Mar 31 2:00s 2:00 Russia EE%sT 2011 Mar 27 2:00s - 3:00 - FET 2014 Oct 26 1:00s - 3:00 - MSK + 3:00 - +03 # Belgium # @@ -1319,7 +1332,7 @@ # http://www.parlament-berlin.de/pds-fraktion.nsf/727459127c8b66ee8525662300459099/defc77cb784f180ac1256c2b0030274b/$FILE/bersarint.pdf # says that Bersarin issued an order to use Moscow time on May 20. # However, Moscow did not observe daylight saving in 1945, so -# this was equivalent to CEMT (GMT+3), not GMT+4. +# this was equivalent to UT +03, not +04. # Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S @@ -1510,73 +1523,84 @@ # But these events all occurred before the 1970 cutoff, # so record only the time in Rome. # -# From Paul Eggert (2006-03-22): -# For Italian DST we have three sources: Shanks & Pottenger, Whitman, and -# F. Pollastri -# Day-light Saving Time in Italy (2006-02-03) -# http://toi.iriti.cnr.it/uk/ienitlt.html -# ('FP' below), taken from an Italian National Electrotechnical Institute -# publication. When the three sources disagree, guess who's right, as follows: +# 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 +# force at the instant at which, according to the time specified in +# the 1st article, the 1st of November 1893 will begin...." # -# year FP Shanks&P. (S) Whitman (W) Go with: -# 1916 06-03 06-03 24:00 06-03 00:00 FP & W -# 09-30 09-30 24:00 09-30 01:00 FP; guess 24:00s -# 1917 04-01 03-31 24:00 03-31 00:00 FP & S -# 09-30 09-29 24:00 09-30 01:00 FP & W -# 1918 03-09 03-09 24:00 03-09 00:00 FP & S -# 10-06 10-05 24:00 10-06 01:00 FP & W -# 1919 03-01 03-01 24:00 03-01 00:00 FP & S -# 10-04 10-04 24:00 10-04 01:00 FP; guess 24:00s -# 1920 03-20 03-20 24:00 03-20 00:00 FP & S -# 09-18 09-18 24:00 10-01 01:00 FP; guess 24:00s -# 1944 04-02 04-03 02:00 S (see C-Eur) -# 09-16 10-02 03:00 FP; guess 24:00s -# 1945 09-14 09-16 24:00 FP; guess 24:00s -# 1970 05-21 05-31 00:00 S -# 09-20 09-27 00:00 S +# From Pierpaolo Bernardi (2016-10-20): +# 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 +# (2016-10-24): +# http://www.renzobaldini.it/le-ore-legali-in-italia/ +# has still different data for 1944. It divides Italy in two, as +# there were effectively two governments at the time, north of Gothic +# Line German controlled territory, official government RSI, and south +# of the Gothic Line, controlled by allied armies. +# +# From Brian Inglis (2016-10-23): +# Viceregal LEGISLATIVE DECREE. 14 September 1944, no. 219. +# Restoration of Standard Time. (044U0219) (OJ 62 of 30.9.1944) ... +# Given the R. law decreed on 1944-03-29, no. 92, by which standard time is +# 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 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. +# Model Rome's occupation by using using C-Eur rules from 1943-09-10 +# to 1944-06-04; although Rome was an open city during this period, it +# was effectively controlled by Germany. # # Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S -Rule Italy 1916 only - Jun 3 0:00s 1:00 S -Rule Italy 1916 only - Oct 1 0:00s 0 - -Rule Italy 1917 only - Apr 1 0:00s 1:00 S -Rule Italy 1917 only - Sep 30 0:00s 0 - -Rule Italy 1918 only - Mar 10 0:00s 1:00 S -Rule Italy 1918 1919 - Oct Sun>=1 0:00s 0 - -Rule Italy 1919 only - Mar 2 0:00s 1:00 S -Rule Italy 1920 only - Mar 21 0:00s 1:00 S -Rule Italy 1920 only - Sep 19 0:00s 0 - -Rule Italy 1940 only - Jun 15 0:00s 1:00 S -Rule Italy 1944 only - Sep 17 0:00s 0 - -Rule Italy 1945 only - Apr 2 2:00 1:00 S -Rule Italy 1945 only - Sep 15 0:00s 0 - -Rule Italy 1946 only - Mar 17 2:00s 1:00 S -Rule Italy 1946 only - Oct 6 2:00s 0 - -Rule Italy 1947 only - Mar 16 0:00s 1:00 S -Rule Italy 1947 only - Oct 5 0:00s 0 - -Rule Italy 1948 only - Feb 29 2:00s 1:00 S -Rule Italy 1948 only - Oct 3 2:00s 0 - -Rule Italy 1966 1968 - May Sun>=22 0:00 1:00 S -Rule Italy 1966 1969 - Sep Sun>=22 0:00 0 - -Rule Italy 1969 only - Jun 1 0:00 1:00 S -Rule Italy 1970 only - May 31 0:00 1:00 S -Rule Italy 1970 only - Sep lastSun 0:00 0 - -Rule Italy 1971 1972 - May Sun>=22 0:00 1:00 S -Rule Italy 1971 only - Sep lastSun 1:00 0 - -Rule Italy 1972 only - Oct 1 0:00 0 - -Rule Italy 1973 only - Jun 3 0:00 1:00 S -Rule Italy 1973 1974 - Sep lastSun 0:00 0 - -Rule Italy 1974 only - May 26 0:00 1:00 S -Rule Italy 1975 only - Jun 1 0:00s 1:00 S -Rule Italy 1975 1977 - Sep lastSun 0:00s 0 - -Rule Italy 1976 only - May 30 0:00s 1:00 S -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 - +Rule Italy 1916 only - Jun 3 24:00 1:00 S +Rule Italy 1916 1917 - Sep 30 24:00 0 - +Rule Italy 1917 only - Mar 31 24:00 1:00 S +Rule Italy 1918 only - Mar 9 24:00 1:00 S +Rule Italy 1918 only - Oct 6 24:00 0 - +Rule Italy 1919 only - Mar 1 24:00 1:00 S +Rule Italy 1919 only - Oct 4 24:00 0 - +Rule Italy 1920 only - Mar 20 24:00 1:00 S +Rule Italy 1920 only - Sep 18 24:00 0 - +Rule Italy 1940 only - Jun 14 24:00 1:00 S +Rule Italy 1942 only - Nov 2 2:00s 0 - +Rule Italy 1943 only - Mar 29 2:00s 1:00 S +Rule Italy 1943 only - Oct 4 2:00s 0 - +Rule Italy 1944 only - Apr 2 2:00s 1:00 S +Rule Italy 1944 only - Sep 17 2:00s 0 - +Rule Italy 1945 only - Apr 2 2:00 1:00 S +Rule Italy 1945 only - Sep 15 1:00 0 - +Rule Italy 1946 only - Mar 17 2:00s 1:00 S +Rule Italy 1946 only - Oct 6 2:00s 0 - +Rule Italy 1947 only - Mar 16 0:00s 1:00 S +Rule Italy 1947 only - Oct 5 0:00s 0 - +Rule Italy 1948 only - Feb 29 2:00s 1:00 S +Rule Italy 1948 only - Oct 3 2:00s 0 - +Rule Italy 1966 1968 - May Sun>=22 0:00s 1:00 S +Rule Italy 1966 only - Sep 24 24:00 0 - +Rule Italy 1967 1969 - Sep Sun>=22 0:00s 0 - +Rule Italy 1969 only - Jun 1 0:00s 1:00 S +Rule Italy 1970 only - May 31 0:00s 1:00 S +Rule Italy 1970 only - Sep lastSun 0:00s 0 - +Rule Italy 1971 1972 - May Sun>=22 0:00s 1:00 S +Rule Italy 1971 only - Sep lastSun 0:00s 0 - +Rule Italy 1972 only - Oct 1 0:00s 0 - +Rule Italy 1973 only - Jun 3 0:00s 1:00 S +Rule Italy 1973 1974 - Sep lastSun 0:00s 0 - +Rule Italy 1974 only - May 26 0:00s 1:00 S +Rule Italy 1975 only - Jun 1 0:00s 1:00 S +Rule Italy 1975 1977 - Sep lastSun 0:00s 0 - +Rule Italy 1976 only - May 30 0:00s 1:00 S +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 - 0:49:56 - RMT 1893 Nov 1 0:00s # Rome Mean - 1:00 Italy CE%sT 1942 Nov 2 2:00s - 1:00 C-Eur CE%sT 1944 Jul + 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 1:00 Italy CE%sT 1980 1:00 EU CE%sT @@ -1775,6 +1799,10 @@ # See Europe/Belgrade. # Malta +# +# From Paul Eggert (2016-10-21): +# Assume 1900-1972 was like Rome, overriding Shanks. +# # Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S Rule Malta 1973 only - Mar 31 0:00s 1:00 S Rule Malta 1973 only - Sep 29 0:00s 0 - @@ -1785,8 +1813,6 @@ Rule Malta 1980 only - Mar 31 2:00 1:00 S # Zone NAME GMTOFF RULES FORMAT [UNTIL] Zone Europe/Malta 0:58:04 - LMT 1893 Nov 2 0:00s # Valletta - 1:00 Italy CE%sT 1942 Nov 2 2:00s - 1:00 C-Eur CE%sT 1945 Apr 2 2:00s 1:00 Italy CE%sT 1973 Mar 31 1:00 Malta CE%sT 1981 1:00 EU CE%sT @@ -1918,7 +1944,7 @@ # Amsterdam mean time. # The data entries before 1945 are taken from -# http://www.phys.uu.nl/~vgent/wettijd/wettijd.htm +# http://www.staff.science.uu.nl/~gent0113/wettijd/wettijd.htm # Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S Rule Neth 1916 only - May 1 0:00 1:00 NST # Netherlands Summer Time @@ -2283,7 +2309,6 @@ # http://www.worldtimezone.com/dst_news/dst_news_russia-map-2014-07.html # From Paul Eggert (2006-03-22): -# Except for Moscow after 1919-07-01, I invented the time zone abbreviations. # Moscow time zone abbreviations after 1919-07-01, and Moscow rules after 1991, # are from Andrey A. Chernov. The rest is from Shanks & Pottenger, # except we follow Chernov's report that 1992 DST transitions were Sat @@ -2359,7 +2384,7 @@ 2:00 Poland CE%sT 1946 3:00 Russia MSK/MSD 1989 Mar 26 2:00s 2:00 Russia EE%sT 2011 Mar 27 2:00s - 3:00 - FET 2014 Oct 26 2:00s + 3:00 - +03 2014 Oct 26 2:00s 2:00 - EET @@ -2412,6 +2437,16 @@ # 78 RU-SPE Saint Petersburg # 83 RU-NEN Nenets Autonomous Okrug +# From Paul Eggert (2016-08-23): +# The Soviets switched to UT-based time in 1919. Decree No. 59 +# (1919-02-08) http://istmat.info/node/35567 established UT-based time +# zones, and Decree No. 147 (1919-03-29) http://istmat.info/node/35854 +# specified a transition date of 1919-07-01, apparently at 00:00 UT. +# No doubt only the Soviet-controlled regions switched on that date; +# later transitions to UT-based time in other parts of Russia are +# taken from what appear to be guesses by Shanks. +# (Thanks to Alexander Belopolsky for pointers to the decrees.) + # From Stepan Golosunov (2016-03-07): # 11. Regions-violators, 1981-1982. # Wikipedia refers to @@ -2453,7 +2488,7 @@ # attributes the 1982 changes to the Act of the Council of Ministers # of the USSR No. 126 from 18.02.1982. 1980-925.txt also adds # Udmurtia to the list of affected territories and lists Khatangsky -# district separately from Taymyr Autonomous Okurg. Probably erroneously. +# district separately from Taymyr Autonomous Okrug. Probably erroneously. # # The affected territories are currently listed under Europe/Moscow, # Asia/Yekaterinburg and Asia/Krasnoyarsk. @@ -2513,7 +2548,7 @@ Zone Europe/Moscow 2:30:17 - LMT 1880 2:30:17 - MMT 1916 Jul 3 # Moscow Mean Time - 2:31:19 Russia %s 1919 Jul 1 2:00 + 2:31:19 Russia %s 1919 Jul 1 0:00u 3:00 Russia %s 1921 Oct 3:00 Russia MSK/MSD 1922 Oct 2:00 - EET 1930 Jun 21 @@ -2596,22 +2631,21 @@ # The 1988 transition is from USSR act No. 5 (1988-01-04). Zone Europe/Volgograd 2:57:40 - LMT 1920 Jan 3 - 3:00 - TSAT 1925 Apr 6 # Tsaritsyn Time - 3:00 - STAT 1930 Jun 21 # Stalingrad Time - 4:00 - STAT 1961 Nov 11 - 4:00 Russia VOL%sT 1988 Mar 27 2:00s # Volgograd T - 3:00 Russia VOL%sT 1991 Mar 31 2:00s - 4:00 - VOLT 1992 Mar 29 2:00s - 3:00 Russia MSK/MSD 2011 Mar 27 2:00s - 4:00 - MSK 2014 Oct 26 2:00s - 3:00 - MSK + 3:00 - +03 1930 Jun 21 + 4:00 - +04 1961 Nov 11 + 4:00 Russia +04/+05 1988 Mar 27 2:00s + 3:00 Russia +03/+04 1991 Mar 31 2:00s + 4:00 - +04 1992 Mar 29 2:00s + 3:00 Russia +03/+04 2011 Mar 27 2:00s + 4:00 - +04 2014 Oct 26 2:00s + 3:00 - +03 # From Paul Eggert (2016-03-18): # Europe/Kirov covers: # 43 RU-KIR Kirov Oblast # The 1989 transition is from USSR act No. 227 (1989-03-14). # -Zone Europe/Kirov 3:18:48 - LMT 1919 Jul 1 2:00 +Zone Europe/Kirov 3:18:48 - LMT 1919 Jul 1 0:00u 3:00 - +03 1930 Jun 21 4:00 Russia +04/+05 1989 Mar 26 2:00s 3:00 Russia +03/+04 1991 Mar 31 2:00s @@ -2629,16 +2663,16 @@ # Byalokoz 1919 says Samara was 3:20:20. # The 1989 transition is from USSR act No. 227 (1989-03-14). -Zone Europe/Samara 3:20:20 - LMT 1919 Jul 1 2:00 - 3:00 - SAMT 1930 Jun 21 # Samara Time - 4:00 - SAMT 1935 Jan 27 - 4:00 Russia KUY%sT 1989 Mar 26 2:00s # Kuybyshev - 3:00 Russia MSK/MSD 1991 Mar 31 2:00s - 2:00 Russia EE%sT 1991 Sep 29 2:00s - 3:00 - SAMT 1991 Oct 20 3:00 - 4:00 Russia SAM%sT 2010 Mar 28 2:00s - 3:00 Russia SAM%sT 2011 Mar 27 2:00s - 4:00 - SAMT +Zone Europe/Samara 3:20:20 - LMT 1919 Jul 1 0:00u + 3:00 - +03 1930 Jun 21 + 4:00 - +04 1935 Jan 27 + 4:00 Russia +04/+05 1989 Mar 26 2:00s + 3:00 Russia +03/+04 1991 Mar 31 2:00s + 2:00 Russia +02/+03 1991 Sep 29 2:00s + 3:00 - +03 1991 Oct 20 3:00 + 4:00 Russia +04/+05 2010 Mar 28 2:00s + 3:00 Russia +03/+04 2011 Mar 27 2:00s + 4:00 - +04 # From Paul Eggert (2016-03-18): # Europe/Ulyanovsk covers: @@ -2653,7 +2687,7 @@ # From Matt Johnson (2016-03-09): # http://publication.pravo.gov.ru/Document/View/0001201603090051 -Zone Europe/Ulyanovsk 3:13:36 - LMT 1919 Jul 1 2:00 +Zone Europe/Ulyanovsk 3:13:36 - LMT 1919 Jul 1 0:00u 3:00 - +03 1930 Jun 21 4:00 Russia +04/+05 1989 Mar 26 2:00s 3:00 Russia +03/+04 1991 Mar 31 2:00s @@ -2685,12 +2719,12 @@ Zone Asia/Yekaterinburg 4:02:33 - LMT 1916 Jul 3 3:45:05 - PMT 1919 Jul 15 4:00 - 4:00 - SVET 1930 Jun 21 # Sverdlovsk Time - 5:00 Russia SVE%sT 1991 Mar 31 2:00s - 4:00 Russia SVE%sT 1992 Jan 19 2:00s - 5:00 Russia YEK%sT 2011 Mar 27 2:00s - 6:00 - YEKT 2014 Oct 26 2:00s - 5:00 - YEKT + 4:00 - +04 1930 Jun 21 + 5:00 Russia +05/+06 1991 Mar 31 2:00s + 4:00 Russia +04/+05 1992 Jan 19 2:00s + 5:00 Russia +05/+06 2011 Mar 27 2:00s + 6:00 - +06 2014 Oct 26 2:00s + 5:00 - +05 # From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2001-08-25): @@ -2700,12 +2734,12 @@ # Byalokoz 1919 says Omsk was 4:53:30. Zone Asia/Omsk 4:53:30 - LMT 1919 Nov 14 - 5:00 - OMST 1930 Jun 21 # Omsk Time - 6:00 Russia OMS%sT 1991 Mar 31 2:00s - 5:00 Russia OMS%sT 1992 Jan 19 2:00s - 6:00 Russia OMS%sT 2011 Mar 27 2:00s - 7:00 - OMST 2014 Oct 26 2:00s - 6:00 - OMST + 5:00 - +05 1930 Jun 21 + 6:00 Russia +06/+07 1991 Mar 31 2:00s + 5:00 Russia +05/+06 1992 Jan 19 2:00s + 6:00 Russia +06/+07 2011 Mar 27 2:00s + 7:00 - +07 2014 Oct 26 2:00s + 6:00 - +06 # From Paul Eggert (2016-02-22): # Asia/Barnaul covers: @@ -2785,7 +2819,7 @@ # Note that time belts (numbered from 2 (Moscow) to 12 according to their # GMT/UTC offset and having too many exceptions like regions formally # belonging to one belt but using time from another) were replaced -# with time zones in 2011 with different numberings (there was a +# with time zones in 2011 with different numbering (there was a # 2-hour gap between second and third zones in 2011-2014). # From Stepan Golosunov (2016-04-12): @@ -2868,12 +2902,12 @@ # Byalokoz 1919 says Krasnoyarsk was 6:11:26. Zone Asia/Krasnoyarsk 6:11:26 - LMT 1920 Jan 6 - 6:00 - KRAT 1930 Jun 21 # Krasnoyarsk Time - 7:00 Russia KRA%sT 1991 Mar 31 2:00s - 6:00 Russia KRA%sT 1992 Jan 19 2:00s - 7:00 Russia KRA%sT 2011 Mar 27 2:00s - 8:00 - KRAT 2014 Oct 26 2:00s - 7:00 - KRAT + 6:00 - +06 1930 Jun 21 + 7:00 Russia +07/+08 1991 Mar 31 2:00s + 6:00 Russia +06/+07 1992 Jan 19 2:00s + 7:00 Russia +07/+08 2011 Mar 27 2:00s + 8:00 - +08 2014 Oct 26 2:00s + 7:00 - +07 # From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2001-08-25): @@ -2890,12 +2924,12 @@ Zone Asia/Irkutsk 6:57:05 - LMT 1880 6:57:05 - IMT 1920 Jan 25 # Irkutsk Mean Time - 7:00 - IRKT 1930 Jun 21 # Irkutsk Time - 8:00 Russia IRK%sT 1991 Mar 31 2:00s - 7:00 Russia IRK%sT 1992 Jan 19 2:00s - 8:00 Russia IRK%sT 2011 Mar 27 2:00s - 9:00 - IRKT 2014 Oct 26 2:00s - 8:00 - IRKT + 7:00 - +07 1930 Jun 21 + 8:00 Russia +08/+09 1991 Mar 31 2:00s + 7:00 Russia +07/+08 1992 Jan 19 2:00s + 8:00 Russia +08/+09 2011 Mar 27 2:00s + 9:00 - +09 2014 Oct 26 2:00s + 8:00 - +08 # From Tim Parenti (2014-07-06): @@ -2912,13 +2946,13 @@ # http://publication.pravo.gov.ru/Document/View/0001201512300107 Zone Asia/Chita 7:33:52 - LMT 1919 Dec 15 - 8:00 - YAKT 1930 Jun 21 # Yakutsk Time - 9:00 Russia YAK%sT 1991 Mar 31 2:00s - 8:00 Russia YAK%sT 1992 Jan 19 2:00s - 9:00 Russia YAK%sT 2011 Mar 27 2:00s - 10:00 - YAKT 2014 Oct 26 2:00s - 8:00 - IRKT 2016 Mar 27 2:00 - 9:00 - YAKT + 8:00 - +08 1930 Jun 21 + 9:00 Russia +09/+10 1991 Mar 31 2:00s + 8:00 Russia +08/+09 1992 Jan 19 2:00s + 9:00 Russia +09/+10 2011 Mar 27 2:00s + 10:00 - +10 2014 Oct 26 2:00s + 8:00 - +08 2016 Mar 27 2:00 + 9:00 - +09 # From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2009-11-29): @@ -2958,12 +2992,12 @@ # Byalokoz 1919 says Yakutsk was 8:38:58. Zone Asia/Yakutsk 8:38:58 - LMT 1919 Dec 15 - 8:00 - YAKT 1930 Jun 21 # Yakutsk Time - 9:00 Russia YAK%sT 1991 Mar 31 2:00s - 8:00 Russia YAK%sT 1992 Jan 19 2:00s - 9:00 Russia YAK%sT 2011 Mar 27 2:00s - 10:00 - YAKT 2014 Oct 26 2:00s - 9:00 - YAKT + 8:00 - +08 1930 Jun 21 + 9:00 Russia +09/+10 1991 Mar 31 2:00s + 8:00 Russia +08/+09 1992 Jan 19 2:00s + 9:00 Russia +09/+10 2011 Mar 27 2:00s + 10:00 - +10 2014 Oct 26 2:00s + 9:00 - +09 # From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2009-11-29): @@ -2981,12 +3015,12 @@ # Go with Byalokoz. Zone Asia/Vladivostok 8:47:31 - LMT 1922 Nov 15 - 9:00 - VLAT 1930 Jun 21 # Vladivostok Time - 10:00 Russia VLA%sT 1991 Mar 31 2:00s - 9:00 Russia VLA%sT 1992 Jan 19 2:00s - 10:00 Russia VLA%sT 2011 Mar 27 2:00s - 11:00 - VLAT 2014 Oct 26 2:00s - 10:00 - VLAT + 9:00 - +09 1930 Jun 21 + 10:00 Russia +10/+11 1991 Mar 31 2:00s + 9:00 Russia +09/+10 1992 Jan 19 2:00s + 10:00 Russia +10/+11 2011 Mar 27 2:00s + 11:00 - +11 2014 Oct 26 2:00s + 10:00 - +10 # From Tim Parenti (2014-07-03): @@ -3004,14 +3038,14 @@ # This transition is no doubt wrong, but we have no better info. Zone Asia/Khandyga 9:02:13 - LMT 1919 Dec 15 - 8:00 - YAKT 1930 Jun 21 # Yakutsk Time - 9:00 Russia YAK%sT 1991 Mar 31 2:00s - 8:00 Russia YAK%sT 1992 Jan 19 2:00s - 9:00 Russia YAK%sT 2004 - 10:00 Russia VLA%sT 2011 Mar 27 2:00s - 11:00 - VLAT 2011 Sep 13 0:00s # Decree 725? - 10:00 - YAKT 2014 Oct 26 2:00s - 9:00 - YAKT + 8:00 - +08 1930 Jun 21 + 9:00 Russia +09/+10 1991 Mar 31 2:00s + 8:00 Russia +08/+09 1992 Jan 19 2:00s + 9:00 Russia +09/+10 2004 + 10:00 Russia +10/+11 2011 Mar 27 2:00s + 11:00 - +11 2011 Sep 13 0:00s # Decree 725? + 10:00 - +10 2014 Oct 26 2:00s + 9:00 - +09 # From Tim Parenti (2014-07-03): @@ -3027,15 +3061,14 @@ # The Zone name should be Asia/Yuzhno-Sakhalinsk, but that's too long. Zone Asia/Sakhalin 9:30:48 - LMT 1905 Aug 23 - 9:00 - JCST 1937 Oct 1 - 9:00 - JST 1945 Aug 25 - 11:00 Russia SAK%sT 1991 Mar 31 2:00s # Sakhalin T - 10:00 Russia SAK%sT 1992 Jan 19 2:00s - 11:00 Russia SAK%sT 1997 Mar lastSun 2:00s - 10:00 Russia SAK%sT 2011 Mar 27 2:00s - 11:00 - SAKT 2014 Oct 26 2:00s - 10:00 - SAKT 2016 Mar 27 2:00s - 11:00 - SAKT + 9:00 - +09 1945 Aug 25 + 11:00 Russia +11/+12 1991 Mar 31 2:00s # Sakhalin T + 10:00 Russia +10/+11 1992 Jan 19 2:00s + 11:00 Russia +11/+12 1997 Mar lastSun 2:00s + 10:00 Russia +10/+11 2011 Mar 27 2:00s + 11:00 - +11 2014 Oct 26 2:00s + 10:00 - +10 2016 Mar 27 2:00s + 11:00 - +11 # From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2009-11-29): @@ -3058,13 +3091,13 @@ # http://publication.pravo.gov.ru/Document/View/0001201604050038 Zone Asia/Magadan 10:03:12 - LMT 1924 May 2 - 10:00 - MAGT 1930 Jun 21 # Magadan Time - 11:00 Russia MAG%sT 1991 Mar 31 2:00s - 10:00 Russia MAG%sT 1992 Jan 19 2:00s - 11:00 Russia MAG%sT 2011 Mar 27 2:00s - 12:00 - MAGT 2014 Oct 26 2:00s - 10:00 - MAGT 2016 Apr 24 2:00s - 11:00 - MAGT + 10:00 - +10 1930 Jun 21 # Magadan Time + 11:00 Russia +11/+12 1991 Mar 31 2:00s + 10:00 Russia +10/+11 1992 Jan 19 2:00s + 11:00 Russia +11/+12 2011 Mar 27 2:00s + 12:00 - +12 2014 Oct 26 2:00s + 10:00 - +10 2016 Apr 24 2:00s + 11:00 - +11 # From Tim Parenti (2014-07-06): @@ -3107,17 +3140,14 @@ # in Russian.) In addition, Srednekolymsk appears to be a much older # settlement and the population of Zyryanka seems to be declining. # Go with Srednekolymsk. -# -# Since Magadan Oblast moves to UTC+10 on 2014-10-26, we cannot keep using MAGT -# as the abbreviation. Use SRET instead. Zone Asia/Srednekolymsk 10:14:52 - LMT 1924 May 2 - 10:00 - MAGT 1930 Jun 21 # Magadan Time - 11:00 Russia MAG%sT 1991 Mar 31 2:00s - 10:00 Russia MAG%sT 1992 Jan 19 2:00s - 11:00 Russia MAG%sT 2011 Mar 27 2:00s - 12:00 - MAGT 2014 Oct 26 2:00s - 11:00 - SRET # Srednekolymsk Time + 10:00 - +10 1930 Jun 21 + 11:00 Russia +11/+12 1991 Mar 31 2:00s + 10:00 Russia +10/+11 1992 Jan 19 2:00s + 11:00 Russia +11/+12 2011 Mar 27 2:00s + 12:00 - +12 2014 Oct 26 2:00s + 11:00 - +11 # From Tim Parenti (2014-07-03): @@ -3135,14 +3165,14 @@ # UTC+12 since at least then, too. Zone Asia/Ust-Nera 9:32:54 - LMT 1919 Dec 15 - 8:00 - YAKT 1930 Jun 21 # Yakutsk Time - 9:00 Russia YAKT 1981 Apr 1 - 11:00 Russia MAG%sT 1991 Mar 31 2:00s - 10:00 Russia MAG%sT 1992 Jan 19 2:00s - 11:00 Russia MAG%sT 2011 Mar 27 2:00s - 12:00 - MAGT 2011 Sep 13 0:00s # Decree 725? - 11:00 - VLAT 2014 Oct 26 2:00s - 10:00 - VLAT + 8:00 - +08 1930 Jun 21 + 9:00 Russia +09/+10 1981 Apr 1 + 11:00 Russia +11/+12 1991 Mar 31 2:00s + 10:00 Russia +10/+11 1992 Jan 19 2:00s + 11:00 Russia +11/+12 2011 Mar 27 2:00s + 12:00 - +12 2011 Sep 13 0:00s # Decree 725? + 11:00 - +11 2014 Oct 26 2:00s + 10:00 - +10 # From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2001-08-25): @@ -3155,12 +3185,12 @@ # The Zone name should be Asia/Petropavlovsk-Kamchatski or perhaps # Asia/Petropavlovsk-Kamchatsky, but these are too long. Zone Asia/Kamchatka 10:34:36 - LMT 1922 Nov 10 - 11:00 - PETT 1930 Jun 21 # P-K Time - 12:00 Russia PET%sT 1991 Mar 31 2:00s - 11:00 Russia PET%sT 1992 Jan 19 2:00s - 12:00 Russia PET%sT 2010 Mar 28 2:00s - 11:00 Russia PET%sT 2011 Mar 27 2:00s - 12:00 - PETT + 11:00 - +11 1930 Jun 21 + 12:00 Russia +12/+13 1991 Mar 31 2:00s + 11:00 Russia +11/+12 1992 Jan 19 2:00s + 12:00 Russia +12/+13 2010 Mar 28 2:00s + 11:00 Russia +11/+12 2011 Mar 27 2:00s + 12:00 - +12 # From Tim Parenti (2014-07-03): @@ -3168,13 +3198,13 @@ # 87 RU-CHU Chukotka Autonomous Okrug Zone Asia/Anadyr 11:49:56 - LMT 1924 May 2 - 12:00 - ANAT 1930 Jun 21 # Anadyr Time - 13:00 Russia ANA%sT 1982 Apr 1 0:00s - 12:00 Russia ANA%sT 1991 Mar 31 2:00s - 11:00 Russia ANA%sT 1992 Jan 19 2:00s - 12:00 Russia ANA%sT 2010 Mar 28 2:00s - 11:00 Russia ANA%sT 2011 Mar 27 2:00s - 12:00 - ANAT + 12:00 - +12 1930 Jun 21 + 13:00 Russia +13/+14 1982 Apr 1 0:00s + 12:00 Russia +12/+13 1991 Mar 31 2:00s + 11:00 Russia +11/+12 1992 Jan 19 2:00s + 12:00 Russia +12/+13 2010 Mar 28 2:00s + 11:00 Russia +11/+12 2011 Mar 27 2:00s + 12:00 - +12 # San Marino @@ -3433,22 +3463,24 @@ # Turkey -# From Amar Devegowda (2007-01-03): -# The time zone rules for Istanbul, Turkey have not been changed for years now. -# ... The latest rules are available at: -# http://www.timeanddate.com/worldclock/timezone.html?n=107 -# From Steffen Thorsen (2007-01-03): -# I have been able to find press records back to 1996 which all say that -# DST started 01:00 local time and end at 02:00 local time. I am not sure -# what happened before that. One example for each year from 1996 to 2001: -# http://newspot.byegm.gov.tr/arsiv/1996/21/N4.htm -# http://www.byegm.gov.tr/YAYINLARIMIZ/CHR/ING97/03/97X03X25.TXT -# http://www.byegm.gov.tr/YAYINLARIMIZ/CHR/ING98/03/98X03X02.HTM -# http://www.byegm.gov.tr/YAYINLARIMIZ/CHR/ING99/10/99X10X26.HTM#%2016 -# http://www.byegm.gov.tr/YAYINLARIMIZ/CHR/ING2000/03/00X03X06.HTM#%2021 -# http://www.byegm.gov.tr/YAYINLARIMIZ/CHR/ING2001/03/23x03x01.HTM#%2027 -# From Paul Eggert (2007-01-03): -# Prefer the above source to Shanks & Pottenger for time stamps after 1990. +# 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/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): +# Prefer the above sources to Shanks & Pottenger for time stamps after 1985. # From Steffen Thorsen (2007-03-09): # Starting 2007 though, it seems that they are adopting EU's 1:00 UTC @@ -3495,6 +3527,14 @@ # Engineered Standard Time," said Twitter user @aysekarahasan. # http://www.bbc.com/news/world-europe-34631326 +# From Burak AYDIN (2016-09-08): +# Turkey will stay in Daylight Saving Time even in winter.... +# http://www.resmigazete.gov.tr/eskiler/2016/09/20160908-2.pdf +# +# From Paul Eggert (2016-09-07): +# The change is permanent, so this is the new standard time in Turkey. +# It takes effect today, which is not much notice. + # Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S Rule Turkey 1916 only - May 1 0:00 1:00 S Rule Turkey 1916 only - Oct 1 0:00 0 - @@ -3549,16 +3589,16 @@ 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 1986 1990 - Mar lastSun 2:00s 1:00 S -Rule Turkey 1986 1990 - Sep lastSun 2:00s 0 - -Rule Turkey 1991 2006 - Mar lastSun 1:00s 1:00 S -Rule Turkey 1991 1995 - Sep lastSun 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 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 TR%sT 1985 Apr 20 # Turkey Time + 3:00 Turkey +03/+04 1985 Apr 20 2:00 Turkey EE%sT 2007 2:00 EU EE%sT 2011 Mar 27 1:00u 2:00 - EET 2011 Mar 28 1:00u @@ -3566,7 +3606,8 @@ 2:00 - EET 2014 Mar 31 1:00u 2:00 EU EE%sT 2015 Oct 25 1:00u 2:00 1:00 EEST 2015 Nov 8 1:00u - 2:00 EU EE%sT + 2:00 EU EE%sT 2016 Sep 7 + 3:00 - +03 Link Europe/Istanbul Asia/Istanbul # Istanbul is in both continents. # Ukraine
--- a/make/data/tzdata/factory Fri Jan 13 17:09:28 2017 +0000 +++ b/make/data/tzdata/factory Mon Jan 23 16:30:43 2017 +0000 @@ -24,9 +24,10 @@ # This file is in the public domain, so clarified as of # 2009-05-17 by Arthur David Olson. -# For companies who don't want to put time zone specification in -# their installation procedures. When users run date, they'll get the message. -# Also useful for the "comp.sources" version. +# For distributors who don't want to put time zone specification in +# their installation procedures. Users that run 'date' will get the +# time zone abbreviation "-00", indicating that the actual time zone +# is unknown. # Zone NAME GMTOFF RULES FORMAT -Zone Factory 0 - "Local time zone must be set--see zic manual page" +Zone Factory 0 - -00
--- a/make/data/tzdata/leapseconds Fri Jan 13 17:09:28 2017 +0000 +++ b/make/data/tzdata/leapseconds Mon Jan 23 16:30:43 2017 +0000 @@ -79,6 +79,7 @@ Leap 2008 Dec 31 23:59:60 + S Leap 2012 Jun 30 23:59:60 + S Leap 2015 Jun 30 23:59:60 + S +Leap 2016 Dec 31 23:59:60 + S -# Updated through IERS Bulletin C51 -# File expires on: 28 December 2016 +# Updated through IERS Bulletin C52 +# File expires on: 28 June 2017
--- a/make/data/tzdata/northamerica Fri Jan 13 17:09:28 2017 +0000 +++ b/make/data/tzdata/northamerica Mon Jan 23 16:30:43 2017 +0000 @@ -47,8 +47,32 @@ # was the result of his proposals at the Convention of Railroad Trunk Lines # in New York City (1869-10). His 1870 proposal was based on Washington, DC, # but in 1872-05 he moved the proposed origin to Greenwich. -# His proposal was adopted by the railroads on 1883-11-18 at 12:00, -# and the most of the country soon followed suit. + +# From Paul Eggert (2016-09-21): +# Dowd's proposal left many details unresolved, such as where to draw +# lines between time zones. The key individual who made time zones +# work in the US was William Frederick Allen - railway engineer, +# managing editor of the Travelers' Guide, and secretary of the +# General Time Convention, a railway standardization group. Allen +# spent months in dialogs with scientific and railway leaders, +# developed a workable plan to institute time zones, and presented it +# to the General Time Convention on 1883-04-11, saying that his plan +# meant "local time would be practically abolished" - a plus for +# railway scheduling. By the next convention on 1883-10-11 nearly all +# railroads had agreed and it took effect on 1883-11-18 at 12:00. +# That Sunday was called the "day of two noons", as the eastern parts +# of the new zones observed noon twice. Allen witnessed the +# transition in New York City, writing: +# +# I heard the bells of St. Paul's strike on the old time. Four +# minutes later, obedient to the electrical signal from the Naval +# Observatory ... the time-ball made its rapid descent, the chimes +# of old Trinity rang twelve measured strokes, and local time was +# abandoned, probably forever. +# +# Most of the US soon followed suit. See: +# Bartky IR. The adoption of standard time. Technol Cult 1989 Jan;30(1):25-56. +# http://dx.doi.org/10.2307/3105430 # From Paul Eggert (2005-04-16): # That 1883 transition occurred at 12:00 new time, not at 12:00 old time. @@ -436,11 +460,42 @@ # north of the Salmon River, and the towns of Burgdorf and Warren), # Nevada (except West Wendover), Oregon (except the northern 3/4 of # Malheur county), and Washington + +# From Paul Eggert (2016-08-20): +# In early February 1948, in response to California's electricity shortage, +# PG&E changed power frequency from 60 to 59.5 Hz during daylight hours, +# causing electric clocks to lose six minutes per day. (This did not change +# legal time, and is not part of the data here.) See: +# Ross SA. An energy crisis from the past: Northern California in 1948. +# Working Paper No. 8, Institute of Governmental Studies, UC Berkeley, +# 1973-11. http://escholarship.org/uc/item/8x22k30c +# +# In another measure to save electricity, DST was instituted from 1948-03-14 +# at 02:01 to 1949-01-16 at 02:00, with the governor having the option to move +# the fallback transition earlier. See pages 3-4 of: +# http://clerk.assembly.ca.gov/sites/clerk.assembly.ca.gov/files/archive/Statutes/1948/48Vol1_Chapters.pdf +# +# In response: +# +# Governor Warren received a torrent of objecting mail, and it is not too much +# to speculate that the objections to Daylight Saving Time were one important +# factor in the defeat of the Dewey-Warren Presidential ticket in California. +# -- Ross, p 25 +# +# On December 8 the governor exercised the option, setting the date to January 1 +# (LA Times 1948-12-09). The transition time was 02:00 (LA Times 1949-01-01). +# +# Despite the controversy, in 1949 California voters approved Proposition 12, +# which established DST from April's last Sunday at 01:00 until September's +# last Sunday at 02:00. This was amended by 1962's Proposition 6, which changed +# the fall-back date to October's last Sunday. See: +# http://repository.uchastings.edu/cgi/viewcontent.cgi?article=1501&context=ca_ballot_props +# http://repository.uchastings.edu/cgi/viewcontent.cgi?article=1636&context=ca_ballot_props # # Rule NAME FROM TO TYPE IN ON AT SAVE LETTER -Rule CA 1948 only - Mar 14 2:00 1:00 D +Rule CA 1948 only - Mar 14 2:01 1:00 D Rule CA 1949 only - Jan 1 2:00 0 S -Rule CA 1950 1966 - Apr lastSun 2:00 1:00 D +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] @@ -3304,7 +3359,7 @@ # indicating that the normal ET rules are followed. # # From Paul Eggert (2014-08-19): -# The 2014-08-13 Cabinet meeting decided to stay on UTC-4 year-round. See: +# The 2014-08-13 Cabinet meeting decided to stay on UT -04 year-round. See: # http://tcweeklynews.com/daylight-savings-time-to-be-maintained-p5353-127.htm # Model this as a switch from EST/EDT to AST ... # From Chris Walton (2014-11-04):
--- a/make/data/tzdata/southamerica Fri Jan 13 17:09:28 2017 +0000 +++ b/make/data/tzdata/southamerica Mon Jan 23 16:30:43 2017 +0000 @@ -433,9 +433,9 @@ # stuck on Summer daylight savings time even though the summer is over. # From Paul Eggert (2013-09-05): -# Perhaps San Luis operates on the legal fiction that it is at UTC-4 +# Perhaps San Luis operates on the legal fiction that it is at -04 # with perpetual summer time, but ordinary usage typically seems to -# just say it's at UTC-3; see, for example, +# just say it's at -03; see, for example, # http://es.wikipedia.org/wiki/Hora_oficial_argentina # We've documented similar situations as being plain changes to # standard time, so let's do that here too. This does not change UTC
--- a/make/data/tzdata/zone.tab Fri Jan 13 17:09:28 2017 +0000 +++ b/make/data/tzdata/zone.tab Mon Jan 23 16:30:43 2017 +0000 @@ -175,7 +175,8 @@ CV +1455-02331 Atlantic/Cape_Verde CW +1211-06900 America/Curacao CX -1025+10543 Indian/Christmas -CY +3510+03322 Asia/Nicosia +CY +3510+03322 Asia/Nicosia Cyprus (most areas) +CY +3507+03357 Asia/Famagusta Northern Cyprus CZ +5005+01426 Europe/Prague DE +5230+01322 Europe/Berlin Germany (most areas) DE +4742+00841 Europe/Busingen Busingen @@ -284,7 +285,7 @@ MH +0905+16720 Pacific/Kwajalein Kwajalein MK +4159+02126 Europe/Skopje ML +1239-00800 Africa/Bamako -MM +1647+09610 Asia/Rangoon +MM +1647+09610 Asia/Yangon MN +4755+10653 Asia/Ulaanbaatar Mongolia (most areas) MN +4801+09139 Asia/Hovd Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan MN +4804+11430 Asia/Choibalsan Dornod, Sukhbaatar
--- a/src/macosx/classes/com/apple/eawt/_AppMenuBarHandler.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/macosx/classes/com/apple/eawt/_AppMenuBarHandler.java Mon Jan 23 16:30:43 2017 +0000 @@ -121,7 +121,7 @@ } // grab the pointer to the CMenuBar, and retain it in native - nativeSetDefaultMenuBar(((CMenuBar)peer).getModel()); + ((CMenuBar) peer).execute(_AppMenuBarHandler::nativeSetDefaultMenuBar); } void setAboutMenuItemVisible(final boolean present) {
--- a/src/macosx/classes/sun/lwawt/macosx/CCheckboxMenuItem.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/macosx/classes/sun/lwawt/macosx/CCheckboxMenuItem.java Mon Jan 23 16:30:43 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -26,29 +26,28 @@ package sun.lwawt.macosx; import java.awt.CheckboxMenuItem; -import java.awt.EventQueue; import java.awt.event.ItemEvent; import java.awt.peer.CheckboxMenuItemPeer; import sun.awt.SunToolkit; public class CCheckboxMenuItem extends CMenuItem implements CheckboxMenuItemPeer { - boolean fAutoToggle = true; - boolean fIsIndeterminate = false; + volatile boolean fAutoToggle = true; + volatile boolean fIsIndeterminate = false; private native void nativeSetState(long modelPtr, boolean state); private native void nativeSetIsCheckbox(long modelPtr); - CCheckboxMenuItem(CheckboxMenuItem target) { + CCheckboxMenuItem(final CheckboxMenuItem target) { super(target); - nativeSetIsCheckbox(getModel()); + execute(this::nativeSetIsCheckbox); setState(target.getState()); } // MenuItemPeer implementation @Override - public void setState(boolean state) { - nativeSetState(getModel(), state); + public void setState(final boolean state) { + execute(ptr -> nativeSetState(ptr, state)); } public void handleAction(final boolean state) {
--- a/src/macosx/classes/sun/lwawt/macosx/CEmbeddedFrame.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/macosx/classes/sun/lwawt/macosx/CEmbeddedFrame.java Mon Jan 23 16:30:43 2017 +0000 @@ -95,7 +95,7 @@ int absY = locationOnScreen.y + y; responder.handleScrollEvent(x, y, absX, absY, modifierFlags, deltaX, - deltaY); + deltaY, NSEvent.SCROLL_PHASE_UNSUPPORTED); } public void handleKeyEvent(int eventType, int modifierFlags, String characters,
--- a/src/macosx/classes/sun/lwawt/macosx/CFRetainedResource.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/macosx/classes/sun/lwawt/macosx/CFRetainedResource.java Mon Jan 23 16:30:43 2017 +0000 @@ -23,7 +23,6 @@ * questions. */ - package sun.lwawt.macosx; /** @@ -34,6 +33,7 @@ private static native void nativeCFRelease(final long ptr, final boolean disposeOnAppKitThread); private final boolean disposeOnAppKitThread; + // TODO this pointer should be private and accessed via CFNativeAction class protected volatile long ptr; /** @@ -70,8 +70,72 @@ nativeCFRelease(oldPtr, disposeOnAppKitThread); // perform outside of the synchronized block } + /** + * The interface which allows to execute some native operations with + * assumption that the native pointer will be valid till the end. + */ + public interface CFNativeAction { + + /** + * The native operation should be called from this method. + * + * @param ptr the pointer to the native data + */ + void run(long ptr); + } + + /** + * The interface which allows to execute some native operations and get a + * result with assumption that the native pointer will be valid till the + * end. + */ + interface CFNativeActionGet { + + /** + * The native operation should be called from this method. + * + * @param ptr the pointer to the native data + * @return result of the native operation + */ + long run(long ptr); + } + + /** + * This is utility method which should be used instead of the direct access + * to the {@link #ptr}, because this method guaranteed that the pointer will + * not be zero and will be valid till the end of the operation.It is highly + * recomended to not use any external lock in action. If the current + * {@link #ptr} is {@code 0} then action will be ignored. + * + * @param action The native operation + */ + public final synchronized void execute(final CFNativeAction action) { + if (ptr != 0) { + action.run(ptr); + } + } + + /** + * This is utility method which should be used instead of the direct access + * to the {@link #ptr}, because this method guaranteed that the pointer will + * not be zero and will be valid till the end of the operation. It is highly + * recomended to not use any external lock in action. If the current + * {@link #ptr} is {@code 0} then action will be ignored and {@code} is + * returned. + * + * @param action the native operation + * @return result of the native operation, usually the native pointer to + * some other data + */ + final synchronized long executeGet(final CFNativeActionGet action) { + if (ptr != 0) { + return action.run(ptr); + } + return 0; + } + @Override - protected void finalize() throws Throwable { + protected final void finalize() throws Throwable { dispose(); } }
--- a/src/macosx/classes/sun/lwawt/macosx/CMenu.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/macosx/classes/sun/lwawt/macosx/CMenu.java Mon Jan 23 16:30:43 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -25,7 +25,9 @@ package sun.lwawt.macosx; -import java.awt.*; +import java.awt.Menu; +import java.awt.MenuBar; +import java.awt.MenuItem; import java.awt.peer.MenuItemPeer; import java.awt.peer.MenuPeer; @@ -37,7 +39,7 @@ // This way we avoiding invocation of the setters twice @Override - protected void initialize(MenuItem target) { + protected final void initialize(MenuItem target) { setLabel(target.getLabel()); setEnabled(target.isEnabled()); } @@ -57,52 +59,50 @@ } @Override - protected long createModel() { + long createModel() { CMenuComponent parent = (CMenuComponent) LWCToolkit.targetToPeer(getTarget().getParent()); - if (parent instanceof CMenu || - parent instanceof CPopupMenu) - { - return nativeCreateSubMenu(parent.getModel()); - } else if (parent instanceof CMenuBar) { + if (parent instanceof CMenu) { + return parent.executeGet(this::nativeCreateSubMenu); + } + if (parent instanceof CMenuBar) { MenuBar parentContainer = (MenuBar)getTarget().getParent(); boolean isHelpMenu = parentContainer.getHelpMenu() == getTarget(); int insertionLocation = ((CMenuBar)parent).getNextInsertionIndex(); - return nativeCreateMenu(parent.getModel(), - isHelpMenu, insertionLocation); - } else { - throw new InternalError("Parent must be CMenu or CMenuBar"); + return parent.executeGet(ptr -> nativeCreateMenu(ptr, isHelpMenu, + insertionLocation)); } + throw new InternalError("Parent must be CMenu or CMenuBar"); } @Override - public void addItem(MenuItem item) { + public final void addItem(MenuItem item) { // Nothing to do here -- we added it when we created the // menu item's peer. } @Override - public void delItem(int index) { - nativeDeleteItem(getModel(), index); + public final void delItem(final int index) { + execute(ptr -> nativeDeleteItem(ptr, index)); } @Override - public void setLabel(String label) { - nativeSetMenuTitle(getModel(), label); + public final void setLabel(final String label) { + execute(ptr->nativeSetMenuTitle(ptr, label)); super.setLabel(label); } // Note that addSeparator is never called directly from java.awt.Menu, // though it is required in the MenuPeer interface. @Override - public void addSeparator() { - nativeAddSeparator(getModel()); + public final void addSeparator() { + execute(this::nativeAddSeparator); } // Used by ScreenMenuBar to get to the native menu for event handling. - public long getNativeMenu() { - return nativeGetNSMenu(getModel()); + public final long getNativeMenu() { + return executeGet(this::nativeGetNSMenu); } private native long nativeCreateMenu(long parentMenuPtr,
--- a/src/macosx/classes/sun/lwawt/macosx/CMenuBar.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/macosx/classes/sun/lwawt/macosx/CMenuBar.java Mon Jan 23 16:30:43 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -29,7 +29,9 @@ import java.awt.MenuBar; import java.awt.peer.MenuBarPeer; -public class CMenuBar extends CMenuComponent implements MenuBarPeer { +import sun.awt.AWTAccessor; + +public final class CMenuBar extends CMenuComponent implements MenuBarPeer { private int nextInsertionIndex = -1; @@ -38,15 +40,16 @@ } @Override - protected long createModel() { + long createModel() { return nativeCreateMenuBar(); } @Override - public void addHelpMenu(Menu m) { - CMenu cMenu = (CMenu)m.getPeer(); - nativeSetHelpMenu(getModel(), cMenu.getModel()); - } + public void addHelpMenu(final Menu m) { + final CMenu cMenu = AWTAccessor.getMenuComponentAccessor().getPeer(m); + execute(parentPtr -> cMenu.execute( + menuPtr -> nativeSetHelpMenu(parentPtr, menuPtr))); + } public int getNextInsertionIndex() { return nextInsertionIndex; @@ -63,8 +66,8 @@ } @Override - public void delMenu(int index) { - nativeDelMenu(getModel(), index); + public void delMenu(final int index) { + execute(ptr -> nativeDelMenu(ptr, index)); } private native long nativeCreateMenuBar();
--- a/src/macosx/classes/sun/lwawt/macosx/CMenuComponent.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/macosx/classes/sun/lwawt/macosx/CMenuComponent.java Mon Jan 23 16:30:43 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -29,36 +29,32 @@ import java.awt.MenuComponent; import java.awt.peer.MenuComponentPeer; -public abstract class CMenuComponent implements MenuComponentPeer { +abstract class CMenuComponent extends CFRetainedResource + implements MenuComponentPeer { + + private final MenuComponent target; - private MenuComponent target; - private long modelPtr; - - CMenuComponent(MenuComponent target) { + CMenuComponent(final MenuComponent target) { + super(0, true); this.target = target; - this.modelPtr = createModel(); + setPtr(createModel()); } - MenuComponent getTarget() { + final MenuComponent getTarget() { return target; } - public long getModel() { - return modelPtr; + abstract long createModel(); + + @Override + public final void dispose() { + super.dispose(); + LWCToolkit.targetDisposedPeer(target, this); } - protected abstract long createModel(); - - public void dispose() { - LWCToolkit.targetDisposedPeer(target, this); - nativeDispose(modelPtr); - target = null; - } - - private native void nativeDispose(long modelPtr); - // 1.5 peer method - public void setFont(Font f) { + @Override + public final void setFont(final Font f) { // no-op, as we don't currently support menu fonts // c.f. radar 4032912 }
--- a/src/macosx/classes/sun/lwawt/macosx/CMenuItem.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/macosx/classes/sun/lwawt/macosx/CMenuItem.java Mon Jan 23 16:30:43 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -25,16 +25,17 @@ package sun.lwawt.macosx; +import java.awt.MenuItem; +import java.awt.MenuShortcut; +import java.awt.event.ActionEvent; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import java.awt.peer.MenuItemPeer; +import java.util.concurrent.atomic.AtomicBoolean; + import sun.awt.SunToolkit; import sun.lwawt.LWToolkit; -import java.awt.MenuContainer; -import java.awt.MenuItem; -import java.awt.MenuShortcut; -import java.awt.event.*; -import java.awt.peer.MenuItemPeer; -import java.util.concurrent.atomic.AtomicBoolean; - public class CMenuItem extends CMenuComponent implements MenuItemPeer { private final AtomicBoolean enabled = new AtomicBoolean(true); @@ -58,9 +59,9 @@ } @Override - protected long createModel() { + long createModel() { CMenuComponent parent = (CMenuComponent)LWToolkit.targetToPeer(getTarget().getParent()); - return nativeCreate(parent.getModel(), isSeparator()); + return parent.executeGet(ptr->nativeCreate(ptr, isSeparator())); } public void setLabel(String label, char keyChar, int keyCode, int modifiers) { @@ -90,7 +91,12 @@ keyChar = 0; } - nativeSetLabel(getModel(), label, keyChar, keyCode, keyMask); + final String finalLabel = label; + final char finalKeyChar = keyChar; + final int finalKeyCode = keyCode; + final int finalKeyMask = keyMask; + execute(ptr -> nativeSetLabel(ptr, finalLabel, finalKeyChar, + finalKeyCode, finalKeyMask)); } @Override @@ -105,16 +111,16 @@ * There isn't a need to expose this except in a instanceof because * it isn't defined in the peer api. */ - public void setImage(java.awt.Image img) { + public final void setImage(final java.awt.Image img) { CImage cimg = CImage.getCreator().createFromImage(img); - nativeSetImage(getModel(), cimg == null ? 0L : cimg.ptr); + execute(ptr -> nativeSetImage(ptr, cimg == null ? 0L : cimg.ptr)); } /** * New API for tooltips */ - public void setToolTipText(String text) { - nativeSetTooltip(getModel(), text); + public final void setToolTipText(final String text) { + execute(ptr -> nativeSetTooltip(ptr, text)); } // @Override @@ -138,7 +144,8 @@ b &= ((CMenuItem) parent).isEnabled(); } if (enabled.compareAndSet(!b, b)) { - nativeSetEnabled(getModel(), b); + final boolean finalB = b; + execute(ptr->nativeSetEnabled(ptr, finalB)); } }
--- a/src/macosx/classes/sun/lwawt/macosx/CPlatformResponder.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/macosx/classes/sun/lwawt/macosx/CPlatformResponder.java Mon Jan 23 16:30:43 2017 +0000 @@ -44,6 +44,8 @@ private final PlatformEventNotifier eventNotifier; private final boolean isNpapiCallback; private int lastKeyPressCode = KeyEvent.VK_UNDEFINED; + private final DeltaAccumulator deltaAccumulatorX = new DeltaAccumulator(); + private final DeltaAccumulator deltaAccumulatorY = new DeltaAccumulator(); CPlatformResponder(final PlatformEventNotifier eventNotifier, final boolean isNpapiCallback) { @@ -90,39 +92,39 @@ */ void handleScrollEvent(final int x, final int y, final int absX, final int absY, final int modifierFlags, - final double deltaX, final double deltaY) { + final double deltaX, final double deltaY, + final int scrollPhase) { final int buttonNumber = CocoaConstants.kCGMouseButtonCenter; int jmodifiers = NSEvent.nsToJavaMouseModifiers(buttonNumber, modifierFlags); final boolean isShift = (jmodifiers & InputEvent.SHIFT_DOWN_MASK) != 0; + int roundDeltaX = deltaAccumulatorX.getRoundedDelta(deltaX, scrollPhase); + int roundDeltaY = deltaAccumulatorY.getRoundedDelta(deltaY, scrollPhase); + // Vertical scroll. - if (!isShift && deltaY != 0.0) { - dispatchScrollEvent(x, y, absX, absY, jmodifiers, deltaY); + if (!isShift && (deltaY != 0.0 || roundDeltaY != 0)) { + dispatchScrollEvent(x, y, absX, absY, jmodifiers, roundDeltaY, deltaY); } // Horizontal scroll or shirt+vertical scroll. final double delta = isShift && deltaY != 0.0 ? deltaY : deltaX; - if (delta != 0.0) { + final int roundDelta = isShift && roundDeltaY != 0 ? roundDeltaY : roundDeltaX; + if (delta != 0.0 || roundDelta != 0) { jmodifiers |= InputEvent.SHIFT_DOWN_MASK; - dispatchScrollEvent(x, y, absX, absY, jmodifiers, delta); + dispatchScrollEvent(x, y, absX, absY, jmodifiers, roundDelta, delta); } } private void dispatchScrollEvent(final int x, final int y, final int absX, final int absY, final int modifiers, - final double delta) { + final int roundDelta, final double delta) { final long when = System.currentTimeMillis(); final int scrollType = MouseWheelEvent.WHEEL_UNIT_SCROLL; final int scrollAmount = 1; - int wheelRotation = (int) delta; - int signum = (int) Math.signum(delta); - if (signum * delta < 1) { - wheelRotation = signum; - } // invert the wheelRotation for the peer eventNotifier.notifyMouseWheelEvent(when, x, y, absX, absY, modifiers, scrollType, scrollAmount, - -wheelRotation, -delta, null); + -roundDelta, -delta, null); } /** @@ -258,4 +260,46 @@ void handleWindowFocusEvent(boolean gained, LWWindowPeer opposite) { eventNotifier.notifyActivation(gained, opposite); } + + static class DeltaAccumulator { + + static final double MIN_THRESHOLD = 0.1; + static final double MAX_THRESHOLD = 0.5; + double accumulatedDelta; + + int getRoundedDelta(double delta, int scrollPhase) { + + int roundDelta = (int) Math.round(delta); + + if (scrollPhase == NSEvent.SCROLL_PHASE_UNSUPPORTED) { // mouse wheel + if (roundDelta == 0 && delta != 0) { + roundDelta = delta > 0 ? 1 : -1; + } + } else { // trackpad + boolean begin = scrollPhase == NSEvent.SCROLL_PHASE_BEGAN; + boolean end = scrollPhase == NSEvent.SCROLL_MASK_PHASE_ENDED + || scrollPhase == NSEvent.SCROLL_MASK_PHASE_CANCELLED; + + if (begin) { + accumulatedDelta = 0; + } + + accumulatedDelta += delta; + + double absAccumulatedDelta = Math.abs(accumulatedDelta); + if (absAccumulatedDelta > MAX_THRESHOLD) { + roundDelta = (int) Math.round(accumulatedDelta); + accumulatedDelta -= roundDelta; + } + + if (end) { + if (roundDelta == 0 && absAccumulatedDelta > MIN_THRESHOLD) { + roundDelta = accumulatedDelta > 0 ? 1 : -1; + } + } + } + + return roundDelta; + } + } }
--- a/src/macosx/classes/sun/lwawt/macosx/CPlatformView.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/macosx/classes/sun/lwawt/macosx/CPlatformView.java Mon Jan 23 16:30:43 2017 +0000 @@ -194,7 +194,8 @@ if (event.getType() == CocoaConstants.NSScrollWheel) { responder.handleScrollEvent(x, y, absX, absY, event.getModifierFlags(), - event.getScrollDeltaX(), event.getScrollDeltaY()); + event.getScrollDeltaX(), event.getScrollDeltaY(), + event.getScrollPhase()); } else { responder.handleMouseEvent(event.getType(), event.getModifierFlags(), event.getButtonNumber(), event.getClickCount(), x, y,
--- a/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java Mon Jan 23 16:30:43 2017 +0000 @@ -419,7 +419,7 @@ final long nsWindowPtr = getNSWindowPtr(); CMenuBar mbPeer = (CMenuBar)LWToolkit.targetToPeer(mb); if (mbPeer != null) { - nativeSetNSWindowMenuBar(nsWindowPtr, mbPeer.getModel()); + mbPeer.execute(ptr -> nativeSetNSWindowMenuBar(nsWindowPtr, ptr)); } else { nativeSetNSWindowMenuBar(nsWindowPtr, 0); }
--- a/src/macosx/classes/sun/lwawt/macosx/CPopupMenu.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/macosx/classes/sun/lwawt/macosx/CPopupMenu.java Mon Jan 23 16:30:43 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -25,18 +25,20 @@ package sun.lwawt.macosx; -import java.awt.*; +import java.awt.Component; +import java.awt.Event; +import java.awt.Point; +import java.awt.PopupMenu; import java.awt.peer.PopupMenuPeer; -import sun.lwawt.LWWindowPeer; +final class CPopupMenu extends CMenu implements PopupMenuPeer { -public class CPopupMenu extends CMenu implements PopupMenuPeer { CPopupMenu(PopupMenu target) { super(target); } @Override - protected long createModel() { + long createModel() { return nativeCreatePopupMenu(); } @@ -50,7 +52,7 @@ Point loc = origin.getLocationOnScreen(); e.x += loc.x; e.y += loc.y; - nativeShowPopupMenu(getModel(), e.x, e.y); + execute(ptr -> nativeShowPopupMenu(ptr, e.x, e.y)); } } }
--- a/src/macosx/classes/sun/lwawt/macosx/CTrayIcon.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/macosx/classes/sun/lwawt/macosx/CTrayIcon.java Mon Jan 23 16:30:43 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -104,7 +104,10 @@ return 0L; } } - return checkAndCreatePopupPeer().getModel(); + // This method is executed on Appkit, so if ptr is not zero means that, + // it is still not deallocated(even if we call NSApp postRunnableEvent) + // and sent CFRelease to the native queue + return checkAndCreatePopupPeer().ptr; } /**
--- a/src/macosx/classes/sun/lwawt/macosx/NSEvent.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/macosx/classes/sun/lwawt/macosx/NSEvent.java Mon Jan 23 16:30:43 2017 +0000 @@ -32,6 +32,13 @@ * JDK functionality. */ final class NSEvent { + + static final int SCROLL_PHASE_UNSUPPORTED = 1; + static final int SCROLL_PHASE_BEGAN = 2; + static final int SCROLL_PHASE_CONTINUED = 3; + static final int SCROLL_MASK_PHASE_CANCELLED = 4; + static final int SCROLL_MASK_PHASE_ENDED = 5; + private int type; private int modifierFlags; @@ -42,6 +49,7 @@ private int y; private double scrollDeltaY; private double scrollDeltaX; + private int scrollPhase; private int absX; private int absY; @@ -62,7 +70,7 @@ // Called from native NSEvent(int type, int modifierFlags, int clickCount, int buttonNumber, int x, int y, int absX, int absY, - double scrollDeltaY, double scrollDeltaX) { + double scrollDeltaY, double scrollDeltaX, int scrollPhase) { this.type = type; this.modifierFlags = modifierFlags; this.clickCount = clickCount; @@ -73,6 +81,7 @@ this.absY = absY; this.scrollDeltaY = scrollDeltaY; this.scrollDeltaX = scrollDeltaX; + this.scrollPhase = scrollPhase; } int getType() { @@ -107,6 +116,10 @@ return scrollDeltaX; } + int getScrollPhase() { + return scrollPhase; + } + int getAbsX() { return absX; }
--- a/src/macosx/native/sun/awt/AWTSurfaceLayers.m Fri Jan 13 17:09:28 2017 +0000 +++ b/src/macosx/native/sun/awt/AWTSurfaceLayers.m Mon Jan 23 16:30:43 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -103,8 +103,6 @@ CALayer *windowLayer = jlong_to_ptr(windowLayerPtr); surfaceLayers = [[AWTSurfaceLayers alloc] initWithWindowLayer: windowLayer]; - CFRetain(surfaceLayers); - [surfaceLayers release]; }]; JNF_COCOA_EXIT(env);
--- a/src/macosx/native/sun/awt/AWTView.m Fri Jan 13 17:09:28 2017 +0000 +++ b/src/macosx/native/sun/awt/AWTView.m Mon Jan 23 16:30:43 2017 +0000 @@ -114,9 +114,9 @@ remoteLayer.parentLayer = parentLayer; remoteLayer.remoteLayer = NULL; remoteLayer.jrsRemoteLayer = [remoteLayer createRemoteLayerBoundTo:JRSRemotePort]; - CFRetain(remoteLayer); // REMIND + [remoteLayer retain]; // REMIND remoteLayer.frame = CGRectMake(0, 0, 720, 500); // REMIND - CFRetain(remoteLayer.jrsRemoteLayer); // REMIND + [remoteLayer.jrsRemoteLayer retain]; // REMIND int layerID = [remoteLayer.jrsRemoteLayer layerID]; NSLog(@"layer id to send = %d", layerID); sendLayerID(layerID); @@ -386,7 +386,7 @@ } static JNF_CLASS_CACHE(jc_NSEvent, "sun/lwawt/macosx/NSEvent"); - static JNF_CTOR_CACHE(jctor_NSEvent, jc_NSEvent, "(IIIIIIIIDD)V"); + static JNF_CTOR_CACHE(jctor_NSEvent, jc_NSEvent, "(IIIIIIIIDDI)V"); jobject jEvent = JNFNewObject(env, jctor_NSEvent, [event type], [event modifierFlags], @@ -395,7 +395,8 @@ (jint)localPoint.x, (jint)localPoint.y, (jint)absP.x, (jint)absP.y, [event deltaY], - [event deltaX]); + [event deltaX], + [AWTToolkit scrollStateWithEvent: event]); if (jEvent == nil) { // Unable to create event by some reason. return; @@ -1340,12 +1341,9 @@ [ThreadUtilities performOnMainThreadWaiting:YES block:^(){ CALayer *windowLayer = jlong_to_ptr(windowLayerPtr); - AWTView *view = [[AWTView alloc] initWithRect:rect - platformView:cPlatformView - windowLayer:windowLayer]; - CFRetain(view); - [view release]; // GC - newView = view; + newView = [[AWTView alloc] initWithRect:rect + platformView:cPlatformView + windowLayer:windowLayer]; }]; JNF_COCOA_EXIT(env);
--- a/src/macosx/native/sun/awt/AWTWindow.m Fri Jan 13 17:09:28 2017 +0000 +++ b/src/macosx/native/sun/awt/AWTWindow.m Mon Jan 23 16:30:43 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -800,6 +800,18 @@ - (void)sendEvent:(NSEvent *)event { if ([event type] == NSLeftMouseDown || [event type] == NSRightMouseDown || [event type] == NSOtherMouseDown) { + // Move parent windows to front and make sure that a child window is displayed + // in front of its nearest parent. + if (self.ownerWindow != nil) { + JNIEnv *env = [ThreadUtilities getJNIEnvUncached]; + jobject platformWindow = [self.javaPlatformWindow jObjectWithEnv:env]; + if (platformWindow != NULL) { + static JNF_MEMBER_CACHE(jm_orderAboveSiblings, jc_CPlatformWindow, "orderAboveSiblings", "()V"); + JNFCallVoidMethod(env,platformWindow, jm_orderAboveSiblings); + (*env)->DeleteLocalRef(env, platformWindow); + } + } + [self orderChildWindows:YES]; NSPoint p = [NSEvent mouseLocation]; NSRect frame = [self.nsWindow frame]; @@ -904,7 +916,7 @@ contentView:contentView]; // the window is released is CPlatformWindow.nativeDispose() - if (window) CFRetain(window.nsWindow); + if (window) [window.nsWindow retain]; }]; JNF_COCOA_EXIT(env); @@ -1100,6 +1112,16 @@ NSWindow *nsWindow = OBJC(windowPtr); [ThreadUtilities performOnMainThreadWaiting:NO block:^(){ [nsWindow orderBack:nil]; + // Order parent windows + AWTWindow *awtWindow = (AWTWindow*)[nsWindow delegate]; + while (awtWindow.ownerWindow != nil) { + awtWindow = awtWindow.ownerWindow; + if ([AWTWindow isJavaPlatformWindowVisible:awtWindow.nsWindow]) { + [awtWindow.nsWindow orderBack:nil]; + } + } + // Order child windows + [(AWTWindow*)[nsWindow delegate] orderChildWindows:NO]; }]; JNF_COCOA_EXIT(env);
--- a/src/macosx/native/sun/awt/ApplicationDelegate.m Fri Jan 13 17:09:28 2017 +0000 +++ b/src/macosx/native/sun/awt/ApplicationDelegate.m Mon Jan 23 16:30:43 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -255,8 +255,6 @@ [super dealloc]; } -//- (void)finalize { [super finalize]; } // GC - #pragma mark Callbacks from AppKit @@ -623,8 +621,7 @@ JNF_COCOA_ENTER(env); [ThreadUtilities performOnMainThreadWaiting:YES block:^(){ - image = [ApplicationDelegate _dockIconImage]; - CFRetain(image); + image = [[ApplicationDelegate _dockIconImage] retain]; }]; JNF_COCOA_EXIT(env);
--- a/src/macosx/native/sun/awt/CClipboard.m Fri Jan 13 17:09:28 2017 +0000 +++ b/src/macosx/native/sun/awt/CClipboard.m Mon Jan 23 16:30:43 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -72,7 +72,6 @@ [super dealloc]; } -//- (void)finalize { [super finalize]; } - (NSData *)data { return fData;
--- a/src/macosx/native/sun/awt/CDesktopPeer.m Fri Jan 13 17:09:28 2017 +0000 +++ b/src/macosx/native/sun/awt/CDesktopPeer.m Mon Jan 23 16:30:43 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -79,7 +79,7 @@ LSApplicationParameters params = {0, flags, NULL, NULL, NULL, NULL, NULL}; status = LSOpenURLsWithRole((CFArrayRef)[NSArray arrayWithObject:url], kLSRolesAll, NULL, ¶ms, NULL, 0); - CFRelease(url); + [url release]; JNF_COCOA_EXIT(env); return status;
--- a/src/macosx/native/sun/awt/CDragSource.m Fri Jan 13 17:09:28 2017 +0000 +++ b/src/macosx/native/sun/awt/CDragSource.m Mon Jan 23 16:30:43 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -193,7 +193,7 @@ fFormatMap = NULL; } - CFRelease(self); // GC + [self release]; } - (void)dealloc @@ -209,8 +209,6 @@ [super dealloc]; } -//- (void)finalize { [super finalize]; } - // Appropriated from Windows' awt_DataTransferer.cpp: //
--- a/src/macosx/native/sun/awt/CDragSourceContextPeer.m Fri Jan 13 17:09:28 2017 +0000 +++ b/src/macosx/native/sun/awt/CDragSourceContextPeer.m Mon Jan 23 16:30:43 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -67,10 +67,6 @@ }]; JNF_COCOA_EXIT(env); - if (dragSource) { - CFRetain(dragSource); // GC - [dragSource release]; - } return ptr_to_jlong(dragSource); }
--- a/src/macosx/native/sun/awt/CDropTarget.m Fri Jan 13 17:09:28 2017 +0000 +++ b/src/macosx/native/sun/awt/CDropTarget.m Mon Jan 23 16:30:43 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -171,7 +171,7 @@ fDropTargetContextPeer = NULL; } - CFRelease(self); + [self release]; } - (void)dealloc @@ -187,7 +187,6 @@ [super dealloc]; } -//- (void)finalize { [super finalize]; } - (NSInteger) getDraggingSequenceNumber { @@ -724,10 +723,6 @@ dropTarget = [[CDropTarget alloc] init:jdroptarget component:jcomponent peer:jpeer control:controlObj]; JNF_COCOA_EXIT(env); - if (dropTarget) { - CFRetain(dropTarget); // GC - [dropTarget release]; - } return ptr_to_jlong(dropTarget); }
--- a/src/macosx/native/sun/awt/CFileDialog.m Fri Jan 13 17:09:28 2017 +0000 +++ b/src/macosx/native/sun/awt/CFileDialog.m Mon Jan 23 16:30:43 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -88,7 +88,6 @@ [super dealloc]; } -//- (void)finalize { [super finalize]; } - (void)safeSaveOrLoad { NSSavePanel *thePanel = nil; @@ -168,9 +167,9 @@ } // ask the file filter up in Java - CFStringRef filePath = CFURLCopyFileSystemPath((CFURLRef)url, kCFURLPOSIXPathStyle); - BOOL shouldEnableFile = [self askFilenameFilter:(NSString *)filePath]; - CFRelease(filePath); + NSString* filePath = (NSString*)CFURLCopyFileSystemPath((CFURLRef)url, kCFURLPOSIXPathStyle); + BOOL shouldEnableFile = [self askFilenameFilter:filePath]; + [filePath release]; return shouldEnableFile; }
--- a/src/macosx/native/sun/awt/CGraphicsEnv.m Fri Jan 13 17:09:28 2017 +0000 +++ b/src/macosx/native/sun/awt/CGraphicsEnv.m Mon Jan 23 16:30:43 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -163,8 +163,7 @@ JNF_COCOA_ENTER(env); - JNFWeakJObjectWrapper *wrapper = [JNFWeakJObjectWrapper wrapperWithJObject:this withEnv:env]; - CFRetain(wrapper); // pin from ObjC-GC + JNFWeakJObjectWrapper *wrapper = [[JNFWeakJObjectWrapper wrapperWithJObject:this withEnv:env] retain]; /* Register the callback */ if (CGDisplayRegisterReconfigurationCallback(&displaycb_handle, wrapper) != kCGErrorSuccess) { @@ -204,8 +203,7 @@ } [wrapper setJObject:NULL withEnv:env]; // more efficiant to pre-clear - - CFRelease(wrapper); + [wrapper release]; JNF_COCOA_EXIT(env); }
--- a/src/macosx/native/sun/awt/CImage.m Fri Jan 13 17:09:28 2017 +0000 +++ b/src/macosx/native/sun/awt/CImage.m Mon Jan 23 16:30:43 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -115,14 +115,9 @@ NSBitmapImageRep* imageRep = CImage_CreateImageRep(env, buffer, width, height); if (imageRep) { - NSImage *nsImage = [[NSImage alloc] initWithSize:NSMakeSize(width, height)]; + NSImage *nsImage = [[[NSImage alloc] initWithSize:NSMakeSize(width, height)] retain]; [nsImage addRepresentation:imageRep]; [imageRep release]; - - if (nsImage != nil) { - CFRetain(nsImage); // GC - } - result = ptr_to_jlong(nsImage); } @@ -165,13 +160,8 @@ (*env)->ReleaseIntArrayElements(env, widths, ws, JNI_ABORT); } if ([reps count]) { - NSImage *nsImage = [[NSImage alloc] initWithSize:NSMakeSize(0, 0)]; + NSImage *nsImage = [[[NSImage alloc] initWithSize:NSMakeSize(0, 0)] retain]; [nsImage addRepresentations: reps]; - - if (nsImage != nil) { - CFRetain(nsImage); // GC - } - result = ptr_to_jlong(nsImage); } @@ -194,8 +184,7 @@ IconRef iconRef; if (noErr == GetIconRef(kOnSystemDisk, kSystemIconsCreator, selector, &iconRef)) { - image = [[NSImage alloc] initWithIconRef:iconRef]; - if (image) CFRetain(image); // GC + image = [[[NSImage alloc] initWithIconRef:iconRef] retain]; ReleaseIconRef(iconRef); } @@ -217,8 +206,7 @@ JNF_COCOA_ENTER(env); NSString *path = JNFNormalizedNSStringForPath(env, file); - image = [[NSImage alloc] initByReferencingFile:path]; - if (image) CFRetain(image); // GC + image = [[[NSImage alloc] initByReferencingFile:path] retain]; JNF_COCOA_EXIT(env); @@ -239,9 +227,8 @@ NSString *path = JNFNormalizedNSStringForPath(env, file); [ThreadUtilities performOnMainThreadWaiting:YES block:^(){ - image = [[NSWorkspace sharedWorkspace] iconForFile:path]; + image = [[[NSWorkspace sharedWorkspace] iconForFile:path] retain]; [image setScalesWhenResized:TRUE]; - if (image) CFRetain(image); // GC }]; JNF_COCOA_EXIT(env); @@ -261,8 +248,7 @@ JNF_COCOA_ENTER(env); - image = [NSImage imageNamed:JNFJavaToNSString(env, name)]; - if (image) CFRetain(image); // GC + image = [[NSImage imageNamed:JNFJavaToNSString(env, name)] retain]; JNF_COCOA_EXIT(env);
--- a/src/macosx/native/sun/awt/CMenu.m Fri Jan 13 17:09:28 2017 +0000 +++ b/src/macosx/native/sun/awt/CMenu.m Mon Jan 23 16:30:43 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -38,7 +38,7 @@ - (id)initWithPeer:(jobject)peer { AWT_ASSERT_APPKIT_THREAD; // Create the new NSMenu - self = [super initWithPeer:peer asSeparator:[NSNumber numberWithBool:NO]]; + self = [super initWithPeer:peer asSeparator:NO]; if (self) { fMenu = [NSMenu javaMenuWithTitle:@""]; [fMenu retain]; @@ -52,7 +52,6 @@ fMenu = nil; [super dealloc]; } -//- (void)finalize { [super finalize]; } - (void)addJavaSubmenu:(CMenu *)submenu { [ThreadUtilities performOnMainThread:@selector(addNativeItem_OnAppKitThread:) on:self withObject:submenu waitUntilDone:YES]; @@ -134,14 +133,13 @@ CMenu * createCMenu (jobject cPeerObjGlobal) { - CMenu *aCMenu = nil; + __block CMenu *aCMenu = nil; + + [ThreadUtilities performOnMainThreadWaiting:YES block:^(){ - // We use an array here only to be able to get a return value - NSMutableArray *args = [[NSMutableArray alloc] initWithObjects:[NSValue valueWithBytes:&cPeerObjGlobal objCType:@encode(jobject)], nil]; - - [ThreadUtilities performOnMainThread:@selector(_create_OnAppKitThread:) on:[CMenu alloc] withObject:args waitUntilDone:YES]; - - aCMenu = (CMenu *)[args objectAtIndex: 0]; + aCMenu = [[CMenu alloc] initWithPeer:cPeerObjGlobal]; + // the aCMenu is released in CMenuComponent.dispose() + }]; if (aCMenu == nil) { return 0L; @@ -169,10 +167,6 @@ // Add it to the parent menu [((CMenu *)jlong_to_ptr(parentMenu)) addJavaSubmenu: aCMenu]; - if (aCMenu) { - CFRetain(aCMenu); // GC - [aCMenu release]; - } JNF_COCOA_EXIT(env); @@ -209,10 +203,6 @@ [parent javaSetHelpMenu: aCMenu]; } - if (aCMenu) { - CFRetain(aCMenu); // GC - [aCMenu release]; - } JNF_COCOA_EXIT(env); return ptr_to_jlong(aCMenu); } @@ -275,13 +265,9 @@ NSMenu* nsMenu = NULL; JNF_COCOA_ENTER(env); - nsMenu = [((CMenu *)jlong_to_ptr(menuObject)) menu]; + // Strong retain this menu; it'll get released in Java_apple_laf_ScreenMenu_addMenuListeners + nsMenu = [[((CMenu *)jlong_to_ptr(menuObject)) menu] retain]; JNF_COCOA_EXIT(env); - // Strong retain this menu; it'll get released in Java_apple_laf_ScreenMenu_addMenuListeners - if (nsMenu) { - CFRetain(nsMenu); // GC - } - return ptr_to_jlong(nsMenu); }
--- a/src/macosx/native/sun/awt/CMenuBar.m Fri Jan 13 17:09:28 2017 +0000 +++ b/src/macosx/native/sun/awt/CMenuBar.m Mon Jan 23 16:30:43 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -383,32 +383,21 @@ Java_sun_lwawt_macosx_CMenuBar_nativeCreateMenuBar (JNIEnv *env, jobject peer) { - CMenuBar *aCMenuBar = nil; + __block CMenuBar *aCMenuBar = nil; JNF_COCOA_ENTER(env); jobject cPeerObjGlobal = (*env)->NewGlobalRef(env, peer); - // We use an array here only to be able to get a return value - NSMutableArray *args = [[NSMutableArray alloc] initWithObjects:[NSValue valueWithBytes:&cPeerObjGlobal objCType:@encode(jobject)], nil]; + [ThreadUtilities performOnMainThreadWaiting:YES block:^(){ - [ThreadUtilities performOnMainThread:@selector(_create_OnAppKitThread:) on:[CMenuBar alloc] withObject:args waitUntilDone:YES]; - - aCMenuBar = (CMenuBar *)[args objectAtIndex: 0]; - + aCMenuBar = [[CMenuBar alloc] initWithPeer:cPeerObjGlobal]; + // the aCMenuBar is released in CMenuComponent.dispose() + }]; if (aCMenuBar == nil) { return 0L; } - // [args release]; - - // A strange memory managment after that. - - JNF_COCOA_EXIT(env); - if (aCMenuBar) { - CFRetain(aCMenuBar); // GC - [aCMenuBar release]; - } return ptr_to_jlong(aCMenuBar); }
--- a/src/macosx/native/sun/awt/CMenuComponent.m Fri Jan 13 17:09:28 2017 +0000 +++ b/src/macosx/native/sun/awt/CMenuComponent.m Mon Jan 23 16:30:43 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -41,49 +41,11 @@ return self; } --(void) cleanup { - // Used by subclasses -} - --(void) disposer { +-(void) dealloc { JNIEnv *env = [ThreadUtilities getJNIEnvUncached]; JNFDeleteGlobalRef(env, fPeer); fPeer = NULL; - [self cleanup]; - - CFRelease(self); // GC + [super dealloc]; } - -// The method is used by all subclasses, since the process of the creation -// is the same. The only exception is the CMenuItem class. -- (void) _create_OnAppKitThread: (NSMutableArray *)argValue { - jobject cPeerObjGlobal = (jobject)[[argValue objectAtIndex: 0] pointerValue]; - CMenuItem *aCMenuItem = [self initWithPeer:cPeerObjGlobal]; - [argValue removeAllObjects]; - [argValue addObject: aCMenuItem]; -} - -//-(void) dealloc { [super dealloc]; } -//- (void)finalize { [super finalize]; } - @end - -/* - * Class: sun_lwawt_macosx_CMenuComponent - * Method: nativeDispose - * Signature: (J)V - */ -JNIEXPORT void JNICALL -Java_sun_lwawt_macosx_CMenuComponent_nativeDispose -(JNIEnv *env, jobject peer, jlong menuItemObj) -{ -JNF_COCOA_ENTER(env); - - [ThreadUtilities performOnMainThread:@selector(disposer) - on:((id)jlong_to_ptr(menuItemObj)) - withObject:nil - waitUntilDone:NO]; - -JNF_COCOA_EXIT(env); -}
--- a/src/macosx/native/sun/awt/CMenuItem.h Fri Jan 13 17:09:28 2017 +0000 +++ b/src/macosx/native/sun/awt/CMenuItem.h Mon Jan 23 16:30:43 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -32,7 +32,7 @@ } // Setup -- (id) initWithPeer:(jobject)peer asSeparator: (NSNumber *) asSeparator; +- (id) initWithPeer:(jobject)peer asSeparator: (BOOL) asSeparator; - (void) setIsCheckbox; // Events
--- a/src/macosx/native/sun/awt/CMenuItem.m Fri Jan 13 17:09:28 2017 +0000 +++ b/src/macosx/native/sun/awt/CMenuItem.m Mon Jan 23 16:30:43 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -39,11 +39,11 @@ @implementation CMenuItem -- (id) initWithPeer:(jobject)peer asSeparator: (NSNumber *) asSeparator{ +- (id) initWithPeer:(jobject)peer asSeparator: (BOOL) asSeparator{ AWT_ASSERT_APPKIT_THREAD; self = [super initWithPeer:peer]; if (self) { - if ([asSeparator boolValue]) { + if (asSeparator) { fMenuItem = (NSMenuItem*)[NSMenuItem separatorItem]; [fMenuItem retain]; } else { @@ -199,12 +199,9 @@ }]; } -- (void)cleanup { +- (void)dealloc { [fMenuItem setAction:NULL]; [fMenuItem setTarget:nil]; -} - -- (void)dealloc { [fMenuItem release]; fMenuItem = nil; @@ -223,14 +220,6 @@ fIsCheckbox = YES; } -- (void) _createMenuItem_OnAppKitThread: (NSMutableArray *)argValue { - jobject cPeerObjGlobal = (jobject)[[argValue objectAtIndex: 0] pointerValue]; - NSNumber * asSeparator = (NSNumber *)[argValue objectAtIndex: 1]; - CMenuItem *aCMenuItem = [self initWithPeer: cPeerObjGlobal asSeparator: asSeparator]; - [argValue removeAllObjects]; - [argValue addObject: aCMenuItem]; -} - - (NSString *)description { return [NSString stringWithFormat:@"CMenuItem[ %@ ]", fMenuItem]; } @@ -392,24 +381,18 @@ (JNIEnv *env, jobject peer, jlong parentCMenuObj, jboolean isSeparator) { - CMenuItem *aCMenuItem = nil; + __block CMenuItem *aCMenuItem = nil; + BOOL asSeparator = (isSeparator == JNI_TRUE) ? YES: NO; CMenu *parentCMenu = (CMenu *)jlong_to_ptr(parentCMenuObj); JNF_COCOA_ENTER(env); jobject cPeerObjGlobal = (*env)->NewGlobalRef(env, peer); - NSMutableArray *args = nil; - - // Create a new item.... - if (isSeparator == JNI_TRUE) { - args = [[NSMutableArray alloc] initWithObjects:[NSValue valueWithBytes:&cPeerObjGlobal objCType:@encode(jobject)], [NSNumber numberWithBool:YES], nil]; - } else { - args = [[NSMutableArray alloc] initWithObjects:[NSValue valueWithBytes:&cPeerObjGlobal objCType:@encode(jobject)], [NSNumber numberWithBool:NO], nil]; - } - - [ThreadUtilities performOnMainThread:@selector(_createMenuItem_OnAppKitThread:) on:[CMenuItem alloc] withObject:args waitUntilDone:YES]; - - aCMenuItem = (CMenuItem *)[args objectAtIndex: 0]; + [ThreadUtilities performOnMainThreadWaiting:YES block:^(){ + aCMenuItem = [[CMenuItem alloc] initWithPeer: cPeerObjGlobal + asSeparator: asSeparator]; + // the CMenuItem is released in CMenuComponent.dispose() + }]; if (aCMenuItem == nil) { return 0L; @@ -420,11 +403,6 @@ // setLabel will be called after creation completes. - if (aCMenuItem) { - CFRetain(aCMenuItem); // GC - [aCMenuItem release]; - } - JNF_COCOA_EXIT(env); return ptr_to_jlong(aCMenuItem); }
--- a/src/macosx/native/sun/awt/CPopupMenu.m Fri Jan 13 17:09:28 2017 +0000 +++ b/src/macosx/native/sun/awt/CPopupMenu.m Mon Jan 23 16:30:43 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -66,8 +66,6 @@ [ThreadUtilities performOnMainThreadWaiting:YES block:^(){ aCPopupMenu = [[CPopupMenu alloc] initWithPeer:cPeerObjGlobal]; - CFRetain(aCPopupMenu); - [aCPopupMenu release]; }]; JNF_COCOA_EXIT(env);
--- a/src/macosx/native/sun/awt/CPrinterJob.m Fri Jan 13 17:09:28 2017 +0000 +++ b/src/macosx/native/sun/awt/CPrinterJob.m Mon Jan 23 16:30:43 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -469,8 +469,6 @@ // safety is assured by the java side of this call. NSPrintInfo* printInfo = createDefaultNSPrintInfo(env, NULL); - if (printInfo) CFRetain(printInfo); // GC - [printInfo release]; result = ptr_to_jlong(printInfo); @@ -490,7 +488,7 @@ if (nsPrintInfo != -1) { NSPrintInfo* printInfo = (NSPrintInfo*)jlong_to_ptr(nsPrintInfo); - if (printInfo) CFRelease(printInfo); // GC + [printInfo release]; } JNF_COCOA_EXIT(env); }
--- a/src/macosx/native/sun/awt/CSystemColors.m Fri Jan 13 17:09:28 2017 +0000 +++ b/src/macosx/native/sun/awt/CSystemColors.m Mon Jan 23 16:30:43 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -75,7 +75,7 @@ sColors = (NSColor**)malloc(sizeof(NSColor*) * java_awt_SystemColor_NUM_COLORS); } else { for (i = 0; i < java_awt_SystemColor_NUM_COLORS; i++) { - if (sColors[i] != NULL) CFRelease(sColors[i]); // GC + if (sColors[i] != NULL) [sColors[i] release]; } } @@ -108,14 +108,14 @@ sColors[java_awt_SystemColor_INFO_TEXT] = [NSColor textColor]; for (i = 0; i < java_awt_SystemColor_NUM_COLORS; i++) { - if (sColors[i] != NULL) CFRetain(sColors[i]); // GC + [sColors[i] retain]; } if (appleColors == nil) { appleColors = (NSColor**)malloc(sizeof(NSColor*) * sun_lwawt_macosx_LWCToolkit_NUM_APPLE_COLORS); } else { for (i = 0; i < sun_lwawt_macosx_LWCToolkit_NUM_APPLE_COLORS; i++) { - if (appleColors[i] != NULL) CFRelease(appleColors[i]); // GC + if (appleColors[i] != NULL) [appleColors[i] release]; } } @@ -124,7 +124,7 @@ appleColors[sun_lwawt_macosx_LWCToolkit_INACTIVE_SELECTION_FOREGROUND_COLOR] = [NSColor controlDarkShadowColor]; for (i = 0; i < sun_lwawt_macosx_LWCToolkit_NUM_APPLE_COLORS; i++) { - if (appleColors[i] != NULL) CFRetain(appleColors[i]); // GC + [appleColors[i] retain]; } }
--- a/src/macosx/native/sun/awt/CTrayIcon.m Fri Jan 13 17:09:28 2017 +0000 +++ b/src/macosx/native/sun/awt/CTrayIcon.m Mon Jan 23 16:30:43 2017 +0000 @@ -136,7 +136,7 @@ clickCount = [event clickCount]; static JNF_CLASS_CACHE(jc_NSEvent, "sun/lwawt/macosx/NSEvent"); - static JNF_CTOR_CACHE(jctor_NSEvent, jc_NSEvent, "(IIIIIIIIDD)V"); + static JNF_CTOR_CACHE(jctor_NSEvent, jc_NSEvent, "(IIIIIIIIDDI)V"); jobject jEvent = JNFNewObject(env, jctor_NSEvent, [event type], [event modifierFlags], @@ -145,7 +145,8 @@ (jint)localPoint.x, (jint)localPoint.y, (jint)absP.x, (jint)absP.y, [event deltaY], - [event deltaX]); + [event deltaX], + [AWTToolkit scrollStateWithEvent: event]); if (jEvent == nil) { // Unable to create event by some reason. return;
--- a/src/macosx/native/sun/awt/ImageSurfaceData.m Fri Jan 13 17:09:28 2017 +0000 +++ b/src/macosx/native/sun/awt/ImageSurfaceData.m Mon Jan 23 16:30:43 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -1497,7 +1497,7 @@ } if (isdo->nsRef) { - CFRelease(isdo->nsRef); // GC + [isdo->nsRef release]; isdo->nsRef = nil; }
--- a/src/macosx/native/sun/awt/JavaAccessibilityAction.m Fri Jan 13 17:09:28 2017 +0000 +++ b/src/macosx/native/sun/awt/JavaAccessibilityAction.m Mon Jan 23 16:30:43 2017 +0000 @@ -55,19 +55,6 @@ [super dealloc]; } -- (void)finalize -{ - JNIEnv *env = [ThreadUtilities getJNIEnvUncached]; - - JNFDeleteWeakGlobalRef(env, fAccessibleAction); - fAccessibleAction = NULL; - - JNFDeleteWeakGlobalRef(env, fComponent); - fComponent = NULL; - - [super finalize]; -} - - (NSString *)getDescription { @@ -127,19 +114,6 @@ [super dealloc]; } -- (void)finalize -{ - JNIEnv *env = [ThreadUtilities getJNIEnvUncached]; - - JNFDeleteWeakGlobalRef(env, fTabGroup); - fTabGroup = NULL; - - JNFDeleteWeakGlobalRef(env, fComponent); - fComponent = NULL; - - [super finalize]; -} - - (NSString *)getDescription { return @"click";
--- a/src/macosx/native/sun/awt/JavaComponentAccessibility.m Fri Jan 13 17:09:28 2017 +0000 +++ b/src/macosx/native/sun/awt/JavaComponentAccessibility.m Mon Jan 23 16:30:43 2017 +0000 @@ -194,20 +194,6 @@ [super dealloc]; } -- (void)finalize -{ - [self unregisterFromCocoaAXSystem]; - - JNIEnv *env = [ThreadUtilities getJNIEnvUncached]; - - (*env)->DeleteWeakGlobalRef(env, fAccessible); - fAccessible = NULL; - - (*env)->DeleteWeakGlobalRef(env, fComponent); - fComponent = NULL; - - [super finalize]; -} - (void)postValueChanged { @@ -371,8 +357,8 @@ // must init freshly -alloc'd object [newChild initWithParent:parent withEnv:env withAccessible:jCAX withIndex:index withView:view withJavaRole:javaRole]; // must init new instance - // must hard CFRetain() pointer poked into Java object - CFRetain(newChild); + // must hard retain pointer poked into Java object + [newChild retain]; JNFSetLongField(env, jCAX, jf_ptr, ptr_to_jlong(newChild)); (*env)->DeleteLocalRef(env, jCAX); @@ -1498,18 +1484,6 @@ [super dealloc]; } -- (void)finalize -{ - JNIEnv *env = [ThreadUtilities getJNIEnvUncached]; - - if (fTabGroupAxContext != NULL) { - JNFDeleteWeakGlobalRef(env, fTabGroupAxContext); - fTabGroupAxContext = NULL; - } - - [super finalize]; -} - - (id)accessibilityValueAttribute { JNIEnv *env = [ThreadUtilities getJNIEnv];
--- a/src/macosx/native/sun/awt/LWCToolkit.h Fri Jan 13 17:09:28 2017 +0000 +++ b/src/macosx/native/sun/awt/LWCToolkit.h Mon Jan 23 16:30:43 2017 +0000 @@ -40,6 +40,7 @@ @interface AWTToolkit : NSObject { } + (long) getEventCount; + (void) eventCountPlusPlus; ++ (jint) scrollStateWithEvent: (NSEvent*) event; @end /*
--- a/src/macosx/native/sun/awt/LWCToolkit.m Fri Jan 13 17:09:28 2017 +0000 +++ b/src/macosx/native/sun/awt/LWCToolkit.m Mon Jan 23 16:30:43 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -39,6 +39,13 @@ #import "sizecalc.h" +// SCROLL PHASE STATE +#define SCROLL_PHASE_UNSUPPORTED 1 +#define SCROLL_PHASE_BEGAN 2 +#define SCROLL_PHASE_CONTINUED 3 +#define SCROLL_PHASE_CANCELLED 4 +#define SCROLL_PHASE_ENDED 5 + int gNumberOfButtons; jint* gButtonDownMasks; @@ -54,6 +61,23 @@ eventCount++; } ++ (jint) scrollStateWithEvent: (NSEvent*) event { + + if ([event type] != NSScrollWheel) { + return 0; + } + + NSEventPhase phase = [event phase]; + NSEventPhase momentumPhase = [event momentumPhase]; + + if (!phase && !momentumPhase) return SCROLL_PHASE_UNSUPPORTED; + switch (phase) { + case NSEventPhaseBegan: return SCROLL_PHASE_BEGAN; + case NSEventPhaseCancelled: return SCROLL_PHASE_CANCELLED; + case NSEventPhaseEnded: return SCROLL_PHASE_ENDED; + } + return SCROLL_PHASE_CONTINUED; +} @end @@ -249,17 +273,15 @@ { AWT_ASSERT_APPKIT_THREAD; - AWTRunLoopObject *o = nil; + jlong result; +JNF_COCOA_ENTER(env); // We double retain because this object is owned by both main thread and "other" thread // We release in both doAWTRunLoop and stopAWTRunLoop - o = [[AWTRunLoopObject alloc] init]; - if (o) { - CFRetain(o); // GC - CFRetain(o); // GC - [o release]; - } - return ptr_to_jlong(o); + result = ptr_to_jlong([[[AWTRunLoopObject alloc] init] retain]); +JNF_COCOA_EXIT(env); + + return result; } /* @@ -296,10 +318,7 @@ } } - - - CFRelease(mediatorObject); - + [mediatorObject release]; JNF_COCOA_EXIT(env); } @@ -317,7 +336,7 @@ [ThreadUtilities performOnMainThread:@selector(endRunLoop) on:mediatorObject withObject:nil waitUntilDone:NO]; - CFRelease(mediatorObject); + [mediatorObject release]; JNF_COCOA_EXIT(env); }
--- a/src/macosx/native/sun/awt/PrintModel.m Fri Jan 13 17:09:28 2017 +0000 +++ b/src/macosx/native/sun/awt/PrintModel.m Mon Jan 23 16:30:43 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -48,7 +48,6 @@ [super dealloc]; } -//- (void)finalize { [super finalize]; } - (BOOL)runPageSetup { __block BOOL fResult = NO; @@ -86,8 +85,8 @@ fResult = [self safePrintLoop:printerView withEnv:env]; } else { // Retain these so they don't go away while we're in Java - CFRetain(self); // GC - if (printerView) CFRetain(printerView); // GC + [self retain]; + [printerView retain]; static JNF_CLASS_CACHE(jc_CPrinterJob, "sun/lwawt/macosx/CPrinterJob"); static JNF_STATIC_MEMBER_CACHE(jm_detachPrintLoop, jc_CPrinterJob, "detachPrintLoop", "(JJ)V"); @@ -134,8 +133,8 @@ [model safePrintLoop:arg withEnv:env]; // These are to match the retains in runPrintLoopWithView: - if (model) CFRelease(model); // GC - if (arg) CFRelease(arg); // GC + [model release]; + [arg release]; JNF_COCOA_EXIT(env); }
--- a/src/macosx/native/sun/osxapp/NSApplicationAWT.m Fri Jan 13 17:09:28 2017 +0000 +++ b/src/macosx/native/sun/osxapp/NSApplicationAWT.m Mon Jan 23 16:30:43 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 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 @@ -71,7 +71,6 @@ [super dealloc]; } -//- (void)finalize { [super finalize]; } - (void)finishLaunching {
--- a/src/share/classes/com/sun/imageio/plugins/png/PNGImageReader.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/classes/com/sun/imageio/plugins/png/PNGImageReader.java Mon Jan 23 16:30:43 2017 +0000 @@ -729,7 +729,11 @@ parse_iCCP_chunk(chunkLength); break; case iTXt_TYPE: - parse_iTXt_chunk(chunkLength); + if (ignoreMetadata) { + stream.skipBytes(chunkLength); + } else { + parse_iTXt_chunk(chunkLength); + } break; case pHYs_TYPE: parse_pHYs_chunk(); @@ -753,7 +757,11 @@ parse_tRNS_chunk(chunkLength); break; case zTXt_TYPE: - parse_zTXt_chunk(chunkLength); + if (ignoreMetadata) { + stream.skipBytes(chunkLength); + } else { + parse_zTXt_chunk(chunkLength); + } break; default: // Read an unknown chunk
--- a/src/share/classes/com/sun/jndi/cosnaming/CNBindingEnumeration.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/classes/com/sun/jndi/cosnaming/CNBindingEnumeration.java Mon Jan 23 16:30:43 2017 +0000 @@ -33,6 +33,8 @@ import org.omg.CosNaming.*; +import com.sun.jndi.toolkit.corba.CorbaUtils; + /** * Implements the JNDI NamingEnumeration interface for COS * Naming. Gets hold of a list of bindings from the COS Naming Server @@ -212,7 +214,10 @@ Name cname = CNNameParser.cosNameToName(bndg.binding_name); try { + // Check whether object factory codebase is trusted + if (CorbaUtils.isObjectFactoryTrusted(obj)) { obj = NamingManager.getObjectInstance(obj, cname, _ctx, _env); + } } catch (NamingException e) { throw e; } catch (Exception e) {
--- a/src/share/classes/com/sun/jndi/cosnaming/CNCtx.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/classes/com/sun/jndi/cosnaming/CNCtx.java Mon Jan 23 16:30:43 2017 +0000 @@ -36,6 +36,8 @@ import java.io.InputStreamReader; import java.io.BufferedReader; import java.io.IOException; +import java.security.AccessController; +import java.security.PrivilegedAction; import org.omg.CosNaming.*; import org.omg.CosNaming.NamingContextPackage.*; @@ -82,6 +84,19 @@ private static final String FED_PROP = "com.sun.jndi.cosnaming.federation"; boolean federation = false; + /** + * Determines whether classes may be loaded from an arbitrary URL code base. + */ + public static final boolean trustURLCodebase; + static { + // System property to control whether classes may be loaded from an + // arbitrary URL code base + PrivilegedAction<String> act = () -> System.getProperty( + "com.sun.jndi.cosnaming.object.trustURLCodebase", "false"); + String trust = AccessController.doPrivileged(act); + trustURLCodebase = "true".equalsIgnoreCase(trust); + } + // Reference counter for tracking _orb references OrbReuseTracker orbTracker = null; int enumCount; @@ -534,12 +549,16 @@ if (name.size() == 0 ) return this; // %%% should clone() so that env can be changed NameComponent[] path = CNNameParser.nameToCosName(name); + java.lang.Object answer = null; try { - java.lang.Object answer = callResolve(path); - + answer = callResolve(path); try { - return NamingManager.getObjectInstance(answer, name, this, _env); + // Check whether object factory codebase is trusted + if (CorbaUtils.isObjectFactoryTrusted(answer)) { + answer = NamingManager.getObjectInstance( + answer, name, this, _env); + } } catch (NamingException e) { throw e; } catch (Exception e) { @@ -552,6 +571,7 @@ javax.naming.Context cctx = getContinuationContext(cpe); return cctx.lookup(cpe.getRemainingName()); } + return answer; } /**
--- a/src/share/classes/com/sun/jndi/cosnaming/ExceptionMapper.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/classes/com/sun/jndi/cosnaming/ExceptionMapper.java Mon Jan 23 16:30:43 2017 +0000 @@ -33,6 +33,8 @@ import org.omg.CosNaming.NamingContextPackage.*; import org.omg.CORBA.*; +import com.sun.jndi.toolkit.corba.CorbaUtils; + /** * A convenience class to map the COS Naming exceptions to the JNDI exceptions. * @author Raj Krishnamurthy @@ -202,10 +204,13 @@ // Not a context, use object factory to transform object. Name cname = CNNameParser.cosNameToName(resolvedName); - java.lang.Object resolvedObj2; + java.lang.Object resolvedObj2 = null; try { + // Check whether object factory codebase is trusted + if (CorbaUtils.isObjectFactoryTrusted(resolvedObj)) { resolvedObj2 = NamingManager.getObjectInstance(resolvedObj, cname, ctx, ctx._env); + } } catch (NamingException ge) { throw ge; } catch (Exception ge) {
--- a/src/share/classes/com/sun/jndi/rmi/registry/RegistryContext.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/classes/com/sun/jndi/rmi/registry/RegistryContext.java Mon Jan 23 16:30:43 2017 +0000 @@ -32,6 +32,8 @@ import java.rmi.server.*; import java.rmi.registry.Registry; import java.rmi.registry.LocateRegistry; +import java.security.AccessController; +import java.security.PrivilegedAction; import javax.naming.*; import javax.naming.spi.NamingManager; @@ -52,6 +54,18 @@ private int port; private static final NameParser nameParser = new AtomicNameParser(); private static final String SOCKET_FACTORY = "com.sun.jndi.rmi.factory.socket"; + /** + * Determines whether classes may be loaded from an arbitrary URL code base. + */ + static final boolean trustURLCodebase; + static { + // System property to control whether classes may be loaded from an + // arbitrary URL codebase + PrivilegedAction<String> act = () -> System.getProperty( + "com.sun.jndi.rmi.object.trustURLCodebase", "false"); + String trust = AccessController.doPrivileged(act); + trustURLCodebase = "true".equalsIgnoreCase(trust); + } Reference reference = null; // ref used to create this context, if any @@ -461,6 +475,27 @@ Object obj = (r instanceof RemoteReference) ? ((RemoteReference)r).getReference() : (Object)r; + + /* + * Classes may only be loaded from an arbitrary URL codebase when + * the system property com.sun.jndi.rmi.object.trustURLCodebase + * has been set to "true". + */ + + // Use reference if possible + Reference ref = null; + if (obj instanceof Reference) { + ref = (Reference) obj; + } else if (obj instanceof Referenceable) { + ref = ((Referenceable)(obj)).getReference(); + } + + if (ref != null && ref.getFactoryClassLocation() != null && + !trustURLCodebase) { + throw new ConfigurationException( + "The object factory is untrusted. Set the system property" + + " 'com.sun.jndi.rmi.object.trustURLCodebase' to 'true'."); + } return NamingManager.getObjectInstance(obj, name, this, environment); } catch (NamingException e) {
--- a/src/share/classes/com/sun/jndi/toolkit/corba/CorbaUtils.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/classes/com/sun/jndi/toolkit/corba/CorbaUtils.java Mon Jan 23 16:30:43 2017 +0000 @@ -36,8 +36,9 @@ import org.omg.CORBA.ORB; -import javax.naming.Context; -import javax.naming.ConfigurationException; +import javax.naming.*; + +import com.sun.jndi.cosnaming.CNCtx; /** * Contains utilities for performing CORBA-related tasks: @@ -204,6 +205,32 @@ } /** + * Check whether object factory code base is trusted. + * Classes may only be loaded from an arbitrary URL code base when + * the system property com.sun.jndi.rmi.object.trustURLCodebase + * has been set to "true". + */ + public static boolean isObjectFactoryTrusted(Object obj) + throws NamingException { + + // Extract Reference, if possible + Reference ref = null; + if (obj instanceof Reference) { + ref = (Reference) obj; + } else if (obj instanceof Referenceable) { + ref = ((Referenceable)(obj)).getReference(); + } + + if (ref != null && ref.getFactoryClassLocation() != null && + !CNCtx.trustURLCodebase) { + throw new ConfigurationException( + "The object factory is untrusted. Set the system property" + + " 'com.sun.jndi.cosnaming.object.trustURLCodebase' to 'true'."); + } + return true; + } + + /** * This method returns a new ORB instance for the given applet * without creating a static dependency on java.applet. */
--- a/src/share/classes/com/sun/security/auth/module/LdapLoginModule.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/classes/com/sun/security/auth/module/LdapLoginModule.java Mon Jan 23 16:30:43 2017 +0000 @@ -426,7 +426,6 @@ constraints = new SearchControls(); constraints.setSearchScope(SearchControls.SUBTREE_SCOPE); constraints.setReturningAttributes(new String[0]); //return no attrs - constraints.setReturningObjFlag(true); // to get the full DN } authzIdentity = (String)options.get(AUTHZ_IDENTITY); @@ -886,11 +885,7 @@ // (Use the first entry if more than one is returned) if (results.hasMore()) { SearchResult entry = results.next(); - - // %%% - use the SearchResult.getNameInNamespace method - // available in JDK 1.5 and later. - // (can remove call to constraints.setReturningObjFlag) - userDN = ((Context)entry.getObject()).getNameInNamespace(); + userDN = entry.getNameInNamespace(); if (debug) { System.out.println("\t\t[LdapLoginModule] found entry: " +
--- a/src/share/classes/java/awt/MenuComponent.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/classes/java/awt/MenuComponent.java Mon Jan 23 16:30:43 2017 +0000 @@ -145,6 +145,10 @@ public Font getFont_NoClientCode(MenuComponent menuComp) { return menuComp.getFont_NoClientCode(); } + @SuppressWarnings("unchecked") + public <T extends MenuComponentPeer> T getPeer(MenuComponent menuComp) { + return (T) menuComp.peer; + } }); }
--- a/src/share/classes/java/io/ObjectInputStream.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/classes/java/io/ObjectInputStream.java Mon Jan 23 16:30:43 2017 +0000 @@ -37,13 +37,18 @@ import java.security.PrivilegedExceptionAction; import java.util.Arrays; import java.util.HashMap; +import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; + import static java.io.ObjectStreamClass.processQueue; + +import sun.misc.ObjectInputFilter; import sun.misc.ObjectStreamClassValidator; import sun.misc.SharedSecrets; -import sun.misc.Unsafe; import sun.reflect.misc.ReflectUtil; +import sun.misc.JavaOISAccess; +import sun.util.logging.PlatformLogger; /** * An ObjectInputStream deserializes primitive data and objects previously @@ -239,12 +244,48 @@ new ReferenceQueue<>(); } + static { + /* Setup access so sun.misc can invoke package private functions. */ + sun.misc.SharedSecrets.setJavaOISAccess(new JavaOISAccess() { + public void setObjectInputFilter(ObjectInputStream stream, ObjectInputFilter filter) { + stream.setInternalObjectInputFilter(filter); + } + + public ObjectInputFilter getObjectInputFilter(ObjectInputStream stream) { + return stream.getInternalObjectInputFilter(); + } + }); + } + + /* + * Separate class to defer initialization of logging until needed. + */ + private static class Logging { + + /* + * Logger for ObjectInputFilter results. + * Setup the filter logger if it is set to INFO or WARNING. + * (Assuming it will not change). + */ + private static final PlatformLogger traceLogger; + private static final PlatformLogger infoLogger; + static { + PlatformLogger filterLog = PlatformLogger.getLogger("java.io.serialization"); + infoLogger = (filterLog != null && + filterLog.isLoggable(PlatformLogger.Level.INFO)) ? filterLog : null; + traceLogger = (filterLog != null && + filterLog.isLoggable(PlatformLogger.Level.FINER)) ? filterLog : null; + } + } + /** filter stream for handling block data conversion */ private final BlockDataInputStream bin; /** validation callback list */ private final ValidationList vlist; /** recursion depth */ - private int depth; + private long depth; + /** Total number of references to any type of object, class, enum, proxy, etc. */ + private long totalObjectRefs; /** whether stream is closed */ private boolean closed; @@ -271,6 +312,12 @@ private SerialCallbackContext curContext; /** + * Filter of class descriptors and classes read from the stream; + * may be null. + */ + private ObjectInputFilter serialFilter; + + /** * Creates an ObjectInputStream that reads from the specified InputStream. * A serialization stream header is read from the stream and verified. * This constructor will block until the corresponding ObjectOutputStream @@ -297,6 +344,7 @@ bin = new BlockDataInputStream(in); handles = new HandleTable(10); vlist = new ValidationList(); + serialFilter = ObjectInputFilter.Config.getSerialFilter(); enableOverride = false; readStreamHeader(); bin.setBlockDataMode(true); @@ -327,6 +375,7 @@ bin = null; handles = null; vlist = null; + serialFilter = ObjectInputFilter.Config.getSerialFilter(); enableOverride = true; } @@ -334,7 +383,7 @@ * Read an object from the ObjectInputStream. The class of the object, the * signature of the class, and the values of the non-transient and * non-static fields of the class and all of its supertypes are read. - * Default deserializing for a class can be overriden using the writeObject + * Default deserializing for a class can be overridden using the writeObject * and readObject methods. Objects referenced by this object are read * transitively so that a complete equivalent graph of objects is * reconstructed by readObject. @@ -1076,6 +1125,138 @@ } /** + * Returns the serialization filter for this stream. + * The serialization filter is the most recent filter set in + * {@link #setInternalObjectInputFilter setInternalObjectInputFilter} or + * the initial process-wide filter from + * {@link ObjectInputFilter.Config#getSerialFilter() ObjectInputFilter.Config.getSerialFilter}. + * + * @return the serialization filter for the stream; may be null + */ + private final ObjectInputFilter getInternalObjectInputFilter() { + return serialFilter; + } + + /** + * Set the serialization filter for the stream. + * The filter's {@link ObjectInputFilter#checkInput checkInput} method is called + * for each class and reference in the stream. + * The filter can check any or all of the class, the array length, the number + * of references, the depth of the graph, and the size of the input stream. + * <p> + * If the filter returns {@link ObjectInputFilter.Status#REJECTED Status.REJECTED}, + * {@code null} or throws a {@link RuntimeException}, + * the active {@code readObject} or {@code readUnshared} + * throws {@link InvalidClassException}, otherwise deserialization + * continues uninterrupted. + * <p> + * The serialization filter is initialized to the value of + * {@link ObjectInputFilter.Config#getSerialFilter() ObjectInputFilter.Config.getSerialFilter} + * when the {@code ObjectInputStream} is constructed and can be set + * to a custom filter only once. + * + * @implSpec + * The filter, when not {@code null}, is invoked during {@link #readObject readObject} + * and {@link #readUnshared readUnshared} for each object + * (regular or class) in the stream including the following: + * <ul> + * <li>each object reference previously deserialized from the stream + * (class is {@code null}, arrayLength is -1), + * <li>each regular class (class is not {@code null}, arrayLength is -1), + * <li>each interface of a dynamic proxy and the dynamic proxy class itself + * (class is not {@code null}, arrayLength is -1), + * <li>each array is filtered using the array type and length of the array + * (class is the array type, arrayLength is the requested length), + * <li>each object replaced by its class' {@code readResolve} method + * is filtered using the replacement object's class, if not {@code null}, + * and if it is an array, the arrayLength, otherwise -1, + * <li>and each object replaced by {@link #resolveObject resolveObject} + * is filtered using the replacement object's class, if not {@code null}, + * and if it is an array, the arrayLength, otherwise -1. + * </ul> + * + * When the {@link ObjectInputFilter#checkInput checkInput} method is invoked + * it is given access to the current class, the array length, + * the current number of references already read from the stream, + * the depth of nested calls to {@link #readObject readObject} or + * {@link #readUnshared readUnshared}, + * and the implementation dependent number of bytes consumed from the input stream. + * <p> + * Each call to {@link #readObject readObject} or + * {@link #readUnshared readUnshared} increases the depth by 1 + * before reading an object and decreases by 1 before returning + * normally or exceptionally. + * The depth starts at {@code 1} and increases for each nested object and + * decrements when each nested call returns. + * The count of references in the stream starts at {@code 1} and + * is increased before reading an object. + * + * @param filter the filter, may be null + * @throws SecurityException if there is security manager and the + * {@code SerializablePermission("serialFilter")} is not granted + * @throws IllegalStateException if the {@linkplain #getInternalObjectInputFilter() current filter} + * is not {@code null} and is not the process-wide filter + */ + private final void setInternalObjectInputFilter(ObjectInputFilter filter) { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + sm.checkPermission(new SerializablePermission("serialFilter")); + } + // Allow replacement of the process-wide filter if not already set + if (serialFilter != null && + serialFilter != ObjectInputFilter.Config.getSerialFilter()) { + throw new IllegalStateException("filter can not be set more than once"); + } + this.serialFilter = filter; + } + + /** + * Invoke the serialization filter if non-null. + * If the filter rejects or an exception is thrown, throws InvalidClassException. + * + * @param clazz the class; may be null + * @param arrayLength the array length requested; use {@code -1} if not creating an array + * @throws InvalidClassException if it rejected by the filter or + * a {@link RuntimeException} is thrown + */ + private void filterCheck(Class<?> clazz, int arrayLength) + throws InvalidClassException { + if (serialFilter != null) { + RuntimeException ex = null; + ObjectInputFilter.Status status; + try { + status = serialFilter.checkInput(new FilterValues(clazz, arrayLength, + totalObjectRefs, depth, bin.getBytesRead())); + } catch (RuntimeException e) { + // Preventive interception of an exception to log + status = ObjectInputFilter.Status.REJECTED; + ex = e; + } + if (status == null || + status == ObjectInputFilter.Status.REJECTED) { + // Debug logging of filter checks that fail + if (Logging.infoLogger != null) { + Logging.infoLogger.info( + "ObjectInputFilter {0}: {1}, array length: {2}, nRefs: {3}, depth: {4}, bytes: {5}, ex: {6}", + status, clazz, arrayLength, totalObjectRefs, depth, bin.getBytesRead(), + Objects.toString(ex, "n/a")); + } + InvalidClassException ice = new InvalidClassException("filter status: " + status); + ice.initCause(ex); + throw ice; + } else { + // Trace logging for those that succeed + if (Logging.traceLogger != null) { + Logging.traceLogger.finer( + "ObjectInputFilter {0}: {1}, array length: {2}, nRefs: {3}, depth: {4}, bytes: {5}, ex: {6}", + status, clazz, arrayLength, totalObjectRefs, depth, bin.getBytesRead(), + Objects.toString(ex, "n/a")); + } + } + } + } + + /** * Provide access to the persistent fields read from the input stream. */ public static abstract class GetField { @@ -1324,6 +1505,7 @@ } depth++; + totalObjectRefs++; try { switch (tc) { case TC_NULL: @@ -1400,6 +1582,15 @@ } Object rep = resolveObject(obj); if (rep != obj) { + // The type of the original object has been filtered but resolveObject + // may have replaced it; filter the replacement's type + if (rep != null) { + if (rep.getClass().isArray()) { + filterCheck(rep.getClass(), Array.getLength(rep)); + } else { + filterCheck(rep.getClass(), -1); + } + } handles.setObject(passHandle, rep); } return rep; @@ -1470,6 +1661,7 @@ throw new InvalidObjectException( "cannot read back reference to unshared object"); } + filterCheck(null, -1); // just a check for number of references, depth, no class return obj; } @@ -1574,6 +1766,10 @@ ReflectUtil.checkProxyPackageAccess( getClass().getClassLoader(), cl.getInterfaces()); + // Filter the interfaces + for (Class<?> clazz : cl.getInterfaces()) { + filterCheck(clazz, -1); + } } } catch (ClassNotFoundException ex) { resolveEx = ex; @@ -1582,6 +1778,9 @@ desc.initProxy(cl, resolveEx, readClassDesc(false)); + // Call filterCheck on the definition + filterCheck(desc.forClass(), -1); + handles.finish(descHandle); passHandle = descHandle; return desc; @@ -1629,8 +1828,12 @@ desc.initNonProxy(readDesc, cl, resolveEx, readClassDesc(false)); + // Call filterCheck on the definition + filterCheck(desc.forClass(), -1); + handles.finish(descHandle); passHandle = descHandle; + return desc; } @@ -1671,6 +1874,8 @@ ObjectStreamClass desc = readClassDesc(false); int len = bin.readInt(); + filterCheck(desc.forClass(), len); + Object array = null; Class<?> cl, ccl = null; if ((cl = desc.forClass()) != null) { @@ -1819,6 +2024,14 @@ rep = cloneArray(rep); } if (rep != obj) { + // Filter the replacement object + if (rep != null) { + if (rep.getClass().isArray()) { + filterCheck(rep.getClass(), Array.getLength(rep)); + } else { + filterCheck(rep.getClass(), -1); + } + } handles.setObject(passHandle, obj = rep); } } @@ -2009,22 +2222,22 @@ desc.setPrimFieldValues(obj, primVals); } - int objHandle = passHandle; - ObjectStreamField[] fields = desc.getFields(false); + int objHandle = passHandle; + ObjectStreamField[] fields = desc.getFields(false); Object[] objVals = new Object[desc.getNumObjFields()]; - int numPrimFields = fields.length - objVals.length; - for (int i = 0; i < objVals.length; i++) { - ObjectStreamField f = fields[numPrimFields + i]; - objVals[i] = readObject0(f.isUnshared()); - if (f.getField() != null) { - handles.markDependency(objHandle, passHandle); - } + int numPrimFields = fields.length - objVals.length; + for (int i = 0; i < objVals.length; i++) { + ObjectStreamField f = fields[numPrimFields + i]; + objVals[i] = readObject0(f.isUnshared()); + if (f.getField() != null) { + handles.markDependency(objHandle, passHandle); } + } if (obj != null) { desc.setObjFieldValues(obj, objVals); } - passHandle = objHandle; - } + passHandle = objHandle; + } /** * Reads in and returns IOException that caused serialization to abort. @@ -2297,6 +2510,51 @@ } /** + * Hold a snapshot of values to be passed to an ObjectInputFilter. + */ + static class FilterValues implements ObjectInputFilter.FilterInfo { + final Class<?> clazz; + final long arrayLength; + final long totalObjectRefs; + final long depth; + final long streamBytes; + + public FilterValues(Class<?> clazz, long arrayLength, long totalObjectRefs, + long depth, long streamBytes) { + this.clazz = clazz; + this.arrayLength = arrayLength; + this.totalObjectRefs = totalObjectRefs; + this.depth = depth; + this.streamBytes = streamBytes; + } + + @Override + public Class<?> serialClass() { + return clazz; + } + + @Override + public long arrayLength() { + return arrayLength; + } + + @Override + public long references() { + return totalObjectRefs; + } + + @Override + public long depth() { + return depth; + } + + @Override + public long streamBytes() { + return streamBytes; + } + } + + /** * Input stream supporting single-byte peek operations. */ private static class PeekInputStream extends InputStream { @@ -2305,6 +2563,8 @@ private final InputStream in; /** peeked byte */ private int peekb = -1; + /** total bytes read from the stream */ + private long totalBytesRead = 0; /** * Creates new PeekInputStream on top of given underlying stream. @@ -2318,7 +2578,12 @@ * that it does not consume the read value. */ int peek() throws IOException { - return (peekb >= 0) ? peekb : (peekb = in.read()); + if (peekb >= 0) { + return peekb; + } + peekb = in.read(); + totalBytesRead += peekb >= 0 ? 1 : 0; + return peekb; } public int read() throws IOException { @@ -2327,21 +2592,27 @@ peekb = -1; return v; } else { - return in.read(); + int nbytes = in.read(); + totalBytesRead += nbytes >= 0 ? 1 : 0; + return nbytes; } } public int read(byte[] b, int off, int len) throws IOException { + int nbytes; if (len == 0) { return 0; } else if (peekb < 0) { - return in.read(b, off, len); + nbytes = in.read(b, off, len); + totalBytesRead += nbytes >= 0 ? nbytes : 0; + return nbytes; } else { b[off++] = (byte) peekb; len--; peekb = -1; - int n = in.read(b, off, len); - return (n >= 0) ? (n + 1) : 1; + nbytes = in.read(b, off, len); + totalBytesRead += nbytes >= 0 ? nbytes : 0; + return (nbytes >= 0) ? (nbytes + 1) : 1; } } @@ -2366,7 +2637,9 @@ skipped++; n--; } - return skipped + skip(n); + n = skipped + in.skip(n); + totalBytesRead += n; + return n; } public int available() throws IOException { @@ -2376,6 +2649,10 @@ public void close() throws IOException { in.close(); } + + public long getBytesRead() { + return totalBytesRead; + } } /** @@ -3231,6 +3508,14 @@ throw new UTFDataFormatException(); } } + + /** + * Returns the number of bytes read from the input stream. + * @return the number of bytes read from the input stream + */ + long getBytesRead() { + return in.getBytesRead(); + } } /**
--- a/src/share/classes/java/lang/invoke/MethodHandles.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/classes/java/lang/invoke/MethodHandles.java Mon Jan 23 16:30:43 2017 +0000 @@ -680,7 +680,9 @@ // disallow lookup more restricted packages if (allowedModes == ALL_MODES && lookupClass.getClassLoader() == null) { if (name.startsWith("java.") || - (name.startsWith("sun.") && !name.startsWith("sun.invoke."))) { + (name.startsWith("sun.") + && !name.startsWith("sun.invoke.") + && !name.equals("sun.reflect.ReflectionFactory"))) { throw newIllegalArgumentException("illegal lookupClass: " + lookupClass); } }
--- a/src/share/classes/java/net/SocketInputStream.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/classes/java/net/SocketInputStream.java Mon Jan 23 16:30:43 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 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 @@ -155,11 +155,12 @@ } // bounds check - if (length <= 0 || off < 0 || off + length > b.length) { + if (length <= 0 || off < 0 || length > b.length - off) { if (length == 0) { return 0; } - throw new ArrayIndexOutOfBoundsException(); + throw new ArrayIndexOutOfBoundsException("length == " + length + + " off == " + off + " buffer length == " + b.length); } boolean gotReset = false;
--- a/src/share/classes/java/net/SocketOutputStream.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/classes/java/net/SocketOutputStream.java Mon Jan 23 16:30:43 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 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 @@ -97,11 +97,13 @@ */ private void socketWrite(byte b[], int off, int len) throws IOException { - if (len <= 0 || off < 0 || off + len > b.length) { + + if (len <= 0 || off < 0 || len > b.length - off) { if (len == 0) { return; } - throw new ArrayIndexOutOfBoundsException(); + throw new ArrayIndexOutOfBoundsException("len == " + len + + " off == " + off + " buffer length == " + b.length); } FileDescriptor fd = impl.acquireFD();
--- a/src/share/classes/java/net/URL.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/classes/java/net/URL.java Mon Jan 23 16:30:43 2017 +0000 @@ -1364,9 +1364,6 @@ path = file; } - if (port == -1) { - port = 0; - } // Set the object fields. this.protocol = protocol; this.host = host;
--- a/src/share/classes/java/net/URLClassLoader.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/classes/java/net/URLClassLoader.java Mon Jan 23 16:30:43 2017 +0000 @@ -103,8 +103,8 @@ if (security != null) { security.checkCreateClassLoader(); } - ucp = new URLClassPath(urls); this.acc = AccessController.getContext(); + ucp = new URLClassPath(urls, acc); } URLClassLoader(URL[] urls, ClassLoader parent, @@ -115,8 +115,8 @@ if (security != null) { security.checkCreateClassLoader(); } - ucp = new URLClassPath(urls); this.acc = acc; + ucp = new URLClassPath(urls, acc); } /** @@ -147,8 +147,8 @@ if (security != null) { security.checkCreateClassLoader(); } - ucp = new URLClassPath(urls); this.acc = AccessController.getContext(); + ucp = new URLClassPath(urls, acc); } URLClassLoader(URL[] urls, AccessControlContext acc) { @@ -158,8 +158,8 @@ if (security != null) { security.checkCreateClassLoader(); } - ucp = new URLClassPath(urls); this.acc = acc; + ucp = new URLClassPath(urls, acc); } /** @@ -191,8 +191,8 @@ if (security != null) { security.checkCreateClassLoader(); } - ucp = new URLClassPath(urls, factory); acc = AccessController.getContext(); + ucp = new URLClassPath(urls, factory, acc); } /* A map (used as a set) to keep track of closeable local resources
--- a/src/share/classes/java/net/URLStreamHandler.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/classes/java/net/URLStreamHandler.java Mon Jan 23 16:30:43 2017 +0000 @@ -161,9 +161,9 @@ (spec.charAt(start + 1) == '/')) { start += 2; i = spec.indexOf('/', start); - if (i < 0) { + if (i < 0 || i > limit) { i = spec.indexOf('?', start); - if (i < 0) + if (i < 0 || i > limit) i = limit; } @@ -171,8 +171,14 @@ int ind = authority.indexOf('@'); if (ind != -1) { - userInfo = authority.substring(0, ind); - host = authority.substring(ind+1); + if (ind != authority.lastIndexOf('@')) { + // more than one '@' in authority. This is not server based + userInfo = null; + host = null; + } else { + userInfo = authority.substring(0, ind); + host = authority.substring(ind+1); + } } else { userInfo = null; }
--- a/src/share/classes/java/rmi/MarshalledObject.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/classes/java/rmi/MarshalledObject.java Mon Jan 23 16:30:43 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -34,9 +34,14 @@ import java.io.ObjectStreamConstants; import java.io.OutputStream; import java.io.Serializable; +import java.security.AccessController; +import java.security.PrivilegedAction; + import sun.rmi.server.MarshalInputStream; import sun.rmi.server.MarshalOutputStream; +import sun.misc.ObjectInputFilter; + /** * A <code>MarshalledObject</code> contains a byte stream with the serialized * representation of an object given to its constructor. The <code>get</code> @@ -90,6 +95,9 @@ */ private int hash; + /** Filter used when creating the instance from a stream; may be null. */ + private transient ObjectInputFilter objectInputFilter = null; + /** Indicate compatibility with 1.2 version of class. */ private static final long serialVersionUID = 8988374069173025854L; @@ -133,6 +141,20 @@ } /** + * Reads in the state of the object and saves the stream's + * serialization filter to be used when the object is deserialized. + * + * @param stream the stream + * @throws IOException if an I/O error occurs + * @throws ClassNotFoundException if a class cannot be found + */ + private void readObject(ObjectInputStream stream) + throws IOException, ClassNotFoundException { + stream.defaultReadObject(); // read in all fields + objectInputFilter = ObjectInputFilter.Config.getObjectInputFilter(stream); + } + + /** * Returns a new copy of the contained marshalledobject. The internal * representation is deserialized with the semantics used for * unmarshaling parameters for RMI calls. @@ -155,7 +177,7 @@ ByteArrayInputStream lin = (locBytes == null ? null : new ByteArrayInputStream(locBytes)); MarshalledObjectInputStream in = - new MarshalledObjectInputStream(bin, lin); + new MarshalledObjectInputStream(bin, lin, objectInputFilter); @SuppressWarnings("unchecked") T obj = (T) in.readObject(); in.close(); @@ -295,11 +317,24 @@ * <code>null</code>, then all annotations will be * <code>null</code>. */ - MarshalledObjectInputStream(InputStream objIn, InputStream locIn) + MarshalledObjectInputStream(InputStream objIn, InputStream locIn, + ObjectInputFilter filter) throws IOException { super(objIn); this.locIn = (locIn == null ? null : new ObjectInputStream(locIn)); + if (filter != null) { + AccessController.doPrivileged(new PrivilegedAction<Void>() { + @Override + public Void run() { + ObjectInputFilter.Config.setObjectInputFilter(MarshalledObjectInputStream.this, filter); + if (MarshalledObjectInputStream.this.locIn != null) { + ObjectInputFilter.Config.setObjectInputFilter(MarshalledObjectInputStream.this.locIn, filter); + } + return null; + } + }); + } } /**
--- a/src/share/classes/java/time/format/ZoneName.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/classes/java/time/format/ZoneName.java Mon Jan 23 16:30:43 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -25,11 +25,8 @@ package java.time.format; import java.util.HashMap; -import java.util.HashSet; import java.util.Locale; import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; /** * A helper class to map a zone name to metazone and back to the @@ -335,6 +332,7 @@ "America/Eirunepe", "Amazon", "America/Manaus", "Africa/Nairobi", "Africa_Eastern", "Africa/Nairobi", "Asia/Yakutsk", "Yakutsk", "Asia/Yakutsk", + "Asia/Yangon", "Myanmar", "Asia/Rangoon", "America/Goose_Bay", "Atlantic", "America/Halifax", "Africa/Maseru", "Africa_Southern", "Africa/Johannesburg", "America/Swift_Current", "America_Central", "America/Chicago", @@ -770,6 +768,7 @@ "America/Indianapolis", "America/Indiana/Indianapolis", "Europe/Belfast", "Europe/London", "America/Kralendijk", "America/Curacao", + "Asia/Rangoon", "Asia/Yangon", }; private static final Map<String, String> zidToMzone = new HashMap<>();
--- a/src/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java Mon Jan 23 16:30:43 2017 +0000 @@ -40,6 +40,7 @@ import java.security.AccessController; import java.security.PrivilegedActionException; import java.security.PrivilegedExceptionAction; +import java.util.Objects; import java.util.function.IntBinaryOperator; import java.util.function.IntUnaryOperator; import sun.reflect.CallerSensitive; @@ -410,7 +411,17 @@ if (!Modifier.isVolatile(modifiers)) throw new IllegalArgumentException("Must be volatile type"); - this.cclass = (Modifier.isProtected(modifiers)) ? caller : tclass; + // Access to protected field members is restricted to receivers only + // of the accessing class, or one of its subclasses, and the + // accessing class must in turn be a subclass (or package sibling) + // of the protected member's defining class. + // If the updater refers to a protected field of a declaring class + // outside the current package, the receiver argument will be + // narrowed to the type of the accessing class. + this.cclass = (Modifier.isProtected(modifiers) && + tclass.isAssignableFrom(caller) && + !isSamePackage(tclass, caller)) + ? caller : tclass; this.tclass = tclass; this.offset = U.objectFieldOffset(field); } @@ -432,6 +443,21 @@ } /** + * Returns true if the two classes have the same class loader and + * package qualifier + */ + private static boolean isSamePackage(Class<?> class1, Class<?> class2) { + return class1.getClassLoader() == class2.getClassLoader() + && Objects.equals(getPackageName(class1), getPackageName(class2)); + } + + private static String getPackageName(Class<?> cls) { + String cn = cls.getName(); + int dot = cn.lastIndexOf('.'); + return (dot != -1) ? cn.substring(0, dot) : ""; + } + + /** * Checks that target argument is instance of cclass. On * failure, throws cause. */
--- a/src/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java Mon Jan 23 16:30:43 2017 +0000 @@ -40,6 +40,7 @@ import java.security.AccessController; import java.security.PrivilegedActionException; import java.security.PrivilegedExceptionAction; +import java.util.Objects; import java.util.function.LongBinaryOperator; import java.util.function.LongUnaryOperator; import sun.reflect.CallerSensitive; @@ -408,7 +409,17 @@ if (!Modifier.isVolatile(modifiers)) throw new IllegalArgumentException("Must be volatile type"); - this.cclass = (Modifier.isProtected(modifiers)) ? caller : tclass; + // Access to protected field members is restricted to receivers only + // of the accessing class, or one of its subclasses, and the + // accessing class must in turn be a subclass (or package sibling) + // of the protected member's defining class. + // If the updater refers to a protected field of a declaring class + // outside the current package, the receiver argument will be + // narrowed to the type of the accessing class. + this.cclass = (Modifier.isProtected(modifiers) && + tclass.isAssignableFrom(caller) && + !isSamePackage(tclass, caller)) + ? caller : tclass; this.tclass = tclass; this.offset = U.objectFieldOffset(field); } @@ -539,7 +550,17 @@ if (!Modifier.isVolatile(modifiers)) throw new IllegalArgumentException("Must be volatile type"); - this.cclass = (Modifier.isProtected(modifiers)) ? caller : tclass; + // Access to protected field members is restricted to receivers only + // of the accessing class, or one of its subclasses, and the + // accessing class must in turn be a subclass (or package sibling) + // of the protected member's defining class. + // If the updater refers to a protected field of a declaring class + // outside the current package, the receiver argument will be + // narrowed to the type of the accessing class. + this.cclass = (Modifier.isProtected(modifiers) && + tclass.isAssignableFrom(caller) && + !isSamePackage(tclass, caller)) + ? caller : tclass; this.tclass = tclass; this.offset = U.objectFieldOffset(field); } @@ -620,4 +641,19 @@ } while (acl != null); return false; } + + /** + * Returns true if the two classes have the same class loader and + * package qualifier + */ + private static boolean isSamePackage(Class<?> class1, Class<?> class2) { + return class1.getClassLoader() == class2.getClassLoader() + && Objects.equals(getPackageName(class1), getPackageName(class2)); } + + private static String getPackageName(Class<?> cls) { + String cn = cls.getName(); + int dot = cn.lastIndexOf('.'); + return (dot != -1) ? cn.substring(0, dot) : ""; + } +}
--- a/src/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java Mon Jan 23 16:30:43 2017 +0000 @@ -40,6 +40,7 @@ import java.security.AccessController; import java.security.PrivilegedActionException; import java.security.PrivilegedExceptionAction; +import java.util.Objects; import java.util.function.BinaryOperator; import java.util.function.UnaryOperator; import sun.reflect.CallerSensitive; @@ -346,7 +347,17 @@ if (!Modifier.isVolatile(modifiers)) throw new IllegalArgumentException("Must be volatile type"); - this.cclass = (Modifier.isProtected(modifiers)) ? caller : tclass; + // Access to protected field members is restricted to receivers only + // of the accessing class, or one of its subclasses, and the + // accessing class must in turn be a subclass (or package sibling) + // of the protected member's defining class. + // If the updater refers to a protected field of a declaring class + // outside the current package, the receiver argument will be + // narrowed to the type of the accessing class. + this.cclass = (Modifier.isProtected(modifiers) && + tclass.isAssignableFrom(caller) && + !isSamePackage(tclass, caller)) + ? caller : tclass; this.tclass = tclass; this.vclass = vclass; this.offset = U.objectFieldOffset(field); @@ -369,6 +380,21 @@ } /** + * Returns true if the two classes have the same class loader and + * package qualifier + */ + private static boolean isSamePackage(Class<?> class1, Class<?> class2) { + return class1.getClassLoader() == class2.getClassLoader() + && Objects.equals(getPackageName(class1), getPackageName(class2)); + } + + private static String getPackageName(Class<?> cls) { + String cn = cls.getName(); + int dot = cn.lastIndexOf('.'); + return (dot != -1) ? cn.substring(0, dot) : ""; + } + + /** * Checks that target argument is instance of cclass. On * failure, throws cause. */
--- a/src/share/classes/java/util/logging/Level.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/classes/java/util/logging/Level.java Mon Jan 23 16:30:43 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -599,11 +599,14 @@ if (list != null) { for (KnownLevel level : list) { Level other = level.mirroredLevel; + Class<? extends Level> type = level.levelObject.getClass(); if (l.value == other.value && (l.resourceBundleName == other.resourceBundleName || (l.resourceBundleName != null && l.resourceBundleName.equals(other.resourceBundleName)))) { - return level; + if (type == l.getClass()) { + return level; + } } } }
--- a/src/share/classes/java/util/logging/LogRecord.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/classes/java/util/logging/LogRecord.java Mon Jan 23 16:30:43 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -502,13 +502,21 @@ throw new IOException("LogRecord: bad version: " + major + "." + minor); } int len = in.readInt(); - if (len == -1) { + if (len < -1) { + throw new NegativeArraySizeException(); + } else if (len == -1) { parameters = null; - } else { + } else if (len < 255) { parameters = new Object[len]; for (int i = 0; i < parameters.length; i++) { parameters[i] = in.readObject(); } + } else { + List<Object> params = new ArrayList<>(Math.min(len, 1024)); + for (int i = 0; i < len; i++) { + params.add(in.readObject()); + } + parameters = params.toArray(new Object[params.size()]); } // If necessary, try to regenerate the resource bundle. if (resourceBundleName != null) {
--- a/src/share/classes/javax/management/remote/rmi/RMIConnectionImpl.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/classes/javax/management/remote/rmi/RMIConnectionImpl.java Mon Jan 23 16:30:43 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -349,7 +349,7 @@ +", unwrapping parameters using classLoaderWithRepository."); values = - nullIsEmpty(unwrap(params, classLoaderWithRepository, Object[].class)); + nullIsEmpty(unwrap(params, classLoaderWithRepository, Object[].class,delegationSubject)); try { final Object params2[] = @@ -413,7 +413,7 @@ values = nullIsEmpty(unwrap(params, getClassLoader(loaderName), defaultClassLoader, - Object[].class)); + Object[].class,delegationSubject)); try { final Object params2[] = @@ -524,7 +524,7 @@ "connectionId=" + connectionId +" unwrapping query with defaultClassLoader."); - queryValue = unwrap(query, defaultContextClassLoader, QueryExp.class); + queryValue = unwrap(query, defaultContextClassLoader, QueryExp.class, delegationSubject); try { final Object params[] = new Object[] { name, queryValue }; @@ -559,7 +559,7 @@ "connectionId=" + connectionId +" unwrapping query with defaultClassLoader."); - queryValue = unwrap(query, defaultContextClassLoader, QueryExp.class); + queryValue = unwrap(query, defaultContextClassLoader, QueryExp.class, delegationSubject); try { final Object params[] = new Object[] { name, queryValue }; @@ -709,7 +709,7 @@ attr = unwrap(attribute, getClassLoaderFor(name), defaultClassLoader, - Attribute.class); + Attribute.class, delegationSubject); try { final Object params[] = new Object[] { name, attr }; @@ -760,7 +760,7 @@ unwrap(attributes, getClassLoaderFor(name), defaultClassLoader, - AttributeList.class); + AttributeList.class, delegationSubject); try { final Object params[] = new Object[] { name, attrlist }; @@ -812,7 +812,7 @@ values = nullIsEmpty(unwrap(params, getClassLoaderFor(name), defaultClassLoader, - Object[].class)); + Object[].class, delegationSubject)); try { final Object params2[] = @@ -992,7 +992,7 @@ filterValues[i] = unwrap(filters[i], targetCl, defaultClassLoader, - NotificationFilter.class); + NotificationFilter.class, sbjs[i]); if (debug) logger.debug("addNotificationListener"+ "(ObjectName,NotificationFilter)", @@ -1060,7 +1060,7 @@ +" unwrapping filter with target extended ClassLoader."); filterValue = - unwrap(filter, targetCl, defaultClassLoader, NotificationFilter.class); + unwrap(filter, targetCl, defaultClassLoader, NotificationFilter.class, delegationSubject); if (debug) logger.debug("addNotificationListener"+ "(ObjectName,ObjectName,NotificationFilter,Object)", @@ -1068,7 +1068,7 @@ +" unwrapping handback with target extended ClassLoader."); handbackValue = - unwrap(handback, targetCl, defaultClassLoader, Object.class); + unwrap(handback, targetCl, defaultClassLoader, Object.class, delegationSubject); try { final Object params[] = @@ -1199,7 +1199,7 @@ +" unwrapping filter with target extended ClassLoader."); filterValue = - unwrap(filter, targetCl, defaultClassLoader, NotificationFilter.class); + unwrap(filter, targetCl, defaultClassLoader, NotificationFilter.class, delegationSubject); if (debug) logger.debug("removeNotificationListener"+ "(ObjectName,ObjectName,NotificationFilter,Object)", @@ -1207,7 +1207,7 @@ +" unwrapping handback with target extended ClassLoader."); handbackValue = - unwrap(handback, targetCl, defaultClassLoader, Object.class); + unwrap(handback, targetCl, defaultClassLoader, Object.class, delegationSubject); try { final Object params[] = @@ -1551,20 +1551,38 @@ } } - private static <T> T unwrap(final MarshalledObject<?> mo, + private <T> T unwrap(final MarshalledObject<?> mo, final ClassLoader cl, - final Class<T> wrappedClass) + final Class<T> wrappedClass, + Subject delegationSubject) throws IOException { if (mo == null) { return null; } try { final ClassLoader old = AccessController.doPrivileged(new SetCcl(cl)); - try { - return wrappedClass.cast(mo.get()); - } catch (ClassNotFoundException cnfe) { - throw new UnmarshalException(cnfe.toString(), cnfe); - } finally { + try{ + final AccessControlContext reqACC; + if (delegationSubject == null) + reqACC = acc; + else { + if (subject == null) { + final String msg = + "Subject delegation cannot be enabled unless " + + "an authenticated subject is put in place"; + throw new SecurityException(msg); + } + reqACC = subjectDelegator.delegatedContext( + acc, delegationSubject, removeCallerContext); + } + if(reqACC != null){ + return AccessController.doPrivileged( + (PrivilegedExceptionAction<T>) () -> + wrappedClass.cast(mo.get()), reqACC); + }else{ + return wrappedClass.cast(mo.get()); + } + }finally{ AccessController.doPrivileged(new SetCcl(old)); } } catch (PrivilegedActionException pe) { @@ -1577,14 +1595,19 @@ } logger.warning("unwrap", "Failed to unmarshall object: " + e); logger.debug("unwrap", e); + }catch (ClassNotFoundException ex) { + logger.warning("unwrap", "Failed to unmarshall object: " + ex); + logger.debug("unwrap", ex); + throw new UnmarshalException(ex.toString(), ex); } return null; } - private static <T> T unwrap(final MarshalledObject<?> mo, + private <T> T unwrap(final MarshalledObject<?> mo, final ClassLoader cl1, final ClassLoader cl2, - final Class<T> wrappedClass) + final Class<T> wrappedClass, + Subject delegationSubject) throws IOException { if (mo == null) { return null; @@ -1598,7 +1621,7 @@ } } ); - return unwrap(mo, orderCL, wrappedClass); + return unwrap(mo, orderCL, wrappedClass,delegationSubject); } catch (PrivilegedActionException pe) { Exception e = extractException(pe); if (e instanceof IOException) {
--- a/src/share/classes/org/jcp/xml/dsig/internal/dom/ApacheTransform.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/classes/org/jcp/xml/dsig/internal/dom/ApacheTransform.java Mon Jan 23 16:30:43 2017 +0000 @@ -21,7 +21,7 @@ * under the License. */ /* - * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. */ /* * $Id: ApacheTransform.java 1333869 2012-05-04 10:42:44Z coheigea $ @@ -38,7 +38,6 @@ import com.sun.org.apache.xml.internal.security.signature.XMLSignatureInput; import com.sun.org.apache.xml.internal.security.transforms.Transform; -import com.sun.org.apache.xml.internal.security.transforms.Transforms; import javax.xml.crypto.*; import javax.xml.crypto.dom.DOMCryptoContext; @@ -150,7 +149,7 @@ if (Utils.secureValidation(xc)) { String algorithm = getAlgorithm(); - if (Transforms.TRANSFORM_XSLT.equals(algorithm)) { + if (Policy.restrictAlg(algorithm)) { throw new TransformException( "Transform " + algorithm + " is forbidden when secure validation is enabled" );
--- a/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMManifest.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMManifest.java Mon Jan 23 16:30:43 2017 +0000 @@ -21,7 +21,7 @@ * under the License. */ /* - * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. */ /* * $Id: DOMManifest.java 1333415 2012-05-03 12:03:51Z coheigea $ @@ -113,9 +113,10 @@ localName + ", expected Reference"); } refs.add(new DOMReference(refElem, context, provider)); - if (secVal && (refs.size() > DOMSignedInfo.MAXIMUM_REFERENCE_COUNT)) { - String error = "A maxiumum of " + DOMSignedInfo.MAXIMUM_REFERENCE_COUNT + " " - + "references per Manifest are allowed with secure validation"; + if (secVal && Policy.restrictNumReferences(refs.size())) { + String error = "A maximum of " + Policy.maxReferences() + + " references per Manifest are allowed when" + + " secure validation is enabled"; throw new MarshalException(error); } refElem = DOMUtils.getNextSiblingElement(refElem);
--- a/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMReference.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMReference.java Mon Jan 23 16:30:43 2017 +0000 @@ -21,7 +21,7 @@ * under the License. */ /* - * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. */ /* * =========================================================================== @@ -51,7 +51,6 @@ import org.w3c.dom.Node; import org.jcp.xml.dsig.internal.DigesterOutputStream; -import com.sun.org.apache.xml.internal.security.algorithms.MessageDigestAlgorithm; import com.sun.org.apache.xml.internal.security.exceptions.Base64DecodingException; import com.sun.org.apache.xml.internal.security.signature.XMLSignatureInput; import com.sun.org.apache.xml.internal.security.utils.Base64; @@ -67,11 +66,6 @@ implements Reference, DOMURIReference { /** - * The maximum number of transforms per reference, if secure validation is enabled. - */ - public static final int MAXIMUM_TRANSFORM_COUNT = 5; - - /** * Look up useC14N11 system property. If true, an explicit C14N11 transform * will be added if necessary when generating the signature. See section * 3.1.1 of http://www.w3.org/2007/xmlsec/Drafts/xmldsig-core/ for more info. @@ -217,9 +211,10 @@ } transforms.add (new DOMTransform(transformElem, context, provider)); - if (secVal && (transforms.size() > MAXIMUM_TRANSFORM_COUNT)) { - String error = "A maxiumum of " + MAXIMUM_TRANSFORM_COUNT + " " - + "transforms per Reference are allowed with secure validation"; + if (secVal && Policy.restrictNumTransforms(transforms.size())) { + String error = "A maximum of " + Policy.maxTransforms() + + " transforms per Reference are allowed when" + + " secure validation is enabled"; throw new MarshalException(error); } transformElem = DOMUtils.getNextSiblingElement(transformElem); @@ -236,10 +231,10 @@ Element dmElem = nextSibling; this.digestMethod = DOMDigestMethod.unmarshal(dmElem); String digestMethodAlgorithm = this.digestMethod.getAlgorithm(); - if (secVal - && MessageDigestAlgorithm.ALGO_ID_DIGEST_NOT_RECOMMENDED_MD5.equals(digestMethodAlgorithm)) { + if (secVal && Policy.restrictAlg(digestMethodAlgorithm)) { throw new MarshalException( - "It is forbidden to use algorithm " + digestMethod + " when secure validation is enabled" + "It is forbidden to use algorithm " + digestMethodAlgorithm + + " when secure validation is enabled" ); }
--- a/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMRetrievalMethod.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMRetrievalMethod.java Mon Jan 23 16:30:43 2017 +0000 @@ -21,7 +21,7 @@ * under the License. */ /* - * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. */ /* * =========================================================================== @@ -154,9 +154,10 @@ } transforms.add (new DOMTransform(transformElem, context, provider)); - if (secVal && (transforms.size() > DOMReference.MAXIMUM_TRANSFORM_COUNT)) { - String error = "A maxiumum of " + DOMReference.MAXIMUM_TRANSFORM_COUNT + " " - + "transforms per Reference are allowed with secure validation"; + if (secVal && Policy.restrictNumTransforms(transforms.size())) { + String error = "A maximum of " + Policy.maxTransforms() + + " transforms per Reference are allowed when" + + " secure validation is enabled"; throw new MarshalException(error); } transformElem = DOMUtils.getNextSiblingElement(transformElem); @@ -243,7 +244,8 @@ } // guard against RetrievalMethod loops - if ((data instanceof NodeSetData) && Utils.secureValidation(context)) { + if ((data instanceof NodeSetData) && Utils.secureValidation(context) + && Policy.restrictRetrievalMethodLoops()) { NodeSetData nsd = (NodeSetData)data; Iterator i = nsd.iterator(); if (i.hasNext()) {
--- a/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMSignatureMethod.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMSignatureMethod.java Mon Jan 23 16:30:43 2017 +0000 @@ -21,7 +21,7 @@ * under the License. */ /* - * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. */ /* * $Id: DOMSignatureMethod.java 1333415 2012-05-03 12:03:51Z coheigea $ @@ -41,6 +41,7 @@ import com.sun.org.apache.xml.internal.security.algorithms.implementations.SignatureECDSA; import com.sun.org.apache.xml.internal.security.utils.JavaUtils; import org.jcp.xml.dsig.internal.SignerOutputStream; +import sun.security.util.KeyUtil; /** * DOM-based abstract implementation of SignatureMethod. @@ -162,6 +163,7 @@ if (!(key instanceof PublicKey)) { throw new InvalidKeyException("key must be PublicKey"); } + checkKeySize(context, key); if (signature == null) { try { Provider p = (Provider)context.getProperty @@ -197,6 +199,37 @@ } } + /** + * If secure validation mode is enabled, checks that the key size is + * restricted. + * + * @param context the context + * @param key the key to check + * @throws XMLSignatureException if the key size is restricted + */ + private static void checkKeySize(XMLCryptoContext context, Key key) + throws XMLSignatureException { + if (Utils.secureValidation(context)) { + int size = KeyUtil.getKeySize(key); + if (size == -1) { + // key size cannot be determined, so we cannot check against + // restrictions. Note that a DSA key w/o params will be + // rejected later if the certificate chain is validated. + if (log.isLoggable(java.util.logging.Level.FINE)) { + log.log(java.util.logging.Level.FINE, "Size for " + + key.getAlgorithm() + " key cannot be determined"); + } + return; + } + if (Policy.restrictKey(key.getAlgorithm(), size)) { + throw new XMLSignatureException(key.getAlgorithm() + + " keys less than " + + Policy.minKeySize(key.getAlgorithm()) + " bits are" + + " forbidden when secure validation is enabled"); + } + } + } + byte[] sign(Key key, SignedInfo si, XMLSignContext context) throws InvalidKeyException, XMLSignatureException { @@ -207,6 +240,7 @@ if (!(key instanceof PrivateKey)) { throw new InvalidKeyException("key must be PrivateKey"); } + checkKeySize(context, key); if (signature == null) { try { Provider p = (Provider)context.getProperty
--- a/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMSignedInfo.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMSignedInfo.java Mon Jan 23 16:30:43 2017 +0000 @@ -21,7 +21,7 @@ * under the License. */ /* - * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. */ /* * $Id: DOMSignedInfo.java 1333415 2012-05-03 12:03:51Z coheigea $ @@ -45,7 +45,6 @@ import org.w3c.dom.Node; import com.sun.org.apache.xml.internal.security.utils.Base64; -import com.sun.org.apache.xml.internal.security.utils.Constants; import com.sun.org.apache.xml.internal.security.utils.UnsyncBufferedOutputStream; /** @@ -55,22 +54,9 @@ */ public final class DOMSignedInfo extends DOMStructure implements SignedInfo { - /** - * The maximum number of references per Manifest, if secure validation is enabled. - */ - public static final int MAXIMUM_REFERENCE_COUNT = 30; - private static java.util.logging.Logger log = java.util.logging.Logger.getLogger("org.jcp.xml.dsig.internal.dom"); - /** Signature - NOT Recommended RSAwithMD5 */ - private static final String ALGO_ID_SIGNATURE_NOT_RECOMMENDED_RSA_MD5 = - Constants.MoreAlgorithmsSpecNS + "rsa-md5"; - - /** HMAC - NOT Recommended HMAC-MD5 */ - private static final String ALGO_ID_MAC_HMAC_NOT_RECOMMENDED_MD5 = - Constants.MoreAlgorithmsSpecNS + "hmac-md5"; - private List<Reference> references; private CanonicalizationMethod canonicalizationMethod; private SignatureMethod signatureMethod; @@ -163,10 +149,10 @@ boolean secVal = Utils.secureValidation(context); String signatureMethodAlgorithm = signatureMethod.getAlgorithm(); - if (secVal && ((ALGO_ID_MAC_HMAC_NOT_RECOMMENDED_MD5.equals(signatureMethodAlgorithm) - || ALGO_ID_SIGNATURE_NOT_RECOMMENDED_RSA_MD5.equals(signatureMethodAlgorithm)))) { + if (secVal && Policy.restrictAlg(signatureMethodAlgorithm)) { throw new MarshalException( - "It is forbidden to use algorithm " + signatureMethod + " when secure validation is enabled" + "It is forbidden to use algorithm " + signatureMethodAlgorithm + + " when secure validation is enabled" ); } @@ -184,9 +170,10 @@ } refList.add(new DOMReference(refElem, context, provider)); - if (secVal && (refList.size() > MAXIMUM_REFERENCE_COUNT)) { - String error = "A maxiumum of " + MAXIMUM_REFERENCE_COUNT + " " - + "references per Manifest are allowed with secure validation"; + if (secVal && Policy.restrictNumReferences(refList.size())) { + String error = "A maximum of " + Policy.maxReferences() + + " references per Manifest are allowed when" + + " secure validation is enabled"; throw new MarshalException(error); } refElem = DOMUtils.getNextSiblingElement(refElem);
--- a/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMURIDereferencer.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMURIDereferencer.java Mon Jan 23 16:30:43 2017 +0000 @@ -73,6 +73,11 @@ boolean secVal = Utils.secureValidation(context); + if (secVal && Policy.restrictReferenceUriScheme(uri)) { + throw new URIReferenceException( + "Uri " + uri + " is forbidden when secure validation is enabled"); + } + // Check if same-document URI and already registered on the context if (uri != null && uri.length() != 0 && uri.charAt(0) == '#') { String id = uri.substring(1); @@ -83,12 +88,19 @@ id = id.substring(i1+1, i2); } - Node referencedElem = dcc.getElementById(id); + // check if element is registered by Id + Node referencedElem = uriAttr.getOwnerDocument().getElementById(id); + if (referencedElem == null) { + // see if element is registered in DOMCryptoContext + referencedElem = dcc.getElementById(id); + } if (referencedElem != null) { - if (secVal) { + if (secVal && Policy.restrictDuplicateIds()) { Element start = referencedElem.getOwnerDocument().getDocumentElement(); if (!XMLUtils.protectAgainstWrappingAttack(start, (Element)referencedElem, id)) { - String error = "Multiple Elements with the same ID " + id + " were detected"; + String error = "Multiple Elements with the same ID " + + id + " detected when secure validation" + + " is enabled"; throw new URIReferenceException(error); } } @@ -110,9 +122,9 @@ try { ResourceResolver apacheResolver = - ResourceResolver.getInstance(uriAttr, baseURI, secVal); + ResourceResolver.getInstance(uriAttr, baseURI, false); XMLSignatureInput in = apacheResolver.resolve(uriAttr, - baseURI, secVal); + baseURI, false); if (in.isOctetStream()) { return new ApacheOctetStreamData(in); } else {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/org/jcp/xml/dsig/internal/dom/Policy.java Mon Jan 23 16:30:43 2017 +0000 @@ -0,0 +1,196 @@ +/* + * Copyright (c) 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. 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 org.jcp.xml.dsig.internal.dom; + +import java.net.URI; +import java.net.URISyntaxException; +import java.security.AccessController; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.security.Security; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Locale; +import java.util.Map; +import java.util.Set; + +/** + * The secure validation policy as specified by the + * jdk.xml.dsig.secureValidationPolicy security property. + */ +public final class Policy { + + // all restrictions are initialized to be unconstrained + private static Set<URI> disallowedAlgs = new HashSet<>(); + private static int maxTrans = Integer.MAX_VALUE; + private static int maxRefs = Integer.MAX_VALUE; + private static Set<String> disallowedRefUriSchemes = new HashSet<>(); + private static Map<String, Integer> minKeyMap = new HashMap<>(); + private static boolean noDuplicateIds = false; + private static boolean noRMLoops = false; + + static { + try { + initialize(); + } catch (Exception e) { + throw new SecurityException( + "Cannot initialize the secure validation policy", e); + } + } + + private Policy() {} + + private static void initialize() { + String prop = + AccessController.doPrivileged((PrivilegedAction<String>) () -> + Security.getProperty("jdk.xml.dsig.secureValidationPolicy")); + if (prop == null || prop.isEmpty()) { + // no policy specified, so don't enforce any restrictions + return; + } + String[] entries = prop.split(","); + for (String entry : entries) { + String[] tokens = entry.split("\\s"); + String type = tokens[0]; + switch(type) { + case "disallowAlg": + if (tokens.length != 2) { + error(entry); + } + disallowedAlgs.add(URI.create(tokens[1])); + break; + case "maxTransforms": + if (tokens.length != 2) { + error(entry); + } + maxTrans = Integer.parseUnsignedInt(tokens[1]); + break; + case "maxReferences": + if (tokens.length != 2) { + error(entry); + } + maxRefs = Integer.parseUnsignedInt(tokens[1]); + break; + case "disallowReferenceUriSchemes": + if (tokens.length == 1) { + error(entry); + } + for (int i = 1; i < tokens.length; i++) { + String scheme = tokens[i]; + disallowedRefUriSchemes.add( + scheme.toLowerCase(Locale.ROOT)); + } + break; + case "minKeySize": + if (tokens.length != 3) { + error(entry); + } + minKeyMap.put(tokens[1], + Integer.parseUnsignedInt(tokens[2])); + break; + case "noDuplicateIds": + if (tokens.length != 1) { + error(entry); + } + noDuplicateIds = true; + break; + case "noRetrievalMethodLoops": + if (tokens.length != 1) { + error(entry); + } + noRMLoops = true; + break; + default: + error(entry); + } + } + } + + public static boolean restrictAlg(String alg) { + try { + URI uri = new URI(alg); + return disallowedAlgs.contains(uri); + } catch (URISyntaxException use) { + return false; + } + } + + public static boolean restrictNumTransforms(int numTrans) { + return (numTrans > maxTrans); + } + + public static boolean restrictNumReferences(int numRefs) { + return (numRefs > maxRefs); + } + + public static boolean restrictReferenceUriScheme(String uri) { + if (uri != null) { + String scheme = java.net.URI.create(uri).getScheme(); + if (scheme != null) { + return disallowedRefUriSchemes.contains( + scheme.toLowerCase(Locale.ROOT)); + } + } + return false; + } + + public static boolean restrictKey(String type, int size) { + return (size < minKeyMap.getOrDefault(type, 0)); + } + + public static boolean restrictDuplicateIds() { + return noDuplicateIds; + } + + public static boolean restrictRetrievalMethodLoops() { + return noRMLoops; + } + + public static Set<URI> disabledAlgs() { + return Collections.<URI>unmodifiableSet(disallowedAlgs); + } + + public static int maxTransforms() { + return maxTrans; + } + + public static int maxReferences() { + return maxRefs; + } + + public static Set<String> disabledReferenceUriSchemes() { + return Collections.<String>unmodifiableSet(disallowedRefUriSchemes); + } + + public static int minKeySize(String type) { + return minKeyMap.getOrDefault(type, 0); + } + + private static void error(String entry) { + throw new IllegalArgumentException( + "Invalid jdk.xml.dsig.secureValidationPolicy entry: " + entry); + } +}
--- a/src/share/classes/sun/awt/AWTAccessor.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/classes/sun/awt/AWTAccessor.java Mon Jan 23 16:30:43 2017 +0000 @@ -36,6 +36,7 @@ import java.awt.event.KeyEvent; import java.awt.geom.Point2D; import java.awt.peer.ComponentPeer; +import java.awt.peer.MenuComponentPeer; import java.lang.reflect.InvocationTargetException; import java.security.AccessControlContext; @@ -463,6 +464,11 @@ * Gets the font used for this menu component. */ Font getFont_NoClientCode(MenuComponent menuComp); + + /** + * Returns the peer of the menu component. + */ + <T extends MenuComponentPeer> T getPeer(MenuComponent menuComp); } /**
--- a/src/share/classes/sun/misc/JarIndex.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/classes/sun/misc/JarIndex.java Mon Jan 23 16:30:43 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -26,9 +26,11 @@ package sun.misc; import java.io.*; +import java.security.AccessController; import java.util.*; import java.util.jar.*; import java.util.zip.*; +import sun.security.action.GetPropertyAction; /** * This class is used to maintain mappings from packages, classes @@ -72,7 +74,8 @@ * be added to the index. Otherwise, just the directory names are added. */ private static final boolean metaInfFilenames = - "true".equals(System.getProperty("sun.misc.JarIndex.metaInfFilenames")); + "true".equals(AccessController.doPrivileged( + new GetPropertyAction("sun.misc.JarIndex.metaInfFilenames"))); /** * Constructs a new, empty jar index.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/sun/misc/JavaOISAccess.java Mon Jan 23 16:30:43 2017 +0000 @@ -0,0 +1,33 @@ +/* + * Copyright (c) 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. 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.ObjectInputStream; + +public interface JavaOISAccess { + void setObjectInputFilter(ObjectInputStream stream, ObjectInputFilter filter); + ObjectInputFilter getObjectInputFilter(ObjectInputStream stream); +}
--- a/src/share/classes/sun/misc/Launcher.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/classes/sun/misc/Launcher.java Mon Jan 23 16:30:43 2017 +0000 @@ -408,7 +408,7 @@ } else { urls = new URL[0]; } - bcp = new URLClassPath(urls, factory); + bcp = new URLClassPath(urls, factory, null); bcp.initLookupCache(null); } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/sun/misc/ObjectInputFilter.java Mon Jan 23 16:30:43 2017 +0000 @@ -0,0 +1,642 @@ +/* + * Copyright (c) 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. 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.ObjectInputStream; +import java.io.SerializablePermission; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.security.Security; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.function.Function; +import sun.util.logging.PlatformLogger; + +/** + * Filter classes, array lengths, and graph metrics during deserialization. + * If set on an {@link ObjectInputStream}, the {@link #checkInput checkInput(FilterInfo)} + * method is called to validate classes, the length of each array, + * the number of objects being read from the stream, the depth of the graph, + * and the total number of bytes read from the stream. + * <p> + * A filter can be set via {@link ObjectInputStream#setObjectInputFilter setObjectInputFilter} + * for an individual ObjectInputStream. + * A filter can be set via {@link Config#setSerialFilter(ObjectInputFilter) Config.setSerialFilter} + * to affect every {@code ObjectInputStream} that does not otherwise set a filter. + * <p> + * A filter determines whether the arguments are {@link Status#ALLOWED ALLOWED} + * or {@link Status#REJECTED REJECTED} and should return the appropriate status. + * If the filter cannot determine the status it should return + * {@link Status#UNDECIDED UNDECIDED}. + * Filters should be designed for the specific use case and expected types. + * A filter designed for a particular use may be passed a class that is outside + * of the scope of the filter. If the purpose of the filter is to black-list classes + * then it can reject a candidate class that matches and report UNDECIDED for others. + * A filter may be called with class equals {@code null}, {@code arrayLength} equal -1, + * the depth, number of references, and stream size and return a status + * that reflects only one or only some of the values. + * This allows a filter to specific about the choice it is reporting and + * to use other filters without forcing either allowed or rejected status. + * + * <p> + * Typically, a custom filter should check if a process-wide filter + * is configured and defer to it if so. For example, + * <pre>{@code + * ObjectInputFilter.Status checkInput(FilterInfo info) { + * ObjectInputFilter serialFilter = ObjectInputFilter.Config.getSerialFilter(); + * if (serialFilter != null) { + * ObjectInputFilter.Status status = serialFilter.checkInput(info); + * if (status != ObjectInputFilter.Status.UNDECIDED) { + * // The process-wide filter overrides this filter + * return status; + * } + * } + * if (info.serialClass() != null && + * Remote.class.isAssignableFrom(info.serialClass())) { + * return Status.REJECTED; // Do not allow Remote objects + * } + * return Status.UNDECIDED; + * } + *}</pre> + * <p> + * Unless otherwise noted, passing a {@code null} argument to a + * method in this interface and its nested classes will cause a + * {@link NullPointerException} to be thrown. + * + * @since 8u + */ +@FunctionalInterface +public interface ObjectInputFilter { + + /** + * Check the class, array length, number of object references, depth, + * stream size, and other available filtering information. + * Implementations of this method check the contents of the object graph being created + * during deserialization. The filter returns {@link Status#ALLOWED Status.ALLOWED}, + * {@link Status#REJECTED Status.REJECTED}, or {@link Status#UNDECIDED Status.UNDECIDED}. + * + * @param filterInfo provides information about the current object being deserialized, + * if any, and the status of the {@link ObjectInputStream} + * @return {@link Status#ALLOWED Status.ALLOWED} if accepted, + * {@link Status#REJECTED Status.REJECTED} if rejected, + * {@link Status#UNDECIDED Status.UNDECIDED} if undecided. + */ + Status checkInput(FilterInfo filterInfo); + + /** + * FilterInfo provides access to information about the current object + * being deserialized and the status of the {@link ObjectInputStream}. + * @since 9 + */ + interface FilterInfo { + /** + * The class of an object being deserialized. + * For arrays, it is the array type. + * For example, the array class name of a 2 dimensional array of strings is + * "{@code [[Ljava.lang.String;}". + * To check the array's element type, iteratively use + * {@link Class#getComponentType() Class.getComponentType} while the result + * is an array and then check the class. + * The {@code serialClass is null} in the case where a new object is not being + * created and to give the filter a chance to check the depth, number of + * references to existing objects, and the stream size. + * + * @return class of an object being deserialized; may be null + */ + Class<?> serialClass(); + + /** + * The number of array elements when deserializing an array of the class. + * + * @return the non-negative number of array elements when deserializing + * an array of the class, otherwise -1 + */ + long arrayLength(); + + /** + * The current depth. + * The depth starts at {@code 1} and increases for each nested object and + * decrements when each nested object returns. + * + * @return the current depth + */ + long depth(); + + /** + * The current number of object references. + * + * @return the non-negative current number of object references + */ + long references(); + + /** + * The current number of bytes consumed. + * @implSpec {@code streamBytes} is implementation specific + * and may not be directly related to the object in the stream + * that caused the callback. + * + * @return the non-negative current number of bytes consumed + */ + long streamBytes(); + } + + /** + * The status of a check on the class, array length, number of references, + * depth, and stream size. + * + * @since 8u + */ + enum Status { + /** + * The status is undecided, not allowed and not rejected. + */ + UNDECIDED, + /** + * The status is allowed. + */ + ALLOWED, + /** + * The status is rejected. + */ + REJECTED; + } + + /** + * A utility class to set and get the process-wide filter or create a filter + * from a pattern string. If a process-wide filter is set, it will be + * used for each {@link ObjectInputStream} that does not set its own filter. + * <p> + * When setting the filter, it should be stateless and idempotent, + * reporting the same result when passed the same arguments. + * <p> + * The filter is configured using the {@link java.security.Security} + * property {@code jdk.serialFilter} and can be overridden by + * the System property {@code jdk.serialFilter}. + * + * The syntax is the same as for the {@link #createFilter(String) createFilter} method. + * + * @since 8u + */ + final class Config { + /* No instances. */ + private Config() {} + + /** + * Lock object for process-wide filter. + */ + private final static Object serialFilterLock = new Object(); + + /** + * Debug: Logger + */ + private final static PlatformLogger configLog; + + /** + * Logger for debugging. + */ + static void filterLog(PlatformLogger.Level level, String msg, Object... args) { + if (configLog != null) { + if (PlatformLogger.Level.INFO.equals(level)) { + configLog.info(msg, args); + } else if (PlatformLogger.Level.WARNING.equals(level)) { + configLog.warning(msg, args); + } else { + configLog.severe(msg, args); + } + } + } + + /** + * The name for the process-wide deserialization filter. + * Used as a system property and a java.security.Security property. + */ + private final static String SERIAL_FILTER_PROPNAME = "jdk.serialFilter"; + + /** + * The process-wide filter; may be null. + * Lookup the filter in java.security.Security or + * the system property. + */ + private final static ObjectInputFilter configuredFilter; + + static { + configuredFilter = AccessController + .doPrivileged((PrivilegedAction<ObjectInputFilter>) () -> { + String props = System.getProperty(SERIAL_FILTER_PROPNAME); + if (props == null) { + props = Security.getProperty(SERIAL_FILTER_PROPNAME); + } + if (props != null) { + PlatformLogger log = PlatformLogger.getLogger("java.io.serialization"); + log.info("Creating serialization filter from {0}", props); + try { + return createFilter(props); + } catch (RuntimeException re) { + log.warning("Error configuring filter: {0}", re); + } + } + return null; + }); + configLog = (configuredFilter != null) ? PlatformLogger.getLogger("java.io.serialization") : null; + } + + /** + * Current configured filter. + */ + private static ObjectInputFilter serialFilter = configuredFilter; + + /** + * Get the filter for classes being deserialized on the ObjectInputStream. + * + * @param inputStream ObjectInputStream from which to get the filter; non-null + * @throws RuntimeException if the filter rejects + */ + public static ObjectInputFilter getObjectInputFilter(ObjectInputStream inputStream) { + Objects.requireNonNull(inputStream, "inputStream"); + return sun.misc.SharedSecrets.getJavaOISAccess().getObjectInputFilter(inputStream); + } + + /** + * Set the process-wide filter if it has not already been configured or set. + * + * @param inputStream ObjectInputStream on which to set the filter; non-null + * @param filter the serialization filter to set as the process-wide filter; not null + * @throws SecurityException if there is security manager and the + * {@code SerializablePermission("serialFilter")} is not granted + * @throws IllegalStateException if the filter has already been set {@code non-null} + */ + public static void setObjectInputFilter(ObjectInputStream inputStream, + ObjectInputFilter filter) { + Objects.requireNonNull(inputStream, "inputStream"); + sun.misc.SharedSecrets.getJavaOISAccess().setObjectInputFilter(inputStream, filter); + } + + /** + * Returns the process-wide serialization filter or {@code null} if not configured. + * + * @return the process-wide serialization filter or {@code null} if not configured + */ + public static ObjectInputFilter getSerialFilter() { + synchronized (serialFilterLock) { + return serialFilter; + } + } + + /** + * Set the process-wide filter if it has not already been configured or set. + * + * @param filter the serialization filter to set as the process-wide filter; not null + * @throws SecurityException if there is security manager and the + * {@code SerializablePermission("serialFilter")} is not granted + * @throws IllegalStateException if the filter has already been set {@code non-null} + */ + public static void setSerialFilter(ObjectInputFilter filter) { + Objects.requireNonNull(filter, "filter"); + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + sm.checkPermission(new SerializablePermission("serialFilter")); + } + synchronized (serialFilterLock) { + if (serialFilter != null) { + throw new IllegalStateException("Serial filter can only be set once"); + } + serialFilter = filter; + } + } + + /** + * Returns an ObjectInputFilter from a string of patterns. + * <p> + * Patterns are separated by ";" (semicolon). Whitespace is significant and + * is considered part of the pattern. + * If a pattern includes an equals assignment, "{@code =}" it sets a limit. + * If a limit appears more than once the last value is used. + * <ul> + * <li>maxdepth={@code value} - the maximum depth of a graph</li> + * <li>maxrefs={@code value} - the maximum number of internal references</li> + * <li>maxbytes={@code value} - the maximum number of bytes in the input stream</li> + * <li>maxarray={@code value} - the maximum array length allowed</li> + * </ul> + * <p> + * Other patterns match or reject class or package name + * as returned from {@link Class#getName() Class.getName()}. + * Note that for arrays the element type is used in the pattern, + * not the array type. + * <ul> + * <li>If the pattern starts with "!", the class is rejected if the remaining pattern is matched; + * otherwise the class is allowed if the pattern matches. + * <li>If the pattern ends with ".**" it matches any class in the package and all subpackages. + * <li>If the pattern ends with ".*" it matches any class in the package. + * <li>If the pattern ends with "*", it matches any class with the pattern as a prefix. + * <li>If the pattern is equal to the class name, it matches. + * <li>Otherwise, the pattern is not matched. + * </ul> + * <p> + * The resulting filter performs the limit checks and then + * tries to match the class, if any. If any of the limits are exceeded, + * the filter returns {@link Status#REJECTED Status.REJECTED}. + * If the class is an array type, the class to be matched is the element type. + * Arrays of any number of dimensions are treated the same as the element type. + * For example, a pattern of "{@code !example.Foo}", + * rejects creation of any instance or array of {@code example.Foo}. + * The first pattern that matches, working from left to right, determines + * the {@link Status#ALLOWED Status.ALLOWED} + * or {@link Status#REJECTED Status.REJECTED} result. + * If nothing matches, the result is {@link Status#UNDECIDED Status.UNDECIDED}. + * + * @param pattern the pattern string to parse; not null + * @return a filter to check a class being deserialized; may be null; + * {@code null} if no patterns + * @throws IllegalArgumentException + * if a limit is missing the name, or the long value + * is not a number or is negative, + * or if the package is missing for ".*" and ".**" + */ + public static ObjectInputFilter createFilter(String pattern) { + Objects.requireNonNull(pattern, "pattern"); + return Global.createFilter(pattern); + } + + /** + * Implementation of ObjectInputFilter that performs the checks of + * the process-wide serialization filter. If configured, it will be + * used for all ObjectInputStreams that do not set their own filters. + * + */ + final static class Global implements ObjectInputFilter { + /** + * The pattern used to create the filter. + */ + private final String pattern; + /** + * The list of class filters. + */ + private final List<Function<Class<?>, Status>> filters; + /** + * Maximum allowed bytes in the stream. + */ + private long maxStreamBytes; + /** + * Maximum depth of the graph allowed. + */ + private long maxDepth; + /** + * Maximum number of references in a graph. + */ + private long maxReferences; + /** + * Maximum length of any array. + */ + private long maxArrayLength; + + /** + * Returns an ObjectInputFilter from a string of patterns. + * + * @param pattern the pattern string to parse + * @return a filter to check a class being deserialized; not null + * @throws IllegalArgumentException if the parameter is malformed + * if the pattern is missing the name, the long value + * is not a number or is negative. + */ + static ObjectInputFilter createFilter(String pattern) { + Global filter = new Global(pattern); + return filter.isEmpty() ? null : filter; + } + + /** + * Construct a new filter from the pattern String. + * + * @param pattern a pattern string of filters + * @throws IllegalArgumentException if the pattern is malformed + */ + private Global(String pattern) { + this.pattern = pattern; + + maxArrayLength = Long.MAX_VALUE; // Default values are unlimited + maxDepth = Long.MAX_VALUE; + maxReferences = Long.MAX_VALUE; + maxStreamBytes = Long.MAX_VALUE; + + String[] patterns = pattern.split(";"); + filters = new ArrayList<>(patterns.length); + for (int i = 0; i < patterns.length; i++) { + String p = patterns[i]; + int nameLen = p.length(); + if (nameLen == 0) { + continue; + } + if (parseLimit(p)) { + // If the pattern contained a limit setting, i.e. type=value + continue; + } + boolean negate = p.charAt(0) == '!'; + + if (p.indexOf('/') >= 0) { + throw new IllegalArgumentException("invalid character \"/\" in: \"" + pattern + "\""); + } + + if (p.endsWith("*")) { + // Wildcard cases + if (p.endsWith(".*")) { + // Pattern is a package name with a wildcard + final String pkg = p.substring(negate ? 1 : 0, nameLen - 1); + if (pkg.length() < 2) { + throw new IllegalArgumentException("package missing in: \"" + pattern + "\""); + } + if (negate) { + // A Function that fails if the class starts with the pattern, otherwise don't care + filters.add(c -> matchesPackage(c, pkg) ? Status.REJECTED : Status.UNDECIDED); + } else { + // A Function that succeeds if the class starts with the pattern, otherwise don't care + filters.add(c -> matchesPackage(c, pkg) ? Status.ALLOWED : Status.UNDECIDED); + } + } else if (p.endsWith(".**")) { + // Pattern is a package prefix with a double wildcard + final String pkgs = p.substring(negate ? 1 : 0, nameLen - 2); + if (pkgs.length() < 2) { + throw new IllegalArgumentException("package missing in: \"" + pattern + "\""); + } + if (negate) { + // A Function that fails if the class starts with the pattern, otherwise don't care + filters.add(c -> c.getName().startsWith(pkgs) ? Status.REJECTED : Status.UNDECIDED); + } else { + // A Function that succeeds if the class starts with the pattern, otherwise don't care + filters.add(c -> c.getName().startsWith(pkgs) ? Status.ALLOWED : Status.UNDECIDED); + } + } else { + // Pattern is a classname (possibly empty) with a trailing wildcard + final String className = p.substring(negate ? 1 : 0, nameLen - 1); + if (negate) { + // A Function that fails if the class starts with the pattern, otherwise don't care + filters.add(c -> c.getName().startsWith(className) ? Status.REJECTED : Status.UNDECIDED); + } else { + // A Function that succeeds if the class starts with the pattern, otherwise don't care + filters.add(c -> c.getName().startsWith(className) ? Status.ALLOWED : Status.UNDECIDED); + } + } + } else { + final String name = p.substring(negate ? 1 : 0); + if (name.isEmpty()) { + throw new IllegalArgumentException("class or package missing in: \"" + pattern + "\""); + } + // Pattern is a class name + if (negate) { + // A Function that fails if the class equals the pattern, otherwise don't care + filters.add(c -> c.getName().equals(name) ? Status.REJECTED : Status.UNDECIDED); + } else { + // A Function that succeeds if the class equals the pattern, otherwise don't care + filters.add(c -> c.getName().equals(name) ? Status.ALLOWED : Status.UNDECIDED); + } + + } + } + } + + /** + * Returns if this filter has any checks. + * @return {@code true} if the filter has any checks, {@code false} otherwise + */ + private boolean isEmpty() { + return filters.isEmpty() && + maxArrayLength == Long.MAX_VALUE && + maxDepth == Long.MAX_VALUE && + maxReferences == Long.MAX_VALUE && + maxStreamBytes == Long.MAX_VALUE; + } + + /** + * Parse out a limit for one of maxarray, maxdepth, maxbytes, maxreferences. + * + * @param pattern a string with a type name, '=' and a value + * @return {@code true} if a limit was parsed, else {@code false} + * @throws IllegalArgumentException if the pattern is missing + * the name, the Long value is not a number or is negative. + */ + private boolean parseLimit(String pattern) { + int eqNdx = pattern.indexOf('='); + if (eqNdx < 0) { + // not a limit pattern + return false; + } + String valueString = pattern.substring(eqNdx + 1); + if (pattern.startsWith("maxdepth=")) { + maxDepth = parseValue(valueString); + } else if (pattern.startsWith("maxarray=")) { + maxArrayLength = parseValue(valueString); + } else if (pattern.startsWith("maxrefs=")) { + maxReferences = parseValue(valueString); + } else if (pattern.startsWith("maxbytes=")) { + maxStreamBytes = parseValue(valueString); + } else { + throw new IllegalArgumentException("unknown limit: " + pattern.substring(0, eqNdx)); + } + return true; + } + + /** + * Parse the value of a limit and check that it is non-negative. + * @param string inputstring + * @return the parsed value + * @throws IllegalArgumentException if parsing the value fails or the value is negative + */ + private static long parseValue(String string) throws IllegalArgumentException { + // Parse a Long from after the '=' to the end + long value = Long.parseLong(string); + if (value < 0) { + throw new IllegalArgumentException("negative limit: " + string); + } + return value; + } + + /** + * {@inheritDoc} + */ + @Override + public Status checkInput(FilterInfo filterInfo) { + if (filterInfo.references() < 0 + || filterInfo.depth() < 0 + || filterInfo.streamBytes() < 0 + || filterInfo.references() > maxReferences + || filterInfo.depth() > maxDepth + || filterInfo.streamBytes() > maxStreamBytes) { + return Status.REJECTED; + } + + Class<?> clazz = filterInfo.serialClass(); + if (clazz != null) { + if (clazz.isArray()) { + if (filterInfo.arrayLength() >= 0 && filterInfo.arrayLength() > maxArrayLength) { + // array length is too big + return Status.REJECTED; + } + do { + // Arrays are decided based on the component type + clazz = clazz.getComponentType(); + } while (clazz.isArray()); + } + + if (clazz.isPrimitive()) { + // Primitive types are undecided; let someone else decide + return Status.UNDECIDED; + } else { + // Find any filter that allowed or rejected the class + final Class<?> cl = clazz; + Optional<Status> status = filters.stream() + .map(f -> f.apply(cl)) + .filter(p -> p != Status.UNDECIDED) + .findFirst(); + return status.orElse(Status.UNDECIDED); + } + } + return Status.UNDECIDED; + } + + /** + * Returns {@code true} if the class is in the package. + * + * @param c a class + * @param pkg a package name (including the trailing ".") + * @return {@code true} if the class is in the package, + * otherwise {@code false} + */ + private static boolean matchesPackage(Class<?> c, String pkg) { + String n = c.getName(); + return n.startsWith(pkg) && n.lastIndexOf('.') == pkg.length() - 1; + } + + /** + * Returns the pattern used to create this filter. + * @return the pattern used to create this filter + */ + @Override + public String toString() { + return pattern; + } + } + } +}
--- a/src/share/classes/sun/misc/SharedSecrets.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/classes/sun/misc/SharedSecrets.java Mon Jan 23 16:30:43 2017 +0000 @@ -25,6 +25,7 @@ package sun.misc; +import java.io.ObjectInputStream; import java.util.jar.JarFile; import java.io.Console; import java.io.FileDescriptor; @@ -56,6 +57,7 @@ private static JavaSecurityAccess javaSecurityAccess; private static JavaUtilZipFileAccess javaUtilZipFileAccess; private static JavaAWTAccess javaAWTAccess; + private static JavaOISAccess javaOISAccess; private static JavaObjectInputStreamAccess javaObjectInputStreamAccess; public static JavaUtilJarAccess javaUtilJarAccess() { @@ -141,6 +143,18 @@ return javaIOFileDescriptorAccess; } + public static void setJavaOISAccess(JavaOISAccess access) { + javaOISAccess = access; + } + + public static JavaOISAccess getJavaOISAccess() { + if (javaOISAccess == null) + unsafe.ensureClassInitialized(ObjectInputStream.class); + + return javaOISAccess; + } + + public static void setJavaSecurityProtectionDomainAccess (JavaSecurityProtectionDomainAccess jspda) { javaSecurityProtectionDomainAccess = jspda;
--- a/src/share/classes/sun/misc/URLClassPath.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/classes/sun/misc/URLClassPath.java Mon Jan 23 16:30:43 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -44,6 +44,7 @@ import java.net.URLStreamHandler; import java.net.URLStreamHandlerFactory; import java.io.*; +import java.security.AccessControlContext; import java.security.AccessController; import java.security.AccessControlException; import java.security.CodeSigner; @@ -67,6 +68,7 @@ private static final boolean DEBUG; private static final boolean DEBUG_LOOKUP_CACHE; private static final boolean DISABLE_JAR_CHECKING; + private static final boolean DISABLE_ACC_CHECKING; static { JAVA_VERSION = java.security.AccessController.doPrivileged( @@ -78,6 +80,10 @@ String p = java.security.AccessController.doPrivileged( new GetPropertyAction("sun.misc.URLClassPath.disableJarChecking")); DISABLE_JAR_CHECKING = p != null ? p.equals("true") || p.equals("") : false; + + p = AccessController.doPrivileged( + new GetPropertyAction("jdk.net.URLClassPath.disableRestrictedPermissions")); + DISABLE_ACC_CHECKING = p != null ? p.equals("true") || p.equals("") : false; } /* The original search path of URLs. */ @@ -98,6 +104,11 @@ /* Whether this URLClassLoader has been closed yet */ private boolean closed = false; + /* The context to be used when loading classes and resources. If non-null + * this is the context that was captured during the creation of the + * URLClassLoader. null implies no additional security restrictions. */ + private final AccessControlContext acc; + /** * Creates a new URLClassPath for the given URLs. The URLs will be * searched in the order specified for classes and resources. A URL @@ -107,8 +118,12 @@ * @param urls the directory and JAR file URLs to search for classes * and resources * @param factory the URLStreamHandlerFactory to use when creating new URLs + * @param acc the context to be used when loading classes and resources, may + * be null */ - public URLClassPath(URL[] urls, URLStreamHandlerFactory factory) { + public URLClassPath(URL[] urls, + URLStreamHandlerFactory factory, + AccessControlContext acc) { for (int i = 0; i < urls.length; i++) { path.add(urls[i]); } @@ -116,10 +131,22 @@ if (factory != null) { jarHandler = factory.createURLStreamHandler("jar"); } + if (DISABLE_ACC_CHECKING) + this.acc = null; + else + this.acc = acc; } + /** + * Constructs a URLClassPath with no additional security restrictions. + * Used by code that implements the class path. + */ public URLClassPath(URL[] urls) { - this(urls, null); + this(urls, null, null); + } + + public URLClassPath(URL[] urls, AccessControlContext acc) { + this(urls, null, acc); } public synchronized List<IOException> closeLoaders() { @@ -499,6 +526,14 @@ } catch (IOException e) { // Silently ignore for now... continue; + } catch (SecurityException se) { + // Always silently ignore. The context, if there is one, that + // this URLClassPath was given during construction will never + // have permission to access the URL. + if (DEBUG) { + System.err.println("Failed to access " + url + ", " + se ); + } + continue; } // Finally, add the Loader to the search path. validateLookupCache(loaders.size(), urlNoFragString); @@ -527,10 +562,10 @@ return new Loader(url); } } else { - return new JarLoader(url, jarHandler, lmap); + return new JarLoader(url, jarHandler, lmap, acc); } } - }); + }, acc); } catch (java.security.PrivilegedActionException pae) { throw (IOException)pae.getException(); } @@ -755,11 +790,12 @@ */ static class JarLoader extends Loader { private JarFile jar; - private URL csu; + private final URL csu; private JarIndex index; private MetaIndex metaIndex; private URLStreamHandler handler; - private HashMap<String, Loader> lmap; + private final HashMap<String, Loader> lmap; + private final AccessControlContext acc; private boolean closed = false; private static final sun.misc.JavaUtilZipFileAccess zipAccess = sun.misc.SharedSecrets.getJavaUtilZipFileAccess(); @@ -769,13 +805,15 @@ * a JAR file. */ JarLoader(URL url, URLStreamHandler jarHandler, - HashMap<String, Loader> loaderMap) + HashMap<String, Loader> loaderMap, + AccessControlContext acc) throws IOException { super(new URL("jar", "", -1, url + "!/", jarHandler)); csu = url; handler = jarHandler; lmap = loaderMap; + this.acc = acc; if (!isOptimizable(url)) { ensureOpen(); @@ -859,8 +897,7 @@ } return null; } - } - ); + }, acc); } catch (java.security.PrivilegedActionException pae) { throw (IOException)pae.getException(); } @@ -1054,9 +1091,9 @@ new PrivilegedExceptionAction<JarLoader>() { public JarLoader run() throws IOException { return new JarLoader(url, handler, - lmap); + lmap, acc); } - }); + }, acc); /* this newly opened jar file has its own index, * merge it into the parent's index, taking into
--- a/src/share/classes/sun/reflect/ReflectionFactory.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/classes/sun/reflect/ReflectionFactory.java Mon Jan 23 16:30:43 2017 +0000 @@ -25,16 +25,28 @@ package sun.reflect; +import java.io.Externalizable; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.ObjectStreamClass; +import java.io.OptionalDataException; +import java.io.Serializable; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; import java.lang.reflect.Field; import java.lang.reflect.Executable; +import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Constructor; import java.lang.reflect.Modifier; import java.security.AccessController; import java.security.Permission; import java.security.PrivilegedAction; +import java.util.Objects; + import sun.reflect.misc.ReflectUtil; + /** <P> The master factory for all reflective objects, both those in java.lang.reflect (Fields, Methods, Constructors) as well as their delegates (FieldAccessors, MethodAccessors, ConstructorAccessors). @@ -56,6 +68,9 @@ // Provides access to package-private mechanisms in java.lang.reflect private static volatile LangReflectAccess langReflectAccess; + /* Method for static class initializer <clinit>, or null */ + private static volatile Method hasStaticInitializerMethod; + // // "Inflation" mechanism. Loading bytecodes to implement // Method.invoke() and Constructor.newInstance() currently costs @@ -73,8 +88,7 @@ private static boolean noInflation = false; private static int inflationThreshold = 15; - private ReflectionFactory() { - } + private ReflectionFactory() {} /** * A convenience class for acquiring the capability to instantiate @@ -328,6 +342,14 @@ // // + /** + * Returns an accessible constructor capable of creating instances + * of the given class, initialized by the given constructor. + * + * @param classToInstantiate the class to instantiate + * @param constructorToCall the constructor to call + * @return an accessible constructor + */ public Constructor<?> newConstructorForSerialization (Class<?> classToInstantiate, Constructor<?> constructorToCall) { @@ -335,6 +357,42 @@ if (constructorToCall.getDeclaringClass() == classToInstantiate) { return constructorToCall; } + return generateConstructor(classToInstantiate, constructorToCall); + } + + /** + * Returns an accessible no-arg constructor for a class. + * The no-arg constructor is found searching the class and its supertypes. + * + * @param cl the class to instantiate + * @return a no-arg constructor for the class or {@code null} if + * the class or supertypes do not have a suitable no-arg constructor + */ + public final Constructor<?> newConstructorForSerialization(Class<?> cl) { + Class<?> initCl = cl; + while (Serializable.class.isAssignableFrom(initCl)) { + if ((initCl = initCl.getSuperclass()) == null) { + return null; + } + } + Constructor<?> constructorToCall; + try { + constructorToCall = initCl.getDeclaredConstructor(); + int mods = constructorToCall.getModifiers(); + if ((mods & Modifier.PRIVATE) != 0 || + ((mods & (Modifier.PUBLIC | Modifier.PROTECTED)) == 0 && + !packageEquals(cl, initCl))) { + return null; + } + } catch (NoSuchMethodException ex) { + return null; + } + return generateConstructor(cl, constructorToCall); + } + + private final Constructor<?> generateConstructor(Class<?> classToInstantiate, + Constructor<?> constructorToCall) { + ConstructorAccessor acc = new MethodAccessorGenerator(). generateSerializationConstructor(classToInstantiate, @@ -355,9 +413,222 @@ langReflectAccess(). getConstructorParameterAnnotations(constructorToCall)); setConstructorAccessor(c, acc); + c.setAccessible(true); return c; } + /** + * Returns an accessible no-arg constructor for an externalizable class to be + * initialized using a public no-argument constructor. + * + * @param cl the class to instantiate + * @return A no-arg constructor for the class; returns {@code null} if + * the class does not implement {@link java.io.Externalizable} + */ + public final Constructor<?> newConstructorForExternalization(Class<?> cl) { + if (!Externalizable.class.isAssignableFrom(cl)) { + return null; + } + try { + Constructor<?> cons = cl.getConstructor(); + cons.setAccessible(true); + return cons; + } catch (NoSuchMethodException ex) { + return null; + } + } + + /** + * Returns a direct MethodHandle for the {@code readObject} method on + * a Serializable class. + * The first argument of {@link MethodHandle#invoke} is the serializable + * object and the second argument is the {@code ObjectInputStream} passed to + * {@code readObject}. + * + * @param cl a Serializable class + * @return a direct MethodHandle for the {@code readObject} method of the class or + * {@code null} if the class does not have a {@code readObject} method + */ + public final MethodHandle readObjectForSerialization(Class<?> cl) { + return findReadWriteObjectForSerialization(cl, "readObject", ObjectInputStream.class); + } + + /** + * Returns a direct MethodHandle for the {@code readObjectNoData} method on + * a Serializable class. + * The first argument of {@link MethodHandle#invoke} is the serializable + * object and the second argument is the {@code ObjectInputStream} passed to + * {@code readObjectNoData}. + * + * @param cl a Serializable class + * @return a direct MethodHandle for the {@code readObjectNoData} method + * of the class or {@code null} if the class does not have a + * {@code readObjectNoData} method + */ + public final MethodHandle readObjectNoDataForSerialization(Class<?> cl) { + return findReadWriteObjectForSerialization(cl, "readObjectNoData", ObjectInputStream.class); + } + + /** + * Returns a direct MethodHandle for the {@code writeObject} method on + * a Serializable class. + * The first argument of {@link MethodHandle#invoke} is the serializable + * object and the second argument is the {@code ObjectOutputStream} passed to + * {@code writeObject}. + * + * @param cl a Serializable class + * @return a direct MethodHandle for the {@code writeObject} method of the class or + * {@code null} if the class does not have a {@code writeObject} method + */ + public final MethodHandle writeObjectForSerialization(Class<?> cl) { + return findReadWriteObjectForSerialization(cl, "writeObject", ObjectOutputStream.class); + } + + private final MethodHandle findReadWriteObjectForSerialization(Class<?> cl, + String methodName, + Class<?> streamClass) { + if (!Serializable.class.isAssignableFrom(cl)) { + return null; + } + + try { + Method meth = cl.getDeclaredMethod(methodName, streamClass); + int mods = meth.getModifiers(); + if (meth.getReturnType() != Void.TYPE || + Modifier.isStatic(mods) || + !Modifier.isPrivate(mods)) { + return null; + } + meth.setAccessible(true); + return MethodHandles.lookup().unreflect(meth); + } catch (NoSuchMethodException ex) { + return null; + } catch (IllegalAccessException ex1) { + throw new InternalError("Error", ex1); + } + } + + /** + * Returns a direct MethodHandle for the {@code readResolve} method on + * a serializable class. + * The single argument of {@link MethodHandle#invoke} is the serializable + * object. + * + * @param cl the Serializable class + * @return a direct MethodHandle for the {@code readResolve} method of the class or + * {@code null} if the class does not have a {@code readResolve} method + */ + public final MethodHandle readResolveForSerialization(Class<?> cl) { + return getReplaceResolveForSerialization(cl, "readResolve"); + } + + /** + * Returns a direct MethodHandle for the {@code writeReplace} method on + * a serializable class. + * The single argument of {@link MethodHandle#invoke} is the serializable + * object. + * + * @param cl the Serializable class + * @return a direct MethodHandle for the {@code writeReplace} method of the class or + * {@code null} if the class does not have a {@code writeReplace} method + */ + public final MethodHandle writeReplaceForSerialization(Class<?> cl) { + return getReplaceResolveForSerialization(cl, "writeReplace"); + } + + /** + * Returns a direct MethodHandle for the {@code writeReplace} method on + * a serializable class. + * The single argument of {@link MethodHandle#invoke} is the serializable + * object. + * + * @param cl the Serializable class + * @return a direct MethodHandle for the {@code writeReplace} method of the class or + * {@code null} if the class does not have a {@code writeReplace} method + */ + private MethodHandle getReplaceResolveForSerialization(Class<?> cl, + String methodName) { + if (!Serializable.class.isAssignableFrom(cl)) { + return null; + } + + Class<?> defCl = cl; + while (defCl != null) { + try { + Method m = defCl.getDeclaredMethod(methodName); + if (m.getReturnType() != Object.class) { + return null; + } + int mods = m.getModifiers(); + if (Modifier.isStatic(mods) | Modifier.isAbstract(mods)) { + return null; + } else if (Modifier.isPublic(mods) | Modifier.isProtected(mods)) { + // fall through + } else if (Modifier.isPrivate(mods) && (cl != defCl)) { + return null; + } else if (!packageEquals(cl, defCl)) { + return null; + } + try { + // Normal return + m.setAccessible(true); + return MethodHandles.lookup().unreflect(m); + } catch (IllegalAccessException ex0) { + // setAccessible should prevent IAE + throw new InternalError("Error", ex0); + } + } catch (NoSuchMethodException ex) { + defCl = defCl.getSuperclass(); + } + } + return null; + } + + /** + * Returns true if the class has a static initializer. + * The presence of a static initializer is used to compute the serialVersionUID. + * @param cl a serializable classLook + * @return {@code true} if the class has a static initializer, + * otherwise {@code false} + */ + public final boolean hasStaticInitializerForSerialization(Class<?> cl) { + Method m = hasStaticInitializerMethod; + if (m == null) { + try { + m = ObjectStreamClass.class.getDeclaredMethod("hasStaticInitializer", + new Class<?>[]{Class.class}); + m.setAccessible(true); + hasStaticInitializerMethod = m; + } catch (NoSuchMethodException ex) { + throw new InternalError("No such method hasStaticInitializer on " + + ObjectStreamClass.class, ex); + } + } + try { + return (Boolean) m.invoke(null, cl); + } catch (InvocationTargetException | IllegalAccessException ex) { + throw new InternalError("Exception invoking hasStaticInitializer", ex); + } + } + + /** + * Returns a new OptionalDataException with {@code eof} set to {@code true} + * or {@code false}. + * @param bool the value of {@code eof} in the created OptionalDataException + * @return a new OptionalDataException + */ + public final OptionalDataException newOptionalDataExceptionForSerialization(boolean bool) { + try { + Constructor<OptionalDataException> boolCtor = + OptionalDataException.class.getDeclaredConstructor(Boolean.TYPE); + boolCtor.setAccessible(true); + return boolCtor.newInstance(bool); + } catch (NoSuchMethodException | InstantiationException| + IllegalAccessException|InvocationTargetException ex) { + throw new InternalError("unable to create OptionalDataException", ex); + } + } + //-------------------------------------------------------------------------- // // Internals only below this point @@ -421,4 +692,17 @@ } return langReflectAccess; } + + /** + * Returns true if classes are defined in the classloader and same package, false + * otherwise. + * @param cl1 a class + * @param cl2 another class + * @returns true if the two classes are in the same classloader and package + */ + private static boolean packageEquals(Class<?> cl1, Class<?> cl2) { + return cl1.getClassLoader() == cl2.getClassLoader() && + Objects.equals(cl1.getPackage(), cl2.getPackage()); + } + }
--- a/src/share/classes/sun/rmi/registry/RegistryImpl.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/classes/sun/rmi/registry/RegistryImpl.java Mon Jan 23 16:30:43 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 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 @@ -30,11 +30,9 @@ import java.util.MissingResourceException; import java.util.ResourceBundle; import java.io.FilePermission; -import java.io.IOException; import java.net.*; import java.rmi.*; import java.rmi.server.ObjID; -import java.rmi.server.RemoteServer; import java.rmi.server.ServerNotActiveException; import java.rmi.registry.Registry; import java.rmi.server.RMIClientSocketFactory; @@ -47,14 +45,18 @@ import java.security.PrivilegedExceptionAction; import java.security.PermissionCollection; import java.security.Permissions; +import java.security.PrivilegedAction; import java.security.ProtectionDomain; +import java.security.Security; import java.text.MessageFormat; -import sun.rmi.server.LoaderHandler; + +import sun.misc.ObjectInputFilter; + +import sun.rmi.runtime.Log; +import sun.rmi.server.UnicastRef; import sun.rmi.server.UnicastServerRef; import sun.rmi.server.UnicastServerRef2; import sun.rmi.transport.LiveRef; -import sun.rmi.transport.ObjectTable; -import sun.rmi.transport.Target; /** * A "registry" exists on every node that allows RMI connections to @@ -86,6 +88,47 @@ private static ResourceBundle resources = null; /** + * Property name of the RMI Registry serial filter to augment + * the built-in list of allowed types. + * Setting the property in the {@code lib/security/java.security} file + * will enable the augmented filter. + */ + private static final String REGISTRY_FILTER_PROPNAME = "sun.rmi.registry.registryFilter"; + + /** Registry max depth of remote invocations. **/ + private static int REGISTRY_MAX_DEPTH = 5; + + /** Registry maximum array size in remote invocations. **/ + private static int REGISTRY_MAX_ARRAY_SIZE = 10000; + + /** + * The registryFilter created from the value of the {@code "sun.rmi.registry.registryFilter"} + * property. + */ + private static final ObjectInputFilter registryFilter = + AccessController.doPrivileged((PrivilegedAction<ObjectInputFilter>)RegistryImpl::initRegistryFilter); + + /** + * Initialize the registryFilter from the security properties or system property; if any + * @return an ObjectInputFilter, or null + */ + private static ObjectInputFilter initRegistryFilter() { + ObjectInputFilter filter = null; + String props = System.getProperty(REGISTRY_FILTER_PROPNAME); + if (props == null) { + props = Security.getProperty(REGISTRY_FILTER_PROPNAME); + } + if (props != null) { + filter = ObjectInputFilter.Config.createFilter(props); + Log regLog = Log.getLog("sun.rmi.registry", "registry", -1); + if (regLog.isLoggable(Log.BRIEF)) { + regLog.log(Log.BRIEF, "registryFilter = " + filter); + } + } + return filter; + } + + /** * Construct a new RegistryImpl on the specified port with the * given custom socket factory pair. */ @@ -100,7 +143,7 @@ AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() { public Void run() throws RemoteException { LiveRef lref = new LiveRef(id, port, csf, ssf); - setup(new UnicastServerRef2(lref)); + setup(new UnicastServerRef2(lref, RegistryImpl::registryFilter)); return null; } }, null, new SocketPermission("localhost:"+port, "listen,accept")); @@ -109,7 +152,7 @@ } } else { LiveRef lref = new LiveRef(id, port, csf, ssf); - setup(new UnicastServerRef2(lref)); + setup(new UnicastServerRef2(lref, RegistryImpl::registryFilter)); } } @@ -125,7 +168,7 @@ AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() { public Void run() throws RemoteException { LiveRef lref = new LiveRef(id, port); - setup(new UnicastServerRef(lref)); + setup(new UnicastServerRef(lref, RegistryImpl::registryFilter)); return null; } }, null, new SocketPermission("localhost:"+port, "listen,accept")); @@ -134,7 +177,7 @@ } } else { LiveRef lref = new LiveRef(id, port); - setup(new UnicastServerRef(lref)); + setup(new UnicastServerRef(lref, RegistryImpl::registryFilter)); } } @@ -155,7 +198,7 @@ /** * Returns the remote object for specified name in the registry. * @exception RemoteException If remote operation failed. - * @exception NotBound If name is not currently bound. + * @exception NotBoundException If name is not currently bound. */ public Remote lookup(String name) throws RemoteException, NotBoundException @@ -188,7 +231,7 @@ /** * Unbind the name. * @exception RemoteException If remote operation failed. - * @exception NotBound If name is not currently bound. + * @exception NotBoundException If name is not currently bound. */ public void unbind(String name) throws RemoteException, NotBoundException, AccessException @@ -333,6 +376,60 @@ } /** + * ObjectInputFilter to filter Registry input objects. + * The list of acceptable classes is limited to classes normally + * stored in a registry. + * + * @param filterInfo access to the class, array length, etc. + * @return {@link ObjectInputFilter.Status#ALLOWED} if allowed, + * {@link ObjectInputFilter.Status#REJECTED} if rejected, + * otherwise {@link ObjectInputFilter.Status#UNDECIDED} + */ + private static ObjectInputFilter.Status registryFilter(ObjectInputFilter.FilterInfo filterInfo) { + if (registryFilter != null) { + ObjectInputFilter.Status status = registryFilter.checkInput(filterInfo); + if (status != ObjectInputFilter.Status.UNDECIDED) { + // The Registry filter can override the built-in white-list + return status; + } + } + + if (filterInfo.depth() > REGISTRY_MAX_DEPTH) { + return ObjectInputFilter.Status.REJECTED; + } + Class<?> clazz = filterInfo.serialClass(); + if (clazz != null) { + if (clazz.isArray()) { + if (filterInfo.arrayLength() >= 0 && filterInfo.arrayLength() > REGISTRY_MAX_ARRAY_SIZE) { + return ObjectInputFilter.Status.REJECTED; + } + do { + // Arrays are allowed depending on the component type + clazz = clazz.getComponentType(); + } while (clazz.isArray()); + } + if (clazz.isPrimitive()) { + // Arrays of primitives are allowed + return ObjectInputFilter.Status.ALLOWED; + } + if (String.class == clazz + || java.lang.Number.class.isAssignableFrom(clazz) + || Remote.class.isAssignableFrom(clazz) + || java.lang.reflect.Proxy.class.isAssignableFrom(clazz) + || UnicastRef.class.isAssignableFrom(clazz) + || RMIClientSocketFactory.class.isAssignableFrom(clazz) + || RMIServerSocketFactory.class.isAssignableFrom(clazz) + || java.rmi.activation.ActivationID.class.isAssignableFrom(clazz) + || java.rmi.server.UID.class.isAssignableFrom(clazz)) { + return ObjectInputFilter.Status.ALLOWED; + } else { + return ObjectInputFilter.Status.REJECTED; + } + } + return ObjectInputFilter.Status.UNDECIDED; + } + + /** * Main program to start a registry. <br> * The port number can be specified on the command line. */
--- a/src/share/classes/sun/rmi/server/UnicastServerRef.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/classes/sun/rmi/server/UnicastServerRef.java Mon Jan 23 16:30:43 2017 +0000 @@ -27,6 +27,7 @@ import java.io.IOException; import java.io.ObjectInput; +import java.io.ObjectInputStream; import java.io.ObjectOutput; import java.io.ObjectStreamClass; import java.lang.reflect.InvocationTargetException; @@ -53,8 +54,8 @@ import java.util.Map; import java.util.WeakHashMap; import java.util.concurrent.atomic.AtomicInteger; +import sun.misc.ObjectInputFilter; import sun.rmi.runtime.Log; -import static sun.rmi.server.UnicastRef.marshalValue; import sun.rmi.transport.LiveRef; import sun.rmi.transport.Target; import sun.rmi.transport.tcp.TCPTransport; @@ -64,6 +65,10 @@ * UnicastServerRef implements the remote reference layer server-side * behavior for remote objects exported with the "UnicastRef" reference * type. + * If an {@link ObjectInputFilter ObjectInputFilter} is supplied it is + * invoked during deserialization to filter the arguments, + * otherwise the default filter of {@link ObjectInputStream ObjectInputStream} + * applies. * * @author Ann Wollrath * @author Roger Riggs @@ -106,6 +111,9 @@ */ private transient Skeleton skel; + // The ObjectInputFilter for checking the invocation arguments + private final transient ObjectInputFilter filter; + /** maps method hash to Method object for each remote method */ private transient Map<Long,Method> hashToMethod_Map = null; @@ -124,16 +132,29 @@ /** * Create a new (empty) Unicast server remote reference. + * The filter is null to defer to the default ObjectInputStream filter, if any. */ public UnicastServerRef() { + this.filter = null; } /** * Construct a Unicast server remote reference for a specified * liveRef. + * The filter is null to defer to the default ObjectInputStream filter, if any. */ public UnicastServerRef(LiveRef ref) { super(ref); + this.filter = null; + } + + /** + * Construct a Unicast server remote reference for a specified + * liveRef and filter. + */ + public UnicastServerRef(LiveRef ref, ObjectInputFilter filter) { + super(ref); + this.filter = filter; } /** @@ -142,6 +163,7 @@ */ public UnicastServerRef(int port) { super(new LiveRef(port)); + this.filter = null; } /** @@ -366,9 +388,26 @@ } } + /** + * Sets a filter for invocation arguments, if a filter has been set. + * Called by dispatch before the arguments are read. + */ protected void unmarshalCustomCallData(ObjectInput in) - throws IOException, ClassNotFoundException - {} + throws IOException, ClassNotFoundException { + if (filter != null && + in instanceof ObjectInputStream) { + // Set the filter on the stream + ObjectInputStream ois = (ObjectInputStream) in; + + AccessController.doPrivileged(new PrivilegedAction<Void>() { + @Override + public Void run() { + ObjectInputFilter.Config.setObjectInputFilter(ois, filter); + return null; + } + }); + } + } /** * Handle server-side dispatch using the RMI 1.1 stub/skeleton
--- a/src/share/classes/sun/rmi/server/UnicastServerRef2.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/classes/sun/rmi/server/UnicastServerRef2.java Mon Jan 23 16:30:43 2017 +0000 @@ -25,12 +25,15 @@ package sun.rmi.server; -import java.io.IOException; + import java.io.ObjectOutput; -import java.rmi.*; -import java.rmi.server.*; -import sun.rmi.transport.*; -import sun.rmi.transport.tcp.*; +import java.rmi.server.RMIClientSocketFactory; +import java.rmi.server.RMIServerSocketFactory; +import java.rmi.server.RemoteRef; + +import sun.misc.ObjectInputFilter; + +import sun.rmi.transport.LiveRef; /** * Server-side ref for a remote impl that uses a custom socket factory. @@ -59,6 +62,16 @@ } /** + * Construct a Unicast server remote reference for a specified + * liveRef and filter. + */ + public UnicastServerRef2(LiveRef ref, + ObjectInputFilter filter) + { + super(ref, filter); + } + + /** * Construct a Unicast server remote reference to be exported * on the specified port. */ @@ -70,6 +83,18 @@ } /** + * Construct a Unicast server remote reference to be exported + * on the specified port. + */ + public UnicastServerRef2(int port, + RMIClientSocketFactory csf, + RMIServerSocketFactory ssf, + ObjectInputFilter filter) + { + super(new LiveRef(port, csf, ssf), filter); + } + + /** * Returns the class of the ref type to be serialized */ public String getRefClass(ObjectOutput out)
--- a/src/share/classes/sun/rmi/transport/DGCImpl.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/classes/sun/rmi/transport/DGCImpl.java Mon Jan 23 16:30:43 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 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 @@ -34,11 +34,13 @@ import java.rmi.server.ObjID; import java.rmi.server.RemoteServer; import java.rmi.server.ServerNotActiveException; +import java.rmi.server.UID; import java.security.AccessControlContext; import java.security.AccessController; import java.security.Permissions; import java.security.PrivilegedAction; import java.security.ProtectionDomain; +import java.security.Security; import java.util.ArrayList; import java.util.HashSet; import java.util.HashMap; @@ -49,6 +51,9 @@ import java.util.concurrent.Future; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; + +import sun.misc.ObjectInputFilter; + import sun.rmi.runtime.Log; import sun.rmi.runtime.RuntimeUtil; import sun.rmi.server.UnicastRef; @@ -102,6 +107,45 @@ } /** + * Property name of the DGC serial filter to augment + * the built-in list of allowed types. + * Setting the property in the {@code lib/security/java.security} file + * will enable the augmented filter. + */ + private static final String DGC_FILTER_PROPNAME = "sun.rmi.transport.dgcFilter"; + + /** Registry max depth of remote invocations. **/ + private static int DGC_MAX_DEPTH = 5; + + /** Registry maximum array size in remote invocations. **/ + private static int DGC_MAX_ARRAY_SIZE = 10000; + /** + * The dgcFilter created from the value of the {@code "sun.rmi.transport.dgcFilter"} + * property. + */ + private static final ObjectInputFilter dgcFilter = + AccessController.doPrivileged((PrivilegedAction<ObjectInputFilter>)DGCImpl::initDgcFilter); + + /** + * Initialize the dgcFilter from the security properties or system property; if any + * @return an ObjectInputFilter, or null + */ + private static ObjectInputFilter initDgcFilter() { + ObjectInputFilter filter = null; + String props = System.getProperty(DGC_FILTER_PROPNAME); + if (props == null) { + props = Security.getProperty(DGC_FILTER_PROPNAME); + } + if (props != null) { + filter = ObjectInputFilter.Config.createFilter(props); + if (dgcLog.isLoggable(Log.BRIEF)) { + dgcLog.log(Log.BRIEF, "dgcFilter = " + filter); + } + } + return filter; + } + + /** * Construct a new server-side remote object collector at * a particular port. Disallow construction from outside. */ @@ -295,7 +339,8 @@ dgc = new DGCImpl(); ObjID dgcID = new ObjID(ObjID.DGC_ID); LiveRef ref = new LiveRef(dgcID, 0); - UnicastServerRef disp = new UnicastServerRef(ref); + UnicastServerRef disp = new UnicastServerRef(ref, + DGCImpl::checkInput); Remote stub = Util.createProxy(DGCImpl.class, new UnicastRef(ref), true); @@ -326,6 +371,53 @@ }); } + /** + * ObjectInputFilter to filter DGC input objects. + * The list of acceptable classes is very short and explicit. + * The depth and array sizes are limited. + * + * @param filterInfo access to class, arrayLength, etc. + * @return {@link ObjectInputFilter.Status#ALLOWED} if allowed, + * {@link ObjectInputFilter.Status#REJECTED} if rejected, + * otherwise {@link ObjectInputFilter.Status#UNDECIDED} + */ + private static ObjectInputFilter.Status checkInput(ObjectInputFilter.FilterInfo filterInfo) { + if (dgcFilter != null) { + ObjectInputFilter.Status status = dgcFilter.checkInput(filterInfo); + if (status != ObjectInputFilter.Status.UNDECIDED) { + // The DGC filter can override the built-in white-list + return status; + } + } + + if (filterInfo.depth() > DGC_MAX_DEPTH) { + return ObjectInputFilter.Status.REJECTED; + } + Class<?> clazz = filterInfo.serialClass(); + if (clazz != null) { + while (clazz.isArray()) { + if (filterInfo.arrayLength() >= 0 && filterInfo.arrayLength() > DGC_MAX_ARRAY_SIZE) { + return ObjectInputFilter.Status.REJECTED; + } + // Arrays are allowed depending on the component type + clazz = clazz.getComponentType(); + } + if (clazz.isPrimitive()) { + // Arrays of primitives are allowed + return ObjectInputFilter.Status.ALLOWED; + } + return (clazz == ObjID.class || + clazz == UID.class || + clazz == VMID.class || + clazz == Lease.class) + ? ObjectInputFilter.Status.ALLOWED + : ObjectInputFilter.Status.REJECTED; + } + // Not a class, not size limited + return ObjectInputFilter.Status.UNDECIDED; + } + + private static class LeaseInfo { VMID vmid; long expiration;
--- a/src/share/classes/sun/security/ec/ECDSASignature.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/classes/sun/security/ec/ECDSASignature.java Mon Jan 23 16:30:43 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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 @@ -25,6 +25,7 @@ package sun.security.ec; +import java.io.IOException; import java.nio.ByteBuffer; import java.math.BigInteger; @@ -363,13 +364,22 @@ } // Convert the DER encoding of R and S into a concatenation of R and S - private byte[] decodeSignature(byte[] signature) throws SignatureException { + private byte[] decodeSignature(byte[] sig) throws SignatureException { try { - DerInputStream in = new DerInputStream(signature); + // Enforce strict DER checking for signatures + DerInputStream in = new DerInputStream(sig, 0, sig.length, false); DerValue[] values = in.getSequence(2); + + // check number of components in the read sequence + // and trailing data + if ((values.length != 2) || (in.available() != 0)) { + throw new IOException("Invalid encoding for signature"); + } + BigInteger r = values[0].getPositiveBigInteger(); BigInteger s = values[1].getPositiveBigInteger(); + // trim leading zeroes byte[] rBytes = trimZeroes(r.toByteArray()); byte[] sBytes = trimZeroes(s.toByteArray()); @@ -383,7 +393,7 @@ return result; } catch (Exception e) { - throw new SignatureException("Could not decode signature", e); + throw new SignatureException("Invalid encoding for signature", e); } }
--- a/src/share/classes/sun/security/pkcs/SignerInfo.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/classes/sun/security/pkcs/SignerInfo.java Mon Jan 23 16:30:43 2017 +0000 @@ -498,6 +498,23 @@ return unauthenticatedAttributes; } + /** + * Returns the timestamp PKCS7 data unverified. + * @return a PKCS7 object + */ + public PKCS7 getTsToken() throws IOException { + if (unauthenticatedAttributes == null) { + return null; + } + PKCS9Attribute tsTokenAttr = + unauthenticatedAttributes.getAttribute( + PKCS9Attribute.SIGNATURE_TIMESTAMP_TOKEN_OID); + if (tsTokenAttr == null) { + return null; + } + return new PKCS7((byte[])tsTokenAttr.getValue()); + } + /* * Extracts a timestamp from a PKCS7 SignerInfo. * @@ -525,19 +542,12 @@ if (timestamp != null || !hasTimestamp) return timestamp; - if (unauthenticatedAttributes == null) { - hasTimestamp = false; - return null; - } - PKCS9Attribute tsTokenAttr = - unauthenticatedAttributes.getAttribute( - PKCS9Attribute.SIGNATURE_TIMESTAMP_TOKEN_OID); - if (tsTokenAttr == null) { + PKCS7 tsToken = getTsToken(); + if (tsToken == null) { hasTimestamp = false; return null; } - PKCS7 tsToken = new PKCS7((byte[])tsTokenAttr.getValue()); // Extract the content (an encoded timestamp token info) byte[] encTsTokenInfo = tsToken.getContentInfo().getData(); // Extract the signer (the Timestamping Authority)
--- a/src/share/classes/sun/security/pkcs11/P11Signature.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/classes/sun/security/pkcs11/P11Signature.java Mon Jan 23 16:30:43 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2014, 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 @@ -705,12 +705,21 @@ } } - private static byte[] asn1ToDSA(byte[] signature) throws SignatureException { + private static byte[] asn1ToDSA(byte[] sig) throws SignatureException { try { - DerInputStream in = new DerInputStream(signature); + // Enforce strict DER checking for signatures + DerInputStream in = new DerInputStream(sig, 0, sig.length, false); DerValue[] values = in.getSequence(2); + + // check number of components in the read sequence + // and trailing data + if ((values.length != 2) || (in.available() != 0)) { + throw new IOException("Invalid encoding for signature"); + } + BigInteger r = values[0].getPositiveBigInteger(); BigInteger s = values[1].getPositiveBigInteger(); + byte[] br = toByteArray(r, 20); byte[] bs = toByteArray(s, 20); if ((br == null) || (bs == null)) { @@ -720,16 +729,25 @@ } catch (SignatureException e) { throw e; } catch (Exception e) { - throw new SignatureException("invalid encoding for signature", e); + throw new SignatureException("Invalid encoding for signature", e); } } - private byte[] asn1ToECDSA(byte[] signature) throws SignatureException { + private byte[] asn1ToECDSA(byte[] sig) throws SignatureException { try { - DerInputStream in = new DerInputStream(signature); + // Enforce strict DER checking for signatures + DerInputStream in = new DerInputStream(sig, 0, sig.length, false); DerValue[] values = in.getSequence(2); + + // check number of components in the read sequence + // and trailing data + if ((values.length != 2) || (in.available() != 0)) { + throw new IOException("Invalid encoding for signature"); + } + BigInteger r = values[0].getPositiveBigInteger(); BigInteger s = values[1].getPositiveBigInteger(); + // trim leading zeroes byte[] br = KeyUtil.trimZeroes(r.toByteArray()); byte[] bs = KeyUtil.trimZeroes(s.toByteArray()); @@ -740,7 +758,7 @@ System.arraycopy(bs, 0, res, res.length - bs.length, bs.length); return res; } catch (Exception e) { - throw new SignatureException("invalid encoding for signature", e); + throw new SignatureException("Invalid encoding for signature", e); } }
--- a/src/share/classes/sun/security/provider/DSA.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/classes/sun/security/provider/DSA.java Mon Jan 23 16:30:43 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 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 @@ -267,14 +267,20 @@ BigInteger s = null; // first decode the signature. try { - DerInputStream in = new DerInputStream(signature, offset, length); + // Enforce strict DER checking for signatures + DerInputStream in = + new DerInputStream(signature, offset, length, false); DerValue[] values = in.getSequence(2); + // check number of components in the read sequence + // and trailing data + if ((values.length != 2) || (in.available() != 0)) { + throw new IOException("Invalid encoding for signature"); + } r = values[0].getBigInteger(); s = values[1].getBigInteger(); - } catch (IOException e) { - throw new SignatureException("invalid encoding for signature"); + throw new SignatureException("Invalid encoding for signature", e); } // some implementations do not correctly encode values in the ASN.1 @@ -366,13 +372,49 @@ return t5.mod(q); } - // NOTE: This following impl is defined in FIPS 186-4 AppendixB.2.1. protected BigInteger generateK(BigInteger q) { + // Implementation defined in FIPS 186-4 AppendixB.2.1. SecureRandom random = getSigningRandom(); byte[] kValue = new byte[(q.bitLength() + 7)/8 + 8]; random.nextBytes(kValue); - return new BigInteger(1, kValue).mod(q.subtract(BigInteger.ONE)).add(BigInteger.ONE); + BigInteger k = new BigInteger(1, kValue).mod( + q.subtract(BigInteger.ONE)).add(BigInteger.ONE); + + // Using an equivalent exponent of fixed length (same as q or 1 bit + // less than q) to keep the kG timing relatively constant. + // + // Note that this is an extra step on top of the approach defined in + // FIPS 186-4 AppendixB.2.1 so as to make a fixed length K. + k = k.add(q).divide(BigInteger.valueOf(2)); + + // An alternative implementation based on FIPS 186-4 AppendixB2.2 + // with fixed-length K. + // + // Please keep it here as we may need to switch to it in the future. + // + // SecureRandom random = getSigningRandom(); + // byte[] kValue = new byte[(q.bitLength() + 7)/8]; + // BigInteger d = q.subtract(BigInteger.TWO); + // BigInteger k; + // do { + // random.nextBytes(kValue); + // BigInteger c = new BigInteger(1, kValue); + // if (c.compareTo(d) <= 0) { + // k = c.add(BigInteger.ONE); + // // Using an equivalent exponent of fixed length to keep + // // the g^k timing relatively constant. + // // + // // Note that this is an extra step on top of the approach + // // defined in FIPS 186-4 AppendixB.2.2 so as to make a + // // fixed length K. + // if (k.bitLength() >= q.bitLength()) { + // break; + // } + // } + // } while (true); + + return k; } // Use the application-specified SecureRandom Object if provided.
--- a/src/share/classes/sun/security/provider/certpath/AlgorithmChecker.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/classes/sun/security/provider/certpath/AlgorithmChecker.java Mon Jan 23 16:30:43 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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 @@ -31,12 +31,10 @@ import java.util.Collections; import java.util.Set; import java.util.EnumSet; -import java.util.HashSet; import java.math.BigInteger; import java.security.PublicKey; import java.security.KeyFactory; import java.security.AlgorithmParameters; -import java.security.NoSuchAlgorithmException; import java.security.GeneralSecurityException; import java.security.cert.Certificate; import java.security.cert.X509CRL; @@ -48,10 +46,13 @@ import java.security.cert.CertPathValidatorException; import java.security.cert.CertPathValidatorException.BasicReason; import java.security.cert.PKIXReason; -import java.io.IOException; -import java.security.interfaces.*; -import java.security.spec.*; +import java.security.interfaces.DSAParams; +import java.security.interfaces.DSAPublicKey; +import java.security.spec.DSAPublicKeySpec; +import sun.security.util.AnchorCertificates; +import sun.security.util.CertConstraintParameters; +import sun.security.util.Debug; import sun.security.util.DisabledAlgorithmConstraints; import sun.security.x509.X509CertImpl; import sun.security.x509.X509CRLImpl; @@ -69,6 +70,7 @@ * @see PKIXParameters */ final public class AlgorithmChecker extends PKIXCertPathChecker { + private static final Debug debug = Debug.getInstance("certpath"); private final AlgorithmConstraints constraints; private final PublicKey trustedPubKey; @@ -88,6 +90,14 @@ certPathDefaultConstraints = new DisabledAlgorithmConstraints( DisabledAlgorithmConstraints.PROPERTY_CERTPATH_DISABLED_ALGS); + // If there is no "cacerts" keyword, then disable anchor checking + private static final boolean publicCALimits = + certPathDefaultConstraints.checkProperty("jdkCA"); + + // If anchor checking enabled, this will be true if the trust anchor + // has a match in the cacerts file + private boolean trustedMatch = false; + /** * Create a new <code>AlgorithmChecker</code> with the algorithm * constraints specified in security property @@ -136,6 +146,11 @@ if (anchor.getTrustedCert() != null) { this.trustedPubKey = anchor.getTrustedCert().getPublicKey(); + // Check for anchor certificate restrictions + trustedMatch = checkFingerprint(anchor.getTrustedCert()); + if (trustedMatch && debug != null) { + debug.println("trustedMatch = true"); + } } else { this.trustedPubKey = anchor.getCAPublicKey(); } @@ -144,6 +159,19 @@ this.constraints = constraints; } + // Check this 'cert' for restrictions in the AnchorCertificates + // trusted certificates list + private static boolean checkFingerprint(X509Certificate cert) { + if (!publicCALimits) { + return false; + } + + if (debug != null) { + debug.println("AlgorithmChecker.contains: " + cert.getSigAlgName()); + } + return AnchorCertificates.contains(cert); + } + @Override public void init(boolean forward) throws CertPathValidatorException { // Note that this class does not support forward mode. @@ -181,36 +209,8 @@ return; } - X509CertImpl x509Cert = null; - try { - x509Cert = X509CertImpl.toImpl((X509Certificate)cert); - } catch (CertificateException ce) { - throw new CertPathValidatorException(ce); - } - - PublicKey currPubKey = x509Cert.getPublicKey(); - String currSigAlg = x509Cert.getSigAlgName(); - - AlgorithmId algorithmId = null; - try { - algorithmId = (AlgorithmId)x509Cert.get(X509CertImpl.SIG_ALG); - } catch (CertificateException ce) { - throw new CertPathValidatorException(ce); - } - - AlgorithmParameters currSigAlgParams = algorithmId.getParameters(); - - // Check the current signature algorithm - if (!constraints.permits( - SIGNATURE_PRIMITIVE_SET, - currSigAlg, currSigAlgParams)) { - throw new CertPathValidatorException( - "Algorithm constraints check failed: " + currSigAlg, - null, null, -1, BasicReason.ALGORITHM_CONSTRAINED); - } - // check the key usage and key size - boolean[] keyUsage = x509Cert.getKeyUsage(); + boolean[] keyUsage = ((X509Certificate) cert).getKeyUsage(); if (keyUsage != null && keyUsage.length < 9) { throw new CertPathValidatorException( "incorrect KeyUsage extension", @@ -248,28 +248,69 @@ if (primitives.isEmpty()) { throw new CertPathValidatorException( - "incorrect KeyUsage extension", + "incorrect KeyUsage extension bits", null, null, -1, PKIXReason.INVALID_KEY_USAGE); } } + PublicKey currPubKey = cert.getPublicKey(); + + if (constraints instanceof DisabledAlgorithmConstraints) { + // Check against DisabledAlgorithmConstraints certpath constraints. + // permits() will throw exception on failure. + ((DisabledAlgorithmConstraints)constraints).permits(primitives, + new CertConstraintParameters((X509Certificate)cert, + trustedMatch)); + // If there is no previous key, set one and exit + if (prevPubKey == null) { + prevPubKey = currPubKey; + return; + } + } + + X509CertImpl x509Cert; + AlgorithmId algorithmId; + try { + x509Cert = X509CertImpl.toImpl((X509Certificate)cert); + algorithmId = (AlgorithmId)x509Cert.get(X509CertImpl.SIG_ALG); + } catch (CertificateException ce) { + throw new CertPathValidatorException(ce); + } + + AlgorithmParameters currSigAlgParams = algorithmId.getParameters(); + String currSigAlg = x509Cert.getSigAlgName(); + + // If 'constraints' is not of DisabledAlgorithmConstraints, check all + // everything individually + if (!(constraints instanceof DisabledAlgorithmConstraints)) { + // Check the current signature algorithm + if (!constraints.permits( + SIGNATURE_PRIMITIVE_SET, + currSigAlg, currSigAlgParams)) { + throw new CertPathValidatorException( + "Algorithm constraints check failed on signature " + + "algorithm: " + currSigAlg, null, null, -1, + BasicReason.ALGORITHM_CONSTRAINED); + } + if (!constraints.permits(primitives, currPubKey)) { throw new CertPathValidatorException( - "algorithm constraints check failed", + "Algorithm constraints check failed on keysize: " + + sun.security.util.KeyUtil.getKeySize(currPubKey), null, null, -1, BasicReason.ALGORITHM_CONSTRAINED); } + } // Check with previous cert for signature algorithm and public key if (prevPubKey != null) { - if (currSigAlg != null) { if (!constraints.permits( SIGNATURE_PRIMITIVE_SET, currSigAlg, prevPubKey, currSigAlgParams)) { throw new CertPathValidatorException( - "Algorithm constraints check failed: " + currSigAlg, + "Algorithm constraints check failed on " + + "signature algorithm: " + currSigAlg, null, null, -1, BasicReason.ALGORITHM_CONSTRAINED); } - } // Inherit key parameters from previous key if (PKIX.isDSAPublicKeyWithoutParams(currPubKey)) { @@ -282,7 +323,7 @@ DSAParams params = ((DSAPublicKey)prevPubKey).getParams(); if (params == null) { throw new CertPathValidatorException( - "Key parameters missing"); + "Key parameters missing from public key."); } try { @@ -330,6 +371,11 @@ // Don't bother to change the trustedPubKey. if (anchor.getTrustedCert() != null) { prevPubKey = anchor.getTrustedCert().getPublicKey(); + // Check for anchor certificate restrictions + trustedMatch = checkFingerprint(anchor.getTrustedCert()); + if (trustedMatch && debug != null) { + debug.println("trustedMatch = true"); + } } else { prevPubKey = anchor.getCAPublicKey(); } @@ -370,7 +416,8 @@ if (!certPathDefaultConstraints.permits( SIGNATURE_PRIMITIVE_SET, sigAlgName, key, sigAlgParams)) { throw new CertPathValidatorException( - "algorithm check failed: " + sigAlgName + " is disabled", + "Algorithm constraints check failed on signature algorithm: " + + sigAlgName + " is disabled", null, null, -1, BasicReason.ALGORITHM_CONSTRAINED); } }
--- a/src/share/classes/sun/security/provider/certpath/PKIXMasterCertPathValidator.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/classes/sun/security/provider/certpath/PKIXMasterCertPathValidator.java Mon Jan 23 16:30:43 2017 +0000 @@ -131,8 +131,8 @@ } catch (CertPathValidatorException cpve) { throw new CertPathValidatorException(cpve.getMessage(), - cpve.getCause(), cpOriginal, cpSize - (i + 1), - cpve.getReason()); + (cpve.getCause() != null) ? cpve.getCause() : cpve, + cpOriginal, cpSize - (i + 1), cpve.getReason()); } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/sun/security/provider/certpath/PKIXTimestampParameters.java Mon Jan 23 16:30:43 2017 +0000 @@ -0,0 +1,218 @@ +/* + * Copyright (c) 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. 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.provider.certpath; + +import java.security.InvalidAlgorithmParameterException; +import java.security.Timestamp; +import java.security.cert.CertSelector; +import java.security.cert.CertStore; +import java.security.cert.PKIXBuilderParameters; +import java.security.cert.PKIXCertPathChecker; +import java.security.cert.TrustAnchor; +import java.util.Date; +import java.util.List; +import java.util.Set; + +/** + * This class is a wrapper for PKIXBuilderParameters so that a Timestamp object + * can be passed alone when PKIXCertPath is checking signed jar files. + */ + +public class PKIXTimestampParameters extends PKIXBuilderParameters { + + private final PKIXBuilderParameters p; + private Timestamp jarTimestamp; + + public PKIXTimestampParameters(PKIXBuilderParameters params, + Timestamp timestamp) throws InvalidAlgorithmParameterException { + super(params.getTrustAnchors(), null); + p = params; + jarTimestamp = timestamp; + } + + public Timestamp getTimestamp() { + return jarTimestamp; + } + public void setTimestamp(Timestamp t) { + jarTimestamp = t; + } + + @Override + public void setDate(Date d) { + p.setDate(d); + } + + @Override + public void addCertPathChecker(PKIXCertPathChecker c) { + p.addCertPathChecker(c); + } + + @Override + public void setMaxPathLength(int maxPathLength) { + p.setMaxPathLength(maxPathLength); + } + + @Override + public int getMaxPathLength() { + return p.getMaxPathLength(); + } + + @Override + public String toString() { + return p.toString(); + } + + @Override + public Set<TrustAnchor> getTrustAnchors() { + return p.getTrustAnchors(); + } + + @Override + public void setTrustAnchors(Set<TrustAnchor> trustAnchors) + throws InvalidAlgorithmParameterException { + // To avoid problems with PKIXBuilderParameter's constructors + if (p == null) { + return; + } + p.setTrustAnchors(trustAnchors); + } + + @Override + public Set<String> getInitialPolicies() { + return p.getInitialPolicies(); + } + + @Override + public void setInitialPolicies(Set<String> initialPolicies) { + p.setInitialPolicies(initialPolicies); + } + + @Override + public void setCertStores(List<CertStore> stores) { + p.setCertStores(stores); + } + + @Override + public void addCertStore(CertStore store) { + p.addCertStore(store); + } + + @Override + public List<CertStore> getCertStores() { + return p.getCertStores(); + } + + @Override + public void setRevocationEnabled(boolean val) { + p.setRevocationEnabled(val); + } + + @Override + public boolean isRevocationEnabled() { + return p.isRevocationEnabled(); + } + + @Override + public void setExplicitPolicyRequired(boolean val) { + p.setExplicitPolicyRequired(val); + } + + @Override + public boolean isExplicitPolicyRequired() { + return p.isExplicitPolicyRequired(); + } + + @Override + public void setPolicyMappingInhibited(boolean val) { + p.setPolicyMappingInhibited(val); + } + + @Override + public boolean isPolicyMappingInhibited() { + return p.isPolicyMappingInhibited(); + } + + @Override + public void setAnyPolicyInhibited(boolean val) { + p.setAnyPolicyInhibited(val); + } + + @Override + public boolean isAnyPolicyInhibited() { + return p.isAnyPolicyInhibited(); + } + + @Override + public void setPolicyQualifiersRejected(boolean qualifiersRejected) { + p.setPolicyQualifiersRejected(qualifiersRejected); + } + + @Override + public boolean getPolicyQualifiersRejected() { + return p.getPolicyQualifiersRejected(); + } + + @Override + public Date getDate() { + return p.getDate(); + } + + @Override + public void setCertPathCheckers(List<PKIXCertPathChecker> checkers) { + p.setCertPathCheckers(checkers); + } + + @Override + public List<PKIXCertPathChecker> getCertPathCheckers() { + return p.getCertPathCheckers(); + } + + @Override + public String getSigProvider() { + return p.getSigProvider(); + } + + @Override + public void setSigProvider(String sigProvider) { + p.setSigProvider(sigProvider); + } + + @Override + public CertSelector getTargetCertConstraints() { + return p.getTargetCertConstraints(); + } + + @Override + public void setTargetCertConstraints(CertSelector selector) { + // To avoid problems with PKIXBuilderParameter's constructors + if (p == null) { + return; + } + p.setTargetCertConstraints(selector); + } + +}
--- a/src/share/classes/sun/security/rsa/RSASignature.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/classes/sun/security/rsa/RSASignature.java Mon Jan 23 16:30:43 2017 +0000 @@ -223,9 +223,10 @@ * Decode the signature data. Verify that the object identifier matches * and return the message digest. */ - public static byte[] decodeSignature(ObjectIdentifier oid, byte[] signature) + public static byte[] decodeSignature(ObjectIdentifier oid, byte[] sig) throws IOException { - DerInputStream in = new DerInputStream(signature); + // Enforce strict DER checking for signatures + DerInputStream in = new DerInputStream(sig, 0, sig.length, false); DerValue[] values = in.getSequence(2); if ((values.length != 2) || (in.available() != 0)) { throw new IOException("SEQUENCE length error");
--- a/src/share/classes/sun/security/ssl/CipherSuite.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/classes/sun/security/ssl/CipherSuite.java Mon Jan 23 16:30:43 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -326,36 +326,38 @@ static enum KeyExchange { // key exchange algorithms - K_NULL ("NULL", false), - K_RSA ("RSA", true), - K_RSA_EXPORT ("RSA_EXPORT", true), - K_DH_RSA ("DH_RSA", false), - K_DH_DSS ("DH_DSS", false), - K_DHE_DSS ("DHE_DSS", true), - K_DHE_RSA ("DHE_RSA", true), - K_DH_ANON ("DH_anon", true), + K_NULL ("NULL", false, false), + K_RSA ("RSA", true, false), + K_RSA_EXPORT ("RSA_EXPORT", true, false), + K_DH_RSA ("DH_RSA", false, false), + K_DH_DSS ("DH_DSS", false, false), + K_DHE_DSS ("DHE_DSS", true, false), + K_DHE_RSA ("DHE_RSA", true, false), + K_DH_ANON ("DH_anon", true, false), - K_ECDH_ECDSA ("ECDH_ECDSA", ALLOW_ECC), - K_ECDH_RSA ("ECDH_RSA", ALLOW_ECC), - K_ECDHE_ECDSA("ECDHE_ECDSA", ALLOW_ECC), - K_ECDHE_RSA ("ECDHE_RSA", ALLOW_ECC), - K_ECDH_ANON ("ECDH_anon", ALLOW_ECC), + K_ECDH_ECDSA ("ECDH_ECDSA", ALLOW_ECC, true), + K_ECDH_RSA ("ECDH_RSA", ALLOW_ECC, true), + K_ECDHE_ECDSA("ECDHE_ECDSA", ALLOW_ECC, true), + K_ECDHE_RSA ("ECDHE_RSA", ALLOW_ECC, true), + K_ECDH_ANON ("ECDH_anon", ALLOW_ECC, true), // Kerberos cipher suites - K_KRB5 ("KRB5", true), - K_KRB5_EXPORT("KRB5_EXPORT", true), + K_KRB5 ("KRB5", true, false), + K_KRB5_EXPORT("KRB5_EXPORT", true, false), // renegotiation protection request signaling cipher suite - K_SCSV ("SCSV", true); + K_SCSV ("SCSV", true, false); // name of the key exchange algorithm, e.g. DHE_DSS final String name; final boolean allowed; + final boolean isEC; private final boolean alwaysAvailable; - KeyExchange(String name, boolean allowed) { + KeyExchange(String name, boolean allowed, boolean isEC) { this.name = name; this.allowed = allowed; + this.isEC = isEC; this.alwaysAvailable = allowed && (!name.startsWith("EC")) && (!name.startsWith("KRB")); } @@ -365,7 +367,7 @@ return true; } - if (name.startsWith("EC")) { + if (isEC) { return (allowed && JsseJce.isEcAvailable()); } else if (name.startsWith("KRB")) { return (allowed && JsseJce.isKerberosAvailable());
--- a/src/share/classes/sun/security/ssl/CipherSuiteList.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/classes/sun/security/ssl/CipherSuiteList.java Mon Jan 23 16:30:43 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -112,20 +112,15 @@ boolean containsEC() { if (containsEC == null) { for (CipherSuite c : cipherSuites) { - switch (c.keyExchange) { - case K_ECDH_ECDSA: - case K_ECDH_RSA: - case K_ECDHE_ECDSA: - case K_ECDHE_RSA: - case K_ECDH_ANON: + if (c.keyExchange.isEC) { containsEC = true; return true; - default: - break; } } + containsEC = false; } + return containsEC; }
--- a/src/share/classes/sun/security/ssl/ClientHandshaker.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/classes/sun/security/ssl/ClientHandshaker.java Mon Jan 23 16:30:43 2017 +0000 @@ -621,8 +621,11 @@ } else { // we wanted to resume, but the server refused // - // Invalidate the session in case of reusing next time. - session.invalidate(); + // Invalidate the session for initial handshake in case + // of reusing next time. + if (isInitialHandshake) { + session.invalidate(); + } session = null; if (!enableNewSession) { throw new SSLException("New session creation is disabled"); @@ -762,30 +765,33 @@ String typeName; switch (certRequest.types[i]) { - case CertificateRequest.cct_rsa_sign: - typeName = "RSA"; - break; + case CertificateRequest.cct_rsa_sign: + typeName = "RSA"; + break; - case CertificateRequest.cct_dss_sign: - typeName = "DSA"; - break; + case CertificateRequest.cct_dss_sign: + typeName = "DSA"; + break; + + case CertificateRequest.cct_ecdsa_sign: + // ignore if we do not have EC crypto available + typeName = JsseJce.isEcAvailable() ? "EC" : null; + break; - case CertificateRequest.cct_ecdsa_sign: - // ignore if we do not have EC crypto available - typeName = JsseJce.isEcAvailable() ? "EC" : null; - break; - - // Fixed DH/ECDH client authentication not supported - case CertificateRequest.cct_rsa_fixed_dh: - case CertificateRequest.cct_dss_fixed_dh: - case CertificateRequest.cct_rsa_fixed_ecdh: - case CertificateRequest.cct_ecdsa_fixed_ecdh: - // Any other values (currently not used in TLS) - case CertificateRequest.cct_rsa_ephemeral_dh: - case CertificateRequest.cct_dss_ephemeral_dh: - default: - typeName = null; - break; + // Fixed DH/ECDH client authentication not supported + // + // case CertificateRequest.cct_rsa_fixed_dh: + // case CertificateRequest.cct_dss_fixed_dh: + // case CertificateRequest.cct_rsa_fixed_ecdh: + // case CertificateRequest.cct_ecdsa_fixed_ecdh: + // + // Any other values (currently not used in TLS) + // + // case CertificateRequest.cct_rsa_ephemeral_dh: + // case CertificateRequest.cct_dss_ephemeral_dh: + default: + typeName = null; + break; } if ((typeName != null) && (!keytypesTmp.contains(typeName))) { @@ -813,18 +819,6 @@ X509Certificate[] certs = km.getCertificateChain(alias); if ((certs != null) && (certs.length != 0)) { PublicKey publicKey = certs[0].getPublicKey(); - // for EC, make sure we use a supported named curve - if (publicKey instanceof ECPublicKey) { - ECParameterSpec params = - ((ECPublicKey)publicKey).getParams(); - int index = - SupportedEllipticCurvesExtension.getCurveIndex( - params); - if (!SupportedEllipticCurvesExtension.isSupported( - index)) { - publicKey = null; - } - } if (publicKey != null) { m1 = new CertificateMsg(certs); signingKey = km.getPrivateKey(alias); @@ -1385,6 +1379,17 @@ sslContext.getSecureRandom(), maxProtocolVersion, sessionId, cipherSuites); + // add elliptic curves and point format extensions + if (cipherSuites.containsEC()) { + SupportedEllipticCurvesExtension ece = + SupportedEllipticCurvesExtension.createExtension(algorithmConstraints); + if (ece != null) { + clientHelloMessage.extensions.add(ece); + clientHelloMessage.extensions.add( + SupportedEllipticPointFormatsExtension.DEFAULT); + } + } + // add signature_algorithm extension if (maxProtocolVersion.v >= ProtocolVersion.TLS12.v) { // we will always send the signature_algorithm extension
--- a/src/share/classes/sun/security/ssl/ECDHCrypt.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/classes/sun/security/ssl/ECDHCrypt.java Mon Jan 23 16:30:43 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 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 @@ -56,10 +56,11 @@ } // Called by ServerHandshaker for ephemeral ECDH - ECDHCrypt(String curveName, SecureRandom random) { + ECDHCrypt(int curveId, SecureRandom random) { try { KeyPairGenerator kpg = JsseJce.getKeyPairGenerator("EC"); - ECGenParameterSpec params = new ECGenParameterSpec(curveName); + ECGenParameterSpec params = + SupportedEllipticCurvesExtension.getECGenParamSpec(curveId); kpg.initialize(params, random); KeyPair kp = kpg.generateKeyPair(); privateKey = kp.getPrivate();
--- a/src/share/classes/sun/security/ssl/HandshakeMessage.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/classes/sun/security/ssl/HandshakeMessage.java Mon Jan 23 16:30:43 2017 +0000 @@ -230,11 +230,6 @@ this.sessionId = sessionId; this.cipherSuites = cipherSuites; - if (cipherSuites.containsEC()) { - extensions.add(SupportedEllipticCurvesExtension.DEFAULT); - extensions.add(SupportedEllipticPointFormatsExtension.DEFAULT); - } - clnt_random = new RandomCookie(generator); compression_methods = NULL_COMPRESSION; }
--- a/src/share/classes/sun/security/ssl/Handshaker.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/classes/sun/security/ssl/Handshaker.java Mon Jan 23 16:30:43 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 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 @@ -636,13 +636,41 @@ ArrayList<CipherSuite> suites = new ArrayList<>(); if (!(activeProtocols.collection().isEmpty()) && activeProtocols.min.v != ProtocolVersion.NONE.v) { + boolean checkedCurves = false; + boolean hasCurves = false; for (CipherSuite suite : enabledCipherSuites.collection()) { if (suite.obsoleted > activeProtocols.min.v && suite.supported <= activeProtocols.max.v) { if (algorithmConstraints.permits( EnumSet.of(CryptoPrimitive.KEY_AGREEMENT), suite.name, null)) { - suites.add(suite); + boolean available = true; + if (suite.keyExchange.isEC) { + if (!checkedCurves) { + hasCurves = SupportedEllipticCurvesExtension + .hasActiveCurves(algorithmConstraints); + checkedCurves = true; + + if (!hasCurves && debug != null && + Debug.isOn("verbose")) { + System.out.println( + "No available elliptic curves"); + } + } + + available = hasCurves; + + if (!available && debug != null && + Debug.isOn("verbose")) { + System.out.println( + "No active elliptic curves, ignore " + + suite); + } + } + + if (available) { + suites.add(suite); + } } } else if (debug != null && Debug.isOn("verbose")) { if (suite.obsoleted <= activeProtocols.min.v) { @@ -679,18 +707,10 @@ ProtocolList getActiveProtocols() { if (activeProtocols == null) { boolean enabledSSL20Hello = false; + boolean checkedCurves = false; + boolean hasCurves = false; ArrayList<ProtocolVersion> protocols = new ArrayList<>(4); for (ProtocolVersion protocol : enabledProtocols.collection()) { - if (!algorithmConstraints.permits( - EnumSet.of(CryptoPrimitive.KEY_AGREEMENT), - protocol.name, null)) { - if (debug != null && Debug.isOn("verbose")) { - System.out.println( - "Ignoring disabled protocol: " + protocol); - } - - continue; - } // Need not to check the SSL20Hello protocol. if (protocol.v == ProtocolVersion.SSL20Hello.v) { enabledSSL20Hello = true; @@ -714,9 +734,36 @@ if (algorithmConstraints.permits( EnumSet.of(CryptoPrimitive.KEY_AGREEMENT), suite.name, null)) { - protocols.add(protocol); - found = true; - break; + + boolean available = true; + if (suite.keyExchange.isEC) { + if (!checkedCurves) { + hasCurves = SupportedEllipticCurvesExtension + .hasActiveCurves(algorithmConstraints); + checkedCurves = true; + + if (!hasCurves && debug != null && + Debug.isOn("verbose")) { + System.out.println( + "No activated elliptic curves"); + } + } + + available = hasCurves; + + if (!available && debug != null && + Debug.isOn("verbose")) { + System.out.println( + "No active elliptic curves, ignore " + + suite + " for " + protocol); + } + } + + if (available) { + protocols.add(protocol); + found = true; + break; + } } else if (debug != null && Debug.isOn("verbose")) { System.out.println( "Ignoring disabled cipher suite: " + suite +
--- a/src/share/classes/sun/security/ssl/JsseJce.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/classes/sun/security/ssl/JsseJce.java Mon Jan 23 16:30:43 2017 +0000 @@ -290,6 +290,15 @@ } } + static AlgorithmParameters getAlgorithmParameters(String algorithm) + throws NoSuchAlgorithmException { + if (cryptoProvider == null) { + return AlgorithmParameters.getInstance(algorithm); + } else { + return AlgorithmParameters.getInstance(algorithm, cryptoProvider); + } + } + static SecureRandom getSecureRandom() throws KeyManagementException { if (cryptoProvider == null) { return new SecureRandom(); @@ -409,6 +418,7 @@ JsseJce.getKeyAgreement("ECDH"); JsseJce.getKeyFactory("EC"); JsseJce.getKeyPairGenerator("EC"); + JsseJce.getAlgorithmParameters("EC"); } catch (Exception e) { mediator = false; }
--- a/src/share/classes/sun/security/ssl/ServerHandshaker.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/classes/sun/security/ssl/ServerHandshaker.java Mon Jan 23 16:30:43 2017 +0000 @@ -92,7 +92,8 @@ // we remember it for the RSA premaster secret version check private ProtocolVersion clientRequestedVersion; - private SupportedEllipticCurvesExtension supportedCurves; + // client supported elliptic curves + private SupportedEllipticCurvesExtension requestedCurves; // the preferable signature algorithm used by ServerKeyExchange message SignatureAndHashAlgorithm preferableSignatureAlgorithm; @@ -682,7 +683,7 @@ throw new SSLException("Client did not resume a session"); } - supportedCurves = (SupportedEllipticCurvesExtension) + requestedCurves = (SupportedEllipticCurvesExtension) mesg.extensions.get(ExtensionType.EXT_ELLIPTIC_CURVES); // We only need to handle the "signature_algorithm" extension @@ -1025,11 +1026,18 @@ if (trySetCipherSuite(suite) == false) { continue; } + + if (debug != null && Debug.isOn("handshake")) { + System.out.println("Standard ciphersuite chosen: " + suite); + } return; } for (CipherSuite suite : legacySuites) { if (trySetCipherSuite(suite)) { + if (debug != null && Debug.isOn("handshake")) { + System.out.println("Legacy ciphersuite chosen: " + suite); + } return; } } @@ -1412,26 +1420,15 @@ // If we cannot continue because we do not support any of the curves that // the client requested, return false. Otherwise (all is well), return true. private boolean setupEphemeralECDHKeys() { - int index = -1; - if (supportedCurves != null) { - // if the client sent the supported curves extension, pick the - // first one that we support; - for (int curveId : supportedCurves.curveIds()) { - if (SupportedEllipticCurvesExtension.isSupported(curveId)) { - index = curveId; - break; - } - } - if (index < 0) { - // no match found, cannot use this ciphersuite - return false; - } - } else { - // pick our preference - index = SupportedEllipticCurvesExtension.DEFAULT.curveIds()[0]; + int index = (requestedCurves != null) ? + requestedCurves.getPreferredCurve(algorithmConstraints) : + SupportedEllipticCurvesExtension.getActiveCurves(algorithmConstraints); + if (index < 0) { + // no match found, cannot use this ciphersuite + return false; } - String oid = SupportedEllipticCurvesExtension.getCurveOid(index); - ecdh = new ECDHCrypt(oid, sslContext.getSecureRandom()); + + ecdh = new ECDHCrypt(index, sslContext.getSecureRandom()); return true; } @@ -1480,11 +1477,9 @@ return false; } ECParameterSpec params = ((ECPublicKey)publicKey).getParams(); - int index = SupportedEllipticCurvesExtension.getCurveIndex(params); - if (SupportedEllipticCurvesExtension.isSupported(index) == false) { - return false; - } - if ((supportedCurves != null) && !supportedCurves.contains(index)) { + int id = SupportedEllipticCurvesExtension.getCurveIndex(params); + if ((id <= 0) || !SupportedEllipticCurvesExtension.isSupported(id) || + ((requestedCurves != null) && !requestedCurves.contains(id))) { return false; } }
--- a/src/share/classes/sun/security/ssl/SupportedEllipticCurvesExtension.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/classes/sun/security/ssl/SupportedEllipticCurvesExtension.java Mon Jan 23 16:30:43 2017 +0000 @@ -27,39 +27,195 @@ import java.io.IOException; import java.security.spec.ECParameterSpec; +import java.security.spec.ECGenParameterSpec; +import java.security.spec.InvalidParameterSpecException; +import java.security.AlgorithmParameters; +import java.security.AlgorithmConstraints; +import java.security.CryptoPrimitive; +import java.security.AccessController; +import java.util.EnumSet; import java.util.HashMap; import java.util.Map; +import java.util.ArrayList; +import javax.net.ssl.SSLProtocolException; -import javax.net.ssl.SSLProtocolException; +import sun.security.action.GetPropertyAction; final class SupportedEllipticCurvesExtension extends HelloExtension { - // the extension value to send in the ClientHello message - static final SupportedEllipticCurvesExtension DEFAULT; + private static final int ARBITRARY_PRIME = 0xff01; + private static final int ARBITRARY_CHAR2 = 0xff02; + + // speed up the searching + private static final Map<String, Integer> oidToIdMap = new HashMap<>(); + private static final Map<Integer, String> idToOidMap = new HashMap<>(); + + // speed up the parameters construction + private static final Map<Integer, + AlgorithmParameters> idToParams = new HashMap<>(); + + // the supported elliptic curves + private static final int[] supportedCurveIds; + + // the curves of the extension + private final int[] curveIds; + + // See sun.security.util.CurveDB for the OIDs + private static enum NamedEllipticCurve { + T163_K1(1, "sect163k1", "1.3.132.0.1", true), // NIST K-163 + T163_R1(2, "sect163r1", "1.3.132.0.2", false), + T163_R2(3, "sect163r2", "1.3.132.0.15", true), // NIST B-163 + T193_R1(4, "sect193r1", "1.3.132.0.24", false), + T193_R2(5, "sect193r2", "1.3.132.0.25", false), + T233_K1(6, "sect233k1", "1.3.132.0.26", true), // NIST K-233 + T233_R1(7, "sect233r1", "1.3.132.0.27", true), // NIST B-233 + T239_K1(8, "sect239k1", "1.3.132.0.3", false), + T283_K1(9, "sect283k1", "1.3.132.0.16", true), // NIST K-283 + T283_R1(10, "sect283r1", "1.3.132.0.17", true), // NIST B-283 + T409_K1(11, "sect409k1", "1.3.132.0.36", true), // NIST K-409 + T409_R1(12, "sect409r1", "1.3.132.0.37", true), // NIST B-409 + T571_K1(13, "sect571k1", "1.3.132.0.38", true), // NIST K-571 + T571_R1(14, "sect571r1", "1.3.132.0.39", true), // NIST B-571 - private static final boolean fips; + P160_K1(15, "secp160k1", "1.3.132.0.9", false), + P160_R1(16, "secp160r1", "1.3.132.0.8", false), + P160_R2(17, "secp160r2", "1.3.132.0.30", false), + P192_K1(18, "secp192k1", "1.3.132.0.31", false), + P192_R1(19, "secp192r1", "1.2.840.10045.3.1.1", true), // NIST P-192 + P224_K1(20, "secp224k1", "1.3.132.0.32", false), + P224_R1(21, "secp224r1", "1.3.132.0.33", true), // NIST P-224 + P256_K1(22, "secp256k1", "1.3.132.0.10", false), + P256_R1(23, "secp256r1", "1.2.840.10045.3.1.7", true), // NIST P-256 + P384_R1(24, "secp384r1", "1.3.132.0.34", true), // NIST P-384 + P521_R1(25, "secp521r1", "1.3.132.0.35", true); // NIST P-521 + + int id; + String name; + String oid; + boolean isFips; + + NamedEllipticCurve(int id, String name, String oid, boolean isFips) { + this.id = id; + this.name = name; + this.oid = oid; + this.isFips = isFips; + + if (oidToIdMap.put(oid, id) != null || + idToOidMap.put(id, oid) != null) { + + throw new RuntimeException( + "Duplicate named elliptic curve definition: " + name); + } + } + + static NamedEllipticCurve getCurve(String name, boolean requireFips) { + for (NamedEllipticCurve curve : NamedEllipticCurve.values()) { + if (curve.name.equals(name) && (!requireFips || curve.isFips)) { + return curve; + } + } + + return null; + } + } static { - int[] ids; - fips = SunJSSE.isFIPS(); - if (fips == false) { - ids = new int[] { - // NIST curves first - // prefer NIST P-256, rest in order of increasing key length - 23, 1, 3, 19, 21, 6, 7, 9, 10, 24, 11, 12, 25, 13, 14, - // non-NIST curves - 15, 16, 17, 2, 18, 4, 5, 20, 8, 22, - }; + boolean requireFips = SunJSSE.isFIPS(); + + // hack code to initialize NamedEllipticCurve + NamedEllipticCurve nec = + NamedEllipticCurve.getCurve("secp256r1", false); + + // The value of the System Property defines a list of enabled named + // curves in preference order, separated with comma. For example: + // + // jdk.tls.namedGroups="secp521r1, secp256r1, secp384r1" + // + // If the System Property is not defined or the value is empty, the + // default curves and preferences will be used. + String property = AccessController.doPrivileged( + new GetPropertyAction("jdk.tls.namedGroups")); + if (property != null && property.length() != 0) { + // remove double quote marks from beginning/end of the property + if (property.length() > 1 && property.charAt(0) == '"' && + property.charAt(property.length() - 1) == '"') { + property = property.substring(1, property.length() - 1); + } + } + + ArrayList<Integer> idList; + if (property != null && property.length() != 0) { // customized curves + String[] curves = property.split(","); + idList = new ArrayList<>(curves.length); + for (String curve : curves) { + curve = curve.trim(); + if (!curve.isEmpty()) { + NamedEllipticCurve namedCurve = + NamedEllipticCurve.getCurve(curve, requireFips); + if (namedCurve != null) { + if (isAvailableCurve(namedCurve.id)) { + idList.add(namedCurve.id); + } + } // ignore unknown curves + } + } + } else { // default curves + int[] ids; + if (requireFips) { + ids = new int[] { + // only NIST curves in FIPS mode + 23, 24, 25, 9, 10, 11, 12, 13, 14, + }; + } else { + ids = new int[] { + // NIST curves first + 23, 24, 25, 9, 10, 11, 12, 13, 14, + // non-NIST curves + 22, + }; + } + + idList = new ArrayList<>(ids.length); + for (int curveId : ids) { + if (isAvailableCurve(curveId)) { + idList.add(curveId); + } + } + } + + if (idList.isEmpty()) { + throw new IllegalArgumentException( + "System property jdk.tls.namedGroups(" + property + ") " + + "contains no supported elliptic curves"); } else { - ids = new int[] { - // same as above, but allow only NIST curves in FIPS mode - 23, 1, 3, 19, 21, 6, 7, 9, 10, 24, 11, 12, 25, 13, 14, - }; + supportedCurveIds = new int[idList.size()]; + int i = 0; + for (Integer id : idList) { + supportedCurveIds[i++] = id; + } } - DEFAULT = new SupportedEllipticCurvesExtension(ids); } - private final int[] curveIds; + // check whether the curve is supported by the underlying providers + private static boolean isAvailableCurve(int curveId) { + String oid = idToOidMap.get(curveId); + if (oid != null) { + AlgorithmParameters params = null; + try { + params = JsseJce.getAlgorithmParameters("EC"); + params.init(new ECGenParameterSpec(oid)); + } catch (Exception e) { + return false; + } + + // cache the parameters + idToParams.put(curveId, params); + + return true; + } + + return false; + } private SupportedEllipticCurvesExtension(int[] curveIds) { super(ExtensionType.EXT_ELLIPTIC_CURVES); @@ -73,12 +229,67 @@ if (((len & 1) != 0) || (k + 2 != len)) { throw new SSLProtocolException("Invalid " + type + " extension"); } + + // Note: unknown curves will be ignored later. curveIds = new int[k >> 1]; for (int i = 0; i < curveIds.length; i++) { curveIds[i] = s.getInt16(); } } + // get the preferred active curve + static int getActiveCurves(AlgorithmConstraints constraints) { + return getPreferredCurve(supportedCurveIds, constraints); + } + + static boolean hasActiveCurves(AlgorithmConstraints constraints) { + return getActiveCurves(constraints) >= 0; + } + + static SupportedEllipticCurvesExtension createExtension( + AlgorithmConstraints constraints) { + + ArrayList<Integer> idList = new ArrayList<>(supportedCurveIds.length); + for (int curveId : supportedCurveIds) { + if (constraints.permits( + EnumSet.of(CryptoPrimitive.KEY_AGREEMENT), + "EC", idToParams.get(curveId))) { + idList.add(curveId); + } + } + + if (!idList.isEmpty()) { + int[] ids = new int[idList.size()]; + int i = 0; + for (Integer id : idList) { + ids[i++] = id; + } + + return new SupportedEllipticCurvesExtension(ids); + } + + return null; + } + + // get the preferred activated curve + int getPreferredCurve(AlgorithmConstraints constraints) { + return getPreferredCurve(curveIds, constraints); + } + + // get a preferred activated curve + private static int getPreferredCurve(int[] curves, + AlgorithmConstraints constraints) { + for (int curveId : curves) { + if (isSupported(curveId) && constraints.permits( + EnumSet.of(CryptoPrimitive.KEY_AGREEMENT), + "EC", idToParams.get(curveId))) { + return curveId; + } + } + + return -1; + } + boolean contains(int index) { for (int curveId : curveIds) { if (index == curveId) { @@ -88,12 +299,6 @@ return false; } - // Return a reference to the internal curveIds array. - // The caller must NOT modify the contents. - int[] curveIds() { - return curveIds; - } - @Override int length() { return 6 + (curveIds.length << 1); @@ -121,18 +326,9 @@ } else { sb.append(", "); } - // first check if it is a known named curve, then try other cases. - String oid = getCurveOid(curveId); - if (oid != null) { - ECParameterSpec spec = JsseJce.getECParameterSpec(oid); - // this toString() output will look nice for the current - // implementation of the ECParameterSpec class in the Sun - // provider, but may not look good for other implementations. - if (spec != null) { - sb.append(spec.toString().split(" ")[0]); - } else { - sb.append(oid); - } + String curveName = getCurveName(curveId); + if (curveName != null) { + sb.append(curveName); } else if (curveId == ARBITRARY_PRIME) { sb.append("arbitrary_explicit_prime_curves"); } else if (curveId == ARBITRARY_CHAR2) { @@ -145,16 +341,15 @@ return sb.toString(); } - // Test whether we support the curve with the given index. + // Test whether the given curve is supported. static boolean isSupported(int index) { - if ((index <= 0) || (index >= NAMED_CURVE_OID_TABLE.length)) { - return false; + for (int curveId : supportedCurveIds) { + if (index == curveId) { + return true; + } } - if (fips == false) { - // in non-FIPS mode, we support all valid indices - return true; - } - return DEFAULT.contains(index); + + return false; } static int getCurveIndex(ECParameterSpec params) { @@ -162,57 +357,32 @@ if (oid == null) { return -1; } - Integer n = curveIndices.get(oid); + Integer n = oidToIdMap.get(oid); return (n == null) ? -1 : n; } static String getCurveOid(int index) { - if ((index > 0) && (index < NAMED_CURVE_OID_TABLE.length)) { - return NAMED_CURVE_OID_TABLE[index]; - } - return null; + return idToOidMap.get(index); } - private final static int ARBITRARY_PRIME = 0xff01; - private final static int ARBITRARY_CHAR2 = 0xff02; - - // See sun.security.ec.NamedCurve for the OIDs - private final static String[] NAMED_CURVE_OID_TABLE = new String[] { - null, // (0) unused - "1.3.132.0.1", // (1) sect163k1, NIST K-163 - "1.3.132.0.2", // (2) sect163r1 - "1.3.132.0.15", // (3) sect163r2, NIST B-163 - "1.3.132.0.24", // (4) sect193r1 - "1.3.132.0.25", // (5) sect193r2 - "1.3.132.0.26", // (6) sect233k1, NIST K-233 - "1.3.132.0.27", // (7) sect233r1, NIST B-233 - "1.3.132.0.3", // (8) sect239k1 - "1.3.132.0.16", // (9) sect283k1, NIST K-283 - "1.3.132.0.17", // (10) sect283r1, NIST B-283 - "1.3.132.0.36", // (11) sect409k1, NIST K-409 - "1.3.132.0.37", // (12) sect409r1, NIST B-409 - "1.3.132.0.38", // (13) sect571k1, NIST K-571 - "1.3.132.0.39", // (14) sect571r1, NIST B-571 - "1.3.132.0.9", // (15) secp160k1 - "1.3.132.0.8", // (16) secp160r1 - "1.3.132.0.30", // (17) secp160r2 - "1.3.132.0.31", // (18) secp192k1 - "1.2.840.10045.3.1.1", // (19) secp192r1, NIST P-192 - "1.3.132.0.32", // (20) secp224k1 - "1.3.132.0.33", // (21) secp224r1, NIST P-224 - "1.3.132.0.10", // (22) secp256k1 - "1.2.840.10045.3.1.7", // (23) secp256r1, NIST P-256 - "1.3.132.0.34", // (24) secp384r1, NIST P-384 - "1.3.132.0.35", // (25) secp521r1, NIST P-521 - }; - - private final static Map<String,Integer> curveIndices; - - static { - curveIndices = new HashMap<String,Integer>(); - for (int i = 1; i < NAMED_CURVE_OID_TABLE.length; i++) { - curveIndices.put(NAMED_CURVE_OID_TABLE[i], i); + static ECGenParameterSpec getECGenParamSpec(int index) { + AlgorithmParameters params = idToParams.get(index); + try { + return params.getParameterSpec(ECGenParameterSpec.class); + } catch (InvalidParameterSpecException ipse) { + // should be unlikely + String curveOid = getCurveOid(index); + return new ECGenParameterSpec(curveOid); } } + private static String getCurveName(int index) { + for (NamedEllipticCurve namedCurve : NamedEllipticCurve.values()) { + if (namedCurve.id == index) { + return namedCurve.name; + } + } + + return null; + } }
--- a/src/share/classes/sun/security/tools/jarsigner/Main.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/classes/sun/security/tools/jarsigner/Main.java Mon Jan 23 16:30:43 2017 +0000 @@ -53,6 +53,9 @@ import java.security.cert.PKIXParameters; import java.security.cert.TrustAnchor; import java.util.Map.Entry; +import sun.security.pkcs.PKCS7; +import sun.security.pkcs.SignerInfo; +import sun.security.timestamp.TimestampToken; import sun.security.tools.KeyStoreUtil; import sun.security.tools.PathList; import sun.security.x509.*; @@ -97,6 +100,15 @@ private static final long SIX_MONTHS = 180*24*60*60*1000L; //milliseconds + private static final DisabledAlgorithmConstraints DISABLED_CHECK = + new DisabledAlgorithmConstraints( + DisabledAlgorithmConstraints.PROPERTY_JAR_DISABLED_ALGS); + + private static final Set<CryptoPrimitive> DIGEST_PRIMITIVE_SET = Collections + .unmodifiableSet(EnumSet.of(CryptoPrimitive.MESSAGE_DIGEST)); + private static final Set<CryptoPrimitive> SIG_PRIMITIVE_SET = Collections + .unmodifiableSet(EnumSet.of(CryptoPrimitive.SIGNATURE)); + // Attention: // This is the entry that get launched by the security tool jarsigner. public static void main(String args[]) throws Exception { @@ -172,6 +184,8 @@ private boolean badExtendedKeyUsage = false; private boolean badNetscapeCertType = false; + private boolean seeWeak = false; + CertificateFactory certificateFactory; CertPathValidator validator; PKIXParameters pkixParameters; @@ -577,6 +591,10 @@ { boolean anySigned = false; // if there exists entry inside jar signed JarFile jf = null; + Map<String,String> digestMap = new HashMap<>(); + Map<String,PKCS7> sigMap = new HashMap<>(); + Map<String,String> sigNameMap = new HashMap<>(); + Map<String,String> unparsableSignatures = new HashMap<>(); try { jf = new JarFile(jarName, true); @@ -587,17 +605,44 @@ while (entries.hasMoreElements()) { JarEntry je = entries.nextElement(); entriesVec.addElement(je); - InputStream is = null; + try (InputStream is = jf.getInputStream(je)) { + String name = je.getName(); + if (signatureRelated(name) + && SignatureFileVerifier.isBlockOrSF(name)) { + String alias = name.substring(name.lastIndexOf('/') + 1, + name.lastIndexOf('.')); try { - is = jf.getInputStream(je); - int n; - while ((n = is.read(buffer, 0, buffer.length)) != -1) { + if (name.endsWith(".SF")) { + Manifest sf = new Manifest(is); + boolean found = false; + for (Object obj : sf.getMainAttributes().keySet()) { + String key = obj.toString(); + if (key.endsWith("-Digest-Manifest")) { + digestMap.put(alias, + key.substring(0, key.length() - 16)); + found = true; + break; + } + } + if (!found) { + unparsableSignatures.putIfAbsent(alias, + String.format( + rb.getString("history.unparsable"), + name)); + } + } else { + sigNameMap.put(alias, name); + sigMap.put(alias, new PKCS7(is)); + } + } catch (IOException ioe) { + unparsableSignatures.putIfAbsent(alias, String.format( + rb.getString("history.unparsable"), name)); + } + } else { + while (is.read(buffer, 0, buffer.length) != -1) { // we just read. this will throw a SecurityException // if a signature/digest check fails. } - } finally { - if (is != null) { - is.close(); } } } @@ -756,13 +801,106 @@ System.out.println(rb.getString( ".X.not.signed.by.specified.alias.es.")); } + } + if (man == null) { + System.out.println(); + System.out.println(rb.getString("no.manifest.")); + } + + // Even if the verbose option is not specified, all out strings + // must be generated so seeWeak can be updated. + if (!digestMap.isEmpty() + || !sigMap.isEmpty() + || !unparsableSignatures.isEmpty()) { + if (verbose != null) { System.out.println(); } - if (man == null) - System.out.println(rb.getString("no.manifest.")); + for (String s : sigMap.keySet()) { + if (!digestMap.containsKey(s)) { + unparsableSignatures.putIfAbsent(s, String.format( + rb.getString("history.nosf"), s)); + } + } + for (String s : digestMap.keySet()) { + PKCS7 p7 = sigMap.get(s); + if (p7 != null) { + String history; + try { + SignerInfo si = p7.getSignerInfos()[0]; + X509Certificate signer = si.getCertificate(p7); + String digestAlg = digestMap.get(s); + String sigAlg = AlgorithmId.makeSigAlg( + si.getDigestAlgorithmId().getName(), + si.getDigestEncryptionAlgorithmId().getName()); + PublicKey key = signer.getPublicKey(); + PKCS7 tsToken = si.getTsToken(); + if (tsToken != null) { + SignerInfo tsSi = tsToken.getSignerInfos()[0]; + X509Certificate tsSigner = tsSi.getCertificate(tsToken); + byte[] encTsTokenInfo = tsToken.getContentInfo().getData(); + TimestampToken tsTokenInfo = new TimestampToken(encTsTokenInfo); + PublicKey tsKey = tsSigner.getPublicKey(); + String tsDigestAlg = tsTokenInfo.getHashAlgorithm().getName(); + String tsSigAlg = AlgorithmId.makeSigAlg( + tsSi.getDigestAlgorithmId().getName(), + tsSi.getDigestEncryptionAlgorithmId().getName()); + Calendar c = Calendar.getInstance( + TimeZone.getTimeZone("UTC"), + Locale.getDefault(Locale.Category.FORMAT)); + c.setTime(tsTokenInfo.getDate()); + history = String.format( + rb.getString("history.with.ts"), + signer.getSubjectX500Principal(), + withWeak(digestAlg, DIGEST_PRIMITIVE_SET), + withWeak(sigAlg, SIG_PRIMITIVE_SET), + withWeak(key), + c, + tsSigner.getSubjectX500Principal(), + withWeak(tsDigestAlg, DIGEST_PRIMITIVE_SET), + withWeak(tsSigAlg, SIG_PRIMITIVE_SET), + withWeak(tsKey)); + } else { + history = String.format( + rb.getString("history.without.ts"), + signer.getSubjectX500Principal(), + withWeak(digestAlg, DIGEST_PRIMITIVE_SET), + withWeak(sigAlg, SIG_PRIMITIVE_SET), + withWeak(key)); + } + } catch (Exception e) { + // The only usage of sigNameMap, remember the name + // of the block file if it's invalid. + history = String.format( + rb.getString("history.unparsable"), + sigNameMap.get(s)); + } + if (verbose != null) { + System.out.println(history); + } + } else { + unparsableSignatures.putIfAbsent(s, String.format( + rb.getString("history.nobk"), s)); + } + } + if (verbose != null) { + for (String s : unparsableSignatures.keySet()) { + System.out.println(unparsableSignatures.get(s)); + } + } + } + System.out.println(); if (!anySigned) { - if (hasSignature) { + if (seeWeak) { + if (verbose != null) { + System.out.println(rb.getString("jar.treated.unsigned.see.weak.verbose")); + System.out.println("\n " + + DisabledAlgorithmConstraints.PROPERTY_JAR_DISABLED_ALGS + + "=" + Security.getProperty(DisabledAlgorithmConstraints.PROPERTY_JAR_DISABLED_ALGS)); + } else { + System.out.println(rb.getString("jar.treated.unsigned.see.weak")); + } + } else if (hasSignature) { System.out.println(rb.getString("jar.treated.unsigned")); } else { System.out.println(rb.getString("jar.is.unsigned")); @@ -869,6 +1007,26 @@ System.exit(1); } + private String withWeak(String alg, Set<CryptoPrimitive> primitiveSet) { + if (DISABLED_CHECK.permits(primitiveSet, alg, null)) { + return alg; + } else { + seeWeak = true; + return String.format(rb.getString("with.weak"), alg); + } + } + + private String withWeak(PublicKey key) { + if (DISABLED_CHECK.permits(SIG_PRIMITIVE_SET, key)) { + return String.format( + rb.getString("key.bit"), KeyUtil.getKeySize(key)); + } else { + seeWeak = true; + return String.format( + rb.getString("key.bit.weak"), KeyUtil.getKeySize(key)); + } + } + private static MessageFormat validityTimeForm = null; private static MessageFormat notYetTimeForm = null; private static MessageFormat expiredTimeForm = null;
--- a/src/share/classes/sun/security/tools/jarsigner/Resources.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/classes/sun/security/tools/jarsigner/Resources.java Mon Jan 23 16:30:43 2017 +0000 @@ -138,11 +138,26 @@ {"jar.is.unsigned", "jar is unsigned."}, {"jar.treated.unsigned", - "Signature not parsable or verifiable. The jar will be treated as unsigned. The jar may have been signed with a weak algorithm that is now disabled. For more information, rerun jarsigner with debug enabled (-J-Djava.security.debug=jar)."}, + "WARNING: Signature is either not parsable or not verifiable, and the jar will be treated as unsigned. For more information, re-run jarsigner with debug enabled (-J-Djava.security.debug=jar)."}, + {"jar.treated.unsigned.see.weak", + "The jar will be treated as unsigned, because it is signed with a weak algorithm that is now disabled.\n\nRe-run jarsigner with the -verbose option for more details."}, + {"jar.treated.unsigned.see.weak.verbose", + "WARNING: The jar will be treated as unsigned, because it is signed with a weak algorithm that is now disabled by the security property:"}, {"jar.signed.", "jar signed."}, {"jar.signed.with.signer.errors.", "jar signed, with signer errors."}, {"jar.verified.", "jar verified."}, {"jar.verified.with.signer.errors.", "jar verified, with signer errors."}, + + {"history.with.ts", "- Signed by \"%1$s\"\n Digest algorithm: %2$s\n Signature algorithm: %3$s, %4$s\n Timestamped by \"%6$s\" on %5$tc\n Timestamp digest algorithm: %7$s\n Timestamp signature algorithm: %8$s, %9$s"}, + {"history.without.ts", "- Signed by \"%1$s\"\n Digest algorithm: %2$s\n Signature algorithm: %3$s, %4$s"}, + {"history.unparsable", "- Unparsable signature-related file %s"}, + {"history.nosf", "- Missing signature-related file META-INF/%s.SF"}, + {"history.nobk", "- Missing block file for signature-related file META-INF/%s.SF"}, + + {"with.weak", "%s (weak)"}, + {"key.bit", "%d-bit key"}, + {"key.bit.weak", "%d-bit key (weak)"}, + {"jarsigner.", "jarsigner: "}, {"signature.filename.must.consist.of.the.following.characters.A.Z.0.9.or.", "signature filename must consist of the following characters: A-Z, 0-9, _ or -"},
--- a/src/share/classes/sun/security/tools/jarsigner/Resources_ja.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/classes/sun/security/tools/jarsigner/Resources_ja.java Mon Jan 23 16:30:43 2017 +0000 @@ -135,12 +135,29 @@ {"no.manifest.", "\u30DE\u30CB\u30D5\u30A7\u30B9\u30C8\u306F\u5B58\u5728\u3057\u307E\u305B\u3093\u3002"}, {".Signature.related.entries.","(\u30B7\u30B0\u30CD\u30C1\u30E3\u95A2\u9023\u30A8\u30F3\u30C8\u30EA)"}, {".Unsigned.entries.", "(\u672A\u7F72\u540D\u306E\u30A8\u30F3\u30C8\u30EA)"}, - {"jar.is.unsigned.signatures.missing.or.not.parsable.", - "jar\u306F\u7F72\u540D\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002(\u30B7\u30B0\u30CD\u30C1\u30E3\u304C\u898B\u3064\u304B\u3089\u306A\u3044\u304B\u3001\u69CB\u6587\u89E3\u6790\u3067\u304D\u307E\u305B\u3093)"}, + {"jar.is.unsigned", + "jar\u306F\u7F72\u540D\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002"}, + {"jar.treated.unsigned", + "\u8B66\u544A: \u7F72\u540D\u304C\u69CB\u6587\u89E3\u6790\u3067\u304D\u306A\u3044\u304B\u691C\u8A3C\u3067\u304D\u306A\u3044\u305F\u3081\u3001\u3053\u306Ejar\u306F\u672A\u7F72\u540D\u3068\u3057\u3066\u6271\u308F\u308C\u307E\u3059\u3002\u8A73\u7D30\u306F\u3001\u30C7\u30D0\u30C3\u30B0\u3092\u6709\u52B9\u306B\u3057\u3066(-J-Djava.security.debug=jar) jarsigner\u3092\u518D\u5B9F\u884C\u3057\u3066\u304F\u3060\u3055\u3044\u3002"}, + {"jar.treated.unsigned.see.weak", + "\u3053\u306Ejar\u306F\u3001\u73FE\u5728\u7121\u52B9\u306B\u306A\u3063\u3066\u3044\u308B\u5F31\u3044\u30A2\u30EB\u30B4\u30EA\u30BA\u30E0\u3067\u7F72\u540D\u3055\u308C\u3066\u3044\u308B\u305F\u3081\u3001\u672A\u7F72\u540D\u3068\u3057\u3066\u6271\u308F\u308C\u307E\u3059\u3002\n\n\u8A73\u7D30\u306F\u3001-verbose\u30AA\u30D7\u30B7\u30E7\u30F3\u3092\u4F7F\u7528\u3057\u3066jarsigner\u3092\u518D\u5B9F\u884C\u3057\u3066\u304F\u3060\u3055\u3044\u3002"}, + {"jar.treated.unsigned.see.weak.verbose", + "\u8B66\u544A: \u3053\u306Ejar\u306F\u3001\u30BB\u30AD\u30E5\u30EA\u30C6\u30A3\u30FB\u30D7\u30ED\u30D1\u30C6\u30A3\u306B\u3088\u3063\u3066\u73FE\u5728\u7121\u52B9\u306B\u306A\u3063\u3066\u3044\u308B\u5F31\u3044\u30A2\u30EB\u30B4\u30EA\u30BA\u30E0\u3067\u7F72\u540D\u3055\u308C\u3066\u3044\u308B\u305F\u3081\u3001\u672A\u7F72\u540D\u3068\u3057\u3066\u6271\u308F\u308C\u307E\u3059:"}, {"jar.signed.", "jar\u306F\u7F72\u540D\u3055\u308C\u307E\u3057\u305F\u3002"}, {"jar.signed.with.signer.errors.", "jar\u306F\u7F72\u540D\u3055\u308C\u307E\u3057\u305F - \u7F72\u540D\u8005\u30A8\u30E9\u30FC\u304C\u3042\u308A\u307E\u3059\u3002"}, {"jar.verified.", "jar\u304C\u691C\u8A3C\u3055\u308C\u307E\u3057\u305F\u3002"}, {"jar.verified.with.signer.errors.", "jar\u306F\u691C\u8A3C\u3055\u308C\u307E\u3057\u305F - \u7F72\u540D\u8005\u30A8\u30E9\u30FC\u304C\u3042\u308A\u307E\u3059\u3002"}, + + {"history.with.ts", "- \u7F72\u540D\u8005: \"%1$s\"\n \u30C0\u30A4\u30B8\u30A7\u30B9\u30C8\u30FB\u30A2\u30EB\u30B4\u30EA\u30BA\u30E0: %2$s\n \u7F72\u540D\u30A2\u30EB\u30B4\u30EA\u30BA\u30E0: %3$s\u3001%4$s\n \u30BF\u30A4\u30E0\u30B9\u30BF\u30F3\u30D7\u4ED8\u52A0\u8005: \"%6$s\" \u65E5\u6642: %5$tc\n \u30BF\u30A4\u30E0\u30B9\u30BF\u30F3\u30D7\u306E\u30C0\u30A4\u30B8\u30A7\u30B9\u30C8\u30FB\u30A2\u30EB\u30B4\u30EA\u30BA\u30E0: %7$s\n \u30BF\u30A4\u30E0\u30B9\u30BF\u30F3\u30D7\u306E\u7F72\u540D\u30A2\u30EB\u30B4\u30EA\u30BA\u30E0: %8$s\u3001%9$s"}, + {"history.without.ts", "- \u7F72\u540D\u8005: \"%1$s\"\n \u30C0\u30A4\u30B8\u30A7\u30B9\u30C8\u30FB\u30A2\u30EB\u30B4\u30EA\u30BA\u30E0: %2$s\n \u7F72\u540D\u30A2\u30EB\u30B4\u30EA\u30BA\u30E0: %3$s\u3001%4$s"}, + {"history.unparsable", "- \u7F72\u540D\u95A2\u9023\u30D5\u30A1\u30A4\u30EB%s\u3092\u89E3\u6790\u3067\u304D\u307E\u305B\u3093"}, + {"history.nosf", "- \u7F72\u540D\u95A2\u9023\u30D5\u30A1\u30A4\u30EBMETA-INF/%s.SF\u304C\u3042\u308A\u307E\u305B\u3093"}, + {"history.nobk", "- \u7F72\u540D\u95A2\u9023\u30D5\u30A1\u30A4\u30EBMETA-INF/%s.SF\u306E\u30D6\u30ED\u30C3\u30AF\u30FB\u30D5\u30A1\u30A4\u30EB\u304C\u3042\u308A\u307E\u305B\u3093"}, + + {"with.weak", "%s (\u5F31)"}, + {"key.bit", "%d\u30D3\u30C3\u30C8\u9375"}, + {"key.bit.weak", "%d\u30D3\u30C3\u30C8\u9375(\u5F31)"}, + {"jarsigner.", "jarsigner: "}, {"signature.filename.must.consist.of.the.following.characters.A.Z.0.9.or.", "\u30B7\u30B0\u30CD\u30C1\u30E3\u306E\u30D5\u30A1\u30A4\u30EB\u540D\u306B\u4F7F\u7528\u3067\u304D\u308B\u6587\u5B57\u306F\u3001A-Z\u30010-9\u3001_\u3001- \u306E\u307F\u3067\u3059\u3002"},
--- a/src/share/classes/sun/security/tools/jarsigner/Resources_zh_CN.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/classes/sun/security/tools/jarsigner/Resources_zh_CN.java Mon Jan 23 16:30:43 2017 +0000 @@ -135,12 +135,29 @@ {"no.manifest.", "\u6CA1\u6709\u6E05\u5355\u3002"}, {".Signature.related.entries.","(\u4E0E\u7B7E\u540D\u76F8\u5173\u7684\u6761\u76EE)"}, {".Unsigned.entries.", "(\u672A\u7B7E\u540D\u6761\u76EE)"}, - {"jar.is.unsigned.signatures.missing.or.not.parsable.", - "jar \u672A\u7B7E\u540D\u3002(\u7F3A\u5C11\u7B7E\u540D\u6216\u65E0\u6CD5\u89E3\u6790\u7B7E\u540D)"}, + {"jar.is.unsigned", + "jar \u672A\u7B7E\u540D\u3002"}, + {"jar.treated.unsigned", + "\u8B66\u544A: \u7B7E\u540D\u65E0\u6CD5\u89E3\u6790\u6216\u9A8C\u8BC1, \u8BE5 jar \u5C06\u88AB\u89C6\u4E3A\u672A\u7B7E\u540D\u3002\u6709\u5173\u8BE6\u7EC6\u4FE1\u606F, \u8BF7\u5728\u542F\u7528\u8C03\u8BD5\u7684\u60C5\u51B5\u4E0B\u91CD\u65B0\u8FD0\u884C jarsigner (-J-Djava.security.debug=jar)\u3002"}, + {"jar.treated.unsigned.see.weak", + "\u7531\u4E8E\u8BE5 jar \u662F\u4F7F\u7528\u76EE\u524D\u5DF2\u7981\u7528\u7684\u5F31\u7B97\u6CD5\u7B7E\u540D\u7684, \u56E0\u6B64\u8BE5 jar \u5C06\u88AB\u89C6\u4E3A\u672A\u7B7E\u540D\u3002\n\n\u6709\u5173\u8BE6\u7EC6\u4FE1\u606F, \u8BF7\u4F7F\u7528 -verbose \u9009\u9879\u91CD\u65B0\u8FD0\u884C jarsigner\u3002"}, + {"jar.treated.unsigned.see.weak.verbose", + "\u8B66\u544A: \u7531\u4E8E\u8BE5 jar \u662F\u4F7F\u7528\u76EE\u524D\u5DF2\u7531\u5B89\u5168\u5C5E\u6027\u7981\u7528\u7684\u5F31\u7B97\u6CD5\u7B7E\u540D\u7684, \u56E0\u6B64\u8BE5 jar \u5C06\u88AB\u89C6\u4E3A\u672A\u7B7E\u540D:"}, {"jar.signed.", "jar \u5DF2\u7B7E\u540D\u3002"}, {"jar.signed.with.signer.errors.", "jar \u5DF2\u7B7E\u540D, \u4F46\u51FA\u73B0\u7B7E\u540D\u8005\u9519\u8BEF\u3002"}, {"jar.verified.", "jar \u5DF2\u9A8C\u8BC1\u3002"}, {"jar.verified.with.signer.errors.", "jar \u5DF2\u9A8C\u8BC1, \u4F46\u51FA\u73B0\u7B7E\u540D\u8005\u9519\u8BEF\u3002"}, + + {"history.with.ts", "- \u7531 \"%1$s\" \u7B7E\u540D\n \u6458\u8981\u7B97\u6CD5: %2$s\n \u7B7E\u540D\u7B97\u6CD5: %3$s, %4$s\n \u7531 \"%6$s\" \u4E8E %5$tc \u52A0\u65F6\u95F4\u6233\n \u65F6\u95F4\u6233\u6458\u8981\u7B97\u6CD5: %7$s\n \u65F6\u95F4\u6233\u7B7E\u540D\u7B97\u6CD5: %8$s, %9$s"}, + {"history.without.ts", "- \u7531 \"%1$s\" \u7B7E\u540D\n \u6458\u8981\u7B97\u6CD5: %2$s\n \u7B7E\u540D\u7B97\u6CD5: %3$s, %4$s"}, + {"history.unparsable", "- \u65E0\u6CD5\u89E3\u6790\u7684\u4E0E\u7B7E\u540D\u76F8\u5173\u7684\u6587\u4EF6 %s"}, + {"history.nosf", "- \u7F3A\u5C11\u4E0E\u7B7E\u540D\u76F8\u5173\u7684\u6587\u4EF6 META-INF/%s.SF"}, + {"history.nobk", "- \u4E0E\u7B7E\u540D\u76F8\u5173\u7684\u6587\u4EF6 META-INF/%s.SF \u7F3A\u5C11\u5757\u6587\u4EF6"}, + + {"with.weak", "%s (\u5F31)"}, + {"key.bit", "%d \u4F4D\u5BC6\u94A5"}, + {"key.bit.weak", "%d \u4F4D\u5BC6\u94A5 (\u5F31)"}, + {"jarsigner.", "jarsigner: "}, {"signature.filename.must.consist.of.the.following.characters.A.Z.0.9.or.", "\u7B7E\u540D\u6587\u4EF6\u540D\u5FC5\u987B\u5305\u542B\u4EE5\u4E0B\u5B57\u7B26: A-Z, 0-9, _ \u6216 -"},
--- a/src/share/classes/sun/security/tools/policytool/Resources_sv.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/classes/sun/security/tools/policytool/Resources_sv.java Mon Jan 23 16:30:43 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -43,7 +43,7 @@ {"Illegal.option.option", "Otill\u00E5tet alternativ: {0}"}, {"Usage.policytool.options.", "Syntax: policytool [alternativ]"}, {".file.file.policy.file.location", - " [-file <fil>] policyfilens plats"}, + " [-file <fil>] policyfiladress"}, {"New", "&Nytt"}, {"Open", "&\u00D6ppna..."}, {"Save", "S¶"},
--- a/src/share/classes/sun/security/util/AbstractAlgorithmConstraints.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/classes/sun/security/util/AbstractAlgorithmConstraints.java Mon Jan 23 16:30:43 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -29,7 +29,6 @@ import java.security.AlgorithmConstraints; import java.security.PrivilegedAction; import java.security.Security; -import java.util.Map; import java.util.Set; /** @@ -45,8 +44,7 @@ } // Get algorithm constraints from the specified security property. - private static void loadAlgorithmsMap(Map<String, String[]> algorithmsMap, - String propertyName) { + static String[] getAlgorithms(String propertyName) { String property = AccessController.doPrivileged( new PrivilegedAction<String>() { @Override @@ -72,18 +70,7 @@ if (algorithmsInProperty == null) { algorithmsInProperty = new String[0]; } - algorithmsMap.put(propertyName, algorithmsInProperty); - } - - static String[] getAlgorithms(Map<String, String[]> algorithmsMap, - String propertyName) { - synchronized (algorithmsMap) { - if (!algorithmsMap.containsKey(propertyName)) { - loadAlgorithmsMap(algorithmsMap, propertyName); - } - - return algorithmsMap.get(propertyName); - } + return algorithmsInProperty; } static boolean checkAlgorithm(String[] algorithms, String algorithm,
--- a/src/share/classes/sun/security/util/AlgorithmDecomposer.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/classes/sun/security/util/AlgorithmDecomposer.java Mon Jan 23 16:30:43 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -38,19 +38,7 @@ private static final Pattern pattern = Pattern.compile("with|and", Pattern.CASE_INSENSITIVE); - /** - * Decompose the standard algorithm name into sub-elements. - * <p> - * For example, we need to decompose "SHA1WithRSA" into "SHA1" and "RSA" - * so that we can check the "SHA1" and "RSA" algorithm constraints - * separately. - * <p> - * Please override the method if need to support more name pattern. - */ - public Set<String> decompose(String algorithm) { - if (algorithm == null || algorithm.length() == 0) { - return new HashSet<>(); - } + private static Set<String> decomposeImpl(String algorithm) { // algorithm/mode/padding String[] transTockens = transPattern.split(algorithm); @@ -76,6 +64,24 @@ elements.add(token); } } + return elements; + } + + /** + * Decompose the standard algorithm name into sub-elements. + * <p> + * For example, we need to decompose "SHA1WithRSA" into "SHA1" and "RSA" + * so that we can check the "SHA1" and "RSA" algorithm constraints + * separately. + * <p> + * Please override the method if need to support more name pattern. + */ + public Set<String> decompose(String algorithm) { + if (algorithm == null || algorithm.length() == 0) { + return new HashSet<>(); + } + + Set<String> elements = decomposeImpl(algorithm); // In Java standard algorithm name specification, for different // purpose, the SHA-1 and SHA-2 algorithm names are different. For @@ -127,4 +133,40 @@ return elements; } + private static void hasLoop(Set<String> elements, String find, String replace) { + if (elements.contains(find)) { + if (!elements.contains(replace)) { + elements.add(replace); } + elements.remove(find); + } + } + + /* + * This decomposes a standard name into sub-elements with a consistent + * message digest algorithm name to avoid overly complicated checking. + */ + public static Set<String> decomposeOneHash(String algorithm) { + if (algorithm == null || algorithm.length() == 0) { + return new HashSet<>(); + } + + Set<String> elements = decomposeImpl(algorithm); + + hasLoop(elements, "SHA-1", "SHA1"); + hasLoop(elements, "SHA-224", "SHA224"); + hasLoop(elements, "SHA-256", "SHA256"); + hasLoop(elements, "SHA-384", "SHA384"); + hasLoop(elements, "SHA-512", "SHA512"); + + return elements; + } + + /* + * The provided message digest algorithm name will return a consistent + * naming scheme. + */ + public static String hashName(String algorithm) { + return algorithm.replace("-", ""); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/sun/security/util/AnchorCertificates.java Mon Jan 23 16:30:43 2017 +0000 @@ -0,0 +1,101 @@ +/* + * Copyright (c) 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. 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.util; + +import java.io.File; +import java.io.FileInputStream; +import java.security.AccessController; +import java.security.KeyStore; +import java.security.PrivilegedAction; +import java.security.cert.X509Certificate; +import java.util.Enumeration; +import java.util.HashSet; + +import sun.security.x509.X509CertImpl; + +/** + * The purpose of this class is to determine the trust anchor certificates is in + * the cacerts file. This is used for PKIX CertPath checking. + */ +public class AnchorCertificates { + + private static final Debug debug = Debug.getInstance("certpath"); + private static final String HASH = "SHA-256"; + private static HashSet<String> certs; + + static { + AccessController.doPrivileged(new PrivilegedAction<Void>() { + @Override + public Void run() { + File f = new File(System.getProperty("java.home"), + "lib/security/cacerts"); + KeyStore cacerts; + try { + cacerts = KeyStore.getInstance("JKS"); + try (FileInputStream fis = new FileInputStream(f)) { + cacerts.load(fis, null); + certs = new HashSet<>(); + Enumeration<String> list = cacerts.aliases(); + String alias; + while (list.hasMoreElements()) { + alias = list.nextElement(); + // Check if this cert is labeled a trust anchor. + if (alias.contains(" [jdk")) { + X509Certificate cert = (X509Certificate) cacerts + .getCertificate(alias); + certs.add(X509CertImpl.getFingerprint(HASH, cert)); + } + } + } + } catch (Exception e) { + if (debug != null) { + debug.println("Error parsing cacerts"); + } + e.printStackTrace(); + } + return null; + } + }); + } + + /** + * Checks if a certificate is a trust anchor. + * + * @param cert the certificate to check + * @return true if the certificate is trusted. + */ + public static boolean contains(X509Certificate cert) { + String key = X509CertImpl.getFingerprint(HASH, cert); + boolean result = certs.contains(key); + if (result && debug != null) { + debug.println("AnchorCertificate.contains: matched " + + cert.getSubjectDN()); + } + return result; + } + + private AnchorCertificates() {} +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/sun/security/util/CertConstraintParameters.java Mon Jan 23 16:30:43 2017 +0000 @@ -0,0 +1,59 @@ +/* + * Copyright (c) 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. 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.util; + +import java.security.cert.X509Certificate; + +/** + * This class is a wrapper for keeping state and passing objects between PKIX, + * AlgorithmChecker, and DisabledAlgorithmConstraints. + */ +public class CertConstraintParameters { + // A certificate being passed to check against constraints. + private final X509Certificate cert; + + // This is true if the trust anchor in the certificate chain matches a cert + // in AnchorCertificates + private final boolean trustedMatch; + + public CertConstraintParameters(X509Certificate c, boolean match) { + cert = c; + trustedMatch = match; + } + + public CertConstraintParameters(X509Certificate c) { + this(c, false); + } + + // Returns if the trust anchor has a match if anchor checking is enabled. + public boolean isTrustedMatch() { + return trustedMatch; + } + + public X509Certificate getCertificate() { + return cert; + } +}
--- a/src/share/classes/sun/security/util/DerInputBuffer.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/classes/sun/security/util/DerInputBuffer.java Mon Jan 23 16:30:43 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 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 @@ -147,6 +147,11 @@ System.arraycopy(buf, pos, bytes, 0, len); skip(len); + // check to make sure no extra leading 0s for DER + if (len >= 2 && (bytes[0] == 0) && (bytes[1] >= 0)) { + throw new IOException("Invalid encoding: redundant leading 0s"); + } + if (makePositive) { return new BigInteger(1, bytes); } else {
--- a/src/share/classes/sun/security/util/DerInputStream.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/classes/sun/security/util/DerInputStream.java Mon Jan 23 16:30:43 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 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 @@ -77,7 +77,7 @@ * @param data the buffer from which to create the string (CONSUMED) */ public DerInputStream(byte[] data) throws IOException { - init(data, 0, data.length); + init(data, 0, data.length, true); } /** @@ -92,23 +92,48 @@ * starting at "offset" */ public DerInputStream(byte[] data, int offset, int len) throws IOException { - init(data, offset, len); + init(data, offset, len, true); + } + + /** + * Create a DER input stream from part of a data buffer with + * additional arg to indicate whether to allow constructed + * indefinite-length encoding. + * The buffer is not copied, it is shared. Accordingly, the + * buffer should be treated as read-only. + * + * @param data the buffer from which to create the string (CONSUMED) + * @param offset the first index of <em>data</em> which will + * be read as DER input in the new stream + * @param len how long a chunk of the buffer to use, + * starting at "offset" + * @param allowIndefiniteLength whether to allow constructed + * indefinite-length encoding + */ + public DerInputStream(byte[] data, int offset, int len, + boolean allowIndefiniteLength) throws IOException { + init(data, offset, len, allowIndefiniteLength); } /* * private helper routine */ - private void init(byte[] data, int offset, int len) throws IOException { + private void init(byte[] data, int offset, int len, + boolean allowIndefiniteLength) throws IOException { if ((offset+2 > data.length) || (offset+len > data.length)) { throw new IOException("Encoding bytes too short"); } // check for indefinite length encoding if (DerIndefLenConverter.isIndefinite(data[offset+1])) { - byte[] inData = new byte[len]; - System.arraycopy(data, offset, inData, 0, len); + if (!allowIndefiniteLength) { + throw new IOException("Indefinite length BER encoding found"); + } else { + byte[] inData = new byte[len]; + System.arraycopy(data, offset, inData, 0, len); - DerIndefLenConverter derIn = new DerIndefLenConverter(); - buffer = new DerInputBuffer(derIn.convert(inData)); + DerIndefLenConverter derIn = new DerIndefLenConverter(); + buffer = new DerInputBuffer(derIn.convert(inData)); + } } else buffer = new DerInputBuffer(data, offset, len); buffer.mark(Integer.MAX_VALUE); @@ -233,12 +258,21 @@ * First byte = number of excess bits in the last octet of the * representation. */ - int validBits = length*8 - buffer.read(); + int excessBits = buffer.read(); + if (excessBits < 0) { + throw new IOException("Unused bits of bit string invalid"); + } + int validBits = length*8 - excessBits; + if (validBits < 0) { + throw new IOException("Valid bits of bit string invalid"); + } byte[] repn = new byte[length]; - if ((length != 0) && (buffer.read(repn) != length)) - throw new IOException("short read of DER bit string"); + if ((length != 0) && (buffer.read(repn) != length)) { + throw new IOException("Short read of DER bit string"); + } + return new BitArray(validBits, repn); } @@ -252,7 +286,7 @@ int length = getLength(buffer); byte[] retval = new byte[length]; if ((length != 0) && (buffer.read(retval) != length)) - throw new IOException("short read of DER octet string"); + throw new IOException("Short read of DER octet string"); return retval; } @@ -262,7 +296,7 @@ */ public void getBytes(byte[] val) throws IOException { if ((val.length != 0) && (buffer.read(val) != val.length)) { - throw new IOException("short read of DER octet string"); + throw new IOException("Short read of DER octet string"); } } @@ -346,7 +380,7 @@ DerInputStream newstr; byte lenByte = (byte)buffer.read(); - int len = getLength((lenByte & 0xff), buffer); + int len = getLength(lenByte, buffer); if (len == -1) { // indefinite length encoding found @@ -392,7 +426,7 @@ } while (newstr.available() > 0); if (newstr.available() != 0) - throw new IOException("extra data at end of vector"); + throw new IOException("Extra data at end of vector"); /* * Now stick them into the array we're returning. @@ -483,7 +517,7 @@ int length = getLength(buffer); byte[] retval = new byte[length]; if ((length != 0) && (buffer.read(retval) != length)) - throw new IOException("short read of DER " + + throw new IOException("Short read of DER " + stringName + " string"); return new String(retval, enc); @@ -544,7 +578,11 @@ */ static int getLength(int lenByte, InputStream in) throws IOException { int value, tmp; + if (lenByte == -1) { + throw new IOException("Short read of DER length"); + } + String mdName = "DerInputStream.getLength(): "; tmp = lenByte; if ((tmp & 0x080) == 0x00) { // short form, 1 byte datum value = tmp; @@ -558,17 +596,23 @@ if (tmp == 0) return -1; if (tmp < 0 || tmp > 4) - throw new IOException("DerInputStream.getLength(): lengthTag=" - + tmp + ", " + throw new IOException(mdName + "lengthTag=" + tmp + ", " + ((tmp < 0) ? "incorrect DER encoding." : "too big.")); - for (value = 0; tmp > 0; tmp --) { + value = 0x0ff & in.read(); + tmp--; + if (value == 0) { + // DER requires length value be encoded in minimum number of bytes + throw new IOException(mdName + "Redundant length bytes found"); + } + while (tmp-- > 0) { value <<= 8; value += 0x0ff & in.read(); } if (value < 0) { - throw new IOException("DerInputStream.getLength(): " - + "Invalid length bytes"); + throw new IOException(mdName + "Invalid length bytes"); + } else if (value <= 127) { + throw new IOException(mdName + "Should use short form for length"); } } return value;
--- a/src/share/classes/sun/security/util/DerValue.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/classes/sun/security/util/DerValue.java Mon Jan 23 16:30:43 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 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 @@ -249,7 +249,7 @@ tag = (byte)in.read(); byte lenByte = (byte)in.read(); - length = DerInputStream.getLength((lenByte & 0xff), in); + length = DerInputStream.getLength(lenByte, in); if (length == -1) { // indefinite length encoding found DerInputBuffer inbuf = in.dup(); int readLen = inbuf.available(); @@ -362,7 +362,7 @@ tag = (byte)in.read(); byte lenByte = (byte)in.read(); - length = DerInputStream.getLength((lenByte & 0xff), in); + length = DerInputStream.getLength(lenByte, in); if (length == -1) { // indefinite length encoding found int readLen = in.available(); int offset = 2; // for tag and length bytes
--- a/src/share/classes/sun/security/util/DisabledAlgorithmConstraints.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/classes/sun/security/util/DisabledAlgorithmConstraints.java Mon Jan 23 16:30:43 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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 @@ -28,12 +28,14 @@ import java.security.CryptoPrimitive; import java.security.AlgorithmParameters; import java.security.Key; +import java.security.cert.CertPathValidatorException; +import java.security.cert.CertPathValidatorException.BasicReason; +import java.security.cert.X509Certificate; +import java.util.HashMap; +import java.util.HashSet; import java.util.Locale; +import java.util.Map; import java.util.Set; -import java.util.Collections; -import java.util.HashSet; -import java.util.Map; -import java.util.HashMap; import java.util.regex.Pattern; import java.util.regex.Matcher; @@ -44,6 +46,7 @@ * for the syntax of the disabled algorithm string. */ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints { + private static final Debug debug = Debug.getInstance("certpath"); // the known security property, jdk.certpath.disabledAlgorithms public final static String PROPERTY_CERTPATH_DISABLED_ALGS = @@ -53,17 +56,12 @@ public final static String PROPERTY_TLS_DISABLED_ALGS = "jdk.tls.disabledAlgorithms"; - private final static Map<String, String[]> disabledAlgorithmsMap = - new HashMap<>(); - private final static Map<String, KeySizeConstraints> keySizeConstraintsMap = - new HashMap<>(); - // the known security property, jdk.jar.disabledAlgorithms public static final String PROPERTY_JAR_DISABLED_ALGS = "jdk.jar.disabledAlgorithms"; private final String[] disabledAlgorithms; - private final KeySizeConstraints keySizeConstraints; + private final Constraints algorithmConstraints; /** * Initialize algorithm constraints with the specified security property. @@ -86,11 +84,14 @@ public DisabledAlgorithmConstraints(String propertyName, AlgorithmDecomposer decomposer) { super(decomposer); - disabledAlgorithms = getAlgorithms(disabledAlgorithmsMap, propertyName); - keySizeConstraints = getKeySizeConstraints(disabledAlgorithms, - propertyName); + disabledAlgorithms = getAlgorithms(propertyName); + algorithmConstraints = new Constraints(disabledAlgorithms); } + /* + * This only checks if the algorithm has been completely disabled. If + * there are keysize or other limit, this method allow the algorithm. + */ @Override final public boolean permits(Set<CryptoPrimitive> primitives, String algorithm, AlgorithmParameters parameters) { @@ -103,11 +104,19 @@ return checkAlgorithm(disabledAlgorithms, algorithm, decomposer); } + /* + * Checks if the key algorithm has been disabled or constraints have been + * placed on the key. + */ @Override final public boolean permits(Set<CryptoPrimitive> primitives, Key key) { return checkConstraints(primitives, "", key, null); } + /* + * Checks if the key algorithm has been disabled or if constraints have + * been placed on the key. + */ @Override final public boolean permits(Set<CryptoPrimitive> primitives, String algorithm, Key key, AlgorithmParameters parameters) { @@ -119,7 +128,39 @@ return checkConstraints(primitives, algorithm, key, parameters); } - // Check algorithm constraints + /* + * Check if a x509Certificate object is permitted. Check if all + * algorithms are allowed, certificate constraints, and the + * public key against key constraints. + * + * Uses new style permit() which throws exceptions. + */ + public final void permits(Set<CryptoPrimitive> primitives, + CertConstraintParameters cp) throws CertPathValidatorException { + checkConstraints(primitives, cp); + } + + /* + * Check if Certificate object is within the constraints. + * Uses new style permit() which throws exceptions. + */ + public final void permits(Set<CryptoPrimitive> primitives, + X509Certificate cert) throws CertPathValidatorException { + checkConstraints(primitives, new CertConstraintParameters(cert)); + } + + // Check if a string is contained inside the property + public boolean checkProperty(String param) { + param = param.toLowerCase(Locale.ENGLISH); + for (String block : disabledAlgorithms) { + if (block.toLowerCase(Locale.ENGLISH).indexOf(param) >= 0) { + return true; + } + } + return false; + } + + // Check algorithm constraints with key and algorithm private boolean checkConstraints(Set<CryptoPrimitive> primitives, String algorithm, Key key, AlgorithmParameters parameters) { @@ -128,7 +169,7 @@ throw new IllegalArgumentException("The key cannot be null"); } - // check the target algorithm + // check the signature algorithm if (algorithm != null && algorithm.length() != 0) { if (!permits(primitives, algorithm, parameters)) { return false; @@ -141,97 +182,203 @@ } // check the key constraints - if (keySizeConstraints.disables(key)) { - return false; - } - - return true; + return algorithmConstraints.permits(key); } - private static KeySizeConstraints getKeySizeConstraints( - String[] disabledAlgorithms, String propertyName) { - synchronized (keySizeConstraintsMap) { - if(!keySizeConstraintsMap.containsKey(propertyName)) { - // map the key constraints - KeySizeConstraints keySizeConstraints = - new KeySizeConstraints(disabledAlgorithms); - keySizeConstraintsMap.put(propertyName, keySizeConstraints); - } + /* + * Check algorithm constraints with Certificate + * Uses new style permit() which throws exceptions. + */ + private void checkConstraints(Set<CryptoPrimitive> primitives, + CertConstraintParameters cp) throws CertPathValidatorException { + + X509Certificate cert = cp.getCertificate(); + String algorithm = cert.getSigAlgName(); - return keySizeConstraintsMap.get(propertyName); + // Check signature algorithm is not disabled + if (!permits(primitives, algorithm, null)) { + throw new CertPathValidatorException( + "Algorithm constraints check failed on disabled "+ + "signature algorithm: " + algorithm, + null, null, -1, BasicReason.ALGORITHM_CONSTRAINED); } + + // Check key algorithm is not disabled + if (!permits(primitives, cert.getPublicKey().getAlgorithm(), null)) { + throw new CertPathValidatorException( + "Algorithm constraints check failed on disabled "+ + "public key algorithm: " + algorithm, + null, null, -1, BasicReason.ALGORITHM_CONSTRAINED); + } + + // Check the certificate and key constraints + algorithmConstraints.permits(cp); + } /** - * key constraints + * Key and Certificate Constraints + * + * The complete disabling of an algorithm is not handled by Constraints or + * Constraint classes. That is addressed with + * permit(Set<CryptoPrimitive>, String, AlgorithmParameters) + * + * When passing a Key to permit(), the boolean return values follow the + * same as the interface class AlgorithmConstraints.permit(). This is to + * maintain compatibility: + * 'true' means the operation is allowed. + * 'false' means it failed the constraints and is disallowed. + * + * When passing CertConstraintParameters through permit(), an exception + * will be thrown on a failure to better identify why the operation was + * disallowed. */ - private static class KeySizeConstraints { - private static final Pattern pattern = Pattern.compile( - "(\\S+)\\s+keySize\\s*(<=|<|==|!=|>|>=)\\s*(\\d+)"); - private Map<String, Set<KeySizeConstraint>> constraintsMap = - Collections.synchronizedMap( - new HashMap<String, Set<KeySizeConstraint>>()); + private static class Constraints { + private Map<String, Set<Constraint>> constraintsMap = new HashMap<>(); + private static final Pattern keySizePattern = Pattern.compile( + "keySize\\s*(<=|<|==|!=|>|>=)\\s*(\\d+)"); - public KeySizeConstraints(String[] restrictions) { - for (String restriction : restrictions) { - if (restriction == null || restriction.isEmpty()) { + public Constraints(String[] constraintArray) { + for (String constraintEntry : constraintArray) { + if (constraintEntry == null || constraintEntry.isEmpty()) { continue; } - Matcher matcher = pattern.matcher(restriction); - if (matcher.matches()) { - String algorithm = matcher.group(1); + constraintEntry = constraintEntry.trim(); + if (debug != null) { + debug.println("Constraints: " + constraintEntry); + } - KeySizeConstraint.Operator operator = - KeySizeConstraint.Operator.of(matcher.group(2)); - int length = Integer.parseInt(matcher.group(3)); + // Check if constraint is a complete disabling of an + // algorithm or has conditions. + String algorithm; + String policy; + int space = constraintEntry.indexOf(' '); + if (space > 0) { + algorithm = AlgorithmDecomposer.hashName( + constraintEntry.substring(0, space). + toUpperCase(Locale.ENGLISH)); + policy = constraintEntry.substring(space + 1); + } else { + constraintsMap.putIfAbsent( + constraintEntry.toUpperCase(Locale.ENGLISH), + new HashSet<>()); + continue; + } - algorithm = algorithm.toLowerCase(Locale.ENGLISH); + // Convert constraint conditions into Constraint classes + Constraint c = null; + Constraint lastConstraint = null; + // Allow only one jdkCA entry per constraint entry + boolean jdkCALimit = false; + + for (String entry : policy.split("&")) { + entry = entry.trim(); - synchronized (constraintsMap) { - if (!constraintsMap.containsKey(algorithm)) { - constraintsMap.put(algorithm, - new HashSet<KeySizeConstraint>()); + Matcher matcher = keySizePattern.matcher(entry); + if (matcher.matches()) { + if (debug != null) { + debug.println("Constraints set to keySize: " + + entry); } + c = new KeySizeConstraint(algorithm, + KeySizeConstraint.Operator.of(matcher.group(1)), + Integer.parseInt(matcher.group(2))); - Set<KeySizeConstraint> constraintSet = - constraintsMap.get(algorithm); - KeySizeConstraint constraint = - new KeySizeConstraint(operator, length); - constraintSet.add(constraint); + } else if (entry.equalsIgnoreCase("jdkCA")) { + if (debug != null) { + debug.println("Constraints set to jdkCA."); + } + if (jdkCALimit) { + throw new IllegalArgumentException("Only one " + + "jdkCA entry allowed in property. " + + "Constraint: " + constraintEntry); + } + c = new jdkCAConstraint(algorithm); + jdkCALimit = true; } + + // Link multiple conditions for a single constraint + // into a linked list. + if (lastConstraint == null) { + if (!constraintsMap.containsKey(algorithm)) { + constraintsMap.putIfAbsent(algorithm, + new HashSet<>()); + } + if (c != null) { + constraintsMap.get(algorithm).add(c); + } + } else { + lastConstraint.nextConstraint = c; + } + lastConstraint = c; } } } - // Does this KeySizeConstraints disable the specified key? - public boolean disables(Key key) { - String algorithm = key.getAlgorithm().toLowerCase(Locale.ENGLISH); - synchronized (constraintsMap) { - if (constraintsMap.containsKey(algorithm)) { - Set<KeySizeConstraint> constraintSet = - constraintsMap.get(algorithm); - for (KeySizeConstraint constraint : constraintSet) { - if (constraint.disables(key)) { - return true; - } + // Get applicable constraints based off the signature algorithm + private Set<Constraint> getConstraints(String algorithm) { + return constraintsMap.get(algorithm); + } + + // Check if KeySizeConstraints permit the specified key + public boolean permits(Key key) { + Set<Constraint> set = getConstraints(key.getAlgorithm()); + if (set == null) { + return true; + } + for (Constraint constraint : set) { + if (!constraint.permits(key)) { + if (debug != null) { + debug.println("keySizeConstraint: failed key " + + "constraint check " + KeyUtil.getKeySize(key)); } + return false; + } + } + return true; + } + + // Check if constraints permit this cert. + public void permits(CertConstraintParameters cp) + throws CertPathValidatorException { + X509Certificate cert = cp.getCertificate(); + + if (debug != null) { + debug.println("Constraints.permits(): " + cert.getSigAlgName()); + } + + // Get all signature algorithms to check for constraints + Set<String> algorithms = + AlgorithmDecomposer.decomposeOneHash(cert.getSigAlgName()); + if (algorithms == null || algorithms.isEmpty()) { + return; + } + + // Attempt to add the public key algorithm to the set + algorithms.add(cert.getPublicKey().getAlgorithm()); + + // Check all applicable constraints + for (String algorithm : algorithms) { + Set<Constraint> set = getConstraints(algorithm); + if (set == null) { + continue; + } + for (Constraint constraint : set) { + constraint.permits(cp); } } - - return false; } - } + } - /** - * Key size constraint. - * - * e.g. "keysize <= 1024" - */ - private static class KeySizeConstraint { + // Abstract class for algorithm constraint checking + private abstract static class Constraint { + String algorithm; + Constraint nextConstraint = null; + // operator - static enum Operator { + enum Operator { EQ, // "==" NE, // "!=" LT, // "<" @@ -255,16 +402,77 @@ return GE; } - throw new IllegalArgumentException( - s + " is not a legal Operator"); + throw new IllegalArgumentException("Error in security " + + "property. " + s + " is not a legal Operator"); } } + /** + * Check if an algorithm constraint permit this key to be used. + * @param key Public key + * @return true if constraints do not match + */ + public boolean permits(Key key) { + return true; + } + + /** + * Check if an algorithm constraint is permit this certificate to + * be used. + * @param cp CertificateParameter containing certificate and state info + * @return true if constraints do not match + */ + public abstract void permits(CertConstraintParameters cp) + throws CertPathValidatorException; + } + + /* + * This class contains constraints dealing with the certificate chain + * of the certificate. + */ + private static class jdkCAConstraint extends Constraint { + jdkCAConstraint(String algo) { + algorithm = algo; + } + + /* + * Check if each constraint fails and check if there is a linked + * constraint Any permitted constraint will exit the linked list + * to allow the operation. + */ + public void permits(CertConstraintParameters cp) + throws CertPathValidatorException { + if (debug != null) { + debug.println("jdkCAConstraints.permits(): " + algorithm); + } + + // Return false if the chain has a trust anchor in cacerts + if (cp.isTrustedMatch()) { + if (nextConstraint != null) { + nextConstraint.permits(cp); + return; + } + throw new CertPathValidatorException( + "Algorithm constraints check failed on certificate " + + "anchor limits", + null, null, -1, BasicReason.ALGORITHM_CONSTRAINED); + } + } + } + + + /* + * This class contains constraints dealing with the key size + * support limits per algorithm. e.g. "keySize <= 1024" + */ + private static class KeySizeConstraint extends Constraint { + private int minSize; // the minimal available key size private int maxSize; // the maximal available key size private int prohibitedSize = -1; // unavailable key sizes - public KeySizeConstraint(Operator operator, int length) { + public KeySizeConstraint(String algo, Operator operator, int length) { + algorithm = algo; switch (operator) { case EQ: // an unavailable key size this.minSize = 0; @@ -298,21 +506,59 @@ } } - // Does this key constraint disable the specified key? - public boolean disables(Key key) { - int size = KeyUtil.getKeySize(key); + /* + * If we are passed a certificate, extract the public key and use it. + * + * Check if each constraint fails and check if there is a linked + * constraint Any permitted constraint will exit the linked list + * to allow the operation. + */ + public void permits(CertConstraintParameters cp) + throws CertPathValidatorException { + if (!permitsImpl(cp.getCertificate().getPublicKey())) { + if (nextConstraint != null) { + nextConstraint.permits(cp); + return; + } + throw new CertPathValidatorException( + "Algorithm constraints check failed on keysize limits", + null, null, -1, BasicReason.ALGORITHM_CONSTRAINED); + } + } + + // Check if key constraint disable the specified key + // Uses old style permit() + public boolean permits(Key key) { + // If we recursively find a constraint that permits us to use + // this key, return true and skip any other constraint checks. + if (nextConstraint != null && nextConstraint.permits(key)) { + return true; + } + if (debug != null) { + debug.println("KeySizeConstraints.permits(): " + algorithm); + } + + return permitsImpl(key); + } + + private boolean permitsImpl(Key key) { + // Verify this constraint is for this public key algorithm + if (algorithm.compareToIgnoreCase(key.getAlgorithm()) != 0) { + return true; + } + + int size = KeyUtil.getKeySize(key); if (size == 0) { - return true; // we don't allow any key of size 0. + return false; // we don't allow any key of size 0. } else if (size > 0) { - return ((size < minSize) || (size > maxSize) || + return !((size < minSize) || (size > maxSize) || (prohibitedSize == size)); } // Otherwise, the key size is not accessible. Conservatively, // please don't disable such keys. - return false; + return true; + } } } -} -
--- a/src/share/classes/sun/security/util/KeyUtil.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/classes/sun/security/util/KeyUtil.java Mon Jan 23 16:30:43 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -32,6 +32,7 @@ import java.security.interfaces.ECKey; import java.security.interfaces.RSAKey; import java.security.interfaces.DSAKey; +import java.security.interfaces.DSAParams; import java.security.SecureRandom; import java.security.spec.KeySpec; import javax.crypto.SecretKey; @@ -87,7 +88,8 @@ size = pubk.getParams().getOrder().bitLength(); } else if (key instanceof DSAKey) { DSAKey pubk = (DSAKey)key; - size = pubk.getParams().getP().bitLength(); + DSAParams params = pubk.getParams(); // params can be null + size = (params != null) ? params.getP().bitLength() : -1; } else if (key instanceof DHKey) { DHKey pubk = (DHKey)key; size = pubk.getParams().getP().bitLength();
--- a/src/share/classes/sun/security/util/LegacyAlgorithmConstraints.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/classes/sun/security/util/LegacyAlgorithmConstraints.java Mon Jan 23 16:30:43 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -28,8 +28,6 @@ import java.security.AlgorithmParameters; import java.security.CryptoPrimitive; import java.security.Key; -import java.util.HashMap; -import java.util.Map; import java.util.Set; import static sun.security.util.AbstractAlgorithmConstraints.getAlgorithms; @@ -42,15 +40,12 @@ public final static String PROPERTY_TLS_LEGACY_ALGS = "jdk.tls.legacyAlgorithms"; - private final static Map<String, String[]> legacyAlgorithmsMap = - new HashMap<>(); - private final String[] legacyAlgorithms; public LegacyAlgorithmConstraints(String propertyName, AlgorithmDecomposer decomposer) { super(decomposer); - legacyAlgorithms = getAlgorithms(legacyAlgorithmsMap, propertyName); + legacyAlgorithms = getAlgorithms(propertyName); } @Override
--- a/src/share/classes/sun/security/util/ObjectIdentifier.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/classes/sun/security/util/ObjectIdentifier.java Mon Jan 23 16:30:43 2017 +0000 @@ -255,7 +255,13 @@ + " (tag = " + type_id + ")" ); - encoding = new byte[in.getLength()]; + int len = in.getLength(); + if (len > in.available()) { + throw new IOException("ObjectIdentifier() -- length exceeds" + + "data available. Length: " + len + ", Available: " + + in.available()); + } + encoding = new byte[len]; in.getBytes(encoding); check(encoding); }
--- a/src/share/classes/sun/security/x509/X509CertImpl.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/classes/sun/security/x509/X509CertImpl.java Mon Jan 23 16:30:43 2017 +0000 @@ -1932,18 +1932,19 @@ public String getFingerprint(String algorithm) { return fingerprints.computeIfAbsent(algorithm, - x -> getCertificateFingerPrint(x)); + x -> getFingerprint(x, this)); } /** * Gets the requested finger print of the certificate. The result * only contains 0-9 and A-F. No small case, no colon. */ - private String getCertificateFingerPrint(String mdAlg) { + public static String getFingerprint(String algorithm, + X509Certificate cert) { String fingerPrint = ""; try { - byte[] encCertInfo = getEncoded(); - MessageDigest md = MessageDigest.getInstance(mdAlg); + byte[] encCertInfo = cert.getEncoded(); + MessageDigest md = MessageDigest.getInstance(algorithm); byte[] digest = md.digest(encCertInfo); StringBuffer buf = new StringBuffer(); for (int i = 0; i < digest.length; i++) {
--- a/src/share/classes/sun/util/resources/TimeZoneNames.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/classes/sun/util/resources/TimeZoneNames.java Mon Jan 23 16:30:43 2017 +0000 @@ -188,6 +188,9 @@ String MHT[] = new String[] {"Marshall Islands Time", "MHT", "Marshall Islands Summer Time", "MHST", "Marshall Islands Time", "MHT"}; + String MMT[] = new String[] {"Myanmar Time", "MMT", + "Myanmar Summer Time", "MMST", + "Myanmar Time", "MMT"}; String MSK[] = new String[] {"Moscow Standard Time", "MSK", "Moscow Daylight Time", "MSD", "Moscow Time", "MT"}; @@ -683,9 +686,7 @@ {"Asia/Qyzylorda", new String[] {"Qyzylorda Time", "QYZT", "Qyzylorda Summer Time", "QYZST", "Qyzylorda Time", "QYZT"}}, - {"Asia/Rangoon", new String[] {"Myanmar Time", "MMT", - "Myanmar Summer Time", "MMST", - "Myanmar Time", "MMT"}}, + {"Asia/Rangoon", MMT}, {"Asia/Riyadh", ARAST}, {"Asia/Saigon", ICT}, {"Asia/Sakhalin", new String[] {"Sakhalin Time", "SAKT", @@ -718,6 +719,7 @@ "Vladivostok Summer Time", "VLAST", "Vladivostok Time", "VLAT"}}, {"Asia/Yakutsk", YAKT}, + {"Asia/Yangon", MMT}, {"Asia/Yekaterinburg", new String[] {"Yekaterinburg Time", "YEKT", "Yekaterinburg Summer Time", "YEKST", "Yekaterinburg Time", "YEKT"}},
--- a/src/share/classes/sun/util/resources/de/TimeZoneNames_de.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/classes/sun/util/resources/de/TimeZoneNames_de.java Mon Jan 23 16:30:43 2017 +0000 @@ -189,6 +189,9 @@ String MHT[] = new String[] {"Marshallinseln Zeit", "MHT", "Marshallinseln Sommerzeit", "MHST", "Marshallinseln Zeit", "MHT"}; + String MMT[] = new String[] {"Myanmar Zeit", "MMT", + "Myanmar Sommerzeit", "MMST", + "Myanmar Zeit", "MMT"}; String MSK[] = new String[] {"Moskauer Normalzeit", "MSK", "Moskauer Sommerzeit", "MSD", "Zeitzone f\u00FCr Moskau", "MT"}; @@ -684,9 +687,7 @@ {"Asia/Qyzylorda", new String[] {"Qyzylorda Zeit", "QYZT", "Qyzylorda Sommerzeit", "QYZST", "Qyzylorda Zeit", "QYZT"}}, - {"Asia/Rangoon", new String[] {"Myanmar Zeit", "MMT", - "Myanmar Sommerzeit", "MMST", - "Myanmar Zeit", "MMT"}}, + {"Asia/Rangoon", MMT}, {"Asia/Riyadh", ARAST}, {"Asia/Saigon", ICT}, {"Asia/Sakhalin", new String[] {"Sakhalin Zeit", "SAKT", @@ -719,6 +720,7 @@ "Wladiwostok Sommerzeit", "VLAST", "Wladiwostok Zeit", "VLAT"}}, {"Asia/Yakutsk", YAKT}, + {"Asia/Yangon", MMT}, {"Asia/Yekaterinburg", new String[] {"Jekaterinburger Zeit", "YEKT", "Jekaterinburger Sommerzeit", "YEKST", "Jekaterinburger Zeit", "YEKT"}},
--- a/src/share/classes/sun/util/resources/es/TimeZoneNames_es.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/classes/sun/util/resources/es/TimeZoneNames_es.java Mon Jan 23 16:30:43 2017 +0000 @@ -189,6 +189,9 @@ String MHT[] = new String[] {"Hora de las Islas Marshall", "MHT", "Hora de verano de las Islas Marshall", "MHST", "Hora de Islas Marshall", "MHT"}; + String MMT[] = new String[] {"Hora de Myanmar", "MMT", + "Hora de verano de Myanmar", "MMST", + "Hora de Myanmar", "MMT"}; String MSK[] = new String[] {"Hora est\u00e1ndar de Mosc\u00fa", "MSK", "Hora de verano de Mosc\u00fa", "MSD", "Hora de Mosc\u00FA", "MT"}; @@ -684,9 +687,7 @@ {"Asia/Qyzylorda", new String[] {"Hora de Qyzylorda", "QYZT", "Hora de verano de Qyzylorda", "QYZST", "Hora de Qyzylorda", "QYZT"}}, - {"Asia/Rangoon", new String[] {"Hora de Myanmar", "MMT", - "Hora de verano de Myanmar", "MMST", - "Hora de Myanmar", "MMT"}}, + {"Asia/Rangoon", MMT}, {"Asia/Riyadh", ARAST}, {"Asia/Saigon", ICT}, {"Asia/Sakhalin", new String[] {"Hora de Sajalin", "SAKT", @@ -719,6 +720,7 @@ "Hora de verano de Vladivostok", "VLAST", "Hora de Vladivostok", "VLAT"}}, {"Asia/Yakutsk", YAKT}, + {"Asia/Yangon", MMT}, {"Asia/Yekaterinburg", new String[] {"Hora de Ekaterinburgo", "YEKT", "Hora de verano de Ekaterinburgo", "YEKST", "Hora de Ekaterinburgo", "YEKT"}},
--- a/src/share/classes/sun/util/resources/fr/TimeZoneNames_fr.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/classes/sun/util/resources/fr/TimeZoneNames_fr.java Mon Jan 23 16:30:43 2017 +0000 @@ -189,6 +189,9 @@ String MHT[] = new String[] {"Heure des Iles Marshall", "MHT", "Heure d'\u00e9t\u00e9 des Iles Marshall", "MHST", "Heure des Iles Marshall", "MHT"}; + String MMT[] = new String[] {"Heure de Myanmar", "MMT", + "Heure d'\u00e9t\u00e9 de Myanmar", "MMST", + "Heure de Myanmar", "MMT"}; String MSK[] = new String[] {"Heure standard de Moscou", "MSK", "Heure avanc\u00e9e de Moscou", "MSD", "Moscou", "MT"}; @@ -684,9 +687,7 @@ {"Asia/Qyzylorda", new String[] {"Heure de Kyzylorda", "QYZT", "Heure d'\u00e9t\u00e9 de Kyzylorda", "QYZST", "Heure de Kyzylorda", "QYZT"}}, - {"Asia/Rangoon", new String[] {"Heure de Myanmar", "MMT", - "Heure d'\u00e9t\u00e9 de Myanmar", "MMST", - "Heure de Myanmar", "MMT"}}, + {"Asia/Rangoon", MMT}, {"Asia/Riyadh", ARAST}, {"Asia/Saigon", ICT}, {"Asia/Sakhalin", new String[] {"Heure de Sakhalin", "SAKT", @@ -719,6 +720,7 @@ "Heure d'\u00e9t\u00e9 de Vladivostok", "VLAST", "Heure de Vladivostok", "VLAT"}}, {"Asia/Yakutsk", YAKT}, + {"Asia/Yangon", MMT}, {"Asia/Yekaterinburg", new String[] {"Heure de Yekaterinburg", "YEKT", "Heure d'\u00e9t\u00e9 de Yekaterinburg", "YEKST", "Heure de Yekaterinburg", "YEKT"}},
--- a/src/share/classes/sun/util/resources/it/TimeZoneNames_it.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/classes/sun/util/resources/it/TimeZoneNames_it.java Mon Jan 23 16:30:43 2017 +0000 @@ -189,6 +189,9 @@ String MHT[] = new String[] {"Ora delle Isole Marshall", "MHT", "Ora estiva delle Isole Marshall", "MHST", "Ora delle Isole Marshall", "MHT"}; + String MMT[] = new String[] {"Ora della Birmania/Myanmar", "MMT", + "Ora estiva della Birmania/Myanmar", "MMST", + "Ora della Birmania/Myanmar", "MMT"}; String MSK[] = new String[] {"Ora standard di Mosca", "MSK", "Ora legale di Mosca", "MSD", "Ora Mosca", "MT"}; @@ -684,9 +687,7 @@ {"Asia/Qyzylorda", new String[] {"Ora di Qyzylorda", "QYZT", "Ora estiva di Qyzylorda", "QYZST", "Ora di Qyzylorda", "QYZT"}}, - {"Asia/Rangoon", new String[] {"Ora della Birmania/Myanmar", "MMT", - "Ora estiva della Birmania/Myanmar", "MMST", - "Ora della Birmania/Myanmar", "MMT"}}, + {"Asia/Rangoon", MMT}, {"Asia/Riyadh", ARAST}, {"Asia/Saigon", ICT}, {"Asia/Sakhalin", new String[] {"Ora di Sakhalin", "SAKT", @@ -719,6 +720,7 @@ "Ora estiva di Vladivostok", "VLAST", "Ora di Vladivostok", "VLAT"}}, {"Asia/Yakutsk", YAKT}, + {"Asia/Yangon", MMT}, {"Asia/Yekaterinburg", new String[] {"Ora di Ekaterinburg", "YEKT", "Ora estiva di Ekaterinburg", "YEKST", "Ora di Ekaterinburg", "YEKT"}},
--- a/src/share/classes/sun/util/resources/ja/TimeZoneNames_ja.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/classes/sun/util/resources/ja/TimeZoneNames_ja.java Mon Jan 23 16:30:43 2017 +0000 @@ -189,6 +189,9 @@ String MHT[] = new String[] {"\u30de\u30fc\u30b7\u30e3\u30eb\u5cf6\u6642\u9593", "MHT", "\u30de\u30fc\u30b7\u30e3\u30eb\u5cf6\u590f\u6642\u9593", "MHST", "\u30DE\u30FC\u30B7\u30E3\u30EB\u8AF8\u5CF6\u6642\u9593", "MHT"}; + String MMT[] = new String[] {"\u30df\u30e3\u30f3\u30de\u30fc\u6642\u9593", "MMT", + "\u30df\u30e3\u30f3\u30de\u30fc\u590f\u6642\u9593", "MMST", + "\u30DF\u30E3\u30F3\u30DE\u30FC\u6642\u9593", "MMT"}; String MSK[] = new String[] {"\u30e2\u30b9\u30af\u30ef\u6a19\u6e96\u6642", "MSK", "\u30e2\u30b9\u30af\u30ef\u590f\u6642\u9593", "MSD", "\u30E2\u30B9\u30AF\u30EF\u6642\u9593", "MT"}; @@ -684,9 +687,7 @@ {"Asia/Qyzylorda", new String[] {"\u30ad\u30b8\u30eb\u30aa\u30eb\u30c0\u6642\u9593", "QYZT", "\u30ad\u30b8\u30eb\u30aa\u30eb\u30c0\u590f\u6642\u9593", "QYZST", "\u30AF\u30BA\u30ED\u30EB\u30C0\u6642\u9593", "QYZT"}}, - {"Asia/Rangoon", new String[] {"\u30df\u30e3\u30f3\u30de\u30fc\u6642\u9593", "MMT", - "\u30df\u30e3\u30f3\u30de\u30fc\u590f\u6642\u9593", "MMST", - "\u30DF\u30E3\u30F3\u30DE\u30FC\u6642\u9593", "MMT"}}, + {"Asia/Rangoon", MMT}, {"Asia/Riyadh", ARAST}, {"Asia/Saigon", ICT}, {"Asia/Sakhalin", new String[] {"\u6a3a\u592a\u6642\u9593", "SAKT", @@ -719,6 +720,7 @@ "\u30a6\u30e9\u30b8\u30aa\u30b9\u30c8\u30af\u590f\u6642\u9593", "VLAST", "\u30A6\u30E9\u30B8\u30AA\u30B9\u30C8\u30AF\u6642\u9593", "VLAT"}}, {"Asia/Yakutsk", YAKT}, + {"Asia/Yangon", MMT}, {"Asia/Yekaterinburg", new String[] {"\u30a8\u30ab\u30c6\u30ea\u30f3\u30d6\u30eb\u30b0\u6642\u9593", "YEKT", "\u30a8\u30ab\u30c6\u30ea\u30f3\u30d6\u30eb\u30b0\u590f\u6642\u9593", "YEKST", "\u30A8\u30AB\u30C6\u30EA\u30F3\u30D6\u30EB\u30AF\u6642\u9593", "YEKT"}},
--- a/src/share/classes/sun/util/resources/ko/TimeZoneNames_ko.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/classes/sun/util/resources/ko/TimeZoneNames_ko.java Mon Jan 23 16:30:43 2017 +0000 @@ -189,6 +189,9 @@ String MHT[] = new String[] {"\ub9c8\uc15c\uc81c\ub3c4 \uc2dc\uac04", "MHT", "\ub9c8\uc15c\uc81c\ub3c4 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "MHST", "\uB9C8\uC15C \uC81C\uB3C4 \uD45C\uC900\uC2DC", "MHT"}; + String MMT[] = new String[] {"\ubbf8\uc580\ub9c8 \uc2dc\uac04", "MMT", + "\ubbf8\uc580\ub9c8 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "MMST", + "\uBBF8\uC580\uB9C8 \uD45C\uC900\uC2DC", "MMT"}; String MSK[] = new String[] {"\ubaa8\uc2a4\ud06c\ubc14 \ud45c\uc900\uc2dc", "MSK", "\ubaa8\uc2a4\ud06c\ubc14 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "MSD", "\uBAA8\uC2A4\uD06C\uBC14 \uD45C\uC900\uC2DC", "MT"}; @@ -684,9 +687,7 @@ {"Asia/Qyzylorda", new String[] {"Qyzylorda \ud45c\uc900\uc2dc", "QYZT", "Qyzylorda \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "QYZST", "\uD0A4\uC9C8\uB85C\uB974\uB2E4 \uD45C\uC900\uC2DC", "QYZT"}}, - {"Asia/Rangoon", new String[] {"\ubbf8\uc580\ub9c8 \uc2dc\uac04", "MMT", - "\ubbf8\uc580\ub9c8 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "MMST", - "\uBBF8\uC580\uB9C8 \uD45C\uC900\uC2DC", "MMT"}}, + {"Asia/Rangoon", MMT}, {"Asia/Riyadh", ARAST}, {"Asia/Saigon", ICT}, {"Asia/Sakhalin", new String[] {"\uc0ac\ud560\ub9b0 \uc2dc\uac04", "SAKT", @@ -719,6 +720,7 @@ "\ube14\ub77c\ub514\ubcf4\uc2a4\ud1a1 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "VLAST", "\uBE14\uB77C\uB514\uBCF4\uC2A4\uD1A1 \uD45C\uC900\uC2DC", "VLAT"}}, {"Asia/Yakutsk", YAKT}, + {"Asia/Yangon", MMT}, {"Asia/Yekaterinburg", new String[] {"\uc608\uce74\ud14c\ub9b0\ubc84\uadf8 \uc2dc\uac04", "YEKT", "\uc608\uce74\ud14c\ub9b0\ubc84\uadf8 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "YEKST", "\uC608\uCE74\uD14C\uB9B0\uBD80\uB974\uD06C \uD45C\uC900\uC2DC", "YEKT"}},
--- a/src/share/classes/sun/util/resources/pt/TimeZoneNames_pt_BR.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/classes/sun/util/resources/pt/TimeZoneNames_pt_BR.java Mon Jan 23 16:30:43 2017 +0000 @@ -189,6 +189,9 @@ String MSK[] = new String[] {"Fuso hor\u00e1rio padr\u00e3o de Moscou", "MSK", "Hor\u00e1rio de luz natural de Moscou", "MSD", "Hor\u00E1rio de Moscou", "MT"}; + String MMT[] = new String[] {"Fuso hor\u00e1rio de Mianmar", "MMT", + "Fuso hor\u00e1rio de ver\u00e3o de Mianmar", "MMST", + "Hor\u00E1rio de Mianmar", "MMT"}; String MST[] = new String[] {"Fuso hor\u00e1rio padr\u00e3o das montanhas", "MST", "Hor\u00e1rio de luz natural das montanhas", "MDT", "Hor\u00E1rio das Montanhas Rochosas", "MT"}; @@ -684,9 +687,7 @@ {"Asia/Qyzylorda", new String[] {"Fuso hor\u00e1rio de Kizil-Orda", "QYZT", "Fuso hor\u00e1rio de ver\u00e3o de Kizil-Orda", "QYZST", "Hor\u00E1rio de Qyzylorda", "QYZT"}}, - {"Asia/Rangoon", new String[] {"Fuso hor\u00e1rio de Mianmar", "MMT", - "Fuso hor\u00e1rio de ver\u00e3o de Mianmar", "MMST", - "Hor\u00E1rio de Mianmar", "MMT"}}, + {"Asia/Rangoon", MMT}, {"Asia/Riyadh", ARAST}, {"Asia/Saigon", ICT}, {"Asia/Sakhalin", new String[] {"Fuso hor\u00e1rio de Sakhalina", "SAKT", @@ -719,6 +720,7 @@ "Fuso hor\u00e1rio de ver\u00e3o de Vladivostok", "VLAST", "Hor\u00E1rio de Vladivostok", "VLAT"}}, {"Asia/Yakutsk", YAKT}, + {"Asia/Yangon", MMT}, {"Asia/Yekaterinburg", new String[] {"Fuso hor\u00e1rio de Yekaterinburgo", "YEKT", "Fuso hor\u00e1rio de ver\u00e3o de Yekaterinburgo", "YEKST", "Hor\u00E1rio de Yekaterinburg", "YEKT"}},
--- a/src/share/classes/sun/util/resources/sv/TimeZoneNames_sv.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/classes/sun/util/resources/sv/TimeZoneNames_sv.java Mon Jan 23 16:30:43 2017 +0000 @@ -189,6 +189,9 @@ String MHT[] = new String[] {"Marshall\u00f6arna, normaltid", "MHT", "Marshall\u00f6arna, sommartid", "MHST", "Marshall\u00F6arna-tid", "MHT"}; + String MMT[] = new String[] {"Myanmar, normaltid", "MMT", + "Myanmar, sommartid", "MMST", + "Myanmar-tid", "MMT"}; String MSK[] = new String[] {"Moskva, normaltid", "MSK", "Moskva, sommartid", "MSD", "Moskvas tid", "MT"}; @@ -684,9 +687,7 @@ {"Asia/Qyzylorda", new String[] {"Qyzylorda, normaltid", "QYZT", "Qyzylorda, sommartid", "QYZST", "Qyzylorda-tid", "QYZT"}}, - {"Asia/Rangoon", new String[] {"Myanmar, normaltid", "MMT", - "Myanmar, sommartid", "MMST", - "Myanmar-tid", "MMT"}}, + {"Asia/Rangoon", MMT}, {"Asia/Riyadh", ARAST}, {"Asia/Saigon", ICT}, {"Asia/Sakhalin", new String[] {"Sakhalin, normaltid", "SAKT", @@ -719,6 +720,7 @@ "Vladivostok, sommartid", "VLAST", "Vladivostok-tid", "VLAT"}}, {"Asia/Yakutsk", YAKT}, + {"Asia/Yangon", MMT}, {"Asia/Yekaterinburg", new String[] {"Jekaterinburg, normaltid", "YEKT", "Jekaterinburg, sommartid", "YEKST", "Jekaterinburg-tid", "YEKT"}},
--- a/src/share/classes/sun/util/resources/zh/TimeZoneNames_zh_CN.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/classes/sun/util/resources/zh/TimeZoneNames_zh_CN.java Mon Jan 23 16:30:43 2017 +0000 @@ -189,6 +189,9 @@ String MHT[] = new String[] {"\u9a6c\u7ecd\u5c14\u7fa4\u5c9b\u65f6\u95f4", "MHT", "\u9a6c\u7ecd\u5c14\u7fa4\u5c9b\u590f\u4ee4\u65f6", "MHST", "\u9A6C\u7ECD\u5C14\u7FA4\u5C9B\u65F6\u95F4", "MHT"}; + String MMT[] = new String[] {"\u7f05\u7538\u65f6\u95f4", "MMT", + "\u7f05\u7538\u590f\u4ee4\u65f6", "MMST", + "\u7F05\u7538\u65F6\u95F4", "MMT"}; String MSK[] = new String[] {"\u83ab\u65af\u79d1\u6807\u51c6\u65f6\u95f4", "MSK", "\u83ab\u65af\u79d1\u590f\u4ee4\u65f6", "MSD", "\u83AB\u65AF\u79D1\u65F6\u95F4", "MT"}; @@ -684,9 +687,7 @@ {"Asia/Qyzylorda", new String[] {"Qyzylorda \u65f6\u95f4", "QYZT", "Qyzylorda \u590f\u4ee4\u65f6", "QYZST", "Qyzylorda \u65F6\u95F4", "QYZT"}}, - {"Asia/Rangoon", new String[] {"\u7f05\u7538\u65f6\u95f4", "MMT", - "\u7f05\u7538\u590f\u4ee4\u65f6", "MMST", - "\u7F05\u7538\u65F6\u95F4", "MMT"}}, + {"Asia/Rangoon", MMT}, {"Asia/Riyadh", ARAST}, {"Asia/Saigon", ICT}, {"Asia/Sakhalin", new String[] {"\u5e93\u9875\u5c9b\u65f6\u95f4", "SAKT", @@ -719,6 +720,7 @@ "\u6d77\u53c2\u5d34\u590f\u4ee4\u65f6", "VLAST", "\u6D77\u53C2\u5D34\u65F6\u95F4", "VLAT"}}, {"Asia/Yakutsk", YAKT}, + {"Asia/Yangon", MMT}, {"Asia/Yekaterinburg", new String[] {"Yekaterinburg \u65f6\u95f4", "YEKT", "Yekaterinburg \u590f\u4ee4\u65f6", "YEKST", "Yekaterinburg \u65F6\u95F4", "YEKT"}},
--- a/src/share/classes/sun/util/resources/zh/TimeZoneNames_zh_TW.java Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/classes/sun/util/resources/zh/TimeZoneNames_zh_TW.java Mon Jan 23 16:30:43 2017 +0000 @@ -189,6 +189,9 @@ String MHT[] = new String[] {"\u99ac\u7d39\u723e\u7fa4\u5cf6\u6642\u9593", "MHT", "\u99ac\u7d39\u723e\u7fa4\u5cf6\u590f\u4ee4\u6642\u9593", "MHST", "\u99AC\u7D39\u723E\u7FA4\u5CF6\u6642\u9593", "MHT"}; + String MMT[] = new String[] {"\u7dec\u7538\u6642\u9593", "MMT", + "\u7dec\u7538\u590f\u4ee4\u6642\u9593", "MMST", + "\u7DEC\u7538\u6642\u9593", "MMT"}; String MSK[] = new String[] {"\u83ab\u65af\u79d1\u6a19\u6e96\u6642\u9593", "MSK", "\u83ab\u65af\u79d1\u65e5\u5149\u7bc0\u7d04\u6642\u9593", "MSD", "\u83AB\u65AF\u79D1\u6642\u9593", "MT"}; @@ -684,9 +687,7 @@ {"Asia/Qyzylorda", new String[] {"Qyzylorda \u6642\u9593", "QYZT", "Qyzylorda \u590f\u4ee4\u6642\u9593", "QYZST", "\u514B\u5B5C\u6D1B\u723E\u9054\u6642\u9593", "QYZT"}}, - {"Asia/Rangoon", new String[] {"\u7dec\u7538\u6642\u9593", "MMT", - "\u7dec\u7538\u590f\u4ee4\u6642\u9593", "MMST", - "\u7DEC\u7538\u6642\u9593", "MMT"}}, + {"Asia/Rangoon", MMT}, {"Asia/Riyadh", ARAST}, {"Asia/Saigon", ICT}, {"Asia/Sakhalin", new String[] {"\u5eab\u9801\u5cf6\u6642\u9593", "SAKT", @@ -721,6 +722,7 @@ "\u6d77\u53c3\u5d34\u590f\u4ee4\u6642\u9593", "VLAST", "\u6D77\u53C3\u5D34\u6642\u9593", "VLAT"}}, {"Asia/Yakutsk", YAKT}, + {"Asia/Yangon", MMT}, {"Asia/Yekaterinburg", new String[] {"Yekaterinburg \u6642\u9593", "YEKT", "Yekaterinburg \u590f\u4ee4\u6642\u9593", "YEKST", "\u8449\u5361\u6377\u7433\u5821\u6642\u9593", "YEKT"}},
--- a/src/share/lib/security/java.security-aix Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/lib/security/java.security-aix Mon Jan 23 16:30:43 2017 +0000 @@ -436,13 +436,13 @@ # " DisabledAlgorithm { , DisabledAlgorithm } " # # DisabledAlgorithm: -# AlgorithmName [Constraint] +# AlgorithmName [Constraint] { '&' Constraint } # # AlgorithmName: # (see below) # # Constraint: -# KeySizeConstraint +# KeySizeConstraint, CertConstraint # # KeySizeConstraint: # keySize Operator DecimalInteger @@ -459,6 +459,9 @@ # DecimalDigit: one of # 1 2 3 4 5 6 7 8 9 0 # +# CertConstraint +# jdkCA +# # The "AlgorithmName" is the standard algorithm name of the disabled # algorithm. See "Java Cryptography Architecture Standard Algorithm Name # Documentation" for information about Standard Algorithm Names. Matching @@ -481,6 +484,29 @@ # be disabled. Note that the "KeySizeConstraint" only makes sense to key # algorithms. # +# "CertConstraint" specifies additional constraints for +# certificates that contain algorithms that are restricted: +# +# "jdkCA" prohibits the specified algorithm only if the algorithm is used +# in a certificate chain that terminates at a marked trust anchor in the +# lib/security/cacerts keystore. All other chains are not affected. +# If the jdkCA constraint is not set, then all chains using the +# specified algorithm are restricted. jdkCA may only be used once in +# a DisabledAlgorithm expression. +# Example: To apply this constraint to SHA-1 certificates, include +# the following "SHA1 jdkCA" +# +# When an algorithm must satisfy more than one constraint, it must be +# delimited by an ampersand '&'. For example, to restrict certificates in a +# chain that terminate at a distribution provided trust anchor and contain +# RSA keys that are less than or equal to 1024 bits, add the following +# constraint: "RSA keySize <= 1024 & jdkCA". +# +# All DisabledAlgorithms expressions are processed in the order defined in the +# property. This requires lower keysize constraints to be specified +# before larger keysize constraints of the same algorithm. For example: +# "RSA keySize < 1024 & jdkCA, RSA keySize < 2048". +# # Note: This property is currently used by Oracle's PKIX implementation. It # is not guaranteed to be examined and used by other implementations. # @@ -488,7 +514,45 @@ # jdk.certpath.disabledAlgorithms=MD2, DSA, RSA keySize < 2048 # # -jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024 +jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024, \ + DSA keySize < 1024, EC keySize < 224 + +# Algorithm restrictions for signed JAR files +# +# In some environments, certain algorithms or key lengths may be undesirable +# for signed JAR validation. For example, "MD2" is generally no longer +# considered to be a secure hash algorithm. This section describes the +# mechanism for disabling algorithms based on algorithm name and/or key length. +# JARs signed with any of the disabled algorithms or key sizes will be treated +# as unsigned. +# +# The syntax of the disabled algorithm string is described as follows: +# DisabledAlgorithms: +# " DisabledAlgorithm { , DisabledAlgorithm } " +# +# DisabledAlgorithm: +# AlgorithmName [Constraint] +# +# AlgorithmName: +# (see below) +# +# Constraint: +# KeySizeConstraint +# +# KeySizeConstraint: +# keySize Operator KeyLength +# +# Operator: +# <= | < | == | != | >= | > +# +# KeyLength: +# Integer value of the algorithm's key length in bits +# +# Note: This property is currently used by the JDK Reference +# implementation. It is not guaranteed to be examined and used by other +# implementations. +# +jdk.jar.disabledAlgorithms=MD2, RSA keySize < 1024 # Algorithm restrictions for Secure Socket Layer/Transport Layer Security # (SSL/TLS) processing @@ -511,12 +575,13 @@ # See the specification of "jdk.certpath.disabledAlgorithms" for the # syntax of the disabled algorithm string. # -# Note: This property is currently used by Oracle's JSSE implementation. +# 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.tls.disabledAlgorithms=MD5, SSLv3, DSA, RSA keySize < 2048 -jdk.tls.disabledAlgorithms=SSLv3, RC4, MD5withRSA, DH keySize < 768 +jdk.tls.disabledAlgorithms=SSLv3, RC4, MD5withRSA, DH keySize < 768, \ + EC keySize < 224 # Legacy algorithms for Secure Socket Layer/Transport Layer Security (SSL/TLS) # processing in JSSE implementation. @@ -530,7 +595,7 @@ # During SSL/TLS security parameters negotiation, legacy algorithms will # not be negotiated unless there are no other candidates. # -# The syntax of the disabled algorithm string is described as this Java +# The syntax of the legacy algorithms string is described as this Java # BNF-style: # LegacyAlgorithms: # " LegacyAlgorithm { , LegacyAlgorithm } " @@ -560,7 +625,7 @@ # See SSL/TLS specifications and "Java Cryptography Architecture Standard # Algorithm Name Documentation" for information about the algorithm names. # -# Note: This property is currently used by Oracle's JSSE implementation. +# Note: This property is currently used by the JDK Reference implementation. # It is not guaranteed to be examined and used by other implementations. # There is no guarantee the property will continue to exist or be of the # same syntax in future releases. @@ -573,7 +638,8 @@ DHE_DSS_EXPORT, DHE_RSA_EXPORT, DH_anon_EXPORT, DH_DSS_EXPORT, \ DH_RSA_EXPORT, RSA_EXPORT, \ DH_anon, ECDH_anon, \ - RC4_128, RC4_40, DES_CBC, DES40_CBC + RC4_128, RC4_40, DES_CBC, DES40_CBC, \ + 3DES_EDE_CBC # The pre-defined default finite field Diffie-Hellman ephemeral (DHE) # parameters for Transport Layer Security (SSL/TLS/DTLS) processing. @@ -632,39 +698,111 @@ # EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE65381 \ # FFFFFFFF FFFFFFFF, 2} -# Algorithm restrictions for signed JAR files +# +# The policy for the XML Signature secure validation mode. The mode is +# enabled by setting the property "org.jcp.xml.dsig.secureValidation" to +# true with the javax.xml.crypto.XMLCryptoContext.setProperty() method, +# or by running the code with a SecurityManager. +# +# Policy: +# Constraint {"," Constraint } +# Constraint: +# AlgConstraint | MaxTransformsConstraint | MaxReferencesConstraint | +# ReferenceUriSchemeConstraint | KeySizeConstraint | OtherConstraint +# AlgConstraint +# "disallowAlg" Uri +# MaxTransformsConstraint: +# "maxTransforms" Integer +# MaxReferencesConstraint: +# "maxReferences" Integer +# ReferenceUriSchemeConstraint: +# "disallowReferenceUriSchemes" String { String } +# KeySizeConstraint: +# "minKeySize" KeyAlg Integer +# OtherConstraint: +# "noDuplicateIds" | "noRetrievalMethodLoops" # -# In some environments, certain algorithms or key lengths may be undesirable -# for signed JAR validation. For example, "MD2" is generally no longer -# considered to be a secure hash algorithm. This section describes the -# mechanism for disabling algorithms based on algorithm name and/or key length. -# JARs signed with any of the disabled algorithms or key sizes will be treated -# as unsigned. +# For AlgConstraint, Uri is the algorithm URI String that is not allowed. +# See the XML Signature Recommendation for more information on algorithm +# URI Identifiers. For KeySizeConstraint, KeyAlg is the standard algorithm +# name of the key type (ex: "RSA"). If the MaxTransformsConstraint, +# MaxReferencesConstraint or KeySizeConstraint (for the same key type) is +# specified more than once, only the last entry is enforced. +# +# Note: This property is currently used by the JDK Reference implementation. It +# is not guaranteed to be examined and used by other implementations. # -# The syntax of the disabled algorithm string is described as follows: -# DisabledAlgorithms: -# " DisabledAlgorithm { , DisabledAlgorithm } " +jdk.xml.dsig.secureValidationPolicy=\ + disallowAlg http://www.w3.org/TR/1999/REC-xslt-19991116,\ + disallowAlg http://www.w3.org/2001/04/xmldsig-more#rsa-md5,\ + disallowAlg http://www.w3.org/2001/04/xmldsig-more#hmac-md5,\ + disallowAlg http://www.w3.org/2001/04/xmldsig-more#md5,\ + maxTransforms 5,\ + maxReferences 30,\ + disallowReferenceUriSchemes file http https,\ + minKeySize RSA 1024,\ + minKeySize DSA 1024,\ + noDuplicateIds,\ + noRetrievalMethodLoops + # -# DisabledAlgorithm: -# AlgorithmName [Constraint] +# Serialization process-wide filter # -# AlgorithmName: -# (see below) +# A filter, if configured, is used by java.io.ObjectInputStream during +# deserialization to check the contents of the stream. +# A filter is configured as a sequence of patterns, each pattern is either +# matched against the name of a class in the stream or defines a limit. +# Patterns are separated by ";" (semicolon). +# Whitespace is significant and is considered part of the pattern. +# +# If a pattern includes a "=", it sets a limit. +# If a limit appears more than once the last value is used. +# Limits are checked before classes regardless of the order in the sequence of patterns. +# If any of the limits are exceeded, the filter status is REJECTED. # -# Constraint: -# KeySizeConstraint +# maxdepth=value - the maximum depth of a graph +# maxrefs=value - the maximum number of internal references +# maxbytes=value - the maximum number of bytes in the input stream +# maxarray=value - the maximum array length allowed # -# KeySizeConstraint: -# keySize Operator KeyLength +# Other patterns, from left to right, match the class or package name as +# returned from Class.getName. +# If the class is an array type, the class or package to be matched is the element type. +# Arrays of any number of dimensions are treated the same as the element type. +# For example, a pattern of "!example.Foo", rejects creation of any instance or +# array of example.Foo. # -# Operator: -# <= | < | == | != | >= | > +# If the pattern starts with "!", the status is REJECTED if the remaining pattern +# is matched; otherwise the status is ALLOWED if the pattern matches. +# If the pattern ends with ".**" it matches any class in the package and all subpackages. +# If the pattern ends with ".*" it matches any class in the package. +# If the pattern ends with "*", it matches any class with the pattern as a prefix. +# If the pattern is equal to the class name, it matches. +# Otherwise, the status is UNDECIDED. # -# KeyLength: -# Integer value of the algorithm's key length in bits +#jdk.serialFilter=pattern;pattern + +# +# RMI Registry Serial Filter +# +# The filter pattern uses the same format as jdk.serialFilter. +# This filter can override the builtin filter if additional types need to be +# allowed or rejected from the RMI Registry. # -# Note: This property is currently used by the JDK Reference -# implementation. It is not guaranteed to be examined and used by other -# implementations. +#sun.rmi.registry.registryFilter=pattern;pattern + +# +# RMI Distributed Garbage Collector (DGC) Serial Filter +# +# The filter pattern uses the same format as jdk.serialFilter. +# This filter can override the builtin filter if additional types need to be +# allowed or rejected from the RMI DGC. # -jdk.jar.disabledAlgorithms=MD2, RSA keySize < 1024 +# The builtin DGC filter can approximately be represented as the filter pattern: +# +#sun.rmi.transport.dgcFilter=\ +# java.rmi.server.ObjID;\ +# java.rmi.server.UID;\ +# java.rmi.dgc.VMID;\ +# java.rmi.dgc.Lease;\ +# maxdepth=5;maxarray=10000
--- a/src/share/lib/security/java.security-linux Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/lib/security/java.security-linux Mon Jan 23 16:30:43 2017 +0000 @@ -436,13 +436,13 @@ # " DisabledAlgorithm { , DisabledAlgorithm } " # # DisabledAlgorithm: -# AlgorithmName [Constraint] +# AlgorithmName [Constraint] { '&' Constraint } # # AlgorithmName: # (see below) # # Constraint: -# KeySizeConstraint +# KeySizeConstraint, CertConstraint # # KeySizeConstraint: # keySize Operator DecimalInteger @@ -459,6 +459,9 @@ # DecimalDigit: one of # 1 2 3 4 5 6 7 8 9 0 # +# CertConstraint +# jdkCA +# # The "AlgorithmName" is the standard algorithm name of the disabled # algorithm. See "Java Cryptography Architecture Standard Algorithm Name # Documentation" for information about Standard Algorithm Names. Matching @@ -481,6 +484,29 @@ # be disabled. Note that the "KeySizeConstraint" only makes sense to key # algorithms. # +# "CertConstraint" specifies additional constraints for +# certificates that contain algorithms that are restricted: +# +# "jdkCA" prohibits the specified algorithm only if the algorithm is used +# in a certificate chain that terminates at a marked trust anchor in the +# lib/security/cacerts keystore. All other chains are not affected. +# If the jdkCA constraint is not set, then all chains using the +# specified algorithm are restricted. jdkCA may only be used once in +# a DisabledAlgorithm expression. +# Example: To apply this constraint to SHA-1 certificates, include +# the following: "SHA1 jdkCA" +# +# When an algorithm must satisfy more than one constraint, it must be +# delimited by an ampersand '&'. For example, to restrict certificates in a +# chain that terminate at a distribution provided trust anchor and contain +# RSA keys that are less than or equal to 1024 bits, add the following +# constraint: "RSA keySize <= 1024 & jdkCA". +# +# All DisabledAlgorithms expressions are processed in the order defined in the +# property. This requires lower keysize constraints to be specified +# before larger keysize constraints of the same algorithm. For example: +# "RSA keySize < 1024 & jdkCA, RSA keySize < 2048". +# # Note: This property is currently used by Oracle's PKIX implementation. It # is not guaranteed to be examined and used by other implementations. # @@ -488,7 +514,45 @@ # jdk.certpath.disabledAlgorithms=MD2, DSA, RSA keySize < 2048 # # -jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024 +jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024, \ + DSA keySize < 1024, EC keySize < 224 + +# Algorithm restrictions for signed JAR files +# +# In some environments, certain algorithms or key lengths may be undesirable +# for signed JAR validation. For example, "MD2" is generally no longer +# considered to be a secure hash algorithm. This section describes the +# mechanism for disabling algorithms based on algorithm name and/or key length. +# JARs signed with any of the disabled algorithms or key sizes will be treated +# as unsigned. +# +# The syntax of the disabled algorithm string is described as follows: +# DisabledAlgorithms: +# " DisabledAlgorithm { , DisabledAlgorithm } " +# +# DisabledAlgorithm: +# AlgorithmName [Constraint] +# +# AlgorithmName: +# (see below) +# +# Constraint: +# KeySizeConstraint +# +# KeySizeConstraint: +# keySize Operator KeyLength +# +# Operator: +# <= | < | == | != | >= | > +# +# KeyLength: +# Integer value of the algorithm's key length in bits +# +# Note: This property is currently used by the JDK Reference +# implementation. It is not guaranteed to be examined and used by other +# implementations. +# +jdk.jar.disabledAlgorithms=MD2, RSA keySize < 1024 # Algorithm restrictions for Secure Socket Layer/Transport Layer Security # (SSL/TLS) processing @@ -511,12 +575,13 @@ # See the specification of "jdk.certpath.disabledAlgorithms" for the # syntax of the disabled algorithm string. # -# Note: This property is currently used by Oracle's JSSE implementation. +# 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.tls.disabledAlgorithms=MD5, SSLv3, DSA, RSA keySize < 2048 -jdk.tls.disabledAlgorithms=SSLv3, RC4, MD5withRSA, DH keySize < 768 +jdk.tls.disabledAlgorithms=SSLv3, RC4, MD5withRSA, DH keySize < 768, \ + EC keySize < 224 # Legacy algorithms for Secure Socket Layer/Transport Layer Security (SSL/TLS) # processing in JSSE implementation. @@ -530,7 +595,7 @@ # During SSL/TLS security parameters negotiation, legacy algorithms will # not be negotiated unless there are no other candidates. # -# The syntax of the disabled algorithm string is described as this Java +# The syntax of the legacy algorithms string is described as this Java # BNF-style: # LegacyAlgorithms: # " LegacyAlgorithm { , LegacyAlgorithm } " @@ -560,7 +625,7 @@ # See SSL/TLS specifications and "Java Cryptography Architecture Standard # Algorithm Name Documentation" for information about the algorithm names. # -# Note: This property is currently used by Oracle's JSSE implementation. +# Note: This property is currently used by the JDK Reference implementation. # It is not guaranteed to be examined and used by other implementations. # There is no guarantee the property will continue to exist or be of the # same syntax in future releases. @@ -573,7 +638,8 @@ DHE_DSS_EXPORT, DHE_RSA_EXPORT, DH_anon_EXPORT, DH_DSS_EXPORT, \ DH_RSA_EXPORT, RSA_EXPORT, \ DH_anon, ECDH_anon, \ - RC4_128, RC4_40, DES_CBC, DES40_CBC + RC4_128, RC4_40, DES_CBC, DES40_CBC, \ + 3DES_EDE_CBC # The pre-defined default finite field Diffie-Hellman ephemeral (DHE) # parameters for Transport Layer Security (SSL/TLS/DTLS) processing. @@ -632,39 +698,111 @@ # EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE65381 \ # FFFFFFFF FFFFFFFF, 2} -# Algorithm restrictions for signed JAR files +# +# The policy for the XML Signature secure validation mode. The mode is +# enabled by setting the property "org.jcp.xml.dsig.secureValidation" to +# true with the javax.xml.crypto.XMLCryptoContext.setProperty() method, +# or by running the code with a SecurityManager. +# +# Policy: +# Constraint {"," Constraint } +# Constraint: +# AlgConstraint | MaxTransformsConstraint | MaxReferencesConstraint | +# ReferenceUriSchemeConstraint | KeySizeConstraint | OtherConstraint +# AlgConstraint +# "disallowAlg" Uri +# MaxTransformsConstraint: +# "maxTransforms" Integer +# MaxReferencesConstraint: +# "maxReferences" Integer +# ReferenceUriSchemeConstraint: +# "disallowReferenceUriSchemes" String { String } +# KeySizeConstraint: +# "minKeySize" KeyAlg Integer +# OtherConstraint: +# "noDuplicateIds" | "noRetrievalMethodLoops" # -# In some environments, certain algorithms or key lengths may be undesirable -# for signed JAR validation. For example, "MD2" is generally no longer -# considered to be a secure hash algorithm. This section describes the -# mechanism for disabling algorithms based on algorithm name and/or key length. -# JARs signed with any of the disabled algorithms or key sizes will be treated -# as unsigned. +# For AlgConstraint, Uri is the algorithm URI String that is not allowed. +# See the XML Signature Recommendation for more information on algorithm +# URI Identifiers. For KeySizeConstraint, KeyAlg is the standard algorithm +# name of the key type (ex: "RSA"). If the MaxTransformsConstraint, +# MaxReferencesConstraint or KeySizeConstraint (for the same key type) is +# specified more than once, only the last entry is enforced. +# +# Note: This property is currently used by the JDK Reference implementation. It +# is not guaranteed to be examined and used by other implementations. # -# The syntax of the disabled algorithm string is described as follows: -# DisabledAlgorithms: -# " DisabledAlgorithm { , DisabledAlgorithm } " +jdk.xml.dsig.secureValidationPolicy=\ + disallowAlg http://www.w3.org/TR/1999/REC-xslt-19991116,\ + disallowAlg http://www.w3.org/2001/04/xmldsig-more#rsa-md5,\ + disallowAlg http://www.w3.org/2001/04/xmldsig-more#hmac-md5,\ + disallowAlg http://www.w3.org/2001/04/xmldsig-more#md5,\ + maxTransforms 5,\ + maxReferences 30,\ + disallowReferenceUriSchemes file http https,\ + minKeySize RSA 1024,\ + minKeySize DSA 1024,\ + noDuplicateIds,\ + noRetrievalMethodLoops + # -# DisabledAlgorithm: -# AlgorithmName [Constraint] +# Serialization process-wide filter # -# AlgorithmName: -# (see below) +# A filter, if configured, is used by java.io.ObjectInputStream during +# deserialization to check the contents of the stream. +# A filter is configured as a sequence of patterns, each pattern is either +# matched against the name of a class in the stream or defines a limit. +# Patterns are separated by ";" (semicolon). +# Whitespace is significant and is considered part of the pattern. +# +# If a pattern includes a "=", it sets a limit. +# If a limit appears more than once the last value is used. +# Limits are checked before classes regardless of the order in the sequence of patterns. +# If any of the limits are exceeded, the filter status is REJECTED. # -# Constraint: -# KeySizeConstraint +# maxdepth=value - the maximum depth of a graph +# maxrefs=value - the maximum number of internal references +# maxbytes=value - the maximum number of bytes in the input stream +# maxarray=value - the maximum array length allowed # -# KeySizeConstraint: -# keySize Operator KeyLength +# Other patterns, from left to right, match the class or package name as +# returned from Class.getName. +# If the class is an array type, the class or package to be matched is the element type. +# Arrays of any number of dimensions are treated the same as the element type. +# For example, a pattern of "!example.Foo", rejects creation of any instance or +# array of example.Foo. # -# Operator: -# <= | < | == | != | >= | > +# If the pattern starts with "!", the status is REJECTED if the remaining pattern +# is matched; otherwise the status is ALLOWED if the pattern matches. +# If the pattern ends with ".**" it matches any class in the package and all subpackages. +# If the pattern ends with ".*" it matches any class in the package. +# If the pattern ends with "*", it matches any class with the pattern as a prefix. +# If the pattern is equal to the class name, it matches. +# Otherwise, the status is UNDECIDED. # -# KeyLength: -# Integer value of the algorithm's key length in bits +#jdk.serialFilter=pattern;pattern + +# +# RMI Registry Serial Filter +# +# The filter pattern uses the same format as jdk.serialFilter. +# This filter can override the builtin filter if additional types need to be +# allowed or rejected from the RMI Registry. # -# Note: This property is currently used by the JDK Reference -# implementation. It is not guaranteed to be examined and used by other -# implementations. +#sun.rmi.registry.registryFilter=pattern;pattern + +# +# RMI Distributed Garbage Collector (DGC) Serial Filter +# +# The filter pattern uses the same format as jdk.serialFilter. +# This filter can override the builtin filter if additional types need to be +# allowed or rejected from the RMI DGC. # -jdk.jar.disabledAlgorithms=MD2, RSA keySize < 1024 +# The builtin DGC filter can approximately be represented as the filter pattern: +# +#sun.rmi.transport.dgcFilter=\ +# java.rmi.server.ObjID;\ +# java.rmi.server.UID;\ +# java.rmi.dgc.VMID;\ +# java.rmi.dgc.Lease;\ +# maxdepth=5;maxarray=10000
--- a/src/share/lib/security/java.security-macosx Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/lib/security/java.security-macosx Mon Jan 23 16:30:43 2017 +0000 @@ -439,13 +439,13 @@ # " DisabledAlgorithm { , DisabledAlgorithm } " # # DisabledAlgorithm: -# AlgorithmName [Constraint] +# AlgorithmName [Constraint] { '&' Constraint } # # AlgorithmName: # (see below) # # Constraint: -# KeySizeConstraint +# KeySizeConstraint, CertConstraint # # KeySizeConstraint: # keySize Operator DecimalInteger @@ -462,6 +462,9 @@ # DecimalDigit: one of # 1 2 3 4 5 6 7 8 9 0 # +# CertConstraint +# jdkCA +# # The "AlgorithmName" is the standard algorithm name of the disabled # algorithm. See "Java Cryptography Architecture Standard Algorithm Name # Documentation" for information about Standard Algorithm Names. Matching @@ -484,6 +487,29 @@ # be disabled. Note that the "KeySizeConstraint" only makes sense to key # algorithms. # +# "CertConstraint" specifies additional constraints for +# certificates that contain algorithms that are restricted: +# +# "jdkCA" prohibits the specified algorithm only if the algorithm is used +# in a certificate chain that terminates at a marked trust anchor in the +# lib/security/cacerts keystore. All other chains are not affected. +# If the jdkCA constraint is not set, then all chains using the +# specified algorithm are restricted. jdkCA may only be used once in +# a DisabledAlgorithm expression. +# Example: To apply this constraint to SHA-1 certificates, include +# the following: "SHA1 jdkCA" +# +# When an algorithm must satisfy more than one constraint, it must be +# delimited by an ampersand '&'. For example, to restrict certificates in a +# chain that terminate at a distribution provided trust anchor and contain +# RSA keys that are less than or equal to 1024 bits, add the following +# constraint: "RSA keySize <= 1024 & jdkCA". +# +# All DisabledAlgorithms expressions are processed in the order defined in the +# property. This requires lower keysize constraints to be specified +# before larger keysize constraints of the same algorithm. For example: +# "RSA keySize < 1024 & jdkCA, RSA keySize < 2048". +# # Note: This property is currently used by Oracle's PKIX implementation. It # is not guaranteed to be examined and used by other implementations. # @@ -491,7 +517,45 @@ # jdk.certpath.disabledAlgorithms=MD2, DSA, RSA keySize < 2048 # # -jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024 +jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024, \ + DSA keySize < 1024, EC keySize < 224 + +# Algorithm restrictions for signed JAR files +# +# In some environments, certain algorithms or key lengths may be undesirable +# for signed JAR validation. For example, "MD2" is generally no longer +# considered to be a secure hash algorithm. This section describes the +# mechanism for disabling algorithms based on algorithm name and/or key length. +# JARs signed with any of the disabled algorithms or key sizes will be treated +# as unsigned. +# +# The syntax of the disabled algorithm string is described as follows: +# DisabledAlgorithms: +# " DisabledAlgorithm { , DisabledAlgorithm } " +# +# DisabledAlgorithm: +# AlgorithmName [Constraint] +# +# AlgorithmName: +# (see below) +# +# Constraint: +# KeySizeConstraint +# +# KeySizeConstraint: +# keySize Operator KeyLength +# +# Operator: +# <= | < | == | != | >= | > +# +# KeyLength: +# Integer value of the algorithm's key length in bits +# +# Note: This property is currently used by the JDK Reference +# implementation. It is not guaranteed to be examined and used by other +# implementations. +# +jdk.jar.disabledAlgorithms=MD2, RSA keySize < 1024 # Algorithm restrictions for Secure Socket Layer/Transport Layer Security # (SSL/TLS) processing @@ -514,12 +578,13 @@ # See the specification of "jdk.certpath.disabledAlgorithms" for the # syntax of the disabled algorithm string. # -# Note: This property is currently used by Oracle's JSSE implementation. +# 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.tls.disabledAlgorithms=MD5, SSLv3, DSA, RSA keySize < 2048 -jdk.tls.disabledAlgorithms=SSLv3, RC4, MD5withRSA, DH keySize < 768 +jdk.tls.disabledAlgorithms=SSLv3, RC4, MD5withRSA, DH keySize < 768, \ + EC keySize < 224 # Legacy algorithms for Secure Socket Layer/Transport Layer Security (SSL/TLS) # processing in JSSE implementation. @@ -533,7 +598,7 @@ # During SSL/TLS security parameters negotiation, legacy algorithms will # not be negotiated unless there are no other candidates. # -# The syntax of the disabled algorithm string is described as this Java +# The syntax of the legacy algorithms string is described as this Java # BNF-style: # LegacyAlgorithms: # " LegacyAlgorithm { , LegacyAlgorithm } " @@ -563,7 +628,7 @@ # See SSL/TLS specifications and "Java Cryptography Architecture Standard # Algorithm Name Documentation" for information about the algorithm names. # -# Note: This property is currently used by Oracle's JSSE implementation. +# Note: This property is currently used by the JDK Reference implementation. # It is not guaranteed to be examined and used by other implementations. # There is no guarantee the property will continue to exist or be of the # same syntax in future releases. @@ -576,7 +641,8 @@ DHE_DSS_EXPORT, DHE_RSA_EXPORT, DH_anon_EXPORT, DH_DSS_EXPORT, \ DH_RSA_EXPORT, RSA_EXPORT, \ DH_anon, ECDH_anon, \ - RC4_128, RC4_40, DES_CBC, DES40_CBC + RC4_128, RC4_40, DES_CBC, DES40_CBC, \ + 3DES_EDE_CBC # The pre-defined default finite field Diffie-Hellman ephemeral (DHE) # parameters for Transport Layer Security (SSL/TLS/DTLS) processing. @@ -635,39 +701,111 @@ # EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE65381 \ # FFFFFFFF FFFFFFFF, 2} -# Algorithm restrictions for signed JAR files +# +# The policy for the XML Signature secure validation mode. The mode is +# enabled by setting the property "org.jcp.xml.dsig.secureValidation" to +# true with the javax.xml.crypto.XMLCryptoContext.setProperty() method, +# or by running the code with a SecurityManager. +# +# Policy: +# Constraint {"," Constraint } +# Constraint: +# AlgConstraint | MaxTransformsConstraint | MaxReferencesConstraint | +# ReferenceUriSchemeConstraint | KeySizeConstraint | OtherConstraint +# AlgConstraint +# "disallowAlg" Uri +# MaxTransformsConstraint: +# "maxTransforms" Integer +# MaxReferencesConstraint: +# "maxReferences" Integer +# ReferenceUriSchemeConstraint: +# "disallowReferenceUriSchemes" String { String } +# KeySizeConstraint: +# "minKeySize" KeyAlg Integer +# OtherConstraint: +# "noDuplicateIds" | "noRetrievalMethodLoops" # -# In some environments, certain algorithms or key lengths may be undesirable -# for signed JAR validation. For example, "MD2" is generally no longer -# considered to be a secure hash algorithm. This section describes the -# mechanism for disabling algorithms based on algorithm name and/or key length. -# JARs signed with any of the disabled algorithms or key sizes will be treated -# as unsigned. +# For AlgConstraint, Uri is the algorithm URI String that is not allowed. +# See the XML Signature Recommendation for more information on algorithm +# URI Identifiers. For KeySizeConstraint, KeyAlg is the standard algorithm +# name of the key type (ex: "RSA"). If the MaxTransformsConstraint, +# MaxReferencesConstraint or KeySizeConstraint (for the same key type) is +# specified more than once, only the last entry is enforced. +# +# Note: This property is currently used by the JDK Reference implementation. It +# is not guaranteed to be examined and used by other implementations. # -# The syntax of the disabled algorithm string is described as follows: -# DisabledAlgorithms: -# " DisabledAlgorithm { , DisabledAlgorithm } " +jdk.xml.dsig.secureValidationPolicy=\ + disallowAlg http://www.w3.org/TR/1999/REC-xslt-19991116,\ + disallowAlg http://www.w3.org/2001/04/xmldsig-more#rsa-md5,\ + disallowAlg http://www.w3.org/2001/04/xmldsig-more#hmac-md5,\ + disallowAlg http://www.w3.org/2001/04/xmldsig-more#md5,\ + maxTransforms 5,\ + maxReferences 30,\ + disallowReferenceUriSchemes file http https,\ + minKeySize RSA 1024,\ + minKeySize DSA 1024,\ + noDuplicateIds,\ + noRetrievalMethodLoops + # -# DisabledAlgorithm: -# AlgorithmName [Constraint] +# Serialization process-wide filter # -# AlgorithmName: -# (see below) +# A filter, if configured, is used by java.io.ObjectInputStream during +# deserialization to check the contents of the stream. +# A filter is configured as a sequence of patterns, each pattern is either +# matched against the name of a class in the stream or defines a limit. +# Patterns are separated by ";" (semicolon). +# Whitespace is significant and is considered part of the pattern. +# +# If a pattern includes a "=", it sets a limit. +# If a limit appears more than once the last value is used. +# Limits are checked before classes regardless of the order in the sequence of patterns. +# If any of the limits are exceeded, the filter status is REJECTED. # -# Constraint: -# KeySizeConstraint +# maxdepth=value - the maximum depth of a graph +# maxrefs=value - the maximum number of internal references +# maxbytes=value - the maximum number of bytes in the input stream +# maxarray=value - the maximum array length allowed # -# KeySizeConstraint: -# keySize Operator KeyLength +# Other patterns, from left to right, match the class or package name as +# returned from Class.getName. +# If the class is an array type, the class or package to be matched is the element type. +# Arrays of any number of dimensions are treated the same as the element type. +# For example, a pattern of "!example.Foo", rejects creation of any instance or +# array of example.Foo. # -# Operator: -# <= | < | == | != | >= | > +# If the pattern starts with "!", the status is REJECTED if the remaining pattern +# is matched; otherwise the status is ALLOWED if the pattern matches. +# If the pattern ends with ".**" it matches any class in the package and all subpackages. +# If the pattern ends with ".*" it matches any class in the package. +# If the pattern ends with "*", it matches any class with the pattern as a prefix. +# If the pattern is equal to the class name, it matches. +# Otherwise, the status is UNDECIDED. # -# KeyLength: -# Integer value of the algorithm's key length in bits +#jdk.serialFilter=pattern;pattern + +# +# RMI Registry Serial Filter +# +# The filter pattern uses the same format as jdk.serialFilter. +# This filter can override the builtin filter if additional types need to be +# allowed or rejected from the RMI Registry. # -# Note: This property is currently used by the JDK Reference -# implementation. It is not guaranteed to be examined and used by other -# implementations. +#sun.rmi.registry.registryFilter=pattern;pattern + +# +# RMI Distributed Garbage Collector (DGC) Serial Filter +# +# The filter pattern uses the same format as jdk.serialFilter. +# This filter can override the builtin filter if additional types need to be +# allowed or rejected from the RMI DGC. # -jdk.jar.disabledAlgorithms=MD2, RSA keySize < 1024 +# The builtin DGC filter can approximately be represented as the filter pattern: +# +#sun.rmi.transport.dgcFilter=\ +# java.rmi.server.ObjID;\ +# java.rmi.server.UID;\ +# java.rmi.dgc.VMID;\ +# java.rmi.dgc.Lease;\ +# maxdepth=5;maxarray=10000
--- a/src/share/lib/security/java.security-solaris Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/lib/security/java.security-solaris Mon Jan 23 16:30:43 2017 +0000 @@ -438,13 +438,13 @@ # " DisabledAlgorithm { , DisabledAlgorithm } " # # DisabledAlgorithm: -# AlgorithmName [Constraint] +# AlgorithmName [Constraint] { '&' Constraint } # # AlgorithmName: # (see below) # # Constraint: -# KeySizeConstraint +# KeySizeConstraint, CertConstraint # # KeySizeConstraint: # keySize Operator DecimalInteger @@ -461,6 +461,9 @@ # DecimalDigit: one of # 1 2 3 4 5 6 7 8 9 0 # +# CertConstraint +# jdkCA +# # The "AlgorithmName" is the standard algorithm name of the disabled # algorithm. See "Java Cryptography Architecture Standard Algorithm Name # Documentation" for information about Standard Algorithm Names. Matching @@ -483,6 +486,29 @@ # be disabled. Note that the "KeySizeConstraint" only makes sense to key # algorithms. # +# "CertConstraint" specifies additional constraints for +# certificates that contain algorithms that are restricted: +# +# "jdkCA" prohibits the specified algorithm only if the algorithm is used +# in a certificate chain that terminates at a marked trust anchor in the +# lib/security/cacerts keystore. All other chains are not affected. +# If the jdkCA constraint is not set, then all chains using the +# specified algorithm are restricted. jdkCA may only be used once in +# a DisabledAlgorithm expression. +# Example: To apply this constraint to SHA-1 certificates, include +# the following: "SHA1 jdkCA" +# +# When an algorithm must satisfy more than one constraint, it must be +# delimited by an ampersand '&'. For example, to restrict certificates in a +# chain that terminate at a distribution provided trust anchor and contain +# RSA keys that are less than or equal to 1024 bits, add the following +# constraint: "RSA keySize <= 1024 & jdkCA". +# +# All DisabledAlgorithms expressions are processed in the order defined in the +# property. This requires lower keysize constraints to be specified +# before larger keysize constraints of the same algorithm. For example: +# "RSA keySize < 1024 & jdkCA, RSA keySize < 2048". +# # Note: This property is currently used by Oracle's PKIX implementation. It # is not guaranteed to be examined and used by other implementations. # @@ -490,7 +516,45 @@ # jdk.certpath.disabledAlgorithms=MD2, DSA, RSA keySize < 2048 # # -jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024 +jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024, \ + DSA keySize < 1024, EC keySize < 224 + +# Algorithm restrictions for signed JAR files +# +# In some environments, certain algorithms or key lengths may be undesirable +# for signed JAR validation. For example, "MD2" is generally no longer +# considered to be a secure hash algorithm. This section describes the +# mechanism for disabling algorithms based on algorithm name and/or key length. +# JARs signed with any of the disabled algorithms or key sizes will be treated +# as unsigned. +# +# The syntax of the disabled algorithm string is described as follows: +# DisabledAlgorithms: +# " DisabledAlgorithm { , DisabledAlgorithm } " +# +# DisabledAlgorithm: +# AlgorithmName [Constraint] +# +# AlgorithmName: +# (see below) +# +# Constraint: +# KeySizeConstraint +# +# KeySizeConstraint: +# keySize Operator KeyLength +# +# Operator: +# <= | < | == | != | >= | > +# +# KeyLength: +# Integer value of the algorithm's key length in bits +# +# Note: This property is currently used by the JDK Reference +# implementation. It is not guaranteed to be examined and used by other +# implementations. +# +jdk.jar.disabledAlgorithms=MD2, RSA keySize < 1024 # Algorithm restrictions for Secure Socket Layer/Transport Layer Security # (SSL/TLS) processing @@ -513,12 +577,13 @@ # See the specification of "jdk.certpath.disabledAlgorithms" for the # syntax of the disabled algorithm string. # -# Note: This property is currently used by Oracle's JSSE implementation. +# 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.tls.disabledAlgorithms=MD5, SSLv3, DSA, RSA keySize < 2048 -jdk.tls.disabledAlgorithms=SSLv3, RC4, MD5withRSA, DH keySize < 768 +jdk.tls.disabledAlgorithms=SSLv3, RC4, MD5withRSA, DH keySize < 768, \ + EC keySize < 224 # Legacy algorithms for Secure Socket Layer/Transport Layer Security (SSL/TLS) # processing in JSSE implementation. @@ -532,7 +597,7 @@ # During SSL/TLS security parameters negotiation, legacy algorithms will # not be negotiated unless there are no other candidates. # -# The syntax of the disabled algorithm string is described as this Java +# The syntax of the legacy algorithms string is described as this Java # BNF-style: # LegacyAlgorithms: # " LegacyAlgorithm { , LegacyAlgorithm } " @@ -562,7 +627,7 @@ # See SSL/TLS specifications and "Java Cryptography Architecture Standard # Algorithm Name Documentation" for information about the algorithm names. # -# Note: This property is currently used by Oracle's JSSE implementation. +# Note: This property is currently used by the JDK Reference implementation. # It is not guaranteed to be examined and used by other implementations. # There is no guarantee the property will continue to exist or be of the # same syntax in future releases. @@ -575,7 +640,8 @@ DHE_DSS_EXPORT, DHE_RSA_EXPORT, DH_anon_EXPORT, DH_DSS_EXPORT, \ DH_RSA_EXPORT, RSA_EXPORT, \ DH_anon, ECDH_anon, \ - RC4_128, RC4_40, DES_CBC, DES40_CBC + RC4_128, RC4_40, DES_CBC, DES40_CBC, \ + 3DES_EDE_CBC # The pre-defined default finite field Diffie-Hellman ephemeral (DHE) # parameters for Transport Layer Security (SSL/TLS/DTLS) processing. @@ -634,39 +700,111 @@ # EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE65381 \ # FFFFFFFF FFFFFFFF, 2} -# Algorithm restrictions for signed JAR files +# +# The policy for the XML Signature secure validation mode. The mode is +# enabled by setting the property "org.jcp.xml.dsig.secureValidation" to +# true with the javax.xml.crypto.XMLCryptoContext.setProperty() method, +# or by running the code with a SecurityManager. +# +# Policy: +# Constraint {"," Constraint } +# Constraint: +# AlgConstraint | MaxTransformsConstraint | MaxReferencesConstraint | +# ReferenceUriSchemeConstraint | KeySizeConstraint | OtherConstraint +# AlgConstraint +# "disallowAlg" Uri +# MaxTransformsConstraint: +# "maxTransforms" Integer +# MaxReferencesConstraint: +# "maxReferences" Integer +# ReferenceUriSchemeConstraint: +# "disallowReferenceUriSchemes" String { String } +# KeySizeConstraint: +# "minKeySize" KeyAlg Integer +# OtherConstraint: +# "noDuplicateIds" | "noRetrievalMethodLoops" # -# In some environments, certain algorithms or key lengths may be undesirable -# for signed JAR validation. For example, "MD2" is generally no longer -# considered to be a secure hash algorithm. This section describes the -# mechanism for disabling algorithms based on algorithm name and/or key length. -# JARs signed with any of the disabled algorithms or key sizes will be treated -# as unsigned. +# For AlgConstraint, Uri is the algorithm URI String that is not allowed. +# See the XML Signature Recommendation for more information on algorithm +# URI Identifiers. For KeySizeConstraint, KeyAlg is the standard algorithm +# name of the key type (ex: "RSA"). If the MaxTransformsConstraint, +# MaxReferencesConstraint or KeySizeConstraint (for the same key type) is +# specified more than once, only the last entry is enforced. +# +# Note: This property is currently used by the JDK Reference implementation. It +# is not guaranteed to be examined and used by other implementations. # -# The syntax of the disabled algorithm string is described as follows: -# DisabledAlgorithms: -# " DisabledAlgorithm { , DisabledAlgorithm } " +jdk.xml.dsig.secureValidationPolicy=\ + disallowAlg http://www.w3.org/TR/1999/REC-xslt-19991116,\ + disallowAlg http://www.w3.org/2001/04/xmldsig-more#rsa-md5,\ + disallowAlg http://www.w3.org/2001/04/xmldsig-more#hmac-md5,\ + disallowAlg http://www.w3.org/2001/04/xmldsig-more#md5,\ + maxTransforms 5,\ + maxReferences 30,\ + disallowReferenceUriSchemes file http https,\ + minKeySize RSA 1024,\ + minKeySize DSA 1024,\ + noDuplicateIds,\ + noRetrievalMethodLoops + # -# DisabledAlgorithm: -# AlgorithmName [Constraint] +# Serialization process-wide filter # -# AlgorithmName: -# (see below) +# A filter, if configured, is used by java.io.ObjectInputStream during +# deserialization to check the contents of the stream. +# A filter is configured as a sequence of patterns, each pattern is either +# matched against the name of a class in the stream or defines a limit. +# Patterns are separated by ";" (semicolon). +# Whitespace is significant and is considered part of the pattern. +# +# If a pattern includes a "=", it sets a limit. +# If a limit appears more than once the last value is used. +# Limits are checked before classes regardless of the order in the sequence of patterns. +# If any of the limits are exceeded, the filter status is REJECTED. # -# Constraint: -# KeySizeConstraint +# maxdepth=value - the maximum depth of a graph +# maxrefs=value - the maximum number of internal references +# maxbytes=value - the maximum number of bytes in the input stream +# maxarray=value - the maximum array length allowed # -# KeySizeConstraint: -# keySize Operator KeyLength +# Other patterns, from left to right, match the class or package name as +# returned from Class.getName. +# If the class is an array type, the class or package to be matched is the element type. +# Arrays of any number of dimensions are treated the same as the element type. +# For example, a pattern of "!example.Foo", rejects creation of any instance or +# array of example.Foo. # -# Operator: -# <= | < | == | != | >= | > +# If the pattern starts with "!", the status is REJECTED if the remaining pattern +# is matched; otherwise the status is ALLOWED if the pattern matches. +# If the pattern ends with ".**" it matches any class in the package and all subpackages. +# If the pattern ends with ".*" it matches any class in the package. +# If the pattern ends with "*", it matches any class with the pattern as a prefix. +# If the pattern is equal to the class name, it matches. +# Otherwise, the status is UNDECIDED. # -# KeyLength: -# Integer value of the algorithm's key length in bits +#jdk.serialFilter=pattern;pattern + +# +# RMI Registry Serial Filter +# +# The filter pattern uses the same format as jdk.serialFilter. +# This filter can override the builtin filter if additional types need to be +# allowed or rejected from the RMI Registry. # -# Note: This property is currently used by the JDK Reference -# implementation. It is not guaranteed to be examined and used by other -# implementations. +#sun.rmi.registry.registryFilter=pattern;pattern + +# +# RMI Distributed Garbage Collector (DGC) Serial Filter +# +# The filter pattern uses the same format as jdk.serialFilter. +# This filter can override the builtin filter if additional types need to be +# allowed or rejected from the RMI DGC. # -jdk.jar.disabledAlgorithms=MD2, RSA keySize < 1024 +# The builtin DGC filter can approximately be represented as the filter pattern: +# +#sun.rmi.transport.dgcFilter=\ +# java.rmi.server.ObjID;\ +# java.rmi.server.UID;\ +# java.rmi.dgc.VMID;\ +# java.rmi.dgc.Lease;\ +# maxdepth=5;maxarray=10000
--- a/src/share/lib/security/java.security-windows Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/lib/security/java.security-windows Mon Jan 23 16:30:43 2017 +0000 @@ -439,13 +439,13 @@ # " DisabledAlgorithm { , DisabledAlgorithm } " # # DisabledAlgorithm: -# AlgorithmName [Constraint] +# AlgorithmName [Constraint] { '&' Constraint } # # AlgorithmName: # (see below) # # Constraint: -# KeySizeConstraint +# KeySizeConstraint, CertConstraint # # KeySizeConstraint: # keySize Operator DecimalInteger @@ -462,6 +462,9 @@ # DecimalDigit: one of # 1 2 3 4 5 6 7 8 9 0 # +# CertConstraint +# jdkCA +# # The "AlgorithmName" is the standard algorithm name of the disabled # algorithm. See "Java Cryptography Architecture Standard Algorithm Name # Documentation" for information about Standard Algorithm Names. Matching @@ -484,6 +487,29 @@ # be disabled. Note that the "KeySizeConstraint" only makes sense to key # algorithms. # +# "CertConstraint" specifies additional constraints for +# certificates that contain algorithms that are restricted: +# +# "jdkCA" prohibits the specified algorithm only if the algorithm is used +# in a certificate chain that terminates at a marked trust anchor in the +# lib/security/cacerts keystore. All other chains are not affected. +# If the jdkCA constraint is not set, then all chains using the +# specified algorithm are restricted. jdkCA may only be used once in +# a DisabledAlgorithm expression. +# Example: To apply this constraint to SHA-1 certificates, include +# the following: "SHA1 jdkCA" +# +# When an algorithm must satisfy more than one constraint, it must be +# delimited by an ampersand '&'. For example, to restrict certificates in a +# chain that terminate at a distribution provided trust anchor and contain +# RSA keys that are less than or equal to 1024 bits, add the following +# constraint: "RSA keySize <= 1024 & jdkCA". +# +# All DisabledAlgorithms expressions are processed in the order defined in the +# property. This requires lower keysize constraints to be specified +# before larger keysize constraints of the same algorithm. For example: +# "RSA keySize < 1024 & jdkCA, RSA keySize < 2048". +# # Note: This property is currently used by Oracle's PKIX implementation. It # is not guaranteed to be examined and used by other implementations. # @@ -491,7 +517,45 @@ # jdk.certpath.disabledAlgorithms=MD2, DSA, RSA keySize < 2048 # # -jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024 +jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024, \ + DSA keySize < 1024, EC keySize < 224 + +# Algorithm restrictions for signed JAR files +# +# In some environments, certain algorithms or key lengths may be undesirable +# for signed JAR validation. For example, "MD2" is generally no longer +# considered to be a secure hash algorithm. This section describes the +# mechanism for disabling algorithms based on algorithm name and/or key length. +# JARs signed with any of the disabled algorithms or key sizes will be treated +# as unsigned. +# +# The syntax of the disabled algorithm string is described as follows: +# DisabledAlgorithms: +# " DisabledAlgorithm { , DisabledAlgorithm } " +# +# DisabledAlgorithm: +# AlgorithmName [Constraint] +# +# AlgorithmName: +# (see below) +# +# Constraint: +# KeySizeConstraint +# +# KeySizeConstraint: +# keySize Operator KeyLength +# +# Operator: +# <= | < | == | != | >= | > +# +# KeyLength: +# Integer value of the algorithm's key length in bits +# +# Note: This property is currently used by the JDK Reference +# implementation. It is not guaranteed to be examined and used by other +# implementations. +# +jdk.jar.disabledAlgorithms=MD2, RSA keySize < 1024 # Algorithm restrictions for Secure Socket Layer/Transport Layer Security # (SSL/TLS) processing @@ -514,12 +578,13 @@ # See the specification of "jdk.certpath.disabledAlgorithms" for the # syntax of the disabled algorithm string. # -# Note: This property is currently used by Oracle's JSSE implementation. +# 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.tls.disabledAlgorithms=MD5, SSLv3, DSA, RSA keySize < 2048 -jdk.tls.disabledAlgorithms=SSLv3, RC4, MD5withRSA, DH keySize < 768 +jdk.tls.disabledAlgorithms=SSLv3, RC4, MD5withRSA, DH keySize < 768, \ + EC keySize < 224 # Legacy algorithms for Secure Socket Layer/Transport Layer Security (SSL/TLS) # processing in JSSE implementation. @@ -533,7 +598,7 @@ # During SSL/TLS security parameters negotiation, legacy algorithms will # not be negotiated unless there are no other candidates. # -# The syntax of the disabled algorithm string is described as this Java +# The syntax of the legacy algorithms string is described as this Java # BNF-style: # LegacyAlgorithms: # " LegacyAlgorithm { , LegacyAlgorithm } " @@ -563,7 +628,7 @@ # See SSL/TLS specifications and "Java Cryptography Architecture Standard # Algorithm Name Documentation" for information about the algorithm names. # -# Note: This property is currently used by Oracle's JSSE implementation. +# Note: This property is currently used by the JDK Reference implementation. # It is not guaranteed to be examined and used by other implementations. # There is no guarantee the property will continue to exist or be of the # same syntax in future releases. @@ -576,7 +641,8 @@ DHE_DSS_EXPORT, DHE_RSA_EXPORT, DH_anon_EXPORT, DH_DSS_EXPORT, \ DH_RSA_EXPORT, RSA_EXPORT, \ DH_anon, ECDH_anon, \ - RC4_128, RC4_40, DES_CBC, DES40_CBC + RC4_128, RC4_40, DES_CBC, DES40_CBC, \ + 3DES_EDE_CBC # The pre-defined default finite field Diffie-Hellman ephemeral (DHE) # parameters for Transport Layer Security (SSL/TLS/DTLS) processing. @@ -635,39 +701,111 @@ # EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE65381 \ # FFFFFFFF FFFFFFFF, 2} -# Algorithm restrictions for signed JAR files +# +# The policy for the XML Signature secure validation mode. The mode is +# enabled by setting the property "org.jcp.xml.dsig.secureValidation" to +# true with the javax.xml.crypto.XMLCryptoContext.setProperty() method, +# or by running the code with a SecurityManager. +# +# Policy: +# Constraint {"," Constraint } +# Constraint: +# AlgConstraint | MaxTransformsConstraint | MaxReferencesConstraint | +# ReferenceUriSchemeConstraint | KeySizeConstraint | OtherConstraint +# AlgConstraint +# "disallowAlg" Uri +# MaxTransformsConstraint: +# "maxTransforms" Integer +# MaxReferencesConstraint: +# "maxReferences" Integer +# ReferenceUriSchemeConstraint: +# "disallowReferenceUriSchemes" String { String } +# KeySizeConstraint: +# "minKeySize" KeyAlg Integer +# OtherConstraint: +# "noDuplicateIds" | "noRetrievalMethodLoops" # -# In some environments, certain algorithms or key lengths may be undesirable -# for signed JAR validation. For example, "MD2" is generally no longer -# considered to be a secure hash algorithm. This section describes the -# mechanism for disabling algorithms based on algorithm name and/or key length. -# JARs signed with any of the disabled algorithms or key sizes will be treated -# as unsigned. +# For AlgConstraint, Uri is the algorithm URI String that is not allowed. +# See the XML Signature Recommendation for more information on algorithm +# URI Identifiers. For KeySizeConstraint, KeyAlg is the standard algorithm +# name of the key type (ex: "RSA"). If the MaxTransformsConstraint, +# MaxReferencesConstraint or KeySizeConstraint (for the same key type) is +# specified more than once, only the last entry is enforced. +# +# Note: This property is currently used by the JDK Reference implementation. It +# is not guaranteed to be examined and used by other implementations. # -# The syntax of the disabled algorithm string is described as follows: -# DisabledAlgorithms: -# " DisabledAlgorithm { , DisabledAlgorithm } " +jdk.xml.dsig.secureValidationPolicy=\ + disallowAlg http://www.w3.org/TR/1999/REC-xslt-19991116,\ + disallowAlg http://www.w3.org/2001/04/xmldsig-more#rsa-md5,\ + disallowAlg http://www.w3.org/2001/04/xmldsig-more#hmac-md5,\ + disallowAlg http://www.w3.org/2001/04/xmldsig-more#md5,\ + maxTransforms 5,\ + maxReferences 30,\ + disallowReferenceUriSchemes file http https,\ + minKeySize RSA 1024,\ + minKeySize DSA 1024,\ + noDuplicateIds,\ + noRetrievalMethodLoops + # -# DisabledAlgorithm: -# AlgorithmName [Constraint] +# Serialization process-wide filter # -# AlgorithmName: -# (see below) +# A filter, if configured, is used by java.io.ObjectInputStream during +# deserialization to check the contents of the stream. +# A filter is configured as a sequence of patterns, each pattern is either +# matched against the name of a class in the stream or defines a limit. +# Patterns are separated by ";" (semicolon). +# Whitespace is significant and is considered part of the pattern. +# +# If a pattern includes a "=", it sets a limit. +# If a limit appears more than once the last value is used. +# Limits are checked before classes regardless of the order in the sequence of patterns. +# If any of the limits are exceeded, the filter status is REJECTED. # -# Constraint: -# KeySizeConstraint +# maxdepth=value - the maximum depth of a graph +# maxrefs=value - the maximum number of internal references +# maxbytes=value - the maximum number of bytes in the input stream +# maxarray=value - the maximum array length allowed # -# KeySizeConstraint: -# keySize Operator KeyLength +# Other patterns, from left to right, match the class or package name as +# returned from Class.getName. +# If the class is an array type, the class or package to be matched is the element type. +# Arrays of any number of dimensions are treated the same as the element type. +# For example, a pattern of "!example.Foo", rejects creation of any instance or +# array of example.Foo. # -# Operator: -# <= | < | == | != | >= | > +# If the pattern starts with "!", the status is REJECTED if the remaining pattern +# is matched; otherwise the status is ALLOWED if the pattern matches. +# If the pattern ends with ".**" it matches any class in the package and all subpackages. +# If the pattern ends with ".*" it matches any class in the package. +# If the pattern ends with "*", it matches any class with the pattern as a prefix. +# If the pattern is equal to the class name, it matches. +# Otherwise, the status is UNDECIDED. # -# KeyLength: -# Integer value of the algorithm's key length in bits +#jdk.serialFilter=pattern;pattern + +# +# RMI Registry Serial Filter +# +# The filter pattern uses the same format as jdk.serialFilter. +# This filter can override the builtin filter if additional types need to be +# allowed or rejected from the RMI Registry. # -# Note: This property is currently used by the JDK Reference -# implementation. It is not guaranteed to be examined and used by other -# implementations. +#sun.rmi.registry.registryFilter=pattern;pattern + +# +# RMI Distributed Garbage Collector (DGC) Serial Filter +# +# The filter pattern uses the same format as jdk.serialFilter. +# This filter can override the builtin filter if additional types need to be +# allowed or rejected from the RMI DGC. # -jdk.jar.disabledAlgorithms=MD2, RSA keySize < 1024 +# The builtin DGC filter can approximately be represented as the filter pattern: +# +#sun.rmi.transport.dgcFilter=\ +# java.rmi.server.ObjID;\ +# java.rmi.server.UID;\ +# java.rmi.dgc.VMID;\ +# java.rmi.dgc.Lease;\ +# maxdepth=5;maxarray=10000
--- a/src/share/native/sun/security/ec/impl/ec.c Fri Jan 13 17:09:28 2017 +0000 +++ b/src/share/native/sun/security/ec/impl/ec.c Mon Jan 23 16:30:43 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. * Use is subject to license terms. * * This library is free software; you can redistribute it and/or @@ -34,7 +34,7 @@ * Dr Vipul Gupta <vipul.gupta@sun.com> and * Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories * - * Last Modified Date from the Original Code: April 2015 + * Last Modified Date from the Original Code: November 2016 *********************************************************************** */ #include "mplogic.h" @@ -714,6 +714,16 @@ } /* + * Using an equivalent exponent of fixed length (same as n or 1 bit less + * than n) to keep the kG timing relatively constant. + * + * Note that this is an extra step on top of the approach defined in + * ANSI X9.62 so as to make a fixed length K. + */ + CHECK_MPI_OK( mp_add(&k, &n, &k) ); + CHECK_MPI_OK( mp_div_2(&k, &k) ); + + /* ** ANSI X9.62, Section 5.3.2, Step 2 ** ** Compute kG
--- a/src/solaris/native/java/net/SocketOutputStream.c Fri Jan 13 17:09:28 2017 +0000 +++ b/src/solaris/native/java/net/SocketOutputStream.c Mon Jan 23 16:30:43 2017 +0000 @@ -103,31 +103,35 @@ int llen = chunkLen; (*env)->GetByteArrayRegion(env, data, off, chunkLen, (jbyte *)bufP); - while(llen > 0) { - int n = NET_Send(fd, bufP + loff, llen, 0); - if (n > 0) { - llen -= n; - loff += n; - continue; + if ((*env)->ExceptionCheck(env)) { + break; + } else { + while(llen > 0) { + int n = NET_Send(fd, bufP + loff, llen, 0); + if (n > 0) { + llen -= n; + loff += n; + continue; + } + if (n == JVM_IO_INTR) { + JNU_ThrowByName(env, "java/io/InterruptedIOException", 0); + } else { + if (errno == ECONNRESET) { + JNU_ThrowByName(env, "sun/net/ConnectionResetException", + "Connection reset"); + } else { + NET_ThrowByNameWithLastError(env, "java/net/SocketException", + "Write failed"); + } + } + if (bufP != BUF) { + free(bufP); + } + return; } - if (n == JVM_IO_INTR) { - JNU_ThrowByName(env, "java/io/InterruptedIOException", 0); - } else { - if (errno == ECONNRESET) { - JNU_ThrowByName(env, "sun/net/ConnectionResetException", - "Connection reset"); - } else { - NET_ThrowByNameWithLastError(env, "java/net/SocketException", - "Write failed"); - } - } - if (bufP != BUF) { - free(bufP); - } - return; + len -= chunkLen; + off += chunkLen; } - len -= chunkLen; - off += chunkLen; } if (bufP != BUF) {
--- a/src/windows/native/java/net/Inet4AddressImpl.c Fri Jan 13 17:09:28 2017 +0000 +++ b/src/windows/native/java/net/Inet4AddressImpl.c Mon Jan 23 16:30:43 2017 +0000 @@ -33,6 +33,7 @@ #include <process.h> #include <iphlpapi.h> #include <icmpapi.h> +#include <WinError.h> #include "java_net_InetAddress.h" #include "java_net_Inet4AddressImpl.h" @@ -481,7 +482,15 @@ DWORD ReplySize = 0; jboolean ret = JNI_FALSE; - ReplySize = sizeof(ICMP_ECHO_REPLY) + sizeof(SendData); + // https://msdn.microsoft.com/en-us/library/windows/desktop/aa366051%28v=vs.85%29.aspx + ReplySize = sizeof(ICMP_ECHO_REPLY) // The buffer should be large enough + // to hold at least one ICMP_ECHO_REPLY + // structure + + sizeof(SendData) // plus RequestSize bytes of data. + + 8; // This buffer should also be large enough + // to also hold 8 more bytes of data + // (the size of an ICMP error message) + ReplyBuffer = (VOID*) malloc(ReplySize); if (ReplyBuffer == NULL) { IcmpCloseHandle(hIcmpFile); @@ -517,10 +526,45 @@ (timeout < 1000) ? 1000 : timeout); // DWORD Timeout } - if (dwRetVal != 0) { + if (dwRetVal == 0) { // if the call failed + TCHAR *buf; + DWORD err = WSAGetLastError(); + switch (err) { + case ERROR_NO_NETWORK: + case ERROR_NETWORK_UNREACHABLE: + case ERROR_HOST_UNREACHABLE: + case ERROR_PROTOCOL_UNREACHABLE: + case ERROR_PORT_UNREACHABLE: + case ERROR_REQUEST_ABORTED: + case ERROR_INCORRECT_ADDRESS: + case ERROR_HOST_DOWN: + case WSAEHOSTUNREACH: /* Host Unreachable */ + case WSAENETUNREACH: /* Network Unreachable */ + case WSAENETDOWN: /* Network is down */ + case WSAEPFNOSUPPORT: /* Protocol Family unsupported */ + case IP_REQ_TIMED_OUT: + break; + default: + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, + NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR)&buf, 0, NULL); + NET_ThrowNew(env, err, buf); + LocalFree(buf); + break; + } + } else { PICMP_ECHO_REPLY pEchoReply = (PICMP_ECHO_REPLY)ReplyBuffer; - if ((int)pEchoReply->RoundTripTime <= timeout) + + // This is to take into account the undocumented minimum + // timeout mentioned in the IcmpSendEcho call above. + // We perform an extra check to make sure that our + // roundtrip time was less than our desired timeout + // for cases where that timeout is < 1000ms. + if (pEchoReply->Status == IP_SUCCESS + && (int)pEchoReply->RoundTripTime <= timeout) + { ret = JNI_TRUE; + } } free(ReplyBuffer);
--- a/src/windows/native/java/net/SocketOutputStream.c Fri Jan 13 17:09:28 2017 +0000 +++ b/src/windows/native/java/net/SocketOutputStream.c Mon Jan 23 16:30:43 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -100,66 +100,69 @@ int retry = 0; (*env)->GetByteArrayRegion(env, data, off, chunkLen, (jbyte *)bufP); - - while(llen > 0) { - int n = send(fd, bufP + loff, llen, 0); - if (n > 0) { - llen -= n; - loff += n; - continue; - } - - /* - * Due to a bug in Windows Sockets (observed on NT and Windows - * 2000) it may be necessary to retry the send. The issue is that - * on blocking sockets send/WSASend is supposed to block if there - * is insufficient buffer space available. If there are a large - * number of threads blocked on write due to congestion then it's - * possile to hit the NT/2000 bug whereby send returns WSAENOBUFS. - * The workaround we use is to retry the send. If we have a - * large buffer to send (>2k) then we retry with a maximum of - * 2k buffer. If we hit the issue with <=2k buffer then we backoff - * for 1 second and retry again. We repeat this up to a reasonable - * limit before bailing out and throwing an exception. In load - * conditions we've observed that the send will succeed after 2-3 - * attempts but this depends on network buffers associated with - * other sockets draining. - */ - if (WSAGetLastError() == WSAENOBUFS) { - if (llen > MAX_BUFFER_LEN) { - buflen = MAX_BUFFER_LEN; - chunkLen = MAX_BUFFER_LEN; - llen = MAX_BUFFER_LEN; + if ((*env)->ExceptionCheck(env)) { + break; + } else { + while(llen > 0) { + int n = send(fd, bufP + loff, llen, 0); + if (n > 0) { + llen -= n; + loff += n; continue; } - if (retry >= 30) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", - "No buffer space available - exhausted attempts to queue buffer"); - if (bufP != BUF) { - free(bufP); - } - return; - } - Sleep(1000); - retry++; - continue; - } - /* - * Send failed - can be caused by close or write error. - */ - if (WSAGetLastError() == WSAENOTSOCK) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed"); - } else { - NET_ThrowCurrent(env, "socket write error"); + /* + * Due to a bug in Windows Sockets (observed on NT and Windows + * 2000) it may be necessary to retry the send. The issue is that + * on blocking sockets send/WSASend is supposed to block if there + * is insufficient buffer space available. If there are a large + * number of threads blocked on write due to congestion then it's + * possile to hit the NT/2000 bug whereby send returns WSAENOBUFS. + * The workaround we use is to retry the send. If we have a + * large buffer to send (>2k) then we retry with a maximum of + * 2k buffer. If we hit the issue with <=2k buffer then we backoff + * for 1 second and retry again. We repeat this up to a reasonable + * limit before bailing out and throwing an exception. In load + * conditions we've observed that the send will succeed after 2-3 + * attempts but this depends on network buffers associated with + * other sockets draining. + */ + if (WSAGetLastError() == WSAENOBUFS) { + if (llen > MAX_BUFFER_LEN) { + buflen = MAX_BUFFER_LEN; + chunkLen = MAX_BUFFER_LEN; + llen = MAX_BUFFER_LEN; + continue; + } + if (retry >= 30) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + "No buffer space available - exhausted attempts to queue buffer"); + if (bufP != BUF) { + free(bufP); + } + return; + } + Sleep(1000); + retry++; + continue; + } + + /* + * Send failed - can be caused by close or write error. + */ + if (WSAGetLastError() == WSAENOTSOCK) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed"); + } else { + NET_ThrowCurrent(env, "socket write error"); + } + if (bufP != BUF) { + free(bufP); + } + return; } - if (bufP != BUF) { - free(bufP); - } - return; + len -= chunkLen; + off += chunkLen; } - len -= chunkLen; - off += chunkLen; } if (bufP != BUF) {
--- a/src/windows/native/sun/security/mscapi/security.cpp Fri Jan 13 17:09:28 2017 +0000 +++ b/src/windows/native/sun/security/mscapi/security.cpp Mon Jan 23 16:30:43 2017 +0000 @@ -352,38 +352,50 @@ BOOL bHasNoPrivateKey = FALSE; DWORD dwPublicKeyLength = 0; - if (::CryptAcquireCertificatePrivateKey(pCertContext, NULL, NULL, - &hCryptProv, &dwKeySpec, &bCallerFreeProv) == FALSE) + // First, probe it silently + if (::CryptAcquireCertificatePrivateKey(pCertContext, CRYPT_ACQUIRE_SILENT_FLAG, NULL, + &hCryptProv, &dwKeySpec, &bCallerFreeProv) == FALSE + && GetLastError() != NTE_SILENT_CONTEXT) { bHasNoPrivateKey = TRUE; - - } else { - // Private key is available - - BOOL bGetUserKey = ::CryptGetUserKey(hCryptProv, dwKeySpec, &hUserKey); - - // Skip certificate if cannot find private key - if (bGetUserKey == FALSE) - { - if (bCallerFreeProv) - ::CryptReleaseContext(hCryptProv, NULL); - - continue; + } + else + { + if (bCallerFreeProv == TRUE) { + ::CryptReleaseContext(hCryptProv, NULL); + bCallerFreeProv = FALSE; } - // Set cipher mode to ECB - DWORD dwCipherMode = CRYPT_MODE_ECB; - ::CryptSetKeyParam(hUserKey, KP_MODE, (BYTE*)&dwCipherMode, NULL); - + // Second, acquire the key normally (not silently) + if (::CryptAcquireCertificatePrivateKey(pCertContext, 0, NULL, + &hCryptProv, &dwKeySpec, &bCallerFreeProv) == FALSE) + { + bHasNoPrivateKey = TRUE; + } + else + { + // Private key is available + BOOL bGetUserKey = ::CryptGetUserKey(hCryptProv, dwKeySpec, &hUserKey); - // If the private key is present in smart card, we may not be able to - // determine the key length by using the private key handle. However, - // since public/private key pairs must have the same length, we could - // determine the key length of the private key by using the public key - // in the certificate. - dwPublicKeyLength = ::CertGetPublicKeyLength(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, - &(pCertContext->pCertInfo->SubjectPublicKeyInfo)); + // Skip certificate if cannot find private key + if (bGetUserKey == FALSE) { + if (bCallerFreeProv) + ::CryptReleaseContext(hCryptProv, NULL); + continue; + } + // Set cipher mode to ECB + DWORD dwCipherMode = CRYPT_MODE_ECB; + ::CryptSetKeyParam(hUserKey, KP_MODE, (BYTE*)&dwCipherMode, NULL); + + // If the private key is present in smart card, we may not be able to + // determine the key length by using the private key handle. However, + // since public/private key pairs must have the same length, we could + // determine the key length of the private key by using the public key + // in the certificate. + dwPublicKeyLength = ::CertGetPublicKeyLength(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, + &(pCertContext->pCertInfo->SubjectPublicKeyInfo)); + } } PCCERT_CHAIN_CONTEXT pCertChainContext = NULL; @@ -392,8 +404,7 @@ // if (GetCertificateChain(OID_EKU_ANY, pCertContext, &pCertChainContext)) { - - for (unsigned int i=0; i < pCertChainContext->cChain; i++) + for (DWORD i = 0; i < pCertChainContext->cChain; i++) { // Found cert chain PCERT_SIMPLE_CHAIN rgpChain = @@ -443,6 +454,7 @@ // cert collection env->CallVoidMethod(obj, mGenCert, byteArray, jArrayList); } + if (bHasNoPrivateKey) { // Generate certificate chain and store into cert chain @@ -1361,43 +1373,57 @@ HCRYPTPROV hCryptProv = NULL; HCRYPTKEY hKey = NULL; DWORD dwKeySpec; + BOOL bCallerFreeProv = FALSE; + BOOL bRes; __try { if (usePrivateKey == JNI_TRUE) { // Locate the key container for the certificate's private key - if (!(::CryptAcquireCertificatePrivateKey( - (PCCERT_CONTEXT) pCertContext, 0, NULL, &hCryptProv, - &dwKeySpec, NULL))) { + + // First, probe it silently + bRes = ::CryptAcquireCertificatePrivateKey( + (PCCERT_CONTEXT) pCertContext, CRYPT_ACQUIRE_SILENT_FLAG, + NULL, &hCryptProv, &dwKeySpec, &bCallerFreeProv); + if (bRes == FALSE && GetLastError() != NTE_SILENT_CONTEXT) + { + ThrowException(env, KEYSTORE_EXCEPTION, GetLastError()); + __leave; + } + + if (bCallerFreeProv == TRUE) { + ::CryptReleaseContext(hCryptProv, NULL); + bCallerFreeProv = FALSE; + } + + // Now, do it normally (not silently) + if (::CryptAcquireCertificatePrivateKey( + (PCCERT_CONTEXT) pCertContext, 0, NULL, &hCryptProv, + &dwKeySpec, &bCallerFreeProv) == FALSE) + { ThrowException(env, KEYSTORE_EXCEPTION, GetLastError()); __leave; } // Get a handle to the private key - if (!(::CryptGetUserKey(hCryptProv, dwKeySpec, &hKey))) { + if (::CryptGetUserKey(hCryptProv, dwKeySpec, &hKey) == FALSE) { ThrowException(env, KEY_EXCEPTION, GetLastError()); __leave; } - - } else { // use public key + } + else // use public key + { + bCallerFreeProv = TRUE; // Acquire a CSP context. - if(::CryptAcquireContext( - &hCryptProv, - "J2SE", - NULL, - PROV_RSA_FULL, - 0) == FALSE) + if (::CryptAcquireContext(&hCryptProv, "J2SE", NULL, + PROV_RSA_FULL, 0) == FALSE) { // If CSP context hasn't been created, create one. // - if (::CryptAcquireContext( - &hCryptProv, - "J2SE", - NULL, - PROV_RSA_FULL, - CRYPT_NEWKEYSET) == FALSE) + if (::CryptAcquireContext(&hCryptProv, "J2SE", NULL, + PROV_RSA_FULL, CRYPT_NEWKEYSET) == FALSE) { ThrowException(env, KEYSTORE_EXCEPTION, GetLastError()); __leave; @@ -1405,10 +1431,10 @@ } // Import the certificate's public key into the key container - if (!(::CryptImportPublicKeyInfo(hCryptProv, X509_ASN_ENCODING, - &(((PCCERT_CONTEXT) pCertContext)->pCertInfo->SubjectPublicKeyInfo), - &hKey))) { - + if (::CryptImportPublicKeyInfo(hCryptProv, X509_ASN_ENCODING, + &(((PCCERT_CONTEXT) pCertContext)->pCertInfo->SubjectPublicKeyInfo), + &hKey) == FALSE) + { ThrowException(env, KEY_EXCEPTION, GetLastError()); __leave; } @@ -1419,7 +1445,7 @@ //-------------------------------------------------------------------- // Clean up. - if (hCryptProv) + if (bCallerFreeProv == TRUE && hCryptProv != NULL) ::CryptReleaseContext(hCryptProv, 0); }
--- a/src/windows/native/sun/windows/awt_Component.cpp Fri Jan 13 17:09:28 2017 +0000 +++ b/src/windows/native/sun/windows/awt_Component.cpp Mon Jan 23 16:30:43 2017 +0000 @@ -98,7 +98,6 @@ HWND AwtComponent::sm_focusOwner = NULL; HWND AwtComponent::sm_focusedWindow = NULL; BOOL AwtComponent::sm_bMenuLoop = FALSE; -AwtComponent* AwtComponent::sm_getComponentCache = NULL; BOOL AwtComponent::sm_inSynthesizeFocus = FALSE; /************************************************************************/ @@ -272,10 +271,6 @@ * handle. */ DestroyHWnd(); - - if (sm_getComponentCache == this) { - sm_getComponentCache = NULL; - } } void AwtComponent::Dispose() @@ -348,9 +343,6 @@ if (hWnd == AwtToolkit::GetInstance().GetHWnd()) { return NULL; } - if (sm_getComponentCache && sm_getComponentCache->GetHWnd() == hWnd) { - return sm_getComponentCache; - } // check that it's an AWT component from the same toolkit as the caller if (::IsWindow(hWnd) && @@ -358,7 +350,7 @@ { DASSERT(WmAwtIsComponent != 0); if (::SendMessage(hWnd, WmAwtIsComponent, 0, 0L)) { - return sm_getComponentCache = GetComponentImpl(hWnd); + return GetComponentImpl(hWnd); } } return NULL;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/io/Serializable/serialFilter/CheckInputOrderTest.java Mon Jan 23 16:30:43 2017 +0000 @@ -0,0 +1,94 @@ +/* + * Copyright (c) 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.ByteArrayInputStream; +import java.io.InvalidClassException; +import java.io.ObjectInputStream; +import java.io.Serializable; +import java.security.Security; + +import sun.misc.ObjectInputFilter; + +import org.testng.annotations.BeforeClass; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import static org.testng.Assert.assertTrue; +import static org.testng.Assert.assertFalse; + +/* @test + * @build CheckInputOrderTest SerialFilterTest + * @run testng/othervm CheckInputOrderTest + * + * @summary Test that when both global filter and specific filter are set, + * global filter will not affect specific filter. + */ + +public class CheckInputOrderTest implements Serializable { + private static final long serialVersionUID = 12345678901L; + + @DataProvider(name="Patterns") + Object[][] patterns() { + return new Object[][] { + new Object[] { SerialFilterTest.genTestObject("maxarray=1", true), "java.**;java.lang.*;java.lang.Long;maxarray=0", false }, + new Object[] { SerialFilterTest.genTestObject("maxarray=1", true), "java.**;java.lang.*;java.lang.Long", true }, + new Object[] { Long.MAX_VALUE, "java.**;java.lang.*;java.lang.Long;maxdepth=0", false }, + new Object[] { Long.MAX_VALUE, "java.**;java.lang.*;java.lang.Long;maxbytes=0", false }, + new Object[] { Long.MAX_VALUE, "java.**;java.lang.*;java.lang.Long;maxrefs=0", false }, + + new Object[] { Long.MAX_VALUE, "java.**;java.lang.*;java.lang.Long", true }, + + new Object[] { Long.MAX_VALUE, "!java.**;java.lang.*;java.lang.Long", false }, + new Object[] { Long.MAX_VALUE, "java.**;!java.lang.*;java.lang.Long", true }, + + new Object[] { Long.MAX_VALUE, "!java.lang.*;java.**;java.lang.Long", false }, + new Object[] { Long.MAX_VALUE, "java.lang.*;!java.**;java.lang.Long", true }, + + new Object[] { Long.MAX_VALUE, "!java.lang.Long;java.**;java.lang.*", false }, + new Object[] { Long.MAX_VALUE, "java.lang.Long;java.**;!java.lang.*", true }, + + new Object[] { Long.MAX_VALUE, "java.lang.Long;!java.**;java.lang.*", false }, + new Object[] { Long.MAX_VALUE, "java.lang.Long;java.lang.Number;!java.**;java.lang.*", true }, + }; + } + + /** + * Test: + * "global filter reject" + "specific ObjectInputStream filter is empty" => should reject + * "global filter reject" + "specific ObjectInputStream filter allow" => should allow + */ + @Test(dataProvider="Patterns") + public void testRejectedInGlobal(Object toDeserialized, String pattern, boolean allowed) throws Exception { + byte[] bytes = SerialFilterTest.writeObjects(toDeserialized); + ObjectInputFilter filter = ObjectInputFilter.Config.createFilter(pattern); + + try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes); + ObjectInputStream ois = new ObjectInputStream(bais)) { + ObjectInputFilter.Config.setObjectInputFilter(ois, filter); + Object o = ois.readObject(); + assertTrue(allowed, "filter should have thrown an exception"); + } catch (InvalidClassException ice) { + assertFalse(allowed, "filter should have thrown an exception"); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/io/Serializable/serialFilter/FilterWithSecurityManagerTest.java Mon Jan 23 16:30:43 2017 +0000 @@ -0,0 +1,101 @@ +/* + * Copyright (c) 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.ByteArrayInputStream; +import java.io.ObjectInputStream; +import java.security.AccessControlException; + +import sun.misc.ObjectInputFilter; + +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertTrue; + +/* @test + * @build FilterWithSecurityManagerTest SerialFilterTest + * @run testng/othervm FilterWithSecurityManagerTest + * @run testng/othervm/policy=security.policy.without.globalFilter + * -Djava.security.manager=default FilterWithSecurityManagerTest + * @run testng/othervm/policy=security.policy + * -Djava.security.manager=default + * -Djdk.serialFilter=java.lang.Integer FilterWithSecurityManagerTest + * + * @summary Test that setting specific filter is checked by security manager, + * setting process-wide filter is checked by security manager. + */ + +@Test +public class FilterWithSecurityManagerTest { + + byte[] bytes; + boolean setSecurityManager; + ObjectInputFilter filter; + + @BeforeClass + public void setup() throws Exception { + setSecurityManager = System.getSecurityManager() != null; + Object toDeserialized = Long.MAX_VALUE; + bytes = SerialFilterTest.writeObjects(toDeserialized); + filter = ObjectInputFilter.Config.createFilter("java.lang.Long"); + } + + /** + * Test that setting process-wide filter is checked by security manager. + */ + @Test + public void testGlobalFilter() throws Exception { + if (ObjectInputFilter.Config.getSerialFilter() == null) { + return; + } + try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes); + ObjectInputStream ois = new ObjectInputStream(bais)) { + ObjectInputFilter.Config.setSerialFilter(filter); + assertFalse(setSecurityManager, + "When SecurityManager exists, without " + + "java.security.SerializablePermission(serialFilter) Exception should be thrown"); + Object o = ois.readObject(); + } catch (AccessControlException ex) { + assertTrue(setSecurityManager); + assertTrue(ex.getMessage().contains("java.io.SerializablePermission")); + assertTrue(ex.getMessage().contains("serialFilter")); + } + } + + /** + * Test that setting specific filter is checked by security manager. + */ + @Test(dependsOnMethods = { "testGlobalFilter" }) + public void testSpecificFilter() throws Exception { + try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes); + ObjectInputStream ois = new ObjectInputStream(bais)) { + ObjectInputFilter.Config.setObjectInputFilter(ois, filter); + Object o = ois.readObject(); + } catch (AccessControlException ex) { + assertTrue(setSecurityManager); + assertTrue(ex.getMessage().contains("java.io.SerializablePermission")); + assertTrue(ex.getMessage().contains("serialFilter")); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/io/Serializable/serialFilter/GlobalFilterTest.java Mon Jan 23 16:30:43 2017 +0000 @@ -0,0 +1,219 @@ +/* + * Copyright (c) 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 static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertSame; +import static org.testng.Assert.assertTrue; + +import java.io.ByteArrayInputStream; +import java.io.EOFException; +import java.io.IOException; +import java.io.InvalidClassException; +import java.io.ObjectInputStream; + +import java.io.SerializablePermission; +import java.security.Security; +import java.util.Objects; + +import org.testng.Assert; +import org.testng.annotations.Test; +import org.testng.annotations.DataProvider; + +import sun.misc.ObjectInputFilter; + +/* @test + * @build GlobalFilterTest SerialFilterTest + * @run testng/othervm GlobalFilterTest + * @run testng/othervm -Djdk.serialFilter=java.** GlobalFilterTest + * @run testng/othervm/policy=security.policy GlobalFilterTest + * @run testng/othervm/policy=security.policy + * -Djava.security.properties=${test.src}/java.security-extra1 + * -Djava.security.debug=properties GlobalFilterTest + * + * @summary Test Global Filters + */ +@Test +public class GlobalFilterTest { + + /** + * DataProvider of patterns and objects derived from the configured process-wide filter. + * @return Array of arrays of pattern, object, allowed boolean, and API factory + */ + @DataProvider(name="globalPatternElements") + Object[][] globalPatternElements() { + String globalFilter = + System.getProperty("jdk.serialFilter", + Security.getProperty("jdk.serialFilter")); + if (globalFilter == null) { + return new Object[0][]; + } + + String[] patterns = globalFilter.split(";"); + Object[][] objects = new Object[patterns.length][]; + + for (int i = 0; i < patterns.length; i++) { + Object o; + boolean allowed; + String pattern = patterns[i].trim(); + if (pattern.contains("=")) { + allowed = false; + o = SerialFilterTest.genTestObject(pattern, false); + } else { + allowed = !pattern.startsWith("!"); + o = (allowed) + ? SerialFilterTest.genTestObject(pattern, true) + : SerialFilterTest.genTestObject(pattern.substring(1), false); + + Assert.assertNotNull(o, "fail generation failed"); + } + objects[i] = new Object[3]; + objects[i][0] = pattern; + objects[i][1] = allowed; + objects[i][2] = o; + } + return objects; + } + + /** + * Test that the process-wide filter is set when the properties are set + * and has the toString matching the configured pattern. + */ + @Test() + static void globalFilter() { + String pattern = + System.getProperty("jdk.serialFilter", + Security.getProperty("jdk.serialFilter")); + ObjectInputFilter filter = ObjectInputFilter.Config.getSerialFilter(); + System.out.printf("global pattern: %s, filter: %s%n", pattern, filter); + Assert.assertEquals(pattern, Objects.toString(filter, null), + "process-wide filter pattern does not match"); + } + + /** + * If the Global filter is already set, it should always refuse to be + * set again. + * If there is a security manager, setting the serialFilter should fail + * without the appropriate permission. + * If there is no security manager then setting it should work. + */ + @Test() + static void setGlobalFilter() { + SecurityManager sm = System.getSecurityManager(); + ObjectInputFilter filter = new SerialFilterTest.Validator(); + ObjectInputFilter global = ObjectInputFilter.Config.getSerialFilter(); + if (global != null) { + // once set, can never be re-set + try { + ObjectInputFilter.Config.setSerialFilter(filter); + Assert.fail("set only once process-wide filter"); + } catch (IllegalStateException ise) { + if (sm != null) { + Assert.fail("wrong exception when security manager is set", ise); + } + } catch (SecurityException se) { + if (sm == null) { + Assert.fail("wrong exception when security manager is not set", se); + } + } + } else { + if (sm == null) { + // no security manager + try { + ObjectInputFilter.Config.setSerialFilter(filter); + // Note once set, it can not be reset; so other tests + System.out.printf("Global Filter set to Validator%n"); + } catch (SecurityException se) { + Assert.fail("setGlobalFilter should not get SecurityException", se); + } + try { + // Try to set it again, expecting it to throw + ObjectInputFilter.Config.setSerialFilter(filter); + Assert.fail("set only once process-wide filter"); + } catch (IllegalStateException ise) { + // Normal case + } + } else { + // Security manager + SecurityException expectSE = null; + try { + sm.checkPermission(new SerializablePermission("serialFilter")); + } catch (SecurityException se1) { + expectSE = se1; + } + SecurityException actualSE = null; + try { + ObjectInputFilter.Config.setSerialFilter(filter); + } catch (SecurityException se2) { + actualSE = se2; + } + if (expectSE == null | actualSE == null) { + Assert.assertEquals(expectSE, actualSE, "SecurityException"); + } else { + Assert.assertEquals(expectSE.getClass(), actualSE.getClass(), + "SecurityException class"); + } + } + } + } + + /** + * For each pattern in the process-wide filter test a generated object + * against the default process-wide filter. + * + * @param pattern a pattern extracted from the configured global pattern + */ + @Test(dataProvider = "globalPatternElements") + static void globalFilterElements(String pattern, boolean allowed,Object obj) { + testGlobalPattern(pattern, obj, allowed); + } + + /** + * Serialize and deserialize an object using the default process-wide filter + * and check allowed or reject. + * + * @param pattern the pattern + * @param object the test object + * @param allowed the expected result from ObjectInputStream (exception or not) + */ + static void testGlobalPattern(String pattern, Object object, boolean allowed) { + try { +// System.out.printf("global %s pattern: %s, obj: %s%n", (allowed ? "allowed" : "not allowed"), pattern, object); + byte[] bytes = SerialFilterTest.writeObjects(object); + try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes); + ObjectInputStream ois = new ObjectInputStream(bais)) { + Object o = ois.readObject(); + } catch (EOFException eof) { + // normal completion + } catch (ClassNotFoundException cnf) { + Assert.fail("Deserializing", cnf); + } + Assert.assertTrue(allowed, "filter should have thrown an exception"); + } catch (IllegalArgumentException iae) { + Assert.fail("bad format pattern", iae); + } catch (InvalidClassException ice) { + Assert.assertFalse(allowed, "filter should not have thrown an exception: " + ice); + } catch (IOException ioe) { + Assert.fail("Unexpected IOException", ioe); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/io/Serializable/serialFilter/MixedFiltersTest.java Mon Jan 23 16:30:43 2017 +0000 @@ -0,0 +1,138 @@ +/* + * Copyright (c) 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.ByteArrayInputStream; +import java.io.InvalidClassException; +import java.io.ObjectInputStream; +import java.io.Serializable; +import java.security.Security; + +import sun.misc.ObjectInputFilter; + +import org.testng.annotations.BeforeClass; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import static org.testng.Assert.assertTrue; +import static org.testng.Assert.fail; + +/* @test + * @build MixedFiltersTest SerialFilterTest + * @run testng/othervm -Djdk.serialFilter=!java.**;!java.lang.Long;maxdepth=5;maxarray=5;maxbytes=90;maxrefs=5 MixedFiltersTest + * @run testng/othervm -Djdk.serialFilter=java.**;java.lang.Long;maxdepth=1000;maxarray=1000;maxbytes=1000;maxrefs=1000 MixedFiltersTest + * + * @summary Test that when both global filter and specific filter are set, + * global filter will not affect specific filter. + */ + +public class MixedFiltersTest implements Serializable { + + private static final long serialVersionUID = 1234567890L; + + + boolean globalRejected; + + @BeforeClass + public void setup() { + String pattern = System.getProperty("jdk.serialFilter", + Security.getProperty("jdk.serialFilter")); + globalRejected = pattern.startsWith("!"); + } + + @DataProvider(name="RejectedInGlobal") + Object[][] rejectedInGlobal() { + if (!globalRejected) { + return new Object[0][]; + } + return new Object[][] { + new Object[] { Long.MAX_VALUE, "java.**" }, + new Object[] { Long.MAX_VALUE, "java.lang.Long" }, + new Object[] { SerialFilterTest.genTestObject("java.lang.**", true), "java.lang.**" }, + new Object[] { SerialFilterTest.genTestObject("maxdepth=10", true), "maxdepth=100" }, + new Object[] { SerialFilterTest.genTestObject("maxarray=10", true), "maxarray=100" }, + new Object[] { SerialFilterTest.genTestObject("maxbytes=100", true), "maxbytes=1000" }, + new Object[] { SerialFilterTest.genTestObject("maxrefs=10", true), "maxrefs=100" }, + }; + } + + /** + * Test: + * "global filter reject" + "specific ObjectInputStream filter is empty" => should reject + * "global filter reject" + "specific ObjectInputStream filter allow" => should allow + */ + @Test(dataProvider="RejectedInGlobal") + public void testRejectedInGlobal(Object toDeserialized, String pattern) throws Exception { + byte[] bytes = SerialFilterTest.writeObjects(toDeserialized); + try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes); + ObjectInputStream ois = new ObjectInputStream(bais)) { + Object o = ois.readObject(); + fail("filter should have thrown an exception"); + } catch (InvalidClassException expected) { } + + ObjectInputFilter filter = ObjectInputFilter.Config.createFilter(pattern); + try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes); + ObjectInputStream ois = new ObjectInputStream(bais)) { + ObjectInputFilter.Config.setObjectInputFilter(ois, filter); + Object o = ois.readObject(); + } + } + + @DataProvider(name="AllowedInGlobal") + Object[][] allowedInGlobal() { + if (globalRejected) { + return new Object[0][]; + } + + return new Object[][] { + new Object[] { Long.MAX_VALUE, "!java.**" }, + new Object[] { Long.MAX_VALUE, "!java.lang.Long" }, + new Object[] { SerialFilterTest.genTestObject("java.lang.**", true), "!java.lang.**" }, + new Object[] { SerialFilterTest.genTestObject("maxdepth=10", true), "maxdepth=5" }, + new Object[] { SerialFilterTest.genTestObject("maxarray=10", true), "maxarray=5" }, + new Object[] { SerialFilterTest.genTestObject("maxbytes=100", true), "maxbytes=5" }, + new Object[] { SerialFilterTest.genTestObject("maxrefs=10", true), "maxrefs=5" }, + }; + } + + /** + * Test: + * "global filter allow" + "specific ObjectInputStream filter is empty" => should allow + * "global filter allow" + "specific ObjectInputStream filter reject" => should reject + */ + @Test(dataProvider="AllowedInGlobal") + public void testAllowedInGlobal(Object toDeserialized, String pattern) throws Exception { + byte[] bytes = SerialFilterTest.writeObjects(toDeserialized); + try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes); + ObjectInputStream ois = new ObjectInputStream(bais)) { + Object o = ois.readObject(); + } + + ObjectInputFilter filter = ObjectInputFilter.Config.createFilter(pattern); + try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes); + ObjectInputStream ois = new ObjectInputStream(bais)) { + ObjectInputFilter.Config.setObjectInputFilter(ois, filter); + Object o = ois.readObject(); + assertTrue(false, "filter should have thrown an exception"); + } catch (InvalidClassException expected) { } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/io/Serializable/serialFilter/SerialFilterTest.java Mon Jan 23 16:30:43 2017 +0000 @@ -0,0 +1,743 @@ +/* + * Copyright (c) 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.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.EOFException; +import java.io.IOException; +import java.io.InvalidClassException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.lang.invoke.SerializedLambda; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Proxy; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Hashtable; +import java.util.Set; +import java.util.concurrent.atomic.LongAdder; + +import sun.misc.ObjectInputFilter; + +import javax.lang.model.SourceVersion; + +import org.testng.Assert; +import org.testng.annotations.Test; +import org.testng.annotations.DataProvider; + +/* @test + * @build SerialFilterTest + * @run testng/othervm SerialFilterTest + * + * @summary Test ObjectInputFilters + */ +@Test +public class SerialFilterTest implements Serializable { + + private static final long serialVersionUID = -6999613679881262446L; + + /** + * Enable three arg lambda. + * @param <T> The pattern + * @param <U> The test object + * @param <V> Boolean for if the filter should allow or reject + */ + interface TriConsumer< T, U, V> { + void accept(T t, U u, V v); + } + + /** + * Misc object to use that should always be accepted. + */ + private static final Object otherObject = Integer.valueOf(0); + + /** + * DataProvider for the individual patterns to test. + * Expand the patterns into cases for each of the Std and Compatibility APIs. + * @return an array of arrays of the parameters including factories + */ + @DataProvider(name="Patterns") + static Object[][] patterns() { + Object[][] patterns = new Object[][]{ + {"java.util.Hashtable"}, + {"java.util.Hash*"}, + {"javax.lang.model.*"}, + {"javax.lang.**"}, + {"*"}, + {"maxarray=47"}, + {"maxdepth=5"}, + {"maxrefs=10"}, + {"maxbytes=100"}, + {"maxbytes=72"}, + {"maxbytes=+1024"}, + }; + return patterns; + } + + @DataProvider(name="InvalidPatterns") + static Object[][] invalidPatterns() { + return new Object [][] { + {"maxrefs=-1"}, + {"maxdepth=-1"}, + {"maxbytes=-1"}, + {"maxarray=-1"}, + {"xyz=0"}, + {"xyz=-1"}, + {"maxrefs=0xabc"}, + {"maxrefs=abc"}, + {"maxrefs="}, + {"maxrefs=+"}, + {".*"}, + {".**"}, + {"!"}, + {"/java.util.Hashtable"}, + {"java.base/"}, + {"/"}, + }; + } + + @DataProvider(name="Limits") + static Object[][] limits() { + // The numbers are arbitrary > 1 + return new Object[][]{ + {"maxrefs", 10}, + {"maxdepth", 5}, + {"maxbytes", 100}, + {"maxarray", 16}, + }; + } + + /** + * DataProvider of individual objects. Used to check the information + * available to the filter. + * @return Arrays of parameters with objects + */ + @DataProvider(name="Objects") + static Object[][] objects() { + byte[] byteArray = new byte[0]; + Object[] objArray = new Object[7]; + objArray[objArray.length - 1] = objArray; + + Class<?> serClass = null; + String className = "java.util.concurrent.atomic.LongAdder$SerializationProxy"; + try { + serClass = Class.forName(className); + } catch (Exception e) { + Assert.fail("missing class: " + className, e); + } + + Class<?>[] interfaces = {Runnable.class}; + Runnable proxy = (Runnable) Proxy.newProxyInstance(null, + interfaces, (p, m, args) -> p); + + Runnable runnable = (Runnable & Serializable) SerialFilterTest::noop; + Object[][] objects = { + { null, 0, -1, 0, 0, 0, + new HashSet<>()}, // no callback, no values + { objArray, 3, 7, 8, 2, 55, + new HashSet<>(Arrays.asList(objArray.getClass()))}, + { Object[].class, 1, -1, 1, 1, 40, + new HashSet<>(Arrays.asList(Object[].class))}, + { new SerialFilterTest(), 1, -1, 1, 1, 37, + new HashSet<>(Arrays.asList(SerialFilterTest.class))}, + { new LongAdder(), 2, -1, 1, 1, 93, + new HashSet<>(Arrays.asList(LongAdder.class, serClass))}, + { new byte[14], 2, 14, 1, 1, 27, + new HashSet<>(Arrays.asList(byteArray.getClass()))}, + { runnable, 13, 0, 10, 2, 514, + new HashSet<>(Arrays.asList(java.lang.invoke.SerializedLambda.class, + SerialFilterTest.class, + objArray.getClass()))}, + { deepHashSet(10), 48, -1, 49, 11, 619, + new HashSet<>(Arrays.asList(HashSet.class))}, + { proxy.getClass(), 3, -1, 1, 1, 114, + new HashSet<>(Arrays.asList(Runnable.class, + java.lang.reflect.Proxy.class))}, + }; + return objects; + } + + @DataProvider(name="Arrays") + static Object[][] arrays() { + return new Object[][]{ + {new Object[16], 16}, + {new boolean[16], 16}, + {new byte[16], 16}, + {new char[16], 16}, + {new int[16], 16}, + {new long[16], 16}, + {new short[16], 16}, + {new float[16], 16}, + {new double[16], 16}, + }; + } + + + /** + * Test each object and verify the classes identified by the filter, + * the count of calls to the filter, the max array size, max refs, max depth, + * max bytes. + * This test ignores/is not dependent on the global filter settings. + * + * @param object a Serializable object + * @param count the expected count of calls to the filter + * @param maxArray the maximum array size + * @param maxRefs the maximum references + * @param maxDepth the maximum depth + * @param maxBytes the maximum stream size + * @param classes the expected (unique) classes + * @throws IOException + */ + @Test(dataProvider="Objects") + public static void t1(Object object, + long count, long maxArray, long maxRefs, long maxDepth, long maxBytes, + Set<Class<?>> classes) throws IOException { + byte[] bytes = writeObjects(object); + Validator validator = new Validator(); + validate(bytes, validator); + System.out.printf("v: %s%n", validator); + Assert.assertEquals(validator.count, count, "callback count wrong"); + Assert.assertEquals(validator.classes, classes, "classes mismatch"); + Assert.assertEquals(validator.maxArray, maxArray, "maxArray mismatch"); + Assert.assertEquals(validator.maxRefs, maxRefs, "maxRefs wrong"); + Assert.assertEquals(validator.maxDepth, maxDepth, "depth wrong"); + Assert.assertEquals(validator.maxBytes, maxBytes, "maxBytes wrong"); + } + + /** + * Test each pattern with an appropriate object. + * A filter is created from the pattern and used to serialize and + * deserialize a generated object with both the positive and negative case. + * This test ignores/is not dependent on the global filter settings. + * + * @param pattern a pattern + */ + @Test(dataProvider="Patterns") + static void testPatterns(String pattern) { + evalPattern(pattern, (p, o, neg) -> testPatterns(p, o, neg)); + } + + /** + * Test that the filter on a OIS can be set only on a fresh OIS, + * before deserializing any objects. + * This test is agnostic the global filter being set or not. + */ + @Test + static void nonResettableFilter() { + Validator validator1 = new Validator(); + Validator validator2 = new Validator(); + + try { + byte[] bytes = writeObjects("text1"); // an object + + try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes); + ObjectInputStream ois = new ObjectInputStream(bais)) { + // Check the initial filter is the global filter; may be null + ObjectInputFilter global = ObjectInputFilter.Config.getSerialFilter(); + ObjectInputFilter initial = ObjectInputFilter.Config.getObjectInputFilter(ois); + Assert.assertEquals(global, initial, "initial filter should be the global filter"); + + // Check if it can be set to null + ObjectInputFilter.Config.setObjectInputFilter(ois, null); + ObjectInputFilter filter = ObjectInputFilter.Config.getObjectInputFilter(ois); + Assert.assertNull(filter, "set to null should be null"); + + ObjectInputFilter.Config.setObjectInputFilter(ois, validator1); + Object o = ois.readObject(); + try { + ObjectInputFilter.Config.setObjectInputFilter(ois, validator2); + Assert.fail("Should not be able to set filter twice"); + } catch (IllegalStateException ise) { + // success, the exception was expected + } + } catch (EOFException eof) { + Assert.fail("Should not reach end-of-file", eof); + } catch (ClassNotFoundException cnf) { + Assert.fail("Deserializing", cnf); + } + } catch (IOException ex) { + Assert.fail("Unexpected IOException", ex); + } + } + + /** + * Test that if an Objects readReadResolve method returns an array + * that the callback to the filter includes the proper array length. + * @throws IOException if an error occurs + */ + @Test(dataProvider="Arrays") + static void testReadResolveToArray(Object array, int length) throws IOException { + ReadResolveToArray object = new ReadResolveToArray(array, length); + byte[] bytes = writeObjects(object); + Object o = validate(bytes, object); // the object is its own filter + Assert.assertEquals(o.getClass(), array.getClass(), "Filter not called with the array"); + } + + /** + * Test repeated limits use the last value. + * Construct a filter with the limit and the limit repeated -1. + * Invoke the filter with the limit to make sure it is rejected. + * Invoke the filter with the limit -1 to make sure it is accepted. + * @param name the name of the limit to test + * @param value a test value + */ + @Test(dataProvider="Limits") + static void testLimits(String name, int value) { + Class<?> arrayClass = new int[0].getClass(); + String pattern = String.format("%s=%d;%s=%d", name, value, name, value - 1); + ObjectInputFilter filter = ObjectInputFilter.Config.createFilter(pattern); + Assert.assertEquals( + filter.checkInput(new FilterValues(arrayClass, value, value, value, value)), + ObjectInputFilter.Status.REJECTED, + "last limit value not used: " + filter); + Assert.assertEquals( + filter.checkInput(new FilterValues(arrayClass, value-1, value-1, value-1, value-1)), + ObjectInputFilter.Status.UNDECIDED, + "last limit value not used: " + filter); + } + + /** + * Test that returning null from a filter causes deserialization to fail. + */ + @Test(expectedExceptions=InvalidClassException.class) + static void testNullStatus() throws IOException { + byte[] bytes = writeObjects(0); // an Integer + try { + Object o = validate(bytes, new ObjectInputFilter() { + public ObjectInputFilter.Status checkInput(ObjectInputFilter.FilterInfo f) { + return null; + } + }); + } catch (InvalidClassException ice) { + System.out.printf("Success exception: %s%n", ice); + throw ice; + } + } + + /** + * Verify that malformed patterns throw IAE. + * @param pattern pattern from the data source + */ + @Test(dataProvider="InvalidPatterns", expectedExceptions=IllegalArgumentException.class) + static void testInvalidPatterns(String pattern) { + try { + ObjectInputFilter.Config.createFilter(pattern); + } catch (IllegalArgumentException iae) { + System.out.printf(" success exception: %s%n", iae); + throw iae; + } + } + + /** + * Test that Config.create returns null if the argument does not contain any patterns or limits. + */ + @Test() + static void testEmptyPattern() { + ObjectInputFilter filter = ObjectInputFilter.Config.createFilter(""); + Assert.assertNull(filter, "empty pattern did not return null"); + + filter = ObjectInputFilter.Config.createFilter(";;;;"); + Assert.assertNull(filter, "pattern with only delimiters did not return null"); + } + + /** + * Read objects from the serialized stream, validated with the filter. + * + * @param bytes a byte array to read objects from + * @param filter the ObjectInputFilter + * @return the object deserialized if any + * @throws IOException can be thrown + */ + static Object validate(byte[] bytes, + ObjectInputFilter filter) throws IOException { + try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes); + ObjectInputStream ois = new ObjectInputStream(bais)) { + ObjectInputFilter.Config.setObjectInputFilter(ois, filter); + + Object o = ois.readObject(); + return o; + } catch (EOFException eof) { + // normal completion + } catch (ClassNotFoundException cnf) { + Assert.fail("Deserializing", cnf); + } + return null; + } + + /** + * Write objects and return a byte array with the bytes. + * + * @param objects zero or more objects to serialize + * @return the byte array of the serialized objects + * @throws IOException if an exception occurs + */ + static byte[] writeObjects(Object... objects) throws IOException { + byte[] bytes; + try (ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(baos)) { + for (Object o : objects) { + oos.writeObject(o); + } + bytes = baos.toByteArray(); + } + return bytes; + } + + /** + * A filter that accumulates information about the checkInput callbacks + * that can be checked after readObject completes. + */ + static class Validator implements ObjectInputFilter { + long count; // Count of calls to checkInput + HashSet<Class<?>> classes = new HashSet<>(); + long maxArray = -1; + long maxRefs; + long maxDepth; + long maxBytes; + + Validator() { + } + + @Override + public ObjectInputFilter.Status checkInput(FilterInfo filter) { + count++; + if (filter.serialClass() != null) { + if (filter.serialClass().getName().contains("$$Lambda$")) { + // TBD: proper identification of serialized Lambdas? + // Fold the serialized Lambda into the SerializedLambda type + classes.add(SerializedLambda.class); + } else if (Proxy.isProxyClass(filter.serialClass())) { + classes.add(Proxy.class); + } else { + classes.add(filter.serialClass()); + } + + } + this.maxArray = Math.max(this.maxArray, filter.arrayLength()); + this.maxRefs = Math.max(this.maxRefs, filter.references()); + this.maxDepth = Math.max(this.maxDepth, filter.depth()); + this.maxBytes = Math.max(this.maxBytes, filter.streamBytes()); + return ObjectInputFilter.Status.UNDECIDED; + } + + public String toString(){ + return "count: " + count + + ", classes: " + classes.toString() + + ", maxArray: " + maxArray + + ", maxRefs: " + maxRefs + + ", maxDepth: " + maxDepth + + ", maxBytes: " + maxBytes; + } + } + + + /** + * Create a filter from a pattern and API factory, then serialize and + * deserialize an object and check allowed or reject. + * + * @param pattern the pattern + * @param object the test object + * @param allowed the expected result from ObjectInputStream (exception or not) + */ + static void testPatterns(String pattern, Object object, boolean allowed) { + try { + byte[] bytes = SerialFilterTest.writeObjects(object); + ObjectInputFilter filter = ObjectInputFilter.Config.createFilter(pattern); + validate(bytes, filter); + Assert.assertTrue(allowed, "filter should have thrown an exception"); + } catch (IllegalArgumentException iae) { + Assert.fail("bad format pattern", iae); + } catch (InvalidClassException ice) { + Assert.assertFalse(allowed, "filter should not have thrown an exception: " + ice); + } catch (IOException ioe) { + Assert.fail("Unexpected IOException", ioe); + } + } + + /** + * For a filter pattern, generate and apply a test object to the action. + * @param pattern a pattern + * @param action an action to perform on positive and negative cases + */ + static void evalPattern(String pattern, TriConsumer<String, Object, Boolean> action) { + Object o = genTestObject(pattern, true); + Assert.assertNotNull(o, "success generation failed"); + action.accept(pattern, o, true); + + // Test the negative pattern + o = genTestObject(pattern, false); + Assert.assertNotNull(o, "fail generation failed"); + String negPattern = pattern.contains("=") ? pattern : "!" + pattern; + action.accept(negPattern, o, false); + } + + /** + * Generate a test object based on the pattern. + * Handles each of the forms of the pattern, wildcards, + * class name, various limit forms. + * @param pattern a pattern + * @param allowed a boolean indicating to generate the allowed or disallowed case + * @return an object or {@code null} to indicate no suitable object could be generated + */ + static Object genTestObject(String pattern, boolean allowed) { + if (pattern.contains("=")) { + return genTestLimit(pattern, allowed); + } else if (pattern.endsWith("*")) { + return genTestObjectWildcard(pattern, allowed); + } else { + // class + try { + Class<?> clazz = Class.forName(pattern); + Constructor<?> cons = clazz.getConstructor(); + return cons.newInstance(); + } catch (ClassNotFoundException ex) { + Assert.fail("no such class available: " + pattern); + } catch (InvocationTargetException + | NoSuchMethodException + | InstantiationException + | IllegalAccessException ex1) { + Assert.fail("newInstance: " + ex1); + } + } + return null; + } + + /** + * Generate an object to be used with the various wildcard pattern forms. + * Explicitly supports only specific package wildcards with specific objects. + * @param pattern a wildcard pattern ending in "*" + * @param allowed a boolean indicating to generate the allowed or disallowed case + * @return an object within or outside the wildcard + */ + static Object genTestObjectWildcard(String pattern, boolean allowed) { + if (pattern.endsWith(".**")) { + // package hierarchy wildcard + if (pattern.startsWith("javax.lang.")) { + return SourceVersion.RELEASE_5; + } + if (pattern.startsWith("java.")) { + return 4; + } + if (pattern.startsWith("javax.")) { + return SourceVersion.RELEASE_6; + } + return otherObject; + } else if (pattern.endsWith(".*")) { + // package wildcard + if (pattern.startsWith("javax.lang.model")) { + return SourceVersion.RELEASE_6; + } + } else { + // class wildcard + if (pattern.equals("*")) { + return otherObject; // any object will do + } + if (pattern.startsWith("java.util.Hash")) { + return new Hashtable<String, String>(); + } + } + Assert.fail("Object could not be generated for pattern: " + + pattern + + ", allowed: " + allowed); + return null; + } + + /** + * Generate a limit test object for the pattern. + * For positive cases, the object exactly hits the limit. + * For negative cases, the object is 1 greater than the limit + * @param pattern the pattern, containing "=" and a maxXXX keyword + * @param allowed a boolean indicating to generate the allowed or disallowed case + * @return a sitable object + */ + static Object genTestLimit(String pattern, boolean allowed) { + int ndx = pattern.indexOf('='); + Assert.assertNotEquals(ndx, -1, "missing value in limit"); + long value = Long.parseUnsignedLong(pattern.substring(ndx+1)); + if (pattern.startsWith("maxdepth=")) { + // Return an object with the requested depth (or 1 greater) + long depth = allowed ? value : value + 1; + Object[] array = new Object[1]; + for (int i = 1; i < depth; i++) { + Object[] n = new Object[1]; + n[0] = array; + array = n; + } + return array; + } else if (pattern.startsWith("maxbytes=")) { + // Return a byte array that when written to OOS creates + // a stream of exactly the size requested. + return genMaxBytesObject(allowed, value); + } else if (pattern.startsWith("maxrefs=")) { + Object[] array = new Object[allowed ? (int)value - 1 : (int)value]; + for (int i = 0; i < array.length; i++) { + array[i] = otherObject; + } + return array; + } else if (pattern.startsWith("maxarray=")) { + return allowed ? new int[(int)value] : new int[(int)value+1]; + } + Assert.fail("Object could not be generated for pattern: " + + pattern + + ", allowed: " + allowed); + return null; + } + + /** + * Generate an an object that will be serialized to some number of bytes. + * Or 1 greater if allowed is false. + * It returns a two element Object array holding a byte array sized + * to achieve the desired total size. + * @param allowed true if the stream should be allowed at that size, + * false if the stream should be larger + * @param maxBytes the number of bytes desired in the stream; + * should not be less than 72 (due to protocol overhead). + * @return a object that will be serialized to the length requested + */ + private static Object genMaxBytesObject(boolean allowed, long maxBytes) { + Object[] holder = new Object[2]; + long desiredSize = allowed ? maxBytes : maxBytes + 1; + long actualSize = desiredSize; + long byteSize = desiredSize - 72; // estimate needed array size + do { + byteSize += (desiredSize - actualSize); + byte[] a = new byte[(int)byteSize]; + holder[0] = a; + holder[1] = a; + try (ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ObjectOutputStream os = new ObjectOutputStream(baos)) { + os.writeObject(holder); + os.flush(); + actualSize = baos.size(); + } catch (IOException ie) { + Assert.fail("exception generating stream", ie); + } + } while (actualSize != desiredSize); + return holder; + } + + /** + * Returns a HashSet of a requested depth. + * @param depth the depth + * @return a HashSet of HashSets... + */ + static HashSet<Object> deepHashSet(int depth) { + HashSet<Object> hashSet = new HashSet<>(); + HashSet<Object> s1 = hashSet; + HashSet<Object> s2 = new HashSet<>(); + for (int i = 0; i < depth; i++ ) { + HashSet<Object> t1 = new HashSet<>(); + HashSet<Object> t2 = new HashSet<>(); + // make t1 not equal to t2 + t1.add("by Jimminy"); + s1.add(t1); + s1.add(t2); + s2.add(t1); + s2.add(t2); + s1 = t1; + s2 = t2; + } + return hashSet; + } + + /** + * Simple method to use with Serialized Lambda. + */ + private static void noop() {} + + + /** + * Class that returns an array from readResolve and also implements + * the ObjectInputFilter to check that it has the expected length. + */ + static class ReadResolveToArray implements Serializable, ObjectInputFilter { + private static final long serialVersionUID = 123456789L; + + private final Object array; + private final int length; + + ReadResolveToArray(Object array, int length) { + this.array = array; + this.length = length; + } + + Object readResolve() { + return array; + } + + @Override + public ObjectInputFilter.Status checkInput(FilterInfo filter) { + if (ReadResolveToArray.class.isAssignableFrom(filter.serialClass())) { + return ObjectInputFilter.Status.ALLOWED; + } + if (filter.serialClass() != array.getClass() || + (filter.arrayLength() >= 0 && filter.arrayLength() != length)) { + return ObjectInputFilter.Status.REJECTED; + } + return ObjectInputFilter.Status.UNDECIDED; + } + + } + + /** + * Hold a snapshot of values to be passed to an ObjectInputFilter. + */ + static class FilterValues implements ObjectInputFilter.FilterInfo { + private final Class<?> clazz; + private final long arrayLength; + private final long depth; + private final long references; + private final long streamBytes; + + public FilterValues(Class<?> clazz, long arrayLength, long depth, long references, long streamBytes) { + this.clazz = clazz; + this.arrayLength = arrayLength; + this.depth = depth; + this.references = references; + this.streamBytes = streamBytes; + } + + @Override + public Class<?> serialClass() { + return clazz; + } + + public long arrayLength() { + return arrayLength; + } + + public long depth() { + return depth; + } + + public long references() { + return references; + } + + public long streamBytes() { + return streamBytes; + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/io/Serializable/serialFilter/java.security-extra1 Mon Jan 23 16:30:43 2017 +0000 @@ -0,0 +1,4 @@ +# Serialization Input Process-wide Filter +# See conf/security/java.security for pattern synatx +# +jdk.serialFilter=java.**;javax.**;maxarray=34;maxdepth=7
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/io/Serializable/serialFilter/security.policy Mon Jan 23 16:30:43 2017 +0000 @@ -0,0 +1,17 @@ +// Individual Permissions to for GlobalFilterTest +grant { + // Specific permission under test + permission java.security.SerializablePermission "serialFilter"; + // Permissions needed to run the test + permission java.util.PropertyPermission "*", "read"; + permission java.io.FilePermission "<<ALL FILES>>", "read,write,delete"; + permission java.lang.reflect.ReflectPermission "suppressAccessChecks"; + permission java.security.SecurityPermission "*"; + permission java.lang.RuntimePermission "accessDeclaredMembers"; + permission java.lang.RuntimePermission "accessClassInPackage.sun.misc"; +}; + +// Standard extensions get all permissions by default +grant codeBase "file:${{java.ext.dirs}}/*" { + permission java.security.AllPermission; +};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/io/Serializable/serialFilter/security.policy.without.globalFilter Mon Jan 23 16:30:43 2017 +0000 @@ -0,0 +1,15 @@ +// Individual Permissions for FilterWithSecurityManagerTest +grant { + // Permissions needed to run the test + permission java.util.PropertyPermission "*", "read"; + permission java.io.FilePermission "<<ALL FILES>>", "read,write,delete"; + permission java.lang.reflect.ReflectPermission "suppressAccessChecks"; + permission java.lang.RuntimePermission "accessDeclaredMembers"; + permission java.lang.RuntimePermission "accessClassInPackage.sun.misc"; +}; + +// Standard extensions get all permissions by default +grant codeBase "file:${{java.ext.dirs}}/*" { + permission java.security.AllPermission; +}; +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/rmi/MarshalledObject/MOFilterTest.java Mon Jan 23 16:30:43 2017 +0000 @@ -0,0 +1,140 @@ +/* + * Copyright (c) 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.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InvalidClassException; +import java.io.ObjectInput; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.rmi.MarshalledObject; +import java.util.Objects; + +import sun.misc.ObjectInputFilter; + +import org.testng.Assert; +import org.testng.annotations.Test; +import org.testng.annotations.DataProvider; + +/* @test + * @run testng/othervm MOFilterTest + * + * @summary Test MarshalledObject applies ObjectInputFilter + */ +@Test +public class MOFilterTest { + + /** + * Two cases are tested. + * The filter = null and a filter set to verify the calls to the filter. + * @return array objects with test parameters for each test case + */ + @DataProvider(name = "FilterCases") + public static Object[][] filterCases() { + return new Object[][] { + {true}, // run the test with the filter + {false}, // run the test without the filter + + }; + } + + /** + * Test that MarshalledObject inherits the ObjectInputFilter from + * the stream it was deserialized from. + */ + @Test(dataProvider="FilterCases") + static void delegatesToMO(boolean withFilter) { + try { + Serializable testobj = Integer.valueOf(5); + MarshalledObject<Serializable> mo = new MarshalledObject<>(testobj); + Assert.assertEquals(mo.get(), testobj, "MarshalledObject.get returned a non-equals test object"); + + byte[] bytes = writeObjects(mo); + + try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes); + ObjectInputStream ois = new ObjectInputStream(bais)) { + + CountingFilter filter1 = new CountingFilter(); + ObjectInputFilter.Config.setObjectInputFilter(ois, withFilter ? filter1 : null); + MarshalledObject<?> actualMO = (MarshalledObject<?>)ois.readObject(); + int count = filter1.getCount(); + + actualMO.get(); + int expectedCount = withFilter ? count + 2 : count; + int actualCount = filter1.getCount(); + Assert.assertEquals(actualCount, expectedCount, "filter called wrong number of times during get()"); + } + } catch (IOException ioe) { + Assert.fail("Unexpected IOException", ioe); + } catch (ClassNotFoundException cnf) { + Assert.fail("Deserializing", cnf); + } + } + + /** + * Write objects and return a byte array with the bytes. + * + * @param objects zero or more objects to serialize + * @return the byte array of the serialized objects + * @throws IOException if an exception occurs + */ + static byte[] writeObjects(Object... objects) throws IOException { + byte[] bytes; + try (ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(baos)) { + for (Object o : objects) { + oos.writeObject(o); + } + bytes = baos.toByteArray(); + } + return bytes; + } + + + static class CountingFilter implements ObjectInputFilter { + + private int count; // count of calls to the filter + + CountingFilter() { + count = 0; + } + + int getCount() { + return count; + } + + /** + * Filter that rejects class Integer and allows others + * + * @param filterInfo access to the class, arrayLength, etc. + * @return {@code STATUS.REJECTED} + */ + public ObjectInputFilter.Status checkInput(FilterInfo filterInfo) { + count++; + return ObjectInputFilter.Status.ALLOWED; + } + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/rmi/registry/serialFilter/RegistryFilterTest.java Mon Jan 23 16:30:43 2017 +0000 @@ -0,0 +1,186 @@ +/* + * Copyright (c) 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.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectOutputStream; +import java.io.Serializable; + +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.rmi.MarshalledObject; +import java.rmi.NotBoundException; +import java.rmi.Remote; +import java.rmi.RemoteException; +import java.rmi.AlreadyBoundException; +import java.rmi.registry.LocateRegistry; +import java.rmi.registry.Registry; +import java.util.Objects; +import java.security.Security; + +import org.testng.Assert; +import org.testng.TestNG; +import org.testng.annotations.BeforeSuite; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +/* + * @test + * @library /java/rmi/testlibrary + * @modules java.rmi/sun.rmi.registry + * java.rmi/sun.rmi.server + * java.rmi/sun.rmi.transport + * java.rmi/sun.rmi.transport.tcp + * @build TestLibrary + * @summary Test filters for the RMI Registry + * @run testng/othervm RegistryFilterTest + * @run testng/othervm + * -Dsun.rmi.registry.registryFilter=!java.lang.Long;!RegistryFilterTest$RejectableClass + * RegistryFilterTest + * @run testng/othervm/policy=security.policy + * -Djava.security.properties=${test.src}/java.security-extra1 + * RegistryFilterTest + */ +public class RegistryFilterTest { + private static Registry impl; + private static int port; + private static Registry registry; + + static final int REGISTRY_MAX_ARRAY = 10000; + + static final String registryFilter = + System.getProperty("sun.rmi.registry.registryFilter", + Security.getProperty("sun.rmi.registry.registryFilter")); + + @DataProvider(name = "bindAllowed") + static Object[][] bindAllowedObjects() { + Object[][] objects = { + }; + return objects; + } + + /** + * Data RMI Regiry bind test. + * - name + * - Object + * - true/false if object is blacklisted by a filter (implicit or explicit) + * @return array of test data + */ + @DataProvider(name = "bindData") + static Object[][] bindObjects() { + Object[][] data = { + { "byte[max]", new XX(new byte[REGISTRY_MAX_ARRAY]), false }, + { "String", new XX("now is the time"), false}, + { "String[]", new XX(new String[3]), false}, + { "Long[4]", new XX(new Long[4]), registryFilter != null }, + { "rej-byte[toobig]", new XX(new byte[REGISTRY_MAX_ARRAY + 1]), true }, + { "rej-MarshalledObject", createMarshalledObject(), true }, + { "rej-RejectableClass", new RejectableClass(), registryFilter != null}, + }; + return data; + } + + static XX createMarshalledObject() { + try { + return new XX(new MarshalledObject<>(null)); + } catch (IOException ioe) { + return new XX(ioe); + } + } + + @BeforeSuite + static void setupRegistry() { + try { + impl = TestLibrary.createRegistryOnEphemeralPort(); + port = TestLibrary.getRegistryPort(impl); + registry = LocateRegistry.getRegistry("localhost", port); + } catch (RemoteException ex) { + Assert.fail("initialization of registry", ex); + } + + System.out.printf("RMI Registry filter: %s%n", registryFilter); + } + + + /* + * Test registry rejects an object with the max array size + 1. + */ + @Test(dataProvider="bindData") + public void simpleBind(String name, Remote obj, boolean blacklisted) throws RemoteException, AlreadyBoundException, NotBoundException { + try { + registry.bind(name, obj); + Assert.assertFalse(blacklisted, "Registry filter did not reject (but should have) "); + registry.unbind(name); + } catch (Exception rex) { + Assert.assertTrue(blacklisted, "Registry filter should not have rejected"); + } + } + + /* + * Test registry rejects an object with a well known class + * if blacklisted in the security properties. + */ + @Test + public void simpleRejectableClass() throws RemoteException, AlreadyBoundException, NotBoundException { + RejectableClass r1 = null; + try { + String name = "reject1"; + r1 = new RejectableClass(); + registry.bind(name, r1); + registry.unbind(name); + Assert.assertNull(registryFilter, "Registry filter should not have rejected"); + } catch (Exception rex) { + Assert.assertNotNull(registryFilter, "Registry filter should have rejected"); + } + } + + /** + * A simple Serializable Remote object that is passed by value. + * It and its contents are checked by the Registry serial filter. + */ + static class XX implements Serializable, Remote { + private static final long serialVersionUID = 362498820763181265L; + + final Object obj; + + XX(Object obj) { + this.obj = obj; + } + + public String toString() { + return super.toString() + "//" + Objects.toString(obj); + } + } + /** + * A simple Serializable Remote object that is passed by value. + * It and its contents are checked by the Registry serial filter. + */ + static class RejectableClass implements Serializable, Remote { + private static final long serialVersionUID = 362498820763181264L; + + RejectableClass() {} + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/rmi/registry/serialFilter/java.security-extra1 Mon Jan 23 16:30:43 2017 +0000 @@ -0,0 +1,8 @@ +# RMI Registry Input Serial Filter +# +# The filter pattern uses the same format as java.io.ObjectInputStream.serialFilter. +# This filter can override the builtin filter if additional types need to be +# allowed or rejected from the RMI Registry. +# +sun.rmi.registry.registryFilter=!java.lang.Long;!RegistryFilterTest$RejectableClass +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/rmi/registry/serialFilter/security.policy Mon Jan 23 16:30:43 2017 +0000 @@ -0,0 +1,4 @@ +grant { + permission java.security.AllPermission; +}; +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/security/Signature/SignatureLength.java Mon Jan 23 16:30:43 2017 +0000 @@ -0,0 +1,101 @@ +/* + * Copyright (c) 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.security.*; + +/* + * @test + * @bug 8161571 + * @summary Reject signatures presented for verification that contain extra + * bytes. + * @run main SignatureLength + */ +public class SignatureLength { + + public static void main(String[] args) throws Exception { + main0("EC", 256, "SHA256withECDSA", "SunEC"); + main0("RSA", 2048, "SHA256withRSA", "SunRsaSign"); + main0("DSA", 2048, "SHA256withDSA", "SUN"); + + if (System.getProperty("os.name").equals("SunOS")) { + main0("EC", 256, "SHA256withECDSA", null); + main0("RSA", 2048, "SHA256withRSA", null); + } + } + + private static void main0(String keyAlgorithm, int keysize, + String signatureAlgorithm, String provider) throws Exception { + byte[] plaintext = "aaa".getBytes("UTF-8"); + + // Generate + KeyPairGenerator generator = + provider == null ? + (KeyPairGenerator) KeyPairGenerator.getInstance(keyAlgorithm) : + (KeyPairGenerator) KeyPairGenerator.getInstance( + keyAlgorithm, provider); + generator.initialize(keysize); + System.out.println("Generating " + keyAlgorithm + " keypair using " + + generator.getProvider().getName() + " JCE provider"); + KeyPair keypair = generator.generateKeyPair(); + + // Sign + Signature signer = + provider == null ? + Signature.getInstance(signatureAlgorithm) : + Signature.getInstance(signatureAlgorithm, provider); + signer.initSign(keypair.getPrivate()); + signer.update(plaintext); + System.out.println("Signing using " + signer.getProvider().getName() + + " JCE provider"); + byte[] signature = signer.sign(); + + // Invalidate + System.out.println("Invalidating signature ..."); + byte[] badSignature = new byte[signature.length + 5]; + System.arraycopy(signature, 0, badSignature, 0, signature.length); + badSignature[signature.length] = 0x01; + badSignature[signature.length + 1] = 0x01; + badSignature[signature.length + 2] = 0x01; + badSignature[signature.length + 3] = 0x01; + badSignature[signature.length + 4] = 0x01; + + // Verify + Signature verifier = + provider == null ? + Signature.getInstance(signatureAlgorithm) : + Signature.getInstance(signatureAlgorithm, provider); + verifier.initVerify(keypair.getPublic()); + verifier.update(plaintext); + System.out.println("Verifying using " + + verifier.getProvider().getName() + " JCE provider"); + + try { + System.out.println("Valid? " + verifier.verify(badSignature)); + throw new Exception( + "ERROR: expected a SignatureException but none was thrown"); + } catch (SignatureException e) { + System.out.println("OK: caught expected exception: " + e); + } + System.out.println(); + } +}
--- a/test/java/time/test/java/time/format/TestZoneTextPrinterParser.java Fri Jan 13 17:09:28 2017 +0000 +++ b/test/java/time/test/java/time/format/TestZoneTextPrinterParser.java Mon Jan 23 16:30:43 2017 +0000 @@ -49,7 +49,7 @@ /* * @test - * @bug 8081022 8151876 + * @bug 8081022 8151876 8166875 * @key randomness */
--- a/test/java/time/test/java/time/format/ZoneName.java Fri Jan 13 17:09:28 2017 +0000 +++ b/test/java/time/test/java/time/format/ZoneName.java Mon Jan 23 16:30:43 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -378,6 +378,7 @@ "Europe/Helsinki", "Europe_Eastern", "Europe/Bucharest", "America/Nome", "Alaska", "America/Juneau", "Asia/Yakutsk", "Yakutsk", "Asia/Yakutsk", + "Asia/Yangon", "Myanmar", "Asia/Rangoon", "Africa/Conakry", "GMT", "Atlantic/Reykjavik", "Asia/Seoul", "Korea", "Asia/Seoul", "America/Antigua", "Atlantic", "America/Halifax", @@ -747,6 +748,7 @@ "NZ", "Pacific/Auckland", "Asia/Tel_Aviv", "Asia/Jerusalem", "Hongkong", "Asia/Hong_Kong", + "Asia/Rangoon", "Asia/Yangon", }; private static final Map<String, String> zidToMzone = new HashMap<>();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/javax/net/ssl/TLSv12/DisabledShortDSAKeys.java Mon Jan 23 16:30:43 2017 +0000 @@ -0,0 +1,441 @@ +/* + * Copyright (c) 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. 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. + */ + +// SunJSSE does not support dynamic system properties, no way to re-use +// system properties in samevm/agentvm mode. + +/* + * @test + * @bug 8139565 + * @summary Restrict certificates with DSA keys less than 1024 bits + * + * @run main/othervm DisabledShortDSAKeys PKIX TLSv1.2 + * @run main/othervm DisabledShortDSAKeys SunX509 TLSv1.2 + * @run main/othervm DisabledShortDSAKeys PKIX TLSv1.1 + * @run main/othervm DisabledShortDSAKeys SunX509 TLSv1.1 + * @run main/othervm DisabledShortDSAKeys PKIX TLSv1 + * @run main/othervm DisabledShortDSAKeys SunX509 TLSv1 + * @run main/othervm DisabledShortDSAKeys PKIX SSLv3 + * @run main/othervm DisabledShortDSAKeys SunX509 SSLv3 + */ + +import java.net.*; +import java.util.*; +import java.io.*; +import javax.net.ssl.*; +import java.security.Security; +import java.security.KeyStore; +import java.security.KeyFactory; +import java.security.cert.Certificate; +import java.security.cert.CertificateFactory; +import java.security.spec.*; +import java.security.interfaces.*; +import java.util.Base64; + + +public class DisabledShortDSAKeys { + + /* + * ============================================================= + * Set the various variables needed for the tests, then + * specify what tests to run on each side. + */ + + /* + * Should we run the client or server in a separate thread? + * Both sides can throw exceptions, but do you have a preference + * as to which side should be the main thread. + */ + static boolean separateServerThread = true; + + /* + * Where do we find the keystores? + */ + // Certificates and key used in the test. + static String trustedCertStr = + "-----BEGIN CERTIFICATE-----\n" + + "MIIDDjCCAs2gAwIBAgIJAO5/hbm1ByJOMAkGByqGSM44BAMwHzELMAkGA1UEBhMC\n" + + "VVMxEDAOBgNVBAoTB0V4YW1wbGUwHhcNMTYwMjE2MDQzNTQ2WhcNMzcwMTI2MDQz\n" + + "NTQ2WjAfMQswCQYDVQQGEwJVUzEQMA4GA1UEChMHRXhhbXBsZTCCAbgwggEsBgcq\n" + + "hkjOOAQBMIIBHwKBgQC4aSK8nBYdWJtuBkz6yoDyjZnNuGFSpDmx1ggKpLpcnPuw\n" + + "YKAbUhqdYhZtaIqQ4aO0T1ZS/HuOM0zvddnMUidFNX3RUvDkvdD/JYOnjqzCm+xW\n" + + "U0NFuPHZdapQY5KFk3ugkqZpHLY1StZbu0qugZOZjbBOMwB7cHAbMDuVpEr8DQIV\n" + + "AOi+ig+h3okFbWEE9MztiI2+DqNrAoGBAKh2EZbuWU9NoHglhVzfDUoz8CeyW6W6\n" + + "rUZuIOQsjWaYOeRPWX0UVAGq9ykIOfamEpurKt4H8ge/pHaL9iazJjonMHOXG12A\n" + + "0lALsMDGv22zVaJzXjOBvdPzc87opr0LIVgHASKOcDYjsICKNYPlS2cL3MJoD+bj\n" + + "NAR67b90VBbEA4GFAAKBgQCGrkRp2tdj2mZF7Qz0tO6p3xSysbEfN6QZxOJYPTvM\n" + + "yIYfLV9Yoy7XaRd/mCpJo/dqmsZMzowtyi+u+enuVpOLKiq/lyCktL+xUzZAjLT+\n" + + "9dafHlS1wR3pDSa1spo9xTEi4Ff/DQDHcdGalBxSXX/UdRtSecIYAp5/fkt3QZ5v\n" + + "0aOBkTCBjjAdBgNVHQ4EFgQUX4qbP5PgBx1J8BJ8qEgfoKVLSnQwTwYDVR0jBEgw\n" + + "RoAUX4qbP5PgBx1J8BJ8qEgfoKVLSnShI6QhMB8xCzAJBgNVBAYTAlVTMRAwDgYD\n" + + "VQQKEwdFeGFtcGxlggkA7n+FubUHIk4wDwYDVR0TAQH/BAUwAwEB/zALBgNVHQ8E\n" + + "BAMCAgQwCQYHKoZIzjgEAwMwADAtAhUAkr5bINXyy/McAx6qwhb6r0/QJUgCFFUP\n" + + "CZokA4/NqJIgq8ThpTQAE8SB\n" + + "-----END CERTIFICATE-----"; + + static String targetCertStr = + "-----BEGIN CERTIFICATE-----\n" + + "MIICUjCCAhGgAwIBAgIJAIiDrs/4W8rtMAkGByqGSM44BAMwHzELMAkGA1UEBhMC\n" + + "VVMxEDAOBgNVBAoTB0V4YW1wbGUwHhcNMTYwMjE2MDQzNTQ2WhcNMzUxMTAzMDQz\n" + + "NTQ2WjA5MQswCQYDVQQGEwJVUzEQMA4GA1UECgwHRXhhbXBsZTEYMBYGA1UEAwwP\n" + + "d3d3LmV4YW1wbGUuY29tMIHwMIGoBgcqhkjOOAQBMIGcAkEAs6A0p3TysTtVXGSv\n" + + "ThR/8GHpbL49KyWRJBMIlmLc5jl/wxJgnL1t07p4YTOEa6ecyTFos04Z8n2GARmp\n" + + "zYlUywIVAJLDcf4JXhZbguRFSQdWwWhZkh+LAkBLCzh3Xvpmc/5CDqU+QHqDcuSk\n" + + "5B8+ZHaHRi2KQ00ejilpF2qZpW5JdHe4m3Pggh0MIuaAGX+leM4JKlnObj14A0MA\n" + + "AkAYb+DYlFgStFhF1ip7rFzY8K6i/3ellkXI2umI/XVwxUQTHSlk5nFOep5Dfzm9\n" + + "pADJwuSe1qGHsHB5LpMZPVpto4GEMIGBMAkGA1UdEwQCMAAwCwYDVR0PBAQDAgPo\n" + + "MB0GA1UdDgQWBBT8nsFyccF4q1dtpWE1dkNK5UiXtTAfBgNVHSMEGDAWgBRfips/\n" + + "k+AHHUnwEnyoSB+gpUtKdDAnBgNVHSUEIDAeBggrBgEFBQcDAQYIKwYBBQUHAwIG\n" + + "CCsGAQUFBwMDMAkGByqGSM44BAMDMAAwLQIUIcIlxpIwaZXdpMC+U076unR1Mp8C\n" + + "FQCD/NE8O0xwq57nwFfp7tUvUHYMMA==\n" + + "-----END CERTIFICATE-----"; + + // Private key in the format of PKCS#8, key size is 512 bits. + static String targetPrivateKey = + "MIHGAgEAMIGoBgcqhkjOOAQBMIGcAkEAs6A0p3TysTtVXGSvThR/8GHpbL49KyWR\n" + + "JBMIlmLc5jl/wxJgnL1t07p4YTOEa6ecyTFos04Z8n2GARmpzYlUywIVAJLDcf4J\n" + + "XhZbguRFSQdWwWhZkh+LAkBLCzh3Xvpmc/5CDqU+QHqDcuSk5B8+ZHaHRi2KQ00e\n" + + "jilpF2qZpW5JdHe4m3Pggh0MIuaAGX+leM4JKlnObj14BBYCFHB2Wek2g5hpNj5y\n" + + "RQfCc6CFO0dv"; + + static char passphrase[] = "passphrase".toCharArray(); + + /* + * Is the server ready to serve? + */ + volatile static boolean serverReady = false; + + /* + * Turn on SSL debugging? + */ + static boolean debug = false; + + /* + * Define the server side of the test. + * + * If the server prematurely exits, serverReady will be set to true + * to avoid infinite hangs. + */ + void doServerSide() throws Exception { + SSLContext context = generateSSLContext(null, targetCertStr, + targetPrivateKey); + SSLServerSocketFactory sslssf = context.getServerSocketFactory(); + SSLServerSocket sslServerSocket = + (SSLServerSocket)sslssf.createServerSocket(serverPort); + serverPort = sslServerSocket.getLocalPort(); + + /* + * Signal Client, we're ready for his connect. + */ + serverReady = true; + + try (SSLSocket sslSocket = (SSLSocket)sslServerSocket.accept()) { + try (InputStream sslIS = sslSocket.getInputStream()) { + sslIS.read(); + } + + throw new Exception( + "DSA keys shorter than 1024 bits should be disabled"); + } catch (SSLHandshakeException sslhe) { + // the expected exception, ignore + } + } + + /* + * Define the client side of the test. + * + * If the server prematurely exits, serverReady will be set to true + * to avoid infinite hangs. + */ + void doClientSide() throws Exception { + + /* + * Wait for server to get started. + */ + while (!serverReady) { + Thread.sleep(50); + } + + SSLContext context = generateSSLContext(trustedCertStr, null, null); + SSLSocketFactory sslsf = context.getSocketFactory(); + + try (SSLSocket sslSocket = + (SSLSocket)sslsf.createSocket("localhost", serverPort)) { + + // only enable the target protocol + sslSocket.setEnabledProtocols(new String[] {enabledProtocol}); + + // enable a block cipher + sslSocket.setEnabledCipherSuites( + new String[] {"TLS_DHE_DSS_WITH_AES_128_CBC_SHA"}); + + try (OutputStream sslOS = sslSocket.getOutputStream()) { + sslOS.write('B'); + sslOS.flush(); + } + + throw new Exception( + "DSA keys shorter than 1024 bits should be disabled"); + } catch (SSLHandshakeException sslhe) { + // the expected exception, ignore + } + } + + /* + * ============================================================= + * The remainder is just support stuff + */ + private static String tmAlgorithm; // trust manager + private static String enabledProtocol; // the target protocol + + private static void parseArguments(String[] args) { + tmAlgorithm = args[0]; + enabledProtocol = args[1]; + } + + private static SSLContext generateSSLContext(String trustedCertStr, + String keyCertStr, String keySpecStr) throws Exception { + + // generate certificate from cert string + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + + // create a key store + KeyStore ks = KeyStore.getInstance("JKS"); + ks.load(null, null); + + // import the trused cert + Certificate trusedCert = null; + ByteArrayInputStream is = null; + if (trustedCertStr != null) { + is = new ByteArrayInputStream(trustedCertStr.getBytes()); + trusedCert = cf.generateCertificate(is); + is.close(); + + ks.setCertificateEntry("DSA Export Signer", trusedCert); + } + + if (keyCertStr != null) { + // generate the private key. + PKCS8EncodedKeySpec priKeySpec = new PKCS8EncodedKeySpec( + Base64.getMimeDecoder().decode(keySpecStr)); + KeyFactory kf = KeyFactory.getInstance("DSA"); + DSAPrivateKey priKey = + (DSAPrivateKey)kf.generatePrivate(priKeySpec); + + // generate certificate chain + is = new ByteArrayInputStream(keyCertStr.getBytes()); + Certificate keyCert = cf.generateCertificate(is); + is.close(); + + Certificate[] chain = null; + if (trusedCert != null) { + chain = new Certificate[2]; + chain[0] = keyCert; + chain[1] = trusedCert; + } else { + chain = new Certificate[1]; + chain[0] = keyCert; + } + + // import the key entry. + ks.setKeyEntry("Whatever", priKey, passphrase, chain); + } + + // create SSL context + TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmAlgorithm); + tmf.init(ks); + + SSLContext ctx = SSLContext.getInstance("TLS"); + if (keyCertStr != null && !keyCertStr.isEmpty()) { + KeyManagerFactory kmf = KeyManagerFactory.getInstance("NewSunX509"); + kmf.init(ks, passphrase); + + ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); + ks = null; + } else { + ctx.init(null, tmf.getTrustManagers(), null); + } + + return ctx; + } + + + // use any free port by default + volatile int serverPort = 0; + + volatile Exception serverException = null; + volatile Exception clientException = null; + + public static void main(String[] args) throws Exception { + if (debug) + System.setProperty("javax.net.debug", "all"); + + /* + * Get the customized arguments. + */ + parseArguments(args); + + /* + * Start the tests. + */ + new DisabledShortDSAKeys(); + } + + Thread clientThread = null; + Thread serverThread = null; + + /* + * Primary constructor, used to drive remainder of the test. + * + * Fork off the other side, then do your work. + */ + DisabledShortDSAKeys() throws Exception { + Exception startException = null; + try { + if (separateServerThread) { + startServer(true); + startClient(false); + } else { + startClient(true); + startServer(false); + } + } catch (Exception e) { + startException = e; + } + + /* + * Wait for other side to close down. + */ + if (separateServerThread) { + if (serverThread != null) { + serverThread.join(); + } + } else { + if (clientThread != null) { + clientThread.join(); + } + } + + /* + * When we get here, the test is pretty much over. + * Which side threw the error? + */ + Exception local; + Exception remote; + + if (separateServerThread) { + remote = serverException; + local = clientException; + } else { + remote = clientException; + local = serverException; + } + + Exception exception = null; + + /* + * Check various exception conditions. + */ + if ((local != null) && (remote != null)) { + // If both failed, return the curthread's exception. + local.initCause(remote); + exception = local; + } else if (local != null) { + exception = local; + } else if (remote != null) { + exception = remote; + } else if (startException != null) { + exception = startException; + } + + /* + * If there was an exception *AND* a startException, + * output it. + */ + if (exception != null) { + if (exception != startException && startException != null) { + exception.addSuppressed(startException); + } + throw exception; + } + + // Fall-through: no exception to throw! + } + + void startServer(boolean newThread) throws Exception { + if (newThread) { + serverThread = new Thread() { + public void run() { + try { + doServerSide(); + } catch (Exception e) { + /* + * Our server thread just died. + * + * Release the client, if not active already... + */ + System.err.println("Server died..."); + serverReady = true; + serverException = e; + } + } + }; + serverThread.start(); + } else { + try { + doServerSide(); + } catch (Exception e) { + serverException = e; + } finally { + serverReady = true; + } + } + } + + void startClient(boolean newThread) throws Exception { + if (newThread) { + clientThread = new Thread() { + public void run() { + try { + doClientSide(); + } catch (Exception e) { + /* + * Our client thread just died. + */ + System.err.println("Client died..."); + clientException = e; + } + } + }; + clientThread.start(); + } else { + try { + doClientSide(); + } catch (Exception e) { + clientException = e; + } + } + } +}
--- a/test/javax/net/ssl/ciphersuites/DisabledAlgorithms.java Fri Jan 13 17:09:28 2017 +0000 +++ b/test/javax/net/ssl/ciphersuites/DisabledAlgorithms.java Mon Jan 23 16:30:43 2017 +0000 @@ -41,7 +41,8 @@ * @bug 8076221 * @summary Check if weak cipher suites are disabled * @run main/othervm DisabledAlgorithms default - * @run main/othervm DisabledAlgorithms empty + * @run main/othervm -Djdk.tls.namedGroups="secp256r1,secp192r1" + * DisabledAlgorithms empty */ public class DisabledAlgorithms { @@ -97,6 +98,11 @@ System.out.println("jdk.tls.disabledAlgorithms = " + Security.getProperty("jdk.tls.disabledAlgorithms")); + // some of the certs in our test are weak; disable + Security.setProperty("jdk.certpath.disabledAlgorithms", ""); + System.out.println("jdk.certpath.disabledAlgorithms = " + + Security.getProperty("jdk.cerpath.disabledAlgorithms")); + // check if RC4 cipher suites can be used // if jdk.tls.disabledAlgorithms is empty checkSuccess(rc4_ciphersuites); @@ -224,6 +230,7 @@ socket.getSession().invalidate(); } catch (SSLHandshakeException e) { System.out.println("Server: run: " + e); + e.printStackTrace(); sslError = true; stopped = true; } catch (IOException e) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/javax/net/ssl/ciphersuites/ECCurvesconstraints.java Mon Jan 23 16:30:43 2017 +0000 @@ -0,0 +1,408 @@ +/* + * Copyright (c) 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. 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. + */ + +// +// SunJSSE does not support dynamic system properties, no way to re-use +// system properties in samevm/agentvm mode. +// + +/* + * @test + * @bug 8148516 + * @summary Improve the default strength of EC in JDK + * @run main/othervm ECCurvesconstraints PKIX + * @run main/othervm ECCurvesconstraints SunX509 + */ + +import java.net.*; +import java.util.*; +import java.io.*; +import javax.net.ssl.*; +import java.security.Security; +import java.security.KeyStore; +import java.security.KeyFactory; +import java.security.cert.Certificate; +import java.security.cert.X509Certificate; +import java.security.cert.CertificateFactory; +import java.security.spec.*; +import java.security.interfaces.*; +import java.util.Base64; + + +public class ECCurvesconstraints { + + /* + * ============================================================= + * Set the various variables needed for the tests, then + * specify what tests to run on each side. + */ + + /* + * Should we run the client or server in a separate thread? + * Both sides can throw exceptions, but do you have a preference + * as to which side should be the main thread. + */ + static boolean separateServerThread = false; + + /* + * Where do we find the keystores? + */ + // Certificates and key used in the test. + // + // EC curve: secp224k1 + static String trustedCertStr = + "-----BEGIN CERTIFICATE-----\n" + + "MIIBCzCBugIEVz2lcjAKBggqhkjOPQQDAjAaMRgwFgYDVQQDDA93d3cuZXhhbXBs\n" + + "ZS5vcmcwHhcNMTYwNTE5MTEzNzM5WhcNMTcwNTE5MTEzNzM5WjAaMRgwFgYDVQQD\n" + + "DA93d3cuZXhhbXBsZS5vcmcwTjAQBgcqhkjOPQIBBgUrgQQAIAM6AAT68uovMZ8f\n" + + "KARn5NOjvieJaq6h8zHYkM9w5DuN0kkOo4KBhke06EkQj0nvQQcSvppTV6RoDLY4\n" + + "djAKBggqhkjOPQQDAgNAADA9AhwMNIujM0R0llpPH6d89d1S3VRGH/78ovc+zw51\n" + + "Ah0AuZ1YlQkUbrJIzkuPSICxz5UfCWPe+7w4as+wiA==\n" + + "-----END CERTIFICATE-----"; + + // Private key in the format of PKCS#8 + static String targetPrivateKey = + "MIGCAgEAMBAGByqGSM49AgEGBSuBBAAgBGswaQIBAQQdAPbckc86mgW/zexB1Ajq\n" + + "38HntWOjdxL6XSoiAsWgBwYFK4EEACChPAM6AAT68uovMZ8fKARn5NOjvieJaq6h\n" + + "8zHYkM9w5DuN0kkOo4KBhke06EkQj0nvQQcSvppTV6RoDLY4dg=="; + + static String[] serverCerts = {trustedCertStr}; + static String[] serverKeys = {targetPrivateKey}; + static String[] clientCerts = {trustedCertStr}; + static String[] clientKeys = {targetPrivateKey}; + + static char passphrase[] = "passphrase".toCharArray(); + + /* + * Is the server ready to serve? + */ + volatile static boolean serverReady = false; + + /* + * Turn on SSL debugging? + */ + static boolean debug = false; + + /* + * Define the server side of the test. + * + * If the server prematurely exits, serverReady will be set to true + * to avoid infinite hangs. + */ + void doServerSide() throws Exception { + SSLContext context = generateSSLContext(false); + SSLServerSocketFactory sslssf = context.getServerSocketFactory(); + SSLServerSocket sslServerSocket = + (SSLServerSocket)sslssf.createServerSocket(serverPort); + serverPort = sslServerSocket.getLocalPort(); + + /* + * Signal Client, we're ready for his connect. + */ + serverReady = true; + + SSLSocket sslSocket = (SSLSocket)sslServerSocket.accept(); + try { + sslSocket.setSoTimeout(5000); + sslSocket.setSoLinger(true, 5); + + InputStream sslIS = sslSocket.getInputStream(); + OutputStream sslOS = sslSocket.getOutputStream(); + + sslIS.read(); + sslOS.write('A'); + sslOS.flush(); + + throw new Exception("EC curve secp224k1 should be disabled"); + } catch (SSLHandshakeException she) { + // expected exception: no cipher suites in common + System.out.println("Expected exception: " + she); + } finally { + sslSocket.close(); + sslServerSocket.close(); + } + } + + /* + * Define the client side of the test. + * + * If the server prematurely exits, serverReady will be set to true + * to avoid infinite hangs. + */ + void doClientSide() throws Exception { + + /* + * Wait for server to get started. + */ + while (!serverReady) { + Thread.sleep(50); + } + + SSLContext context = generateSSLContext(true); + SSLSocketFactory sslsf = context.getSocketFactory(); + + SSLSocket sslSocket = + (SSLSocket)sslsf.createSocket("localhost", serverPort); + + try { + sslSocket.setSoTimeout(5000); + sslSocket.setSoLinger(true, 5); + + InputStream sslIS = sslSocket.getInputStream(); + OutputStream sslOS = sslSocket.getOutputStream(); + + sslOS.write('B'); + sslOS.flush(); + sslIS.read(); + + throw new Exception("EC curve secp224k1 should be disabled"); + } catch (SSLHandshakeException she) { + // expected exception: Received fatal alert + System.out.println("Expected exception: " + she); + } finally { + sslSocket.close(); + } + } + + /* + * ============================================================= + * The remainder is just support stuff + */ + private static String tmAlgorithm; // trust manager + + private static void parseArguments(String[] args) { + tmAlgorithm = args[0]; + } + + private static SSLContext generateSSLContext(boolean isClient) + throws Exception { + + // generate certificate from cert string + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + + // create a key store + KeyStore ks = KeyStore.getInstance("JKS"); + ks.load(null, null); + + // import the trused cert + ByteArrayInputStream is = + new ByteArrayInputStream(trustedCertStr.getBytes()); + Certificate trusedCert = cf.generateCertificate(is); + is.close(); + + ks.setCertificateEntry("Export Signer", trusedCert); + + String[] certStrs = null; + String[] keyStrs = null; + if (isClient) { + certStrs = clientCerts; + keyStrs = clientKeys; + } else { + certStrs = serverCerts; + keyStrs = serverKeys; + } + + for (int i = 0; i < certStrs.length; i++) { + // generate the private key. + String keySpecStr = keyStrs[i]; + PKCS8EncodedKeySpec priKeySpec = new PKCS8EncodedKeySpec( + Base64.getMimeDecoder().decode(keySpecStr)); + KeyFactory kf = KeyFactory.getInstance("EC"); + ECPrivateKey priKey = + (ECPrivateKey)kf.generatePrivate(priKeySpec); + + // generate certificate chain + String keyCertStr = certStrs[i]; + is = new ByteArrayInputStream(keyCertStr.getBytes()); + Certificate keyCert = cf.generateCertificate(is); + is.close(); + + Certificate[] chain = new Certificate[2]; + chain[0] = keyCert; + chain[1] = trusedCert; + + // import the key entry. + ks.setKeyEntry("key-entry-" + i, priKey, passphrase, chain); + } + + // create SSL context + TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmAlgorithm); + tmf.init(ks); + + SSLContext ctx = SSLContext.getInstance("TLS"); + KeyManagerFactory kmf = KeyManagerFactory.getInstance("NewSunX509"); + kmf.init(ks, passphrase); + + ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); + ks = null; + + return ctx; + } + + // use any free port by default + volatile int serverPort = 0; + + volatile Exception serverException = null; + volatile Exception clientException = null; + + public static void main(String[] args) throws Exception { + if (debug) { + System.setProperty("javax.net.debug", "all"); + } + + /* + * Get the customized arguments. + */ + parseArguments(args); + + /* + * Start the tests. + */ + new ECCurvesconstraints(); + } + + Thread clientThread = null; + Thread serverThread = null; + + /* + * Primary constructor, used to drive remainder of the test. + * + * Fork off the other side, then do your work. + */ + ECCurvesconstraints() throws Exception { + try { + if (separateServerThread) { + startServer(true); + startClient(false); + } else { + startClient(true); + startServer(false); + } + } catch (Exception e) { + // swallow for now. Show later + } + + /* + * Wait for other side to close down. + */ + if (separateServerThread) { + serverThread.join(); + } else { + clientThread.join(); + } + + /* + * When we get here, the test is pretty much over. + * Which side threw the error? + */ + Exception local; + Exception remote; + String whichRemote; + + if (separateServerThread) { + remote = serverException; + local = clientException; + whichRemote = "server"; + } else { + remote = clientException; + local = serverException; + whichRemote = "client"; + } + + /* + * If both failed, return the curthread's exception, but also + * print the remote side Exception + */ + if ((local != null) && (remote != null)) { + System.out.println(whichRemote + " also threw:"); + remote.printStackTrace(); + System.out.println(); + throw local; + } + + if (remote != null) { + throw remote; + } + + if (local != null) { + throw local; + } + } + + void startServer(boolean newThread) throws Exception { + if (newThread) { + serverThread = new Thread() { + public void run() { + try { + doServerSide(); + } catch (Exception e) { + /* + * Our server thread just died. + * + * Release the client, if not active already... + */ + System.err.println("Server died, because of " + e); + serverReady = true; + serverException = e; + } + } + }; + serverThread.start(); + } else { + try { + doServerSide(); + } catch (Exception e) { + serverException = e; + } finally { + serverReady = true; + } + } + } + + void startClient(boolean newThread) throws Exception { + if (newThread) { + clientThread = new Thread() { + public void run() { + try { + doClientSide(); + } catch (Exception e) { + /* + * Our client thread just died. + */ + System.err.println("Client died, because of " + e); + clientException = e; + } + } + }; + clientThread.start(); + } else { + try { + doClientSide(); + } catch (Exception e) { + clientException = e; + } + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/javax/swing/plaf/basic/BasicScrollPaneUI/8166591/TooMuchWheelRotationEventsTest.java Mon Jan 23 16:30:43 2017 +0000 @@ -0,0 +1,188 @@ +/* + * Copyright (c) 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.awt.Color; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import javax.swing.BoxLayout; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTextArea; +import javax.swing.SwingUtilities; + +/* + * @test + * @bug 8166591 + * @summary [macos 10.12] Trackpad scrolling of text on OS X 10.12 Sierra + * is very fast (Trackpad, Retina only) + * @run main/manual/othervm TooMuchWheelRotationEventsTest + */ +public class TooMuchWheelRotationEventsTest { + + private static volatile boolean testResult = false; + private static volatile CountDownLatch countDownLatch; + private static final String INSTRUCTIONS = "INSTRUCTIONS:\n" + + "Try to check the issue on Mac OS X 10.12 Sierra with trackpad" + + " on Retina display.\n" + + "\n" + + "If the trackpad is not supported, press PASS\n" + + "\n" + + "Use the trackpad to slightly scroll the JTextArea horizontally and vertically.\n" + + "If the text area is scrolled too fast press FAIL, else press PASS."; + + public static void main(String args[]) throws Exception { + countDownLatch = new CountDownLatch(1); + + SwingUtilities.invokeLater(TooMuchWheelRotationEventsTest::createUI); + countDownLatch.await(15, TimeUnit.MINUTES); + + if (!testResult) { + throw new RuntimeException("Test fails!"); + } + } + + private static void createUI() { + + final JFrame mainFrame = new JFrame("Trackpad scrolling test"); + GridBagLayout layout = new GridBagLayout(); + JPanel mainControlPanel = new JPanel(layout); + JPanel resultButtonPanel = new JPanel(layout); + + GridBagConstraints gbc = new GridBagConstraints(); + + JPanel testPanel = createTestPanel(); + + gbc.gridx = 0; + gbc.gridy = 0; + gbc.fill = GridBagConstraints.HORIZONTAL; + mainControlPanel.add(testPanel, gbc); + + JTextArea instructionTextArea = new JTextArea(); + instructionTextArea.setText(INSTRUCTIONS); + instructionTextArea.setEditable(false); + instructionTextArea.setBackground(Color.white); + + gbc.gridx = 0; + gbc.gridy = 1; + gbc.fill = GridBagConstraints.HORIZONTAL; + mainControlPanel.add(instructionTextArea, gbc); + + JButton passButton = new JButton("Pass"); + passButton.setActionCommand("Pass"); + passButton.addActionListener((ActionEvent e) -> { + testResult = true; + mainFrame.dispose(); + countDownLatch.countDown(); + + }); + + JButton failButton = new JButton("Fail"); + failButton.setActionCommand("Fail"); + failButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + mainFrame.dispose(); + countDownLatch.countDown(); + } + }); + + gbc.gridx = 0; + gbc.gridy = 0; + resultButtonPanel.add(passButton, gbc); + + gbc.gridx = 1; + gbc.gridy = 0; + resultButtonPanel.add(failButton, gbc); + + gbc.gridx = 0; + gbc.gridy = 2; + mainControlPanel.add(resultButtonPanel, gbc); + + mainFrame.add(mainControlPanel); + mainFrame.pack(); + + mainFrame.addWindowListener(new WindowAdapter() { + + @Override + public void windowClosing(WindowEvent e) { + mainFrame.dispose(); + countDownLatch.countDown(); + } + }); + mainFrame.setVisible(true); + } + + private static JPanel createTestPanel() { + JPanel panel = new JPanel(); + panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); + JTextArea textArea = new JTextArea(20, 20); + textArea.setText(getLongString()); + JScrollPane scrollPane = new JScrollPane(textArea); + panel.add(scrollPane); + return panel; + } + + private static String getLongString() { + + String lowCaseString = getLongString('a', 'z'); + String upperCaseString = getLongString('A', 'Z'); + String digitsString = getLongString('0', '9'); + + int repeat = 30; + StringBuilder lowCaseBuilder = new StringBuilder(); + StringBuilder upperCaseBuilder = new StringBuilder(); + StringBuilder digitsBuilder = new StringBuilder(); + + for (int i = 0; i < repeat; i++) { + lowCaseBuilder.append(lowCaseString).append(' '); + upperCaseBuilder.append(upperCaseString).append(' '); + digitsBuilder.append(digitsString).append(' '); + } + + StringBuilder builder = new StringBuilder(); + for (int i = 0; i < 200; i++) { + builder.append(upperCaseBuilder).append('\n') + .append(lowCaseBuilder).append('\n') + .append(digitsBuilder).append("\n\n\n"); + } + + return builder.toString(); + } + + private static String getLongString(char c1, char c2) { + + char[] chars = new char[c2 - c1 + 1]; + for (char i = c1; i <= c2; i++) { + chars[i - c1] = i; + } + return new String(chars); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/javax/xml/crypto/dsig/SecureValidationPolicy.java Mon Jan 23 16:30:43 2017 +0000 @@ -0,0 +1,73 @@ +/* + * Copyright (c) 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. + */ + +/** + * @test + * @bug 8151893 + * @summary Tests for the jdk.xml.dsig.secureValidationPolicy security property + * @modules java.xml.crypto/org.jcp.xml.dsig.internal.dom + */ + +import java.security.Security; +import java.util.List; +import java.util.Arrays; +import org.jcp.xml.dsig.internal.dom.Policy; + +public class SecureValidationPolicy { + + public static void main(String[] args) throws Exception { + + List<String> restrictedSchemes = Arrays.asList("file:/tmp/foo", + "http://java.com", "https://java.com"); + List<String> restrictedAlgs = Arrays.asList( + "http://www.w3.org/TR/1999/REC-xslt-19991116", + "http://www.w3.org/2001/04/xmldsig-more#rsa-md5", + "http://www.w3.org/2001/04/xmldsig-more#hmac-md5", + "http://www.w3.org/2001/04/xmldsig-more#md5"); + + // Test expected defaults + System.out.println("Testing defaults"); + if (!Policy.restrictNumTransforms(6)) { + throw new Exception("maxTransforms not enforced"); + } + if (!Policy.restrictNumReferences(31)) { + throw new Exception("maxReferences not enforced"); + } + for (String scheme : restrictedSchemes) { + if (!Policy.restrictReferenceUriScheme(scheme)) { + throw new Exception(scheme + " scheme not restricted"); + } + } + for (String alg : restrictedAlgs) { + if (!Policy.restrictAlg(alg)) { + throw new Exception(alg + " alg not restricted"); + } + } + if (!Policy.restrictDuplicateIds()) { + throw new Exception("noDuplicateIds not enforced"); + } + if (!Policy.restrictRetrievalMethodLoops()) { + throw new Exception("noRetrievalMethodLoops not enforced"); + } + } +}
--- a/test/lib/testlibrary/jdk/testlibrary/JarUtils.java Fri Jan 13 17:09:28 2017 +0000 +++ b/test/lib/testlibrary/jdk/testlibrary/JarUtils.java Mon Jan 23 16:30:43 2017 +0000 @@ -25,6 +25,7 @@ import java.io.File; import java.io.FileInputStream; +import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.nio.file.Path; @@ -43,7 +44,8 @@ /** - * Create jar file with specified files from specified location. + * Create jar file with specified files. If a specified file does not exist, + * a new jar entry will be created with the file name itself as the content. */ public static void createJar(String dest, Path filesLocation, String... fileNames) throws IOException { @@ -63,6 +65,8 @@ } try (FileInputStream fis = new FileInputStream(file)) { Utils.transferBetweenStreams(fis, jos); + } catch (FileNotFoundException e) { + jos.write(fileName.getBytes()); } } } @@ -78,7 +82,17 @@ } /** - * Add specified files to existing jar file. + * Add or remove specified files to existing jar file. If a specified file + * to be updated or added does not exist, the jar entry will be created + * with the file name itself as the content. + * + * @param src the original jar file name + * @param dest the new jar file name + * @param files the files to update. The list is broken into 2 groups + * by a "-" string. The files before in the 1st group will + * be either updated or added. The files in the 2nd group + * will be removed. If no "-" exists, all files belong to + * the 1st group. */ public static void updateJar(String src, String dest, String... files) throws IOException { @@ -94,8 +108,11 @@ JarEntry entry = entries.nextElement(); String name = entry.getName(); boolean found = false; + boolean update = true; for (String file : files) { - if (name.equals(file)) { + if (file.equals("-")) { + update = false; + } else if (name.equals(file)) { updatedFiles.add(file); found = true; break; @@ -103,11 +120,18 @@ } if (found) { + if (update) { System.out.println(String.format("Updating %s with %s", dest, name)); jos.putNextEntry(new JarEntry(name)); try (FileInputStream fis = new FileInputStream(name)) { Utils.transferBetweenStreams(fis, jos); + } catch (FileNotFoundException e) { + jos.write(name.getBytes()); + } + } else { + System.out.println(String.format("Removing %s from %s", + name, dest)); } } else { System.out.println(String.format("Copying %s to %s", @@ -121,12 +145,17 @@ // append new files for (String file : files) { + if (file.equals("-")) { + break; + } if (!updatedFiles.contains(file)) { System.out.println(String.format("Adding %s with %s", dest, file)); jos.putNextEntry(new JarEntry(file)); try (FileInputStream fis = new FileInputStream(file)) { Utils.transferBetweenStreams(fis, jos); + } catch (FileNotFoundException e) { + jos.write(file.getBytes()); } } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/sun/reflect/ReflectionFactory/ReflectionFactoryTest.java Mon Jan 23 16:30:43 2017 +0000 @@ -0,0 +1,341 @@ +/* + * Copyright (c) 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.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.Externalizable; +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectInputStream; +import java.io.ObjectOutput; +import java.io.ObjectOutputStream; +import java.io.OptionalDataException; +import java.io.Serializable; +import java.lang.invoke.MethodHandle; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; + +import sun.reflect.ReflectionFactory; + +import org.testng.Assert; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; +import org.testng.annotations.DataProvider; +import org.testng.TestNG; + +/* + * @test + * @bug 8137058 8164908 8168980 + * @run testng ReflectionFactoryTest + * @run testng/othervm/policy=security.policy ReflectionFactoryTest + * @summary Basic test for the unsupported ReflectionFactory + */ + +public class ReflectionFactoryTest { + + // Initialized by init() + static ReflectionFactory factory; + + @DataProvider(name = "ClassConstructors") + static Object[][] classConstructors() { + return new Object[][] { + {Object.class}, + {Foo.class}, + {Bar.class}, + }; + } + + @BeforeClass + static void init() { + factory = ReflectionFactory.getReflectionFactory(); + } + + /** + * Test that the correct Constructor is selected and run. + * @param type type of object to create + * @throws NoSuchMethodException - error + * @throws InstantiationException - error + * @throws IllegalAccessException - error + * @throws InvocationTargetException - error + */ + @Test(dataProvider="ClassConstructors") + static void testConstructor(Class<?> type) + throws NoSuchMethodException, InstantiationException, + IllegalAccessException, InvocationTargetException + { + @SuppressWarnings("unchecked") + Constructor<?> c = factory.newConstructorForSerialization(type); + + Object o = c.newInstance(); + Assert.assertEquals(o.getClass(), type, "Instance is wrong type"); + if (o instanceof Foo) { + Foo foo = (Foo)o; + foo.check(); + } + } + + @DataProvider(name = "NonSerialConstructors") + static Object[][] constructors() throws NoSuchMethodException { + return new Object[][] { + {Foo.class, Object.class.getDeclaredConstructor()}, + {Foo.class, Foo.class.getDeclaredConstructor()}, + {Baz.class, Object.class.getDeclaredConstructor()}, + {Baz.class, Foo.class.getDeclaredConstructor()}, + {Baz.class, Baz.class.getDeclaredConstructor()} + }; + } + + /** + * Tests that the given Constructor, in the hierarchy, is run. + */ + @Test(dataProvider="NonSerialConstructors") + static void testNonSerializableConstructor(Class<?> cl, + Constructor<?> constructorToCall) + throws ReflectiveOperationException + { + @SuppressWarnings("unchecked") + Constructor<?> c = factory.newConstructorForSerialization(cl, + constructorToCall); + + Object o = c.newInstance(); + Assert.assertEquals(o.getClass(), cl, "Instance is wrong type"); + + int expectedFoo = 0; + int expectedBaz = 0; + if (constructorToCall.getName().equals("ReflectionFactoryTest$Foo")) { + expectedFoo = 1; + } else if (constructorToCall.getName().equals("ReflectionFactoryTest$Baz")) { + expectedFoo = 1; + expectedBaz = 4; + } + + Assert.assertEquals(((Foo)o).foo(), expectedFoo); + if (o instanceof Baz) { + Assert.assertEquals(((Baz)o).baz(), expectedBaz); + } + } + + static class Foo { + private int foo; + public Foo() { + this.foo = 1; + } + + public String toString() { + return "foo: " + foo; + } + + public void check() { + int expectedFoo = 1; + Assert.assertEquals(foo, expectedFoo, "foo() constructor not run"); + } + + public int foo() { return foo; } + } + + static class Bar extends Foo implements Serializable { + private static final long serialVersionUID = 3L; + + private int bar; + public Bar() { + this.bar = 1; + } + + public String toString() { + return super.toString() + ", bar: " + bar; + } + + public void check() { + super.check(); + int expectedBar = 0; + Assert.assertEquals(bar, expectedBar, "bar() constructor not run"); + } + } + + static class Baz extends Foo { + private static final long serialVersionUID = 4L; + + private final int baz; + public Baz() { this.baz = 4; } + public int baz() { return baz; } + } + + /** + * Test newConstructorForExternalization returns the constructor and it can be called. + * @throws NoSuchMethodException - error + * @throws InstantiationException - error + * @throws IllegalAccessException - error + * @throws InvocationTargetException - error + */ + @Test + static void newConstructorForExternalization() + throws NoSuchMethodException, InstantiationException, + IllegalAccessException, InvocationTargetException { + Constructor<?> cons = factory.newConstructorForExternalization(Ext.class); + Ext ext = (Ext)cons.newInstance(); + Assert.assertEquals(ext.ext, 1, "Constructor not run"); + } + + static class Ext implements Externalizable { + private static final long serialVersionUID = 1L; + + int ext; + + public Ext() { + ext = 1; + } + + @Override + public void writeExternal(ObjectOutput out) throws IOException {} + + @Override + public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {} + } + + @Test + static void testReadWriteObjectForSerialization() throws Throwable { + MethodHandle readObjectMethod = factory.readObjectForSerialization(Ser.class); + Assert.assertNotNull(readObjectMethod, "readObjectMethod not found"); + + MethodHandle readObjectNoDataMethod = factory.readObjectNoDataForSerialization(Ser.class); + Assert.assertNotNull(readObjectNoDataMethod, "readObjectNoDataMethod not found"); + + MethodHandle writeObjectMethod = factory.writeObjectForSerialization(Ser.class); + Assert.assertNotNull(writeObjectMethod, "writeObjectMethod not found"); + + MethodHandle readResolveMethod = factory.readResolveForSerialization(Ser.class); + Assert.assertNotNull(readResolveMethod, "readResolveMethod not found"); + + MethodHandle writeReplaceMethod = factory.writeReplaceForSerialization(Ser.class); + Assert.assertNotNull(writeReplaceMethod, "writeReplaceMethod not found"); + + byte[] data = null; + try (ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(baos)) { + Ser ser = new Ser(); + + writeReplaceMethod.invoke(ser); + Assert.assertTrue(ser.writeReplaceCalled, "writeReplace not called"); + Assert.assertFalse(ser.writeObjectCalled, "writeObject should not have been called"); + + writeObjectMethod.invoke(ser, oos); + Assert.assertTrue(ser.writeReplaceCalled, "writeReplace should have been called"); + Assert.assertTrue(ser.writeObjectCalled, "writeObject not called"); + oos.flush(); + data = baos.toByteArray(); + } + + try (ByteArrayInputStream bais = new ByteArrayInputStream(data); + ObjectInputStream ois = new ObjectInputStream(bais)) { + Ser ser2 = new Ser(); + + readObjectMethod.invoke(ser2, ois); + Assert.assertTrue(ser2.readObjectCalled, "readObject not called"); + Assert.assertFalse(ser2.readObjectNoDataCalled, "readObjectNoData should not be called"); + Assert.assertFalse(ser2.readResolveCalled, "readResolve should not be called"); + + readObjectNoDataMethod.invoke(ser2, ois); + Assert.assertTrue(ser2.readObjectCalled, "readObject should have been called"); + Assert.assertTrue(ser2.readObjectNoDataCalled, "readObjectNoData not called"); + Assert.assertFalse(ser2.readResolveCalled, "readResolve should not be called"); + + readResolveMethod.invoke(ser2); + Assert.assertTrue(ser2.readObjectCalled, "readObject should have been called"); + Assert.assertTrue(ser2.readObjectNoDataCalled, "readObjectNoData not called"); + Assert.assertTrue(ser2.readResolveCalled, "readResolve not called"); + } + } + + @Test + static void hasStaticInitializer() { + boolean actual = factory.hasStaticInitializerForSerialization(Ser.class); + Assert.assertTrue(actual, "hasStaticInitializerForSerialization is wrong"); + } + + static class Ser implements Serializable { + private static final long serialVersionUID = 2L; + static { + // Define a static class initialization method + } + + boolean readObjectCalled = false; + boolean readObjectNoDataCalled = false; + boolean writeObjectCalled = false; + boolean readResolveCalled = false; + boolean writeReplaceCalled = false; + + public Ser() {} + + private void readObject(ObjectInputStream ois) throws IOException { + Assert.assertFalse(writeObjectCalled, "readObject called too many times"); + readObjectCalled = ois.readBoolean(); + } + + private void readObjectNoData(ObjectInputStream ois) throws IOException { + Assert.assertFalse(readObjectNoDataCalled, "readObjectNoData called too many times"); + readObjectNoDataCalled = true; + } + + private void writeObject(ObjectOutputStream oos) throws IOException { + Assert.assertFalse(writeObjectCalled, "writeObject called too many times"); + writeObjectCalled = true; + oos.writeBoolean(writeObjectCalled); + } + + private Object writeReplace() { + Assert.assertFalse(writeReplaceCalled, "writeReplace called too many times"); + writeReplaceCalled = true; + return this; + } + + private Object readResolve() { + Assert.assertFalse(readResolveCalled, "readResolve called too many times"); + readResolveCalled = true; + return this; + } + } + + /** + * Test the constructor of OptionalDataExceptions. + */ + @Test + static void newOptionalDataException() { + OptionalDataException ode = factory.newOptionalDataExceptionForSerialization(true); + Assert.assertTrue(ode.eof, "eof wrong"); + ode = factory.newOptionalDataExceptionForSerialization(false); + Assert.assertFalse(ode.eof, "eof wrong"); + + } + + + + // Main can be used to run the tests from the command line with only testng.jar. + @SuppressWarnings("raw_types") + @Test(enabled = false) + public static void main(String[] args) { + Class<?>[] testclass = {ReflectionFactoryTest.class}; + TestNG testng = new TestNG(); + testng.setTestClasses(testclass); + testng.run(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/sun/reflect/ReflectionFactory/security.policy Mon Jan 23 16:30:43 2017 +0000 @@ -0,0 +1,11 @@ +// Individual Permissions for ReflectionFactoryTest +grant { + // Permissions needed to run the test + permission java.util.PropertyPermission "*", "read"; + permission java.io.FilePermission "<<ALL FILES>>", "read,write,delete,execute"; + + permission java.lang.reflect.ReflectPermission "suppressAccessChecks"; + permission java.lang.RuntimePermission "accessDeclaredMembers"; + permission java.lang.RuntimePermission "accessClassInPackage.sun.reflect"; + permission java.lang.RuntimePermission "reflectionFactoryAccess"; +};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/sun/rmi/server/UnicastServerRef/FilterUSRTest.java Mon Jan 23 16:30:43 2017 +0000 @@ -0,0 +1,206 @@ +/* + * Copyright (c) 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.InvalidClassException; +import java.io.Serializable; + +import java.rmi.Remote; +import java.rmi.RemoteException; +import java.rmi.UnmarshalException; + +import java.util.Objects; + +import sun.misc.ObjectInputFilter; +import sun.rmi.server.UnicastServerRef; +import sun.rmi.server.UnicastServerRef2; +import sun.rmi.transport.LiveRef; + +import org.testng.Assert; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +/* + * @test + * @modules java.rmi/sun.rmi.registry + * java.rmi/sun.rmi.server + * java.rmi/sun.rmi.transport + * java.rmi/sun.rmi.transport.tcp + * @run testng/othervm FilterUSRTest + * @summary Check objects exported with ObjectInputFilters via internal UnicastServerRef(2) + */ +public class FilterUSRTest { + + /** + * Data to test serialFilter call counts. + * - name + * - Object + * - expected count of calls to checkInput. + * + * @return array of test data + */ + @DataProvider(name = "bindData") + static Object[][] bindObjects() { + Object[][] data = { + {"SimpleString", "SimpleString", 0}, + {"String", new XX("now is the time"), 1}, + {"String[]", new XX(new String[3]), 3}, + {"Long[4]", new XX(new Long[4]), 3}, + {"RejectME", new XX(new RejectME()), -1}, + }; + return data; + } + + /* + * Test exporting an object with a serialFilter using UnicastServerRef.exportObject(). + * Send some objects and check the number of calls to the serialFilter. + */ + @Test(dataProvider = "bindData") + public void UnicastServerRef(String name, Object obj, int expectedFilterCount) throws RemoteException { + try { + RemoteImpl impl = RemoteImpl.create(); + UnicastServerRef ref = new UnicastServerRef(new LiveRef(0), impl.checker); + + Echo client = (Echo) ref.exportObject(impl, null, false); + + int count = client.filterCount(obj); + System.out.printf("count: %d, obj: %s%n", count, obj); + Assert.assertEquals(count, expectedFilterCount, "wrong number of filter calls"); + } catch (RemoteException rex) { + if (expectedFilterCount == -1 && + UnmarshalException.class.equals(rex.getCause().getClass()) && + InvalidClassException.class.equals(rex.getCause().getCause().getClass())) { + return; // normal expected exception + } + rex.printStackTrace(); + Assert.fail("unexpected remote exception", rex); + } catch (Exception ex) { + Assert.fail("unexpected exception", ex); + } + } + + /* + * Test exporting an object with a serialFilter using UnicastServerRef2.exportObject() + * with explicit (but null) SocketFactories. + * Send some objects and check the number of calls to the serialFilter. + */ + @Test(dataProvider = "bindData") + public void UnicastServerRef2(String name, Object obj, int expectedFilterCount) throws RemoteException { + try { + RemoteImpl impl = RemoteImpl.create(); + UnicastServerRef2 ref = new UnicastServerRef2(0, null, null, impl.checker); + + Echo client = (Echo) ref.exportObject(impl, null, false); + + int count = client.filterCount(obj); + System.out.printf("count: %d, obj: %s%n", count, obj); + Assert.assertEquals(count, expectedFilterCount, "wrong number of filter calls"); + } catch (RemoteException rex) { + if (expectedFilterCount == -1 && + UnmarshalException.class.equals(rex.getCause().getClass()) && + InvalidClassException.class.equals(rex.getCause().getCause().getClass())) { + return; // normal expected exception + } + rex.printStackTrace(); + Assert.fail("unexpected remote exception", rex); + } catch (Exception rex) { + Assert.fail("unexpected exception", rex); + } + } + + /** + * A simple Serializable holding an object that is passed by value. + * It and its contents are checked by the filter. + */ + static class XX implements Serializable { + private static final long serialVersionUID = 362498820763181265L; + + final Object obj; + + XX(Object obj) { + this.obj = obj; + } + + public String toString() { + return super.toString() + "//" + Objects.toString(obj); + } + } + + interface Echo extends Remote { + int filterCount(Object obj) throws RemoteException; + } + + /** + * This remote object just counts the calls to the serialFilter + * and returns it. The caller can check the number against + * what was expected for the object passed as an argument. + * A new RemoteImpl is used for each test so the count starts at zero again. + */ + static class RemoteImpl implements Echo { + + private static final long serialVersionUID = 1L; + + transient Checker checker; + + static RemoteImpl create() throws RemoteException { + RemoteImpl impl = new RemoteImpl(new Checker()); + return impl; + } + + private RemoteImpl(Checker checker) throws RemoteException { + this.checker = checker; + } + + public int filterCount(Object obj) throws RemoteException { + return checker.count(); + } + + } + + /** + * A ObjectInputFilter that just counts when it is called. + */ + static class Checker implements ObjectInputFilter { + int count; + + @Override + public Status checkInput(ObjectInputFilter.FilterInfo info) { + if (info.serialClass() == RejectME.class) { + return Status.REJECTED; + } + count++; + return Status.UNDECIDED; + } + + public int count() { + return count; + } + } + + /** + * A class to be rejected by the filter. + */ + static class RejectME implements Serializable { + private static final long serialVersionUID = 2L; + } + +}
--- a/test/sun/security/ec/TestEC.java Fri Jan 13 17:09:28 2017 +0000 +++ b/test/sun/security/ec/TestEC.java Mon Jan 23 16:30:43 2017 +0000 @@ -35,7 +35,7 @@ * @library ../pkcs11/sslecc * @library ../../../java/security/testlibrary * @compile -XDignore.symbol.file TestEC.java - * @run main/othervm TestEC + * @run main/othervm -Djdk.tls.namedGroups="secp256r1,sect193r1" TestEC */ import java.security.NoSuchProviderException;
--- a/test/sun/security/pkcs11/sslecc/ClientJSSEServerJSSE.java Fri Jan 13 17:09:28 2017 +0000 +++ b/test/sun/security/pkcs11/sslecc/ClientJSSEServerJSSE.java Mon Jan 23 16:30:43 2017 +0000 @@ -33,7 +33,8 @@ * @author Andreas Sterbenz * @library .. * @library ../../../../java/security/testlibrary - * @run main/othervm ClientJSSEServerJSSE + * @run main/othervm -Djdk.tls.namedGroups="secp256r1,sect193r1" + * ClientJSSEServerJSSE */ import java.security.*;
--- a/test/sun/security/smartcardio/TestChannel.java Fri Jan 13 17:09:28 2017 +0000 +++ b/test/sun/security/smartcardio/TestChannel.java Mon Jan 23 16:30:43 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -46,6 +46,11 @@ public static void main(String[] args) throws Exception { CardTerminal terminal = getTerminal(args); + if (terminal == null) { + System.out.println("Skipping the test: " + + "no card terminals available"); + return; + } // establish a connection with the card Card card = terminal.connect("T=0");
--- a/test/sun/security/smartcardio/TestConnect.java Fri Jan 13 17:09:28 2017 +0000 +++ b/test/sun/security/smartcardio/TestConnect.java Mon Jan 23 16:30:43 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -39,23 +39,12 @@ public class TestConnect extends Utils { public static void main(String[] args) throws Exception { - TerminalFactory factory = TerminalFactory.getInstance("PC/SC", null, "SunPCSC"); - System.out.println(factory); - - List<CardTerminal> terminals = factory.terminals().list(); - System.out.println("Terminals: " + terminals); - if (terminals.isEmpty()) { - throw new Exception("No card terminals available"); + CardTerminal terminal = getTerminal(args, "SunPCSC"); + if (terminal == null) { + System.out.println("Skipping the test: " + + "no card terminals available"); + return; } - CardTerminal terminal = terminals.get(0); - - if (terminal.isCardPresent() == false) { - System.out.println("*** Insert card"); - if (terminal.waitForCardPresent(20 * 1000) == false) { - throw new Exception("no card available"); - } - } - System.out.println("card present: " + terminal.isCardPresent()); Card card = terminal.connect("*"); System.out.println("card: " + card);
--- a/test/sun/security/smartcardio/TestConnectAgain.java Fri Jan 13 17:09:28 2017 +0000 +++ b/test/sun/security/smartcardio/TestConnectAgain.java Mon Jan 23 16:30:43 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -39,6 +39,11 @@ public static void main(String[] args) throws Exception { CardTerminal terminal = getTerminal(args); + if (terminal == null) { + System.out.println("Skipping the test: " + + "no card terminals available"); + return; + } Card card = terminal.connect("T=0"); CardChannel channel = card.getBasicChannel();
--- a/test/sun/security/smartcardio/TestControl.java Fri Jan 13 17:09:28 2017 +0000 +++ b/test/sun/security/smartcardio/TestControl.java Mon Jan 23 16:30:43 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -40,6 +40,11 @@ public static void main(String[] args) throws Exception { CardTerminal terminal = getTerminal(args); + if (terminal == null) { + System.out.println("Skipping the test: " + + "no card terminals available"); + return; + } // establish a connection with the card Card card = terminal.connect("T=0");
--- a/test/sun/security/smartcardio/TestDefault.java Fri Jan 13 17:09:28 2017 +0000 +++ b/test/sun/security/smartcardio/TestDefault.java Mon Jan 23 16:30:43 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -40,10 +40,12 @@ TerminalFactory factory = TerminalFactory.getDefault(); System.out.println("Type: " + factory.getType()); List<CardTerminal> terminals = factory.terminals().list(); + if (terminals.isEmpty()) { + System.out.println("Skipping the test: " + + "no card terminals available"); + return; + } System.out.println("Terminals: " + terminals); - if (terminals.isEmpty()) { - throw new Exception("no terminals"); - } System.out.println("OK."); }
--- a/test/sun/security/smartcardio/TestDirect.java Fri Jan 13 17:09:28 2017 +0000 +++ b/test/sun/security/smartcardio/TestDirect.java Mon Jan 23 16:30:43 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 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 @@ -40,10 +40,12 @@ public static void main(String[] args) throws Exception { TerminalFactory terminalFactory = TerminalFactory.getDefault(); List<CardTerminal> cardTerminals = terminalFactory.terminals().list(); + if (cardTerminals.isEmpty()) { + System.out.println("Skipping the test: " + + "no card terminals available"); + return; + } System.out.println("Terminals: " + cardTerminals); - if (cardTerminals.isEmpty()) { - throw new Exception("No card terminals available"); - } CardTerminal cardTerminal = cardTerminals.get(0); Card card = cardTerminal.connect("DIRECT"); card.disconnect(true);
--- a/test/sun/security/smartcardio/TestExclusive.java Fri Jan 13 17:09:28 2017 +0000 +++ b/test/sun/security/smartcardio/TestExclusive.java Mon Jan 23 16:30:43 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -44,6 +44,11 @@ public static void main(String[] args) throws Exception { CardTerminal terminal = getTerminal(args); + if (terminal == null) { + System.out.println("Skipping the test: " + + "no card terminals available"); + return; + } // establish a connection with the card Card card = terminal.connect("T=0");
--- a/test/sun/security/smartcardio/TestMultiplePresent.java Fri Jan 13 17:09:28 2017 +0000 +++ b/test/sun/security/smartcardio/TestMultiplePresent.java Mon Jan 23 16:30:43 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -40,7 +40,12 @@ public static void main(String[] args) throws Exception { Utils.setLibrary(args); - TerminalFactory factory = TerminalFactory.getInstance("PC/SC", null); + TerminalFactory factory = Utils.getTerminalFactory(null); + if (factory == null) { + System.out.println("Skipping the test: " + + "no card terminals available"); + return; + } System.out.println(factory); CardTerminals terminals = factory.terminals(); @@ -49,7 +54,9 @@ boolean multipleReaders = true; if (list.size() < 2) { if (list.isEmpty()) { - throw new Exception("no terminals"); + System.out.println("Skipping the test: " + + "no card terminals available"); + return; } System.out.println("Only one reader present, using simplified test"); multipleReaders = false;
--- a/test/sun/security/smartcardio/TestPresent.java Fri Jan 13 17:09:28 2017 +0000 +++ b/test/sun/security/smartcardio/TestPresent.java Mon Jan 23 16:30:43 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -34,7 +34,7 @@ import javax.smartcardio.CardTerminal; import javax.smartcardio.TerminalFactory; -public class TestPresent { +public class TestPresent extends Utils { private static class Timer { private long time = System.currentTimeMillis(); @@ -66,15 +66,12 @@ } public static void main(String[] args) throws Exception { - TerminalFactory factory = TerminalFactory.getInstance("PC/SC", null); - System.out.println(factory); - - List<CardTerminal> terminals = factory.terminals().list(); - System.out.println("Terminals: " + terminals); - if (terminals.isEmpty()) { - throw new Exception("No card terminals available"); + CardTerminal terminal = getTerminal(args); + if (terminal == null) { + System.out.println("Skipping the test: " + + "no card terminals available"); + return; } - CardTerminal terminal = terminals.get(0); while (terminal.isCardPresent()) { System.out.println("*** Remove card!");
--- a/test/sun/security/smartcardio/TestTransmit.java Fri Jan 13 17:09:28 2017 +0000 +++ b/test/sun/security/smartcardio/TestTransmit.java Mon Jan 23 16:30:43 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -48,6 +48,11 @@ public static void main(String[] args) throws Exception { CardTerminal terminal = getTerminal(args); + if (terminal == null) { + System.out.println("Skipping the test: " + + "no card terminals available"); + return; + } Card card = terminal.connect("T=0"); CardChannel channel = card.getBasicChannel();
--- a/test/sun/security/smartcardio/Utils.java Fri Jan 13 17:09:28 2017 +0000 +++ b/test/sun/security/smartcardio/Utils.java Mon Jan 23 16:30:43 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -27,6 +27,7 @@ import java.io.StringReader; import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.security.NoSuchAlgorithmException; import java.util.Arrays; import java.util.List; import javax.smartcardio.CardTerminal; @@ -43,26 +44,59 @@ } } + static TerminalFactory getTerminalFactory(String provName) throws Exception { + try { + TerminalFactory factory = (provName == null) + ? TerminalFactory.getInstance("PC/SC", null) + : TerminalFactory.getInstance("PC/SC", null, provName); + System.out.println(factory); + return factory; + } catch (NoSuchAlgorithmException e) { + Throwable cause = e.getCause(); + if (cause != null && cause.getMessage().startsWith("PC/SC not available")) { + return null; + } + throw e; + } + } + static CardTerminal getTerminal(String[] args) throws Exception { + return getTerminal(args, null); + } + + static CardTerminal getTerminal(String[] args, String provider) throws Exception { setLibrary(args); - TerminalFactory factory = TerminalFactory.getInstance("PC/SC", null); - System.out.println(factory); + try { + TerminalFactory factory = (provider == null) + ? TerminalFactory.getInstance("PC/SC", null) + : TerminalFactory.getInstance("PC/SC", null, provider); + System.out.println(factory); + + List<CardTerminal> terminals = factory.terminals().list(); + System.out.println("Terminals: " + terminals); + if (terminals.isEmpty()) { + return null; + } + CardTerminal terminal = terminals.get(0); - List<CardTerminal> terminals = factory.terminals().list(); - System.out.println("Terminals: " + terminals); - if (terminals.isEmpty()) { - throw new Exception("No card terminals available"); + if (terminal.isCardPresent() == false) { + System.out.println("*** Insert card"); + if (terminal.waitForCardPresent(20 * 1000) == false) { + throw new Exception("no card available"); + } + } + System.out.println("card present: " + terminal.isCardPresent()); + + return terminal; + + } catch (NoSuchAlgorithmException e) { + Throwable cause = e.getCause(); + if (cause != null && cause.getMessage().startsWith("PC/SC not available")) { + return null; + } + throw e; } - CardTerminal terminal = terminals.get(0); - - if (terminal.isCardPresent() == false) { - System.out.println("*** Insert card"); - if (terminal.waitForCardPresent(20 * 1000) == false) { - throw new Exception("no card available"); - } - } - return terminal; } static final byte[] C1 = parse("00 A4 04 00 07 A0 00 00 00 62 81 01 00");
--- a/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/X509TrustManagerImpl/PKIXExtendedTM.java Fri Jan 13 17:09:28 2017 +0000 +++ b/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/X509TrustManagerImpl/PKIXExtendedTM.java Mon Jan 23 16:30:43 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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 @@ -28,9 +28,12 @@ /* * @test - * @bug 6916074 + * @bug 6916074 8170131 * @summary Add support for TLS 1.2 - * @run main/othervm PKIXExtendedTM + * @run main/othervm PKIXExtendedTM 0 + * @run main/othervm PKIXExtendedTM 1 + * @run main/othervm PKIXExtendedTM 2 + * @run main/othervm PKIXExtendedTM 3 */ import java.net.*; @@ -42,6 +45,7 @@ import java.security.KeyFactory; import java.security.cert.Certificate; import java.security.cert.CertificateFactory; +import java.security.cert.CertPathValidatorException; import java.security.spec.*; import java.security.interfaces.*; import java.math.BigInteger; @@ -792,20 +796,85 @@ volatile Exception serverException = null; volatile Exception clientException = null; + static class Test { + String tlsDisAlgs; + String certPathDisAlgs; + boolean fail; + Test(String tlsDisAlgs, String certPathDisAlgs, boolean fail) { + this.tlsDisAlgs = tlsDisAlgs; + this.certPathDisAlgs = certPathDisAlgs; + this.fail = fail; + } + } + + static Test[] tests = { + // MD5 is used in this test case, don't disable MD5 algorithm. + new Test( + "SSLv3, RC4, DH keySize < 768", + "MD2, RSA keySize < 1024", + false), + // Disable MD5 but only if cert chains back to public root CA, should + // pass because the MD5 cert in this test case is issued by test CA + new Test( + "SSLv3, RC4, DH keySize < 768", + "MD2, MD5 jdkCA, RSA keySize < 1024", + false), + // Disable MD5 alg via TLS property and expect failure + new Test( + "SSLv3, MD5, RC4, DH keySize < 768", + "MD2, RSA keySize < 1024", + true), + // Disable MD5 alg via certpath property and expect failure + new Test( + "SSLv3, RC4, DH keySize < 768", + "MD2, MD5, RSA keySize < 1024", + true), + }; + public static void main(String args[]) throws Exception { - // MD5 is used in this test case, don't disable MD5 algorithm. + if (args.length != 1) { + throw new Exception("Incorrect number of arguments"); + } + Test test = tests[Integer.parseInt(args[0])]; + Security.setProperty("jdk.tls.disabledAlgorithms", test.tlsDisAlgs); Security.setProperty("jdk.certpath.disabledAlgorithms", - "MD2, RSA keySize < 1024"); - Security.setProperty("jdk.tls.disabledAlgorithms", - "SSLv3, RC4, DH keySize < 768"); + test.certPathDisAlgs); - if (debug) + if (debug) { System.setProperty("javax.net.debug", "all"); + } /* * Start the tests. */ - new PKIXExtendedTM(); + try { + new PKIXExtendedTM(); + if (test.fail) { + throw new Exception("Expected MD5 certificate to be blocked"); + } + } catch (Exception e) { + if (test.fail) { + // find expected cause + boolean correctReason = false; + Throwable cause = e.getCause(); + while (cause != null) { + if (cause instanceof CertPathValidatorException) { + CertPathValidatorException cpve = + (CertPathValidatorException)cause; + if (cpve.getReason() == CertPathValidatorException.BasicReason.ALGORITHM_CONSTRAINED) { + correctReason = true; + break; + } + } + cause = cause.getCause(); + } + if (!correctReason) { + throw new Exception("Unexpected exception", e); + } + } else { + throw e; + } + } } Thread clientThread = null;
--- a/test/sun/security/ssl/javax/net/ssl/SSLParameters/UseCipherSuitesOrder.java Fri Jan 13 17:09:28 2017 +0000 +++ b/test/sun/security/ssl/javax/net/ssl/SSLParameters/UseCipherSuitesOrder.java Mon Jan 23 16:30:43 2017 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 @@ -31,7 +31,7 @@ * @bug 7188657 * @summary There should be a way to reorder the JSSE ciphers * @run main/othervm UseCipherSuitesOrder - * TLS_RSA_WITH_AES_128_CBC_SHA,SSL_RSA_WITH_3DES_EDE_CBC_SHA + * TLS_RSA_WITH_AES_128_CBC_SHA,TLS_DHE_RSA_WITH_AES_128_CBC_SHA */ import java.io.*;
--- a/test/sun/security/ssl/sanity/interop/ClientJSSEServerJSSE.java Fri Jan 13 17:09:28 2017 +0000 +++ b/test/sun/security/ssl/sanity/interop/ClientJSSEServerJSSE.java Mon Jan 23 16:30:43 2017 +0000 @@ -26,7 +26,8 @@ * @bug 4496785 * @summary Verify that all ciphersuites work in all configurations * @author Andreas Sterbenz - * @run main/othervm/timeout=300 ClientJSSEServerJSSE + * @run main/othervm/timeout=300 -Djdk.tls.namedGroups="secp256r1,secp192r1" + * ClientJSSEServerJSSE */ import java.security.Security;
--- a/test/sun/security/tools/jarsigner/TimestampCheck.java Fri Jan 13 17:09:28 2017 +0000 +++ b/test/sun/security/tools/jarsigner/TimestampCheck.java Mon Jan 23 16:30:43 2017 +0000 @@ -22,25 +22,31 @@ */ import com.sun.net.httpserver.*; -import java.io.BufferedReader; import java.io.ByteArrayOutputStream; +import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; -import java.io.InputStreamReader; import java.io.OutputStream; import java.math.BigInteger; import java.net.InetSocketAddress; +import java.nio.file.Files; +import java.nio.file.Paths; import java.security.KeyStore; import java.security.PrivateKey; import java.security.Signature; import java.security.cert.Certificate; import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.Arrays; import java.util.Calendar; +import java.util.List; import java.util.jar.JarEntry; import java.util.jar.JarFile; import sun.misc.IOUtils; +import jdk.testlibrary.*; +import jdk.testlibrary.JarUtils; import sun.security.pkcs.ContentInfo; import sun.security.pkcs.PKCS7; import sun.security.pkcs.PKCS9Attribute; @@ -52,11 +58,22 @@ import sun.security.x509.AlgorithmId; import sun.security.x509.X500Name; +/* + * @test + * @bug 6543842 6543440 6939248 8009636 8024302 8163304 8169911 8169688 + * @summary checking response of timestamp + * @modules java.base/sun.security.pkcs + * java.base/sun.security.timestamp + * java.base/sun.security.x509 + * java.base/sun.security.util + * java.base/sun.security.tools.keytool + * @library /lib/testlibrary + * @run main/timeout=600 TimestampCheck + */ public class TimestampCheck { - static final String TSKS = "tsks"; - static final String JAR = "old.jar"; - static final String defaultPolicyId = "2.3.4.5"; + static final String defaultPolicyId = "2.3.4"; + static String host = null; static class Handler implements HttpHandler, AutoCloseable { @@ -75,11 +92,7 @@ t.getRequestBody().read(input); try { - int path = 0; - if (t.getRequestURI().getPath().length() > 1) { - path = Integer.parseInt( - t.getRequestURI().getPath().substring(1)); - } + String path = t.getRequestURI().getPath().substring(1); byte[] output = sign(input, path); Headers out = t.getResponseHeaders(); out.set("Content-Type", "application/timestamp-reply"); @@ -97,24 +110,9 @@ /** * @param input The data to sign * @param path different cases to simulate, impl on URL path - * 0: normal - * 1: Missing nonce - * 2: Different nonce - * 3: Bad digets octets in messageImprint - * 4: Different algorithmId in messageImprint - * 5: whole chain in cert set - * 6: extension is missing - * 7: extension is non-critical - * 8: extension does not have timestamping - * 9: no cert in response - * 10: normal - * 11: always return default policy id - * 12: normal - * otherwise: normal * @returns the signed */ - byte[] sign(byte[] input, int path) throws Exception { - // Read TSRequest + byte[] sign(byte[] input, String path) throws Exception { DerValue value = new DerValue(input); System.err.println("\nIncoming Request\n==================="); System.err.println("Version: " + value.data.getInteger()); @@ -138,36 +136,35 @@ } } - // Write TSResponse System.err.println("\nResponse\n==================="); - KeyStore ks = KeyStore.getInstance("JKS"); - try (FileInputStream fis = new FileInputStream(keystore)) { - ks.load(fis, "changeit".toCharArray()); + FileInputStream is = new FileInputStream(keystore); + KeyStore ks = KeyStore.getInstance("JCEKS"); + ks.load(is, "changeit".toCharArray()); + is.close(); + + String alias = "ts"; + if (path.startsWith("bad") || path.equals("weak")) { + alias = "ts" + path; } - String alias = "ts"; - if (path == 6) alias = "tsbad1"; - if (path == 7) alias = "tsbad2"; - if (path == 8) alias = "tsbad3"; - - if (path == 11) { + if (path.equals("diffpolicy")) { policyId = new ObjectIdentifier(defaultPolicyId); } DerOutputStream statusInfo = new DerOutputStream(); statusInfo.putInteger(0); - DerOutputStream token = new DerOutputStream(); AlgorithmId[] algorithms = {aid}; Certificate[] chain = ks.getCertificateChain(alias); - X509Certificate[] signerCertificateChain = null; + X509Certificate[] signerCertificateChain; X509Certificate signer = (X509Certificate)chain[0]; - if (path == 5) { // Only case 5 uses full chain + + if (path.equals("fullchain")) { // Only case 5 uses full chain signerCertificateChain = new X509Certificate[chain.length]; for (int i=0; i<chain.length; i++) { signerCertificateChain[i] = (X509Certificate)chain[i]; } - } else if (path == 9) { + } else if (path.equals("nocert")) { signerCertificateChain = new X509Certificate[0]; } else { signerCertificateChain = new X509Certificate[1]; @@ -179,11 +176,11 @@ tst.putInteger(1); tst.putOID(policyId); - if (path != 3 && path != 4) { + if (!path.equals("baddigest") && !path.equals("diffalg")) { tst.putDerValue(messageImprint); } else { byte[] data = messageImprint.toByteArray(); - if (path == 4) { + if (path.equals("diffalg")) { data[6] = (byte)0x01; } else { data[data.length-1] = (byte)0x01; @@ -198,10 +195,10 @@ Calendar cal = Calendar.getInstance(); tst.putGeneralizedTime(cal.getTime()); - if (path == 2) { + if (path.equals("diffnonce")) { tst.putInteger(1234); - } else if (path == 1) { - // do nothing + } else if (path.equals("nononce")) { + // no noce } else { tst.putInteger(nonce); } @@ -212,6 +209,8 @@ DerOutputStream tstInfo2 = new DerOutputStream(); tstInfo2.putOctetString(tstInfo.toByteArray()); + // Always use the same algorithm at timestamp signing + // so it is different from the hash algorithm. Signature sig = Signature.getInstance("SHA1withRSA"); sig.initSign((PrivateKey)(ks.getKey( alias, "changeit".toCharArray()))); @@ -229,12 +228,11 @@ SignerInfo signerInfo = new SignerInfo( new X500Name(signer.getIssuerX500Principal().getName()), signer.getSerialNumber(), - aid, AlgorithmId.get("RSA"), sig.sign()); + AlgorithmId.get("SHA-1"), AlgorithmId.get("RSA"), sig.sign()); SignerInfo[] signerInfos = {signerInfo}; - PKCS7 p7 = - new PKCS7(algorithms, contentInfo, signerCertificateChain, - signerInfos); + PKCS7 p7 = new PKCS7(algorithms, contentInfo, + signerCertificateChain, signerInfos); ByteArrayOutputStream p7out = new ByteArrayOutputStream(); p7.encodeSignedData(p7out); @@ -293,42 +291,79 @@ stop(); } } - public static void main(String[] args) throws Exception { - try (Handler tsa = Handler.init(0, TSKS);) { + + public static void main(String[] args) throws Throwable { + + prepare(); + + try (Handler tsa = Handler.init(0, "tsks");) { tsa.start(); int port = tsa.getPort(); - String cmd; - // Use -J-Djava.security.egd=file:/dev/./urandom to speed up - // nonce generation in timestamping request. Not avaibale on - // Windows and defaults to thread seed generator, not too bad. - if (System.getProperty("java.home").endsWith("jre")) { - cmd = System.getProperty("java.home") + "/../bin/jarsigner"; - } else { - cmd = System.getProperty("java.home") + "/bin/jarsigner"; - } - - cmd += " -J-Djava.security.egd=file:/dev/./urandom" - + " -debug -keystore " + TSKS + " -storepass changeit" - + " -tsa http://localhost:" + port + "/%d" - + " -signedjar new_%d.jar " + JAR + " old"; + host = "http://localhost:" + port + "/"; if (args.length == 0) { // Run this test - jarsigner(cmd, 0, true); // Success, normal call - jarsigner(cmd, 1, false); // These 4 should fail - jarsigner(cmd, 2, false); - jarsigner(cmd, 3, false); - jarsigner(cmd, 4, false); - jarsigner(cmd, 5, true); // Success, 6543440 solved. - jarsigner(cmd, 6, false); // tsbad1 - jarsigner(cmd, 7, false); // tsbad2 - jarsigner(cmd, 8, false); // tsbad3 - jarsigner(cmd, 9, false); // no cert in timestamp - jarsigner(cmd + " -tsapolicyid 1.2.3.4", 10, true); - checkTimestamp("new_10.jar", "1.2.3.4", "SHA-256"); - jarsigner(cmd + " -tsapolicyid 1.2.3.5", 11, false); - jarsigner(cmd + " -tsadigestalg SHA", 12, true); - checkTimestamp("new_12.jar", defaultPolicyId, "SHA-1"); + sign("none") + .shouldContain("is not timestamped") + .shouldHaveExitValue(0); + + sign("badku") + .shouldHaveExitValue(0); + checkBadKU("badku.jar"); + + sign("normal") + .shouldNotContain("is not timestamped") + .shouldHaveExitValue(0); + + sign("nononce") + .shouldHaveExitValue(1); + sign("diffnonce") + .shouldHaveExitValue(1); + sign("baddigest") + .shouldHaveExitValue(1); + sign("diffalg") + .shouldHaveExitValue(1); + sign("fullchain") + .shouldHaveExitValue(0); // Success, 6543440 solved. + sign("bad1") + .shouldHaveExitValue(1); + sign("bad2") + .shouldHaveExitValue(1); + sign("bad3") + .shouldHaveExitValue(1); + sign("nocert") + .shouldHaveExitValue(1); + + sign("policy", "-tsapolicyid", "1.2.3") + .shouldHaveExitValue(0); + checkTimestamp("policy.jar", "1.2.3", "SHA-256"); + + sign("diffpolicy", "-tsapolicyid", "1.2.3") + .shouldHaveExitValue(1); + + sign("tsaalg", "-tsadigestalg", "SHA") + .shouldHaveExitValue(0); + checkTimestamp("tsaalg.jar", defaultPolicyId, "SHA-1"); + + sign("weak", "-digestalg", "MD2", + "-sigalg", "MD2withRSA", "-tsadigestalg", "MD2") + .shouldHaveExitValue(0); + checkWeak("weak.jar"); + + signWithAliasAndTsa("halfWeak", "old.jar", "old", "-digestalg", "MD5") + .shouldHaveExitValue(0); + checkHalfWeak("halfWeak.jar"); + + // sign with DSA key + signWithAliasAndTsa("sign1", "old.jar", "dsakey") + .shouldHaveExitValue(0); + // sign with RSAkeysize < 1024 + signWithAliasAndTsa("sign2", "sign1.jar", "weakkeysize") + .shouldHaveExitValue(0); + checkMultiple("sign2.jar"); + + // When .SF or .RSA is missing or invalid + checkMissingOrInvalidFiles("normal.jar"); } else { // Run as a standalone server System.err.println("Press Enter to quit server"); System.in.read(); @@ -336,6 +371,132 @@ } } + private static void checkMissingOrInvalidFiles(String s) + throws Throwable { + JarUtils.updateJar(s, "1.jar", "-", "META-INF/OLD.SF"); + verify("1.jar", "-verbose") + .shouldHaveExitValue(0) + .shouldContain("treated as unsigned") + .shouldContain("Missing signature-related file META-INF/OLD.SF"); + JarUtils.updateJar(s, "2.jar", "-", "META-INF/OLD.RSA"); + verify("2.jar", "-verbose") + .shouldHaveExitValue(0) + .shouldContain("treated as unsigned") + .shouldContain("Missing block file for signature-related file META-INF/OLD.SF"); + JarUtils.updateJar(s, "3.jar", "META-INF/OLD.SF"); + verify("3.jar", "-verbose") + .shouldHaveExitValue(0) + .shouldContain("treated as unsigned") + .shouldContain("Unparsable signature-related file META-INF/OLD.SF"); + JarUtils.updateJar(s, "4.jar", "META-INF/OLD.RSA"); + verify("4.jar", "-verbose") + .shouldHaveExitValue(0) + .shouldContain("treated as unsigned") + .shouldContain("Unparsable signature-related file META-INF/OLD.RSA"); + } + + static OutputAnalyzer jarsigner(List<String> extra) + throws Throwable { + JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jarsigner") + .addVMArg("-Duser.language=en") + .addVMArg("-Duser.country=US") + .addToolArg("-keystore") + .addToolArg("tsks") + .addToolArg("-storepass") + .addToolArg("changeit"); + for (String s : extra) { + if (s.startsWith("-J")) { + launcher.addVMArg(s.substring(2)); + } else { + launcher.addToolArg(s); + } + } + System.err.println("COMMAND: "); + for (String cmd : launcher.getCommand()) { + System.err.print(cmd + " "); + } + System.err.println(); + return ProcessTools.executeCommand(launcher.getCommand()); + } + + static OutputAnalyzer verify(String file, String... extra) + throws Throwable { + List<String> args = new ArrayList<>(); + args.add("-verify"); + args.add(file); + args.addAll(Arrays.asList(extra)); + return jarsigner(args); + } + + static void checkBadKU(String file) throws Throwable { + System.err.println("BadKU: " + file); + verify(file) + .shouldHaveExitValue(0) + .shouldContain("treated as unsigned") + .shouldContain("re-run jarsigner with debug enabled"); + verify(file, "-verbose") + .shouldHaveExitValue(0) + .shouldContain("Signed by") + .shouldContain("treated as unsigned") + .shouldContain("re-run jarsigner with debug enabled"); + verify(file, "-J-Djava.security.debug=jar") + .shouldHaveExitValue(0) + .shouldContain("SignatureException: Key usage restricted") + .shouldContain("treated as unsigned") + .shouldContain("re-run jarsigner with debug enabled"); + } + + static void checkWeak(String file) throws Throwable { + verify(file) + .shouldHaveExitValue(0) + .shouldContain("treated as unsigned") + .shouldMatch("weak algorithm that is now disabled.") + .shouldMatch("Re-run jarsigner with the -verbose option for more details"); + verify(file, "-verbose") + .shouldHaveExitValue(0) + .shouldContain("treated as unsigned") + .shouldMatch("weak algorithm that is now disabled by") + .shouldMatch("Digest algorithm: .*weak") + .shouldMatch("Signature algorithm: .*weak") + .shouldMatch("Timestamp digest algorithm: .*weak") + .shouldNotMatch("Timestamp signature algorithm: .*weak.*weak") + .shouldMatch("Timestamp signature algorithm: .*key.*weak"); + verify(file, "-J-Djava.security.debug=jar") + .shouldHaveExitValue(0) + .shouldMatch("SignatureException:.*Disabled"); + } + + static void checkHalfWeak(String file) throws Throwable { + verify(file) + .shouldHaveExitValue(0) + .shouldContain("treated as unsigned") + .shouldMatch("weak algorithm that is now disabled.") + .shouldMatch("Re-run jarsigner with the -verbose option for more details"); + verify(file, "-verbose") + .shouldHaveExitValue(0) + .shouldContain("treated as unsigned") + .shouldMatch("weak algorithm that is now disabled by") + .shouldMatch("Digest algorithm: .*weak") + .shouldNotMatch("Signature algorithm: .*weak") + .shouldNotMatch("Timestamp digest algorithm: .*weak") + .shouldNotMatch("Timestamp signature algorithm: .*weak.*weak") + .shouldNotMatch("Timestamp signature algorithm: .*key.*weak"); + } + + static void checkMultiple(String file) throws Throwable { + verify(file) + .shouldHaveExitValue(0) + .shouldContain("jar verified"); + verify(file, "-verbose", "-certs") + .shouldHaveExitValue(0) + .shouldContain("jar verified") + .shouldMatch("X.509.*CN=dsakey") + .shouldNotMatch("X.509.*CN=weakkeysize") + .shouldMatch("Signed by .*CN=dsakey") + .shouldMatch("Signed by .*CN=weakkeysize") + .shouldMatch("Signature algorithm: .*key.*weak"); + } + static void checkTimestamp(String file, String policyId, String digestAlg) throws Exception { try (JarFile jf = new JarFile(file)) { @@ -362,41 +523,75 @@ } } + static int which = 0; + /** - * @param cmd the command line (with a hole to plug in) - * @param path the path in the URL, i.e, http://localhost/path - * @param expected if this command should succeed + * @param extra more args given to jarsigner */ - static void jarsigner(String cmd, int path, boolean expected) - throws Exception { - System.err.println("Test " + path); - Process p = Runtime.getRuntime().exec(String.format(cmd, path, path)); - BufferedReader reader = new BufferedReader( - new InputStreamReader(p.getErrorStream())); - while (true) { - String s = reader.readLine(); - if (s == null) break; - System.err.println(s); - } + static OutputAnalyzer sign(String path, String... extra) + throws Throwable { + String alias = path.equals("badku") ? "badku" : "old"; + return signWithAliasAndTsa(path, "old.jar", alias, extra); + } + + static OutputAnalyzer signWithAliasAndTsa (String path, String jar, + String alias, String...extra) throws Throwable { + which++; + System.err.println("\n>> Test #" + which + ": " + Arrays.toString(extra)); + List<String> args = new ArrayList<>(); + args.add("-J-Djava.security.egd=file:/dev/./urandom"); + args.add("-debug"); + args.add("-signedjar"); + args.add(path + ".jar"); + args.add(jar); + args.add(alias); + if (!path.equals("none") && !path.equals("badku")) { + args.add("-tsa"); + args.add(host + path); + } + args.addAll(Arrays.asList(extra)); + return jarsigner(args); + } - // Will not see noTimestamp warning - boolean seeWarning = false; - reader = new BufferedReader( - new InputStreamReader(p.getInputStream())); - while (true) { - String s = reader.readLine(); - if (s == null) break; - System.err.println(s); - if (s.indexOf("Warning:") >= 0) { - seeWarning = true; - } + static void prepare() throws Exception { + jdk.testlibrary.JarUtils.createJar("old.jar", "A"); + Files.deleteIfExists(Paths.get("tsks")); + keytool("-alias ca -genkeypair -ext bc -dname CN=CA"); + keytool("-alias old -genkeypair -dname CN=old"); + keytool("-alias dsakey -genkeypair -keyalg DSA -dname CN=dsakey"); + keytool("-alias weakkeysize -genkeypair -keysize 512 -dname CN=weakkeysize"); + keytool("-alias badku -genkeypair -dname CN=badku"); + keytool("-alias ts -genkeypair -dname CN=ts"); + keytool("-alias tsweak -genkeypair -keysize 512 -dname CN=tsbad1"); + keytool("-alias tsbad1 -genkeypair -dname CN=tsbad1"); + keytool("-alias tsbad2 -genkeypair -dname CN=tsbad2"); + keytool("-alias tsbad3 -genkeypair -dname CN=tsbad3"); + + gencert("old"); + gencert("dsakey"); + gencert("weakkeysize"); + gencert("badku", "-ext ku:critical=keyAgreement"); + gencert("ts", "-ext eku:critical=ts"); + gencert("tsweak", "-ext eku:critical=ts"); + gencert("tsbad1"); + gencert("tsbad2", "-ext eku=ts"); + gencert("tsbad3", "-ext eku:critical=cs"); + } + + static void gencert(String alias, String... extra) throws Exception { + keytool("-alias " + alias + " -certreq -file " + alias + ".req"); + String genCmd = "-gencert -alias ca -infile " + + alias + ".req -outfile " + alias + ".cert"; + for (String s : extra) { + genCmd += " " + s; } - int result = p.waitFor(); - if (expected && result != 0 || !expected && result == 0) { - throw new Exception("Failed"); - } - if (seeWarning) { - throw new Exception("See warning"); - } + keytool(genCmd); + keytool("-alias " + alias + " -importcert -file " + alias + ".cert"); + } + + static void keytool(String cmd) throws Exception { + cmd = "-keystore tsks -storepass changeit -keypass changeit " + + "-keyalg rsa -validity 200 " + cmd; + sun.security.tools.keytool.Main.main(cmd.split(" ")); } }
--- a/test/sun/security/tools/jarsigner/ts.sh Fri Jan 13 17:09:28 2017 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,91 +0,0 @@ -# -# 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 -# 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 6543842 6543440 6939248 8009636 8024302 -# @summary checking response of timestamp -# -# @run shell/timeout=600 ts.sh - -# Run for a long time because jarsigner with timestamp needs to create a -# 64-bit random number and it might be extremely slow on a machine with -# not enough entropy pool - -# set platform-dependent variables -OS=`uname -s` -case "$OS" in - Windows_* ) - FS="\\" - ;; - * ) - FS="/" - ;; -esac - -if [ "${TESTSRC}" = "" ] ; then - TESTSRC="." -fi -if [ "${TESTJAVA}" = "" ] ; then - JAVAC_CMD=`which javac` - TESTJAVA=`dirname $JAVAC_CMD`/.. -fi - -JAR="${TESTJAVA}${FS}bin${FS}jar" -JAVA="${TESTJAVA}${FS}bin${FS}java" -JAVAC="${TESTJAVA}${FS}bin${FS}javac" -KT="${TESTJAVA}${FS}bin${FS}keytool -keystore tsks -storepass changeit -keypass changeit -keyalg rsa -validity 200" - -rm tsks -echo Nothing > A -rm old.jar -$JAR cvf old.jar A - -# ca is CA -# old is signer for code -# ts is signer for timestamp -# tsbad1 has no extendedKeyUsage -# tsbad2's extendedKeyUsage is non-critical -# tsbad3's extendedKeyUsage has no timestamping - -$KT -alias ca -genkeypair -ext bc -dname CN=CA -$KT -alias old -genkeypair -dname CN=old -$KT -alias ts -genkeypair -dname CN=ts -$KT -alias tsbad1 -genkeypair -dname CN=tsbad1 -$KT -alias tsbad2 -genkeypair -dname CN=tsbad2 -$KT -alias tsbad3 -genkeypair -dname CN=tsbad3 -$KT -alias ts -certreq | \ - $KT -alias ca -gencert -ext eku:critical=ts | \ - $KT -alias ts -importcert -$KT -alias tsbad1 -certreq | \ - $KT -alias ca -gencert | \ - $KT -alias tsbad1 -importcert -$KT -alias tsbad2 -certreq | \ - $KT -alias ca -gencert -ext eku=ts | \ - $KT -alias tsbad2 -importcert -$KT -alias tsbad3 -certreq | \ - $KT -alias ca -gencert -ext eku:critical=cs | \ - $KT -alias tsbad3 -importcert - -$JAVAC -XDignore.symbol.file -d . ${TESTSRC}/TimestampCheck.java -$JAVA ${TESTVMOPTS} TimestampCheck -
--- a/test/sun/security/tools/jarsigner/warnings/Test.java Fri Jan 13 17:09:28 2017 +0000 +++ b/test/sun/security/tools/jarsigner/warnings/Test.java Mon Jan 23 16:30:43 2017 +0000 @@ -22,6 +22,11 @@ */ import jdk.testlibrary.OutputAnalyzer; +import jdk.testlibrary.ProcessTools; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; /** * Base class. @@ -175,4 +180,38 @@ } analyzer.shouldContain(JAR_SIGNED); } + + protected OutputAnalyzer keytool(String... cmd) throws Throwable { + return tool(KEYTOOL, cmd); + } + + protected OutputAnalyzer jarsigner(String... cmd) throws Throwable { + return tool(JARSIGNER, cmd); + } + + private OutputAnalyzer tool(String tool, String... args) throws Throwable { + List<String> cmd = new ArrayList<>(); + cmd.add(tool); + cmd.add("-J-Duser.language=en"); + cmd.add("-J-Duser.country=US"); + cmd.addAll(Arrays.asList(args)); + return ProcessTools.executeCommand(cmd.toArray(new String[cmd.size()])); + } + + protected OutputAnalyzer keytool(String... cmd) throws Throwable { + return tool(KEYTOOL, cmd); + } + + protected OutputAnalyzer jarsigner(String... cmd) throws Throwable { + return tool(JARSIGNER, cmd); + } + + private OutputAnalyzer tool(String tool, String... args) throws Throwable { + List<String> cmd = new ArrayList<>(); + cmd.add(tool); + cmd.add("-J-Duser.language=en"); + cmd.add("-J-Duser.country=US"); + cmd.addAll(Arrays.asList(args)); + return ProcessTools.executeCommand(cmd.toArray(new String[cmd.size()])); + } }
--- a/test/sun/util/calendar/zi/tzdata/VERSION Fri Jan 13 17:09:28 2017 +0000 +++ b/test/sun/util/calendar/zi/tzdata/VERSION Mon Jan 23 16:30:43 2017 +0000 @@ -21,4 +21,4 @@ # or visit www.oracle.com if you need additional information or have any # questions. # -tzdata2016f +tzdata2016i
--- a/test/sun/util/calendar/zi/tzdata/africa Fri Jan 13 17:09:28 2017 +0000 +++ b/test/sun/util/calendar/zi/tzdata/africa Mon Jan 23 16:30:43 2017 +0000 @@ -487,7 +487,7 @@ # http://www.libyaherald.com/2013/10/24/correction-no-time-change-tomorrow/ # # From Paul Eggert (2013-10-25): -# For now, assume they're reverting to the pre-2012 rules of permanent UTC+2. +# For now, assume they're reverting to the pre-2012 rules of permanent UT +02. # Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S Rule Libya 1951 only - Oct 14 2:00 1:00 S
--- a/test/sun/util/calendar/zi/tzdata/antarctica Fri Jan 13 17:09:28 2017 +0000 +++ b/test/sun/util/calendar/zi/tzdata/antarctica Mon Jan 23 16:30:43 2017 +0000 @@ -33,9 +33,7 @@ # http://www.spri.cam.ac.uk/bob/periant.htm # for information. # Unless otherwise specified, we have no time zone information. -# -# Except for the French entries, -# I made up all time zone abbreviations mentioned here; corrections welcome! + # FORMAT is '-00' and GMTOFF is 0 for locations while uninhabited. # Argentina - year-round bases @@ -52,7 +50,7 @@ # previously sealers and scientific personnel wintered # Margaret Turner reports # http://web.archive.org/web/20021204222245/http://www.dstc.qut.edu.au/DST/marg/daylight.html -# (1999-09-30) that they're UTC+5, with no DST; +# (1999-09-30) that they're UT +05, with no DST; # presumably this is when they have visitors. # # year-round bases @@ -89,25 +87,29 @@ # Background: # http://www.timeanddate.com/news/time/antartica-time-changes-2010.html +# From Steffen Thorsen (2016-10-28): +# 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 Antarctica/Casey 0 - -00 1969 - 8:00 - AWST 2009 Oct 18 2:00 - # Australian Western Std Time - 11:00 - CAST 2010 Mar 5 2:00 # Casey Time - 8:00 - AWST 2011 Oct 28 2:00 - 11:00 - CAST 2012 Feb 21 17:00u - 8:00 - AWST + 8:00 - +08 2009 Oct 18 2:00 + 11:00 - +11 2010 Mar 5 2:00 + 8:00 - +08 2011 Oct 28 2:00 + 11:00 - +11 2012 Feb 21 17:00u + 8:00 - +08 2016 Oct 22 + 11:00 - +11 Zone Antarctica/Davis 0 - -00 1957 Jan 13 - 7:00 - DAVT 1964 Nov # Davis Time + 7:00 - +07 1964 Nov 0 - -00 1969 Feb - 7:00 - DAVT 2009 Oct 18 2:00 - 5:00 - DAVT 2010 Mar 10 20:00u - 7:00 - DAVT 2011 Oct 28 2:00 - 5:00 - DAVT 2012 Feb 21 20:00u - 7:00 - DAVT + 7:00 - +07 2009 Oct 18 2:00 + 5:00 - +05 2010 Mar 10 20:00u + 7:00 - +07 2011 Oct 28 2:00 + 5:00 - +05 2012 Feb 21 20:00u + 7:00 - +07 Zone Antarctica/Mawson 0 - -00 1954 Feb 13 - 6:00 - MAWT 2009 Oct 18 2:00 # Mawson Time - 5:00 - MAWT + 6:00 - +06 2009 Oct 18 2:00 + 5:00 - +05 # References: # Casey Weather (1998-02-26) # http://www.antdiv.gov.au/aad/exop/sfo/casey/casey_aws.html @@ -161,7 +163,7 @@ # # Zone NAME GMTOFF RULES FORMAT [UNTIL] Zone Indian/Kerguelen 0 - -00 1950 # Port-aux-Français - 5:00 - TFT # ISO code TF Time + 5:00 - +05 # # year-round base in the main continent # Dumont d'Urville, Île des Pétrels, -6640+14001, since 1956-11 @@ -172,9 +174,9 @@ # # Zone NAME GMTOFF RULES FORMAT [UNTIL] Zone Antarctica/DumontDUrville 0 - -00 1947 - 10:00 - PMT 1952 Jan 14 # Port-Martin Time + 10:00 - +10 1952 Jan 14 0 - -00 1956 Nov - 10:00 - DDUT # Dumont-d'Urville Time + 10:00 - +10 # France & Italy - year-round base # Concordia, -750600+1232000, since 2005 @@ -200,7 +202,7 @@ # station of Japan, it's appropriate for the principal location. # Zone NAME GMTOFF RULES FORMAT [UNTIL] Zone Antarctica/Syowa 0 - -00 1957 Jan 29 - 3:00 - SYOT # Syowa Time + 3:00 - +03 # See: # NIPR Antarctic Research Activities (1999-08-17) # http://www.nipr.ac.jp/english/ara01.html @@ -237,17 +239,17 @@ # correct, but they should be quite close to the actual dates. # # From Paul Eggert (2014-03-21): -# The CET-switching Troll rules require zic from tzcode 2014b or later, so as +# The CET-switching Troll rules require zic from tz 2014b or later, so as # suggested by Bengt-Inge Larsson comment them out for now, and approximate # with only UTC and CEST. Uncomment them when 2014b is more prevalent. # # Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S -#Rule Troll 2005 max - Mar 1 1:00u 1:00 CET -Rule Troll 2005 max - Mar lastSun 1:00u 2:00 CEST -#Rule Troll 2005 max - Oct lastSun 1:00u 1:00 CET -#Rule Troll 2004 max - Nov 7 1:00u 0:00 UTC +#Rule Troll 2005 max - Mar 1 1:00u 1:00 +01 +Rule Troll 2005 max - Mar lastSun 1:00u 2:00 +02 +#Rule Troll 2005 max - Oct lastSun 1:00u 1:00 +01 +#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 UTC +Rule Troll 2004 max - Oct lastSun 1:00u 0:00 +00 # Zone NAME GMTOFF RULES FORMAT [UNTIL] Zone Antarctica/Troll 0 - -00 2005 Feb 12 0:00 Troll %s @@ -288,10 +290,10 @@ # changes during the year and does not necessarily correspond to mean # solar noon. So the Vostok time might have been whatever the clocks # happened to be during their visit. So we still don't really know what time -# it is at Vostok. But we'll guess UTC+6. +# it is at Vostok. But we'll guess +06. # Zone Antarctica/Vostok 0 - -00 1957 Dec 16 - 6:00 - VOST # Vostok time + 6:00 - +06 # S Africa - year-round bases # Marion Island, -4653+03752 @@ -324,7 +326,7 @@ # # Zone NAME GMTOFF RULES FORMAT [UNTIL] Zone Antarctica/Rothera 0 - -00 1976 Dec 1 - -3:00 - ROTT # Rothera time + -3:00 - -03 # Uruguay - year round base # Artigas, King George Island, -621104-0585107
--- a/test/sun/util/calendar/zi/tzdata/asia Fri Jan 13 17:09:28 2017 +0000 +++ b/test/sun/util/calendar/zi/tzdata/asia Mon Jan 23 16:30:43 2017 +0000 @@ -139,13 +139,11 @@ # http://www.worldtimezone.com/dst_news/dst_news_armenia03.html # Zone NAME GMTOFF RULES FORMAT [UNTIL] Zone Asia/Yerevan 2:58:00 - LMT 1924 May 2 - 3:00 - YERT 1957 Mar # Yerevan Time - 4:00 RussiaAsia YER%sT 1991 Mar 31 2:00s - 3:00 1:00 YERST 1991 Sep 23 # independence - 3:00 RussiaAsia AM%sT 1995 Sep 24 2:00s - 4:00 - AMT 1997 - 4:00 RussiaAsia AM%sT 2012 Feb 9 - 4:00 - AMT + 3:00 - +03 1957 Mar + 4:00 RussiaAsia +04/+05 1991 Mar 31 2:00s + 3:00 RussiaAsia +03/+04 1995 Sep 24 2:00s + 4:00 - +04 1997 + 4:00 RussiaAsia +04/+05 # Azerbaijan @@ -166,13 +164,12 @@ Rule Azer 1997 2015 - Oct lastSun 5:00 0 - # Zone NAME GMTOFF RULES FORMAT [UNTIL] Zone Asia/Baku 3:19:24 - LMT 1924 May 2 - 3:00 - BAKT 1957 Mar # Baku Time - 4:00 RussiaAsia BAK%sT 1991 Mar 31 2:00s - 3:00 1:00 BAKST 1991 Aug 30 # independence - 3:00 RussiaAsia AZ%sT 1992 Sep lastSun 2:00s - 4:00 - AZT 1996 # Azerbaijan Time - 4:00 EUAsia AZ%sT 1997 - 4:00 Azer AZ%sT + 3:00 - +03 1957 Mar + 4:00 RussiaAsia +04/+05 1991 Mar 31 2:00s + 3:00 RussiaAsia +03/+04 1992 Sep lastSun 2:00s + 4:00 - +04 1996 + 4:00 EUAsia +04/+05 1997 + 4:00 Azer +04/+05 # Bahrain # See Asia/Qatar. @@ -291,7 +288,7 @@ # Milne says 6:24:40 was the meridian of the time ball observatory at Rangoon. # Zone NAME GMTOFF RULES FORMAT [UNTIL] -Zone Asia/Rangoon 6:24:40 - LMT 1880 # or Yangon +Zone Asia/Yangon 6:24:40 - LMT 1880 # or Rangoon 6:24:40 - RMT 1920 # Rangoon Mean Time? 6:30 - BURT 1942 May # Burma Time 9:00 - JST 1945 May 3 @@ -406,7 +403,7 @@ # Lewiston (ME) Daily Sun (1939-05-29), p 17, said "Even the time is # different - the occupied districts going by Tokyo time, an hour # ahead of that prevailing in the rest of Shanghai." Guess that the -# Xujiahui Observatory was under French control and stuck with UT+8. +# Xujiahui Observatory was under French control and stuck with UT +08. # # In earlier versions of this file, China had many separate Zone entries, but # this was based on what were apparently incorrect data in Shanks & Pottenger. @@ -415,26 +412,26 @@ # Proposed in 1918 and theoretically in effect until 1949 (although in practice # mainly observed in coastal areas), the five zones were: # -# Changbai Time ("Long-white Time", Long-white = Heilongjiang area) UT+8.5 +# Changbai Time ("Long-white Time", Long-white = Heilongjiang area) UT +08:30 # Asia/Harbin (currently a link to Asia/Shanghai) # Heilongjiang (except Mohe county), Jilin # -# Zhongyuan Time ("Central plain Time") UT+8 +# Zhongyuan Time ("Central plain Time") UT +08 # Asia/Shanghai # most of China # This currently represents most other zones as well, # as apparently these regions have been the same since 1970. # Milne gives 8:05:43.2 for Xujiahui Observatory time; round to nearest. -# Guo says Shanghai switched to UT+8 "from the end of the 19th century". +# Guo says Shanghai switched to UT +08 "from the end of the 19th century". # -# Long-shu Time (probably due to Long and Shu being two names of that area) UT+7 +# Long-shu Time (probably due to Long and Shu being two names of the area) UT +07 # Asia/Chongqing (currently a link to Asia/Shanghai) # Guangxi, Guizhou, Hainan, Ningxia, Sichuan, Shaanxi, and Yunnan; # most of Gansu; west Inner Mongolia; west Qinghai; and the Guangdong # counties Deqing, Enping, Kaiping, Luoding, Taishan, Xinxing, # Yangchun, Yangjiang, Yu'nan, and Yunfu. # -# Xin-zang Time ("Xinjiang-Tibet Time") UT+6 +# Xin-zang Time ("Xinjiang-Tibet Time") UT +06 # Asia/Urumqi # This currently represents Kunlun Time as well, # as apparently the two regions have been the same since 1970. @@ -447,7 +444,7 @@ # Shihezi, Changji, Yanqi, Heshuo, Tuokexun, Tulufan, Shanshan, Hami, # Fukang, Kuitun, Kumukuli, Miquan, Qitai, and Turfan. # -# Kunlun Time UT+5.5 +# Kunlun Time UT +05:30 # Asia/Kashgar (currently a link to Asia/Urumqi) # West Tibet, including Pulan, Aheqi, Shufu, Shule; # West Xinjiang, including Aksu, Atushi, Yining, Hetian, Cele, Luopu, Nileke, @@ -463,7 +460,7 @@ # # On the other hand, ethnic Uyghurs, who make up about half the # population of Xinjiang, typically use "Xinjiang time" which is two -# hours behind Beijing time, or UTC +0600. The government of the Xinjiang +# hours behind Beijing time, or UT +06. The government of the Xinjiang # Uyghur Autonomous Region, (XAUR, or just Xinjiang for short) as well as # local governments such as the Ürümqi city government use both times in # publications, referring to what is popularly called Xinjiang time as @@ -519,8 +516,8 @@ # having the same time as Beijing. # From Paul Eggert (2014-06-30): -# In the early days of the PRC, Tibet was given its own time zone (UT+6) but -# this was withdrawn in 1959 and never reinstated; see Tubten Khétsun, +# In the early days of the PRC, Tibet was given its own time zone (UT +06) +# but this was withdrawn in 1959 and never reinstated; see Tubten Khétsun, # Memories of life in Lhasa under Chinese Rule, Columbia U Press, ISBN # 978-0231142861 (2008), translator's introduction by Matthew Akester, p x. # As this is before our 1970 cutoff, Tibet doesn't need a separate zone. @@ -534,12 +531,12 @@ # Republics, the Soviet Union, the Kuomintang, and the People's Republic of # China, and tracking down all these organizations' timekeeping rules would be # quite a trick. Approximate this lost history by a transition from LMT to -# XJT at the start of 1928, the year of accession of the warlord Jin Shuren, +# UT +06 at the start of 1928, the year of accession of the warlord Jin Shuren, # which happens to be the date given by Shanks & Pottenger (no doubt as a -# guess) as the transition from LMT. Ignore the usage of UT+8 before -# 1986-02-01 under the theory that the transition date to UT+8 is unknown and +# guess) as the transition from LMT. Ignore the usage of +08 before +# 1986-02-01 under the theory that the transition date to +08 is unknown and # that the sort of users who prefer Asia/Urumqi now typically ignored the -# UT+8 mandate back then. +# +08 mandate back then. # Zone NAME GMTOFF RULES FORMAT [UNTIL] # Beijing time, used throughout China; represented by Shanghai. @@ -744,7 +741,7 @@ # be found from historical government announcement database. # From Paul Eggert (2014-07-03): -# As per Yu-Cheng Chuang, say that Taiwan was at UT+9 from 1937-10-01 +# As per Yu-Cheng Chuang, say that Taiwan was at UT +09 from 1937-10-01 # until 1945-09-21 at 01:00, overriding Shanks & Pottenger. # Likewise, use Yu-Cheng Chuang's data for DST in Taiwan. @@ -797,9 +794,19 @@ ############################################################################### # Cyprus -# + # Milne says the Eastern Telegraph Company used 2:14:00. Stick with LMT. +# IATA SSIM (1998-09) has Cyprus using EU rules for the first time. + +# From Paul Eggert (2016-09-09): +# Yesterday's Cyprus Mail reports that Northern Cyprus followed Turkey's +# lead and switched from +02/+03 to +03 year-round. +# http://cyprus-mail.com/2016/09/08/two-time-zones-cyprus-turkey-will-not-turn-clocks-back-next-month/ # +# From Even Scharning (2016-10-31): +# Looks like the time zone split in Cyprus went through last night. +# http://cyprus-mail.com/2016/10/30/cyprus-new-division-two-time-zones-now-reality/ + # Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S Rule Cyprus 1975 only - Apr 13 0:00 1:00 S Rule Cyprus 1975 only - Oct 12 0:00 0 - @@ -814,7 +821,10 @@ Zone Asia/Nicosia 2:13:28 - LMT 1921 Nov 14 2:00 Cyprus EE%sT 1998 Sep 2:00 EUAsia EE%sT -# IATA SSIM (1998-09) has Cyprus using EU rules for the first time. +Zone Asia/Famagusta 2:15:48 - LMT 1921 Nov 14 + 2:00 Cyprus EE%sT 1998 Sep + 2:00 EUAsia EE%sT 2016 Sep 8 + 3:00 - +03 # Classically, Cyprus belongs to Asia; e.g. see Herodotus, Histories, I.72. # However, for various reasons many users expect to find it under Europe. @@ -858,16 +868,15 @@ # Zone NAME GMTOFF RULES FORMAT [UNTIL] Zone Asia/Tbilisi 2:59:11 - LMT 1880 2:59:11 - TBMT 1924 May 2 # Tbilisi Mean Time - 3:00 - TBIT 1957 Mar # Tbilisi Time - 4:00 RussiaAsia TBI%sT 1991 Mar 31 2:00s - 3:00 1:00 TBIST 1991 Apr 9 # independence - 3:00 RussiaAsia GE%sT 1992 # Georgia Time - 3:00 E-EurAsia GE%sT 1994 Sep lastSun - 4:00 E-EurAsia GE%sT 1996 Oct lastSun - 4:00 1:00 GEST 1997 Mar lastSun - 4:00 E-EurAsia GE%sT 2004 Jun 27 - 3:00 RussiaAsia GE%sT 2005 Mar lastSun 2:00 - 4:00 - GET + 3:00 - +03 1957 Mar + 4:00 RussiaAsia +04/+05 1991 Mar 31 2:00s + 3:00 RussiaAsia +03/+04 1992 + 3:00 E-EurAsia +03/+04 1994 Sep lastSun + 4:00 E-EurAsia +04/+05 1996 Oct lastSun + 4:00 1:00 +05 1997 Mar lastSun + 4:00 E-EurAsia +04/+05 2004 Jun 27 + 3:00 RussiaAsia +03/+04 2005 Mar lastSun 2:00 + 4:00 - +04 # East Timor @@ -944,7 +953,7 @@ # These would be the earliest possible times for a change. # Régimes horaires pour le monde entier, by Henri Le Corre, (Éditions # Traditionnelles, 1987, Paris) says that Java and Madura switched -# from JST to UTC+07:30 on 1945-09-23, and gives 1944-09-01 for Jayapura +# from UT +09 to +07:30 on 1945-09-23, and gives 1944-09-01 for Jayapura # (Hollandia). For now, assume all Indonesian locations other than Jayapura # switched on 1945-09-23. # @@ -955,11 +964,11 @@ # summary published by the Time and Frequency Laboratory of the # Research Center for Calibration, Instrumentation and Metrology, # Indonesia, <http://time.kim.lipi.go.id/time-eng.php> (2006-09-29). -# The abbreviations are: +# The time zone abbreviations and UT offsets are: # -# WIB - UTC+7 - Waktu Indonesia Barat (Indonesia western time) -# WITA - UTC+8 - Waktu Indonesia Tengah (Indonesia central time) -# WIT - UTC+9 - Waktu Indonesia Timur (Indonesia eastern time) +# WIB - +07 - Waktu Indonesia Barat (Indonesia western time) +# WITA - +08 - Waktu Indonesia Tengah (Indonesia central time) +# WIT - +09 - Waktu Indonesia Timur (Indonesia eastern time) # # Zone NAME GMTOFF RULES FORMAT [UNTIL] # Java, Sumatra @@ -1848,11 +1857,11 @@ Rule Kyrgyz 1997 2004 - Oct lastSun 2:30 0 - # Zone NAME GMTOFF RULES FORMAT [UNTIL] Zone Asia/Bishkek 4:58:24 - LMT 1924 May 2 - 5:00 - FRUT 1930 Jun 21 # Frunze Time - 6:00 RussiaAsia FRU%sT 1991 Mar 31 2:00s - 5:00 1:00 FRUST 1991 Aug 31 2:00 # independence - 5:00 Kyrgyz KG%sT 2005 Aug 12 # Kyrgyzstan Time - 6:00 - KGT + 5:00 - +05 1930 Jun 21 + 6:00 RussiaAsia +06/+07 1991 Mar 31 2:00s + 5:00 RussiaAsia +05/+06 1991 Aug 31 2:00 + 5:00 Kyrgyz +05/+06 2005 Aug 12 + 6:00 - +06 ############################################################################### @@ -1891,25 +1900,24 @@ Rule ROK 1987 1988 - May Sun>=8 2:00 1:00 D Rule ROK 1987 1988 - Oct Sun>=8 3:00 0 S -# From Paul Eggert (2014-10-30): +# From Paul Eggert (2016-08-23): # The Korean Wikipedia entry gives the following sources for UT offsets: # -# 1908: Official Journal Article No. 3994 (Edict No. 5) +# 1908: Official Journal Article No. 3994 (decree No. 5) # 1912: Governor-General of Korea Official Gazette Issue No. 367 # (Announcement No. 338) # 1954: Presidential Decree No. 876 (1954-03-17) # 1961: Law No. 676 (1961-08-07) -# 1987: Law No. 3919 (1986-12-31) # -# The Wikipedia entry also has confusing information about a change -# to UT+9 in April 1910, but then what would be the point of the later change -# to UT+9 on 1912-01-01? Omit the 1910 change for now. +# (Another source "1987: Law No. 3919 (1986-12-31)" was in the 2014-10-30 +# edition of the Korean Wikipedia entry.) # # I guessed that time zone abbreviations through 1945 followed the same # rules as discussed under Taiwan, with nominal switches from JST to KST # when the respective cities were taken over by the Allies after WWII. # -# For Pyongyang we have no information; guess no changes since World War II. +# For Pyongyang, guess no changes from World War II until 2015, as we +# have no information otherwise. # From Steffen Thorsen (2015-08-07): # According to many news sources, North Korea is going to change to @@ -2069,7 +2077,7 @@ # Bill Bonnet (2005-05-19) reports that the US Embassy in Ulaanbaatar says # there is only one time zone and that DST is observed, citing Microsoft # Windows XP as the source. Risto Nykänen (2005-05-16) reports that -# travelmongolia.org says there are two time zones (UTC+7, UTC+8) with no DST. +# travelmongolia.org says there are two time zones (UT +07, +08) with no DST. # Oscar van Vlijmen (2005-05-20) reports that the Mongolian Embassy in # Washington, DC says there are two time zones, with DST observed. # He also found @@ -2572,11 +2580,6 @@ # From Paul Eggert (2015-03-03): # http://www.timeanddate.com/time/change/west-bank/ramallah?year=2014 # says that the fall 2014 transition was Oct 23 at 24:00. -# For future dates, guess the last Friday in March at 24:00 through -# the first Friday on or after October 21 at 00:00. This is consistent with -# the predictions in today's editions of the following URLs: -# http://www.timeanddate.com/time/change/gaza-strip/gaza -# http://www.timeanddate.com/time/change/west-bank/hebron # From Hannah Kreitem (2016-03-09): # http://www.palestinecabinet.gov.ps/WebSite/ar/ViewDetails?ID=31728 @@ -2586,7 +2589,21 @@ # # From Paul Eggert (2016-03-12): # Predict spring transitions on March's last Saturday at 01:00 from now on. -# Leave fall predictions alone for now. + +# From Sharef Mustafa (2016-10-19): +# [T]he Palestinian cabinet decision (Mar 8th 2016) published on +# http://www.palestinecabinet.gov.ps/WebSite/Upload/Decree/GOV_17/16032016134830.pdf +# states that summer time will end on Oct 29th at 01:00. +# +# From Tim Parenti (2016-10-19): +# Predict fall transitions on October's last Saturday at 01:00 from now on. +# This is consistent with the 2016 transition as well as our spring +# predictions. +# +# From Paul Eggert (2016-10-19): +# It's also consistent with predictions in the following URLs today: +# http://www.timeanddate.com/time/change/gaza-strip/gaza +# http://www.timeanddate.com/time/change/west-bank/hebron # Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S Rule EgyptAsia 1957 only - May 10 0:00 1:00 S @@ -2615,9 +2632,10 @@ Rule Palestine 2012 2014 - Mar lastThu 24:00 1:00 S Rule Palestine 2012 only - Sep 21 1:00 0 - Rule Palestine 2013 only - Sep Fri>=21 0:00 0 - -Rule Palestine 2014 max - Oct 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 lastSat 1:00 1:00 S +Rule Palestine 2016 max - Oct lastSat 1:00 0 - # Zone NAME GMTOFF RULES FORMAT [UNTIL] Zone Asia/Gaza 2:17:52 - LMT 1900 Oct @@ -2705,7 +2723,7 @@ # earlier date. # # Shanks & Pottenger also state that until 1968-05-01 Saudi Arabia had two -# time zones; the other zone, at UTC+4, was in the far eastern part of +# time zones; the other zone, at UT +04, was in the far eastern part of # the country. Ignore this, as it's before our 1970 cutoff. # # Zone NAME GMTOFF RULES FORMAT [UNTIL] @@ -2767,45 +2785,31 @@ # People who live in regions under Tamil control can use [TZ='Asia/Kolkata'], # as that zone has agreed with the Tamil areas since our cutoff date of 1970. -# From K Sethu (2006-04-25): -# I think the abbreviation LKT originated from the world of computers at -# the time of or subsequent to the time zone changes by SL Government -# twice in 1996 and probably SL Government or its standardization -# agencies never declared an abbreviation as a national standard. -# -# I recollect before the recent change the government announcements -# mentioning it as simply changing Sri Lanka Standard Time or Sri Lanka -# Time and no mention was made about the abbreviation. +# From Sadika Sumanapala (2016-10-19): +# According to http://www.sltime.org (maintained by Measurement Units, +# Standards & Services Department, Sri Lanka) abbreviation for Sri Lanka +# standard time is SLST. # -# If we look at Sri Lanka Department of Government's "Official News -# Website of Sri Lanka" ... http://www.news.lk/ we can see that they -# use SLT as abbreviation in time stamp at the beginning of each news -# item.... -# -# Within Sri Lanka I think LKT is well known among computer users and -# administrators. In my opinion SLT may not be a good choice because the -# nation's largest telcom / internet operator Sri Lanka Telcom is well -# known by that abbreviation - simply as SLT (there IP domains are -# slt.lk and sltnet.lk). -# -# But if indeed our government has adopted SLT as standard abbreviation -# (that we have not known so far) then it is better that it be used for -# all computers. - -# From Paul Eggert (2006-04-25): -# One possibility is that we wait for a bit for the dust to settle down -# and then see what people actually say in practice. +# From Paul Eggert (2016-10-18): +# "SLST" seems to be reasonably recent and rarely-used outside time +# zone nerd sources. I searched Google News and found three uses of +# it in the International Business Times of India in February and +# March of this year when discussing cricket match times, but nothing +# since then (though there has been a lot of cricket) and nothing in +# other English-language news sources. Our old abbreviation "LKT" is +# 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 Asia/Colombo 5:19:24 - LMT 1880 5:19:32 - MMT 1906 # Moratuwa Mean Time - 5:30 - IST 1942 Jan 5 - 5:30 0:30 IHST 1942 Sep - 5:30 1:00 IST 1945 Oct 16 2:00 - 5:30 - IST 1996 May 25 0:00 - 6:30 - LKT 1996 Oct 26 0:30 - 6:00 - LKT 2006 Apr 15 0:30 - 5:30 - IST + 5:30 - +0530 1942 Jan 5 + 5:30 0:30 +0530/+06 1942 Sep + 5:30 1:00 +0530/+0630 1945 Oct 16 2:00 + 5:30 - +0530 1996 May 25 0:00 + 6:30 - +0630 1996 Oct 26 0:30 + 6:00 - +06 2006 Apr 15 0:30 + 5:30 - +0530 # Syria # Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S @@ -2974,10 +2978,10 @@ # From Shanks & Pottenger. # Zone NAME GMTOFF RULES FORMAT [UNTIL] Zone Asia/Dushanbe 4:35:12 - LMT 1924 May 2 - 5:00 - DUST 1930 Jun 21 # Dushanbe Time - 6:00 RussiaAsia DUS%sT 1991 Mar 31 2:00s - 5:00 1:00 DUSST 1991 Sep 9 2:00s - 5:00 - TJT # Tajikistan Time + 5:00 - +05 1930 Jun 21 + 6:00 RussiaAsia +06/+07 1991 Mar 31 2:00s + 5:00 1:00 +05/+06 1991 Sep 9 2:00s + 5:00 - +05 # Thailand # Zone NAME GMTOFF RULES FORMAT [UNTIL] @@ -2991,11 +2995,10 @@ # From Shanks & Pottenger. # Zone NAME GMTOFF RULES FORMAT [UNTIL] Zone Asia/Ashgabat 3:53:32 - LMT 1924 May 2 # or Ashkhabad - 4:00 - ASHT 1930 Jun 21 # Ashkhabad Time - 5:00 RussiaAsia ASH%sT 1991 Mar 31 2:00 - 4:00 RussiaAsia ASH%sT 1991 Oct 27 # independence - 4:00 RussiaAsia TM%sT 1992 Jan 19 2:00 - 5:00 - TMT + 4:00 - +04 1930 Jun 21 + 5:00 RussiaAsia +05/+06 1991 Mar 31 2:00 + 4:00 RussiaAsia +04/+05 1992 Jan 19 2:00 + 5:00 - +05 # United Arab Emirates # Zone NAME GMTOFF RULES FORMAT [UNTIL] @@ -3007,20 +3010,18 @@ # Byalokoz 1919 says Uzbekistan was 4:27:53. # Zone NAME GMTOFF RULES FORMAT [UNTIL] Zone Asia/Samarkand 4:27:53 - LMT 1924 May 2 - 4:00 - SAMT 1930 Jun 21 # Samarkand Time - 5:00 - SAMT 1981 Apr 1 - 5:00 1:00 SAMST 1981 Oct 1 - 6:00 - TAST 1982 Apr 1 # Tashkent Time - 5:00 RussiaAsia SAM%sT 1991 Sep 1 # independence - 5:00 RussiaAsia UZ%sT 1992 - 5:00 - UZT + 4:00 - +04 1930 Jun 21 + 5:00 - +05 1981 Apr 1 + 5:00 1:00 +06 1981 Oct 1 + 6:00 - +06 1982 Apr 1 + 5:00 RussiaAsia +05/+06 1992 + 5:00 - +05 # Milne says Tashkent was 4:37:10.8; round to nearest. Zone Asia/Tashkent 4:37:11 - LMT 1924 May 2 - 5:00 - TAST 1930 Jun 21 # Tashkent Time - 6:00 RussiaAsia TAS%sT 1991 Mar 31 2:00 - 5:00 RussiaAsia TAS%sT 1991 Sep 1 # independence - 5:00 RussiaAsia UZ%sT 1992 - 5:00 - UZT + 5:00 - +05 1930 Jun 21 + 6:00 RussiaAsia +06/+07 1991 Mar 31 2:00 + 5:00 RussiaAsia +05/+06 1992 + 5:00 - +05 # Vietnam
--- a/test/sun/util/calendar/zi/tzdata/australasia Fri Jan 13 17:09:28 2017 +0000 +++ b/test/sun/util/calendar/zi/tzdata/australasia Mon Jan 23 16:30:43 2017 +0000 @@ -373,7 +373,13 @@ # commencing at 2.00 am on Sunday 1st November, 2015 and ending at # 3.00 am on Sunday 17th January, 2016. -# From Paul Eggert (2015-09-01): +# From Raymond Kumar (2016-10-04): +# http://www.fiji.gov.fj/Media-Center/Press-Releases/DAYLIGHT-SAVING-STARTS-ON-6th-NOVEMBER,-2016.aspx +# "Fiji's daylight savings will begin on Sunday, 6 November 2016, when +# clocks go forward an hour at 2am to 3am.... Daylight Saving will +# end at 3.00am on Sunday 15th January 2017." + +# From Paul Eggert (2016-10-03): # For now, guess DST from 02:00 the first Sunday in November to # 03:00 the third Sunday in January. Although ad hoc, it matches # transitions since late 2014 and seems more likely to match future @@ -568,7 +574,7 @@ # Base the Bougainville entry on the Arawa-Kieta region, which appears to have # the most people even though it was devastated in the Bougainville Civil War. # -# Although Shanks gives 1942-03-15 / 1943-11-01 for JST, these dates +# Although Shanks gives 1942-03-15 / 1943-11-01 for UT +09, these dates # are apparently rough guesswork from the starts of military campaigns. # The World War II entries below are instead based on Arawa-Kieta. # The Japanese occupied Kieta in July 1942, @@ -576,8 +582,8 @@ # http://pwencycl.kgbudge.com/B/o/Bougainville.htm # and seem to have controlled it until their 1945-08-21 surrender. # -# The Autonomous Region of Bougainville plans to switch from UTC+10 to UTC+11 -# on 2014-12-28 at 02:00. They call UTC+11 "Bougainville Standard Time"; +# The Autonomous Region of Bougainville switched from UT +10 to +11 +# on 2014-12-28 at 02:00. They call +11 "Bougainville Standard Time"; # abbreviate this as BST. See: # http://www.bougainville24.com/bougainville-issues/bougainville-gets-own-timezone/ # @@ -643,7 +649,7 @@ # From Paul Eggert (2014-06-27): # The International Date Line Act 2011 # http://www.parliament.gov.ws/images/ACTS/International_Date_Line_Act__2011_-_Eng.pdf -# changed Samoa from UTC-11 to UTC+13, effective "12 o'clock midnight, on +# changed Samoa from UT -11 to +13, effective "12 o'clock midnight, on # Thursday 29th December 2011". The International Date Line was adjusted # accordingly. @@ -719,11 +725,13 @@ Rule Tonga 2000 only - Mar 19 2:00s 0 - Rule Tonga 2000 2001 - Nov Sun>=1 2:00 1:00 S Rule Tonga 2001 2002 - Jan lastSun 2:00 0 - +Rule Tonga 2016 max - Nov Sun>=1 2:00 1:00 S +Rule Tonga 2017 max - Jan Sun>=15 3:00 0 - # Zone NAME GMTOFF RULES FORMAT [UNTIL] Zone Pacific/Tongatapu 12:19:20 - LMT 1901 - 12:20 - TOT 1941 # Tonga Time - 13:00 - TOT 1999 - 13:00 Tonga TO%sT + 12:20 - +1220 1941 + 13:00 - +13 1999 + 13:00 Tonga +13/+14 # Tuvalu # Zone NAME GMTOFF RULES FORMAT [UNTIL] @@ -738,7 +746,7 @@ # 1886-1891; Baker was similar but exact dates are not known. # Inhabited by civilians 1935-1942; U.S. military bases 1943-1944; # uninhabited thereafter. -# Howland observed Hawaii Standard Time (UT-10:30) in 1937; +# Howland observed Hawaii Standard Time (UT -10:30) in 1937; # see page 206 of Elgen M. Long and Marie K. Long, # Amelia Earhart: the Mystery Solved, Simon & Schuster (2000). # So most likely Howland and Baker observed Hawaii Time from 1935 @@ -1496,7 +1504,7 @@ # Zealand time. I understand that is the time they keep locally, anyhow." # For now, assume this practice goes back to the introduction of standard time # in New Zealand, as this would make Chatham Islands time almost exactly match -# LMT back when New Zealand was at UTC+11:30; also, assume Chatham Islands did +# LMT back when New Zealand was at UT +11:30; also, assume Chatham Islands did # not observe New Zealand's prewar DST. ############################################################################### @@ -1552,7 +1560,7 @@ # For now, we assume the Ladrones switched at the same time as the Philippines; # see Asia/Manila. -# US Public Law 106-564 (2000-12-23) made UTC+10 the official standard time, +# US Public Law 106-564 (2000-12-23) made UT +10 the official standard time, # under the name "Chamorro Standard Time". There is no official abbreviation, # but Congressman Robert A. Underwood, author of the bill that became law, # wrote in a press release (2000-12-27) that he will seek the use of "ChST". @@ -1564,15 +1572,15 @@ # "I am certain, having lived there for the past decade, that 'Truk' # (now properly known as Chuuk) ... is in the time zone GMT+10." # -# Shanks & Pottenger write that Truk switched from UTC+10 to UTC+11 +# Shanks & Pottenger write that Truk switched from UT +10 to +11 # on 1978-10-01; ignore this for now. # From Paul Eggert (1999-10-29): # The Federated States of Micronesia Visitors Board writes in # The Federated States of Micronesia - Visitor Information (1999-01-26) # http://www.fsmgov.org/info/clocks.html -# that Truk and Yap are UTC+10, and Ponape and Kosrae are UTC+11. -# We don't know when Kosrae switched from UTC+12; assume January 1 for now. +# that Truk and Yap are UT +10, and Ponape and Kosrae are +11. +# We don't know when Kosrae switched from +12; assume January 1 for now. # Midway @@ -1638,11 +1646,11 @@ # ordaining - by a masterpiece of diplomatic flattery - that # the Fourth of July should be celebrated twice in that year." -# Although Shanks & Pottenger says they both switched to UTC-11:30 -# in 1911, and to UTC-11 in 1950. many earlier sources give UTC-11 +# Although Shanks & Pottenger says they both switched to UT -11:30 +# in 1911, and to -11 in 1950. many earlier sources give -11 # for American Samoa, e.g., the US National Bureau of Standards # circular "Standard Time Throughout the World", 1932. -# Assume American Samoa switched to UTC-11 in 1911, not 1950, +# Assume American Samoa switched to -11 in 1911, not 1950, # and that after 1950 they agreed until (western) Samoa skipped a # day in 2011. Assume also that the Samoas follow the US and New # Zealand's "ST"/"DT" style of daylight-saving abbreviations. @@ -1729,9 +1737,17 @@ # of January the standard time in the Kingdom shall be moved backward by one # hour to 1:00am. -# From Pulu 'Anau (2002-11-05): +# From Pulu ʻAnau (2002-11-05): # The law was for 3 years, supposedly to get renewed. It wasn't. +# From Pulu ʻAnau (2016-10-27): +# http://mic.gov.to/news-today/press-releases/6375-daylight-saving-set-to-run-from-6-november-2016-to-15-january-2017 +# Cannot find anyone who knows the rules, has seen the duration or has seen +# the cabinet decision, but it appears we are following Fiji's rule set. +# +# From Tim Parenti (2016-10-26): +# Assume Tonga will observe DST from the first Sunday in November at 02:00 +# through the third Sunday in January at 03:00, like Fiji, for now. # Wake
--- a/test/sun/util/calendar/zi/tzdata/backward Fri Jan 13 17:09:28 2017 +0000 +++ b/test/sun/util/calendar/zi/tzdata/backward Mon Jan 23 16:30:43 2017 +0000 @@ -59,6 +59,7 @@ Link Asia/Urumqi Asia/Kashgar Link Asia/Kathmandu Asia/Katmandu Link Asia/Macau Asia/Macao +Link Asia/Yangon Asia/Rangoon Link Asia/Ho_Chi_Minh Asia/Saigon Link Asia/Jerusalem Asia/Tel_Aviv Link Asia/Thimphu Asia/Thimbu
--- a/test/sun/util/calendar/zi/tzdata/etcetera Fri Jan 13 17:09:28 2017 +0000 +++ b/test/sun/util/calendar/zi/tzdata/etcetera Mon Jan 23 16:30:43 2017 +0000 @@ -31,6 +31,13 @@ # need now for the entries that are not on UTC are for ships at sea # that cannot use POSIX TZ settings. +# Starting with POSIX 1003.1-2001, the entries below are all +# unnecessary as settings for the TZ environment variable. E.g., +# instead of TZ='Etc/GMT+4' one can use the POSIX setting TZ='<-04>+4'. +# +# Do not use a POSIX TZ setting like TZ='GMT+4', which is four hours +# behind GMT but uses the completely misleading abbreviation "GMT". + Zone Etc/GMT 0 - GMT Zone Etc/UTC 0 - UTC Zone Etc/UCT 0 - UCT @@ -49,23 +56,13 @@ Link Etc/GMT Etc/GMT+0 Link Etc/GMT Etc/GMT0 -# We use POSIX-style signs in the Zone names and the output abbreviations, +# Be consistent with POSIX TZ settings in the Zone names, # even though this is the opposite of what many people expect. # POSIX has positive signs west of Greenwich, but many people expect # positive signs east of Greenwich. For example, TZ='Etc/GMT+4' uses -# the abbreviation "GMT+4" and corresponds to 4 hours behind UT +# the abbreviation "-04" and corresponds to 4 hours behind UT # (i.e. west of Greenwich) even though many people would expect it to # mean 4 hours ahead of UT (i.e. east of Greenwich). -# -# In the draft 5 of POSIX 1003.1-200x, the angle bracket notation allows for -# TZ='<GMT-4>+4'; if you want time zone abbreviations conforming to -# ISO 8601 you can use TZ='<-0400>+4'. Thus the commonly-expected -# offset is kept within the angle bracket (and is used for display) -# while the POSIX sign is kept outside the angle bracket (and is used -# for calculation). -# -# Do not use a TZ setting like TZ='GMT+4', which is four hours behind -# GMT but uses the completely misleading abbreviation "GMT". # Earlier incarnations of this package were not POSIX-compliant, # and had lines such as @@ -74,30 +71,31 @@ # way does a # zic -l GMT-12 # so we moved the names into the Etc subdirectory. +# Also, the time zone abbreviations are now compatible with %z. -Zone Etc/GMT-14 14 - GMT-14 # 14 hours ahead of GMT -Zone Etc/GMT-13 13 - GMT-13 -Zone Etc/GMT-12 12 - GMT-12 -Zone Etc/GMT-11 11 - GMT-11 -Zone Etc/GMT-10 10 - GMT-10 -Zone Etc/GMT-9 9 - GMT-9 -Zone Etc/GMT-8 8 - GMT-8 -Zone Etc/GMT-7 7 - GMT-7 -Zone Etc/GMT-6 6 - GMT-6 -Zone Etc/GMT-5 5 - GMT-5 -Zone Etc/GMT-4 4 - GMT-4 -Zone Etc/GMT-3 3 - GMT-3 -Zone Etc/GMT-2 2 - GMT-2 -Zone Etc/GMT-1 1 - GMT-1 -Zone Etc/GMT+1 -1 - GMT+1 -Zone Etc/GMT+2 -2 - GMT+2 -Zone Etc/GMT+3 -3 - GMT+3 -Zone Etc/GMT+4 -4 - GMT+4 -Zone Etc/GMT+5 -5 - GMT+5 -Zone Etc/GMT+6 -6 - GMT+6 -Zone Etc/GMT+7 -7 - GMT+7 -Zone Etc/GMT+8 -8 - GMT+8 -Zone Etc/GMT+9 -9 - GMT+9 -Zone Etc/GMT+10 -10 - GMT+10 -Zone Etc/GMT+11 -11 - GMT+11 -Zone Etc/GMT+12 -12 - GMT+12 +Zone Etc/GMT-14 14 - +14 +Zone Etc/GMT-13 13 - +13 +Zone Etc/GMT-12 12 - +12 +Zone Etc/GMT-11 11 - +11 +Zone Etc/GMT-10 10 - +10 +Zone Etc/GMT-9 9 - +09 +Zone Etc/GMT-8 8 - +08 +Zone Etc/GMT-7 7 - +07 +Zone Etc/GMT-6 6 - +06 +Zone Etc/GMT-5 5 - +05 +Zone Etc/GMT-4 4 - +04 +Zone Etc/GMT-3 3 - +03 +Zone Etc/GMT-2 2 - +02 +Zone Etc/GMT-1 1 - +01 +Zone Etc/GMT+1 -1 - -01 +Zone Etc/GMT+2 -2 - -02 +Zone Etc/GMT+3 -3 - -03 +Zone Etc/GMT+4 -4 - -04 +Zone Etc/GMT+5 -5 - -05 +Zone Etc/GMT+6 -6 - -06 +Zone Etc/GMT+7 -7 - -07 +Zone Etc/GMT+8 -8 - -08 +Zone Etc/GMT+9 -9 - -09 +Zone Etc/GMT+10 -10 - -10 +Zone Etc/GMT+11 -11 - -11 +Zone Etc/GMT+12 -12 - -12
--- a/test/sun/util/calendar/zi/tzdata/europe Fri Jan 13 17:09:28 2017 +0000 +++ b/test/sun/util/calendar/zi/tzdata/europe Mon Jan 23 16:30:43 2017 +0000 @@ -98,8 +98,7 @@ # 1:00 CET CEST CEMT Central Europe # 1:00:14 SET Swedish (1879-1899)* # 2:00 EET EEST Eastern Europe -# 3:00 FET Further-eastern Europe (2011-2014)* -# 3:00 MSK MSD MSM* Minsk, Moscow +# 3:00 MSK MSD Moscow # From Peter Ilieve (1994-12-04), # The original six [EU members]: Belgium, France, (West) Germany, Italy, @@ -606,16 +605,33 @@ Rule E-Eur 1981 max - Mar lastSun 0:00 1:00 S Rule E-Eur 1996 max - Oct lastSun 0:00 0 - + +# Daylight saving time for Russia and the Soviet Union +# +# The 1917-1921 decree URLs are from Alexander Belopolsky (2016-08-23). + # Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S Rule Russia 1917 only - Jul 1 23:00 1:00 MST # Moscow Summer Time +# +# Decree No. 142 (1917-12-22) http://istmat.info/node/28137 Rule Russia 1917 only - Dec 28 0:00 0 MMT # Moscow Mean Time +# +# Decree No. 497 (1918-05-30) http://istmat.info/node/30001 Rule Russia 1918 only - May 31 22:00 2:00 MDST # Moscow Double Summer Time Rule Russia 1918 only - Sep 16 1:00 1:00 MST +# +# Decree No. 258 (1919-05-29) http://istmat.info/node/37949 Rule Russia 1919 only - May 31 23:00 2:00 MDST -Rule Russia 1919 only - Jul 1 2:00 1:00 MSD +# +Rule Russia 1919 only - Jul 1 0:00u 1:00 MSD Rule Russia 1919 only - Aug 16 0:00 0 MSK +# +# Decree No. 63 (1921-02-03) http://istmat.info/node/45840 Rule Russia 1921 only - Feb 14 23:00 1:00 MSD -Rule Russia 1921 only - Mar 20 23:00 2:00 MSM # Midsummer +# +# Decree No. 121 (1921-03-07) http://istmat.info/node/45949 +Rule Russia 1921 only - Mar 20 23:00 2:00 +05 +# Rule Russia 1921 only - Sep 1 0:00 1:00 MSD Rule Russia 1921 only - Oct 1 0:00 0 - # Act No. 925 of the Council of Ministers of the USSR (1980-10-24): @@ -798,8 +814,6 @@ # From Alexander Bokovoy (2014-10-09): # 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 -# From Paul Eggert (2014-10-08): -# Hence Belarus can share time zone abbreviations with Moscow again. # # Zone NAME GMTOFF RULES FORMAT [UNTIL] Zone Europe/Minsk 1:50:16 - LMT 1880 @@ -810,8 +824,7 @@ 3:00 Russia MSK/MSD 1990 3:00 - MSK 1991 Mar 31 2:00s 2:00 Russia EE%sT 2011 Mar 27 2:00s - 3:00 - FET 2014 Oct 26 1:00s - 3:00 - MSK + 3:00 - +03 # Belgium # @@ -1319,7 +1332,7 @@ # http://www.parlament-berlin.de/pds-fraktion.nsf/727459127c8b66ee8525662300459099/defc77cb784f180ac1256c2b0030274b/$FILE/bersarint.pdf # says that Bersarin issued an order to use Moscow time on May 20. # However, Moscow did not observe daylight saving in 1945, so -# this was equivalent to CEMT (GMT+3), not GMT+4. +# this was equivalent to UT +03, not +04. # Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S @@ -1510,73 +1523,84 @@ # But these events all occurred before the 1970 cutoff, # so record only the time in Rome. # -# From Paul Eggert (2006-03-22): -# For Italian DST we have three sources: Shanks & Pottenger, Whitman, and -# F. Pollastri -# Day-light Saving Time in Italy (2006-02-03) -# http://toi.iriti.cnr.it/uk/ienitlt.html -# ('FP' below), taken from an Italian National Electrotechnical Institute -# publication. When the three sources disagree, guess who's right, as follows: +# 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 +# force at the instant at which, according to the time specified in +# the 1st article, the 1st of November 1893 will begin...." # -# year FP Shanks&P. (S) Whitman (W) Go with: -# 1916 06-03 06-03 24:00 06-03 00:00 FP & W -# 09-30 09-30 24:00 09-30 01:00 FP; guess 24:00s -# 1917 04-01 03-31 24:00 03-31 00:00 FP & S -# 09-30 09-29 24:00 09-30 01:00 FP & W -# 1918 03-09 03-09 24:00 03-09 00:00 FP & S -# 10-06 10-05 24:00 10-06 01:00 FP & W -# 1919 03-01 03-01 24:00 03-01 00:00 FP & S -# 10-04 10-04 24:00 10-04 01:00 FP; guess 24:00s -# 1920 03-20 03-20 24:00 03-20 00:00 FP & S -# 09-18 09-18 24:00 10-01 01:00 FP; guess 24:00s -# 1944 04-02 04-03 02:00 S (see C-Eur) -# 09-16 10-02 03:00 FP; guess 24:00s -# 1945 09-14 09-16 24:00 FP; guess 24:00s -# 1970 05-21 05-31 00:00 S -# 09-20 09-27 00:00 S +# From Pierpaolo Bernardi (2016-10-20): +# 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 +# (2016-10-24): +# http://www.renzobaldini.it/le-ore-legali-in-italia/ +# has still different data for 1944. It divides Italy in two, as +# there were effectively two governments at the time, north of Gothic +# Line German controlled territory, official government RSI, and south +# of the Gothic Line, controlled by allied armies. +# +# From Brian Inglis (2016-10-23): +# Viceregal LEGISLATIVE DECREE. 14 September 1944, no. 219. +# Restoration of Standard Time. (044U0219) (OJ 62 of 30.9.1944) ... +# Given the R. law decreed on 1944-03-29, no. 92, by which standard time is +# 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 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. +# Model Rome's occupation by using using C-Eur rules from 1943-09-10 +# to 1944-06-04; although Rome was an open city during this period, it +# was effectively controlled by Germany. # # Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S -Rule Italy 1916 only - Jun 3 0:00s 1:00 S -Rule Italy 1916 only - Oct 1 0:00s 0 - -Rule Italy 1917 only - Apr 1 0:00s 1:00 S -Rule Italy 1917 only - Sep 30 0:00s 0 - -Rule Italy 1918 only - Mar 10 0:00s 1:00 S -Rule Italy 1918 1919 - Oct Sun>=1 0:00s 0 - -Rule Italy 1919 only - Mar 2 0:00s 1:00 S -Rule Italy 1920 only - Mar 21 0:00s 1:00 S -Rule Italy 1920 only - Sep 19 0:00s 0 - -Rule Italy 1940 only - Jun 15 0:00s 1:00 S -Rule Italy 1944 only - Sep 17 0:00s 0 - -Rule Italy 1945 only - Apr 2 2:00 1:00 S -Rule Italy 1945 only - Sep 15 0:00s 0 - -Rule Italy 1946 only - Mar 17 2:00s 1:00 S -Rule Italy 1946 only - Oct 6 2:00s 0 - -Rule Italy 1947 only - Mar 16 0:00s 1:00 S -Rule Italy 1947 only - Oct 5 0:00s 0 - -Rule Italy 1948 only - Feb 29 2:00s 1:00 S -Rule Italy 1948 only - Oct 3 2:00s 0 - -Rule Italy 1966 1968 - May Sun>=22 0:00 1:00 S -Rule Italy 1966 1969 - Sep Sun>=22 0:00 0 - -Rule Italy 1969 only - Jun 1 0:00 1:00 S -Rule Italy 1970 only - May 31 0:00 1:00 S -Rule Italy 1970 only - Sep lastSun 0:00 0 - -Rule Italy 1971 1972 - May Sun>=22 0:00 1:00 S -Rule Italy 1971 only - Sep lastSun 1:00 0 - -Rule Italy 1972 only - Oct 1 0:00 0 - -Rule Italy 1973 only - Jun 3 0:00 1:00 S -Rule Italy 1973 1974 - Sep lastSun 0:00 0 - -Rule Italy 1974 only - May 26 0:00 1:00 S -Rule Italy 1975 only - Jun 1 0:00s 1:00 S -Rule Italy 1975 1977 - Sep lastSun 0:00s 0 - -Rule Italy 1976 only - May 30 0:00s 1:00 S -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 - +Rule Italy 1916 only - Jun 3 24:00 1:00 S +Rule Italy 1916 1917 - Sep 30 24:00 0 - +Rule Italy 1917 only - Mar 31 24:00 1:00 S +Rule Italy 1918 only - Mar 9 24:00 1:00 S +Rule Italy 1918 only - Oct 6 24:00 0 - +Rule Italy 1919 only - Mar 1 24:00 1:00 S +Rule Italy 1919 only - Oct 4 24:00 0 - +Rule Italy 1920 only - Mar 20 24:00 1:00 S +Rule Italy 1920 only - Sep 18 24:00 0 - +Rule Italy 1940 only - Jun 14 24:00 1:00 S +Rule Italy 1942 only - Nov 2 2:00s 0 - +Rule Italy 1943 only - Mar 29 2:00s 1:00 S +Rule Italy 1943 only - Oct 4 2:00s 0 - +Rule Italy 1944 only - Apr 2 2:00s 1:00 S +Rule Italy 1944 only - Sep 17 2:00s 0 - +Rule Italy 1945 only - Apr 2 2:00 1:00 S +Rule Italy 1945 only - Sep 15 1:00 0 - +Rule Italy 1946 only - Mar 17 2:00s 1:00 S +Rule Italy 1946 only - Oct 6 2:00s 0 - +Rule Italy 1947 only - Mar 16 0:00s 1:00 S +Rule Italy 1947 only - Oct 5 0:00s 0 - +Rule Italy 1948 only - Feb 29 2:00s 1:00 S +Rule Italy 1948 only - Oct 3 2:00s 0 - +Rule Italy 1966 1968 - May Sun>=22 0:00s 1:00 S +Rule Italy 1966 only - Sep 24 24:00 0 - +Rule Italy 1967 1969 - Sep Sun>=22 0:00s 0 - +Rule Italy 1969 only - Jun 1 0:00s 1:00 S +Rule Italy 1970 only - May 31 0:00s 1:00 S +Rule Italy 1970 only - Sep lastSun 0:00s 0 - +Rule Italy 1971 1972 - May Sun>=22 0:00s 1:00 S +Rule Italy 1971 only - Sep lastSun 0:00s 0 - +Rule Italy 1972 only - Oct 1 0:00s 0 - +Rule Italy 1973 only - Jun 3 0:00s 1:00 S +Rule Italy 1973 1974 - Sep lastSun 0:00s 0 - +Rule Italy 1974 only - May 26 0:00s 1:00 S +Rule Italy 1975 only - Jun 1 0:00s 1:00 S +Rule Italy 1975 1977 - Sep lastSun 0:00s 0 - +Rule Italy 1976 only - May 30 0:00s 1:00 S +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 - 0:49:56 - RMT 1893 Nov 1 0:00s # Rome Mean - 1:00 Italy CE%sT 1942 Nov 2 2:00s - 1:00 C-Eur CE%sT 1944 Jul + 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 1:00 Italy CE%sT 1980 1:00 EU CE%sT @@ -1775,6 +1799,10 @@ # See Europe/Belgrade. # Malta +# +# From Paul Eggert (2016-10-21): +# Assume 1900-1972 was like Rome, overriding Shanks. +# # Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S Rule Malta 1973 only - Mar 31 0:00s 1:00 S Rule Malta 1973 only - Sep 29 0:00s 0 - @@ -1785,8 +1813,6 @@ Rule Malta 1980 only - Mar 31 2:00 1:00 S # Zone NAME GMTOFF RULES FORMAT [UNTIL] Zone Europe/Malta 0:58:04 - LMT 1893 Nov 2 0:00s # Valletta - 1:00 Italy CE%sT 1942 Nov 2 2:00s - 1:00 C-Eur CE%sT 1945 Apr 2 2:00s 1:00 Italy CE%sT 1973 Mar 31 1:00 Malta CE%sT 1981 1:00 EU CE%sT @@ -1918,7 +1944,7 @@ # Amsterdam mean time. # The data entries before 1945 are taken from -# http://www.phys.uu.nl/~vgent/wettijd/wettijd.htm +# http://www.staff.science.uu.nl/~gent0113/wettijd/wettijd.htm # Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S Rule Neth 1916 only - May 1 0:00 1:00 NST # Netherlands Summer Time @@ -2283,7 +2309,6 @@ # http://www.worldtimezone.com/dst_news/dst_news_russia-map-2014-07.html # From Paul Eggert (2006-03-22): -# Except for Moscow after 1919-07-01, I invented the time zone abbreviations. # Moscow time zone abbreviations after 1919-07-01, and Moscow rules after 1991, # are from Andrey A. Chernov. The rest is from Shanks & Pottenger, # except we follow Chernov's report that 1992 DST transitions were Sat @@ -2359,7 +2384,7 @@ 2:00 Poland CE%sT 1946 3:00 Russia MSK/MSD 1989 Mar 26 2:00s 2:00 Russia EE%sT 2011 Mar 27 2:00s - 3:00 - FET 2014 Oct 26 2:00s + 3:00 - +03 2014 Oct 26 2:00s 2:00 - EET @@ -2412,6 +2437,16 @@ # 78 RU-SPE Saint Petersburg # 83 RU-NEN Nenets Autonomous Okrug +# From Paul Eggert (2016-08-23): +# The Soviets switched to UT-based time in 1919. Decree No. 59 +# (1919-02-08) http://istmat.info/node/35567 established UT-based time +# zones, and Decree No. 147 (1919-03-29) http://istmat.info/node/35854 +# specified a transition date of 1919-07-01, apparently at 00:00 UT. +# No doubt only the Soviet-controlled regions switched on that date; +# later transitions to UT-based time in other parts of Russia are +# taken from what appear to be guesses by Shanks. +# (Thanks to Alexander Belopolsky for pointers to the decrees.) + # From Stepan Golosunov (2016-03-07): # 11. Regions-violators, 1981-1982. # Wikipedia refers to @@ -2453,7 +2488,7 @@ # attributes the 1982 changes to the Act of the Council of Ministers # of the USSR No. 126 from 18.02.1982. 1980-925.txt also adds # Udmurtia to the list of affected territories and lists Khatangsky -# district separately from Taymyr Autonomous Okurg. Probably erroneously. +# district separately from Taymyr Autonomous Okrug. Probably erroneously. # # The affected territories are currently listed under Europe/Moscow, # Asia/Yekaterinburg and Asia/Krasnoyarsk. @@ -2513,7 +2548,7 @@ Zone Europe/Moscow 2:30:17 - LMT 1880 2:30:17 - MMT 1916 Jul 3 # Moscow Mean Time - 2:31:19 Russia %s 1919 Jul 1 2:00 + 2:31:19 Russia %s 1919 Jul 1 0:00u 3:00 Russia %s 1921 Oct 3:00 Russia MSK/MSD 1922 Oct 2:00 - EET 1930 Jun 21 @@ -2596,22 +2631,21 @@ # The 1988 transition is from USSR act No. 5 (1988-01-04). Zone Europe/Volgograd 2:57:40 - LMT 1920 Jan 3 - 3:00 - TSAT 1925 Apr 6 # Tsaritsyn Time - 3:00 - STAT 1930 Jun 21 # Stalingrad Time - 4:00 - STAT 1961 Nov 11 - 4:00 Russia VOL%sT 1988 Mar 27 2:00s # Volgograd T - 3:00 Russia VOL%sT 1991 Mar 31 2:00s - 4:00 - VOLT 1992 Mar 29 2:00s - 3:00 Russia MSK/MSD 2011 Mar 27 2:00s - 4:00 - MSK 2014 Oct 26 2:00s - 3:00 - MSK + 3:00 - +03 1930 Jun 21 + 4:00 - +04 1961 Nov 11 + 4:00 Russia +04/+05 1988 Mar 27 2:00s + 3:00 Russia +03/+04 1991 Mar 31 2:00s + 4:00 - +04 1992 Mar 29 2:00s + 3:00 Russia +03/+04 2011 Mar 27 2:00s + 4:00 - +04 2014 Oct 26 2:00s + 3:00 - +03 # From Paul Eggert (2016-03-18): # Europe/Kirov covers: # 43 RU-KIR Kirov Oblast # The 1989 transition is from USSR act No. 227 (1989-03-14). # -Zone Europe/Kirov 3:18:48 - LMT 1919 Jul 1 2:00 +Zone Europe/Kirov 3:18:48 - LMT 1919 Jul 1 0:00u 3:00 - +03 1930 Jun 21 4:00 Russia +04/+05 1989 Mar 26 2:00s 3:00 Russia +03/+04 1991 Mar 31 2:00s @@ -2629,16 +2663,16 @@ # Byalokoz 1919 says Samara was 3:20:20. # The 1989 transition is from USSR act No. 227 (1989-03-14). -Zone Europe/Samara 3:20:20 - LMT 1919 Jul 1 2:00 - 3:00 - SAMT 1930 Jun 21 # Samara Time - 4:00 - SAMT 1935 Jan 27 - 4:00 Russia KUY%sT 1989 Mar 26 2:00s # Kuybyshev - 3:00 Russia MSK/MSD 1991 Mar 31 2:00s - 2:00 Russia EE%sT 1991 Sep 29 2:00s - 3:00 - SAMT 1991 Oct 20 3:00 - 4:00 Russia SAM%sT 2010 Mar 28 2:00s - 3:00 Russia SAM%sT 2011 Mar 27 2:00s - 4:00 - SAMT +Zone Europe/Samara 3:20:20 - LMT 1919 Jul 1 0:00u + 3:00 - +03 1930 Jun 21 + 4:00 - +04 1935 Jan 27 + 4:00 Russia +04/+05 1989 Mar 26 2:00s + 3:00 Russia +03/+04 1991 Mar 31 2:00s + 2:00 Russia +02/+03 1991 Sep 29 2:00s + 3:00 - +03 1991 Oct 20 3:00 + 4:00 Russia +04/+05 2010 Mar 28 2:00s + 3:00 Russia +03/+04 2011 Mar 27 2:00s + 4:00 - +04 # From Paul Eggert (2016-03-18): # Europe/Ulyanovsk covers: @@ -2653,7 +2687,7 @@ # From Matt Johnson (2016-03-09): # http://publication.pravo.gov.ru/Document/View/0001201603090051 -Zone Europe/Ulyanovsk 3:13:36 - LMT 1919 Jul 1 2:00 +Zone Europe/Ulyanovsk 3:13:36 - LMT 1919 Jul 1 0:00u 3:00 - +03 1930 Jun 21 4:00 Russia +04/+05 1989 Mar 26 2:00s 3:00 Russia +03/+04 1991 Mar 31 2:00s @@ -2685,12 +2719,12 @@ Zone Asia/Yekaterinburg 4:02:33 - LMT 1916 Jul 3 3:45:05 - PMT 1919 Jul 15 4:00 - 4:00 - SVET 1930 Jun 21 # Sverdlovsk Time - 5:00 Russia SVE%sT 1991 Mar 31 2:00s - 4:00 Russia SVE%sT 1992 Jan 19 2:00s - 5:00 Russia YEK%sT 2011 Mar 27 2:00s - 6:00 - YEKT 2014 Oct 26 2:00s - 5:00 - YEKT + 4:00 - +04 1930 Jun 21 + 5:00 Russia +05/+06 1991 Mar 31 2:00s + 4:00 Russia +04/+05 1992 Jan 19 2:00s + 5:00 Russia +05/+06 2011 Mar 27 2:00s + 6:00 - +06 2014 Oct 26 2:00s + 5:00 - +05 # From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2001-08-25): @@ -2700,12 +2734,12 @@ # Byalokoz 1919 says Omsk was 4:53:30. Zone Asia/Omsk 4:53:30 - LMT 1919 Nov 14 - 5:00 - OMST 1930 Jun 21 # Omsk Time - 6:00 Russia OMS%sT 1991 Mar 31 2:00s - 5:00 Russia OMS%sT 1992 Jan 19 2:00s - 6:00 Russia OMS%sT 2011 Mar 27 2:00s - 7:00 - OMST 2014 Oct 26 2:00s - 6:00 - OMST + 5:00 - +05 1930 Jun 21 + 6:00 Russia +06/+07 1991 Mar 31 2:00s + 5:00 Russia +05/+06 1992 Jan 19 2:00s + 6:00 Russia +06/+07 2011 Mar 27 2:00s + 7:00 - +07 2014 Oct 26 2:00s + 6:00 - +06 # From Paul Eggert (2016-02-22): # Asia/Barnaul covers: @@ -2785,7 +2819,7 @@ # Note that time belts (numbered from 2 (Moscow) to 12 according to their # GMT/UTC offset and having too many exceptions like regions formally # belonging to one belt but using time from another) were replaced -# with time zones in 2011 with different numberings (there was a +# with time zones in 2011 with different numbering (there was a # 2-hour gap between second and third zones in 2011-2014). # From Stepan Golosunov (2016-04-12): @@ -2868,12 +2902,12 @@ # Byalokoz 1919 says Krasnoyarsk was 6:11:26. Zone Asia/Krasnoyarsk 6:11:26 - LMT 1920 Jan 6 - 6:00 - KRAT 1930 Jun 21 # Krasnoyarsk Time - 7:00 Russia KRA%sT 1991 Mar 31 2:00s - 6:00 Russia KRA%sT 1992 Jan 19 2:00s - 7:00 Russia KRA%sT 2011 Mar 27 2:00s - 8:00 - KRAT 2014 Oct 26 2:00s - 7:00 - KRAT + 6:00 - +06 1930 Jun 21 + 7:00 Russia +07/+08 1991 Mar 31 2:00s + 6:00 Russia +06/+07 1992 Jan 19 2:00s + 7:00 Russia +07/+08 2011 Mar 27 2:00s + 8:00 - +08 2014 Oct 26 2:00s + 7:00 - +07 # From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2001-08-25): @@ -2890,12 +2924,12 @@ Zone Asia/Irkutsk 6:57:05 - LMT 1880 6:57:05 - IMT 1920 Jan 25 # Irkutsk Mean Time - 7:00 - IRKT 1930 Jun 21 # Irkutsk Time - 8:00 Russia IRK%sT 1991 Mar 31 2:00s - 7:00 Russia IRK%sT 1992 Jan 19 2:00s - 8:00 Russia IRK%sT 2011 Mar 27 2:00s - 9:00 - IRKT 2014 Oct 26 2:00s - 8:00 - IRKT + 7:00 - +07 1930 Jun 21 + 8:00 Russia +08/+09 1991 Mar 31 2:00s + 7:00 Russia +07/+08 1992 Jan 19 2:00s + 8:00 Russia +08/+09 2011 Mar 27 2:00s + 9:00 - +09 2014 Oct 26 2:00s + 8:00 - +08 # From Tim Parenti (2014-07-06): @@ -2912,13 +2946,13 @@ # http://publication.pravo.gov.ru/Document/View/0001201512300107 Zone Asia/Chita 7:33:52 - LMT 1919 Dec 15 - 8:00 - YAKT 1930 Jun 21 # Yakutsk Time - 9:00 Russia YAK%sT 1991 Mar 31 2:00s - 8:00 Russia YAK%sT 1992 Jan 19 2:00s - 9:00 Russia YAK%sT 2011 Mar 27 2:00s - 10:00 - YAKT 2014 Oct 26 2:00s - 8:00 - IRKT 2016 Mar 27 2:00 - 9:00 - YAKT + 8:00 - +08 1930 Jun 21 + 9:00 Russia +09/+10 1991 Mar 31 2:00s + 8:00 Russia +08/+09 1992 Jan 19 2:00s + 9:00 Russia +09/+10 2011 Mar 27 2:00s + 10:00 - +10 2014 Oct 26 2:00s + 8:00 - +08 2016 Mar 27 2:00 + 9:00 - +09 # From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2009-11-29): @@ -2958,12 +2992,12 @@ # Byalokoz 1919 says Yakutsk was 8:38:58. Zone Asia/Yakutsk 8:38:58 - LMT 1919 Dec 15 - 8:00 - YAKT 1930 Jun 21 # Yakutsk Time - 9:00 Russia YAK%sT 1991 Mar 31 2:00s - 8:00 Russia YAK%sT 1992 Jan 19 2:00s - 9:00 Russia YAK%sT 2011 Mar 27 2:00s - 10:00 - YAKT 2014 Oct 26 2:00s - 9:00 - YAKT + 8:00 - +08 1930 Jun 21 + 9:00 Russia +09/+10 1991 Mar 31 2:00s + 8:00 Russia +08/+09 1992 Jan 19 2:00s + 9:00 Russia +09/+10 2011 Mar 27 2:00s + 10:00 - +10 2014 Oct 26 2:00s + 9:00 - +09 # From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2009-11-29): @@ -2981,12 +3015,12 @@ # Go with Byalokoz. Zone Asia/Vladivostok 8:47:31 - LMT 1922 Nov 15 - 9:00 - VLAT 1930 Jun 21 # Vladivostok Time - 10:00 Russia VLA%sT 1991 Mar 31 2:00s - 9:00 Russia VLA%sT 1992 Jan 19 2:00s - 10:00 Russia VLA%sT 2011 Mar 27 2:00s - 11:00 - VLAT 2014 Oct 26 2:00s - 10:00 - VLAT + 9:00 - +09 1930 Jun 21 + 10:00 Russia +10/+11 1991 Mar 31 2:00s + 9:00 Russia +09/+10 1992 Jan 19 2:00s + 10:00 Russia +10/+11 2011 Mar 27 2:00s + 11:00 - +11 2014 Oct 26 2:00s + 10:00 - +10 # From Tim Parenti (2014-07-03): @@ -3004,14 +3038,14 @@ # This transition is no doubt wrong, but we have no better info. Zone Asia/Khandyga 9:02:13 - LMT 1919 Dec 15 - 8:00 - YAKT 1930 Jun 21 # Yakutsk Time - 9:00 Russia YAK%sT 1991 Mar 31 2:00s - 8:00 Russia YAK%sT 1992 Jan 19 2:00s - 9:00 Russia YAK%sT 2004 - 10:00 Russia VLA%sT 2011 Mar 27 2:00s - 11:00 - VLAT 2011 Sep 13 0:00s # Decree 725? - 10:00 - YAKT 2014 Oct 26 2:00s - 9:00 - YAKT + 8:00 - +08 1930 Jun 21 + 9:00 Russia +09/+10 1991 Mar 31 2:00s + 8:00 Russia +08/+09 1992 Jan 19 2:00s + 9:00 Russia +09/+10 2004 + 10:00 Russia +10/+11 2011 Mar 27 2:00s + 11:00 - +11 2011 Sep 13 0:00s # Decree 725? + 10:00 - +10 2014 Oct 26 2:00s + 9:00 - +09 # From Tim Parenti (2014-07-03): @@ -3027,15 +3061,14 @@ # The Zone name should be Asia/Yuzhno-Sakhalinsk, but that's too long. Zone Asia/Sakhalin 9:30:48 - LMT 1905 Aug 23 - 9:00 - JCST 1937 Oct 1 - 9:00 - JST 1945 Aug 25 - 11:00 Russia SAK%sT 1991 Mar 31 2:00s # Sakhalin T - 10:00 Russia SAK%sT 1992 Jan 19 2:00s - 11:00 Russia SAK%sT 1997 Mar lastSun 2:00s - 10:00 Russia SAK%sT 2011 Mar 27 2:00s - 11:00 - SAKT 2014 Oct 26 2:00s - 10:00 - SAKT 2016 Mar 27 2:00s - 11:00 - SAKT + 9:00 - +09 1945 Aug 25 + 11:00 Russia +11/+12 1991 Mar 31 2:00s # Sakhalin T + 10:00 Russia +10/+11 1992 Jan 19 2:00s + 11:00 Russia +11/+12 1997 Mar lastSun 2:00s + 10:00 Russia +10/+11 2011 Mar 27 2:00s + 11:00 - +11 2014 Oct 26 2:00s + 10:00 - +10 2016 Mar 27 2:00s + 11:00 - +11 # From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2009-11-29): @@ -3058,13 +3091,13 @@ # http://publication.pravo.gov.ru/Document/View/0001201604050038 Zone Asia/Magadan 10:03:12 - LMT 1924 May 2 - 10:00 - MAGT 1930 Jun 21 # Magadan Time - 11:00 Russia MAG%sT 1991 Mar 31 2:00s - 10:00 Russia MAG%sT 1992 Jan 19 2:00s - 11:00 Russia MAG%sT 2011 Mar 27 2:00s - 12:00 - MAGT 2014 Oct 26 2:00s - 10:00 - MAGT 2016 Apr 24 2:00s - 11:00 - MAGT + 10:00 - +10 1930 Jun 21 # Magadan Time + 11:00 Russia +11/+12 1991 Mar 31 2:00s + 10:00 Russia +10/+11 1992 Jan 19 2:00s + 11:00 Russia +11/+12 2011 Mar 27 2:00s + 12:00 - +12 2014 Oct 26 2:00s + 10:00 - +10 2016 Apr 24 2:00s + 11:00 - +11 # From Tim Parenti (2014-07-06): @@ -3107,17 +3140,14 @@ # in Russian.) In addition, Srednekolymsk appears to be a much older # settlement and the population of Zyryanka seems to be declining. # Go with Srednekolymsk. -# -# Since Magadan Oblast moves to UTC+10 on 2014-10-26, we cannot keep using MAGT -# as the abbreviation. Use SRET instead. Zone Asia/Srednekolymsk 10:14:52 - LMT 1924 May 2 - 10:00 - MAGT 1930 Jun 21 # Magadan Time - 11:00 Russia MAG%sT 1991 Mar 31 2:00s - 10:00 Russia MAG%sT 1992 Jan 19 2:00s - 11:00 Russia MAG%sT 2011 Mar 27 2:00s - 12:00 - MAGT 2014 Oct 26 2:00s - 11:00 - SRET # Srednekolymsk Time + 10:00 - +10 1930 Jun 21 + 11:00 Russia +11/+12 1991 Mar 31 2:00s + 10:00 Russia +10/+11 1992 Jan 19 2:00s + 11:00 Russia +11/+12 2011 Mar 27 2:00s + 12:00 - +12 2014 Oct 26 2:00s + 11:00 - +11 # From Tim Parenti (2014-07-03): @@ -3135,14 +3165,14 @@ # UTC+12 since at least then, too. Zone Asia/Ust-Nera 9:32:54 - LMT 1919 Dec 15 - 8:00 - YAKT 1930 Jun 21 # Yakutsk Time - 9:00 Russia YAKT 1981 Apr 1 - 11:00 Russia MAG%sT 1991 Mar 31 2:00s - 10:00 Russia MAG%sT 1992 Jan 19 2:00s - 11:00 Russia MAG%sT 2011 Mar 27 2:00s - 12:00 - MAGT 2011 Sep 13 0:00s # Decree 725? - 11:00 - VLAT 2014 Oct 26 2:00s - 10:00 - VLAT + 8:00 - +08 1930 Jun 21 + 9:00 Russia +09/+10 1981 Apr 1 + 11:00 Russia +11/+12 1991 Mar 31 2:00s + 10:00 Russia +10/+11 1992 Jan 19 2:00s + 11:00 Russia +11/+12 2011 Mar 27 2:00s + 12:00 - +12 2011 Sep 13 0:00s # Decree 725? + 11:00 - +11 2014 Oct 26 2:00s + 10:00 - +10 # From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2001-08-25): @@ -3155,12 +3185,12 @@ # The Zone name should be Asia/Petropavlovsk-Kamchatski or perhaps # Asia/Petropavlovsk-Kamchatsky, but these are too long. Zone Asia/Kamchatka 10:34:36 - LMT 1922 Nov 10 - 11:00 - PETT 1930 Jun 21 # P-K Time - 12:00 Russia PET%sT 1991 Mar 31 2:00s - 11:00 Russia PET%sT 1992 Jan 19 2:00s - 12:00 Russia PET%sT 2010 Mar 28 2:00s - 11:00 Russia PET%sT 2011 Mar 27 2:00s - 12:00 - PETT + 11:00 - +11 1930 Jun 21 + 12:00 Russia +12/+13 1991 Mar 31 2:00s + 11:00 Russia +11/+12 1992 Jan 19 2:00s + 12:00 Russia +12/+13 2010 Mar 28 2:00s + 11:00 Russia +11/+12 2011 Mar 27 2:00s + 12:00 - +12 # From Tim Parenti (2014-07-03): @@ -3168,13 +3198,13 @@ # 87 RU-CHU Chukotka Autonomous Okrug Zone Asia/Anadyr 11:49:56 - LMT 1924 May 2 - 12:00 - ANAT 1930 Jun 21 # Anadyr Time - 13:00 Russia ANA%sT 1982 Apr 1 0:00s - 12:00 Russia ANA%sT 1991 Mar 31 2:00s - 11:00 Russia ANA%sT 1992 Jan 19 2:00s - 12:00 Russia ANA%sT 2010 Mar 28 2:00s - 11:00 Russia ANA%sT 2011 Mar 27 2:00s - 12:00 - ANAT + 12:00 - +12 1930 Jun 21 + 13:00 Russia +13/+14 1982 Apr 1 0:00s + 12:00 Russia +12/+13 1991 Mar 31 2:00s + 11:00 Russia +11/+12 1992 Jan 19 2:00s + 12:00 Russia +12/+13 2010 Mar 28 2:00s + 11:00 Russia +11/+12 2011 Mar 27 2:00s + 12:00 - +12 # San Marino @@ -3433,22 +3463,24 @@ # Turkey -# From Amar Devegowda (2007-01-03): -# The time zone rules for Istanbul, Turkey have not been changed for years now. -# ... The latest rules are available at: -# http://www.timeanddate.com/worldclock/timezone.html?n=107 -# From Steffen Thorsen (2007-01-03): -# I have been able to find press records back to 1996 which all say that -# DST started 01:00 local time and end at 02:00 local time. I am not sure -# what happened before that. One example for each year from 1996 to 2001: -# http://newspot.byegm.gov.tr/arsiv/1996/21/N4.htm -# http://www.byegm.gov.tr/YAYINLARIMIZ/CHR/ING97/03/97X03X25.TXT -# http://www.byegm.gov.tr/YAYINLARIMIZ/CHR/ING98/03/98X03X02.HTM -# http://www.byegm.gov.tr/YAYINLARIMIZ/CHR/ING99/10/99X10X26.HTM#%2016 -# http://www.byegm.gov.tr/YAYINLARIMIZ/CHR/ING2000/03/00X03X06.HTM#%2021 -# http://www.byegm.gov.tr/YAYINLARIMIZ/CHR/ING2001/03/23x03x01.HTM#%2027 -# From Paul Eggert (2007-01-03): -# Prefer the above source to Shanks & Pottenger for time stamps after 1990. +# 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/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): +# Prefer the above sources to Shanks & Pottenger for time stamps after 1985. # From Steffen Thorsen (2007-03-09): # Starting 2007 though, it seems that they are adopting EU's 1:00 UTC @@ -3495,6 +3527,14 @@ # Engineered Standard Time," said Twitter user @aysekarahasan. # http://www.bbc.com/news/world-europe-34631326 +# From Burak AYDIN (2016-09-08): +# Turkey will stay in Daylight Saving Time even in winter.... +# http://www.resmigazete.gov.tr/eskiler/2016/09/20160908-2.pdf +# +# From Paul Eggert (2016-09-07): +# The change is permanent, so this is the new standard time in Turkey. +# It takes effect today, which is not much notice. + # Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S Rule Turkey 1916 only - May 1 0:00 1:00 S Rule Turkey 1916 only - Oct 1 0:00 0 - @@ -3549,16 +3589,16 @@ 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 1986 1990 - Mar lastSun 2:00s 1:00 S -Rule Turkey 1986 1990 - Sep lastSun 2:00s 0 - -Rule Turkey 1991 2006 - Mar lastSun 1:00s 1:00 S -Rule Turkey 1991 1995 - Sep lastSun 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 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 TR%sT 1985 Apr 20 # Turkey Time + 3:00 Turkey +03/+04 1985 Apr 20 2:00 Turkey EE%sT 2007 2:00 EU EE%sT 2011 Mar 27 1:00u 2:00 - EET 2011 Mar 28 1:00u @@ -3566,7 +3606,8 @@ 2:00 - EET 2014 Mar 31 1:00u 2:00 EU EE%sT 2015 Oct 25 1:00u 2:00 1:00 EEST 2015 Nov 8 1:00u - 2:00 EU EE%sT + 2:00 EU EE%sT 2016 Sep 7 + 3:00 - +03 Link Europe/Istanbul Asia/Istanbul # Istanbul is in both continents. # Ukraine
--- a/test/sun/util/calendar/zi/tzdata/factory Fri Jan 13 17:09:28 2017 +0000 +++ b/test/sun/util/calendar/zi/tzdata/factory Mon Jan 23 16:30:43 2017 +0000 @@ -24,9 +24,10 @@ # This file is in the public domain, so clarified as of # 2009-05-17 by Arthur David Olson. -# For companies who don't want to put time zone specification in -# their installation procedures. When users run date, they'll get the message. -# Also useful for the "comp.sources" version. +# For distributors who don't want to put time zone specification in +# their installation procedures. Users that run 'date' will get the +# time zone abbreviation "-00", indicating that the actual time zone +# is unknown. # Zone NAME GMTOFF RULES FORMAT -Zone Factory 0 - "Local time zone must be set--see zic manual page" +Zone Factory 0 - -00
--- a/test/sun/util/calendar/zi/tzdata/leapseconds Fri Jan 13 17:09:28 2017 +0000 +++ b/test/sun/util/calendar/zi/tzdata/leapseconds Mon Jan 23 16:30:43 2017 +0000 @@ -79,6 +79,7 @@ Leap 2008 Dec 31 23:59:60 + S Leap 2012 Jun 30 23:59:60 + S Leap 2015 Jun 30 23:59:60 + S +Leap 2016 Dec 31 23:59:60 + S -# Updated through IERS Bulletin C51 -# File expires on: 28 December 2016 +# Updated through IERS Bulletin C52 +# File expires on: 28 June 2017
--- a/test/sun/util/calendar/zi/tzdata/northamerica Fri Jan 13 17:09:28 2017 +0000 +++ b/test/sun/util/calendar/zi/tzdata/northamerica Mon Jan 23 16:30:43 2017 +0000 @@ -47,8 +47,32 @@ # was the result of his proposals at the Convention of Railroad Trunk Lines # in New York City (1869-10). His 1870 proposal was based on Washington, DC, # but in 1872-05 he moved the proposed origin to Greenwich. -# His proposal was adopted by the railroads on 1883-11-18 at 12:00, -# and the most of the country soon followed suit. + +# From Paul Eggert (2016-09-21): +# Dowd's proposal left many details unresolved, such as where to draw +# lines between time zones. The key individual who made time zones +# work in the US was William Frederick Allen - railway engineer, +# managing editor of the Travelers' Guide, and secretary of the +# General Time Convention, a railway standardization group. Allen +# spent months in dialogs with scientific and railway leaders, +# developed a workable plan to institute time zones, and presented it +# to the General Time Convention on 1883-04-11, saying that his plan +# meant "local time would be practically abolished" - a plus for +# railway scheduling. By the next convention on 1883-10-11 nearly all +# railroads had agreed and it took effect on 1883-11-18 at 12:00. +# That Sunday was called the "day of two noons", as the eastern parts +# of the new zones observed noon twice. Allen witnessed the +# transition in New York City, writing: +# +# I heard the bells of St. Paul's strike on the old time. Four +# minutes later, obedient to the electrical signal from the Naval +# Observatory ... the time-ball made its rapid descent, the chimes +# of old Trinity rang twelve measured strokes, and local time was +# abandoned, probably forever. +# +# Most of the US soon followed suit. See: +# Bartky IR. The adoption of standard time. Technol Cult 1989 Jan;30(1):25-56. +# http://dx.doi.org/10.2307/3105430 # From Paul Eggert (2005-04-16): # That 1883 transition occurred at 12:00 new time, not at 12:00 old time. @@ -436,11 +460,42 @@ # north of the Salmon River, and the towns of Burgdorf and Warren), # Nevada (except West Wendover), Oregon (except the northern 3/4 of # Malheur county), and Washington + +# From Paul Eggert (2016-08-20): +# In early February 1948, in response to California's electricity shortage, +# PG&E changed power frequency from 60 to 59.5 Hz during daylight hours, +# causing electric clocks to lose six minutes per day. (This did not change +# legal time, and is not part of the data here.) See: +# Ross SA. An energy crisis from the past: Northern California in 1948. +# Working Paper No. 8, Institute of Governmental Studies, UC Berkeley, +# 1973-11. http://escholarship.org/uc/item/8x22k30c +# +# In another measure to save electricity, DST was instituted from 1948-03-14 +# at 02:01 to 1949-01-16 at 02:00, with the governor having the option to move +# the fallback transition earlier. See pages 3-4 of: +# http://clerk.assembly.ca.gov/sites/clerk.assembly.ca.gov/files/archive/Statutes/1948/48Vol1_Chapters.pdf +# +# In response: +# +# Governor Warren received a torrent of objecting mail, and it is not too much +# to speculate that the objections to Daylight Saving Time were one important +# factor in the defeat of the Dewey-Warren Presidential ticket in California. +# -- Ross, p 25 +# +# On December 8 the governor exercised the option, setting the date to January 1 +# (LA Times 1948-12-09). The transition time was 02:00 (LA Times 1949-01-01). +# +# Despite the controversy, in 1949 California voters approved Proposition 12, +# which established DST from April's last Sunday at 01:00 until September's +# last Sunday at 02:00. This was amended by 1962's Proposition 6, which changed +# the fall-back date to October's last Sunday. See: +# http://repository.uchastings.edu/cgi/viewcontent.cgi?article=1501&context=ca_ballot_props +# http://repository.uchastings.edu/cgi/viewcontent.cgi?article=1636&context=ca_ballot_props # # Rule NAME FROM TO TYPE IN ON AT SAVE LETTER -Rule CA 1948 only - Mar 14 2:00 1:00 D +Rule CA 1948 only - Mar 14 2:01 1:00 D Rule CA 1949 only - Jan 1 2:00 0 S -Rule CA 1950 1966 - Apr lastSun 2:00 1:00 D +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] @@ -3304,7 +3359,7 @@ # indicating that the normal ET rules are followed. # # From Paul Eggert (2014-08-19): -# The 2014-08-13 Cabinet meeting decided to stay on UTC-4 year-round. See: +# The 2014-08-13 Cabinet meeting decided to stay on UT -04 year-round. See: # http://tcweeklynews.com/daylight-savings-time-to-be-maintained-p5353-127.htm # Model this as a switch from EST/EDT to AST ... # From Chris Walton (2014-11-04):
--- a/test/sun/util/calendar/zi/tzdata/southamerica Fri Jan 13 17:09:28 2017 +0000 +++ b/test/sun/util/calendar/zi/tzdata/southamerica Mon Jan 23 16:30:43 2017 +0000 @@ -433,9 +433,9 @@ # stuck on Summer daylight savings time even though the summer is over. # From Paul Eggert (2013-09-05): -# Perhaps San Luis operates on the legal fiction that it is at UTC-4 +# Perhaps San Luis operates on the legal fiction that it is at -04 # with perpetual summer time, but ordinary usage typically seems to -# just say it's at UTC-3; see, for example, +# just say it's at -03; see, for example, # http://es.wikipedia.org/wiki/Hora_oficial_argentina # We've documented similar situations as being plain changes to # standard time, so let's do that here too. This does not change UTC
--- a/test/sun/util/calendar/zi/tzdata/zone.tab Fri Jan 13 17:09:28 2017 +0000 +++ b/test/sun/util/calendar/zi/tzdata/zone.tab Mon Jan 23 16:30:43 2017 +0000 @@ -175,7 +175,8 @@ CV +1455-02331 Atlantic/Cape_Verde CW +1211-06900 America/Curacao CX -1025+10543 Indian/Christmas -CY +3510+03322 Asia/Nicosia +CY +3510+03322 Asia/Nicosia Cyprus (most areas) +CY +3507+03357 Asia/Famagusta Northern Cyprus CZ +5005+01426 Europe/Prague DE +5230+01322 Europe/Berlin Germany (most areas) DE +4742+00841 Europe/Busingen Busingen @@ -284,7 +285,7 @@ MH +0905+16720 Pacific/Kwajalein Kwajalein MK +4159+02126 Europe/Skopje ML +1239-00800 Africa/Bamako -MM +1647+09610 Asia/Rangoon +MM +1647+09610 Asia/Yangon MN +4755+10653 Asia/Ulaanbaatar Mongolia (most areas) MN +4801+09139 Asia/Hovd Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan MN +4804+11430 Asia/Choibalsan Dornod, Sukhbaatar