pull/16031/merge
SamareshSingh 12 hours ago committed by GitHub
commit c794e7a7ee
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -49,6 +49,29 @@ is the equivalent of::
address-groups:
HOME_NET: "[192.168.0.0/16,10.0.0.0/8,172.16.0.0/12]"
Glob Patterns
-------------
Filenames in ``include`` may contain shell-style glob metacharacters
(``*``, ``?``, ``[...]``). Patterns are expanded at startup via
``glob(3)`` and each matching file is loaded in lexicographic order. A
pattern that matches no files is logged as a warning and is not treated
as an error, which allows drop-in ``conf.d/``-style directories to be
empty.
::
include:
- /etc/suricata/conf.d/*.yaml
Relative patterns are resolved against the directory of the top-level
configuration file, the same as literal includes.
.. note:: Glob expansion requires ``glob(3)``, which is not available on
all platforms. On platforms without it, notably Windows, an
``include`` containing glob metacharacters is skipped with a warning
and no files are loaded from it. Literal filenames are unaffected.
.. note:: Suricata versions less than 7 required multiple ``include``
statements to be specified to include more than one file. While
Suricata 7.0 still supports this it will issue a deprecation

@ -27,6 +27,9 @@
#include "conf.h"
#include "conf-yaml-loader.h"
#include <yaml.h>
#ifdef HAVE_GLOB_H
#include <glob.h>
#endif
#include "util-path.h"
#include "util-debug.h"
@ -103,18 +106,17 @@ ConfYamlSetConfDirname(const char *filename)
}
/**
* \brief Include a file in the configuration.
* \brief Include a single resolved file in the configuration.
*
* \param parent The configuration node the included configuration will be
* placed at.
* \param filename The filename to include.
* \param filename The fully resolved filename to include.
*
* \retval 0 on success, -1 on failure.
*/
int SCConfYamlHandleInclude(SCConfNode *parent, const char *filename)
static int ConfYamlHandleIncludeOne(SCConfNode *parent, const char *filename)
{
yaml_parser_t parser;
char include_filename[PATH_MAX];
FILE *file = NULL;
int ret = -1;
@ -123,18 +125,9 @@ int SCConfYamlHandleInclude(SCConfNode *parent, const char *filename)
return -1;
}
if (PathIsAbsolute(filename)) {
strlcpy(include_filename, filename, sizeof(include_filename));
}
else {
snprintf(include_filename, sizeof(include_filename), "%s/%s",
conf_dirname, filename);
}
file = fopen(include_filename, "r");
file = fopen(filename, "r");
if (file == NULL) {
SCLogError("Failed to open configuration include file %s: %s", include_filename,
strerror(errno));
SCLogError("Failed to open configuration include file %s: %s", filename, strerror(errno));
goto done;
}
@ -156,6 +149,75 @@ done:
return ret;
}
/**
* \brief Include a file or glob pattern in the configuration.
*
* Relative paths are resolved against the directory of the top-level config
* file. If the input contains glob metacharacters (\c *, \c ?, \c [) the
* pattern is expanded via glob(3) and each match is included in lexicographic
* order. A pattern that matches no files is logged as a warning and not
* treated as an error, to support drop-in `conf.d/` directories.
*
* Glob expansion needs glob(3). On platforms without it, notably Windows, a
* pattern is logged as a warning and skipped instead of being opened as a
* literal filename.
*
* \param parent The configuration node the included configuration will be
* placed at.
* \param filename The filename or glob pattern to include.
*
* \retval 0 on success, -1 on failure.
*/
int SCConfYamlHandleInclude(SCConfNode *parent, const char *filename)
{
char include_filename[PATH_MAX];
if (PathIsAbsolute(filename)) {
strlcpy(include_filename, filename, sizeof(include_filename));
} else {
snprintf(include_filename, sizeof(include_filename), "%s/%s", conf_dirname, filename);
}
const bool is_pattern = strpbrk(filename, "*?[") != NULL;
#ifdef HAVE_GLOB_H
if (is_pattern) {
glob_t globbuf;
int gret = glob(include_filename, 0, NULL, &globbuf);
if (gret == GLOB_NOMATCH) {
SCLogWarning("No files match include pattern %s", include_filename);
return 0;
} else if (gret != 0) {
SCLogError(
"Failed to expand include pattern %s: %s", include_filename, strerror(errno));
return -1;
}
int ret = 0;
for (size_t i = 0; i < (size_t)globbuf.gl_pathc; i++) {
const char *path = globbuf.gl_pathv[i];
SCLogInfo("Including configuration file %s (matched %s).", path, filename);
if (ConfYamlHandleIncludeOne(parent, path) != 0) {
ret = -1;
break;
}
}
globfree(&globbuf);
return ret;
}
#else
if (is_pattern) {
SCLogWarning("Glob patterns in include are not supported on this platform, "
"skipping include %s",
include_filename);
return 0;
}
#endif
return ConfYamlHandleIncludeOne(parent, include_filename);
}
/**
* \brief Parse a YAML layer.
*

Loading…
Cancel
Save