From: Alan T. DeKok Date: Wed, 24 Sep 2025 14:38:26 +0000 (-0400) Subject: allow dictionary to use $INCLUDE directory.d/ X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=49d45cb2d6fa1cd4d15f7fbfb14b9954426c08b2;p=thirdparty%2Ffreeradius-server.git allow dictionary to use $INCLUDE directory.d/ --- diff --git a/doc/antora/modules/reference/pages/raddb/dictionary.adoc b/doc/antora/modules/reference/pages/raddb/dictionary.adoc index bd500e9d4a..ea85f6210c 100644 --- a/doc/antora/modules/reference/pages/raddb/dictionary.adoc +++ b/doc/antora/modules/reference/pages/raddb/dictionary.adoc @@ -156,6 +156,13 @@ This dictionary includes v3-compatible names like "Cleartext-Password", or "NT-Password". + +Any local dictionaries can be added in the `dictionary.d` subdirectory. + +The server will load all files in that directory, but will skip +editor backup files, and others which are known to not be real files. + + == Default Configuration ``` @@ -167,6 +174,7 @@ or "NT-Password". #$INCLUDE ${dictdir}/radius/v3/dictionary.aruba #END-PROTOCOL RADIUS #$INCLUDE ${dictdir}/freeradius/v3/dictionary.freeradius.internal +$INCLUDE- dictionary.d/ ``` // Copyright (C) 2025 Network RADIUS SAS. Licenced under CC-by-NC 4.0. diff --git a/raddb/dictionary b/raddb/dictionary index d5e88c3c57..93e86c6286 100644 --- a/raddb/dictionary +++ b/raddb/dictionary @@ -166,3 +166,11 @@ # or "NT-Password". # #$INCLUDE ${dictdir}/freeradius/v3/dictionary.freeradius.internal + +# +# Any local dictionaries can be added in the `dictionary.d` subdirectory. +# +# The server will load all files in that directory, but will skip +# editor backup files, and others which are known to not be real files. +# +$INCLUDE- dictionary.d/ diff --git a/src/lib/util/dict_tokenize.c b/src/lib/util/dict_tokenize.c index 28c7b6d029..0a093f48c5 100644 --- a/src/lib/util/dict_tokenize.c +++ b/src/lib/util/dict_tokenize.c @@ -1163,10 +1163,13 @@ static int dict_read_process_common(dict_tokenize_ctx_t *dctx, fr_dict_attr_t ** static int dict_read_process_include(dict_tokenize_ctx_t *dctx, char **argv, int argc, char const *dir) { int rcode; + bool required = true; int stack_depth = dctx->stack_depth; char *src_file = dctx->filename; int src_line = dctx->line; - char *filename; + char *pattern; + char const *filename; + fr_globdir_iter_t iter; /* * Allow "$INCLUDE" or "$INCLUDE-", but @@ -1182,41 +1185,68 @@ static int dict_read_process_include(dict_tokenize_ctx_t *dctx, char **argv, int return -1; } - filename = argv[1]; + pattern = argv[1]; + required = (argv[0][8] != '-'); /* * Allow limited macro capability, so people don't have * to remember where the root dictionaries are located. */ - if (strncmp(filename, "${dictdir}/", 11) == 0) { + if (strncmp(pattern, "${dictdir}/", 11) == 0) { dir = fr_dict_global_ctx_dir(); - filename += 11; - } - - rcode = _dict_from_file(dctx, dir, filename, src_file, src_line); - if ((rcode == -2) && (argv[0][8] == '-')) { - fr_strerror_clear(); /* delete all errors */ - return 0; + pattern += 11; } + /* + * Figure out what we need to open, and put the result into "filename". + */ + rcode = fr_globdir_iter_init(&filename, dir, pattern, &iter); if (rcode < 0) { - fr_strerror_printf_push("from $INCLUDE at %s[%d]", fr_cwd_strip(src_file), src_line); + failed: + fr_strerror_printf("Failed opening $INCLUDE of %s/%s at %s[%d] - %s", + dir, pattern, fr_cwd_strip(src_file), src_line, fr_syserror(errno)); return -1; } - if (dctx->stack_depth < stack_depth) { - fr_strerror_printf("unexpected END-??? in $INCLUDE at %s[%d]", - fr_cwd_strip(src_file), src_line); - return -1; + /* + * No files may or may not be an error, depending on if the $INCLUDE was required. + */ + if (rcode == 0) { + if (required) { + errno = ENOENT; + goto failed; + } + + fr_strerror_clear(); /* delete all errors */ + return 0; } + /* + * "filename" is already the file, so we use do{}while() instead of while{} + */ + do { + rcode = _dict_from_file(dctx, dir, filename, src_file, src_line); + if (rcode < 0) { + fr_strerror_printf_push("from $INCLUDE at %s[%d]", fr_cwd_strip(src_file), src_line); + break; + } + + if (dctx->stack_depth < stack_depth) { + fr_strerror_printf("unexpected END-??? in $INCLUDE at %s[%d]", + fr_cwd_strip(src_file), src_line); + rcode = -1; + break; + } + + } while ((rcode = fr_globdir_iter_next(&filename, &iter)) == 1); + (void) fr_globdir_iter_free(&iter); + /* * Reset the filename and line number. */ dctx->filename = src_file; dctx->line = src_line; - - return 0; + return rcode; /* could be an error! */ } static int dict_read_parse_format(char const *format, int *ptype, int *plength, bool *pcontinuation)