flags->class = FR_DER_CLASS_CONTEXT;
flags->option = num;
+ flags->is_option = true;
return 0;
}
flags->class = FR_DER_CLASS_CONTEXT;
flags->option = 3;
+ flags->is_option = true;
flags->is_sequence_of = true;
flags->sequence_of = FR_DER_TAG_SEQUENCE;
#endif
/*
- * When sequence_of=choice, it MUST also have a ref. But we can't check that
- * right now, as the ref isn't added until later.
- *
* A group of choices is really a sequence of sequences. i.e. x509extensions
* contain only a sequence, as does sequence_of=oid_and_value.
- *
- * @todo - fix that.
*/
flags->restrictions = (1 << FR_DER_TAG_SEQUENCE);
if (parent->is_choice) {
if (!flags->option) {
fr_assert(da->attr < FR_DER_TAG_VALUE_MAX);
+
+ flags->class = FR_DER_CLASS_CONTEXT;
flags->option = da->attr;
+ flags->is_option = true;
}
- flags->class = FR_DER_CLASS_CONTEXT;
-
if ((parent->restrictions & (1 << flags->option)) != 0) {
fr_strerror_printf("Parent %s already has a child with option %u - duplicates are not allowed",
da->parent->name, flags->option);
fr_assert(flags->der_type < FR_DER_TAG_VALUE_MAX);
flags->class = FR_DER_CLASS_CONTEXT;
+// flags->option = flags->der_type;
if ((parent->restrictions & (1 << flags->der_type)) != 0) {
fr_strerror_printf("Parent %s already has a child with tag %s - duplicates are not allowed",
return false;
}
+ /*
+ * A sequence can sometimes have mixed tags && options.
+ */
+ fr_assert(!flags->is_option);
+
} else if (parent->is_set_of) {
if (flags->der_type != parent->set_of) {
fr_strerror_printf("Parent %s is a set_of=%s - a child cannot be %s",
}
-static const fr_der_tag_decode_t tag_funcs[FR_DER_TAG_MAX] = {
+static const fr_der_tag_decode_t tag_funcs[FR_DER_TAG_VALUE_MAX] = {
[FR_DER_TAG_BOOLEAN] = { .constructed = FR_DER_TAG_PRIMITIVE, .decode = fr_der_decode_boolean },
[FR_DER_TAG_INTEGER] = { .constructed = FR_DER_TAG_PRIMITIVE, .decode = fr_der_decode_integer },
[FR_DER_TAG_BITSTRING] = { .constructed = FR_DER_TAG_PRIMITIVE, .decode = fr_der_decode_bitstring },
/*
* Check if the tag is not universal
*/
- if (tag_class != FR_DER_CLASS_UNIVERSAL) {
+ switch (tag_class) {
+ case FR_DER_CLASS_UNIVERSAL:
+ if ((*tag == FR_DER_TAG_INVALID) || (*tag >= FR_DER_TAG_VALUE_MAX)) {
+ fr_strerror_printf("Invalid tag %u", *tag);
+ return -1;
+ }
+ break;
+
+ case FR_DER_CLASS_CONTEXT:
/*
* The data type will need to be resolved using the dictionary and the tag value
*/
-
if (!parent) {
fr_strerror_const("No parent attribute to resolve tag");
return -1;
/*
* Doesn't match, check if it's optional.
*/
- if (*tag != flags->option) {
- if (flags->optional) return 0;
+ if (flags->is_option) {
+ if (*tag != flags->option) {
+ if (flags->optional) return 0;
- fr_strerror_printf("Invalid tag %u for attribute %s. Expected %u", *tag, parent->name,
- fr_der_flag_option(parent));
- return -1;
- }
+ fr_strerror_printf("Invalid option %u for attribute %s. Expected option %u",
+ *tag, parent->name, flags->option);
+ return -1;
+ }
- *tag = flags->der_type;
- }
+ *tag = flags->der_type;
- if ((*tag >= NUM_ELEMENTS(tag_funcs)) || (*tag == FR_DER_TAG_INVALID)) {
- fr_strerror_printf("Unknown tag %u", *tag);
+ } else {
+ if (*tag != flags->der_type) {
+ if (flags->optional) return 0;
+
+ fr_strerror_printf("Invalid tag %s for attribute %s. Expected tag %s",
+ fr_der_tag_to_str(*tag), parent->name, fr_der_tag_to_str(flags->der_type));
+ return -1;
+ }
+ }
+ fr_assert(flags->der_type != FR_DER_TAG_INVALID);
+ fr_assert(flags->der_type < NUM_ELEMENTS(tag_funcs));
+ break;
+
+ default:
+ fr_strerror_printf("Unsupported tag class %02x", tag_class);
return -1;
}
FR_DBUFF_OUT_RETURN(&len_byte, &our_in);
*len = (*len << 8) | len_byte;
}
- }
-
- else if (!constructed) {
+ } else if (!constructed) {
fr_strerror_const("Primitive data with indefinite form length field is invalid");
return -1;
}
+
} else {
*len = len_byte;
}
/*
- * Check if the length is valid for our buffer
+ * Ensure that there is the correct amount of data available to read.
*/
- if (unlikely(fr_dbuff_extend_lowat(NULL, &our_in, *len) < *len)) {
+ if (*len && unlikely((fr_dbuff_extend_lowat(NULL, &our_in, *len) < *len))) {
fr_strerror_printf("Insufficient data for length field (%zu)", *len);
return -1;
}