ATTRIBUTE otherName 0 sequence option=0
BEGIN otherName
DEFINE type-id oid
-DEFINE Value-thing sequence class=context-specific,tagnum=0
+DEFINE Value-thing sequence option=0
BEGIN Value-thing
DEFINE userPrincipalName utf8string
END Value-thing
ATTRIBUTE otherName 0 sequence option=0
BEGIN otherName
DEFINE type-id oid
-DEFINE Value-thing sequence class=context-specific,tagnum=0
+DEFINE Value-thing sequence option=0
BEGIN Value-thing
DEFINE userPrincipalName utf8string
END Value-thing
ATTRIBUTE otherName 0 sequence option=0
BEGIN otherName
DEFINE type-id oid
-DEFINE Value-thing sequence class=context-specific,tagnum=0
+DEFINE Value-thing sequence option=0
BEGIN Value-thing
DEFINE userPrincipalName utf8string
END Value-thing
DEFINE subjectPublicKey bitstring
END subjectPublicKeyInfo
-DEFINE Attributes sequence class=context-specific,tagnum=0
+DEFINE Attributes sequence option=0
BEGIN Attributes
DEFINE Attribute-thing tlv
BEGIN Attribute-thing
DEFINE tbsCertificate tlv
BEGIN tbsCertificate
-DEFINE version sequence class=context-specific,tagnum=0
+DEFINE version sequence option=0
BEGIN version
DEFINE VersionNum integer
END version
fr_dict_autofree(libfreeradius_der_dict);
}
-static int dict_flag_tagnum(fr_dict_attr_t **da_p, char const *value, UNUSED fr_dict_flag_parser_rule_t const *rules)
-{
- fr_der_attr_flags_t *flags = fr_dict_attr_ext(*da_p, FR_DICT_ATTR_EXT_PROTOCOL_SPECIFIC);
- unsigned long num;
- char *end = NULL;
-
- /*
- * We limit the allowed tag numbers to ones which fit into the
- * 5 bits of the first byte. We don't support continued tags.
- */
- num = strtoul(value, &end, 10);
- if ((num > 0x1f) || *end) {
- fr_strerror_printf("Invalid tag number '%s'", value);
- return -1;
- }
-
- flags->tagnum = num;
-
- return 0;
-}
-
+#if 0
static int dict_flag_class(fr_dict_attr_t **da_p, char const *value, UNUSED fr_dict_flag_parser_rule_t const *rules)
{
static fr_table_num_sorted_t const table[] = {
return 0;
}
+#endif
static int dict_flag_has_default(fr_dict_attr_t **da_p, UNUSED char const *value, UNUSED fr_dict_flag_parser_rule_t const *rules)
{
return -1;
}
+ /*
+ * Don't over-ride 'class==foo,option=bar'
+ */
flags->class = FR_DER_CLASS_CONTEXT;
- flags->tagnum = num;
+ flags->option = num;
return 0;
}
-static fr_dict_flag_parser_t const der_flags[] = {
- { L("class"), { .func = dict_flag_class } },
+static const fr_dict_flag_parser_t der_flags[] = {
+// { L("class"), { .func = dict_flag_class } },
{ L("der_type"), { .func = dict_flag_der_type, .needs_value = true } },
{ L("has_default"), { .func = dict_flag_has_default } },
{ L("is_choice"), { .func = dict_flag_is_choice } },
{ L("option"), { .func = dict_flag_option } },
{ L("sequence_of"), { .func = dict_flag_sequence_of } },
{ L("set_of"), { .func = dict_flag_set_of } },
- { L("tagnum"), { .func = dict_flag_tagnum } }
};
static bool type_parse(fr_type_t *type_p,fr_dict_attr_t **da_p, char const *name)
/*
* If it is a collection of x509 extensions, we will set a few other flags
* as per RFC 5280.
+ *
+ * @todo - this is hard-coded for RFC 5280 rules. Other
+ * things may have different rules.
*/
if (fr_type == FR_TYPE_GROUP) {
- dict_flag_is_extensions(da_p, "true", NULL);
- dict_flag_tagnum(da_p, "3", NULL);
- dict_flag_class(da_p, "context-specific", NULL);
- dict_flag_sequence_of(da_p, "sequence", NULL);
+ flags->is_extensions = true;
+
+ flags->class = FR_DER_CLASS_CONTEXT;
+ flags->option = 3;
+
+ flags->is_sequence_of = true;
+ flags->sequence_of = FR_DER_TAG_SEQUENCE;
}
flags->is_choice = (strcmp(name, "choice") == 0);
if (tag_class != fr_der_flag_class(parent)) {
bad_tag:
fr_strerror_printf("Invalid tag %u for attribute %s. Expected %" PRIu32, *tag, parent->name,
- fr_der_flag_tagnum(parent));
+ fr_der_flag_option(parent));
return -1;
}
- if (*tag != fr_der_flag_tagnum(parent)) goto bad_tag;
+ if (*tag != fr_der_flag_option(parent)) goto bad_tag;
*tag = fr_der_flag_der_type(parent);
}
#define DER_BOOLEAN_TRUE 0xff //!< DER encoded boolean true value.
typedef struct {
- uint8_t tagnum;
+ uint8_t option; //!< "attribute number" encoded in the tag field.
fr_der_tag_class_t class;
fr_der_tag_t der_type;
union {
return fr_dict_attr_ext(da, FR_DICT_ATTR_EXT_PROTOCOL_SPECIFIC);
}
-#define fr_der_flag_tagnum(_da) (fr_der_attr_flags(_da)->tagnum)
+#define fr_der_flag_option(_da) (fr_der_attr_flags(_da)->option)
#define fr_der_flag_class(_da) (fr_der_attr_flags(_da)->class)
#define fr_der_flag_der_type(_da) (fr_der_attr_flags(_da)->der_type)
#define fr_der_flag_sequence_of(_da) (fr_der_attr_flags(_da)->sequence_of)
fr_pair_t const *vp;
fr_dbuff_t our_dbuff = FR_DBUFF(dbuff);
fr_dbuff_marker_t marker;
- fr_der_tag_encode_t *tag_encode;
- fr_der_tag_t tag_num;
+ fr_der_tag_encode_t *func;
+ fr_der_tag_t tag;
fr_der_tag_class_t tag_class;
fr_der_encode_ctx_t *uctx = encode_ctx;
ssize_t slen = 0;
return fr_dbuff_set(dbuff, &our_dbuff);
}
- tag_num = fr_der_flag_der_type(vp->da) ? fr_der_flag_der_type(vp->da) : fr_type_to_der_tag_default(vp->vp_type);
+ tag = fr_der_flag_der_type(vp->da);
+ if (!tag) tag = fr_type_to_der_tag_default(vp->vp_type);
- if (unlikely(tag_num == FR_DER_TAG_INVALID)) {
- fr_strerror_printf("No tag number for type %" PRId32, vp->vp_type);
+ if (unlikely(tag == FR_DER_TAG_INVALID)) {
+ fr_strerror_printf("No tag defined for type %s", fr_type_to_str(vp->vp_type));
return -1;
}
- tag_encode = &tag_funcs[tag_num];
- if (!tag_encode->encode) {
- fr_strerror_printf("No encoding function for type %" PRId32, vp->vp_type);
+ func = &tag_funcs[tag];
+ if (!func->encode) {
+ fr_strerror_printf("No encoding function for type %s", fr_type_to_str(vp->vp_type));
return -1;
}
- tag_class = fr_der_flag_class(vp->da) ? fr_der_flag_class(vp->da) : FR_DER_CLASS_UNIVERSAL;
+ /*
+ * Default flag class is 0, which is FR_DER_CLASS_UNIVERSAL.
+ */
+ tag_class = fr_der_flag_class(vp->da);
+
+ /*
+ * We call the DER type encoding function based on its
+ * tag, but we might need to encode an option value
+ * instead of a tag.
+ */
+ if (fr_der_flag_option(vp->da) | tag_class) tag = fr_der_flag_option(vp->da);
fr_dbuff_marker(&uctx->encoding_start, &our_dbuff);
- slen = fr_der_encode_tag(&our_dbuff,
- fr_der_flag_tagnum(vp->da) | tag_class ? fr_der_flag_tagnum(vp->da) : tag_num,
- tag_class, tag_encode->constructed);
+ slen = fr_der_encode_tag(&our_dbuff, tag, tag_class, func->constructed);
if (slen < 0) {
error:
fr_dbuff_marker_release(&uctx->encoding_start);
if (fr_der_flag_is_extensions(vp->da)) {
slen = fr_der_encode_X509_extensions(&our_dbuff, cursor, uctx);
} else {
- slen = tag_encode->encode(&our_dbuff, cursor, uctx);
+ slen = func->encode(&our_dbuff, cursor, uctx);
}
if (slen < 0) {
fr_dbuff_marker_release(&marker);
MEMBER Test-Integer int64
END Set-Bool-Integer
-DEFINE Test-Context-Specific bool class=context-specific,tagnum=0,der_type=boolean
+DEFINE Test-Context-Specific bool option=0
DEFINE Test-Sequence-TLV sequence
BEGIN Test-Sequence-TLV