@@ -207,36 +207,49 @@ void fr_der_global_free(void)
207207 fr_dict_autofree (libfreeradius_der_dict );
208208}
209209
210- #if 0
210+ /*
211+ * Allow setting class of APPLICATION and PRIVATE.
212+ */
211213static int dict_flag_class (fr_dict_attr_t * * da_p , char const * value , UNUSED fr_dict_flag_parser_rule_t const * rules )
212214{
213215 static const fr_table_num_sorted_t table [] = {
214216 { L ("application" ), FR_DER_CLASS_APPLICATION },
215- { L ("context-specific" ), FR_DER_CLASS_CONTEXT },
216217 { L ("private" ), FR_DER_CLASS_PRIVATE },
217- { L ("universal" ), FR_DER_CLASS_UNIVERSAL },
218218 };
219219 static size_t table_len = NUM_ELEMENTS (table );
220220
221- fr_der_attr_flags_t * flags = fr_dict_attr_ext ( * da_p , FR_DICT_ATTR_EXT_PROTOCOL_SPECIFIC ) ;
221+ fr_der_attr_flags_t * flags ;
222222 fr_der_tag_class_t tag_class ;
223223
224+ flags = fr_dict_attr_ext ((* da_p )-> parent , FR_DICT_ATTR_EXT_PROTOCOL_SPECIFIC );
225+ if (flags -> der_type != FR_DER_TAG_SEQUENCE ) {
226+ fr_strerror_printf ("Cannot use 'class' for attribute %s DER type %s - the parent must be 'sequence'" ,
227+ (* da_p )-> parent -> name , fr_der_tag_to_str (flags -> der_type ));
228+ return -1 ;
229+ }
230+
231+ if ((* da_p )-> attr >= FR_DER_TAG_VALUE_MAX ) {
232+ fr_strerror_printf ("Cannot use 'class' for attribute %s - the attribute number must be 0..30" ,
233+ (* da_p )-> parent -> name );
234+ return -1 ;
235+ }
236+
237+ flags = fr_dict_attr_ext (* da_p , FR_DICT_ATTR_EXT_PROTOCOL_SPECIFIC );
224238 if (flags -> class ) {
225- fr_strerror_printf ("Attribute already has a 'class' defined" );
239+ fr_strerror_printf ("Attribute %s already has a 'class' defined" , ( * da_p ) -> name );
226240 return -1 ;
227241 }
228242
229243 tag_class = fr_table_value_by_str (table , value , FR_DER_CLASS_INVALID );
230244 if (tag_class == FR_DER_CLASS_INVALID ) {
231- fr_strerror_printf ("Invalid value in 'class=%s'" , value );
245+ fr_strerror_printf ("Unknown or invalid name in 'class=%s'" , value );
232246 return -1 ;
233247 }
234248
235249 flags -> class = tag_class ;
236250
237251 return 0 ;
238252}
239- #endif
240253
241254static int dict_flag_has_default (fr_dict_attr_t * * da_p , UNUSED char const * value , UNUSED fr_dict_flag_parser_rule_t const * rules )
242255{
@@ -573,7 +586,7 @@ static int dict_flag_optional(fr_dict_attr_t **da_p, UNUSED char const *value, U
573586}
574587
575588static const fr_dict_flag_parser_t der_flags [] = {
576- // { L("class"), { .func = dict_flag_class } },
589+ { L ("class" ), { .func = dict_flag_class } },
577590 { L ("der_type" ), { .func = dict_flag_der_type , .needs_value = true } },
578591 { L ("has_default" ), { .func = dict_flag_has_default } },
579592 { L ("is_extensions" ), { .func = dict_flag_is_extensions } },
@@ -912,15 +925,23 @@ static bool attr_valid(fr_dict_attr_t *da)
912925 * If the parent is a choice, then the child MUST have a limited set of options / tags.
913926 */
914927 parent = fr_dict_attr_ext (da -> parent , FR_DICT_ATTR_EXT_PROTOCOL_SPECIFIC );
915- if (parent -> is_choice || flags -> is_option ) {
916- if (!flags -> class ) {
917- fr_assert (da -> attr < FR_DER_TAG_VALUE_MAX );
918928
919- flags -> class = FR_DER_CLASS_CONTEXT ;
920- flags -> option = da -> attr ;
921- flags -> is_option = true;
922- }
929+ /*
930+ * The attribute was defined with the full OID, and no 'option' flag. Add it manually.
931+ */
932+ if ((parent -> is_choice && !flags -> is_option ) ||
933+ (flags -> class == FR_DER_CLASS_PRIVATE ) || (flags -> class == FR_DER_CLASS_APPLICATION )) {
934+ fr_assert (da -> attr < FR_DER_TAG_VALUE_MAX );
935+
936+ if (!flags -> class ) flags -> class = FR_DER_CLASS_CONTEXT ;
937+ flags -> option = da -> attr ;
938+ flags -> is_option = true;
939+ }
923940
941+ /*
942+ * Can't have duplicates.
943+ */
944+ if (flags -> is_option ) {
924945 if ((parent -> restrictions & (1 << flags -> option )) != 0 ) {
925946 fr_strerror_printf ("Parent %s already has a child with option %u - duplicates are not allowed" ,
926947 da -> parent -> name , flags -> option );
0 commit comments