.RE
.sp
..
-.TH dictionary 5 "09 Oct 2020"
+.TH dictionary 5 "18 Sep 2021"
.SH NAME
-dictionary \- RADIUS dictionary file
+dictionary \- FreeRADIUS dictionary file
.SH DESCRIPTION
-The master RADIUS dictionary file resides in
-\fI/etc/raddb/dictionary\fP. It references other \fIdictionary\fP
-files located in \fI/usr/local/share/freeradius/\fP. Each dictionary
-file contains a list of RADIUS attributes and values, which the server
-uses to map between descriptive names and on-the-wire data. The names
-have no meaning outside of the RADIUS server itself, and are never
-exchanged between server and clients.
+The local dictionary file resides in \fI/etc/raddb/dictionary\fP. It
+references other \fIdictionary\fP files located in
+\fI/usr/local/share/freeradius/\fP. Each dictionary file contains a
+list of protocol-specific attributes and values, which the server uses
+to map between descriptive names and on-the-wire data. The names have
+no meaning outside of the server, and are never sent "on the wire"
+between server and clients.
.PP
That is, editing the dictionaries will have NO EFFECT on anything
other than the server that is reading those files. Adding new
-attributes to the dictionaries will have NO EFFECT on RADIUS clients,
-and will not make RADIUS clients magically understand those
-attributes. The dictionaries are solely for local administrator
-convenience, and are specific to each version of FreeRADIUS.
+attributes to the dictionaries will have NO EFFECT on clients, and
+will not make clients magically understand those attributes. The
+dictionaries are solely for local administrator convenience, and are
+specific to each version of FreeRADIUS.
.PP
The dictionaries in \fI/usr/local/share\fP SHOULD NOT be edited unless
you know exactly what you are doing. Changing them will most likely
-break your RADIUS deployment.
+break the FreeRADIUS system.
.PP
If you need to add new attributes, please edit the
\fI/etc/raddb/dictionary\fP file. It's sole purpose is to contain
long-extended use "long-extended" as a flag instead
time use "date" instead
-FreeRADIUS will accept a VALUE definition for any "base" data type.
-For example, you can define VALUEs for IP addresses, Ethernet
-addresses, etc. VALUEs cannot be defined for "structural" data types
-such as struct, tlv, vsa, group, etc.
-
The "struct" type is a compound type. An attribute of data type
"struct" can have multiple sub-attributes defined, just as with TLVs.
Each sub-attribute has to be numbered sequentially, starting at 1.
The options are:
- encrypt=... set encryption type 1, 2, or 3.
+ encrypt=... set encryption type 1, 2, or 3.
has_tag The attribute can have an RFC 2868 style tag
+ clone=... copy another attribute subtree
The "encrypt" flag marks the attribute as being encrypted with one of
three possible methods. "1" means that the attribute is encrypted
grouping of attributes for tunneled users. See \fIRFC2868\fP for
more details.
-When the server receives an encoded attribute in a RADIUS packet, it
-looks up that attribute by number in the dictionary, and uses the
-definition found there for printing diagnostic and log messages. When
-the server sees an attribute name in a configuration file, it looks up
-that attribute by name in the dictionary, and uses the definition
-found there.
+When the server receives an encoded attribute in a packet, it looks up
+that attribute by number in the dictionary, and uses the definition
+found there for printing diagnostic and log messages. When the server
+sees an attribute name in a configuration file, it looks up that
+attribute by name in the dictionary, and uses the definition found
+there.
+
+.TP 0.5i
+.B ENUM name type
+Define an enumerated type, which can contain VALUEs.
+
+The \fIname\fP field has the same definition as for an ATTRIBUTE.
+
+
+The \fItype\fP field has the same definition as for an attribute.
+
+The purpose of ENUM is to define a common set of VALUEs, which can be
+re-used across multiple ATTRIBUTEs. Each ATTRIBUTE which needs to
+refer to an ENUM should set the "clone" flag, which refers to the ENUM
+name. For example. "ATTRIBUTE foo 1 uint16 enum=name_of_enum".
.TP 0.5i
.B MEMBER name type [flags]
other documents.. The \fInumber\fP field is also taken from the
relevant documents, for that name.
-When the server receives an encoded value in a RADIUS packet, it looks
-up the value of that attribute by number in the dictionary, and uses
-the name found there for printing diagnostic and log messages.
+When the server receives an encoded value in a packet, it looks up the
+value of that attribute by number in the dictionary, and uses the name
+found there for printing diagnostic and log messages.
+
+FreeRADIUS will accept a VALUE definition for any "base" data type.
+For example, you can define VALUEs for IP addresses, Ethernet
+addresses, etc. VALUEs cannot be defined for "structural" data types
+such as struct, tlv, vsa, group, etc.
+
.TP 0.5i
.B VENDOR vendor-name number [format=...]
Define a Vendor Specific Attribute encapsulation for \fIvendor-name\fP
*/
*ref = talloc_strdup(ctx->fixup.pool, value);
+ } else if (strcmp(key, "enum") == 0) {
+ /*
+ * Allow enum=... as a synonym for
+ * "clone". We check the sources and not
+ * the targets, because that's easier.
+ *
+ * Plus, ENUMs are really just normal attributes
+ * in disguise.
+ */
+ if (!value) {
+ fr_strerror_const("Missing ENUM name for 'enum=...'");
+ return -1;
+ }
+
+ switch (type) {
+ case FR_TYPE_LEAF:
+ break;
+
+ default:
+ fr_strerror_const("ENUM references be used for structural types");
+ return -1;
+ }
+
+ *ref = talloc_strdup(ctx->fixup.pool, value);
+
} else if (ctx->dict->subtype_table) {
int subtype;
}
+/*
+ * Process the ENUM command
+ */
+static int dict_read_process_enum(dict_tokenize_ctx_t *ctx, char **argv, int argc,
+ fr_dict_attr_flags_t *base_flags)
+{
+ int attr = -1;
+ fr_type_t type;
+ fr_dict_attr_flags_t flags;
+ fr_dict_attr_t const *parent, *da;
+
+ if (argc != 2) {
+ fr_strerror_const("Invalid ENUM syntax");
+ return -1;
+ }
+
+ /*
+ * Dictionaries need to have real names, not shitty ones.
+ */
+ if (strncmp(argv[0], "Attr-", 5) == 0) {
+ fr_strerror_const("Invalid ENUM name");
+ return -1;
+ }
+
+ flags = *base_flags;
+
+ if (dict_process_type_field(ctx, argv[1], &type, &flags) < 0) return -1;
+
+ if (flags.extra && (flags.subtype == FLAG_BIT_FIELD)) {
+ fr_strerror_const("Bit fields can only be defined as a MEMBER of a STRUCT");
+ return -1;
+ }
+
+ switch (type) {
+ case FR_TYPE_LEAF:
+ break;
+
+ default:
+ fr_strerror_printf("ENUMs can only be a leaf type, not %s",
+ fr_table_str_by_value(fr_value_box_type_table, type, "?Unknown?"));
+ break;
+ }
+
+ parent = ctx->stack[ctx->stack_depth].da;
+ if (!parent) {
+ fr_strerror_const("Invalid location for ENUM");
+ return -1;
+ }
+
+ /*
+ * ENUMs cannot have a flag field, so we don't parse that.
+ *
+ * Maybe we do want a flag field for named time deltas?
+ */
+
+#ifdef __clang_analyzer__
+ if (!ctx->dict) return -1;
+#endif
+
+ /*
+ * We have to call this first in order to allocate a
+ * number for the attribute.
+ */
+ if (!dict_attr_fields_valid(ctx->dict, parent, argv[0], &attr, type, &flags)) return -1;
+
+ /*
+ * Add in an attribute
+ */
+ if (fr_dict_attr_add(ctx->dict, parent, argv[0], attr, type, &flags) < 0) return -1;
+
+ /*
+ * If we need to set the previous attribute, we have to
+ * look it up by number. This lets us set the
+ * *canonical* previous attribute, and not any potential
+ * duplicate which was just added.
+ */
+ da = dict_attr_child_by_num(parent, attr);
+ if (!da) {
+ fr_strerror_printf("Failed to find attribute '%s' we just added.", argv[0]);
+ return -1;
+ }
+
+#ifndef NDEBUG
+ if (!dict_attr_by_name(NULL, parent, argv[0])) {
+ fr_strerror_printf("Failed to find attribute '%s' we just added.", argv[0]);
+ return -1;
+ }
+#endif
+
+ memcpy(&ctx->value_attr, &da, sizeof(da));
+
+ return 0;
+}
+
/*
* Process the MEMBER command
*/
continue;
}
+ /*
+ * Perhaps this is an enum.
+ */
+ if (strcasecmp(argv[0], "ENUM") == 0) {
+ if (dict_read_process_enum(ctx,
+ argv + 1, argc - 1,
+ &base_flags) == -1) goto error;
+ continue;
+ }
+
/*
* Process FLAGS lines.
*/