From: Jason Ish Date: Fri, 10 Apr 2020 16:05:31 +0000 (-0600) Subject: Better environment detection for user-agent X-Git-Tag: 1.2.0rc1~4 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=510f209c4c518858c164786f3176a232f0ab25fc;p=thirdparty%2Fsuricata-update.git Better environment detection for user-agent Don't rely on Python's platform.linux_distribution module as it has been deprecated and removed in the latest version of Python. Instead use more generic ways to pick up the distribution such as looking at /etc/os-release, or falling back to uname. Should also pickup the version of FreeBSD, which was previously missing. --- diff --git a/suricata/update/net.py b/suricata/update/net.py index 8135441..49a58cf 100644 --- a/suricata/update/net.py +++ b/suricata/update/net.py @@ -35,6 +35,7 @@ except ImportError: from suricata.update.version import version from suricata.update import config +from suricata.update import osinfo logger = logging.getLogger() @@ -61,16 +62,24 @@ def build_user_agent(): logger.debug("Suppressing HTTP User-Agent header") return None return user_agent - uname_system = platform.uname()[0] - params.append("OS: %s" % (uname_system)) - params.append("CPU: %s" % (platform.machine())) - params.append("Python: %s" % (platform.python_version())) - - if uname_system == "Linux" and hasattr(platform, "linux_distribution"): - distribution = platform.linux_distribution() - params.append("Dist: %s/%s" % ( - str(distribution[0]), str(distribution[1]))) + params = [] + try: + params.append("OS: {}".format(platform.system())) + except Exception as err: + logger.error("Failed to set user-agent OS: {}".format(str(err))) + try: + params.append("CPU: {}".format(osinfo.arch())) + except Exception as err: + logger.error("Failed to set user-agent architecture: {}".format(str(err))) + try: + params.append("Python: {}".format(platform.python_version())) + except Exception as err: + logger.error("Failed to set user-agent python version: {}".format(str(err))) + try: + params.append("Dist: {}".format(osinfo.dist())) + except Exception as err: + logger.error("Failed to set user-agent distribution: {}".format(str(err))) params.append("Suricata: %s" % (user_agent_suricata_verison)) diff --git a/suricata/update/osinfo.py b/suricata/update/osinfo.py new file mode 100644 index 0000000..82816bc --- /dev/null +++ b/suricata/update/osinfo.py @@ -0,0 +1,75 @@ +# Copyright (C) 2020 Open Information Security Foundation +# +# You can copy, redistribute or modify this Program under the terms of +# the GNU General Public License version 2 as published by the Free +# Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# version 2 along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301, USA. + +import re +import os.path +import platform + +def parse_os_release(filename="/etc/os-release"): + os_release={} + + if not os.path.exists(filename): + return os_release + + with open(filename) as fileobj: + for line in fileobj: + line = line.strip() + m = re.match("^(\w+)=\"?(.*?)\"?$", line) + if m: + os_release[m.group(1)] = m.group(2) + return os_release + +def dist(): + os_release = parse_os_release() + if "NAME" in os_release: + version_fields = ["VERSION_ID", "BUILD_ID"] + for vf in version_fields: + if vf in os_release: + return "{}/{}".format(os_release["NAME"], os_release[vf]) + return os_release["NAME"] + + # Arch may or may not have /etc/os-release, but its easy to + # detect. + if os.path.exists("/etc/arch-release"): + return "Arch Linux" + + # Uname fallback. + uname = platform.uname() + return "{}/{}".format(uname[0], uname[2]) + +normalized_arch = { + "amd64": "x86_64", +} + +def arch(): + """Return the machine architecture. """ + machine = platform.machine() + return normalized_arch.get(machine, machine) + +if __name__ == "__main__": + # Build a user agent string. Something like: + # Suricata-Update/1.2.0dev0 (OS: Linux; \ + # CPU: x86_64; \ + # Python: 3.7.7; \ + # Dist: Fedora/31; \ + # Suricata: 4.0.0) + parts = [] + parts.append("OS: {}".format(platform.system())) + parts.append("CPU: {}".format(arch())) + parts.append("Python: {}".format(platform.python_version())) + parts.append("Dist: {}".format(dist())) + + print("Suricata-Update/1.2.0dev0 ({})".format("; ".join(parts)))