From 35465aaf307201a19b773a8e2de03d84e5d47ffa Mon Sep 17 00:00:00 2001 From: Johanna Amann Date: Thu, 29 Sep 2016 12:45:48 -0700 Subject: [PATCH] Add convenient way to access version information to Bro. With the introduction of the package manager, it will get more common that applications are able to get information about the currently running version of Bro. With this commit, scripts can easily compare which version of Bro they are running. Commonly, this probably will either look like this (both lines check if the current Bro version is greater or equal to 2.5) @if ( Version::num >= 20500 ) or @if ( Version::greater_equal("2.5") ) Version::info contains detailed information about the running version of Bro, including beta flags, etc. --- scripts/base/init-default.bro | 5 +- scripts/base/misc/version.bro | 90 +++++++++++++++++++ src/strings.bif | 3 +- .../scripts.base.misc.version-2/.stderr | 0 .../scripts.base.misc.version-2/.stdout | 3 + .../scripts.base.misc.version/.stderr | 4 + .../scripts.base.misc.version/.stdout | 12 +++ testing/btest/scripts/base/misc/version.bro | 40 +++++++++ 8 files changed, 154 insertions(+), 3 deletions(-) create mode 100644 scripts/base/misc/version.bro create mode 100644 testing/btest/Baseline/scripts.base.misc.version-2/.stderr create mode 100644 testing/btest/Baseline/scripts.base.misc.version-2/.stdout create mode 100644 testing/btest/Baseline/scripts.base.misc.version/.stderr create mode 100644 testing/btest/Baseline/scripts.base.misc.version/.stdout create mode 100644 testing/btest/scripts/base/misc/version.bro diff --git a/scripts/base/init-default.bro b/scripts/base/init-default.bro index ff89b39177..65b41305c7 100644 --- a/scripts/base/init-default.bro +++ b/scripts/base/init-default.bro @@ -23,7 +23,7 @@ @load base/utils/time @load base/utils/urls -# This has some deep interplay between types and BiFs so it's +# This has some deep interplay between types and BiFs so it's # loaded in base/init-bare.bro #@load base/frameworks/logging @load base/frameworks/notice @@ -61,7 +61,7 @@ @load base/protocols/rfb @load base/protocols/sip @load base/protocols/snmp -# This DOES NOT enable the SMB analyzer. It's just some base support +# This DOES NOT enable the SMB analyzer. It's just some base support # for other protocols. @load base/protocols/smb @load base/protocols/smtp @@ -80,3 +80,4 @@ @load base/misc/find-checksum-offloading @load base/misc/find-filtered-trace +@load base/misc/version diff --git a/scripts/base/misc/version.bro b/scripts/base/misc/version.bro new file mode 100644 index 0000000000..d5e26ed518 --- /dev/null +++ b/scripts/base/misc/version.bro @@ -0,0 +1,90 @@ +##! Set information about the currently running Bro version. +##! The most convenient way to access this are the Version::num +##! and Version::info constants. + +@load base/frameworks/reporter +@load base/utils/strings + +module Version; + +export { + ## A type exactly describing a bro version + type VersionDescription: record { + ## Number representing the version which can be used for easy comparison. + ## The format of the number is ABBCC with A being the major version, + ## bb being the minor version (2 digits) and CC being the patchlevel (2 digits). + ## As an example, Bro 2.4.1 results in the number 20401 + version_num: count; + ## Major version number (e.g. 2 for 2.5) + major: count; + ## Minor version number (e.g. 5 for 2.5) + minor: count; + ## Patch version number (e.g. 0 for 2.5 or 1 for 2.4.1) + patch: count; + ## Commit number for development versions, e.g. 12 for 2.4-12. 0 for non-development versions + commit: count; + ## If set to true, the version is a beta build of bro + beta: bool; + ## If set to true, the version is a debug build + debug: bool; + ## String representation of this version + version_string: string; + }; + + ## Parse a given version string. + ## + ## version_string: Bro version string. + ## + ## Returns: `VersionDescription` record. + global parse: function(version_string: string): VersionDescription; + + ## Test if the current running version of Bro is greater or equal to the given version + ## string. + ## + ## version_string: Version to check against the current running version. + ## + ## Returns: True if running version greater or equal to the given version. + global greater_equal: function(version_string: string): bool; +} + +function parse(version_string: string): VersionDescription + { + if ( /[[:digit:]]\.[[:digit:]][[:digit:]]?(\.[[:digit:]][[:digit:]]?)?(\-beta)?(-[[:digit:]]+)?(\-debug)?/ != version_string ) + { + Reporter::error(fmt("Version string %s cannot be parsed", version_string)); + return VersionDescription($version_num=0, $major=0, $minor=0, $patch=0, $commit=0, $beta=F, $debug=F, $version_string=version_string); + } + + local components = split_string1(version_string, /\-/); + local version_split = split_string(components[0], /\./); + local major = to_count(version_split[0]); + local minor = to_count(version_split[1]); + local patchlevel = ( |version_split| > 2) ? to_count(version_split[2]) : 0; + local version_num = major*10000+minor*100+patchlevel; + local beta = /\-beta/ in version_string; + local debug = /\-debug/ in version_string; + local commit = 0; + if ( |components| > 1 ) + { + local commitpart = find_last(components[1], /\-[[:digit:]]+/); + commit = ( |commitpart| > 0 ) ? to_count(sub_bytes(commitpart, 2, 999)) : 0; + } + + return VersionDescription($version_num=version_num, $major=major, $minor=minor, $patch=patchlevel, $commit=commit, $beta=beta, $debug=debug, $version_string=version_string); + } + +export { + ## version number of the currently running version of Bro as a numeric representation. + ## The format of the number is ABBCC with A being the major version, + ## bb being the minor version (2 digits) and CC being the patchlevel (2 digits). + ## As an example, Bro 2.4.1 results in the number 20401 + const num = Version::parse(bro_version())$version_num; + + ## `VersionDescription` record pertaining to the currently running version of Bro. + const info = Version::parse(bro_version()); +} + +function greater_equal(version_string: string): bool + { + return Version::parse(version_string)$version_num >= Version::num; + } diff --git a/src/strings.bif b/src/strings.bif index 914baaebbf..5a1ee5161d 100644 --- a/src/strings.bif +++ b/src/strings.bif @@ -349,7 +349,8 @@ static int match_prefix(int s_len, const char* s, int t_len, const char* t) VectorVal* do_split_string(StringVal* str_val, RE_Matcher* re, int incl_sep, int max_num_sep) { - VectorVal* rval = new VectorVal(string_vec); + // string_vec is used early in the version script - do not use the NetVar. + VectorVal* rval = new VectorVal(internal_type("string_vec")->AsVectorType()); const u_char* s = str_val->Bytes(); int n = str_val->Len(); const u_char* end_of_s = s + n; diff --git a/testing/btest/Baseline/scripts.base.misc.version-2/.stderr b/testing/btest/Baseline/scripts.base.misc.version-2/.stderr new file mode 100644 index 0000000000..e69de29bb2 diff --git a/testing/btest/Baseline/scripts.base.misc.version-2/.stdout b/testing/btest/Baseline/scripts.base.misc.version-2/.stdout new file mode 100644 index 0000000000..aad2c94307 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.misc.version-2/.stdout @@ -0,0 +1,3 @@ +yup +yup +yup diff --git a/testing/btest/Baseline/scripts.base.misc.version/.stderr b/testing/btest/Baseline/scripts.base.misc.version/.stderr new file mode 100644 index 0000000000..b4151671b7 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.misc.version/.stderr @@ -0,0 +1,4 @@ +error in /Users/johanna/bro/master/scripts/base/misc/version.bro, line 54: Version string 1 cannot be parsed +error in /Users/johanna/bro/master/scripts/base/misc/version.bro, line 54: Version string 12.5 cannot be parsed +error in /Users/johanna/bro/master/scripts/base/misc/version.bro, line 54: Version string 1.12-beta-drunk cannot be parsed +error in /Users/johanna/bro/master/scripts/base/misc/version.bro, line 54: Version string JustARandomString cannot be parsed diff --git a/testing/btest/Baseline/scripts.base.misc.version/.stdout b/testing/btest/Baseline/scripts.base.misc.version/.stdout new file mode 100644 index 0000000000..c6fd315164 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.misc.version/.stdout @@ -0,0 +1,12 @@ +[version_num=10500, major=1, minor=5, patch=0, commit=0, beta=F, debug=F, version_string=1.5] +[version_num=20000, major=2, minor=0, patch=0, commit=0, beta=F, debug=F, version_string=2.0] +[version_num=20500, major=2, minor=5, patch=0, commit=0, beta=T, debug=F, version_string=2.5-beta] +[version_num=20501, major=2, minor=5, patch=1, commit=0, beta=F, debug=T, version_string=2.5.1-debug] +[version_num=20500, major=2, minor=5, patch=0, commit=12, beta=T, debug=F, version_string=2.5-beta-12] +[version_num=20500, major=2, minor=5, patch=0, commit=0, beta=F, debug=T, version_string=2.5-12-debug] +[version_num=20502, major=2, minor=5, patch=2, commit=12, beta=T, debug=T, version_string=2.5.2-beta-12-debug] +[version_num=11220, major=1, minor=12, patch=20, commit=2562, beta=T, debug=T, version_string=1.12.20-beta-2562-debug] +[version_num=0, major=0, minor=0, patch=0, commit=0, beta=F, debug=F, version_string=1] +[version_num=0, major=0, minor=0, patch=0, commit=0, beta=F, debug=F, version_string=12.5] +[version_num=0, major=0, minor=0, patch=0, commit=0, beta=F, debug=F, version_string=1.12-beta-drunk] +[version_num=0, major=0, minor=0, patch=0, commit=0, beta=F, debug=F, version_string=JustARandomString] diff --git a/testing/btest/scripts/base/misc/version.bro b/testing/btest/scripts/base/misc/version.bro new file mode 100644 index 0000000000..43d78a6662 --- /dev/null +++ b/testing/btest/scripts/base/misc/version.bro @@ -0,0 +1,40 @@ +# @TEST-EXEC: bro %INPUT +# @TEST-EXEC: btest-diff .stdout +# @TEST-EXEC: btest-diff .stderr + +# good versions +print Version::parse("1.5"); +print Version::parse("2.0"); +print Version::parse("2.5-beta"); +print Version::parse("2.5.1-debug"); +print Version::parse("2.5-beta-12"); +print Version::parse("2.5-12-debug"); +print Version::parse("2.5.2-beta-12-debug"); +print Version::parse("1.12.20-beta-2562-debug"); + +# bad versions +print Version::parse("1"); +print Version::parse("12.5"); +print Version::parse("1.12-beta-drunk"); +print Version::parse("JustARandomString"); + +# check that current running version of Bro parses without error +Version::parse(bro_version()); + +@TEST-START-NEXT + +@if ( Version::num >= 20500 ) +print "yup"; +@endif + +@if ( Version::parse("1.5")$version_num < 20500 ) +print "yup"; +@endif + +@if ( Version::greater_equal("2.5") ) +print "yup"; +@endif + +@if ( Version::greater_equal("2.4") ) +print "no"; +@endif