diff --git a/doc/userguide/partials/options.rst b/doc/userguide/partials/options.rst index bcbca0f622..c2657d41a2 100644 --- a/doc/userguide/partials/options.rst +++ b/doc/userguide/partials/options.rst @@ -263,7 +263,7 @@ List all supported application layer protocols. -.. option:: --list-keywords=[all|csv|] +.. option:: --list-keywords=[all|json|csv|] List all supported rule keywords. diff --git a/src/detect-engine-register.c b/src/detect-engine-register.c index 23a1c4d0e5..e044b0eaa2 100644 --- a/src/detect-engine-register.c +++ b/src/detect-engine-register.c @@ -374,6 +374,98 @@ static void SigMultilinePrint(size_t i, const char *prefix) printf("\n"); } +static void SigJsonPrint(void) +{ + SCJsonBuilder *js = SCJbNewObject(); + if (unlikely(js == NULL)) { + return; + } + + for (size_t i = 0; i < (size_t)DETECT_TBLSIZE; i++) { + if (sigmatch_table[i].name == NULL) + continue; + // do not show __flowvar__postmatch__ and such + if (sigmatch_table[i].name[0] == '_') + continue; + + SCJbOpenObject(js, sigmatch_table[i].name); + if (sigmatch_table[i].desc) { + SCJbSetString(js, "description", sigmatch_table[i].desc); + } + if (sigmatch_table[i].url) { + char urldoc[2048]; + snprintf(urldoc, sizeof(urldoc), "%s%s", GetDocURL(), sigmatch_table[i].url); + SCJbSetString(js, "doc", urldoc); + } + if (sigmatch_table[i].alternative) { + SCJbSetString(js, "alternative", sigmatch_table[sigmatch_table[i].alternative].name); + } + if (sigmatch_table[i].alias) { + SCJbSetString(js, "alias", sigmatch_table[i].alias); + } + SCJbOpenArray(js, "features"); + + const uint32_t flags = sigmatch_table[i].flags; + if (flags & SIGMATCH_NOOPT) { + SCJbAppendString(js, "No option"); + } + if (flags & SIGMATCH_IPONLY_COMPAT) { + SCJbAppendString(js, "compatible with IP only rule"); + } + if (flags & SIGMATCH_DEONLY_COMPAT) { + SCJbAppendString(js, "compatible with decoder event only rule"); + } + if (flags & SIGMATCH_INFO_CONTENT_MODIFIER) { + SCJbAppendString(js, "content modifier"); + } + if (flags & SIGMATCH_INFO_STICKY_BUFFER) { + SCJbAppendString(js, "sticky buffer"); + } + if (flags & SIGMATCH_SUPPORT_FIREWALL) { + SCJbAppendString(js, "supports firewall"); + } + if (flags & SIGMATCH_INFO_MULTI_BUFFER) { + SCJbAppendString(js, "multi buffer"); + } + if (flags & (SIGMATCH_INFO_UINT8 | SIGMATCH_INFO_UINT16 | SIGMATCH_INFO_UINT32 | + SIGMATCH_INFO_UINT64)) { + if (flags & SIGMATCH_INFO_MULTI_UINT) + SCJbAppendString(js, "multi uint"); + if (flags & SIGMATCH_INFO_ENUM_UINT) + SCJbAppendString(js, "enum uint"); + if (flags & SIGMATCH_INFO_BITFLAGS_UINT) + SCJbAppendString(js, "bitflags"); + if (flags & SIGMATCH_INFO_UINT8) + SCJbAppendString(js, "uint8"); + if (flags & SIGMATCH_INFO_UINT16) + SCJbAppendString(js, "uint16"); + if (flags & SIGMATCH_INFO_UINT32) + SCJbAppendString(js, "uint32"); + if (flags & SIGMATCH_INFO_UINT64) + SCJbAppendString(js, "uint64"); + } + if (flags & SIGMATCH_BAN_FIREWALL_RULE) { + SCJbAppendString(js, "not supported for firewall rules"); + } + if (flags & SIGMATCH_BAN_FIREWALL_MODE) { + SCJbAppendString(js, "not supported for firewall mode"); + } + if (sigmatch_table[i].Transform) { + SCJbAppendString(js, "transform"); + } + if (sigmatch_table[i].SupportsPrefilter) { + SCJbAppendString(js, "prefilter"); + } + SCJbClose(js); + + SCJbClose(js); // SCJbOpenObject keyword name + } + + SCJbClose(js); + fwrite(SCJbPtr(js), SCJbLen(js), 1, stdout); + SCJbFree(js); +} + /** \brief Check if a keyword exists. */ bool SCSigTableHasKeyword(const char *keyword) { @@ -441,6 +533,9 @@ int SigTableList(const char *keyword) SigMultilinePrint(i, "\t"); } } + } else if (strcmp("json", keyword) == 0) { + SigJsonPrint(); + return TM_ECODE_DONE; } else { for (i = 0; i < size; i++) { if ((sigmatch_table[i].name != NULL) && diff --git a/src/suricata.c b/src/suricata.c index 1a19137147..e79729a033 100644 --- a/src/suricata.c +++ b/src/suricata.c @@ -748,7 +748,8 @@ static void PrintUsage(const char *progname) printf("\n Info:\n"); printf("\t-V : display Suricata version\n"); - printf("\t--list-keywords[=all|csv|] : list keywords implemented by the engine\n"); + printf("\t--list-keywords : list keywords implemented by the engine\n"); + printf("\t [=all|json|csv|]\n"); printf("\t--list-runmodes : list supported runmodes\n"); printf("\t--list-app-layer-protos : list supported app layer protocols\n"); printf("\t--list-rule-protos : list supported rule protocols\n");