├── .gitignore
├── .travis.yml
├── AUTHORS
├── COPYING
├── ChangeLog
├── INSTALL
├── LICENSE
├── Makefile.am
├── NEWS
├── README
├── README.md
├── autogen.sh
├── config.h.in
├── configure.ac
├── doc
├── Makefile
├── make.bat
└── source
│ ├── command-line-options.rst
│ ├── conf.py
│ ├── console-output.rst
│ ├── core.rst
│ ├── getting-help.rst
│ ├── index.rst
│ ├── install.rst
│ ├── output.rst
│ ├── starting-meer.rst
│ └── what-is-meer.rst
├── etc
└── meer.yaml
├── extra
└── build-test
│ └── build-test.sh
├── screenshots
└── discord.png
├── src
├── Makefile.am
├── calculate-stats.c
├── calculate-stats.h
├── config-yaml.c
├── config-yaml.h
├── counters.c
├── counters.h
├── daemonize.c
├── daemonize.h
├── decode-json.c
├── decode-json.h
├── decode-output-json-client-stats.c
├── decode-output-json-client-stats.h
├── geoip.c
├── geoip.h
├── get-dns.c
├── get-dns.h
├── get-fingerprint.c
├── get-fingerprint.h
├── get-geoip.c
├── get-geoip.h
├── get-oui.c
├── get-oui.h
├── input-plugins
│ ├── commandline.c
│ ├── commandline.h
│ ├── file.c
│ ├── file.h
│ ├── redis.c
│ └── redis.h
├── lockfile.c
├── lockfile.h
├── meer-def.h
├── meer.c
├── meer.h
├── ndp-collector.c
├── ndp-collector.h
├── oui.c
├── oui.h
├── output-plugins
│ ├── bluedot.c
│ ├── bluedot.h
│ ├── elasticsearch.c
│ ├── elasticsearch.h
│ ├── external.c
│ ├── external.h
│ ├── file.c
│ ├── file.h
│ ├── pipe.c
│ ├── pipe.h
│ ├── redis.c
│ ├── redis.h
│ ├── syslog.c
│ └── syslog.h
├── output.c
├── output.h
├── stats.c
├── stats.h
├── usage.c
├── usage.h
├── util-base64.c
├── util-base64.h
├── util-dns.c
├── util-dns.h
├── util-md5.c
├── util-md5.h
├── util-signal.c
├── util-signal.h
├── util-strlcat.c
├── util-strlcpy.c
├── util.c
├── util.h
├── version.h
├── waldo.c
└── waldo.h
├── stamp-h1
└── tools
├── external
├── external-program-blocklist
│ ├── README.md
│ ├── blocklist.cgi
│ ├── blocklist.sql
│ ├── blocklister.j2
│ ├── blocklister_cron.j2
│ └── external-program-sql-blocklist.j2
├── external-program-http-get
└── external-program-iptables
└── reference_handler
├── README.md
├── reference_data.sql
└── reference_sources.conf
/.gitignore:
--------------------------------------------------------------------------------
1 | # Prerequisites
2 | *.d
3 |
4 | # Object files
5 | *.o
6 | *.ko
7 | *.obj
8 | *.elf
9 |
10 | # Linker output
11 | *.ilk
12 | *.map
13 | *.exp
14 |
15 | # Precompiled Headers
16 | *.gch
17 | *.pch
18 |
19 | # Libraries
20 | *.lib
21 | *.a
22 | *.la
23 | *.lo
24 |
25 | # Shared objects (inc. Windows DLLs)
26 | *.dll
27 | *.so
28 | *.so.*
29 | *.dylib
30 |
31 | # Executables
32 | *.exe
33 | *.out
34 | *.app
35 | *.i*86
36 | *.x86_64
37 | *.hex
38 |
39 | # Debug files
40 | *.dSYM/
41 | *.su
42 | *.idb
43 | *.pdb
44 |
45 | # Kernel Module Compile Results
46 | *.mod*
47 | *.cmd
48 | .tmp_versions/
49 | modules.order
50 | Module.symvers
51 | Mkfile.old
52 | dkms.conf
53 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | # Default parameters, even this default build is excluded in the build
2 | # matrix below. We define so Travis doesn't think this is a Ruby
3 | # project.
4 | os: linux
5 | language: c
6 | compiler: gcc
7 |
8 | # Define the default CFLAGS used by all builds as a YAML anchor.
9 | default-cflags: &default-cflags
10 | CFLAGS="-Wall -Wno-unused-parameter -Wno-unused-function"
11 | #CFLAGS="-Wall -Wextra -Werror -Wno-unused-parameter -Wno-unused-function"
12 |
13 | # The default build is Linux with gcc. Add additional builds to the
14 | # matrix here.
15 | matrix:
16 | # Exclude the default build so any the builds in the matrix will be done.
17 | exclude:
18 | - os: linux
19 | compiler: gcc
20 | include:
21 | # Linux, gcc, tests enabled.
22 | - os: linux
23 | compiler: gcc
24 | env:
25 | - NAME="linux,gcc"
26 | - *default-cflags
27 | # Linux, clang. For this build we'll also enable -Wshadow.
28 | - os: linux
29 | compiler: clang
30 | env:
31 | - NAME="linux,clang"
32 | - *default-cflags
33 | - EXTRA_CFLAGS="-Wshadow"
34 |
35 | # Change this to your needs
36 | script:
37 | - ./autogen.sh
38 | - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then
39 | ./configure || { echo "!!!! ERROR !!!!"; cat config.log && false; }
40 | fi
41 | - make
42 |
43 | before_install:
44 | - |
45 | if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then
46 |
47 | sudo apt-get update -qq
48 | sudo apt-get install -y libjson-c-dev libyaml-dev \
49 | build-essential autoconf automake libyaml-0-2 pkg-config libhiredis-dev
50 | fi
51 |
--------------------------------------------------------------------------------
/AUTHORS:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/quadrantsec/meer/68362cac477f9fe6d8d3662aed245239c0c65725/AUTHORS
--------------------------------------------------------------------------------
/ChangeLog:
--------------------------------------------------------------------------------
1 | Release v2.0.0 [2021/XX/XX]
2 |
3 | Same as v1.0.0, but with SQL removed.
4 |
5 | Release v1.0.0 [2021/11/29]
6 |
7 | Inital release of version 1.0 of Meer!
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/Makefile.am:
--------------------------------------------------------------------------------
1 | AUTOMAKE_OPIONS=foreign no-dependencies subdir-objects
2 | ACLOCAL_AMFLAGS =
3 | SUBDIRS = src
4 |
5 | #INCLUDES = @INCLUDES@
6 |
7 | install-data-local:
8 | test -z "$(DESTDIR)$(sysconfdir)" || /bin/mkdir -p "$(DESTDIR)$(sysconfdir)"
9 | test -f "$(DESTDIR)$(sysconfdir)/meer.yaml" || $(INSTALL_DATA) etc/meer.yaml "$(DESTDIR)$(sysconfdir)/meer.yaml"
10 | test -z "$(DESTDIR)$(bindir)" || /bin/mkdir -p "$(DESTDIR)$(bindir)"
11 | $(INSTALL) -m 755 src/meer "$(DESTDIR)$(bindir)/meer"
12 | @echo ""
13 | @echo "------------------------------------------------------------------------------"
14 | @echo "Meer has been installed!"
15 | @echo "------------------------------------------------------------------------------"
16 | @echo ""
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/NEWS:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/quadrantsec/meer/68362cac477f9fe6d8d3662aed245239c0c65725/NEWS
--------------------------------------------------------------------------------
/README:
--------------------------------------------------------------------------------
1 |
2 |
3 | See README.md
4 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | @@@@@@@@@@ @@@@@@@@ @@@@@@@@ @@@@@@@
3 | @@! @@! @@! @@! @@! @@! @@@ Quadrant Information Security
4 | @!! !!@ @!@ @!!!:! @!!!:! @!@!!@a https://quadrantsec.com
5 | !!: !!: !!: !!: !!: :!a Copyright (C) 2018-2023
6 | : : : :: :: : :: :: : : :
7 |
8 |
9 | # Join the Meer Discord channel
10 |
11 | [](https://discord.gg/VS6jTjH4gW)
12 |
13 | # Meer Documentation
14 |
15 | Meer "Read The Docs! https://meer.readthedocs.io
16 |
17 | # What is “Meer”.
18 |
19 | "Meer" is a dedicated data broker for the `Suricata `_ IDS/IPS systems and the `Sagan ` log analysis engine.
20 |
21 | Meer takes EVE data (JSON) from Suricata or Sagan (via an ``input-plugin``), augments it by enriching it
22 | with DNS, GeoIP, and other information (via the ``meer-core``), and then pushes the data to a database (via a ``output-plugin``) of your choice.
23 |
24 | Meer is written in C which makes it fast and very light weight. This makes is suitable for processing data on systems with limited resource.
25 |
26 | Meer ``input-plugins`` that are currently supported are Suricata/Sagan EVE ("spool") files and Redis.
27 |
28 | Meer ``output-plugins`` that are currently supported are Elasticsearch, Opensearch, Zincsearch
29 | (https://github.com/zinclabs/zinc), Redis, named pipes, files, and "external" programs. Meer release 1.0.0
30 | supports SQL (MariaDB, MySQL and PostgreSQL) that is compatible with older "Barnyard2" systems. Meer versions
31 | _after_ 1.0.0 do _not_ support SQL.
32 |
33 | # Input Plugins
34 |
35 | * file - Meer can read ("follow") data files generated by Suricata or Sagan
36 |
37 | * Redis - Meer can connect to and read data via a Redis PUB/SUB.
38 |
39 | # Output Plugins:
40 |
41 | * Redis - Meer can write store data to a Redis database similar to Suricata (list/lpush, rpush, channel/publish or set).
42 |
43 | * "elasticsearch" support - This allows Meer to write Sagan & Suricata EVE (JSON) data to Elasticsearch search.
44 |
45 | * "external" support - This allows you to call your own program. When an event happens and if the signature specifies the option, Meer will 'call' your program. The EVE/JSON is handed to your program via stdin. This can be useful to build custom firewall routines, customer reactions to events, custom ways to store data, etc.
46 |
47 | * "pipe" support - This allows Meer to write EVE/JSON data to a Unix "named pipe" or FIFO. Meer acts as a pipe "writer" and you can have a consumer (reader) on the other side of the "pipe". For example, you might use a program like "Sagan" (https://sagan.io) to analyze the data received via a named pipe.
48 |
49 | # Current Features:
50 |
51 | * Meer can "enrich" EVE/JSON data! For example, Meer can add DNS records, do OUI (hardware manufacturer) on MAC addresses, add GeoIP data and more!
52 | * Meer is written in C and has a very small memory footprint (only several meg of RAM). It also CPU efficient.
53 | * Fast startup times (under one second).
54 | * Simple command line and configuration syntax. Meer uses a YAML configurations similar to Suricata and Sagan.
55 | * Out of the box IPv6 support.
56 | * Meer can do reverse DNS/PTR record lookups. Meer has an internal DNS cache system so to not overburden DNS servers with repeated queries.
57 | * Supports "fingerprint" rule set. These are special Suricata & Sagan signatures that allow you to collect data about devices in your network and store them in a Redis database. See https://github.com/quadrantsec/fingerprint-rules for more information.
58 | * Supports "client stats" for Meer when injecting Sagan EVE/JSON data. This allows give you statistics about who and what is sending Sagan data within an environment.
59 | * Meer can generated "non-repetitive" data which can be useful for fast Indicator of Compromise (IoC) searches. This is known as "Network Data Points" or NDP.
60 |
61 | # Future "output" support:
62 |
63 | Meer is under development. This is our brief "road-map" of what we would like to see Meer do. If
64 | you have any ideas or requests, please let us know via our "issues" page (https://github.com/quadrantsec/meer/issues).
65 |
66 | * Syslog support (JSON, decoded, etc).
67 |
68 | # Support:
69 |
70 | * Need help getting started or looking for documentation? Go to https://meer.readthedocs.org !
71 |
72 | * Have a question or comment about Meer? Please post to the Meer mailing at https://groups.google.com/forum/#!forum/meer-users. You can also visit the Sagan/Meer Discord channel by going to https://discord.gg/VS6jTjH4gW
73 |
74 | * If you need to report a bug, please post that in our Github "issues" page. That is at https://github.com/quadrantsec/meer/issues
75 |
76 |
--------------------------------------------------------------------------------
/autogen.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # This generates Makefiles, ./configure, etc.
4 |
5 | autoreconf -vfi
6 |
--------------------------------------------------------------------------------
/doc/Makefile:
--------------------------------------------------------------------------------
1 | # Minimal makefile for Sphinx documentation
2 | #
3 |
4 | # You can set these variables from the command line.
5 | SPHINXOPTS =
6 | SPHINXBUILD = sphinx-build
7 | SOURCEDIR = source
8 | BUILDDIR = build
9 |
10 | # Put it first so that "make" without argument is like "make help".
11 | help:
12 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
13 |
14 | .PHONY: help Makefile
15 |
16 | # Catch-all target: route all unknown targets to Sphinx using the new
17 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
18 | %: Makefile
19 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
--------------------------------------------------------------------------------
/doc/make.bat:
--------------------------------------------------------------------------------
1 | @ECHO OFF
2 |
3 | pushd %~dp0
4 |
5 | REM Command file for Sphinx documentation
6 |
7 | if "%SPHINXBUILD%" == "" (
8 | set SPHINXBUILD=sphinx-build
9 | )
10 | set SOURCEDIR=source
11 | set BUILDDIR=build
12 |
13 | if "%1" == "" goto help
14 |
15 | %SPHINXBUILD% >NUL 2>NUL
16 | if errorlevel 9009 (
17 | echo.
18 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
19 | echo.installed, then set the SPHINXBUILD environment variable to point
20 | echo.to the full path of the 'sphinx-build' executable. Alternatively you
21 | echo.may add the Sphinx directory to PATH.
22 | echo.
23 | echo.If you don't have Sphinx installed, grab it from
24 | echo.http://sphinx-doc.org/
25 | exit /b 1
26 | )
27 |
28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
29 | goto end
30 |
31 | :help
32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
33 |
34 | :end
35 | popd
36 |
--------------------------------------------------------------------------------
/doc/source/command-line-options.rst:
--------------------------------------------------------------------------------
1 | Command Line Options
2 | ====================
3 |
4 | The majority of controls for Meer are within the ``meer.yaml`` file.
5 |
6 | .. option:: -d, --daemon
7 |
8 | This option tells Meer to fork to the background.
9 |
10 | .. option:: -c, --config
11 |
12 | This option tells what configuration file to use. By default Meer uses ``/usr/local/etc/meer.yaml``.
13 |
14 | .. option:: -h, --help
15 |
16 | The Meer help screen.
17 |
18 | .. option:: -q, --quiet
19 |
20 | This option to tells Meer to not output to the console. Logs are still sent to the /var/log/meer directory.
21 |
22 | .. option:: -q, --file
23 |
24 | This option bypasses the meer.yaml 'input-type' option and reads in files from the command line. Gzip compressed files can be read if Meer is compiled with GZIP support. If specifying multiple files, make sure to enclose your options with quotes (for example, --file "/var/log/suricata/*.gz")
25 |
26 |
--------------------------------------------------------------------------------
/doc/source/conf.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | #
3 | # Configuration file for the Sphinx documentation builder.
4 | #
5 | # This file does only contain a selection of the most common options. For a
6 | # full list see the documentation:
7 | # http://www.sphinx-doc.org/en/master/config
8 |
9 | # -- Path setup --------------------------------------------------------------
10 |
11 | # If extensions (or modules to document with autodoc) are in another directory,
12 | # add these directories to sys.path here. If the directory is relative to the
13 | # documentation root, use os.path.abspath to make it absolute, like shown here.
14 | #
15 | # import os
16 | # import sys
17 | # sys.path.insert(0, os.path.abspath('.'))
18 |
19 |
20 | # -- Project information -----------------------------------------------------
21 |
22 | project = u'Meer User Guide'
23 | copyright = u'2018,2019 Champ Clark III'
24 | author = u'Champ Clark III'
25 |
26 | # The short X.Y version
27 | version = u''
28 | # The full version, including alpha/beta/rc tags
29 | release = u'0.0.3'
30 |
31 |
32 | # -- General configuration ---------------------------------------------------
33 |
34 | # If your documentation needs a minimal Sphinx version, state it here.
35 | #
36 | # needs_sphinx = '1.0'
37 |
38 | # Add any Sphinx extension module names here, as strings. They can be
39 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
40 | # ones.
41 | extensions = [
42 | 'sphinx.ext.autodoc',
43 | 'sphinx.ext.doctest',
44 | 'sphinx.ext.intersphinx',
45 | 'sphinx.ext.todo',
46 | 'sphinx.ext.coverage',
47 | 'sphinx.ext.mathjax',
48 | 'sphinx.ext.ifconfig',
49 | 'sphinx.ext.viewcode',
50 | 'sphinx.ext.githubpages',
51 | ]
52 |
53 | # Add any paths that contain templates here, relative to this directory.
54 | templates_path = ['_templates']
55 |
56 | # The suffix(es) of source filenames.
57 | # You can specify multiple suffix as a list of string:
58 | #
59 | # source_suffix = ['.rst', '.md']
60 | source_suffix = '.rst'
61 |
62 | # The master toctree document.
63 | master_doc = 'index'
64 |
65 | # The language for content autogenerated by Sphinx. Refer to documentation
66 | # for a list of supported languages.
67 | #
68 | # This is also used if you do content translation via gettext catalogs.
69 | # Usually you set "language" from the command line for these cases.
70 | language = None
71 |
72 | # List of patterns, relative to source directory, that match files and
73 | # directories to ignore when looking for source files.
74 | # This pattern also affects html_static_path and html_extra_path.
75 | exclude_patterns = []
76 |
77 | # The name of the Pygments (syntax highlighting) style to use.
78 | pygments_style = None
79 |
80 |
81 | # -- Options for HTML output -------------------------------------------------
82 |
83 | # The theme to use for HTML and HTML Help pages. See the documentation for
84 | # a list of builtin themes.
85 | #
86 | #html_theme = 'alabaster'
87 | #html_theme = 'default'
88 | html_theme = 'sphinx_rtd_theme'
89 |
90 | # Theme options are theme-specific and customize the look and feel of a theme
91 | # further. For a list of options available for each theme, see the
92 | # documentation.
93 | #
94 | # html_theme_options = {}
95 |
96 | # Add any paths that contain custom static files (such as style sheets) here,
97 | # relative to this directory. They are copied after the builtin static files,
98 | # so a file named "default.css" will overwrite the builtin "default.css".
99 | html_static_path = ['_static']
100 |
101 | # Custom sidebar templates, must be a dictionary that maps document names
102 | # to template names.
103 | #
104 | # The default sidebars (for documents that don't match any pattern) are
105 | # defined by theme itself. Builtin themes are using these templates by
106 | # default: ``['localtoc.html', 'relations.html', 'sourcelink.html',
107 | # 'searchbox.html']``.
108 | #
109 | # html_sidebars = {}
110 |
111 |
112 | # -- Options for HTMLHelp output ---------------------------------------------
113 |
114 | # Output file base name for HTML help builder.
115 | htmlhelp_basename = 'MeerUserGuidedoc'
116 |
117 |
118 | # -- Options for LaTeX output ------------------------------------------------
119 |
120 | latex_elements = {
121 | # The paper size ('letterpaper' or 'a4paper').
122 | #
123 | # 'papersize': 'letterpaper',
124 |
125 | # The font size ('10pt', '11pt' or '12pt').
126 | #
127 | # 'pointsize': '10pt',
128 |
129 | # Additional stuff for the LaTeX preamble.
130 | #
131 | # 'preamble': '',
132 |
133 | # Latex figure (float) alignment
134 | #
135 | # 'figure_align': 'htbp',
136 | }
137 |
138 | # Grouping the document tree into LaTeX files. List of tuples
139 | # (source start file, target name, title,
140 | # author, documentclass [howto, manual, or own class]).
141 | latex_documents = [
142 | (master_doc, 'MeerUserGuide.tex', u'Meer User Guide Documentation',
143 | u'Champ Clark III', 'manual'),
144 | ]
145 |
146 |
147 | # -- Options for manual page output ------------------------------------------
148 |
149 | # One entry per manual page. List of tuples
150 | # (source start file, name, description, authors, manual section).
151 | man_pages = [
152 | (master_doc, 'meeruserguide', u'Meer User Guide Documentation',
153 | [author], 1)
154 | ]
155 |
156 |
157 | # -- Options for Texinfo output ----------------------------------------------
158 |
159 | # Grouping the document tree into Texinfo files. List of tuples
160 | # (source start file, target name, title, author,
161 | # dir menu entry, description, category)
162 | texinfo_documents = [
163 | (master_doc, 'MeerUserGuide', u'Meer User Guide Documentation',
164 | author, 'MeerUserGuide', 'One line description of project.',
165 | 'Miscellaneous'),
166 | ]
167 |
168 |
169 | # -- Options for Epub output -------------------------------------------------
170 |
171 | # Bibliographic Dublin Core info.
172 | epub_title = project
173 |
174 | # The unique identifier of the text. This can be a ISBN number
175 | # or the project homepage.
176 | #
177 | # epub_identifier = ''
178 |
179 | # A unique identification for the text.
180 | #
181 | # epub_uid = ''
182 |
183 | # A list of files that should not be packed into the epub file.
184 | epub_exclude_files = ['search.html']
185 |
186 |
187 | # -- Extension configuration -------------------------------------------------
188 |
189 | # -- Options for intersphinx extension ---------------------------------------
190 |
191 | # Example configuration for intersphinx: refer to the Python standard library.
192 | intersphinx_mapping = {'https://docs.python.org/': None}
193 |
194 | # -- Options for todo extension ----------------------------------------------
195 |
196 | # If true, `todo` and `todoList` produce output, else they produce nothing.
197 | todo_include_todos = True
198 |
--------------------------------------------------------------------------------
/doc/source/console-output.rst:
--------------------------------------------------------------------------------
1 | Console Output
2 | ==============
3 |
4 | Console/Log Startup
5 | -------------------
6 |
7 | At start up, the logs and console output give you information about the status of Meer.
8 | For example, you will want to note the ``Redis`` and ``Elasticsearch``, such as the driver and whether
9 | a successful connection was made. If there is a problem making a connection to your database,
10 | Meer will display the error that is causing the issues.
11 |
12 | Another important item to note is the database sensor ID. This will be the ID number used in
13 | the database to store events.
14 |
15 | Common issues are database rights and directory/file permission problems.
16 |
17 | If Meer makes it to the ``Waiting of new data...``, then Meer has successfully started.
18 |
19 | ::
20 |
21 | [*] [10/20/2021 20:55:23] Configuration '/usr/local/etc/meer.yaml' for host 'dev' successfully loaded.
22 | [*] [10/20/2021 20:55:23]
23 | [*] [10/20/2021 20:55:23] @@@@@@@@@@ @@@@@@@@ @@@@@@@@ @@@@@@@ Meer version 1.0.0-git
24 | [*] [10/20/2021 20:55:23] @@! @@! @@! @@! @@! @@! @@@ Quadrant Information Security
25 | [*] [10/20/2021 20:55:23] @!! !!@ @!@ @!!!:! @!!!:! @!@!!@a https://quadrantsec.com
26 | [*] [10/20/2021 20:55:23] !!: !!: !!: !!: !!: :!a Copyright (C) 2018-2021
27 | [*] [10/20/2021 20:55:23] : : : :: :: : :: :: : : :
28 | [*] [10/20/2021 20:55:23]
29 | [*] [10/20/2021 20:55:23] Meer's PID is 14606
30 | [*] [10/20/2021 20:55:23] Dropping privileges! [UID: 1011 GID: 1011]
31 | [*] [10/20/2021 20:55:23] Loaded 40382 entries from OUI database [/usr/local/etc/manuf].
32 | [*] [10/20/2021 20:55:23] Classifications file loaded [/usr/local/etc/sagan-rules/classification.config].
33 | [*] [10/20/2021 20:55:23]
34 | [*] [10/20/2021 20:55:23] Fingerprint support : enabled
35 | [*] [10/20/2021 20:55:23] Health updates : enabled
36 | [*] [10/20/2021 20:55:23]
37 | [*] [10/20/2021 20:55:23] GeoIP support : enabled
38 | [*] [10/20/2021 20:55:23] GeoIP database : /usr/local/share/GeoIP2/GeoLite2-City.mmdb
39 | [*] [10/20/2021 20:55:23]
40 | [*] [10/20/2021 20:55:23] Waldo loaded. Current position: 2345
41 | [*] [10/20/2021 20:55:23]
42 | [*] [10/20/2021 20:55:23] --[ Redis output information ]--------------------------------------
43 | [*] [10/20/2021 20:55:23]
44 | [*] [10/20/2021 20:55:23] Successfully connected to Redis server at 127.0.0.1:6379.
45 | [*] [10/20/2021 20:55:23] Got PONG from Redis at 127.0.0.1:6379.
46 | [*] [10/20/2021 20:55:23]
47 | [*] [10/20/2021 20:55:23] Write 'alert' : enabled
48 | [*] [10/20/2021 20:55:23] Write 'stats' : enabled
49 | [*] [10/20/2021 20:55:23] Write 'email' : enabled
50 | [*] [10/20/2021 20:55:23] Write 'dns' : enabled
51 | [*] [10/20/2021 20:55:23] Write 'flow' : enabled
52 | [*] [10/20/2021 20:55:23] Write 'http' : enabled
53 | [*] [10/20/2021 20:55:23] Write 'tls' : enabled
54 | [*] [10/20/2021 20:55:23] Write 'ssh' : enabled
55 | [*] [10/20/2021 20:55:23] Write 'smtp' : enabled
56 | [*] [10/20/2021 20:55:23] Write 'files' : enabled
57 | [*] [10/20/2021 20:55:23] Write 'fileinfo' : enabled
58 | [*] [10/20/2021 20:55:23] Write 'dhcp' : enabled
59 | [*] [10/20/2021 20:55:23] Write 'rdp' : enabled
60 | [*] [10/20/2021 20:55:23] Write 'sip' : enabled
61 | [*] [10/20/2021 20:55:23] Write 'ftp' : enabled
62 | [*] [10/20/2021 20:55:23] Write 'ikev2' : enabled
63 | [*] [10/20/2021 20:55:23] Write 'nfs' : enabled
64 | [*] [10/20/2021 20:55:23] Write 'tftp' : enabled
65 | [*] [10/20/2021 20:55:23] Write 'smb' : enabled
66 | [*] [10/20/2021 20:55:23] Write 'dcerpc' : enabled
67 | [*] [10/20/2021 20:55:23] Write 'mqtt' : enabled
68 | [*] [10/20/2021 20:55:23] Write 'netflow' : enabled
69 | [*] [10/20/2021 20:55:23] Write 'metadata' : enabled
70 | [*] [10/20/2021 20:55:23] Write 'dnp3' : enabled
71 | [*] [10/20/2021 20:55:23] Write 'anomaly' : enabled
72 | [*] [10/20/2021 20:55:23] Write 'client_stats' : enabled
73 | [*] [10/20/2021 20:55:23]
74 | [*] [10/20/2021 20:55:23] --[ Elasticsearch output information ]---------------------------
75 | [*] [10/20/2021 20:55:23]
76 | [*] [10/20/2021 20:55:23] URL to connect to : "https://127.0.0.1:9200/_bulk"
77 | [*] [10/20/2021 20:55:23] Index template : "suricata_$EVENTTYPE_$YEAR$MONTH$DAY"
78 | [*] [10/20/2021 20:55:23] Batch size per/POST : 100
79 | [*] [10/20/2021 20:55:23] Threads : 10
80 | [*] [10/20/2021 20:55:23] Authentication : enabled
81 | [*] [10/20/2021 20:55:23]
82 | [*] [10/20/2021 20:55:23] Record 'alert' : enabled
83 | [*] [10/20/2021 20:55:23] Record 'files' : enabled
84 | [*] [10/20/2021 20:55:23] Record 'flow' : enabled
85 | [*] [10/20/2021 20:55:23] Record 'dns' : enabled
86 | [*] [10/20/2021 20:55:23] Record 'http' : enabled
87 | [*] [10/20/2021 20:55:23] Record 'tls' : enabled
88 | [*] [10/20/2021 20:55:23] Record 'ssh' : enabled
89 | [*] [10/20/2021 20:55:23] Record 'smtp' : enabled
90 | [*] [10/20/2021 20:55:23] Record 'email' : enabled
91 | [*] [10/20/2021 20:55:23] Record 'fileinfo' : enabled
92 | [*] [10/20/2021 20:55:23] Record 'dhcp' : enabled
93 | [*] [10/20/2021 20:55:23] Record 'stats' : enabled
94 | [*] [10/20/2021 20:55:23] Record 'rdp' : enabled
95 | [*] [10/20/2021 20:55:23] Record 'sip' : enabled
96 | [*] [10/20/2021 20:55:23] Record 'ftp' : enabled
97 | [*] [10/20/2021 20:55:23] Record 'nfs' : enabled
98 | [*] [10/20/2021 20:55:23] Record 'tftp' : enabled
99 | [*] [10/20/2021 20:55:23] Record 'smb' : enabled
100 | [*] [10/20/2021 20:55:23] Record 'mqtt' : enabled
101 | [*] [10/20/2021 20:55:23] Record 'dcerpc' : enabled
102 | [*] [10/20/2021 20:55:23] Record 'netflow' : enabled
103 | [*] [10/20/2021 20:55:23] Record 'metadata' : enabled
104 | [*] [10/20/2021 20:55:23] Record 'dnp3' : enabled
105 | [*] [10/20/2021 20:55:23] Record 'anomaly' : enabled
106 | [*] [10/20/2021 20:55:23]
107 | [*] [10/20/2021 20:55:23] Spawning 10 Elasticsearch threads.
108 | [*] [10/20/2021 20:55:23]
109 | [*] [10/20/2021 20:55:23] --[ Meer engine information ]-------------------------------------
110 | [*] [10/20/2021 20:55:23]
111 | [*] [10/20/2021 20:55:23] Successfully opened /home/champ/test.eve
112 | [*] [10/20/2021 20:55:23] Skipping to record 2345 in /home/champ/test.eve
113 | [*] [10/20/2021 20:55:23] Reached target record of 2345. Processing new records.
114 | [*] [10/20/2021 20:55:23] Read in 2345 lines
115 | [*] [10/20/2021 20:55:23] Waiting for new data......
116 |
117 |
--------------------------------------------------------------------------------
/doc/source/getting-help.rst:
--------------------------------------------------------------------------------
1 | Getting help
2 | ============
3 |
4 | The Meer Github site is located at:
5 |
6 | https://github.com/quadrantsec/meer
7 |
8 | If you are having issues getting Meer to work, consider posting in the Meer mailing list. This list
9 | is good for general configuration, install, and usage questions.
10 |
11 | https://groups.google.com/forum/#!forum/meer-users
12 |
13 | If you need to report a compile or programming issue, please use our Github.com issues page. That is
14 | located at:
15 |
16 | https://github.com/quadrantsec/meer/issues
17 |
18 | You can also get support via our Meer Discord channel. That is at:
19 |
20 | https://discord.gg/VS6jTjH4gW
21 |
--------------------------------------------------------------------------------
/doc/source/index.rst:
--------------------------------------------------------------------------------
1 | Meer User Guide
2 | ===============
3 |
4 | .. toctree::
5 | :numbered:
6 | :maxdepth: 2
7 |
8 | what-is-meer
9 | install.rst
10 | command-line-options
11 | starting-meer
12 | core
13 | input
14 | output
15 | console-output
16 | getting-help
17 |
18 |
--------------------------------------------------------------------------------
/doc/source/install.rst:
--------------------------------------------------------------------------------
1 | Installation
2 | ============
3 |
4 | Quick start from source
5 | ------------------------
6 |
7 | Quick installation using common flags. For more information on packages and flags, skip to ``Required Prerequisites`` and ``Optional Prerequisites``.
8 |
9 | ::
10 |
11 | sudo apt-get install libjson-c-dev libyaml-dev libmaxminddb-dev libcurl4-openssl-dev libhiredis-dev libevent-dev zlib1g-dev
12 | git clone https://github.com/quadrantsec/meer
13 | cd meer
14 | ./autogen.sh
15 | ./configure --enable-redis --enable-elasticsearch --enable-geoip
16 | make
17 | sudo make install
18 |
19 | By default, this will install Meer into the ``/usr/local/bin/`` directory with the default Meer configuration file in the ``/usr/local/etc/`` directory. By default (without any flags), Meer will compile with only Redis support.
20 |
21 |
22 | Required Prerequisites
23 | ----------------------
24 |
25 | Meer uses a YAML configuration file. This means that Meer will need libyaml installed on the system. On Ubuntu/Debian systems, this can be installed via:
26 |
27 | .. option:: apt-get install libyaml-dev
28 |
29 | Meer uses `JSON-C `_ to parse JSON (EVE) output from Sagan and Suricata. On Ubuntu/Debian systems, this prerequisite can be installed via:
30 |
31 | .. option:: apt-get install libjson-c-dev
32 |
33 | Optional Prerequisites
34 | ----------------------
35 |
36 | Redis
37 | ~~~~~
38 |
39 | If you would like to have Meer store data into Redis, which is enabled by default during compile time, you will need the "hiredis" library and development files. You will also need ``libevent`` installed as well.
40 |
41 | On Ubuntu/Debian systems:
42 |
43 | .. option:: sudo apt-get install libhiredis-dev libevent-dev
44 |
45 |
46 | Elasticsearch
47 | ~~~~~~~~~~~~~
48 |
49 | If you would like Meer to use the 'elasticsearch' output plugin, then you'll need to install libcurl. To do this on Ubuntu/Debian systems, do the following:
50 |
51 | .. option:: apt-get install libcurl4-openssl-dev
52 |
53 | Maxmind (GeoIP support)
54 | ~~~~~~~~~~~~~~~~~~~~~~~
55 |
56 | If you would like Meer to add GeoIP data to Suricata/Sagan EVE data, you'll want to install the Maxmind (https://maxmind.com) library. To do this on Ubuntu/Debian systems, do the following:
57 |
58 | .. option:: apt-get install libmaxminddb-dev
59 |
60 | JEMalloc
61 | ~~~~~~~~
62 |
63 | For JEMalloc support, on Debian/Ubuntu systems, install the JEMalloc library:
64 |
65 | .. option:: apt-get install libjemalloc-dev
66 |
67 | TCMalloc
68 | ~~~~~~~~
69 |
70 | For TCMalloc support, on Debian/Ubuntu systems, install the TCMalloc library:
71 |
72 | .. option:: apt-get install libtcmalloc-minimal4
73 |
74 |
75 | Common configure options
76 | ^^^^^^^^^^^^^^^^^^^^^^^^
77 |
78 | .. option:: --prefix=/usr/
79 |
80 | Installs the Meer binary in the /usr/bin. The default is ``/usr/local/bin``.
81 |
82 | .. option:: --sysconfdir=/etc
83 |
84 | Installs the Meer configuration file (meer.yaml) in the /etc directory. The default is ``/usr/local/etc/``.
85 |
86 | .. option:: --with-libjsonc-libraries
87 |
88 | This option points Meer to where the json-c libraries reside.
89 |
90 | .. option:: --with-libjsonc-includes
91 |
92 | This option points Meer to where the json-c header files reside.
93 |
94 | .. option:: --with-libyaml_libraries
95 |
96 | This option points Meer to where the libyaml files reside.
97 |
98 | .. option:: --with-libyaml-includes
99 |
100 | This option points Meer to where the libyaml header files reside.
101 |
102 | .. option:: --enable-redis
103 |
104 | This option enables Redis output support. It requires "hiredis" to be installedt.
105 |
106 | .. option:: --enable-elastcisearch
107 |
108 | This option enables Elastcisearch support. It requires "libcurl" to be installed.
109 |
110 | .. option:: --enable-geoip
111 |
112 | This option enables Maxmind's GeoIP support. It requires "libmaxminddb" Maxmind library to be install.
113 |
114 | .. option:: --enable-bluedot
115 |
116 | This optino allows Meer to write to a Bluedot "threat intel" database alert data via HTTP. This
117 | requres that "libcurl" be installed. You probably don't want this.
118 |
119 | .. option:: --enable-tcmalloc
120 |
121 | This options enables support for Google's TCMalloc. For more information, see https://github.com/google/tcmalloc
122 |
123 | .. option:: --enable-jemalloc
124 |
125 | This options enables support for JEMalloc. For more information, see https://jemalloc.net.
126 |
127 |
128 |
--------------------------------------------------------------------------------
/doc/source/starting-meer.rst:
--------------------------------------------------------------------------------
1 | Starting Meer
2 | =============
3 |
4 | To start Meer as root type::
5 |
6 | /usr/local/bin/meer
7 |
8 | To start Meer with a specified configuration file as root type::
9 |
10 | /usr/local/bin/meer --config /path/to/my/config
11 |
12 | To start Meer with a specified configuration file in "quiet" mode as root type::
13 |
14 | /usr/local/bin/meer --config /path/to/my/config --quiet
15 |
16 | to start Meer in the background as "root" type::
17 |
18 | /usr/local/bin/meer --daemon
19 |
20 |
--------------------------------------------------------------------------------
/doc/source/what-is-meer.rst:
--------------------------------------------------------------------------------
1 | What is Meer
2 | ============
3 |
4 | "Meer" is a dedicated data broker for the `Suricata `_ IDS/IPS system and the `Sagan `_ log analysis engine.
5 |
6 | Meer takes EVE data (JSON) from Suricata or Sagan (via an ``input-plugin``), augments it by enriching it
7 | with DNS, GeoIP, and other information (via the ``meer-core``), and then pushes the data to a database (via a ``output-plugin``) of your choice.
8 |
9 | Meer is written in C which makes it fast and very light weight. This makes is suitable for processing data on systems with limited resource.
10 |
11 | Meer ``input-plugins`` that are currently supported are Suricata/Sagan EVE ("spool") files and Redis.
12 |
13 | Meer ``output-plugins`` that are currently supported are Elasticsearch, Opensearch, Zincsearch
14 | (https://github.com/zinclabs/zinc), Redis, named pipes, files, and "external" programs. Meer release 1.0.0
15 | supports SQL (MariaDB, MySQL and PostgreSQL) that is compatible with older "Barnyard2" systems. Meer versions
16 | _after_ 1.0.0 do _not_ support SQL.
17 |
18 | The primary Meer site is located at:
19 |
20 | https://github.com/quadrantsec/meer
21 |
22 |
23 | License
24 | -------
25 |
26 | Meer is licensed under the GNU/GPL version 2.
27 |
28 |
--------------------------------------------------------------------------------
/extra/build-test/build-test.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Simple shell script that compiles Meern with multiple flags. This helps
4 | # hunt down compile time bugs.
5 | #
6 | # - Public release (20211004)
7 | # --disable-tcmalloc
8 | #
9 | # - Disabled mysql/postgresql support (20211129)
10 |
11 | STANDARD="--disable-elasticsearch --disable-bluedot --disable-geoip --enable-redis --disable-jemalloc --disable-gzip --enable-syslog"
12 | ALLFLAGS="--enable-elasticsearch --enable-bluedot --enable-geoip --enable-redis --enable-jemalloc --enable-gzip -enable-syslog"
13 | NOFLAG="--disable-elasticsearch --disable-bluedot --disable-geoip --disable-redis --disable-jemalloc --disable-gzip --disable-syslog"
14 |
15 | LOG="output.log"
16 |
17 | MAKE_FLAGS="-j7"
18 |
19 | autoreconf -vfi
20 |
21 | echo "**** STANDARD BUILD | NO FLAGS ****"
22 | echo "**** STANDARD BUILD | NO FLAGS ****" >> $LOG
23 |
24 | #make clean
25 | #cd tools && make clean && cd ..
26 |
27 | CFLAGS=-Wall ./configure
28 |
29 | if [ "$?" != "0" ]
30 | then
31 | echo "./configure failed!";
32 | exit
33 | fi
34 |
35 | make $MAKE_FLAGS 2>> $LOG
36 |
37 | if [ "$?" != "0" ]
38 | then
39 | echo "Error on standard build!";
40 | exit
41 | fi
42 |
43 | echo "**** ALL FLAGS : $ALLFLAGS ****"
44 | echo "**** ALL FLAGS : $ALLFLAGS ****" >> $LOG
45 |
46 | make clean
47 |
48 | CFLAGS=-Wall ./configure $ALLFLAGS
49 |
50 | if [ "$?" != "0" ]
51 | then
52 | echo "./configure failed!";
53 | exit
54 | fi
55 |
56 | make $MAKE_FLAGS 2>> $LOG
57 |
58 | if [ "$?" != "0" ]
59 | then
60 | echo "Error on standard build!";
61 | exit
62 | fi
63 |
64 | echo "**** NO FLAGS : $NOFLAG ****"
65 | echo "**** NO FLAGS : $NOFLAG ****" >> $LOG
66 |
67 | make clean
68 |
69 | CFLAGS=-Wall ./configure $NOFLAG
70 |
71 | if [ "$?" != "0" ]
72 | then
73 | echo "./configure failed!";
74 | exit
75 | fi
76 |
77 | make $MAKE_FLAGS 2>> $LOG
78 |
79 | if [ "$?" != "0" ]
80 | then
81 | echo "Error on standard build!";
82 | exit
83 | fi
84 |
85 | echo "--------------------[ Rotating Through Flags ]--------------------"
86 | echo "--------------------[ Rotating Through Flags ]--------------------" >> $LOG
87 |
88 | for I in $STANDARD
89 | do
90 |
91 | make clean
92 |
93 | echo "**** FLAGS $I *****"
94 | echo "**** FLAGS $I *****" >> $LOG
95 |
96 | CFLAGS=-Wall ./configure $I
97 |
98 | if [ "$?" != "0" ]
99 | then
100 | echo "./configure failed!";
101 | exit
102 | fi
103 |
104 | make $MAKE_FLAGS 2>> $LOG
105 |
106 | if [ "$?" != "0" ]
107 | then
108 | echo "Error on with $I";
109 | exit
110 | fi
111 | done
112 |
113 | for I in $ALLFLAGS
114 | do
115 |
116 | make clean
117 |
118 | echo "**** FLAGS $I *****"
119 | echo "**** FLAGS $I *****" >> $LOG
120 |
121 | CFLAGS=-Wall ./configure $I
122 |
123 | if [ "$?" != "0" ]
124 | then
125 | echo "./configure failed!";
126 | exit
127 | fi
128 |
129 | make $MAKE_FLAGS 2>> $LOG
130 |
131 | if [ "$?" != "0" ]
132 | then
133 | echo "Error on with $I";
134 | exit
135 | fi
136 | done
137 |
138 | for I in $NOFLAGS
139 | do
140 |
141 | make clean
142 |
143 | echo "**** FLAGS $I *****"
144 | echo "**** FLAGS $I *****" >> $LOG
145 |
146 | CFLAGS=-Wall ./configure $I
147 |
148 | if [ "$?" != "0" ]
149 | then
150 | echo "./configure failed!";
151 | exit
152 | fi
153 |
154 | make $MAKE_FLAGS 2>> $LOG
155 |
156 | if [ "$?" != "0" ]
157 | then
158 | echo "Error on with $I";
159 | exit
160 | fi
161 | done
162 |
163 |
--------------------------------------------------------------------------------
/screenshots/discord.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/quadrantsec/meer/68362cac477f9fe6d8d3662aed245239c0c65725/screenshots/discord.png
--------------------------------------------------------------------------------
/src/Makefile.am:
--------------------------------------------------------------------------------
1 | ACLOCAL_AMFLAGS = -I m4
2 |
3 | AUTOMAKE_OPIONS=foreign no-dependencies subdir-objects
4 |
5 | bin_PROGRAMS = meer
6 | meer_CPPFLAGS = -I$(top_srcdir) $(LIBFASTJSON_CFLAGS) $(LIBESTR_CFLAGS)
7 | meer_LDADD = $(LIBFASTJSON_LIBS) $(LIBLOGNORM_LIBS) $(LIBESTR_LIBS)
8 |
9 | meer_SOURCES = meer.c \
10 | config-yaml.c \
11 | util.c \
12 | daemonize.c \
13 | util-strlcpy.c \
14 | util-strlcat.c \
15 | util-signal.c \
16 | util-base64.c \
17 | util-md5.c \
18 | util-dns.c \
19 | get-dns.c \
20 | get-geoip.c \
21 | get-oui.c \
22 | get-fingerprint.c \
23 | lockfile.c \
24 | counters.c \
25 | stats.c \
26 | waldo.c \
27 | output.c \
28 | usage.c \
29 | oui.c \
30 | geoip.c \
31 | calculate-stats.c \
32 | ndp-collector.c \
33 | decode-json.c \
34 | decode-output-json-client-stats.c \
35 | output-plugins/pipe.c \
36 | output-plugins/external.c \
37 | output-plugins/redis.c \
38 | output-plugins/bluedot.c \
39 | output-plugins/elasticsearch.c \
40 | output-plugins/file.c \
41 | output-plugins/syslog.c \
42 | input-plugins/file.c \
43 | input-plugins/redis.c \
44 | input-plugins/commandline.c
45 |
46 |
47 | install-data-local:
48 |
49 |
--------------------------------------------------------------------------------
/src/calculate-stats.h:
--------------------------------------------------------------------------------
1 | /*
2 | ** Copyright (C) 2018-2023 Quadrant Information Security
3 | ** Copyright (C) 2018-2023 Champ Clark III
4 | **
5 | ** This program is free software; you can redistribute it and/or modify
6 | ** it under the terms of the GNU General Public License Version 2 as
7 | ** published by the Free Software Foundation. You may not use, modify or
8 | ** distribute this program under any other version of the GNU General
9 | ** Public License.
10 | **
11 | ** This program is distributed in the hope that it will be useful,
12 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | ** GNU General Public License for more details.
15 | **
16 | ** You should have received a copy of the GNU General Public License
17 | ** along with this program; if not, write to the Free Software
18 | ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 | */
20 |
21 | void Calculate_Stats( struct json_object *json_obj, char *str );
22 |
23 |
--------------------------------------------------------------------------------
/src/config-yaml.h:
--------------------------------------------------------------------------------
1 | /*
2 | ** Copyright (C) 2018-2023 Quadrant Information Security
3 | ** Copyright (C) 2018-2023 Champ Clark III
4 | **
5 | ** This program is free software; you can redistribute it and/or modify
6 | ** it under the terms of the GNU General Public License Version 2 as
7 | ** published by the Free Software Foundation. You may not use, modify or
8 | ** distribute this program under any other version of the GNU General
9 | ** Public License.
10 | **
11 | ** This program is distributed in the hope that it will be useful,
12 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | ** GNU General Public License for more details.
15 | **
16 | ** You should have received a copy of the GNU General Public License
17 | ** along with this program; if not, write to the Free Software
18 | ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 | */
20 |
21 | #ifdef HAVE_CONFIG_H
22 | #include "config.h" /* From autoconf */
23 | #endif
24 |
25 | /* Prototypes */
26 |
27 | void Load_YAML_Config ( char *yaml_file );
28 |
29 |
30 | #ifdef HAVE_LIBYAML
31 |
32 | /************************/
33 | /* Minimum YAML version */
34 | /************************/
35 |
36 | #define YAML_VERSION_MAJOR 1
37 | #define YAML_VERSION_MINOR 1
38 |
39 | /*****************/
40 | /* Primary types */
41 | /*****************/
42 |
43 | #define YAML_TYPE_MEER 1
44 | #define YAML_TYPE_OUTPUT 2
45 | #define YAML_TYPE_INPUT 3
46 |
47 | /*******************/
48 | /* Secondary types */
49 | /*******************/
50 |
51 | #define YAML_MEER_CORE_CORE 1
52 | #define YAML_MEER_PIPE 2
53 | #define YAML_MEER_EXTERNAL 3
54 | #define YAML_MEER_REDIS 4
55 | #define YAML_MEER_BLUEDOT 5
56 | #define YAML_MEER_ELASTICSEARCH 6
57 | #define YAML_MEER_FILE 7
58 | #define YAML_MEER_SYSLOG 8
59 |
60 | /***************/
61 | /* Input types */
62 | /***************/
63 |
64 | #define YAML_INPUT_FILE 1
65 | #define YAML_INPUT_PIPE 2
66 | #define YAML_INPUT_REDIS 3
67 | #define YAML_INPUT_COMMAND_LINE 4
68 |
69 |
70 | #endif
71 |
--------------------------------------------------------------------------------
/src/counters.c:
--------------------------------------------------------------------------------
1 | /*
2 | ** Copyright (C) 2018-2023 Quadrant Information Security
3 | ** Copyright (C) 2018-2023 Champ Clark III
4 | **
5 | ** This program is free software; you can redistribute it and/or modify
6 | ** it under the terms of the GNU General Public License Version 2 as
7 | ** published by the Free Software Foundation. You may not use, modify or
8 | ** distribute this program under any other version of the GNU General
9 | ** Public License.
10 | **
11 | ** This program is distributed in the hope that it will be useful,
12 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | ** GNU General Public License for more details.
15 | **
16 | ** You should have received a copy of the GNU General Public License
17 | ** along with this program; if not, write to the Free Software
18 | ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 | */
20 |
21 | #ifdef HAVE_CONFIG_H
22 | #include "config.h" /* From autoconf */
23 | #endif
24 |
25 | #include
26 | #include
27 | #include
28 |
29 | #include "meer.h"
30 | #include "meer-def.h"
31 | #include "counters.h"
32 |
33 | extern struct _MeerCounters *MeerCounters;
34 |
35 | void Counters ( const char *event_type )
36 | {
37 |
38 | MeerCounters->total++;
39 |
40 | if ( !strcmp(event_type, "alert" ) )
41 | {
42 | MeerCounters->alert++;
43 | return;
44 | }
45 |
46 | else if ( !strcmp(event_type, "files" ) )
47 | {
48 | MeerCounters->files++;
49 | return;
50 | }
51 |
52 | else if ( !strcmp(event_type, "flow" ) )
53 | {
54 | MeerCounters->flow++;
55 | return;
56 | }
57 |
58 | else if ( !strcmp(event_type, "dns" ) )
59 | {
60 | MeerCounters->dns++;
61 | return;
62 | }
63 |
64 | else if ( !strcmp(event_type, "http" ) )
65 | {
66 | MeerCounters->http++;
67 | return;
68 | }
69 |
70 | else if ( !strcmp(event_type, "tls" ) )
71 | {
72 | MeerCounters->tls++;
73 | return;
74 | }
75 |
76 | else if ( !strcmp(event_type, "ssh" ) )
77 | {
78 | MeerCounters->ssh++;
79 | return;
80 | }
81 |
82 | else if ( !strcmp(event_type, "smtp" ) )
83 | {
84 | MeerCounters->smtp++;
85 | return;
86 | }
87 |
88 | else if ( !strcmp(event_type, "email" ) )
89 | {
90 | MeerCounters->email++;
91 | return;
92 | }
93 |
94 | else if ( !strcmp(event_type, "fileinfo" ) )
95 | {
96 | MeerCounters->fileinfo++;
97 | return;
98 | }
99 |
100 | else if ( !strcmp(event_type, "dhcp" ) )
101 | {
102 | MeerCounters->dhcp++;
103 | return;
104 | }
105 |
106 | else if ( !strcmp(event_type, "stats" ) )
107 | {
108 | MeerCounters->stats++;
109 | return;
110 | }
111 |
112 | else if ( !strcmp(event_type, "rdp" ) )
113 | {
114 | MeerCounters->rdp++;
115 | return;
116 | }
117 |
118 | else if ( !strcmp(event_type, "sip" ) )
119 | {
120 | MeerCounters->sip++;
121 | return;
122 | }
123 |
124 | else if ( !strcmp(event_type, "ftp" ) || !strcmp(event_type, "ftp_data" ) )
125 | {
126 | MeerCounters->ftp++;
127 | return;
128 | }
129 |
130 | else if ( !strcmp(event_type, "ikev2" ) )
131 | {
132 | MeerCounters->ikev2++;
133 | return;
134 | }
135 |
136 | else if ( !strcmp(event_type, "nfs" ) )
137 | {
138 | MeerCounters->nfs++;
139 | return;
140 | }
141 |
142 | else if ( !strcmp(event_type, "tftp" ) )
143 | {
144 | MeerCounters->tftp++;
145 | return;
146 | }
147 |
148 | else if ( !strcmp(event_type, "smb" ) )
149 | {
150 | MeerCounters->smb++;
151 | return;
152 | }
153 |
154 | else if ( !strcmp(event_type, "dcerpc" ) )
155 | {
156 | MeerCounters->dcerpc++;
157 | return;
158 | }
159 |
160 | else if ( !strcmp(event_type, "mqtt" ) )
161 | {
162 | MeerCounters->mqtt++;
163 | return;
164 | }
165 |
166 | else if ( !strcmp(event_type, "netflow" ) )
167 | {
168 | MeerCounters->netflow++;
169 | return;
170 | }
171 |
172 | else if ( !strcmp(event_type, "metadata" ) )
173 | {
174 | MeerCounters->metadata++;
175 | return;
176 | }
177 |
178 | else if ( !strcmp(event_type, "dnp3" ) )
179 | {
180 | MeerCounters->dnp3++;
181 | return;
182 | }
183 |
184 | else if ( !strcmp(event_type, "anomaly" ) )
185 | {
186 | MeerCounters->anomaly++;
187 | return;
188 | }
189 |
190 | else if ( !strcmp(event_type, "fingerprint" ) )
191 | {
192 | MeerCounters->fingerprint++;
193 | return;
194 | }
195 |
196 | else if ( !strcmp(event_type, "client_stats" ) )
197 | {
198 | MeerCounters->client_stats++;
199 | return;
200 | }
201 |
202 | MeerCounters->unknown++;
203 | Meer_Log(WARN, "[%s, line %d] Unknown event_type '%s'. Skipping....", __FILE__, __LINE__, event_type);
204 |
205 | }
206 |
--------------------------------------------------------------------------------
/src/counters.h:
--------------------------------------------------------------------------------
1 | /*
2 | ** Copyright (C) 2018-2023 Quadrant Information Security
3 | ** Copyright (C) 2018-2023 Champ Clark III
4 | **
5 | ** This program is free software; you can redistribute it and/or modify
6 | ** it under the terms of the GNU General Public License Version 2 as
7 | ** published by the Free Software Foundation. You may not use, modify or
8 | ** distribute this program under any other version of the GNU General
9 | ** Public License.
10 | **
11 | ** This program is distributed in the hope that it will be useful,
12 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | ** GNU General Public License for more details.
15 | **
16 | ** You should have received a copy of the GNU General Public License
17 | ** along with this program; if not, write to the Free Software
18 | ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 | */
20 |
21 | void Counters ( const char *event_type );
22 |
--------------------------------------------------------------------------------
/src/daemonize.c:
--------------------------------------------------------------------------------
1 | /*
2 | ** Copyright (C) 2018-2023 Quadrant Information Security
3 | ** Copyright (C) 2018-2023 Champ Clark III
4 | **
5 | ** This program is free software; you can redistribute it and/or modify
6 | ** it under the terms of the GNU General Public License Version 2 as
7 | ** published by the Free Software Foundation. You may not use, modify or
8 | ** distribute this program under any other version of the GNU General
9 | ** Public License.
10 | **
11 | ** This program is distributed in the hope that it will be useful,
12 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | ** GNU General Public License for more details.
15 | **
16 | ** You should have received a copy of the GNU General Public License
17 | ** along with this program; if not, write to the Free Software
18 | ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 | */
20 |
21 | #ifdef HAVE_CONFIG_H
22 | #include "config.h" /* From autoconf */
23 | #endif
24 |
25 | #include
26 | #include
27 | #include
28 | #include
29 | #include
30 | #include
31 | #include
32 |
33 |
34 | #include "meer-def.h"
35 | #include "meer.h"
36 |
37 | extern struct _MeerConfig *MeerConfig;
38 |
39 | void Daemonize()
40 | {
41 |
42 | Meer_Log(NORMAL, "Becoming a daemon!");
43 |
44 | pid_t pid = 0;
45 | pid = fork();
46 |
47 | if ( pid == 0 )
48 | {
49 |
50 | /* Child */
51 |
52 | if ( setsid() == -1 )
53 | {
54 | Meer_Log(ERROR, "[%s, line %d] Failed creating new session while daemonizing", __FILE__, __LINE__);
55 | exit(1);
56 | }
57 |
58 | pid = fork();
59 |
60 | if ( pid == 0 )
61 | {
62 |
63 | /* Grandchild, the actual daemon */
64 |
65 | if ( chdir("/") == -1 )
66 | {
67 | Meer_Log(ERROR, "[%s, line %d] Failed changing directory to / after daemonizing [errno %d]", __FILE__, __LINE__, errno);
68 | exit(1);
69 | }
70 |
71 | /* Close and re-open stdin, stdout, and stderr, so as to
72 | to release anyone waiting on them. */
73 |
74 | close(0);
75 | close(1);
76 | close(2);
77 |
78 | if ( open("/dev/null", O_RDONLY) == -1 )
79 | {
80 | Meer_Log(ERROR, "[%s, line %d] Failed reopening stdin after daemonizing [errno %d]", __FILE__, __LINE__, errno);
81 | }
82 |
83 | if ( open("/dev/null", O_WRONLY) == -1 )
84 | {
85 | Meer_Log(ERROR, "[%s, line %d] Failed reopening stdout after daemonizing [errno %d]", __FILE__, __LINE__, errno);
86 | }
87 |
88 | if ( open("/dev/null", O_RDWR) == -1 )
89 | {
90 | Meer_Log(ERROR, "[%s, line %d] Failed reopening stderr after daemonizing [errno %d]", __FILE__, __LINE__, errno);
91 | }
92 |
93 | }
94 | else if ( pid < 0 )
95 | {
96 |
97 | Meer_Log(ERROR, "[%s, line %d] Failed second fork while daemonizing", __FILE__, __LINE__);
98 | exit(1);
99 |
100 | }
101 | else
102 | {
103 |
104 | exit(0);
105 | }
106 |
107 | }
108 | else if ( pid < 0 )
109 | {
110 |
111 | Meer_Log(ERROR, "[%s, line %d] Failed first fork while daemonizing", __FILE__, __LINE__);
112 | exit(1);
113 |
114 | }
115 | else
116 | {
117 |
118 | /* Wait for child to exit */
119 | waitpid(pid, NULL, 0);
120 | exit(0);
121 | }
122 |
123 | }
124 |
125 |
--------------------------------------------------------------------------------
/src/daemonize.h:
--------------------------------------------------------------------------------
1 | void Daemonize();
2 |
--------------------------------------------------------------------------------
/src/decode-json.h:
--------------------------------------------------------------------------------
1 | /*
2 | ** Copyright (C) 2018-2023 Quadrant Information Security
3 | ** Copyright (C) 2018-2023 Champ Clark III
4 | **
5 | ** This program is free software; you can redistribute it and/or modify
6 | ** it under the terms of the GNU General Public License Version 2 as
7 | ** published by the Free Software Foundation. You may not use, modify or
8 | ** distribute this program under any other version of the GNU General
9 | ** Public License.
10 | **
11 | ** This program is distributed in the hope that it will be useful,
12 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | ** GNU General Public License for more details.
15 | **
16 | ** You should have received a copy of the GNU General Public License
17 | ** along with this program; if not, write to the Free Software
18 | ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 | */
20 |
21 | bool Decode_JSON( char *json_string );
22 |
--------------------------------------------------------------------------------
/src/decode-output-json-client-stats.h:
--------------------------------------------------------------------------------
1 | /*
2 | ** Copyright (C) 2018-2023 Quadrant Information Security
3 | ** Copyright (C) 2018-2023 Champ Clark III
4 | **
5 | ** This program is free software; you can redistribute it and/or modify
6 | ** it under the terms of the GNU General Public License Version 2 as
7 | ** published by the Free Software Foundation. You may not use, modify or
8 | ** distribute this program under any other version of the GNU General
9 | ** Public License.
10 | **
11 | ** This program is distributed in the hope that it will be useful,
12 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | ** GNU General Public License for more details.
15 | **
16 | ** You should have received a copy of the GNU General Public License
17 | ** along with this program; if not, write to the Free Software
18 | ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 | */
20 |
21 | #ifdef HAVE_CONFIG_H
22 | #include "config.h" /* From autoconf */
23 | #endif
24 |
25 | #ifdef HAVE_LIBJSON_C
26 | #include
27 | #endif
28 |
29 | #ifndef HAVE_LIBJSON_C
30 | libjson-c is required for Meer to function!
31 | #endif
32 |
33 | void Decode_Output_JSON_Client_Stats ( struct json_object *json_obj, const char *json_string );
34 |
35 |
--------------------------------------------------------------------------------
/src/geoip.c:
--------------------------------------------------------------------------------
1 | /*
2 | ** Copyright (C) 2018-2023 Quadrant Information Security
3 | ** Copyright (C) 2018-2023 Champ Clark III
4 | **
5 | ** This program is free software; you can redistribute it and/or modify
6 | ** it under the terms of the GNU General Public License Version 2 as
7 | ** published by the Free Software Foundation. You may not use, modify or
8 | ** distribute this program under any other version of the GNU General
9 | ** Public License.
10 | **
11 | ** This program is distributed in the hope that it will be useful,
12 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | ** GNU General Public License for more details.
15 | **
16 | ** You should have received a copy of the GNU General Public License
17 | ** along with this program; if not, write to the Free Software
18 | ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 | */
20 |
21 | #ifdef HAVE_CONFIG_H
22 | #include "config.h" /* From autoconf */
23 | #endif
24 |
25 | #ifdef HAVE_LIBMAXMINDDB
26 |
27 | #include
28 | #include
29 | #include
30 | #include
31 | #include
32 |
33 | #include "meer.h"
34 | #include "meer-def.h"
35 | #include "util.h"
36 | #include "geoip.h"
37 |
38 | extern struct _MeerConfig *MeerConfig;
39 |
40 | MMDB_s geoip;
41 |
42 | void Open_GeoIP_Database( void )
43 | {
44 |
45 | int status;
46 |
47 | /*
48 | * The GeoIP library gives a really vague error when it cannot load
49 | * the GeoIP database. We give the user more information here so
50 | * that they might fix the issue.
51 | */
52 |
53 | status = access(MeerConfig->geoip_database, R_OK);
54 |
55 | if ( status != 0 )
56 | {
57 | Meer_Log(WARN, "Cannot open '%s' [%s]!", MeerConfig->geoip_database, strerror(errno));
58 | Meer_Log(ERROR, "Make sure the GeoIP database '%s' is readable by '%s'.", MeerConfig->geoip_database, MeerConfig->runas);
59 | }
60 |
61 | status = MMDB_open(MeerConfig->geoip_database, MMDB_MODE_MMAP, &geoip);
62 |
63 | if ( status != 0 )
64 | {
65 | Meer_Log(ERROR, "Error loading Maxmind GeoIP data (%s). Are you trying to load an older, non-GeoIP database?", MeerConfig->geoip_database);
66 | }
67 |
68 |
69 | }
70 |
71 | void GeoIP_Lookup( const char *ip_address, struct _GeoIP *GeoIP )
72 | {
73 |
74 | int gai_error;
75 | int mmdb_error;
76 | int res;
77 |
78 | bool failure = false;
79 |
80 | unsigned char ip_convert[MAXIPBIT] = { 0 };
81 |
82 | IP2Bit( (char*)ip_address, ip_convert);
83 |
84 | if ( Is_Notroutable(ip_convert) )
85 | {
86 | return;
87 | }
88 |
89 | MMDB_lookup_result_s result = MMDB_lookup_string(&geoip, ip_address, &gai_error, &mmdb_error);
90 | MMDB_entry_data_s entry_data;
91 |
92 | /* Country code */
93 |
94 | res = MMDB_get_value(&result.entry, &entry_data, "country", "iso_code", NULL);
95 |
96 | if (res != MMDB_SUCCESS)
97 | {
98 | strlcpy(GeoIP->country, "LOOKUP_FAILURE", sizeof(GeoIP->country));
99 | failure = true;
100 | }
101 |
102 | if ( !entry_data.has_data || entry_data.type != MMDB_DATA_TYPE_UTF8_STRING )
103 | {
104 | strlcpy( GeoIP->country, "NOT_FOUND", sizeof( GeoIP->country ) );
105 | failure = true;
106 | }
107 |
108 | if ( failure == false )
109 | {
110 | strlcpy(GeoIP->country, entry_data.utf8_string, 3);
111 | }
112 |
113 | /* City */
114 |
115 | MMDB_get_value(&result.entry, &entry_data, "city", "names", "en", NULL);
116 |
117 | if ( entry_data.has_data )
118 | {
119 | strlcpy(GeoIP->city, entry_data.utf8_string, entry_data.data_size+1);
120 | }
121 |
122 | /* Subdivision */
123 |
124 | MMDB_get_value(&result.entry, &entry_data, "subdivisions", "0", "iso_code", NULL);
125 |
126 | if ( entry_data.has_data )
127 | {
128 | strlcpy(GeoIP->subdivision, entry_data.utf8_string, entry_data.data_size+1);
129 | }
130 |
131 | /* Postal */
132 |
133 | MMDB_get_value(&result.entry, &entry_data, "postal", "code", NULL);
134 |
135 | if ( entry_data.has_data )
136 | {
137 | strlcpy(GeoIP->postal, entry_data.utf8_string, entry_data.data_size+1);
138 | }
139 |
140 | /* Timezone */
141 |
142 | MMDB_get_value(&result.entry, &entry_data, "location", "time_zone", NULL);
143 |
144 | if ( entry_data.has_data )
145 | {
146 | strlcpy(GeoIP->timezone, entry_data.utf8_string, entry_data.data_size+1);
147 | }
148 |
149 | /* Latitude */
150 |
151 | MMDB_get_value(&result.entry, &entry_data, "location", "latitude", NULL);
152 |
153 | if ( entry_data.has_data )
154 | {
155 | snprintf(GeoIP->latitude, sizeof(GeoIP->latitude), "%f", entry_data.double_value);
156 | GeoIP->latitude[ sizeof(GeoIP->latitude) - 1 ] = '\0';
157 | }
158 |
159 | /* Longitude */
160 |
161 | MMDB_get_value(&result.entry, &entry_data, "location", "longitude", NULL);
162 |
163 | if ( entry_data.has_data )
164 | {
165 | snprintf(GeoIP->longitude, sizeof(GeoIP->longitude), "%f", entry_data.double_value);
166 | GeoIP->longitude[ sizeof(GeoIP->longitude) - 1 ] = '\0';
167 | }
168 |
169 | }
170 |
171 | #endif
172 |
--------------------------------------------------------------------------------
/src/geoip.h:
--------------------------------------------------------------------------------
1 | /*
2 | ** Copyright (C) 2018-2023 Quadrant Information Security
3 | ** Copyright (C) 2018-2023 Champ Clark III
4 | **
5 | ** This program is free software; you can redistribute it and/or modify
6 | ** it under the terms of the GNU General Public License Version 2 as
7 | ** published by the Free Software Foundation. You may not use, modify or
8 | ** distribute this program under any other version of the GNU General
9 | ** Public License.
10 | **
11 | ** This program is distributed in the hope that it will be useful,
12 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | ** GNU General Public License for more details. **
15 | ** You should have received a copy of the GNU General Public License
16 | ** along with this program; if not, write to the Free Software
17 | ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 | */
19 |
20 | typedef struct _GeoIP _GeoIP;
21 | struct _GeoIP
22 | {
23 |
24 | uint_fast8_t results;
25 |
26 | char city[32];
27 | char country[32];
28 | char subdivision[3];
29 | char postal[16];
30 | char timezone[32];
31 | char latitude[16];
32 | char longitude[16];
33 |
34 | };
35 |
36 |
37 | void Open_GeoIP_Database( void );
38 | void GeoIP_Lookup( const char *ip_address, struct _GeoIP *GeoIP );
39 |
40 |
--------------------------------------------------------------------------------
/src/get-dns.c:
--------------------------------------------------------------------------------
1 | /*
2 | ** Copyright (C) 2018-2023 Quadrant Information Security
3 | ** Copyright (C) 2018-2023 Champ Clark III
4 | **
5 | ** This program is free software; you can redistribute it and/or modify
6 | ** it under the terms of the GNU General Public License Version 2 as
7 | ** published by the Free Software Foundation. You may not use, modify or
8 | ** distribute this program under any other version of the GNU General
9 | ** Public License.
10 | **
11 | ** This program is distributed in the hope that it will be useful,
12 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | ** GNU General Public License for more details.
15 | **
16 | ** You should have received a copy of the GNU General Public License
17 | ** along with this program; if not, write to the Free Software
18 | ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 | */
20 |
21 | #ifdef HAVE_CONFIG_H
22 | #include "config.h" /* From autoconf */
23 | #endif
24 |
25 | #include
26 |
27 | #include
28 | #include
29 |
30 | #include "meer-def.h"
31 | #include "meer.h"
32 | #include "util-dns.h"
33 |
34 | extern struct _MeerConfig *MeerConfig;
35 | extern struct _MeerCounters *MeerCounters;
36 |
37 | /******************************************************************/
38 | /* Get_DNS() - looks up and adds DNS PTR records to a JSON object */
39 | /******************************************************************/
40 |
41 | void Get_DNS( struct json_object *json_obj, char *str )
42 | {
43 |
44 | struct json_object *tmp = NULL;
45 |
46 | char src_ip[64] = { 0 };
47 | char dest_ip[64] = { 0 };
48 |
49 | char src_dns[256] = { 0 };
50 | char dest_dns[256] = { 0 };
51 |
52 | json_object_object_get_ex(json_obj, "src_ip", &tmp);
53 | strlcpy( src_ip, json_object_get_string(tmp), sizeof(src_ip) );
54 |
55 | json_object_object_get_ex(json_obj, "dest_ip", &tmp);
56 | strlcpy( dest_ip, json_object_get_string(tmp), sizeof(dest_ip) );
57 |
58 | DNS_Lookup_Reverse( src_ip, src_dns, sizeof( src_dns ) );
59 |
60 | if ( src_dns[0] != '\0' )
61 | {
62 | json_object *jsrc_dns = json_object_new_string(src_dns);
63 | json_object_object_add(json_obj,"src_dns", jsrc_dns);
64 | }
65 |
66 | DNS_Lookup_Reverse( dest_ip, dest_dns, sizeof( dest_dns ) );
67 |
68 | if ( dest_dns[0] != '\0' )
69 | {
70 | json_object *jdest_dns = json_object_new_string(dest_dns);
71 | json_object_object_add(json_obj,"dest_dns", jdest_dns);
72 | }
73 |
74 | snprintf(str, MeerConfig->payload_buffer_size, "%s", (char*)json_object_to_json_string(json_obj) );
75 |
76 | }
77 |
78 | /****************************************************************************/
79 | /* Is_DNS_Event_Type() - Used to determine if an "event_type" need to have */
80 | /* DNS PTR records added or not. */
81 | /****************************************************************************/
82 |
83 | bool Is_DNS_Event_Type( const char *event_type )
84 | {
85 |
86 | uint8_t i = 0;
87 |
88 | /* If it's 'all' we always return true */
89 |
90 | if ( MeerConfig->dns_lookup_types[0][0] == 'a' && MeerConfig->dns_lookup_types[0][1] == 'l' &&
91 | MeerConfig->dns_lookup_types[0][2] == 'l' )
92 | {
93 | return(true);
94 | }
95 |
96 | /* Lookup event_type and decide DNS PTR is needed */
97 |
98 | for ( i = 0; i < MeerConfig->dns_lookup_types_count; i++ )
99 | {
100 |
101 | if ( !strcmp( event_type, MeerConfig->dns_lookup_types[i] ) )
102 | {
103 | return(true);
104 | }
105 |
106 | }
107 |
108 | return(false);
109 | }
110 |
111 |
--------------------------------------------------------------------------------
/src/get-dns.h:
--------------------------------------------------------------------------------
1 | /*
2 | ** Copyright (C) 2018-2023 Quadrant Information Security
3 | ** Copyright (C) 2018-2023 Champ Clark III
4 | **
5 | ** This program is free software; you can redistribute it and/or modify
6 | ** it under the terms of the GNU General Public License Version 2 as
7 | ** published by the Free Software Foundation. You may not use, modify or
8 | ** distribute this program under any other version of the GNU General
9 | ** Public License.
10 | **
11 | ** This program is distributed in the hope that it will be useful,
12 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | ** GNU General Public License for more details.
15 | **
16 | ** You should have received a copy of the GNU General Public License
17 | ** along with this program; if not, write to the Free Software
18 | ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 | */
20 |
21 | void Get_DNS( struct json_object *json_obj, char *str );
22 | bool Is_DNS_Event_Type( const char *event_type );
23 |
24 |
--------------------------------------------------------------------------------
/src/get-fingerprint.h:
--------------------------------------------------------------------------------
1 | /*
2 | ** Copyright (C) 2018-2023 Quadrant Information Security
3 | ** Copyright (C) 2018-2023 Champ Clark III
4 | **
5 | ** This program is free software; you can redistribute it and/or modify
6 | ** it under the terms of the GNU General Public License Version 2 as
7 | ** published by the Free Software Foundation. You may not use, modify or
8 | ** distribute this program under any other version of the GNU General
9 | ** Public License.
10 | **
11 | ** This program is distributed in the hope that it will be useful,
12 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | ** GNU General Public License for more details.
15 | **
16 | ** You should have received a copy of the GNU General Public License
17 | ** along with this program; if not, write to the Free Software
18 | ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 | */
20 |
21 |
22 | void Fingerprint_DHCP ( struct json_object *json_obj, const char *json_string );
23 | bool Fingerprint_In_Range( char *ip_address );
24 | bool Is_Fingerprint( struct json_object *json_obj );
25 | bool Fingerprint_JSON_IP_Redis ( struct json_object *json_obj );
26 | bool Fingerprint_JSON_Event_Redis ( struct json_object *json_obj, char *str, size_t size );
27 | void Get_Fingerprint( struct json_object *json_obj, char *str, size_t size, const char *json_string );
28 |
29 |
--------------------------------------------------------------------------------
/src/get-geoip.c:
--------------------------------------------------------------------------------
1 | /*
2 | ** Copyright (C) 2018-2023 Quadrant Information Security
3 | ** Copyright (C) 2018-2023 Champ Clark III
4 | **
5 | ** This program is free software; you can redistribute it and/or modify
6 | ** it under the terms of the GNU General Public License Version 2 as
7 | ** published by the Free Software Foundation. You may not use, modify or
8 | ** distribute this program under any other version of the GNU General
9 | ** Public License.
10 | **
11 | ** This program is distributed in the hope that it will be useful,
12 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | ** GNU General Public License for more details.
15 | **
16 | ** You should have received a copy of the GNU General Public License
17 | ** along with this program; if not, write to the Free Software
18 | ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 | */
20 |
21 | #ifdef HAVE_CONFIG_H
22 | #include "config.h" /* From autoconf */
23 | #endif
24 |
25 | #include
26 | #include
27 | #include
28 |
29 | #include "meer-def.h"
30 | #include "meer.h"
31 |
32 | #include "geoip.h"
33 |
34 | extern struct _MeerCounters *MeerCounters;
35 | extern struct _MeerConfig *MeerConfig;
36 |
37 | #ifdef HAVE_LIBMAXMINDDB
38 |
39 | void Get_GeoIP( struct json_object *json_obj, char *str, const char *src_ip, const char *dest_ip )
40 | {
41 |
42 | /*************************************************/
43 | /* Add any GeoIP data for the source/destination */
44 | /*************************************************/
45 |
46 | struct _GeoIP *GeoIP;
47 | GeoIP = malloc(sizeof(_GeoIP));
48 |
49 | if ( GeoIP == NULL )
50 | {
51 | Meer_Log(ERROR, "[%s, line %d] Failed to allocate memory for _GeoIP. Abort!", __FILE__, __LINE__);
52 | }
53 |
54 | memset(GeoIP, 0, sizeof(_GeoIP));
55 |
56 | /*******************/
57 | /* Get src_ip data */
58 | /*******************/
59 |
60 | GeoIP_Lookup( src_ip, GeoIP );
61 |
62 | if ( GeoIP->country[0] != '\0' )
63 | {
64 |
65 | /* Only allocate json_object when we actually need to tie it to *json_obj
66 | We won't need to deallocate it as it will become part of *json_obj! */
67 |
68 | struct json_object *jobj_geoip_src = NULL;
69 | jobj_geoip_src = json_object_new_object();
70 |
71 | json_object *jgeoip_country = json_object_new_string( GeoIP->country );
72 | json_object_object_add(jobj_geoip_src,"country", jgeoip_country);
73 |
74 | if ( GeoIP->city[0] != '\0' )
75 | {
76 | json_object *jgeoip_city = json_object_new_string( GeoIP->city );
77 | json_object_object_add(jobj_geoip_src,"city", jgeoip_city);
78 | }
79 |
80 | if ( GeoIP->subdivision[0] != '\0' )
81 | {
82 | json_object *jgeoip_subdivision = json_object_new_string( GeoIP->subdivision );
83 | json_object_object_add(jobj_geoip_src,"subdivision", jgeoip_subdivision);
84 | }
85 |
86 | if ( GeoIP->postal[0] != '\0' )
87 | {
88 | json_object *jgeoip_postal = json_object_new_string( GeoIP->postal );
89 | json_object_object_add(jobj_geoip_src,"postal", jgeoip_postal);
90 | }
91 |
92 | if ( GeoIP->timezone[0] != '\0' )
93 | {
94 | json_object *jgeoip_timezone = json_object_new_string( GeoIP->timezone );
95 | json_object_object_add(jobj_geoip_src,"timezone", jgeoip_timezone);
96 | }
97 |
98 | if ( GeoIP->longitude[0] != '\0' )
99 | {
100 | json_object *jgeoip_longitude = json_object_new_string( GeoIP->longitude );
101 | json_object_object_add(jobj_geoip_src,"longitude", jgeoip_longitude);
102 | }
103 |
104 | if ( GeoIP->latitude[0] != '\0' )
105 | {
106 | json_object *jgeoip_latitude = json_object_new_string( GeoIP->latitude );
107 | json_object_object_add(jobj_geoip_src,"latitude", jgeoip_latitude);
108 | }
109 |
110 | json_object_object_add(json_obj, "geoip_src", jobj_geoip_src);
111 |
112 | }
113 |
114 | /*****************************************/
115 | /* Get dest_ip GeoIP information (reset) */
116 | /*****************************************/
117 |
118 | memset(GeoIP, 0, sizeof(_GeoIP));
119 |
120 | GeoIP_Lookup( dest_ip, GeoIP );
121 |
122 | if ( GeoIP->country[0] != '\0' )
123 | {
124 |
125 | struct json_object *jobj_geoip_dest = NULL;
126 | jobj_geoip_dest = json_object_new_object();
127 |
128 | json_object *jgeoip_country = json_object_new_string( GeoIP->country );
129 | json_object_object_add(jobj_geoip_dest,"country", jgeoip_country);
130 |
131 | if ( GeoIP->city[0] != '\0' )
132 | {
133 | json_object *jgeoip_city = json_object_new_string( GeoIP->city );
134 | json_object_object_add(jobj_geoip_dest,"city", jgeoip_city);
135 | }
136 |
137 | if ( GeoIP->subdivision[0] != '\0' )
138 | {
139 | json_object *jgeoip_subdivision = json_object_new_string( GeoIP->subdivision );
140 | json_object_object_add(jobj_geoip_dest,"subdivision", jgeoip_subdivision);
141 | }
142 |
143 | if ( GeoIP->postal[0] != '\0' )
144 | {
145 | json_object *jgeoip_postal = json_object_new_string( GeoIP->postal );
146 | json_object_object_add(jobj_geoip_dest,"postal", jgeoip_postal);
147 | }
148 |
149 | if ( GeoIP->timezone[0] != '\0' )
150 | {
151 | json_object *jgeoip_timezone = json_object_new_string( GeoIP->timezone );
152 | json_object_object_add(jobj_geoip_dest,"timezone", jgeoip_timezone);
153 | }
154 |
155 | if ( GeoIP->longitude[0] != '\0' )
156 | {
157 | json_object *jgeoip_longitude = json_object_new_string( GeoIP->longitude );
158 | json_object_object_add(jobj_geoip_dest,"longitude", jgeoip_longitude);
159 | }
160 |
161 | if ( GeoIP->latitude[0] != '\0' )
162 | {
163 | json_object *jgeoip_latitude = json_object_new_string( GeoIP->latitude );
164 | json_object_object_add(jobj_geoip_dest,"latitude", jgeoip_latitude);
165 | }
166 |
167 | json_object_object_add(json_obj, "geoip_dest", jobj_geoip_dest);
168 |
169 | }
170 |
171 | snprintf(str, MeerConfig->payload_buffer_size, "%s", (char*)json_object_to_json_string(json_obj) );
172 | free(GeoIP);
173 |
174 | }
175 |
176 | #endif
177 |
--------------------------------------------------------------------------------
/src/get-geoip.h:
--------------------------------------------------------------------------------
1 | /*
2 | ** Copyright (C) 2018-2023 Quadrant Information Security
3 | ** Copyright (C) 2018-2023 Champ Clark III
4 | **
5 | ** This program is free software; you can redistribute it and/or modify
6 | ** it under the terms of the GNU General Public License Version 2 as
7 | ** published by the Free Software Foundation. You may not use, modify or
8 | ** distribute this program under any other version of the GNU General
9 | ** Public License.
10 | **
11 | ** This program is distributed in the hope that it will be useful,
12 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | ** GNU General Public License for more details.
15 | **
16 | ** You should have received a copy of the GNU General Public License
17 | ** along with this program; if not, write to the Free Software
18 | ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 | */
20 |
21 | void Get_GeoIP( struct json_object *json_obj, char *str, const char *src_ip, const char *dest_ip );
22 |
--------------------------------------------------------------------------------
/src/get-oui.h:
--------------------------------------------------------------------------------
1 | /*
2 | ** Copyright (C) 2018-2023 Quadrant Information Security
3 | ** Copyright (C) 2018-2023 Champ Clark III
4 | **
5 | ** This program is free software; you can redistribute it and/or modify
6 | ** it under the terms of the GNU General Public License Version 2 as
7 | ** published by the Free Software Foundation. You may not use, modify or
8 | ** distribute this program under any other version of the GNU General
9 | ** Public License.
10 | **
11 | ** This program is distributed in the hope that it will be useful,
12 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | ** GNU General Public License for more details.
15 | **
16 | ** You should have received a copy of the GNU General Public License
17 | ** along with this program; if not, write to the Free Software
18 | ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 | */
20 |
21 | void Get_OUI( struct json_object *json_obj, char *str );
22 |
23 |
--------------------------------------------------------------------------------
/src/input-plugins/commandline.c:
--------------------------------------------------------------------------------
1 | /*
2 | ** Copyright (C) 2018-2023 Quadrant Information Security
3 | ** Copyright (C) 2018-2023 Champ Clark III
4 | **
5 | ** This program is free software; you can redistribute it and/or modify
6 | ** it under the terms of the GNU General Public License Version 2 as ** published by the Free Software Foundation. You may not use, modify or
7 | ** distribute this program under any other version of the GNU General
8 | ** Public License.
9 | **
10 | ** This program is distributed in the hope that it will be useful,
11 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | ** GNU General Public License for more details.
14 | **
15 | ** You should have received a copy of the GNU General Public License
16 | ** along with this program; if not, write to the Free Software
17 | ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 | */
19 |
20 | /* --file command line for normal and gzip files */
21 |
22 | #include
23 | #include
24 | #include
25 | #include
26 | #include
27 | #include
28 |
29 | #ifdef HAVE_CONFIG_H
30 | #include "config.h" /* From autoconf */
31 | #endif
32 |
33 | #ifdef HAVE_LIBZ
34 | #include
35 | #endif
36 |
37 | #include "meer.h"
38 | #include "meer-def.h"
39 | #include "util.h"
40 |
41 | #include "input-plugins/commandline.h"
42 |
43 | extern struct _MeerConfig *MeerConfig;
44 |
45 | void Command_Line()
46 | {
47 |
48 | glob_t globbuf = {0};
49 |
50 | Meer_Log(NORMAL, "--[ Command line - file input information ]--------------------------------------");
51 | Meer_Log(NORMAL, "");
52 |
53 | glob(MeerConfig->command_line, GLOB_DOOFFS, NULL, &globbuf);
54 |
55 | for (size_t z = 0; z != globbuf.gl_pathc; ++z)
56 | {
57 |
58 | if ( globbuf.gl_pathv[z][ strlen(globbuf.gl_pathv[z]) - 3 ] == '.' &&
59 | globbuf.gl_pathv[z][ strlen(globbuf.gl_pathv[z]) - 2 ] == 'g' &&
60 | globbuf.gl_pathv[z][ strlen(globbuf.gl_pathv[z]) - 1 ] == 'z' )
61 | {
62 | #ifdef HAVE_LIBZ
63 | GZIP_Input( globbuf.gl_pathv[z] );
64 | #endif
65 |
66 | #ifndef HAVE_LIBZ
67 | Meer_Log(WARN, "[%s, line %d] Meer lacks gzip/libz support. Skipping %s.", __FILE__, __LINE__, globbuf.gl_pathv[z]);
68 | #endif
69 | }
70 | else
71 | {
72 | Read_File( globbuf.gl_pathv[z] );
73 | }
74 | }
75 |
76 | Meer_Log(NORMAL, "Done processing all files.");
77 |
78 | }
79 |
80 | #ifdef HAVE_LIBZ
81 |
82 | void GZIP_Input( const char *filename )
83 | {
84 |
85 | uint64_t linecount = 0;
86 |
87 | gzFile fd;
88 |
89 | if (( fd = gzopen(filename, "rb")) == NULL )
90 | {
91 | Meer_Log(ERROR, "[%s, line %d] Cannot open %s! [%s]", __FILE__, __LINE__, filename, strerror(errno));
92 | }
93 |
94 | Meer_Log(NORMAL, "Successfully opened GZIP file %s.... processing.....", filename);
95 |
96 | char *buf = malloc(MeerConfig->payload_buffer_size);
97 |
98 | if ( buf == NULL )
99 | {
100 | fprintf(stderr, "[%s, line %d] Fatal Error: Can't allocate memory for buf! Abort!\n", __FILE__, __LINE__);
101 | exit(-1);
102 | }
103 |
104 |
105 | while(gzgets(fd, buf, MeerConfig->payload_buffer_size) != NULL)
106 | {
107 |
108 | if ( Validate_JSON_String( buf ) == 0 )
109 | {
110 | Decode_JSON( buf );
111 | }
112 |
113 | linecount++;
114 |
115 | }
116 |
117 | Meer_Log(NORMAL, "Done with %s. Processed %"PRIu64 " lines", filename, linecount);
118 |
119 | free(buf);
120 |
121 | gzclose(fd);
122 | }
123 |
124 | #endif
125 |
126 |
127 | void Read_File( const char *filename )
128 | {
129 |
130 | FILE *fd_file;
131 |
132 | struct stat st;
133 |
134 | bool skip_flag = 0;
135 | bool wait_flag = false;
136 |
137 | uint64_t linecount = 0;
138 |
139 | /* DEBUG: This never gets hit!??! */
140 |
141 | if ( ( fd_file = fopen("whatever", "r" )) == NULL )
142 | {
143 | Meer_Log(ERROR, "[%s, line %d] Cannot open %s [%s]", __FILE__, __LINE__, filename, strerror(errno));
144 | }
145 |
146 | char *buf = malloc(MeerConfig->payload_buffer_size);
147 |
148 | if ( buf == NULL )
149 | {
150 | fprintf(stderr, "[%s, line %d] Fatal Error: Can't allocate memory for buf! Abort!\n", __FILE__, __LINE__);
151 | exit(-1);
152 | }
153 |
154 | Meer_Log(NORMAL, "Processing %s......", filename);
155 |
156 | while(fgets(buf, MeerConfig->payload_buffer_size, fd_file) != NULL)
157 | {
158 |
159 | if ( Validate_JSON_String( buf ) == 0 )
160 | {
161 | Decode_JSON( buf );
162 | }
163 |
164 | linecount++;
165 |
166 | }
167 |
168 | Meer_Log(NORMAL, "Done with %s. Processed %"PRIu64 " lines", filename, linecount);
169 |
170 | free(buf);
171 | fclose(fd_file);
172 |
173 | }
174 |
--------------------------------------------------------------------------------
/src/input-plugins/commandline.h:
--------------------------------------------------------------------------------
1 | /*
2 | ** Copyright (C) 2018-2023 Quadrant Information Security
3 | ** Copyright (C) 2018-2023 Champ Clark III
4 | **
5 | ** This program is free software; you can redistribute it and/or modify
6 | ** it under the terms of the GNU General Public License Version 2 as ** published by the Free Software Foundation. You may not use, modify or
7 | ** distribute this program under any other version of the GNU General
8 | ** Public License.
9 | **
10 | ** This program is distributed in the hope that it will be useful,
11 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | ** GNU General Public License for more details.
14 | **
15 | ** You should have received a copy of the GNU General Public License
16 | ** along with this program; if not, write to the Free Software
17 | ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 | */
19 |
20 |
21 | void Command_Line( void );
22 | void GZIP_Input( const char *input_file );
23 | void Read_File( const char *filename );
24 |
25 |
--------------------------------------------------------------------------------
/src/input-plugins/file.h:
--------------------------------------------------------------------------------
1 |
2 | void Input_File( void );
3 |
--------------------------------------------------------------------------------
/src/input-plugins/redis.c:
--------------------------------------------------------------------------------
1 | /*
2 | ** Copyright (C) 2018-2023 Quadrant Information Security
3 | ** Copyright (C) 2018-2023 Champ Clark III
4 | **
5 | ** This program is free software; you can redistribute it and/or modify
6 | ** it under the terms of the GNU General Public License Version 2 as ** published by the Free Software Foundation. You may not use, modify or
7 | ** distribute this program under any other version of the GNU General
8 | ** Public License.
9 | **
10 | ** This program is distributed in the hope that it will be useful,
11 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | ** GNU General Public License for more details.
14 | **
15 | ** You should have received a copy of the GNU General Public License
16 | ** along with this program; if not, write to the Free Software
17 | ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 | */
19 |
20 | /* Redis "input" - Support for "pub/sub" */
21 |
22 | #ifdef HAVE_CONFIG_H
23 | #include "config.h" /* From autoconf */
24 | #endif
25 |
26 | #ifdef HAVE_LIBHIREDIS
27 |
28 | #include
29 | #include
30 | #include
31 | #include
32 | #include
33 | #include
34 | #include
35 | #include
36 |
37 | #include "meer-def.h"
38 | #include "meer.h"
39 | #include "util.h"
40 | #include "util-signal.h"
41 |
42 | #include "input-plugins/redis.h"
43 |
44 | /* Proto for connect callback */
45 |
46 | void connectCallback(const redisAsyncContext *c, int status);
47 |
48 | extern struct _MeerConfig *MeerConfig;
49 | extern struct _MeerInput *MeerInput;
50 |
51 | /*************************************************************/
52 | /* onMessage - Call back for what to do with data from Redis */
53 | /*************************************************************/
54 |
55 | void onMessage(redisAsyncContext *c, void *reply, void *privdata)
56 | {
57 |
58 | bool skip_flag = false;
59 |
60 | char *buf = malloc(MeerConfig->payload_buffer_size);
61 |
62 | if ( buf == NULL )
63 | {
64 | Meer_Log(ERROR, "[%s, line %d] Fatal Error: Can't allocate memory for buf! Abort!\n", __FILE__, __LINE__);
65 | }
66 |
67 | memset(buf, 0, MeerConfig->payload_buffer_size);
68 |
69 | redisReply *r = reply;
70 |
71 | /* Can't allocate for reply */
72 |
73 | if (reply == NULL)
74 | {
75 | Meer_Log(WARN, "[%s, line %d] Can't allocate memory for reply!", __FILE__, __LINE__);
76 | free(buf);
77 | return;
78 | }
79 |
80 |
81 | /* Get array of data */
82 |
83 | if (r->type == REDIS_REPLY_ARRAY)
84 | {
85 |
86 | if ( r->element[2]->str != NULL )
87 | {
88 |
89 |
90 | snprintf(buf, MeerConfig->payload_buffer_size, "%s\n", r->element[2]->str);
91 | buf[ MeerConfig->payload_buffer_size -1 ] = '\0';
92 |
93 | skip_flag = Validate_JSON_String( buf );
94 |
95 | if ( skip_flag == 0 )
96 | {
97 | Decode_JSON( buf );
98 | }
99 |
100 | }
101 | }
102 |
103 | free(buf);
104 | }
105 |
106 |
107 | void Input_Redis_Subscribe( void )
108 | {
109 |
110 | char tmp_command[512] = { 0 };
111 |
112 | struct event_base *base = event_base_new();
113 |
114 | redisAsyncContext *c = redisAsyncConnect(MeerInput->redis_server, MeerInput->redis_port);
115 |
116 | if (c->err)
117 | {
118 | Meer_Log(WARN, "[%s, line %d] Redis error: %s", __FILE__, __LINE__, c->errstr);
119 | redisAsyncFree(c);
120 | return;
121 | }
122 |
123 |
124 | if ( MeerInput->redis_password[0] != '\0' )
125 | {
126 |
127 | if ( redisAsyncCommand( c, NULL, NULL, "AUTH %s", MeerInput->redis_password) != REDIS_OK )
128 | {
129 | Meer_Log(ERROR, "ERROR LOGGING IN\n");
130 | }
131 |
132 | }
133 |
134 |
135 | snprintf(tmp_command, sizeof(tmp_command), "SUBSCRIBE %s", MeerInput->redis_key);
136 | tmp_command[ sizeof(tmp_command) - 1 ] = '\0';
137 |
138 | redisLibeventAttach(c, base);
139 | redisAsyncSetConnectCallback(c,connectCallback);
140 |
141 | redisAsyncCommand( c, onMessage, NULL, tmp_command );
142 |
143 | event_base_dispatch(base);
144 |
145 | event_base_free(base);
146 |
147 | return;
148 |
149 | }
150 |
151 |
152 | void connectCallback(const redisAsyncContext *c, int status)
153 | {
154 | if (status != REDIS_OK)
155 | {
156 | printf("Error: %s\n", c->errstr);
157 | return;
158 | }
159 | Meer_Log(NORMAL, "Connected and streaming data from \"%s\".....", MeerInput->redis_key );
160 | }
161 |
162 | //void disconnectCallback(const redisAsyncContext *c, int status) {
163 | // if (status != REDIS_OK) {
164 | // printf("Error: %s\n", c->errstr);
165 | // return;
166 | // }
167 |
168 | // Meer_Log(NORMAL, "Disconnect from stream \"%s\"", MeerInput->redis_key );
169 |
170 | //}
171 |
172 | #endif
173 |
174 |
--------------------------------------------------------------------------------
/src/input-plugins/redis.h:
--------------------------------------------------------------------------------
1 | /*
2 | ** Copyright (C) 2018-2023 Quadrant Information Security
3 | ** Copyright (C) 2018-2023 Champ Clark III
4 | **
5 | ** This program is free software; you can redistribute it and/or modify
6 | ** it under the terms of the GNU General Public License Version 2 as
7 | ** published by the Free Software Foundation. You may not use, modify or
8 | ** distribute this program under any other version of the GNU General
9 | ** Public License.
10 | **
11 | ** This program is distributed in the hope that it will be useful,
12 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | ** GNU General Public License for more details.
15 | **
16 | ** You should have received a copy of the GNU General Public License
17 | ** along with this program; if not, write to the Free Software
18 | ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 | */
20 |
21 | void Input_Redis_Subscribe( void );
22 |
--------------------------------------------------------------------------------
/src/lockfile.c:
--------------------------------------------------------------------------------
1 | /*
2 | ** Copyright (C) 2018-2023 Quadrant Information Security
3 | ** Copyright (C) 2018-2023 Champ Clark III
4 | **
5 | ** This program is free software; you can redistribute it and/or modify
6 | ** it under the terms of the GNU General Public License Version 2 as
7 | ** published by the Free Software Foundation. You may not use, modify or
8 | ** distribute this program under any other version of the GNU General
9 | ** Public License.
10 | **
11 | ** This program is distributed in the hope that it will be useful,
12 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | ** GNU General Public License for more details.
15 | **
16 | ** You should have received a copy of the GNU General Public License
17 | ** along with this program; if not, write to the Free Software
18 | ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 | */
20 |
21 | /* Lock file routines */
22 |
23 | #ifdef HAVE_CONFIG_H
24 | #include "config.h" /* From autoconf */
25 | #endif
26 |
27 | #include
28 | #include
29 | #include
30 | #include
31 | #include
32 | #include
33 | #include
34 | #include
35 |
36 | #include "meer.h"
37 | #include "meer-def.h"
38 | #include "lockfile.h"
39 |
40 | extern struct _MeerConfig *MeerConfig;
41 |
42 | void CheckLockFile ( void )
43 | {
44 |
45 | char buf[10];
46 | FILE *lck;
47 | int pid;
48 | struct stat lckcheck;
49 |
50 | /* Check for lockfile first */
51 |
52 | if (stat(MeerConfig->lock_file, &lckcheck) == 0 )
53 | {
54 |
55 | /* Lock file is present, open for read */
56 |
57 | if (( lck = fopen(MeerConfig->lock_file, "r" )) == NULL )
58 | {
59 | Meer_Log(ERROR, "[%s, line %d] Lock file '%s' is present but can't be read [%s]", __FILE__, __LINE__, MeerConfig->lock_file, strerror(errno));
60 | }
61 | else
62 | {
63 | if (!fgets(buf, sizeof(buf), lck))
64 | {
65 | Meer_Log(ERROR, "[%s, line %d] Lock file (%s) is open for reading, but can't read contents.", __FILE__, __LINE__, MeerConfig->lock_file);
66 | }
67 |
68 | fclose(lck);
69 | pid = atoi(buf);
70 |
71 | if ( pid == 0 )
72 | {
73 | Meer_Log(ERROR, "[%s, line %d] Lock file read but pid value is zero. Aborting.....", __FILE__, __LINE__);
74 | }
75 |
76 | /* Check to see if process is running. We use kill with 0 signal
77 | * to determine this. We check this return value. Signal 0
78 | * won't affect running processes */
79 |
80 | if ( kill(pid, 0) != -1 )
81 | {
82 | Meer_Log(ERROR, "[%s, line %d] It appears that Meer is already running (pid: %d).", __FILE__, __LINE__, pid);
83 | }
84 | else
85 | {
86 |
87 | Meer_Log(NORMAL, "Lock file is present, but Meer isn't at pid %d (Removing stale %s file)", pid, MeerConfig->lock_file);
88 |
89 | if (unlink(MeerConfig->lock_file))
90 | {
91 | Meer_Log(ERROR, "Unable to unlink %s.", MeerConfig->lock_file);
92 | }
93 | }
94 | }
95 | }
96 | else
97 | {
98 |
99 | /* No lock file present, so create it */
100 |
101 | if (( lck = fopen(MeerConfig->lock_file, "w" )) == NULL )
102 | {
103 | Meer_Log(ERROR, "[%s, line %d] Cannot create lock file (%s - %s)", __FILE__, __LINE__, MeerConfig->lock_file, strerror(errno));
104 | }
105 | else
106 | {
107 | fprintf(lck, "%d", getpid() );
108 | fflush(lck);
109 | fclose(lck);
110 | }
111 | }
112 | }
113 |
114 | void Remove_Lock_File ( void )
115 | {
116 |
117 | struct stat lckcheck;
118 |
119 | if ( (stat(MeerConfig->lock_file, &lckcheck) == 0) && unlink(MeerConfig->lock_file) != 0 )
120 | {
121 | Meer_Log(ERROR, "[%s, line %d] Cannot remove lock file (%s - %s)", __FILE__, __LINE__, MeerConfig->lock_file, strerror(errno));
122 | }
123 | }
124 |
125 |
--------------------------------------------------------------------------------
/src/lockfile.h:
--------------------------------------------------------------------------------
1 | /*
2 | ** Copyright (C) 2018-2023 Quadrant Information Security
3 | ** Copyright (C) 2018-2023 Champ Clark III
4 | **
5 | ** This program is free software; you can redistribute it and/or modify
6 | ** it under the terms of the GNU General Public License Version 2 as
7 | ** published by the Free Software Foundation. You may not use, modify or
8 | ** distribute this program under any other version of the GNU General
9 | ** Public License.
10 | **
11 | ** This program is distributed in the hope that it will be useful,
12 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | ** GNU General Public License for more details.
15 | **
16 | ** You should have received a copy of the GNU General Public License
17 | ** along with this program; if not, write to the Free Software
18 | ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 | */
20 |
21 | void Remove_Lock_File ( void );
22 | void CheckLockFile ( void );
23 |
24 |
--------------------------------------------------------------------------------
/src/meer-def.h:
--------------------------------------------------------------------------------
1 | /*
2 | ** Copyright (C) 2018-2023 Quadrant Information Security
3 | ** Copyright (C) 2018-2023 Champ Clark III
4 | **
5 | ** This program is free software; you can redistribute it and/or modify
6 | ** it under the terms of the GNU General Public License Version 2 as
7 | ** published by the Free Software Foundation. You may not use, modify or
8 | ** distribute this program under any other version of the GNU General
9 | ** Public License.
10 | **
11 | ** This program is distributed in the hope that it will be useful,
12 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | ** GNU General Public License for more details.
15 | **
16 | ** You should have received a copy of the GNU General Public License
17 | ** along with this program; if not, write to the Free Software
18 | ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 | */
20 |
21 | #ifdef HAVE_CONFIG_H
22 | #include "config.h" /* From autoconf */
23 | #endif
24 |
25 | #define DEFAULT_CONFIG "/usr/local/etc/meer.yaml"
26 |
27 | #define BUFFER_SIZE 10240
28 |
29 | #define MEER_LOG "/var/log/meer.log"
30 |
31 | #define BAD_IP "127.127.127.127"
32 | #define MEER_DESC "My Awesome Sensor"
33 |
34 | #define NORMAL 0
35 | #define ERROR 1
36 | #define WARN 2
37 | #define DEBUG 3
38 |
39 | #define TCP 6
40 | #define UDP 17
41 | #define ICMP 1
42 |
43 | #define SSH_SERVER 0
44 | #define SSH_CLIENT 1
45 |
46 | #define MAXIP 64 /* Max IP length */
47 | #define MAXIPBIT 16 /* Max IP length in bytes */
48 |
49 | #define IPv4 4
50 | #define IPv6 6
51 |
52 | #define DNS_CACHE_DEFAULT 900
53 | #define DNS_LOOKUP_TYPES "alert,ssh,http,rdp,ftp"
54 | #define DNS_MAX_TYPES 20
55 | #define DNS_MAX_TYPES_LEN 16
56 |
57 | #define PACKET_BUFFER_SIZE_DEFAULT 1048576
58 |
59 | #define SQL_RECONNECT_TIME 10
60 |
61 | #define MAX_SQL_QUERY 10240 + PACKET_BUFFER_SIZE_DEFAULT
62 |
63 |
64 | #define EXTRA_ORIGNAL_CLIENT_IPV4 1
65 | #define EXTRA_ORIGNAL_CLIENT_IPV6 2
66 | #define EXTRA_UNUSED 3
67 | #define EXTRA_GZIP_DECOMPRESSED_DATA 4
68 | #define EXTRA_SMTP_FILENAME 5
69 | #define EXTRA_SMTP_MAIL_FROM 6
70 | #define EXTRA_SMTP_RCPT_TO 7
71 | #define EXTRA_SMTP_EMAIL_HEADERS 8
72 | #define EXTRA_HTTP_URI 9
73 | #define EXTRA_HTTP_HOSTNAME 10
74 | #define EXTRA_IPV6_SOURCE_ADDRESS 11
75 | #define EXTRA_IPV6_DESTINATION_ADDRESS 12
76 | #define EXTRA_NORMALIZED_JAVASCRIPT 13
77 |
78 | #define DEFAULT_PIPE_SIZE 1048576
79 |
80 | #define MAX_REDIS_BATCH 100
81 | #define DEFAULT_REDIS_KEY "suricata"
82 |
83 | #define MAX_ELASTICSEARCH_BATCH 10000
84 |
85 | #define FINGERPRINT_REDIS_KEY "fingerprint"
86 | #define FINGERPRINT_REDIS_EXPIRE 3600
87 | #define FINGERPRINT_DHCP_REDIS_EXPIRE 86400
88 | #define FINGERPRINT_IP_REDIS_EXPIRE 86400
89 | #define FINGERPRINT_EVENT_REDIS_EXPIRE 86400
90 |
91 | #define MEER_USER_AGENT "User-Agent: Meer"
92 | #define MEER_BLUEDOT_SOURCE "Meer"
93 |
94 | #define MD5_SIZE 33
95 | #define SHA1_SIZE 41
96 | #define SHA256_SIZE 65
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
--------------------------------------------------------------------------------
/src/ndp-collector.h:
--------------------------------------------------------------------------------
1 | /* ** Copyright (C) 2018-2023 Quadrant Information Security ** Copyright (C) 2018-2023 Champ Clark III ** ** This program is free software; you can redistribute it and/or modify
2 | ** it under the terms of the GNU General Public License Version 2 as
3 | ** published by the Free Software Foundation. You may not use, modify or
4 | ** distribute this program under any other version of the GNU General
5 | ** Public License.
6 | **
7 | ** This program is distributed in the hope that it will be useful,
8 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of
9 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 | ** GNU General Public License for more details.
11 | **
12 | ** You should have received a copy of the GNU General Public License
13 | ** along with this program; if not, write to the Free Software
14 | ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
15 | */
16 |
17 | typedef struct _NDP_SMB_Commands _NDP_SMB_Commands;
18 | struct _NDP_SMB_Commands
19 | {
20 | char command[32];
21 | };
22 |
23 | typedef struct _NDP_FTP_Commands _NDP_FTP_Commands;
24 | struct _NDP_FTP_Commands
25 | {
26 | char command[5];
27 | };
28 |
29 |
30 | bool NDP_In_Range( char *ip_address );
31 | void NDP_Collector( struct json_object *json_obj, const char *json_string, const char *event_type, const char *src_ip, const char *dest_ip, const char *flow_id );
32 | void NDP_Flow( struct json_object *json_obj, const char *src_ip, const char *dest_ip, const char *flow_id );
33 | void NDP_FileInfo( struct json_object *json_obj, const char *src_ip, const char *dest_ip, const char *flow_id );
34 | void NDP_TLS( struct json_object *json_obj, const char *src_ip, const char *dest_ip, const char *flow_id );
35 | void NDP_DNS( struct json_object *json_obj, const char *src_ip, const char *dest_ip, const char *flow_id );
36 | void NDP_SSH( struct json_object *json_obj, const char *src_ip, const char *dest_ip, const char *flow_id );
37 | void NDP_HTTP( struct json_object *json_obj, const char *src_ip, const char *dest_ip, const char *flow_id );
38 | void NDP_SMB( struct json_object *json_obj, const char *src_ip, const char *dest_ip, const char *flow_id );
39 | void NDP_FTP( struct json_object *json_obj, const char *src_ip, const char *dest_ip, const char *flow_id );
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/src/oui.c:
--------------------------------------------------------------------------------
1 | /*
2 | ** Copyright (C) 2018-2023 Quadrant Information Security
3 | ** Copyright (C) 2018-2023 Champ Clark III
4 | **
5 | ** This program is free software; you can redistribute it and/or modify
6 | ** it under the terms of the GNU General Public License Version 2 as
7 | ** published by the Free Software Foundation. You may not use, modify or
8 | ** distribute this program under any other version of the GNU General
9 | ** Public License.
10 | **
11 | ** This program is distributed in the hope that it will be useful,
12 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | ** GNU General Public License for more details.
15 | **
16 | ** You should have received a copy of the GNU General Public License
17 | ** along with this program; if not, write to the Free Software
18 | ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 | */
20 |
21 |
22 | /* Lookup routines for MAC address / vender */
23 |
24 | #ifdef HAVE_CONFIG_H
25 | #include "config.h" /* From autoconf */
26 | #endif
27 |
28 | #include
29 | #include
30 | #include
31 | #include
32 |
33 | #include "meer.h"
34 | #include "meer-def.h"
35 | #include "util.h"
36 | #include "oui.h"
37 |
38 | extern struct _MeerCounters *MeerCounters;
39 | extern struct _MeerConfig *MeerConfig;
40 |
41 | struct _Manfact_Struct *MF_Struct = NULL;
42 |
43 | /*****************************************************************************/
44 | /* Load MAC/Vendor information into memory. This list is from the Wireshark */
45 | /* team. Get it: */
46 | /* https://gitlab.com/wireshark/wireshark/raw/master/manuf */
47 | /* The list need to be in the wireshark format! */
48 | /*****************************************************************************/
49 |
50 | void Load_OUI( void )
51 | {
52 |
53 | char buf[1024] = { 0 };
54 | char *saveptr = NULL;
55 |
56 | char *mac = NULL;
57 | char *short_manfact = NULL;
58 | char *long_manfact = NULL;
59 |
60 | int linecount = 0;
61 |
62 | FILE *mf;
63 |
64 | if (( mf = fopen(MeerConfig->oui_filename, "r" )) == NULL )
65 | {
66 | Meer_Log(ERROR, "[%s, line %d] Cannot open rule file %s. [%s]", __FILE__, __LINE__, MeerConfig->oui_filename, strerror(errno) );
67 | }
68 |
69 | while(fgets(buf, sizeof(buf), mf) != NULL)
70 | {
71 |
72 | linecount++;
73 |
74 | /* Skip comments, etc */
75 |
76 | if (buf[0] == '#' || buf[0] == 10 || buf[0] == ';' || buf[0] == 32)
77 | {
78 | continue;
79 | }
80 |
81 | buf[ strlen(buf) - 1 ] = '\0'; /* Remove return */
82 |
83 | /* Pull in all values */
84 |
85 | mac = strtok_r(buf, "\t", &saveptr);
86 | short_manfact = strtok_r(NULL, "\t", &saveptr);
87 | long_manfact = strtok_r(NULL, "\t", &saveptr);
88 |
89 | /* mac / short_manfact should _always be there. long_manfact isn't
90 | always there */
91 |
92 | if ( mac == NULL || short_manfact == NULL )
93 | {
94 | Meer_Log(ERROR, "[%s, line %d] %s incorrectly formated at line %d", __FILE__, __LINE__, MeerConfig->oui_filename, linecount );
95 | }
96 |
97 | /* if no long_manfact is present */
98 |
99 | if ( long_manfact == NULL )
100 | {
101 | long_manfact = "0";
102 | }
103 |
104 | /* Allocate memory for classifications, but not comments */
105 |
106 | MF_Struct = (_Manfact_Struct *) realloc(MF_Struct, (MeerCounters->OUICount+1) * sizeof(_Manfact_Struct));
107 |
108 | if ( MF_Struct == NULL )
109 | {
110 | Meer_Log(ERROR, "[%s, line %d] Failed to reallocate memory for _Manfact_Struct. Abort!", __FILE__, __LINE__);
111 | }
112 |
113 | memset(&MF_Struct[MeerCounters->OUICount], 0, sizeof(struct _Manfact_Struct));
114 |
115 |
116 | /* Store into memory the values */
117 |
118 | strlcpy(MF_Struct[MeerCounters->OUICount].mac, mac, sizeof(MF_Struct[MeerCounters->OUICount].mac));
119 | strlcpy(MF_Struct[MeerCounters->OUICount].short_manfact, short_manfact, sizeof(MF_Struct[MeerCounters->OUICount].short_manfact));
120 | strlcpy(MF_Struct[MeerCounters->OUICount].long_manfact, long_manfact, sizeof(MF_Struct[MeerCounters->OUICount].long_manfact));
121 |
122 | MeerCounters->OUICount++;
123 |
124 | }
125 |
126 | Meer_Log(NORMAL, "Loaded %d entries from OUI database [%s].", MeerCounters->OUICount, MeerConfig->oui_filename);
127 |
128 | }
129 |
130 |
131 | /**************************************************************/
132 | /* OUI_Lookup - looks up a MAC address and returns the vender */
133 | /**************************************************************/
134 |
135 | void OUI_Lookup ( char *mac, char *str, size_t size )
136 | {
137 |
138 | char *s1 = NULL;
139 | char *s2 = NULL;
140 | char *s3 = NULL;
141 | char *saveptr = NULL;
142 |
143 | int i = 0;
144 |
145 | char new_mac[32] = { 0 };
146 | char search_string[9] = { 0 };
147 |
148 | /* Convert the MAC to upper case */
149 |
150 | strlcpy(new_mac, mac, sizeof(new_mac));
151 | To_UpperC(new_mac);
152 |
153 | /* Break up the MAC ( 00:00:00 ) */
154 |
155 | s1 = strtok_r(new_mac, ":", &saveptr);
156 | s2 = strtok_r(NULL, ":", &saveptr);
157 | s3 = strtok_r(NULL, ":", &saveptr);
158 |
159 | /* Our new search string */
160 |
161 | snprintf(search_string, sizeof(search_string), "%s:%s:%s", s1, s2, s3);
162 | search_string[ sizeof(search_string) - 1 ] = '\0';
163 |
164 | /* See if we can find the MAC address */
165 |
166 | for ( i = 0; i < MeerCounters->OUICount; i++ )
167 | {
168 |
169 | if ( !strncmp(search_string, MF_Struct[i].mac, 8) )
170 | {
171 |
172 | /* By default, return the long_manfact information. If that
173 | isn't present, then return the short_manfact data */
174 |
175 | if ( MF_Struct[i].long_manfact[0] != '0' )
176 | {
177 | snprintf(str, size, "%s", MF_Struct[i].long_manfact);
178 | str[ size - 1 ] = '\0';
179 | return;
180 | }
181 | else
182 | {
183 | snprintf(str, size, "%s", MF_Struct[i].short_manfact);
184 | str[ size - 1 ] = '\0';
185 | return;
186 | }
187 |
188 | }
189 |
190 | }
191 |
192 | /* Unknown / not found */
193 |
194 | str[0] = '\0';
195 |
196 | }
197 |
198 |
--------------------------------------------------------------------------------
/src/oui.h:
--------------------------------------------------------------------------------
1 | /*
2 | ** Copyright (C) 2018-2023 Quadrant Information Security
3 | ** Copyright (C) 2018-2023 Champ Clark III
4 | **
5 | ** This program is free software; you can redistribute it and/or modify
6 | ** it under the terms of the GNU General Public License Version 2 as
7 | ** published by the Free Software Foundation. You may not use, modify or
8 | ** distribute this program under any other version of the GNU General
9 | ** Public License.
10 | **
11 | ** This program is distributed in the hope that it will be useful,
12 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | ** GNU General Public License for more details.
15 | **
16 | ** You should have received a copy of the GNU General Public License
17 | ** along with this program; if not, write to the Free Software
18 | ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 | */
20 |
21 | typedef struct _Manfact_Struct _Manfact_Struct;
22 | struct _Manfact_Struct
23 | {
24 | char mac[22];
25 | char short_manfact[9];
26 | char long_manfact[128];
27 | };
28 |
29 |
30 | void Load_OUI( void );
31 | void OUI_Lookup ( char *mac, char *str, size_t size );
32 |
33 |
34 |
--------------------------------------------------------------------------------
/src/output-plugins/bluedot.c:
--------------------------------------------------------------------------------
1 | /*
2 | ** Copyright (C) 2018-2023 Quadrant Information Security
3 | ** Copyright (C) 2018-2023 Champ Clark III
4 | **
5 | ** This program is free software; you can redistribute it and/or modify
6 | ** it under the terms of the GNU General Public License Version 2 as
7 | ** published by the Free Software Foundation. You may not use, modify or
8 | ** distribute this program under any other version of the GNU General
9 | ** Public License.
10 | **
11 | ** This program is distributed in the hope that it will be useful,
12 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | ** GNU General Public License for more details.
15 | **
16 | ** You should have received a copy of the GNU General Public License
17 | ** along with this program; if not, write to the Free Software
18 | ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 | */
20 |
21 | /*
22 | * bluedot:
23 | * enabled: yes
24 | * debug: yes
25 | * url: "https://bluedot.quadrantsec.com/insert.php?apikey=KEYHERE"
26 | * insecure: true # Only applied when https is used.
27 | * source: "Field Sensors"
28 | * skip_networks: "10.0.0.0/8,192.168.0.0/16,172.16.0.0/12,12.159.2.0/24,199.188.171.0/27"
29 | *
30 | *
31 | */
32 |
33 | #ifdef HAVE_CONFIG_H
34 | #include "config.h" /* From autoconf */
35 | #endif
36 |
37 | #ifdef WITH_BLUEDOT
38 |
39 | #include
40 | #include
41 | #include
42 | #include
43 | #include
44 | #include
45 |
46 | #include
47 | #include
48 |
49 | #include "meer.h"
50 | #include "meer-def.h"
51 | #include "util.h"
52 | #include "bluedot.h"
53 |
54 | extern struct _MeerOutput *MeerOutput;
55 | extern struct _MeerCounters *MeerCounters;
56 | extern struct _Bluedot_Skip *Bluedot_Skip;
57 |
58 |
59 | CURL *curl_bluedot;
60 | struct curl_slist *headers = NULL;
61 |
62 | void Bluedot_Init( void )
63 | {
64 |
65 | curl_global_init(CURL_GLOBAL_ALL);
66 | curl_bluedot = curl_easy_init();
67 |
68 | if ( MeerOutput->bluedot_insecure == true )
69 | {
70 |
71 | curl_easy_setopt(curl_bluedot, CURLOPT_SSL_VERIFYPEER, false);
72 | curl_easy_setopt(curl_bluedot, CURLOPT_SSL_VERIFYHOST, false);
73 | curl_easy_setopt(curl_bluedot, CURLOPT_SSL_VERIFYSTATUS, false);
74 |
75 | }
76 |
77 | if ( MeerOutput->bluedot_debug == true )
78 | {
79 | curl_easy_setopt(curl_bluedot, CURLOPT_VERBOSE, 1);
80 | curl_easy_setopt(curl_bluedot, CURLOPT_NOBODY, 0); /* Show output for debigging */
81 | }
82 | else
83 | {
84 | curl_easy_setopt(curl_bluedot, CURLOPT_NOBODY, 1); /* Throw away output */
85 | }
86 |
87 |
88 | curl_easy_setopt(curl_bluedot, CURLOPT_NOSIGNAL, 1); /* Will send SIGALRM if not set */
89 |
90 | headers = curl_slist_append (headers, MEER_USER_AGENT);
91 | curl_easy_setopt(curl_bluedot, CURLOPT_HTTPHEADER, headers);
92 |
93 | }
94 |
95 | void Bluedot ( const char *metadata, struct json_object *json_obj )
96 | {
97 |
98 | char ip[MAXIP] = { 0 };
99 | char buff[8192] = { 0 };
100 | unsigned char ip_convert[MAXIPBIT] = { 0 };
101 |
102 | const char *bluedot = NULL;
103 | const char *alert = NULL;
104 | const char *signature = NULL;
105 |
106 | struct json_object *json_obj_metadata = NULL;
107 | struct json_object *json_obj_alert = NULL;
108 |
109 | struct json_object *tmp = NULL;
110 |
111 | uint32_t i = 0;
112 |
113 | CURLcode res;
114 |
115 | char *source_encoded = NULL;
116 | char *comments_encoded = NULL;
117 |
118 | json_obj_metadata = json_tokener_parse(metadata);
119 |
120 | if (json_object_object_get_ex(json_obj_metadata, "bluedot", &tmp))
121 | {
122 | bluedot = (char *)json_object_get_string(tmp);
123 |
124 | if ( bluedot == NULL )
125 | {
126 | json_object_put(json_obj_metadata);
127 | return;
128 | }
129 |
130 | if ( strstr( bluedot, "by_source" ) )
131 | {
132 | json_object_object_get_ex(json_obj, "src_ip", &tmp);
133 | strlcpy(ip, json_object_get_string(tmp), MAXIP);
134 | }
135 |
136 | else if ( strstr ( bluedot, "by_destination" ) )
137 | {
138 | json_object_object_get_ex(json_obj, "dest_ip", &tmp);
139 | strlcpy(ip, json_object_get_string(tmp), MAXIP);
140 | }
141 |
142 | }
143 |
144 | /* This should never, ever happen */
145 |
146 | if ( ip[0] == '\0' )
147 | {
148 | Meer_Log(WARN, "No 'by_source' or 'by_destination' not found in signature!");
149 | json_object_put(json_obj_metadata);
150 | return;
151 | }
152 |
153 | json_object_object_get_ex(json_obj, "alert", &tmp);
154 | alert = json_object_get_string(tmp);
155 |
156 | if ( alert == NULL )
157 | {
158 | Meer_Log(WARN, "No 'alert' data found!");
159 | json_object_put(json_obj_metadata);
160 | return;
161 | }
162 |
163 | json_obj_alert = json_tokener_parse(alert);
164 |
165 | json_object_object_get_ex(json_obj_alert, "signature", &tmp);
166 | signature = json_object_get_string(tmp);
167 |
168 | if ( signature == NULL )
169 | {
170 | Meer_Log(WARN, "No 'signature' data found!");
171 | json_object_put(json_obj_metadata);
172 | json_object_put(json_obj_alert);
173 | return;
174 | }
175 |
176 | IP2Bit( ip, ip_convert );
177 |
178 | /* Is the IP within the "skip_networks"? Is so, skip it! */
179 |
180 | for ( i = 0; i < MeerCounters->bluedot_skip_count; i++ )
181 | {
182 |
183 | if ( Is_Inrange(ip_convert, (unsigned char *)&Bluedot_Skip[i].range, 1) )
184 | {
185 |
186 | if ( MeerOutput->bluedot_debug == true )
187 | {
188 | Meer_Log(DEBUG, "IP address %s is in the 'skip_network' range. Skipping!", ip);
189 | }
190 |
191 | json_object_put(json_obj_metadata);
192 | return;
193 | }
194 |
195 | }
196 |
197 | /* We need to encode some data */
198 |
199 | comments_encoded = curl_easy_escape(curl_bluedot, signature, strlen(signature));
200 | source_encoded = curl_easy_escape(curl_bluedot, MeerOutput->bluedot_source, strlen(MeerOutput->bluedot_source));
201 |
202 | snprintf(buff, sizeof(buff), "%s&ip=%s&code=4&comments=%s&source=%s", MeerOutput->bluedot_url,ip, comments_encoded, source_encoded);
203 |
204 | buff[ sizeof(buff) - 1 ] = '\0';
205 |
206 | curl_easy_setopt(curl_bluedot, CURLOPT_URL, buff);
207 | res = curl_easy_perform(curl_bluedot);
208 |
209 | if(res != CURLE_OK)
210 | {
211 | Meer_Log(WARN, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
212 | }
213 |
214 | json_object_put(json_obj_metadata);
215 | json_object_put(json_obj_alert);
216 |
217 | }
218 |
219 | #endif
220 |
--------------------------------------------------------------------------------
/src/output-plugins/bluedot.h:
--------------------------------------------------------------------------------
1 | /*
2 | ** Copyright (C) 2018-2023 Quadrant Information Security
3 | ** Copyright (C) 2018-2023 Champ Clark III
4 | **
5 | ** This program is free software; you can redistribute it and/or modify
6 | ** it under the terms of the GNU General Public License Version 2 as
7 | ** published by the Free Software Foundation. You may not use, modify or
8 | ** distribute this program under any other version of the GNU General
9 | ** Public License.
10 | **
11 | ** This program is distributed in the hope that it will be useful,
12 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | ** GNU General Public License for more details. **
15 | ** You should have received a copy of the GNU General Public License
16 | ** along with this program; if not, write to the Free Software
17 | ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 | */
19 |
20 | void Bluedot_Init( void );
21 | void Bluedot ( const char *metadata, struct json_object *json_obj );
22 |
23 | typedef struct _Bluedot_Skip _Bluedot_Skip;
24 | struct _Bluedot_Skip
25 | {
26 |
27 | struct
28 | {
29 | unsigned char ipbits[MAXIPBIT];
30 | unsigned char maskbits[MAXIPBIT];
31 | } range;
32 |
33 | };
34 |
35 |
--------------------------------------------------------------------------------
/src/output-plugins/elasticsearch.h:
--------------------------------------------------------------------------------
1 | /*
2 | ** Copyright (C) 2018-2023 Quadrant Information Security
3 | ** Copyright (C) 2018-2023 Champ Clark III
4 | **
5 | ** This program is free software; you can redistribute it and/or modify
6 | ** it under the terms of the GNU General Public License Version 2 as
7 | ** published by the Free Software Foundation. You may not use, modify or
8 | ** distribute this program under any other version of the GNU General
9 | ** Public License.
10 | **
11 | ** This program is distributed in the hope that it will be useful,
12 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | ** GNU General Public License for more details.
15 | **
16 | ** You should have received a copy of the GNU General Public License
17 | ** along with this program; if not, write to the Free Software
18 | ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 | */
20 |
21 |
22 | #define MEER_AUTO_AUTH 0
23 | #define MEER_BASIC_AUTH 1
24 | #define MEER_DIGEST_AUTH 2
25 | #define MEER_NTLM_AUTH 3
26 | #define MEER_NEGOTIATE_AUTH 4
27 |
28 | struct MemoryStruct
29 | {
30 | char *memory;
31 | size_t size;
32 | };
33 |
34 | void Elasticsearch_Init( void );
35 | void Elasticsearch_Get_Index ( char *str, size_t size, const char *event_type );
36 | void Elasticsearch( void );
37 |
--------------------------------------------------------------------------------
/src/output-plugins/external.c:
--------------------------------------------------------------------------------
1 | /*
2 | ** Copyright (C) 2018-2023 Quadrant Information Security
3 | ** Copyright (C) 2018-2023 Champ Clark III
4 | **
5 | ** This program is free software; you can redistribute it and/or modify
6 | ** it under the terms of the GNU General Public License Version 2 as
7 | ** published by the Free Software Foundation. You may not use, modify or
8 | ** distribute this program under any other version of the GNU General
9 | ** Public License.
10 | **
11 | ** This program is distributed in the hope that it will be useful,
12 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | ** GNU General Public License for more details.
15 | **
16 | ** You should have received a copy of the GNU General Public License
17 | ** along with this program; if not, write to the Free Software
18 | ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 | */
20 |
21 | /*
22 | * This calls an external program
23 | */
24 |
25 | #ifdef HAVE_CONFIG_H
26 | #include "config.h" /* From autoconf */
27 | #endif
28 |
29 | #include
30 | #include
31 | #include
32 | #include
33 | #include
34 | #include
35 | #include
36 |
37 | #include "meer.h"
38 | #include "meer-def.h"
39 | #include "util.h"
40 |
41 | extern struct _MeerOutput *MeerOutput;
42 | extern struct _MeerCounters *MeerCounters;
43 | extern struct _MeerConfig *MeerConfig;
44 |
45 | bool External( const char *json_string )
46 | {
47 |
48 | int in[2];
49 | int out[2];
50 | int pid;
51 | int n;
52 |
53 | char *buf = malloc((MeerConfig->payload_buffer_size)*sizeof(char));
54 |
55 | if ( buf == NULL )
56 | {
57 | fprintf(stderr, "[%s, line %d] Fatal Error: Can't allocate memory! Abort!\n", __FILE__, __LINE__);
58 | exit(-1);
59 | }
60 |
61 |
62 | if( File_Check( MeerOutput->external_program ) != 1 )
63 | {
64 |
65 | Meer_Log(WARN, "Warning! The external program '%s' does not exsist!", MeerOutput->external_program);
66 | MeerCounters->ExternalMissCount++;
67 | free(buf);
68 | return(1);
69 |
70 | }
71 |
72 | if ( pipe(in) < 0 )
73 | {
74 | Meer_Log(WARN, "[%s, line %d] Cannot create input pipe!", __FILE__, __LINE__);
75 | MeerCounters->ExternalMissCount++;
76 | free(buf);
77 | return(1);
78 | }
79 |
80 |
81 | if ( pipe(out) < 0 )
82 | {
83 | Meer_Log(WARN, "[%s, line %d] Cannot create output pipe!", __FILE__, __LINE__);
84 | MeerCounters->ExternalMissCount++;
85 | free(buf);
86 | return(1);
87 | }
88 |
89 | pid=fork();
90 | if ( pid < 0 )
91 | {
92 | Meer_Log(WARN, "[%s, line %d] Cannot create external program process", __FILE__, __LINE__);
93 | MeerCounters->ExternalMissCount++;
94 | free(buf);
95 | return(1);
96 | }
97 | else if ( pid == 0 )
98 | {
99 | /* Causes problems with alert.log */
100 |
101 |
102 | close(0);
103 | close(1);
104 | close(2);
105 |
106 | dup2(in[0],0);
107 | dup2(out[1],1);
108 | dup2(out[1],2);
109 |
110 | close(in[1]);
111 | close(out[0]);
112 |
113 | execl(MeerOutput->external_program, MeerOutput->external_program, NULL, (char *)NULL);
114 |
115 | Meer_Log(WARN, "[%s, line %d] Cannot execute %s", __FILE__, __LINE__, MeerOutput->external_program);
116 | MeerCounters->ExternalMissCount++;
117 | }
118 |
119 | close(in[0]);
120 | close(out[1]);
121 |
122 | /* Write to child input */
123 |
124 | n = write(in[1], json_string, strlen(json_string));
125 | n = write(in[1], "\n", 1); /* Take on \n */
126 | close(in[1]);
127 |
128 | n = read(out[0], buf, sizeof(buf));
129 | close(out[0]);
130 | buf[n] = 0;
131 |
132 | waitpid(pid, NULL, 0);
133 |
134 | if ( MeerOutput->external_debug )
135 | {
136 | Meer_Log(DEBUG, "DEBUG: Executed '%s'", MeerOutput->external_program);
137 | }
138 |
139 | MeerCounters->ExternalHitCount++;
140 |
141 | free(buf);
142 | return(0);
143 |
144 | }
145 |
--------------------------------------------------------------------------------
/src/output-plugins/external.h:
--------------------------------------------------------------------------------
1 | /*
2 | ** Copyright (C) 2018-2023 Quadrant Information Security
3 | ** Copyright (C) 2018-2023 Champ Clark III
4 | **
5 | ** This program is free software; you can redistribute it and/or modify
6 | ** it under the terms of the GNU General Public License Version 2 as
7 | ** published by the Free Software Foundation. You may not use, modify or
8 | ** distribute this program under any other version of the GNU General
9 | ** Public License.
10 | **
11 | ** This program is distributed in the hope that it will be useful,
12 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | ** GNU General Public License for more details.
15 | **
16 | ** You should have received a copy of the GNU General Public License
17 | ** along with this program; if not, write to the Free Software
18 | ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 | */
20 |
21 | bool External( const char *json_string );
22 |
--------------------------------------------------------------------------------
/src/output-plugins/file.c:
--------------------------------------------------------------------------------
1 | /*
2 | ** Copyright (C) 2018-2023 Quadrant Information Security
3 | ** Copyright (C) 2018-2023 Champ Clark III
4 | **
5 | ** This program is free software; you can redistribute it and/or modify
6 | ** it under the terms of the GNU General Public License Version 2 as
7 | ** published by the Free Software Foundation. You may not use, modify or
8 | ** distribute this program under any other version of the GNU General
9 | ** Public License.
10 | **
11 | ** This program is distributed in the hope that it will be useful,
12 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | ** GNU General Public License for more details.
15 | **
16 | ** You should have received a copy of the GNU General Public License
17 | ** along with this program; if not, write to the Free Software
18 | ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 | */
20 |
21 | #ifdef HAVE_CONFIG_H
22 | #include "config.h" /* From autoconf */
23 | #endif
24 |
25 | #include
26 | #include
27 | #include
28 | #include
29 |
30 | #include "output-plugins/file.h"
31 |
32 | #include "meer.h"
33 | #include "meer-def.h"
34 | #include "util.h"
35 |
36 | extern struct _MeerOutput *MeerOutput;
37 |
38 | bool Output_Do_File ( const char *json_string )
39 | {
40 | fprintf(MeerOutput->file_fd, "%s\n", json_string);
41 | fflush(MeerOutput->file_fd);
42 | return(true);
43 | }
44 |
45 |
46 |
--------------------------------------------------------------------------------
/src/output-plugins/file.h:
--------------------------------------------------------------------------------
1 | /*
2 | ** Copyright (C) 2018-2023 Quadrant Information Security
3 | ** Copyright (C) 2018-2023 Champ Clark III
4 | **
5 | ** This program is free software; you can redistribute it and/or modify
6 | ** it under the terms of the GNU General Public License Version 2 as
7 | ** published by the Free Software Foundation. You may not use, modify or
8 | ** distribute this program under any other version of the GNU General
9 | ** Public License.
10 | **
11 | ** This program is distributed in the hope that it will be useful,
12 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | ** GNU General Public License for more details.
15 | **
16 | ** You should have received a copy of the GNU General Public License
17 | ** along with this program; if not, write to the Free Software
18 | ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 | */
20 |
21 |
22 | bool Output_Do_File ( const char *json_string );
23 |
--------------------------------------------------------------------------------
/src/output-plugins/pipe.c:
--------------------------------------------------------------------------------
1 | /*
2 | ** Copyright (C) 2018-2023 Quadrant Information Security
3 | ** Copyright (C) 2018-2023 Champ Clark III
4 | **
5 | ** This program is free software; you can redistribute it and/or modify
6 | ** it under the terms of the GNU General Public License Version 2 as
7 | ** published by the Free Software Foundation. You may not use, modify or
8 | ** distribute this program under any other version of the GNU General
9 | ** Public License.
10 | **
11 | ** This program is distributed in the hope that it will be useful,
12 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | ** GNU General Public License for more details.
15 | **
16 | ** You should have received a copy of the GNU General Public License
17 | ** along with this program; if not, write to the Free Software
18 | ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 | */
20 |
21 | /****************************************************************************
22 | * This takes input data (JSON) and writes it out to a named pipe/FIFO
23 | ****************************************************************************/
24 |
25 | #ifdef HAVE_CONFIG_H
26 | #include "config.h" /* From autoconf */
27 | #endif
28 |
29 | #include
30 | #include
31 | #include
32 | #include
33 |
34 | #include "meer.h"
35 | #include "meer-def.h"
36 | #include "pipe.h"
37 |
38 | extern struct _MeerOutput *MeerOutput;
39 | extern struct _MeerCounters *MeerCounters;
40 |
41 | void Pipe_Write ( const char *json_string )
42 | {
43 | uint32_t ret = 0;
44 |
45 | ret = write(MeerOutput->pipe_fd, json_string, strlen(json_string));
46 |
47 | if ( ret < 0 )
48 | {
49 | Meer_Log(WARN, "Could not write pipe. Error: %s", strerror(errno));
50 | return;
51 | }
52 |
53 | /* Tack on newline */
54 |
55 | ret = write(MeerOutput->pipe_fd, "\n", 1);
56 |
57 | if ( ret < 0 )
58 | {
59 | Meer_Log(WARN, "Could not write pipe. Error: %s", strerror(errno));
60 | return;
61 | }
62 |
63 |
64 | MeerCounters->JSONPipeWrites++;
65 |
66 | }
67 |
--------------------------------------------------------------------------------
/src/output-plugins/pipe.h:
--------------------------------------------------------------------------------
1 | /*
2 | ** Copyright (C) 2018-2023 Quadrant Information Security
3 | ** Copyright (C) 2018-2023 Champ Clark III
4 | **
5 | ** This program is free software; you can redistribute it and/or modify
6 | ** it under the terms of the GNU General Public License Version 2 as
7 | ** published by the Free Software Foundation. You may not use, modify or
8 | ** distribute this program under any other version of the GNU General
9 | ** Public License.
10 | **
11 | ** This program is distributed in the hope that it will be useful,
12 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | ** GNU General Public License for more details.
15 | **
16 | ** You should have received a copy of the GNU General Public License
17 | ** along with this program; if not, write to the Free Software
18 | ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 | */
20 |
21 | void Pipe_Write( const char *json_string );
22 |
23 |
--------------------------------------------------------------------------------
/src/output-plugins/redis.h:
--------------------------------------------------------------------------------
1 | /*
2 | ** Copyright (C) 2018-2023 Quadrant Information Security ** Copyright (C) 2018-2023 Champ Clark III
3 | **
4 | ** This program is free software; you can redistribute it and/or modify
5 | ** it under the terms of the GNU General Public License Version 2 as
6 | ** published by the Free Software Foundation. You may not use, modify or
7 | ** distribute this program under any other version of the GNU General
8 | ** Public License.
9 | **
10 | ** This program is distributed in the hope that it will be useful,
11 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | ** GNU General Public License for more details.
14 | **
15 | ** You should have received a copy of the GNU General Public License
16 | ** along with this program; if not, write to the Free Software
17 | ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 | */
19 |
20 | #define REDIS_PUBSUB 1
21 |
22 | void Redis_Init ( void );
23 | void Redis_Close ( void );
24 | void Redis_Connect( void );
25 | void Redis_Reader ( char *redis_command, char *str, size_t size );
26 | bool Redis_Writer ( const char *command, const char *key, const char *value, int expire );
27 | void JSON_To_Redis ( const char *json_string, const char *key );
28 |
29 |
--------------------------------------------------------------------------------
/src/output-plugins/syslog.c:
--------------------------------------------------------------------------------
1 | /*
2 | ** Copyright (C) 2018-2023 Quadrant Information Security
3 | ** Copyright (C) 2018-2023 Champ Clark III
4 | **
5 | ** This program is free software; you can redistribute it and/or modify
6 | ** it under the terms of the GNU General Public License Version 2 as
7 | ** published by the Free Software Foundation. You may not use, modify or
8 | ** distribute this program under any other version of the GNU General
9 | ** Public License.
10 | **
11 | ** This program is distributed in the hope that it will be useful,
12 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | ** GNU General Public License for more details.
15 | **
16 | ** You should have received a copy of the GNU General Public License
17 | ** along with this program; if not, write to the Free Software
18 | ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 | */
20 |
21 | #ifdef HAVE_CONFIG_H
22 | #include "config.h" /* From autoconf */
23 | #endif
24 |
25 | #ifdef WITH_SYSLOG
26 |
27 | #include
28 | #include
29 | #include
30 | #include
31 | #include
32 |
33 | #include "output-plugins/syslog.h"
34 |
35 | #include "meer.h"
36 | #include "meer-def.h"
37 | #include "util.h"
38 |
39 | extern struct _MeerOutput *MeerOutput;
40 |
41 | bool Output_Do_Syslog ( const char *json_string, const char *event_type )
42 | {
43 |
44 | openlog(event_type, MeerOutput->syslog_options, MeerOutput->syslog_facility);
45 | syslog(MeerOutput->syslog_priority, "%s", json_string);
46 | closelog();
47 |
48 | }
49 |
50 |
51 | #endif
52 |
--------------------------------------------------------------------------------
/src/output-plugins/syslog.h:
--------------------------------------------------------------------------------
1 | /*
2 | ** Copyright (C) 2018-2023 Quadrant Information Security
3 | ** Copyright (C) 2018-2023 Champ Clark III
4 | **
5 | ** This program is free software; you can redistribute it and/or modify
6 | ** it under the terms of the GNU General Public License Version 2 as
7 | ** published by the Free Software Foundation. You may not use, modify or
8 | ** distribute this program under any other version of the GNU General
9 | ** Public License.
10 | **
11 | ** This program is distributed in the hope that it will be useful,
12 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | ** GNU General Public License for more details.
15 | **
16 | ** You should have received a copy of the GNU General Public License
17 | ** along with this program; if not, write to the Free Software
18 | ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 | */
20 |
21 |
22 | bool Output_Do_Syslog ( const char *json_string, const char *event_type );
23 |
--------------------------------------------------------------------------------
/src/output.h:
--------------------------------------------------------------------------------
1 | /*
2 | ** Copyright (C) 2018-2023 Quadrant Information Security
3 | ** Copyright (C) 2018-2023 Champ Clark III
4 | **
5 | ** This program is free software; you can redistribute it and/or modify
6 | ** it under the terms of the GNU General Public License Version 2 as
7 | ** published by the Free Software Foundation. You may not use, modify or
8 | ** distribute this program under any other version of the GNU General
9 | ** Public License.
10 | **
11 | ** This program is distributed in the hope that it will be useful,
12 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | ** GNU General Public License for more details.
15 | **
16 | ** You should have received a copy of the GNU General Public License
17 | ** along with this program; if not, write to the Free Software
18 | ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 | */
20 |
21 | #include
22 |
23 | void Init_Output( void );
24 | bool Output_Pipe ( const char *json_string, const char *event_type );
25 | bool Output_External ( const char *json_string, struct json_object *json_obj, const char *event_type );
26 | void Output_Bluedot ( struct json_object *json_obj );
27 | bool Output_Elasticsearch ( const char *json_string, const char *event_type, const char *id );
28 | bool Output_Do_Elasticsearch ( const char *json_string, const char *event_type, const char *id );
29 | bool Output_File ( const char *json_string, const char *event_type );
30 | bool Output_Redis( const char *json_string, const char *event_type );
31 | bool Output_Syslog ( const char *json_string, const char *event_type );
32 |
33 |
--------------------------------------------------------------------------------
/src/stats.c:
--------------------------------------------------------------------------------
1 | /*
2 | ** Copyright (C) 2018-2023 Quadrant Information Security
3 | ** Copyright (C) 2018-2023 Champ Clark III
4 | **
5 | ** This program is free software; you can redistribute it and/or modify
6 | ** it under the terms of the GNU General Public License Version 2 as
7 | ** published by the Free Software Foundation. You may not use, modify or
8 | ** distribute this program under any other version of the GNU General
9 | ** Public License.
10 | **
11 | ** This program is distributed in the hope that it will be useful,
12 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | ** GNU General Public License for more details.
15 | **
16 | ** You should have received a copy of the GNU General Public License
17 | ** along with this program; if not, write to the Free Software
18 | ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 | */
20 |
21 | /* Display statistics */
22 |
23 | #ifdef HAVE_CONFIG_H
24 | #include "config.h" /* From autoconf */
25 | #endif
26 |
27 | #include
28 |
29 | #include "meer.h"
30 | #include "meer-def.h"
31 | #include "stats.h"
32 | #include "util.h"
33 | #include "config-yaml.h"
34 |
35 |
36 | extern struct _MeerCounters *MeerCounters;
37 | extern struct _MeerWaldo *MeerWaldo;
38 | extern struct _MeerConfig *MeerConfig;
39 | extern struct _MeerOutput *MeerOutput;
40 | extern struct _MeerInput *MeerInput;
41 |
42 |
43 | void Statistics( void )
44 | {
45 |
46 | /* Idea: Add "JSON per/sec"? */
47 |
48 | Meer_Log(NORMAL, "");
49 | Meer_Log(NORMAL, "--[ Meer Statistics ]---------------------------------------");
50 | Meer_Log(NORMAL, "");
51 | Meer_Log(NORMAL, " - Decoded Statistics:");
52 | Meer_Log(NORMAL, "");
53 | Meer_Log(NORMAL, " Total : %" PRIu64 "", MeerCounters->total);
54 | Meer_Log(NORMAL, " Bad : %" PRIu64 " (%.3f%%)", MeerCounters->bad, CalcPct( MeerCounters->bad, MeerCounters->total ) );
55 | Meer_Log(NORMAL, "");
56 | Meer_Log(NORMAL, " alert : %" PRIu64 " (%.3f%%)", MeerCounters->alert, CalcPct( MeerCounters->alert, MeerCounters->total ) );
57 | Meer_Log(NORMAL, " files : %" PRIu64 " (%.3f%%)", MeerCounters->files, CalcPct( MeerCounters->files, MeerCounters->total ) );
58 | Meer_Log(NORMAL, " flow : %" PRIu64 " (%.3f%%)", MeerCounters->flow, CalcPct( MeerCounters->flow, MeerCounters->total ) );
59 | Meer_Log(NORMAL, " dns : %" PRIu64 " (%.3f%%)", MeerCounters->dns, CalcPct( MeerCounters->dns, MeerCounters->total ) );
60 | Meer_Log(NORMAL, " http : %" PRIu64 " (%.3f%%)", MeerCounters->http, CalcPct( MeerCounters->http, MeerCounters->total ) );
61 | Meer_Log(NORMAL, " tls : %" PRIu64 " (%.3f%%)", MeerCounters->tls, CalcPct( MeerCounters->tls, MeerCounters->total ) );
62 | Meer_Log(NORMAL, " ssh : %" PRIu64 " (%.3f%%)", MeerCounters->ssh, CalcPct( MeerCounters->ssh, MeerCounters->total ) );
63 | Meer_Log(NORMAL, " smtp : %" PRIu64 " (%.3f%%)", MeerCounters->smtp, CalcPct( MeerCounters->smtp, MeerCounters->total ) );
64 | Meer_Log(NORMAL, " email : %" PRIu64 " (%.3f%%)", MeerCounters->email, CalcPct( MeerCounters->email, MeerCounters->total ) );
65 | Meer_Log(NORMAL, " fileinfo : %" PRIu64 " (%.3f%%)", MeerCounters->fileinfo, CalcPct( MeerCounters->fileinfo, MeerCounters->total ) );
66 | Meer_Log(NORMAL, " dhcp : %" PRIu64 " (%.3f%%)", MeerCounters->dhcp, CalcPct( MeerCounters->dhcp, MeerCounters->total ) );
67 | Meer_Log(NORMAL, " stats : %" PRIu64 " (%.3f%%)", MeerCounters->stats, CalcPct( MeerCounters->stats, MeerCounters->total ) );
68 | Meer_Log(NORMAL, " rdp : %" PRIu64 " (%.3f%%)", MeerCounters->rdp, CalcPct( MeerCounters->rdp, MeerCounters->total ) );
69 | Meer_Log(NORMAL, " sip : %" PRIu64 " (%.3f%%)", MeerCounters->sip, CalcPct( MeerCounters->sip, MeerCounters->total ) );
70 | Meer_Log(NORMAL, " ftp : %" PRIu64 " (%.3f%%)", MeerCounters->ftp, CalcPct( MeerCounters->ftp, MeerCounters->total ) );
71 | Meer_Log(NORMAL, " ikev2 : %" PRIu64 " (%.3f%%)", MeerCounters->ikev2, CalcPct( MeerCounters->ikev2, MeerCounters->total ) );
72 | Meer_Log(NORMAL, " nfs : %" PRIu64 " (%.3f%%)", MeerCounters->nfs, CalcPct( MeerCounters->nfs, MeerCounters->total ) );
73 | Meer_Log(NORMAL, " tftp : %" PRIu64 " (%.3f%%)", MeerCounters->tftp, CalcPct( MeerCounters->tftp, MeerCounters->total ) );
74 | Meer_Log(NORMAL, " smb : %" PRIu64 " (%.3f%%)", MeerCounters->smb, CalcPct( MeerCounters->smb, MeerCounters->total ) );
75 | Meer_Log(NORMAL, " dcerpc : %" PRIu64 " (%.3f%%)", MeerCounters->dcerpc, CalcPct( MeerCounters->dcerpc, MeerCounters->total ) );
76 | Meer_Log(NORMAL, " mqtt : %" PRIu64 " (%.3f%%)", MeerCounters->mqtt, CalcPct( MeerCounters->mqtt, MeerCounters->total ) );
77 | Meer_Log(NORMAL, " netflow : %" PRIu64 " (%.3f%%)", MeerCounters->netflow, CalcPct( MeerCounters->netflow, MeerCounters->total ) );
78 | Meer_Log(NORMAL, " metadata : %" PRIu64 " (%.3f%%)", MeerCounters->metadata, CalcPct( MeerCounters->metadata, MeerCounters->total ) );
79 | Meer_Log(NORMAL, " dnp3 : %" PRIu64 " (%.3f%%)", MeerCounters->dnp3, CalcPct( MeerCounters->dnp3, MeerCounters->total ) );
80 | Meer_Log(NORMAL, " anomaly : %" PRIu64 " (%.3f%%)", MeerCounters->anomaly, CalcPct( MeerCounters->anomaly, MeerCounters->total ) );
81 | Meer_Log(NORMAL, " client_stats : %" PRIu64 " (%.3f%%)", MeerCounters->client_stats, CalcPct( MeerCounters->client_stats, MeerCounters->total ) );
82 | Meer_Log(NORMAL, " ndp : %" PRIu64 " (%.3f%%)", MeerCounters->ndp, CalcPct( MeerCounters->ndp, MeerCounters->total ) );
83 | Meer_Log(NORMAL, " ndp skipped : %" PRIu64 " (%.3f%%)", MeerCounters->ndp_skip, CalcPct( MeerCounters->ndp_skip, MeerCounters->total ) );
84 |
85 |
86 | Meer_Log(NORMAL, "");
87 |
88 | if ( MeerInput->type == YAML_INPUT_FILE )
89 | {
90 | Meer_Log(NORMAL, " Waldo Postion : %" PRIu64 "", MeerWaldo->position);
91 | }
92 |
93 | // Meer_Log(NORMAL, " JSON : %" PRIu64 "", MeerCounters->JSONCount);
94 | // Meer_Log(NORMAL, " Invalid JSON : %" PRIu64 " (%.3f%%)", MeerCounters->bad, CalcPct(MeerCounters->JSONCount,MeerCounters->bad));
95 |
96 | #ifdef BLUEDOT
97 | Meer_Log(NORMAL, " Bluedot : %" PRIu64 "", MeerCounters->bluedot);
98 | #endif
99 |
100 |
101 | Meer_Log(NORMAL, "");
102 |
103 | if ( MeerConfig->dns == true )
104 | {
105 |
106 | Meer_Log(NORMAL, " - DNS Statistics:");
107 | Meer_Log(NORMAL, "");
108 | Meer_Log(NORMAL, " DNS Lookups : %"PRIu64 "", MeerCounters->DNSCount);
109 | Meer_Log(NORMAL, " DNS Cache Hits: %"PRIu64 " (%.3f%%)", MeerCounters->DNSCacheCount, CalcPct(MeerCounters->DNSCacheCount,MeerCounters->DNSCount));
110 | Meer_Log(NORMAL, "");
111 |
112 | }
113 |
114 | if ( MeerOutput->pipe_enabled == true )
115 | {
116 |
117 | Meer_Log(NORMAL, " - Pipe Statistics:");
118 | Meer_Log(NORMAL, "");
119 | Meer_Log(NORMAL, " JSON writes : %"PRIu64 "", MeerCounters->JSONPipeWrites);
120 | Meer_Log(NORMAL, " JSON misses/errors : %"PRIu64 " (%.3f%%)", MeerCounters->JSONPipeMisses, CalcPct(MeerCounters->JSONPipeWrites, MeerCounters->JSONPipeMisses));
121 |
122 | }
123 |
124 | if ( MeerOutput->external_enabled == true )
125 | {
126 |
127 | Meer_Log(NORMAL, " - External Statistics:");
128 | Meer_Log(NORMAL, "");
129 | Meer_Log(NORMAL, " Success : %"PRIu64 "", MeerCounters->ExternalHitCount);
130 | Meer_Log(NORMAL, " Failures : %"PRIu64 "", MeerCounters->ExternalMissCount);
131 |
132 | }
133 |
134 |
135 | Meer_Log(NORMAL, "");
136 |
137 | }
138 |
--------------------------------------------------------------------------------
/src/stats.h:
--------------------------------------------------------------------------------
1 | /*
2 | ** Copyright (C) 2018-2023 Quadrant Information Security
3 | ** Copyright (C) 2018-2023 Champ Clark III
4 | **
5 | ** This program is free software; you can redistribute it and/or modify
6 | ** it under the terms of the GNU General Public License Version 2 as
7 | ** published by the Free Software Foundation. You may not use, modify or
8 | ** distribute this program under any other version of the GNU General
9 | ** Public License.
10 | **
11 | ** This program is distributed in the hope that it will be useful,
12 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | ** GNU General Public License for more details.
15 | **
16 | ** You should have received a copy of the GNU General Public License
17 | ** along with this program; if not, write to the Free Software
18 | ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 | */
20 |
21 | void Statistics( void );
22 |
--------------------------------------------------------------------------------
/src/usage.c:
--------------------------------------------------------------------------------
1 | /*
2 | ** Copyright (C) 2018-2023 Quadrant Information Security
3 | ** Copyright (C) 2018-2023 Champ Clark III
4 | **
5 | ** This program is free software; you can redistribute it and/or modify
6 | ** it under the terms of the GNU General Public License Version 2 as
7 | ** published by the Free Software Foundation. You may not use, modify or
8 | ** distribute this program under any other version of the GNU General
9 | ** Public License.
10 | **
11 | ** This program is distributed in the hope that it will be useful,
12 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | ** GNU General Public License for more details.
15 | **
16 | ** You should have received a copy of the GNU General Public License
17 | ** along with this program; if not, write to the Free Software
18 | ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 | */
20 |
21 | #include
22 |
23 | #include "meer-def.h"
24 | #include "version.h"
25 |
26 | void Usage( void )
27 | {
28 |
29 | printf("\n");
30 | printf("@@@@@@@@@@ @@@@@@@@ @@@@@@@@ @@@@@@@ Meer version %s\n", VERSION);
31 | printf("@@! @@! @@! @@! @@! @@! @@@ Quadrant Information Security\n");
32 | printf("@!! !!@ @!@ @!!!:! @!!!:! @!@!!@a https://quadrantsec.com\n");
33 | printf("!!: !!: !!: !!: !!: :!a Copyright (C) 2018-2023\n");
34 | printf(": : : :: :: : :: :: : : :\n\n");
35 |
36 | printf("-D, --dameon\t\tPut Meer in the background.\n");
37 | printf("-c, --config\t\tMeer Configuration File [default: %s]\n", DEFAULT_CONFIG);
38 | printf("-h, --help\t\tMeer help screen.\n");
39 | printf("-q, --quiet\t\tTell Meer to be quiet.\n");
40 | printf("-f, --file\t\tGrab files, process them and store the results.\n");
41 | printf("\nMeer was compile on %s at %s.\n", __DATE__, __TIME__);
42 |
43 |
44 | }
45 |
--------------------------------------------------------------------------------
/src/usage.h:
--------------------------------------------------------------------------------
1 | /*
2 | ** Copyright (C) 2018-2023 Quadrant Information Security
3 | ** Copyright (C) 2018-2023 Champ Clark III
4 | **
5 | ** This program is free software; you can redistribute it and/or modify
6 | ** it under the terms of the GNU General Public License Version 2 as
7 | ** published by the Free Software Foundation. You may not use, modify or
8 | ** distribute this program under any other version of the GNU General
9 | ** Public License.
10 | **
11 | ** This program is distributed in the hope that it will be useful,
12 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | ** GNU General Public License for more details.
15 | **
16 | ** You should have received a copy of the GNU General Public License
17 | ** along with this program; if not, write to the Free Software
18 | ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 | */
20 |
21 | void Usage( void );
22 |
--------------------------------------------------------------------------------
/src/util-base64.c:
--------------------------------------------------------------------------------
1 | /*
2 | ** Copyright (C) 2018-2023 Quadrant Information Security
3 | ** Copyright (C) 2018-2023 Champ Clark III
4 | **
5 | ** This program is free software; you can redistribute it and/or modify
6 | ** it under the terms of the GNU General Public License Version 2 as
7 | ** published by the Free Software Foundation. You may not use, modify or
8 | ** distribute this program under any other version of the GNU General
9 | ** Public License.
10 | **
11 | ** This program is distributed in the hope that it will be useful,
12 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | ** GNU General Public License for more details.
15 | **
16 | ** You should have received a copy of the GNU General Public License
17 | ** along with this program; if not, write to the Free Software
18 | ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 | */
20 |
21 | #ifdef HAVE_CONFIG_H
22 | #include "config.h" /* From autoconf */
23 | #endif
24 |
25 | #include
26 | #include
27 | #include
28 | #include
29 |
30 | #include "util-base64.h"
31 |
32 | #define ASCII_BLOCK 3
33 | #define B64_BLOCK 4
34 | #define BASE64_TABLE_MAX 122
35 |
36 | static inline void DecodeBase64Block(uint8_t ascii[ASCII_BLOCK], uint8_t b64[B64_BLOCK]);
37 | static inline int GetBase64Value(uint8_t c);
38 |
39 |
40 | /* Base64 character to index conversion table */
41 | /* Characters are mapped as "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" */
42 |
43 | static const int b64table[] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
44 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
45 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
46 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
47 | -1, -1, -1, 62, -1, -1, -1, 63, 52, 53,
48 | 54, 55, 56, 57, 58, 59, 60, 61, -1, -1,
49 | -1, -1, -1, -1, -1, 0, 1, 2, 3, 4,
50 | 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
51 | 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
52 | 25, -1, -1, -1, -1, -1, -1, 26, 27, 28,
53 | 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
54 | 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
55 | 49, 50, 51
56 | };
57 |
58 |
59 | uint32_t DecodeBase64(uint8_t *dest, const uint8_t *src, uint32_t len,
60 | int strict)
61 | {
62 | int val;
63 | uint32_t padding = 0, numDecoded = 0, bbidx = 0, valid = 1, i;
64 | uint8_t *dptr = dest;
65 | uint8_t b64[B64_BLOCK] = { 0,0,0,0 };
66 |
67 | /* Traverse through each alpha-numeric letter in the source array */
68 | for(i = 0; i < len && src[i] != 0; i++)
69 | {
70 |
71 | /* Get decimal representation */
72 | val = GetBase64Value(src[i]);
73 | if (val < 0)
74 | {
75 |
76 | /* Invalid character found, so decoding fails */
77 | if (src[i] != '=')
78 | {
79 | valid = 0;
80 | if (strict)
81 | {
82 | numDecoded = 0;
83 | }
84 | break;
85 | }
86 | padding++;
87 | }
88 |
89 | /* For each alpha-numeric letter in the source array, find the numeric
90 | * value */
91 | b64[bbidx++] = (val > 0 ? val : 0);
92 |
93 | /* Decode every 4 base64 bytes into 3 ascii bytes */
94 | if (bbidx == B64_BLOCK)
95 | {
96 |
97 | /* For every 4 bytes, add 3 bytes but deduct the '=' padded blocks */
98 | numDecoded += ASCII_BLOCK - (padding < B64_BLOCK ?
99 | padding : ASCII_BLOCK);
100 |
101 | /* Decode base-64 block into ascii block and move pointer */
102 | DecodeBase64Block(dptr, b64);
103 | dptr += ASCII_BLOCK;
104 |
105 | /* Reset base-64 block and index */
106 | bbidx = 0;
107 | padding = 0;
108 | }
109 | }
110 |
111 | /* Finish remaining b64 bytes by padding */
112 | if (valid && bbidx > 0)
113 | {
114 |
115 | /* Decode remaining */
116 | numDecoded += ASCII_BLOCK - (B64_BLOCK - bbidx);
117 | DecodeBase64Block(dptr, b64);
118 | }
119 |
120 | // if (numDecoded == 0) {
121 | // SCLogDebug("base64 decoding failed");
122 | // }
123 |
124 | return numDecoded;
125 | }
126 |
127 |
128 | static inline int GetBase64Value(uint8_t c)
129 | {
130 | int val = -1;
131 |
132 | /* Pull from conversion table */
133 | if (c <= BASE64_TABLE_MAX)
134 | {
135 | val = b64table[(int) c];
136 | }
137 |
138 | return val;
139 | }
140 |
141 | static inline void DecodeBase64Block(uint8_t ascii[ASCII_BLOCK], uint8_t b64[B64_BLOCK])
142 | {
143 | ascii[0] = (uint8_t) (b64[0] << 2) | (b64[1] >> 4);
144 | ascii[1] = (uint8_t) (b64[1] << 4) | (b64[2] >> 2);
145 | ascii[2] = (uint8_t) (b64[2] << 6) | (b64[3]);
146 | }
147 |
148 |
--------------------------------------------------------------------------------
/src/util-base64.h:
--------------------------------------------------------------------------------
1 | /*
2 | ** Copyright (C) 2018-2023 Quadrant Information Security
3 | ** Copyright (C) 2018-2023 Champ Clark III
4 | **
5 | ** This program is free software; you can redistribute it and/or modify
6 | ** it under the terms of the GNU General Public License Version 2 as
7 | ** published by the Free Software Foundation. You may not use, modify or
8 | ** distribute this program under any other version of the GNU General
9 | ** Public License.
10 | **
11 | ** This program is distributed in the hope that it will be useful,
12 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | ** GNU General Public License for more details.
15 | **
16 | ** You should have received a copy of the GNU General Public License
17 | ** along with this program; if not, write to the Free Software
18 | ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 | */
20 |
21 | uint32_t DecodeBase64(uint8_t *dest, const uint8_t *src, uint32_t len, int strict);
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/src/util-dns.c:
--------------------------------------------------------------------------------
1 | /*
2 | ** Copyright (C) 2018-2023 Quadrant Information Security
3 | ** Copyright (C) 2018-2023 Champ Clark III
4 | **
5 | ** This program is free software; you can redistribute it and/or modify
6 | ** it under the terms of the GNU General Public License Version 2 as
7 | ** published by the Free Software Foundation. You may not use, modify or
8 | ** distribute this program under any other version of the GNU General
9 | ** Public License.
10 | **
11 | ** This program is distributed in the hope that it will be useful,
12 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | ** GNU General Public License for more details.
15 | **
16 | ** You should have received a copy of the GNU General Public License
17 | ** along with this program; if not, write to the Free Software
18 | ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 | */
20 |
21 | #ifdef HAVE_CONFIG_H
22 | #include "config.h" /* From autoconf */
23 | #endif
24 |
25 | #include
26 | #include
27 | #include
28 | #include
29 | #include
30 | #include
31 | #include
32 | #include
33 |
34 | #include "meer-def.h"
35 | #include "meer.h"
36 |
37 | #include "util-dns.h"
38 |
39 |
40 | extern struct _MeerConfig *MeerConfig;
41 | extern struct _MeerCounters *MeerCounters;
42 |
43 | struct _DnsCache *DnsCache;
44 | uint32_t DnsCacheCount = 0;
45 |
46 | void DNS_Lookup_Reverse( char *host, char *str, size_t size )
47 | {
48 |
49 | struct sockaddr_in ipaddr;
50 | time_t t;
51 | struct tm *run;
52 | char utime_string[20] = { 0 };
53 | int i = 0;
54 |
55 | t = time(NULL);
56 | run=localtime(&t);
57 | strftime(utime_string, sizeof(utime_string), "%s", run);
58 | uint64_t utime = atol(utime_string);
59 |
60 | char host_r[NI_MAXHOST] = { 0 };
61 |
62 | /* Don't return a DNS lookup for the "bad IP" value */
63 |
64 | if ( !strcmp( host, BAD_IP ) )
65 | {
66 | str[0] = '\0';
67 | return;
68 | }
69 |
70 | for (i=0; idns_cache )
79 | {
80 |
81 | MeerCounters->DNSCacheCount++;
82 |
83 | snprintf(str, size, "%s", DnsCache[i].reverse);
84 | str[ size - 1 ] ='\0';
85 | return;
86 |
87 | }
88 | else
89 | {
90 |
91 | /* Re-look it up and return it if cache is stale */
92 |
93 | memset(&ipaddr, 0, sizeof(struct sockaddr_in));
94 |
95 | ipaddr.sin_family = AF_INET;
96 | ipaddr.sin_port = htons(0);
97 |
98 | inet_pton(AF_INET, host, &ipaddr.sin_addr);
99 |
100 | (void)getnameinfo((struct sockaddr *)&ipaddr, sizeof(struct sockaddr_in), host_r, sizeof(host_r), NULL, 0, NI_NAMEREQD);
101 |
102 | strlcpy(DnsCache[i].reverse, host_r, sizeof(DnsCache[i].reverse));
103 | DnsCache[i].lookup_time = utime;
104 |
105 | MeerCounters->DNSCount++;
106 |
107 | snprintf(str, size, "%s", DnsCache[i].reverse);
108 | str[ size - 1 ] = '0';
109 |
110 | return;
111 | }
112 |
113 | }
114 |
115 | }
116 |
117 | memset(&ipaddr, 0, sizeof(struct sockaddr_in));
118 |
119 | ipaddr.sin_family = AF_INET;
120 | ipaddr.sin_port = htons(0);
121 |
122 | inet_pton(AF_INET, host, &ipaddr.sin_addr);
123 |
124 | (void)getnameinfo((struct sockaddr *)&ipaddr, sizeof(struct sockaddr_in), host_r, sizeof(host_r), NULL, 0, NI_NAMEREQD);
125 |
126 | /* Insert DNS into cache */
127 |
128 | DnsCache = (_DnsCache *) realloc(DnsCache, (DnsCacheCount+1) * sizeof(_DnsCache));
129 |
130 | strlcpy(DnsCache[DnsCacheCount].ipaddress, host, sizeof(DnsCache[DnsCacheCount].ipaddress));
131 | strlcpy(DnsCache[DnsCacheCount].reverse, host_r, sizeof(DnsCache[DnsCacheCount].reverse));
132 | DnsCache[DnsCacheCount].lookup_time = utime;
133 |
134 | DnsCacheCount++;
135 | MeerCounters->DNSCount++;
136 |
137 | snprintf(str, size, "%s", host_r);
138 | str[ size - 1 ] = '\0';
139 |
140 | }
141 |
142 | int DNS_Lookup_Forward( const char *host, char *str, size_t size )
143 | {
144 |
145 | char ipstr[INET6_ADDRSTRLEN] = { 0 };
146 |
147 | struct addrinfo hints = {0}, *res = NULL;
148 | int status;
149 | void *addr;
150 |
151 | memset(&hints, 0, sizeof hints);
152 | hints.ai_family = AF_UNSPEC; /* AF_INET or AF_INET6 to force version */
153 | hints.ai_socktype = SOCK_STREAM;
154 |
155 | if ((status = getaddrinfo(host, NULL, &hints, &res)) != 0)
156 | {
157 |
158 | Meer_Log(WARN, "%s: %s", gai_strerror(status), host);
159 | return -1;
160 |
161 | }
162 |
163 | if (res->ai_family == AF_INET) /* IPv4 */
164 | {
165 |
166 | struct sockaddr_in *ipv4 = (struct sockaddr_in *)res->ai_addr;
167 | addr = &(ipv4->sin_addr);
168 |
169 | }
170 | else /* IPv6 */
171 | {
172 |
173 | struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)res->ai_addr;
174 | addr = &(ipv6->sin6_addr);
175 |
176 | }
177 |
178 | inet_ntop(res->ai_family, addr, ipstr, sizeof ipstr);
179 | freeaddrinfo(res);
180 |
181 | snprintf(str, size, "%s", ipstr);
182 | str[ size - 1 ] = '\0';
183 |
184 | return 0;
185 | }
186 |
187 |
--------------------------------------------------------------------------------
/src/util-dns.h:
--------------------------------------------------------------------------------
1 | /*
2 | ** Copyright (C) 2018-2023 Quadrant Information Security
3 | ** Copyright (C) 2018-2023 Champ Clark III
4 | **
5 | ** This program is free software; you can redistribute it and/or modify
6 | ** it under the terms of the GNU General Public License Version 2 as
7 | ** published by the Free Software Foundation. You may not use, modify or
8 | ** distribute this program under any other version of the GNU General
9 | ** Public License.
10 | **
11 | ** This program is distributed in the hope that it will be useful,
12 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | ** GNU General Public License for more details. **
15 | ** You should have received a copy of the GNU General Public License
16 | ** along with this program; if not, write to the Free Software
17 | ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 | */
19 |
20 |
21 | typedef struct _DnsCache _DnsCache;
22 | struct _DnsCache
23 | {
24 | char ipaddress[48];
25 | char reverse[256];
26 | uint64_t lookup_time;
27 |
28 | };
29 |
30 |
31 | void DNS_Lookup_Reverse( char *host, char *str, size_t size );
32 | int DNS_Lookup_Forward( const char *host, char *str, size_t size );
33 |
34 |
--------------------------------------------------------------------------------
/src/util-md5.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 |
6 |
7 | void MD5(uint8_t *initial_msg, size_t initial_len, char *str, size_t size)
8 | {
9 |
10 | #define LEFTROTATE(x, c) (((x) << (c)) | ((x) >> (32 - (c))))
11 |
12 | uint8_t *msg = NULL;
13 | uint32_t h0, h1, h2, h3;
14 |
15 | char digest[41] = { 0 };
16 | char tmp[9] = { 0 };
17 |
18 | // Note: All variables are unsigned 32 bit and wrap modulo 2^32 when calculating
19 |
20 | // r specifies the per-round shift amounts
21 |
22 | uint32_t r[] = {7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,
23 | 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20,
24 | 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23,
25 | 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21
26 | };
27 |
28 | // Use binary integer part of the sines of integers (in radians) as constants// Initialize variables:
29 |
30 | uint32_t k[] =
31 | {
32 | 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
33 | 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
34 | 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
35 | 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
36 | 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
37 | 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
38 | 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
39 | 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
40 | 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
41 | 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
42 | 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,
43 | 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
44 | 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
45 | 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
46 | 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
47 | 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391
48 | };
49 |
50 | h0 = 0x67452301;
51 | h1 = 0xefcdab89;
52 | h2 = 0x98badcfe;
53 | h3 = 0x10325476;
54 |
55 | // Pre-processing: adding a single 1 bit
56 | // append "1" bit to message
57 | /* Notice: the input bytes are considered as bits strings,
58 | where the first bit is the most significant bit of the byte.[37] */
59 |
60 | // Pre-processing: padding with zeros
61 | // append "0" bit until message length in bit ≡ 448 (mod 512)
62 | // append length mod (2 pow 64) to message
63 |
64 | int new_len = ((((initial_len + 8) / 64) + 1) * 64) - 8;
65 |
66 | msg = calloc(new_len + 64, 1); // also appends "0" bits
67 | // (we alloc also 64 extra bytes...)
68 | memcpy(msg, initial_msg, initial_len);
69 | msg[initial_len] = 128; // write the "1" bit
70 |
71 | uint32_t bits_len = 8*initial_len; // note, we append the len
72 | memcpy(msg + new_len, &bits_len, 4); // in bits at the end of the buffer
73 |
74 | // Process the message in successive 512-bit chunks:
75 | //for each 512-bit chunk of message:
76 | int offset;
77 | for(offset=0; offset
3 | ** Copyright (C) 2018-2023 Champ Clark III
4 | **
5 | ** This program is free software; you can redistribute it and/or modify
6 | ** it under the terms of the GNU General Public License Version 2 as
7 | ** published by the Free Software Foundation. You may not use, modify or
8 | ** distribute this program under any other version of the GNU General
9 | ** Public License.
10 | **
11 | ** This program is distributed in the hope that it will be useful,
12 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | ** GNU General Public License for more details.
15 | **
16 | ** You should have received a copy of the GNU General Public License
17 | ** along with this program; if not, write to the Free Software
18 | ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 | */
20 |
21 | #ifdef HAVE_CONFIG_H
22 | #include "config.h" /* From autoconf */
23 | #endif
24 |
25 | #include
26 | #include
27 | #include
28 | #include
29 | #include
30 | #include
31 | #include
32 |
33 | #include "meer.h"
34 | #include "meer-def.h"
35 | #include "config-yaml.h"
36 | #include "lockfile.h"
37 | #include "stats.h"
38 | #include "waldo.h"
39 | #include "config-yaml.h"
40 |
41 | #if defined(WITH_BLUEDOT) || defined(WITH_ELASTICSEARCH)
42 | #include
43 | #endif
44 |
45 | #ifdef WITH_ELASTICSEARCH
46 | #include
47 | bool elasticsearch_death = false;
48 | uint8_t elasticsearch_death_count = 0;
49 | extern uint_fast16_t elastic_proc_running;
50 | extern char *big_batch;
51 | extern char *big_batch_THREAD;
52 | #endif
53 |
54 | #ifdef HAVE_LIBHIREDIS
55 | #include
56 | #endif
57 |
58 | #ifdef WITH_BLUEDOT
59 | #include
60 | extern CURL *curl_bluedot;
61 | #endif
62 |
63 | extern struct _MeerWaldo *MeerWaldo;
64 | extern struct _MeerConfig *MeerConfig;
65 | extern struct _MeerOutput *MeerOutput;
66 | extern struct _MeerInput *MeerInput;
67 |
68 | void Signal_Handler(int sig_num)
69 | {
70 |
71 | Meer_Log(NORMAL, "Got signal %d!", sig_num);
72 |
73 | switch( sig_num )
74 | {
75 |
76 | /* exit */
77 |
78 | case SIGQUIT:
79 | case SIGINT:
80 | case SIGTERM:
81 | // case SIGSEGV:
82 | // case SIGABRT:
83 |
84 | if ( MeerOutput->pipe_enabled == true )
85 | {
86 | close(MeerOutput->pipe_fd);
87 | }
88 |
89 | #ifdef HAVE_LIBHIREDIS
90 |
91 | if ( MeerOutput->redis_enabled == true )
92 | {
93 | Redis_Close();
94 | }
95 |
96 | #endif
97 |
98 |
99 | #ifdef WITH_ELASTICSEARCH
100 |
101 | if ( MeerOutput->elasticsearch_enabled == true )
102 | {
103 |
104 | elasticsearch_death = true;
105 | elasticsearch_death_count = 0;
106 |
107 | while ( elastic_proc_running != 0 )
108 | {
109 | Meer_Log(NORMAL, "Waiting on %d Elasticseach thread to shutdown.", elastic_proc_running);
110 | sleep(1);
111 |
112 | if ( elasticsearch_death_count == 15 )
113 | {
114 | Meer_Log(WARN, "Timemout reached! Forcing shutdown.");
115 | break;
116 | }
117 |
118 | elasticsearch_death_count++;
119 |
120 | }
121 |
122 | if ( elastic_proc_running == 0 )
123 | {
124 | free( big_batch );
125 | free( big_batch_THREAD);
126 | }
127 |
128 | }
129 |
130 | #endif
131 |
132 | /* Some gymnastics to cleanup libcurl */
133 |
134 | #if defined(WITH_BLUEDOT) || defined(WITH_ELASTICSEARCH)
135 |
136 | bool clean_up = false;
137 |
138 | #ifdef WITH_BLUEDOT
139 |
140 | if ( MeerOutput->bluedot_flag == true )
141 | {
142 | curl_global_cleanup();
143 | clean_up = true;
144 | }
145 |
146 | #endif
147 |
148 | #ifdef WITH_ELASTICSEARCH
149 |
150 | if ( MeerOutput->elasticsearch_enabled == true && clean_up == false )
151 | {
152 | curl_global_cleanup();
153 | }
154 | #endif
155 |
156 | #endif
157 |
158 | if ( MeerOutput->file_enabled == true )
159 | {
160 | fflush(MeerOutput->file_fd);
161 | fclose(MeerOutput->file_fd);
162 | }
163 |
164 |
165 |
166 | Remove_Lock_File();
167 |
168 | Statistics();
169 |
170 |
171 | if ( MeerInput->type == YAML_INPUT_FILE )
172 | {
173 | fsync(MeerInput->waldo_fd);
174 | close(MeerInput->waldo_fd);
175 | Waldo_Close();
176 | }
177 |
178 | Meer_Log(NORMAL, "Shutdown complete.");
179 |
180 | fclose(MeerConfig->meer_log_fd);
181 | fflush(stdout);
182 |
183 | exit(0);
184 |
185 | /* Signals to ignore */
186 |
187 | case 17: /* Child process has exited. */
188 | case 28: /* Terminal 'resize'/alarm. */
189 |
190 | break;
191 |
192 | case SIGUSR1:
193 |
194 | Statistics();
195 | break;
196 |
197 | case SIGUSR2:
198 |
199 | Statistics();
200 | break;
201 |
202 | case SIGPIPE:
203 | Meer_Log(NORMAL, "[Received signal %d [SIGPIPE]. Possible incomplete JSON?", sig_num);
204 | break;
205 |
206 |
207 | default:
208 | Meer_Log(NORMAL, "[Received signal %d. Meer doesn't know how to deal with.", sig_num);
209 | }
210 |
211 | }
212 |
213 |
214 |
215 |
--------------------------------------------------------------------------------
/src/util-signal.h:
--------------------------------------------------------------------------------
1 | /*
2 | ** Copyright (C) 2018-2023 Quadrant Information Security
3 | ** Copyright (C) 2018-2023 Champ Clark III
4 | **
5 | ** This program is free software; you can redistribute it and/or modify
6 | ** it under the terms of the GNU General Public License Version 2 as
7 | ** published by the Free Software Foundation. You may not use, modify or
8 | ** distribute this program under any other version of the GNU General
9 | ** Public License.
10 | **
11 | ** This program is distributed in the hope that it will be useful,
12 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | ** GNU General Public License for more details.
15 | **
16 | ** You should have received a copy of the GNU General Public License
17 | ** along with this program; if not, write to the Free Software
18 | ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 | */
20 |
21 | void Signal_Handler(int sig_num);
22 |
23 |
--------------------------------------------------------------------------------
/src/util-strlcat.c:
--------------------------------------------------------------------------------
1 | /* strlcat
2 | *
3 | * Provided by the OpenBSD team. This is here for systems that do not
4 | * support the strlcat call.
5 | *
6 | */
7 |
8 |
9 | /* $OpenBSD: strlcat.c,v 1.13 2005/08/08 08:05:37 espie Exp $ */
10 | /*
11 | * Copyright (c) 1998 Todd C. Miller
12 | *
13 | * Permission to use, copy, modify, and distribute this software for any
14 | * purpose with or without fee is hereby granted, provided that the above
15 | * copyright notice and this permission notice appear in all copies.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
18 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
19 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
20 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
21 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
22 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
23 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
24 | */
25 |
26 | #ifdef HAVE_CONFIG_H
27 | #include "config.h" /* From autoconf */
28 | #endif
29 |
30 | #ifndef HAVE_STRLCAT
31 |
32 | #include
33 | #include
34 |
35 | /*
36 | * Appends src to string dst of size siz (unlike strncat, siz is the
37 | * full size of dst, not space left). At most siz-1 characters
38 | * will be copied. Always NUL terminates (unless siz <= strlen(dst)).
39 | * Returns strlen(src) + MIN(siz, strlen(initial dst)).
40 | * If retval >= siz, truncation occurred.
41 | */
42 | size_t
43 | strlcat(char *dst, const char *src, size_t siz)
44 | {
45 | char *d = dst;
46 | const char *s = src;
47 | size_t n = siz;
48 | size_t dlen;
49 |
50 | /* Find the end of dst and adjust bytes left but don't go past end */
51 | while (n-- != 0 && *d != '\0')
52 | d++;
53 | dlen = d - dst;
54 | n = siz - dlen;
55 |
56 | if (n == 0)
57 | return(dlen + strlen(s));
58 | while (*s != '\0')
59 | {
60 | if (n != 1)
61 | {
62 | *d++ = *s;
63 | n--;
64 | }
65 | s++;
66 | }
67 | *d = '\0';
68 |
69 | return(dlen + (s - src)); /* count does not include NUL */
70 | }
71 |
72 | #endif
73 |
--------------------------------------------------------------------------------
/src/util-strlcpy.c:
--------------------------------------------------------------------------------
1 | /* strlcpy
2 | *
3 | * Provided by the OpenBSD team. This file is here for systems that
4 | * do not support the strlcpy call.
5 | *
6 | */
7 |
8 | /* $OpenBSD: strlcpy.c,v 1.11 2006/05/05 15:27:38 millert Exp $ */
9 |
10 | /*
11 | * Copyright (c) 1998 Todd C. Miller
12 | *
13 | * Permission to use, copy, modify, and distribute this software for any
14 | * purpose with or without fee is hereby granted, provided that the above
15 | * copyright notice and this permission notice appear in all copies.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
18 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
19 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
20 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
21 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
22 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
23 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
24 | */
25 |
26 | #ifdef HAVE_CONFIG_H
27 | #include "config.h" /* From autoconf */
28 | #endif
29 |
30 | #ifndef HAVE_STRLCPY
31 |
32 | #include
33 | #include
34 |
35 | /*
36 | * Copy src to string dst of size siz. At most siz-1 characters
37 | * will be copied. Always NUL terminates (unless siz == 0).
38 | * Returns strlen(src); if retval >= siz, truncation occurred.
39 | */
40 | size_t
41 | strlcpy(char *dst, const char *src, size_t siz)
42 | {
43 | char *d = dst;
44 | const char *s = src;
45 | size_t n = siz;
46 |
47 | /* Copy as many bytes as will fit */
48 | if (n != 0)
49 | {
50 | while (--n != 0)
51 | {
52 | if ((*d++ = *s++) == '\0')
53 | break;
54 | }
55 | }
56 |
57 | /* Not enough room in dst, add NUL and traverse rest of src */
58 | if (n == 0)
59 | {
60 | if (siz != 0)
61 | *d = '\0'; /* NUL-terminate dst */
62 | while (*s++)
63 | ;
64 | }
65 |
66 | return(s - src - 1); /* count does not include NUL */
67 | }
68 |
69 | #endif
70 |
--------------------------------------------------------------------------------
/src/util.h:
--------------------------------------------------------------------------------
1 | /*
2 | ** Copyright (C) 2018-2023 Quadrant Information Security
3 | ** Copyright (C) 2018-2023 Champ Clark III
4 | **
5 | ** This program is free software; you can redistribute it and/or modify
6 | ** it under the terms of the GNU General Public License Version 2 as
7 | ** published by the Free Software Foundation. You may not use, modify or
8 | ** distribute this program under any other version of the GNU General
9 | ** Public License.
10 | **
11 | ** This program is distributed in the hope that it will be useful,
12 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | ** GNU General Public License for more details.
15 | **
16 | ** You should have received a copy of the GNU General Public License
17 | ** along with this program; if not, write to the Free Software
18 | ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 | */
20 |
21 | #include
22 | #include "meer-def.h"
23 |
24 | typedef struct _Fingerprint_Networks _Fingerprint_Networks;
25 | struct _Fingerprint_Networks
26 | {
27 |
28 | struct
29 | {
30 | unsigned char ipbits[MAXIPBIT];
31 | unsigned char maskbits[MAXIPBIT];
32 | } range;
33 |
34 | };
35 |
36 | typedef struct _NDP_Ignore _NDP_Ignore;
37 | struct _NDP_Ignore
38 | {
39 |
40 | struct
41 | {
42 | unsigned char ipbits[MAXIPBIT];
43 | unsigned char maskbits[MAXIPBIT];
44 | } range;
45 |
46 | };
47 |
48 | void Drop_Priv(void);
49 | bool Check_Endian(void);
50 | char *Hexify(char *xdata, int length);
51 | bool Validate_JSON_String( const char *buf );
52 | bool IP2Bit(char *ipaddr, unsigned char *out);
53 | bool Mask2Bit(int mask, unsigned char *out);
54 | void Remove_Spaces(char *s);
55 | void Remove_Return(char *s);
56 | uint64_t Current_Epoch( void );
57 | bool Is_IPv6 (char *ipaddr);
58 | double CalcPct(uint64_t cnt, uint64_t total);
59 |
60 | bool Is_IP (char *ipaddr, int ver );
61 | int File_Check (char *filename);
62 | bool Is_Inrange ( unsigned char *ip, unsigned char *tests, int count);
63 | void To_UpperC(char *const s);
64 | uint32_t Djb2_Hash(char *str);
65 | void Convert_ISO8601_For_SQL( char *time, char *str, size_t size );
66 | bool Is_Notroutable ( unsigned char *ip );
67 | bool Try_And_Fix_IP ( char *orig_ip, char *str, size_t size );
68 |
69 |
--------------------------------------------------------------------------------
/src/version.h:
--------------------------------------------------------------------------------
1 | #define VERSION "2.1.0"
2 |
--------------------------------------------------------------------------------
/src/waldo.c:
--------------------------------------------------------------------------------
1 | /*
2 | ** Copyright (C) 2018-2023 Quadrant Information Security
3 | ** Copyright (C) 2018-2023 Champ Clark III
4 | **
5 | ** This program is free software; you can redistribute it and/or modify
6 | ** it under the terms of the GNU General Public License Version 2 as
7 | ** published by the Free Software Foundation. You may not use, modify or
8 | ** distribute this program under any other version of the GNU General
9 | ** Public License.
10 | **
11 | ** This program is distributed in the hope that it will be useful,
12 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | ** GNU General Public License for more details.
15 | **
16 | ** You should have received a copy of the GNU General Public License
17 | ** along with this program; if not, write to the Free Software
18 | ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 | */
20 |
21 | #ifdef HAVE_CONFIG_H
22 | #include "config.h" /* From autoconf */
23 | #endif
24 |
25 | #include
26 | #include
27 | #include
28 | #include
29 | #include
30 | #include
31 | #include
32 | #include
33 | #include
34 | #include
35 |
36 | #include "meer.h"
37 | #include "meer-def.h"
38 |
39 | extern struct _MeerWaldo *MeerWaldo;
40 | //extern struct _MeerConfig *MeerConfig;
41 | extern struct _MeerInput *MeerInput;
42 |
43 | void Waldo_Sync( void )
44 | {
45 | msync(MeerWaldo, sizeof(_MeerWaldo), MS_ASYNC);
46 | }
47 |
48 | void Waldo_Close( void )
49 | {
50 |
51 | Waldo_Sync();
52 | munmap(MeerWaldo, sizeof(_MeerWaldo));
53 |
54 | }
55 |
56 | void Init_Waldo( void )
57 | {
58 |
59 | bool new_waldo = false;
60 |
61 |
62 | if (( MeerInput->waldo_fd = open(MeerInput->waldo_file, (O_CREAT | O_EXCL | O_RDWR), (S_IREAD | S_IWRITE))) > 0 )
63 | {
64 | Meer_Log(NORMAL,"New waldo file created.");
65 | new_waldo = true;
66 | }
67 |
68 |
69 | else if ((MeerInput->waldo_fd = open(MeerInput->waldo_file, (O_CREAT | O_RDWR), (S_IREAD | S_IWRITE))) < 0 )
70 | {
71 | Meer_Log(ERROR, "[%s, line %d] Cannot open() for waldo '%s' [%s]", __FILE__, __LINE__, MeerInput->waldo_file, strerror(errno));
72 | }
73 |
74 | if ( ftruncate(MeerInput->waldo_fd, sizeof(_MeerWaldo)) != 0 )
75 | {
76 | Meer_Log(ERROR, "[%s, line %d] Failed to ftruncate for _MeerWaldo. [%s]", __FILE__, __LINE__, strerror(errno));
77 | }
78 |
79 | if (( MeerWaldo = mmap(0, sizeof(_MeerWaldo), (PROT_READ | PROT_WRITE), MAP_SHARED, MeerInput->waldo_fd, 0)) == MAP_FAILED )
80 | {
81 | Meer_Log(ERROR,"[%s, line %d] Error allocating memory for counters object! [%s]", __FILE__, __LINE__, strerror(errno));
82 | }
83 |
84 | if ( new_waldo == false )
85 | {
86 | Meer_Log(NORMAL, "Waldo loaded. Current position: %" PRIu64 "", MeerWaldo->position);
87 | }
88 |
89 | Meer_Log(NORMAL, "");
90 |
91 | }
92 |
--------------------------------------------------------------------------------
/src/waldo.h:
--------------------------------------------------------------------------------
1 | /*
2 | ** Copyright (C) 2018-2023 Quadrant Information Security
3 | ** Copyright (C) 2018-2023 Champ Clark III
4 | **
5 | ** This program is free software; you can redistribute it and/or modify
6 | ** it under the terms of the GNU General Public License Version 2 as
7 | ** published by the Free Software Foundation. You may not use, modify or
8 | ** distribute this program under any other version of the GNU General
9 | ** Public License.
10 | **
11 | ** This program is distributed in the hope that it will be useful,
12 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | ** GNU General Public License for more details.
15 | **
16 | ** You should have received a copy of the GNU General Public License
17 | ** along with this program; if not, write to the Free Software
18 | ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 | */
20 |
21 | void Waldo_Sync( void );
22 | void Waldo_Close( void );
23 | void Init_Waldo( void );
24 |
--------------------------------------------------------------------------------
/stamp-h1:
--------------------------------------------------------------------------------
1 | timestamp for config.h
2 |
--------------------------------------------------------------------------------
/tools/external/external-program-blocklist/README.md:
--------------------------------------------------------------------------------
1 | # External
2 |
3 | These are a set of simple routines that allow Meer to write out "block lists"
4 | to a MySQL/MariaDB database. The list can then be consumed by other devices
5 | (firewalls for example) as a "block list".
6 |
7 | ## SQL
8 |
9 | SQL database/table for routines to use. To setup, do this:
10 |
11 | $ mysqladmin -u root -p create blocklist
12 | $ mysql -u root -p blocklist < blocklist.sql
13 |
14 | ## Inserting Into SQL
15 |
16 | ### external-program-sql-blocklist.j2
17 |
18 | This is the routine that will be called by Meer's "external" processors. This
19 | needs to be fed "alert" data.
20 |
21 | As provided, it is a Ansible J2 template.
22 |
23 | The following need for it.
24 |
25 | - BLOCKLISTER_USER
26 | - BLOCKLISTER_PASS
27 | - BLOCKLISTER_DB
28 | - BLOCKLISTER_SERVER
29 | - BLOCKLISTER_LOG
30 | - BLOCKLISTER_IGNORE_PORTS
31 |
32 | ## Fetching
33 |
34 | ### blocklist.cgi
35 |
36 | This is the web CGI that "sends" the block list to the "client". As IP
37 | addresses are sent, they are removed. This routines URL is where you would
38 | configured you device to get blocklist. For example:
39 |
40 | http://10.10.10.10/cgi-bin/blocklist.cgi?apikey=yourkeyhere
41 |
42 | The API key is set in the blocklist.cgi routine. This prevents unauthorized
43 | access to you block lists.
44 |
45 | This script will also remove the entries when fetched.
46 |
47 | Any subnets in `/usr/local/etc/blocklister_ignore_subnets` will be ignored.
48 |
49 | ### blocklister.j2
50 |
51 | Generates a size limited list of IPs and subnets for use with like Fortigates.
52 |
53 | Unlike blocklist.cgi, this script builds a list of nets to ignore. Where possible
54 | if a set of IPs can be collapsed into a full subnet they will. Any subnets ending in
55 | `/32` or `/128` have the netmask removed to save space as it is just a IP.
56 |
57 | If the size execeds the max allowable size, the oldest entry will be removed and it
58 | will try again. It will do this till it gets down to a max size.
59 |
60 | As provided it is a Ansible J2 template. The following keys below are used.
61 |
62 | - BLOCKLISTER_DB
63 | - BLOCKLISTER_SERVER
64 | - BLOCKLISTER_USER
65 | - BLOCKLISTER_PASS
66 | - BLOCKLISTER_MAX_SIZE
67 | - BLOCKLISTER_MAX_AGE
68 | - BLOCKLISTER_RM_OLD
69 |
70 | ## Cron
71 |
72 | The example cron Ansible J2 template provides a example of running this and copying
73 | it some place it can be fetched. Copied to a file name specied by `BLOCKLISTER_KEY` in
74 | the default www on a basic Debian based systems.
75 |
76 | ## Template Variables
77 |
78 | | Variable | Type | Suggested Base Settings | Description |
79 | |---------------------------|--------|---------------------------|-------------------------------------------------------------|
80 | | BLOCKLISTER_DB | string | blocklist | The DB name to connect to. |
81 | | BLOCKLISTER_DB_ENABLE | bool | 0 | Enable the DB related bits for Blocklister |
82 | | BLOCKLISTER_ENABLE | bool | 0 | Enables BLOCKLISTER_DB_ENABLE and BLOCKLISTER_SCRIPT_ENABLE |
83 | | BLOCKLISTER_KEY | string | undef | Access key/filename. |
84 | | BLOCKLISTER_MAX_AGE | int | 7776000 | Max age in seconds. Default is 90 days. |
85 | | BLOCKLISTER_MAX_SIZE | int | 10000000 | Max size in bytes. The default is based on Fortigate. |
86 | | BLOCKLISTER_PASS | string | undef | Password for the DB user. |
87 | | BLOCKLISTER_RM_OLD | bool | 0 | Remove items that have a age older than the max age. |
88 | | BLOCKLISTER_SCRIPT_ENABLE | bool | 0 | Enable the script related bits for Blocklister. |
89 | | BLOCKLISTER_SERVER | IP | 127.0.0.1 | IP to connect to. |
90 | | BLOCKLISTER_USER | string | blocklister | DB user |
91 | | BLOCKLISTER_IGNORE_PORTS | string | | A space seperated string of ports to ignore. |
92 | | BLOCKLISTER_LOG | string | /var/log/meer/blocklister | Where to write the logs out to. |
93 |
--------------------------------------------------------------------------------
/tools/external/external-program-blocklist/blocklist.cgi:
--------------------------------------------------------------------------------
1 | #!/usr/bin/perl
2 |
3 | #############################################################################
4 | # blocklist.cgi - Simple routine that reads data put into a table by
5 | # "external-program-blocklist" (called by Meer) and sends to to the caller.
6 | # As the data is being sent, it is removed from the SQL database to prevent
7 | # repeatedly sending the same data over and over again.
8 | # This can be useful for creating block lists for firewalls to read (Palo
9 | # Alto, Forigate, etc).
10 | #
11 | # Champ Clark III
12 | # 20220908
13 | #############################################################################
14 |
15 | use DBI;
16 | use CGI qw(:all);
17 |
18 | # Set this to your database credentials
19 |
20 | my $my_username = "username";
21 | my $my_password = "password";
22 | my $my_host = "127.0.0.1";
23 | my $my_database = "blocklist";
24 |
25 | my $API_KEY = "1ee217b83185ffdceb1597994ce0e4c710577085";
26 |
27 | my $api_key = &remove_unwanted(scalar param("apikey"));
28 |
29 | #############################################################################
30 | # Connect to SQL database!
31 | #############################################################################
32 |
33 | my $db = "DBI:MariaDB:database=$my_database;host=$my_host";
34 | my $dbh = DBI->connect($db, $my_username, $my_password) || die "$DBI::errstr\n";
35 |
36 | my $db2 = "DBI:MariaDB:database=$my_database;host=$my_host";
37 | my $dbh2 = DBI->connect($db2, $my_username, $my_password) || die "$DBI::errstr\n";
38 |
39 | my $sql;
40 | my $sql2;
41 | my $sth;
42 | my $sth2;
43 |
44 | print "Content-type: text/plain\n\n";
45 |
46 | # Verify that the API key is valid!
47 |
48 | if ( $api_key ne $API_KEY )
49 | {
50 | print "Access Denied.\n";
51 | exit(0);
52 | }
53 |
54 | # Pull list of active IP address that need to be sent (blocked)
55 |
56 | $sql = "SELECT id,ip FROM drop_list";
57 | $sth = $dbh->prepare( $sql );
58 | $sth->execute || die "$DBI::errstr\n";
59 |
60 | while (my(@bl)=$sth->fetchrow_array)
61 | {
62 |
63 | my $id = $bl[0];
64 | my $ip = $bl[1];
65 |
66 | print "$ip\n";
67 |
68 | # Delete after sending. Prevent resending data if interrupted
69 |
70 | $sql2 = "DELETE FROM drop_list WHERE id=$id";
71 | $sth2 = $dbh2->prepare( $sql2 );
72 | $sth2->execute || die "$DBI::errstr\n";
73 |
74 | }
75 |
76 | exit 0;
77 |
78 | #############################################################################
79 | # remove_unwanted - input validation
80 | #############################################################################
81 |
82 | sub remove_unwanted {
83 | our $s;
84 | local($s) = @_;
85 | $s =~ s/\.\.//g;
86 | $s =~ s/[^A-Za-z0-9\@\-\_\/:.]//g if defined $s;
87 | return $s;
88 | }
89 |
90 |
91 |
--------------------------------------------------------------------------------
/tools/external/external-program-blocklist/blocklist.sql:
--------------------------------------------------------------------------------
1 |
2 | DROP TABLE IF EXISTS `drop_list`;
3 | CREATE TABLE IF NOT EXISTS `drop_list` (
4 | `id` int(11) NOT NULL AUTO_INCREMENT,
5 | `timestamp` DATETIME NOT NULL,
6 | `ip` VARCHAR(64) NOT NULL,
7 | `sid` BIGINT(20) NOT NULL,
8 | KEY `id` (`id`),
9 | INDEX `ip` (`ip`)
10 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
11 | ALTER TABLE drop_list ADD UNIQUE(ip);
12 |
--------------------------------------------------------------------------------
/tools/external/external-program-blocklist/blocklister.j2:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env perl
2 |
3 | #############################################################################
4 | # Based on blocklist.cgi by Champ Clark III and updated for building size
5 | # subnet limited collections by Zane C. Bowers-Hadley for the use with
6 | # like Fortigate etc.
7 | #
8 | # 20221230
9 | #############################################################################
10 |
11 | use DBI;
12 | use warnings;
13 | use strict;
14 | use Net::CIDR::Lite;
15 | use TOML qw(from_toml);
16 | use File::Slurp;
17 | use Time::Piece;
18 |
19 | my $config_file = '/usr/local/etc/blocklister.toml';
20 |
21 | # 7776000 = 90 days in seconds
22 | my $config = {
23 | dsn => 'DBI:MariaDB:database={{ BLOCKLISTER_DB }};host={{ BLOCKLISTER_SERVER }}',
24 | user => '{{ BLOCKLISTER_USER }}',
25 | pass => '{{ BLOCKLISTER_PASS }}',
26 | max_size => '{{ BLOCKLISTER_MAX_SIZE }}',
27 | max_age => '{{ BLOCKLISTER_MAX_AGE }}',
28 | remote_only => '1',
29 | delete => '0',
30 | delete_old => '{{ BLOCKLISTER_RM_OLD }}',
31 | cache_dir => '/var/cache/blocklister',
32 | };
33 |
34 | if ( -f $config_file ) {
35 | die( '"' . $config_file . '" does not exist' );
36 |
37 | my $config_raw = slurp($config_file);
38 | my ( $config_parsed, $err ) = from_toml($config_raw);
39 | unless ($config) {
40 | die "Error parsing toml: $err";
41 | }
42 |
43 | my @keys = keys( %{$config} );
44 | foreach my $key (@keys) {
45 | if ( defined( $config_parsed->{$key} ) ) {
46 | $config->{$key} = $config_parsed->{$key};
47 | }
48 | }
49 | }
50 |
51 | if ( !-d $config->{cache_dir} ) {
52 | mkdir( $config->{cache_dir} ) || die( '"' . $config->{cache_dir} . '" does not exist and could not be created' );
53 | }
54 |
55 | my $cache_file = $config->{cache_dir} . '/cache';
56 |
57 | my $cache = {};
58 | if ( !$config->{remote_only} ) {
59 | if ( -f $cache_file ) {
60 | my $cache_raw = slurp($cache_file);
61 | my @cache_split = split( /\n/, $cache_raw );
62 | foreach my $line (@cache_split) {
63 | my ( $ip, $time ) = split( /\,/, $line );
64 | $cache->{$ip} = $time;
65 | }
66 | }
67 | }
68 |
69 | my $current_time = time;
70 | my $max_age = $current_time - $config->{max_age};
71 |
72 | my $dbh = DBI->connect( $config->{dsn}, $config->{user}, $config->{pass} ) || die "$DBI::errstr\n";
73 | my $dbh2 = DBI->connect( $config->{dsn}, $config->{user}, $config->{pass} ) || die "$DBI::errstr\n";
74 |
75 | my $sql = "SELECT id,ip,timestamp FROM drop_list";
76 | my $sth = $dbh->prepare($sql);
77 | $sth->execute || die "$DBI::errstr\n";
78 |
79 | while ( my (@bl) = $sth->fetchrow_array ) {
80 | my $id = $bl[0];
81 | my $ip = $bl[1];
82 | my $timestamp = $bl[2];
83 |
84 | # 2022-12-01 02:30:14
85 | my $t = Time::Piece->strptime( $timestamp, '%Y-%m-%d %H:%M:%S' );
86 |
87 | # check to see if max age if not zero and if not
88 | # only add it if it falls inside the time frame we want
89 | my $add_it = 1;
90 | if ( $config->{max_age} != 0 && $t->epoch < $max_age ) {
91 | $add_it = 0;
92 | }
93 | if ($add_it) {
94 | $cache->{$ip} = $t->epoch;
95 | }
96 |
97 | # remove it if removing all or it is old and removing old
98 | if ( $config->{delete} || ( $config->{delete_old} && !$add_it ) ) {
99 | my $sql2 = "DELETE FROM drop_list WHERE id=$id";
100 | my $sth2 = $dbh2->prepare($sql2);
101 | $sth2->execute || die "$DBI::errstr\n";
102 | }
103 | }
104 |
105 | # if not remote only and we have a max age set, check the cache
106 | # if remote only, then we did not add any old items
107 | if ( $config->{max_age} > 0 && !$config->{remote_only} ) {
108 | my @keys = keys( %{$cache} );
109 | foreach my $ip (@keys) {
110 | if ( $$cache->{ip} < $max_age ) {
111 | delete( $cache->{$ip} );
112 | }
113 | }
114 | }
115 |
116 | # save the updated cache if needed
117 | if ( !$config->{remote_only} ) {
118 | my $cache_raw = '';
119 | my @keys = keys( %{$cache} );
120 | foreach my $ip (@keys) {
121 | $cache_raw = $cache_raw . $ip . ',' . $cache->{$ip} . "\n";
122 | }
123 | write_file( $cache_file, $cache_raw );
124 | }
125 |
126 | my $output = '';
127 |
128 | # put together the output file, looping until we have one small enough to use
129 | my $oversized = 1;
130 | my $resized = 0;
131 | while ($oversized) {
132 |
133 | # Net::CIDR::Lite can't work both, add each IP to it's respective one
134 | my $cidr_ipv4 = Net::CIDR::Lite->new;
135 | my $cidr_ipv6 = Net::CIDR::Lite->new;
136 | my @keys = keys( %{$cache} );
137 | foreach my $ip (@keys) {
138 | if ( $ip =~ /\./ ) {
139 | $cidr_ipv4->add( $ip . "/32" );
140 | }
141 | else {
142 | $cidr_ipv6->add( $ip . "/128" );
143 | }
144 | }
145 |
146 | # put together the output
147 | my @ipv4 = $cidr_ipv4->list;
148 | my $output_ipv4 = join( "\n", @ipv4 ) . "\n";
149 | my @ipv6 = $cidr_ipv6->list;
150 | my $output_ipv6 = join( "\n", @ipv6 ) . "\n";
151 | $output = $output_ipv4 . $output_ipv6;
152 | $output =~ s/\n\n+/\n/g;
153 |
154 | # remove subnet ending for full IPs
155 | $output =~ s/\/32//g;
156 | $output =~ s/\/128//g;
157 |
158 | # check size
159 | if ( length($output) < $config->{max_size} ) {
160 | $oversized = 0;
161 | }
162 | else {
163 | # if oversized still, remove the oldest key and try again
164 | my $oldest;
165 | foreach my $ip (@keys) {
166 | if ( !defined($oldest) ) {
167 | $oldest = $ip;
168 | }
169 | else {
170 | if ( $cache->{$oldest} > $cache->{$ip} ) {
171 | $oldest = $ip;
172 | }
173 | }
174 | }
175 | delete( $cache->{$oldest} );
176 | $resized = 1;
177 | }
178 | }
179 |
180 | # save the saved cache since some keys were removed if needed
181 | if ( !$config->{remote_only} ) {
182 | my $cache_raw = '';
183 | if ($resized) {
184 | my @keys = keys( %{$cache} );
185 | foreach my $ip (@keys) {
186 | $cache_raw = $cache_raw . $ip . ',' . $cache->{$ip} . "\n";
187 | }
188 | write_file( $cache_file, $cache_raw );
189 | }
190 | }
191 |
192 | write_file( $config->{cache_dir} . '/output', $output );
193 |
194 | exit 0;
195 |
--------------------------------------------------------------------------------
/tools/external/external-program-blocklist/blocklister_cron.j2:
--------------------------------------------------------------------------------
1 | */10 * * * * root /usr/bin/env LC_ALL=C /usr/local/quadrant/bin/blocklister 2> /dev/null; cp /var/cache/blocklister/output /var/www/html/{{BLOCKLISTER_KEY}} 2> /dev/null
2 |
--------------------------------------------------------------------------------
/tools/external/external-program-blocklist/external-program-sql-blocklist.j2:
--------------------------------------------------------------------------------
1 | #!/usr/bin/perl
2 |
3 | #############################################################################
4 | # external-program-sql-blocklist - Simple routine that takes Surcata/Sagan
5 | # EVE data, parses it and sends a "blocklist" SQL database. This data can
6 | # then be retrieve by the get-blocklists.cgi.
7 | #
8 | # Champ Clark III (cclark@quadrantsec.com)
9 | # 20220907
10 | #
11 | #############################################################################
12 |
13 | use JSON;
14 | use Net::Subnet qw(subnet_matcher);
15 | use DBI;
16 | use File::Slurp;
17 |
18 | use warnings;
19 | use strict;
20 |
21 | #############################################################################
22 | # SQL Authentication Data
23 | #############################################################################
24 |
25 | my $my_username = "{{ BLOCKLISTER_USER }}";
26 | my $my_password = "{{ BLOCKLISTER_PASS }}";
27 | my $my_database = "{{ BLOCKLISTER_DB }}";
28 | my $my_host = "{{ BLOCKLISTER_SERVER }}";
29 | my $ignore_subnet_file = "/usr/local/etc/blocklister_ignore_subnets";
30 | my $LOG_FILE = "{{ BLOCKLISTER_LOG }}"; # Log file
31 |
32 | #############################################################################
33 | # Connect to SQL database!
34 | #############################################################################
35 |
36 | my $db = "DBI:MariaDB:database=$my_database;host=$my_host";
37 | my $dbh = DBI->connect( $db, $my_username, $my_password ) || die "$DBI::errstr\n";
38 |
39 | my $sql;
40 | my $sth;
41 |
42 | #############################################################################
43 | # The $white_list are IP address that you do NOT to send blocks for. You'll
44 | # likely want to put your network (internal & external) IP address ranges
45 | # within this list!
46 | #############################################################################
47 |
48 | my $ignore_raw = read_file($ignore_subnet_file);
49 | my @to_ignore = split( /\n/, $ignore_raw );
50 | @to_ignore = grep( !/^[\ \t]*\#/, @to_ignore );
51 | @to_ignore = grep( !/^\w*$/, @to_ignore );
52 |
53 | my $int = 0;
54 | while ( defined( $to_ignore[$int] ) ) {
55 | $to_ignore[$int] =~ s/^[\ \t]*//;
56 | $to_ignore[$int] =~ s/[\ \t].*$//;
57 | $to_ignore[$int] =~ s/#.*$//;
58 | $int++;
59 | }
60 | my $white_list = subnet_matcher @to_ignore;
61 |
62 | #########################################################################################
63 | # Build a list of ports to ignore. Array used for the templating purposes
64 | #########################################################################################
65 |
66 | my @ignore_ports_array = qw(
67 | {{ BLOCKLISTER_IGNORE_PORTS }}
68 | );
69 |
70 | my %ignore_ports;
71 | foreach my $port (@ignore_ports_array) {
72 | $ignore_ports{$port} = 1;
73 | }
74 |
75 | #############################################################################
76 | # You shouldn't need to mess with anything else below this
77 | #############################################################################
78 |
79 | my $json_d;
80 | my $target;
81 | my $src_ip;
82 | my $src_port;
83 | my $dest_ip;
84 | my $dest_port;
85 | my $signature;
86 | my $sig_id;
87 |
88 | # Handle signals cleanly...
89 |
90 | $SIG{'INT'} = \&Signal_Handler;
91 | $SIG{'TERM'} = \&Signal_Handler;
92 | $SIG{'HUP'} = \&Signal_Handler;
93 |
94 | open( LOG, ">> $LOG_FILE" ) || die "Cannot open $LOG_FILE!\n";
95 |
96 | # Wait on stdin and collect the incoming json.
97 |
98 | while (<>) {
99 |
100 | Log("------------------------------------------------------------------------------");
101 | Log( "** Received EVE: " . $_ );
102 |
103 | $json_d = decode_json($_);
104 |
105 | $src_ip = $json_d->{src_ip};
106 | $src_port = $json_d->{src_port};
107 | $dest_ip = $json_d->{dest_ip};
108 | $dest_port = $json_d->{dest_port};
109 | $signature = $json_d->{alert}{signature};
110 | $sig_id = $json_d->{alert}{signature_id};
111 |
112 | # Do some quick sanity checks for the data comming in.
113 |
114 | if ( $src_ip eq "" ) {
115 | Log("Error. Soruce IP address is missing or couldn't be parsed.");
116 | exit(1);
117 | }
118 |
119 | if ( $dest_ip eq "" ) {
120 | Log("Error. Destination IP address is missing or couldn't be parsed.");
121 | exit(1);
122 | }
123 |
124 | if ( $signature eq "" ) {
125 | Log("Error. The 'siganture' missing or couldn't be parsed.");
126 | exit(1);
127 | }
128 |
129 | if ( $sig_id eq "" ) {
130 | Log("Error. The 'siganture_id' missing or couldn't be parsed.");
131 | exit(1);
132 | }
133 |
134 | Log("Parsed $src_ip -> $dest_ip");
135 |
136 | # Got good data. Try to figure out what "side" of the connection to send
137 | # the block request for, prioritizing blocking the src_ip
138 |
139 | if ( !$white_list->($src_ip) && !defined( $ignore_ports{$src_port} ) ) {
140 | $target = $src_ip;
141 | }
142 | elsif ( !$white_list->($dest_ip) && !defined( $ignore_ports{$dest_port} ) ) {
143 | $target = $dest_ip;
144 | }
145 |
146 | if ( !$target ) {
147 | Log("No usable firewall targets in $src_ip -> $dest_ip. Abort");
148 | exit(0);
149 | }
150 |
151 | Log("Writing $target for '$signature' [Sig ID: $sig_id] to the database");
152 |
153 | #############################################################################
154 | # Target goes into SQL
155 | #############################################################################
156 |
157 | $sql = "REPLACE INTO drop_list ( `timestamp`, `ip`, `sid` ) VALUES ( now(), ?, ? )";
158 | $sth = $dbh->prepare($sql);
159 | $sth->bind_param( 1, $target );
160 | $sth->bind_param( 2, $sig_id );
161 | $sth->execute || die "$DBI::errstr\n";
162 |
163 | }
164 |
165 | Log("Execution complete.");
166 |
167 | close(LOG);
168 | exit(0);
169 |
170 | #############################################################################
171 | # Signal_Handler - What to do on signals..
172 | #############################################################################
173 |
174 | sub Signal_Handler {
175 |
176 | close(LOG);
177 | exit(0);
178 |
179 | }
180 |
181 | #############################################################################
182 | # Log - Simple "logging" routine to include timestamp.
183 | #############################################################################
184 |
185 | sub Log {
186 |
187 | our $s;
188 | local ($s) = @_;
189 | my $dt = localtime();
190 | print LOG "[$dt] $s\n";
191 |
192 | }
193 |
--------------------------------------------------------------------------------
/tools/external/external-program-http-get:
--------------------------------------------------------------------------------
1 | #!/usr/bin/perl
2 |
3 | #############################################################################
4 | # external-program-http-get - Simple routine that takes Surcata/Sagan EVE
5 | # data, parses it and sends a "block" request to a remote URL via a HTTP
6 | # GET request.
7 | #
8 | # Champ Clark III (cclark@quadrantsec.com)
9 | # 2019/07/17
10 | #
11 | #############################################################################
12 |
13 | use JSON;
14 | use Net::Subnet qw(subnet_matcher);
15 | use LWP::UserAgent;
16 |
17 | use warnings;
18 | use strict;
19 |
20 | my $LOG_FILE = "/tmp/firewall.log"; # Log file
21 | my $block_url = "http://example.com/blockip="; # URL to send blocks to.
22 |
23 | #############################################################################
24 | # The $white_list are IP address that you do NOT to send blocks for. You'll
25 | # likely want to put your network (internal & external) IP address ranges
26 | # within this list!
27 | #############################################################################
28 |
29 | my $white_list = subnet_matcher qw(
30 | 10.0.0.0/8
31 | 192.168.0.0/16
32 | 172.16.0.0/12
33 | 169.254.0.0/16
34 | fd00::/8
35 | );
36 |
37 | #############################################################################
38 | # You shouldn't need to mess with anything else below this
39 | #############################################################################
40 |
41 | my $json_d;
42 | my $url;
43 | my $response;
44 | my $target;
45 | my $src_ip;
46 | my $dest_ip;
47 | my $signature;
48 | my $sig_id;
49 |
50 | my $ua = LWP::UserAgent->new;
51 |
52 | # Handle signals cleanly...
53 |
54 | $SIG{'INT'} = \&Signal_Handler;
55 | $SIG{'TERM'} = \&Signal_Handler;
56 | $SIG{'HUP'} = \&Signal_Handler;
57 |
58 | open(LOG, ">> $LOG_FILE") || die "Cannot open $LOG_FILE!\n";
59 |
60 | # Wait on stdin and collect the incoming json.
61 |
62 | while (<>) {
63 |
64 | Log("------------------------------------------------------------------------------");
65 | Log("** Received EVE: " . $_);
66 |
67 | $json_d = decode_json($_);
68 |
69 | $src_ip = $json_d->{src_ip};
70 | $dest_ip = $json_d->{dest_ip};
71 | $signature = $json_d->{alert}{signature};
72 | $sig_id = $json_d->{alert}{signature_id};
73 |
74 | # Do some quick sanity checks for the data comming in.
75 |
76 | if ( $src_ip eq "" )
77 | {
78 | Log("Error. Soruce IP address is missing or couldn't be parsed.");
79 | exit(1);
80 | }
81 |
82 | if ( $dest_ip eq "" )
83 | {
84 | Log("Error. Destination IP address is missing or couldn't be parsed.");
85 | exit(1);
86 | }
87 |
88 | if ( $signature eq "" )
89 | {
90 | Log("Error. The 'siganture' missing or couldn't be parsed.");
91 | exit(1);
92 | }
93 |
94 | if ( $sig_id eq "" )
95 | {
96 | Log("Error. The 'siganture_id' missing or couldn't be parsed.");
97 | exit(1);
98 | }
99 |
100 |
101 | Log("Parsed $src_ip -> $dest_ip");
102 |
103 | # Got good data. Try to figure out what "side" of the connection to send
104 | # the block request for.
105 |
106 | if ( !$white_list->($dest_ip) )
107 | {
108 | $target = $dest_ip;
109 | }
110 |
111 | if ( !$white_list->($src_ip) )
112 | {
113 | $target = $src_ip;
114 | }
115 |
116 | if ( !$target )
117 | {
118 | Log("No usable firewall targets in $src_ip -> $dest_ip. Abort");
119 | exit(0);
120 | }
121 |
122 | # Send block request!
123 |
124 | Log("Target to firewall is $target for '$signature' [Sig ID: $sig_id]");
125 |
126 | $url = $block_url . $target;
127 |
128 | Log("Sending $url");
129 |
130 | $ua->timeout(60);
131 | $ua->agent("Meer Blocking Agent");
132 | $response = $ua->get($url);
133 |
134 | # Check block request response.
135 |
136 | if ( $response->is_success )
137 | {
138 | Log("Successfully send to $url [" . $response->status_line . "]");
139 | } else {
140 | Log("Failed to send to $url [" . $response->status_line . "]");
141 | }
142 |
143 | }
144 |
145 | Log("Execution complete.");
146 |
147 | close(LOG);
148 | exit(0);
149 |
150 | #############################################################################
151 | # Signal_Handler - What to do on signals..
152 | #############################################################################
153 |
154 | sub Signal_Handler {
155 |
156 | close(LOG);
157 | exit(0);
158 |
159 | }
160 |
161 | #############################################################################
162 | # Log - Simple "logging" routine to include timestamp.
163 | #############################################################################
164 |
165 | sub Log {
166 |
167 | our $s;
168 | local($s) = @_;
169 | my $dt = localtime();
170 | print LOG "[$dt] $s\n";
171 |
172 | }
173 |
174 |
--------------------------------------------------------------------------------
/tools/external/external-program-iptables:
--------------------------------------------------------------------------------
1 | #!/usr/bin/perl
2 |
3 | #############################################################################
4 | # external-program-iptables - Simple routine that takes Surcata/Sagan EVE
5 | # data, parses it and firewalls via iptables.
6 | #
7 | # In order for this routine to work, the user will need to be able to run
8 | # iptables as "root". To do this, we add the following lines to your
9 | # /etc/sudoers via the "visudo" command.
10 | #
11 | # suricata ALL=(ALL) NOPASSWD: /sbin/iptables -A INPUT -s * -j DROP,/sbin/iptables -A INPUT -d * -j DROP,/sbin/iptables -A FORWARD -s * -j DROP,/sbin/iptables -A FORWARD -d * -j DROP
12 |
13 | #
14 | # (Replaces 'suricata' with whatever you run Suricata/Sagan as)
15 | #
16 | # Champ Clark III (cclark@quadrantsec.com)
17 | # 2019/07/20
18 | #
19 | #############################################################################
20 |
21 | use JSON;
22 | use Net::Subnet qw(subnet_matcher);
23 |
24 | use warnings;
25 | use strict;
26 |
27 | my $LOG_FILE = "/tmp/firewall.log"; # Log file
28 | my $IPTABLES = "/usr/bin/sudo /sbin/iptables";
29 |
30 | #############################################################################
31 | # The $white_list are IP address that you do NOT to send blocks for. You'll
32 | # likely want to put your network (internal & external) IP address ranges
33 | # within this list!
34 | #############################################################################
35 |
36 | my $white_list = subnet_matcher qw(
37 | 10.0.0.0/8
38 | 192.168.0.0/16
39 | 172.16.0.0/12
40 | 169.254.0.0/16
41 | fd00::/8
42 | );
43 |
44 | #############################################################################
45 | # You shouldn't need to mess with anything else below this
46 | #############################################################################
47 |
48 | my $json_d;
49 | my $cmd;
50 | my $target;
51 | my $src_ip;
52 | my $dest_ip;
53 | my $signature;
54 | my $sig_id;
55 | my $direction;
56 |
57 | # Handle signals cleanly...
58 |
59 | $SIG{'INT'} = \&Signal_Handler;
60 | $SIG{'TERM'} = \&Signal_Handler;
61 | $SIG{'HUP'} = \&Signal_Handler;
62 |
63 | open(LOG, ">> $LOG_FILE") || die "Cannot open $LOG_FILE!\n";
64 |
65 | # Wait on stdin and collect the incoming json.
66 |
67 | while (<>) {
68 |
69 | Log("------------------------------------------------------------------------------");
70 | Log("** Received EVE: " . $_);
71 |
72 | $json_d = decode_json($_);
73 |
74 | $src_ip = $json_d->{src_ip};
75 | $dest_ip = $json_d->{dest_ip};
76 | $signature = $json_d->{alert}{signature};
77 | $sig_id = $json_d->{alert}{signature_id};
78 |
79 | # Do some quick sanity checks for the data comming in.
80 |
81 | if ( $src_ip eq "" )
82 | {
83 | Log("Error. Soruce IP address is missing or couldn't be parsed.");
84 | exit(1);
85 | }
86 |
87 | if ( $dest_ip eq "" )
88 | {
89 | Log("Error. Destination IP address is missing or couldn't be parsed.");
90 | exit(1);
91 | }
92 |
93 | if ( $signature eq "" )
94 | {
95 | Log("Error. The 'siganture' missing or couldn't be parsed.");
96 | exit(1);
97 | }
98 |
99 | if ( $sig_id eq "" )
100 | {
101 | Log("Error. The 'siganture_id' missing or couldn't be parsed.");
102 | exit(1);
103 | }
104 |
105 |
106 | Log("Parsed $src_ip -> $dest_ip");
107 |
108 | # Got good data. Try to figure out what "side" of the connection to send
109 | # the block request for.
110 |
111 | if ( !$white_list->($dest_ip) )
112 | {
113 | $target = $dest_ip;
114 | $direction = "-d";
115 | }
116 |
117 | if ( !$white_list->($src_ip) )
118 | {
119 | $target = $src_ip;
120 | $direction = "-s";
121 | }
122 |
123 | if ( !$target )
124 | {
125 | Log("No usable firewall targets in $src_ip -> $dest_ip. Abort");
126 | exit(0);
127 | }
128 |
129 | # Send block request!
130 |
131 | Log("Target to firewall is $target for '$signature' [Sig ID: $sig_id]");
132 |
133 | $cmd = "$IPTABLES -A FORWARD $direction $target -j DROP; $IPTABLES -A INPUT $direction $target -j DROP";
134 |
135 | Log("Executing command: $cmd");
136 | system($cmd);
137 | Log("System cal completed.");
138 |
139 | }
140 |
141 | Log("Execution complete.");
142 |
143 | close(LOG);
144 | exit(0);
145 |
146 | #############################################################################
147 | # Signal_Handler - What to do on signals..
148 | #############################################################################
149 |
150 | sub Signal_Handler {
151 |
152 | close(LOG);
153 | exit(0);
154 |
155 | }
156 |
157 | #############################################################################
158 | # Log - Simple "logging" routine to include timestamp.
159 | #############################################################################
160 |
161 | sub Log {
162 |
163 | our $s;
164 | local($s) = @_;
165 | my $dt = localtime();
166 | print LOG "[$dt] $s\n";
167 |
168 | }
169 |
170 |
--------------------------------------------------------------------------------
/tools/reference_handler/README.md:
--------------------------------------------------------------------------------
1 | # Meer - Reference_Handlers
2 |
3 | This takes "reference" data from Suricata/Sagan/Snort rules and populates a centralized database
4 | with that data. If you have more than one Suricata/Snort/Sagan database, you'll likely want
5 | to use this than the "traditional" reference system.
6 |
7 |
--------------------------------------------------------------------------------
/tools/reference_handler/reference_data.sql:
--------------------------------------------------------------------------------
1 | --
2 | -- Table structure for table `reference_data`
3 | --
4 |
5 | DROP TABLE IF EXISTS `reference_data`;
6 |
7 | CREATE TABLE `reference_data` (
8 | `sid` bigint(20) NOT NULL,
9 | `ref_type` varchar(10) NOT NULL,
10 | `ref_url` varchar(255) NOT NULL,
11 | PRIMARY KEY (`sid`,`ref_type`,`ref_url`)
12 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
13 |
--------------------------------------------------------------------------------
/tools/reference_handler/reference_sources.conf:
--------------------------------------------------------------------------------
1 | # List of references used by Snort/Sagan/Suricata Rules.
2 | #
3 | url|http://
4 | bugtraq|http://www.securityfocus.com/bid/
5 | nessus|https://www.tenable.com/plugins/index.php?view=single&id=
6 | cve|http://www.cve.mitre.org/cgi-bin/cvename.cgi?name=
7 | md5|http://virustotalorsomething
8 | quadrant|http://wiki.quadrantsec.com/bin/view/Main/
9 | quadrantsec|http://wiki.quadrantsec.com/bin/view/Main/
10 | arachnids|http://ifolderlinks.ru/404/
11 | mcafee|https://home.mcafee.com/virusinfo/virusprofile.aspx?key=
12 | bid|http://www.securityfocus.com/bid/
13 | secunia|http://www.secunia.com/advisories/
14 | et|http://doc.emergingthreats.net/
15 | etpro|http://doc.emergingthreatpro.com/
16 | #telus|http://
17 | osvb|http://osvdb.org/show/osvdb/
18 | threatexpert|http://www.threatexpert.com/report.aspx?md5=
19 | exploitdb|http://www.exploit-db.com/exploits/
20 | openpacket|https://www.openpacket.org/capture/grab/
21 | securitytracker|http://securitytracker.com/id?
22 | xforce|http://xforce.iss.net/xforce/xfdb/
23 |
--------------------------------------------------------------------------------