]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Correctly terminate the buffer we use to parse generalized time in DER, and support...
authorArran Cudbard-Bell <a.cudbardb@freeradius.org>
Sat, 21 Feb 2026 04:52:48 +0000 (21:52 -0700)
committerArran Cudbard-Bell <a.cudbardb@freeradius.org>
Sat, 21 Feb 2026 04:52:48 +0000 (21:52 -0700)
src/protocols/der/decode.c
src/protocols/der/der.h
src/tests/unit/protocols/der/base.txt

index f83a9d18c0e27fadd31570a6d9046d053cc799fe..702184c090c379f01cf910974a8fdb21ce062adb 100644 (file)
@@ -1288,7 +1288,7 @@ static ssize_t fr_der_decode_generalized_time(TALLOC_CTX *ctx, fr_pair_list_t *o
         */
        if (timestr[DER_GENERALIZED_TIME_LEN_MIN - 1] == '.') {
                /*
-                *      We only support subseconds up to 4 decimal places
+                *      We only support subseconds up to 9 decimal places (nanoseconds)
                 */
                char subsecstring[DER_GENERALIZED_TIME_PRECISION_MAX + 1];
 
@@ -1310,7 +1310,7 @@ static ssize_t fr_der_decode_generalized_time(TALLOC_CTX *ctx, fr_pair_list_t *o
                        return -1;
                }
 
-               subsecstring[DER_GENERALIZED_TIME_PRECISION_MAX] = '\0';
+               subsecstring[precision] = '\0';
 
                /*
                 *      Convert the subseconds to an unsigned long
@@ -1318,9 +1318,22 @@ static ssize_t fr_der_decode_generalized_time(TALLOC_CTX *ctx, fr_pair_list_t *o
                subseconds = strtoul(subsecstring, NULL, 10);
 
                /*
-                *      Scale to nanoseconds
+                *      Scale to nanoseconds based on actual precision.
                 */
-               subseconds *= 1000000;
+               {
+                       static const unsigned long nsec_multiplier[] = {
+                               [1] = 100000000,
+                               [2] = 10000000,
+                               [3] = 1000000,
+                               [4] = 100000,
+                               [5] = 10000,
+                               [6] = 1000,
+                               [7] = 100,
+                               [8] = 10,
+                               [9] = 1,
+                       };
+                       subseconds *= nsec_multiplier[precision];
+               }
        }
 
        /*
index ab77b28ca0016b6d7ff389ce999177f3b5b1e103..67fc39e6664b1e57fc0cdd55aa5ca11b7671353e 100644 (file)
@@ -77,7 +77,7 @@ typedef enum {
 
 #define DER_UTC_TIME_LEN 13     //!< Length of the UTC time string.
 #define DER_GENERALIZED_TIME_LEN_MIN 15         //!< Minimum length of the generalized time string.
-#define DER_GENERALIZED_TIME_PRECISION_MAX 4 //!< Maximum precision of the generalized time string.
+#define DER_GENERALIZED_TIME_PRECISION_MAX 9 //!< Maximum precision of the generalized time string (nanoseconds).
 
 #define DER_TAG_CLASS_MASK 0xc0         //!< Mask to extract the class from the tag.
 #define DER_TAG_CONSTRUCTED_MASK 0x20   //!< Mask to check if the tag is constructed.
index c1d015c34f859aa78b022941d3e57630310990dd..62673b886a821474e553bfb0f099dcffa736011a 100644 (file)
@@ -590,6 +590,22 @@ match Generalized time contains null byte
 decode-pair 18 14 32 30 31 39 31 32 31 36 30 33 30 32 31 30 2e 30 30 00 31 5a
 match Generalized time contains null byte in subseconds
 
+# 9-digit fractional seconds (full nanosecond precision)
+decode-pair 181932303139303130323033303430352e3132333435363738395a
+match Test-Date = "2019-01-02T03:04:05Z"
+
+# 10-digit fractional seconds (overflow, truncated to 9 digits)
+decode-pair 181a32303139303130323033303430352e313233343536373839315a
+match Test-Date = "2019-01-02T03:04:05Z"
+
+# 9-digit fractional seconds, maximum subseconds (.999999999)
+decode-pair 181932303135313233313233353935392e3939393939393939395a
+match Test-Date = "2015-12-31T23:59:59Z"
+
+# 10-digit fractional seconds overflow, maximum subseconds (.9999999999)
+decode-pair 181a32303135313233313233353935392e393939393939393939395a
+match Test-Date = "2015-12-31T23:59:59Z"
+
 decode-pair 18 10 32 30 31 39 31 32 31 36 30 33 30 32 31 30 2e 5a
 match Insufficient data for subseconds
 
@@ -972,4 +988,4 @@ match c0 01 01 c1 01 02
 
 
 count
-match 575
+match 583