You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by co...@apache.org on 2023/03/30 10:42:36 UTC

[directory-kerby] 03/03: DIRKRB-747 - Date encoding is buggy with JDK 15 and non-Arabic (Western) numerals

This is an automated email from the ASF dual-hosted git repository.

coheigea pushed a commit to branch 1.1.x-fixes
in repository https://gitbox.apache.org/repos/asf/directory-kerby.git

commit 223ada9f7d32d8bce3b6855ae9f403e078c70b2b
Author: Colm O hEigeartaigh <co...@apache.org>
AuthorDate: Thu Jan 19 07:56:50 2023 +0000

    DIRKRB-747 - Date encoding is buggy with JDK 15 and non-Arabic (Western) numerals
---
 .../kerby/asn1/type/Asn1GeneralizedTime.java       |  9 ++--
 .../org/apache/kerby/asn1/type/Asn1UtcTime.java    |  5 ++-
 ...cTimeTest.java => Asn1GeneralizedTimeTest.java} | 48 +++++++++++-----------
 .../org/apache/kerby/asn1/Asn1UtcTimeTest.java     | 22 ++++++++++
 .../src/main/java/org/apache/kerby/KOptions.java   |  8 +---
 .../kerby/kerberos/tool/klist/KlistTool.java       |  5 ++-
 6 files changed, 58 insertions(+), 39 deletions(-)

diff --git a/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1GeneralizedTime.java b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1GeneralizedTime.java
index 9738df26..81069ccd 100644
--- a/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1GeneralizedTime.java
+++ b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1GeneralizedTime.java
@@ -26,6 +26,7 @@ import java.nio.charset.StandardCharsets;
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
 import java.util.Date;
+import java.util.Locale;
 import java.util.SimpleTimeZone;
 import java.util.TimeZone;
 
@@ -61,14 +62,14 @@ public class Asn1GeneralizedTime extends Asn1Simple<Date> {
 
         fixedDateStr = dateStr.substring(0, 14) + millSecs;
         if (withZ) {
-            sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
+            sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS", Locale.US);
             sdf.setTimeZone(new SimpleTimeZone(0, "Z"));
         } else if (withZone) {
             fixedDateStr += timeZonePart;
-            sdf = new SimpleDateFormat("yyyyMMddHHmmssSSSz");
+            sdf = new SimpleDateFormat("yyyyMMddHHmmssSSSz", Locale.US);
             sdf.setTimeZone(new SimpleTimeZone(0, "Z"));
         } else {
-            sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
+            sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS", Locale.US);
             sdf.setTimeZone(new SimpleTimeZone(0, TimeZone.getDefault().getID()));
         }
 
@@ -82,7 +83,7 @@ public class Asn1GeneralizedTime extends Asn1Simple<Date> {
     @Override
     protected void toBytes() {
         Date date = getValue();
-        SimpleDateFormat dateF = new SimpleDateFormat("yyyyMMddHHmmss'Z'");
+        SimpleDateFormat dateF = new SimpleDateFormat("yyyyMMddHHmmss'Z'", Locale.US);
         dateF.setTimeZone(new SimpleTimeZone(0, "Z"));
 
         String str = dateF.format(date);
diff --git a/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1UtcTime.java b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1UtcTime.java
index 3c048f09..9a0b2a1d 100644
--- a/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1UtcTime.java
+++ b/kerby-common/kerby-asn1/src/main/java/org/apache/kerby/asn1/type/Asn1UtcTime.java
@@ -26,6 +26,7 @@ import java.nio.charset.StandardCharsets;
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
 import java.util.Date;
+import java.util.Locale;
 import java.util.SimpleTimeZone;
 
 /**
@@ -68,7 +69,7 @@ public class Asn1UtcTime extends Asn1Simple<Date> {
             throw new IllegalArgumentException("Bad utc time string " + dateStr);
         }
 
-        SimpleDateFormat sdf = new SimpleDateFormat("yyMMddHHmmssZ");
+        SimpleDateFormat sdf = new SimpleDateFormat("yyMMddHHmmssZ", Locale.US);
         sdf.setTimeZone(new SimpleTimeZone(0, "Z"));
         try {
             setValue(sdf.parse(fixedDateStr));
@@ -80,7 +81,7 @@ public class Asn1UtcTime extends Asn1Simple<Date> {
     @Override
     protected void toBytes() {
         Date date = getValue();
-        SimpleDateFormat sdf = new SimpleDateFormat("yyMMddHHmmss'Z'");
+        SimpleDateFormat sdf = new SimpleDateFormat("yyMMddHHmmss'Z'", Locale.US);
         sdf.setTimeZone(new SimpleTimeZone(0, "Z"));
 
         String str = sdf.format(date);
diff --git a/kerby-common/kerby-asn1/src/test/java/org/apache/kerby/asn1/Asn1UtcTimeTest.java b/kerby-common/kerby-asn1/src/test/java/org/apache/kerby/asn1/Asn1GeneralizedTimeTest.java
similarity index 56%
copy from kerby-common/kerby-asn1/src/test/java/org/apache/kerby/asn1/Asn1UtcTimeTest.java
copy to kerby-common/kerby-asn1/src/test/java/org/apache/kerby/asn1/Asn1GeneralizedTimeTest.java
index 271abff8..8e7bc227 100644
--- a/kerby-common/kerby-asn1/src/test/java/org/apache/kerby/asn1/Asn1UtcTimeTest.java
+++ b/kerby-common/kerby-asn1/src/test/java/org/apache/kerby/asn1/Asn1GeneralizedTimeTest.java
@@ -19,54 +19,52 @@
  */
 package org.apache.kerby.asn1;
 
-import org.apache.kerby.asn1.type.Asn1UtcTime;
+import org.apache.kerby.asn1.type.Asn1GeneralizedTime;
 import org.apache.kerby.asn1.util.HexUtil;
 import org.junit.Test;
 
 import java.io.IOException;
 import java.text.SimpleDateFormat;
 import java.util.Date;
+import java.util.Locale;
 import java.util.SimpleTimeZone;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
-public class Asn1UtcTimeTest {
+public class Asn1GeneralizedTimeTest {
 
     @Test
     public void testEncoding() throws Exception {
-        /**
-         * Cryptography for Developers -> ASN.1 UTCTIME Type
-         * the encoding of July 4, 2003 at 11:33 and 28 seconds would be
-         ā€œ030704113328Zā€ and be encoded as 0x17 0D 30 33 30 37 30 34 31 31 33 33 32 38 5A.
-         */
-        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
         sdf.setTimeZone(new SimpleTimeZone(0, "Z"));
-        String dateInString = "2003-07-04 11:33:28";
+        String dateInString = "2003070113328000";
         Date date = sdf.parse(dateInString);
-        testEncodingWith(date, "0x17 0D 30 33 30 37 30 34 31 31 33 33 32 38 5A");
+        testEncodingWith(date, "0x18 0F 32 30 30 33 30 37 30 31 31 33 33 33 32 30 5A");
+    }
+
+    // https://issues.apache.org/jira/browse/DIRKRB-747
+    @Test
+    public void testEncodingNonASCIILocale() throws Exception {
+        Locale existingLocale = Locale.getDefault();
+        try {
+            Locale.setDefault(new Locale("mni", "IN", "Beng"));
+            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
+            sdf.setTimeZone(new SimpleTimeZone(0, "Z"));
+            String dateInString = "2003070113328000";
+            Date date = sdf.parse(dateInString);
+            testEncodingWith(date, "0x18 0F 32 30 30 33 30 37 30 31 31 33 33 33 32 30 5A");
+        } finally {
+            Locale.setDefault(existingLocale);
+        }
     }
 
     private void testEncodingWith(Date value, String expectedEncoding) throws IOException {
         byte[] expected = HexUtil.hex2bytesFriendly(expectedEncoding);
-        Asn1UtcTime aValue = new Asn1UtcTime(value);
+        Asn1GeneralizedTime aValue = new Asn1GeneralizedTime(value);
         aValue.useDER();
         byte[] encodingBytes = aValue.encode();
         assertThat(encodingBytes).isEqualTo(expected);
     }
 
-    @Test
-    public void testDecoding() throws Exception {
-        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
-        String dateInString = "2003-07-04 11:33:28";
-        sdf.setTimeZone(new SimpleTimeZone(0, "Z"));
-        Date date = sdf.parse(dateInString);
-        testDecodingWith(date, "0x17 0D 30 33 30 37 30 34 31 31 33 33 32 38 5A");
-    }
 
-    private void testDecodingWith(Date expectedValue, String content) throws IOException {
-        Asn1UtcTime decoded = new Asn1UtcTime();
-        decoded.useDER();
-        decoded.decode(HexUtil.hex2bytesFriendly(content));
-        assertThat(decoded.getValue()).isEqualTo(expectedValue);
-    }
 }
diff --git a/kerby-common/kerby-asn1/src/test/java/org/apache/kerby/asn1/Asn1UtcTimeTest.java b/kerby-common/kerby-asn1/src/test/java/org/apache/kerby/asn1/Asn1UtcTimeTest.java
index 271abff8..abede6d9 100644
--- a/kerby-common/kerby-asn1/src/test/java/org/apache/kerby/asn1/Asn1UtcTimeTest.java
+++ b/kerby-common/kerby-asn1/src/test/java/org/apache/kerby/asn1/Asn1UtcTimeTest.java
@@ -26,6 +26,7 @@ import org.junit.Test;
 import java.io.IOException;
 import java.text.SimpleDateFormat;
 import java.util.Date;
+import java.util.Locale;
 import java.util.SimpleTimeZone;
 
 import static org.assertj.core.api.Assertions.assertThat;
@@ -46,6 +47,27 @@ public class Asn1UtcTimeTest {
         testEncodingWith(date, "0x17 0D 30 33 30 37 30 34 31 31 33 33 32 38 5A");
     }
 
+    // https://issues.apache.org/jira/browse/DIRKRB-747
+    @Test
+    public void testEncodingNonASCIILocale() throws Exception {
+        /**
+         * Cryptography for Developers -> ASN.1 UTCTIME Type
+         * the encoding of July 4, 2003 at 11:33 and 28 seconds would be
+         ā€œ030704113328Zā€ and be encoded as 0x17 0D 30 33 30 37 30 34 31 31 33 33 32 38 5A.
+         */
+        Locale existingLocale = Locale.getDefault();
+        try {
+            Locale.setDefault(new Locale("mni", "IN", "Beng"));
+            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+            sdf.setTimeZone(new SimpleTimeZone(0, "Z"));
+            String dateInString = "2003-07-04 11:33:28";
+            Date date = sdf.parse(dateInString);
+            testEncodingWith(date, "0x17 0D 30 33 30 37 30 34 31 31 33 33 32 38 5A");
+        } finally {
+            Locale.setDefault(existingLocale);
+        }
+    }
+
     private void testEncodingWith(Date value, String expectedEncoding) throws IOException {
         byte[] expected = HexUtil.hex2bytesFriendly(expectedEncoding);
         Asn1UtcTime aValue = new Asn1UtcTime(value);
diff --git a/kerby-common/kerby-util/src/main/java/org/apache/kerby/KOptions.java b/kerby-common/kerby-util/src/main/java/org/apache/kerby/KOptions.java
index d564f436..02b04974 100644
--- a/kerby-common/kerby-util/src/main/java/org/apache/kerby/KOptions.java
+++ b/kerby-common/kerby-util/src/main/java/org/apache/kerby/KOptions.java
@@ -23,11 +23,7 @@ import java.io.File;
 import java.text.DateFormat;
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -72,7 +68,7 @@ public class KOptions {
         } else if (kt == KOptionType.STR) {
             kopt.setValue(strValue);
         } else if (kt == KOptionType.DATE) {
-            DateFormat df = new SimpleDateFormat("dd/MM/yy:HH:mm:ss");
+            DateFormat df = new SimpleDateFormat("dd/MM/yy:HH:mm:ss", Locale.US);
             Date date = null;
             try {
                 date = df.parse(strValue);
diff --git a/kerby-tool/client-tool/src/main/java/org/apache/kerby/kerberos/tool/klist/KlistTool.java b/kerby-tool/client-tool/src/main/java/org/apache/kerby/kerberos/tool/klist/KlistTool.java
index 560bfacc..ac51f339 100644
--- a/kerby-tool/client-tool/src/main/java/org/apache/kerby/kerberos/tool/klist/KlistTool.java
+++ b/kerby-tool/client-tool/src/main/java/org/apache/kerby/kerberos/tool/klist/KlistTool.java
@@ -43,6 +43,7 @@ import java.text.DateFormat;
 import java.text.SimpleDateFormat;
 import java.util.Date;
 import java.util.List;
+import java.util.Locale;
 
 /**
  * klist like tool
@@ -118,7 +119,7 @@ public class KlistTool {
         if (credentials.isEmpty()) {
             System.out.println("No credential has been cached.");
         } else {
-            DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+            DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.US);
 
             System.out.println("Valid starting\t\tExpires\t\t\tService principal");
 
@@ -198,7 +199,7 @@ public class KlistTool {
                 return 0;
             }
             System.out.println(header[outputIndex]);
-            SimpleDateFormat format = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
+            SimpleDateFormat format = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss", Locale.US);
             Keytab keytab = Keytab.loadKeytab(keytabFile);
             List<PrincipalName> principals = keytab.getPrincipals();
             for (PrincipalName principal : principals) {