]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
limit 'der_type=foo' to compatible FreeRADIUS data types.
authorAlan T. DeKok <aland@freeradius.org>
Sun, 16 Feb 2025 22:01:03 +0000 (17:01 -0500)
committerAlan T. DeKok <aland@freeradius.org>
Sun, 16 Feb 2025 22:01:03 +0000 (17:01 -0500)
Except for serialNumber, which is der_type=integer, and FreeRADIUS
type 'octets'.  That's because the serial numbers are larger than
64 bits, and we really don't need to see them as decimal values.

Update the decoder to allow this case.  The encoder already
allowed it, so we update the encoder with a comment explaining
why it's allowed.

share/dictionary/der/dictionary.rfc5280
src/protocols/der/base.c
src/protocols/der/decode.c
src/protocols/der/encode.c

index c86b52e7a3801d81da7a5592ec9c964dc1e4e600..e627dbb3e5e6e6e54797b59bed7d2b736c7cb638 100644 (file)
@@ -11,7 +11,7 @@ DEFINE        version                                         sequence class=context-specific,tagnum=0
 BEGIN version
 DEFINE VersionNum                                      integer
 END version
-DEFINE serialNumber                                    octets tagnum=2
+DEFINE serialNumber                                    octets der_type=integer
 DEFINE signature                                       group ref=OID-Tree,is_pair
 
 DEFINE issuer                                          sequence sequence_of=set,is_pairs
index e414494f52ccd43a153ad4f3a4aaaa9ff078da1c..2a7d4b4f342a6cfe45f4fc5b9e50c8b2d1fa22a8 100644 (file)
@@ -249,6 +249,21 @@ static int dict_flag_der_type(fr_dict_attr_t **da_p, char const *value, UNUSED f
                return -1;
        }
 
+       /*
+        *      The DER type and FreeRADIUS type must be compatible.
+        *
+        *      Except for some der_type=integer, such as a
+        *      certificate serialNumber.  Those are too large for us
+        *      to represent in 64 bits, so we just treat them as
+        *      'octets'.
+        */
+       if (!fr_type_to_der_tag_valid((*da_p)->type, der_type) &&
+           (der_type != FR_DER_TAG_INTEGER) && ((*da_p)->type != FR_TYPE_OCTETS)) {
+               fr_strerror_printf("Attribute type %s is not compatible with 'der_type=%s'",
+                                  fr_type_to_str((*da_p)->type), value);
+               return -1;
+       }
+
        flags->der_type = der_type;
 
        return 0;
index 11bf6223109d1b31d40502f2a3133c80a55c1d98..260db9e7e191c50883476db58602d5445207c96a 100644 (file)
@@ -2310,6 +2310,8 @@ static ssize_t fr_der_decode_pair_dbuff(TALLOC_CTX *ctx, fr_pair_list_t *out, fr
                if (fr_type_is_octets(parent->type)) {
                        /*
                         *      We will store the value as raw octets if indicated by the dictionary
+                        *
+                        *      This is mainly for large 'integer' types, such as serialNumber.
                         */
                        tag = FR_DER_TAG_OCTETSTRING;
 
index 613b4ba80a69db22a57ccea43a4d70fc67f6a575..873e7233e4724a0139c2f6d2ebb0aaeebfdc2c87 100644 (file)
@@ -191,6 +191,17 @@ static ssize_t fr_der_encode_integer(fr_dbuff_t *dbuff, fr_dcursor_t *cursor, UN
         *            the contents octets.
         */
 
+       /*
+        *      Some 'integer' types such as serialNumber are too
+        *      large for 64-bits.  So we just treat them as octet
+        *      strings.
+        */
+       if (vp->da->type != FR_TYPE_INT64) {
+               fr_assert(vp->da->type == FR_TYPE_OCTETS);
+               FR_DBUFF_IN_MEMCPY_RETURN(&our_dbuff, vp->vp_octets, vp->vp_length);
+               return fr_dbuff_set(dbuff, &our_dbuff);
+       }
+
        /*
         *      Yes, the type is FR_TYPE_INT64.  But we encode the
         *      data as-is, without caring about things like signed