From: Alan T. DeKok Date: Sun, 16 Feb 2025 22:01:03 +0000 (-0500) Subject: limit 'der_type=foo' to compatible FreeRADIUS data types. X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ec450eadd4d7e089820395f24204e5b976dc1042;p=thirdparty%2Ffreeradius-server.git limit 'der_type=foo' to compatible FreeRADIUS data types. 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. --- diff --git a/share/dictionary/der/dictionary.rfc5280 b/share/dictionary/der/dictionary.rfc5280 index c86b52e7a38..e627dbb3e5e 100644 --- a/share/dictionary/der/dictionary.rfc5280 +++ b/share/dictionary/der/dictionary.rfc5280 @@ -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 diff --git a/src/protocols/der/base.c b/src/protocols/der/base.c index e414494f52c..2a7d4b4f342 100644 --- a/src/protocols/der/base.c +++ b/src/protocols/der/base.c @@ -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; diff --git a/src/protocols/der/decode.c b/src/protocols/der/decode.c index 11bf6223109..260db9e7e19 100644 --- a/src/protocols/der/decode.c +++ b/src/protocols/der/decode.c @@ -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; diff --git a/src/protocols/der/encode.c b/src/protocols/der/encode.c index 613b4ba80a6..873e7233e47 100644 --- a/src/protocols/der/encode.c +++ b/src/protocols/der/encode.c @@ -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