]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
doc: add a lua support top level section
authorEric Leblond <eric@regit.org>
Fri, 16 Feb 2018 07:52:51 +0000 (08:52 +0100)
committerVictor Julien <victor@inliniac.net>
Tue, 3 Apr 2018 08:07:44 +0000 (10:07 +0200)
Both output and signature are using lua. So lua functions should
be displayed in a single section.

doc/userguide/index.rst
doc/userguide/lua/index.rst [new file with mode: 0644]
doc/userguide/lua/lua-functions.rst [new file with mode: 0644]
doc/userguide/lua/lua-usage.rst [new file with mode: 0644]
doc/userguide/output/lua-output.rst
doc/userguide/rules/rule-lua-scripting.rst

index 900c6e7fb6b7d258231b426ab1df2db5b3a5f03c..e3b337d84eac1e292eb720cbe1e2e35abfbae1b3 100644 (file)
@@ -17,6 +17,7 @@ Suricata User Guide
    initscripts
    setting-up-ipsinline-for-linux
    output/index.rst
+   lua/index.rst
    file-extraction/file-extraction.rst
    public-data-sets
    capture-hardware/index.rst
diff --git a/doc/userguide/lua/index.rst b/doc/userguide/lua/index.rst
new file mode 100644 (file)
index 0000000..d6bbf70
--- /dev/null
@@ -0,0 +1,7 @@
+Lua support
+===========
+
+.. toctree::
+
+   lua-usage
+   lua-functions
diff --git a/doc/userguide/lua/lua-functions.rst b/doc/userguide/lua/lua-functions.rst
new file mode 100644 (file)
index 0000000..856512a
--- /dev/null
@@ -0,0 +1,773 @@
+.. _lua-functions:
+
+Lua functions
+=============
+
+packet
+------
+
+Initialize with:
+
+::
+
+  function init (args)
+      local needs = {}
+      needs["type"] = "packet"
+      return needs
+  end
+
+SCPacketTimestamp
+~~~~~~~~~~~~~~~~~
+
+Get packets timestamp as 2 numbers: seconds & microseconds elapsed since
+1970-01-01 00:00:00 UTC.
+
+::
+
+  function log(args)
+      local sec, usec = SCPacketTimestamp()
+  end
+
+SCPacketTimeString
+~~~~~~~~~~~~~~~~~~
+
+Add SCPacketTimeString to get the packets time string in the format:
+11/24/2009-18:57:25.179869
+
+::
+
+  function log(args)
+      ts = SCPacketTimeString()
+
+SCPacketTuple
+~~~~~~~~~~~~~
+
+::
+
+  ipver, srcip, dstip, proto, sp, dp = SCPacketTuple()
+
+SCPacketPayload
+~~~~~~~~~~~~~~~
+
+::
+
+  p = SCPacketPayload()
+
+flow
+----
+
+::
+
+  function init (args)
+      local needs = {}
+      needs["type"] = "flow"
+      return needs
+  end
+
+SCFlowTimestamps
+~~~~~~~~~~~~~~~~
+
+Get timestamps (seconds and microseconds) of the first and the last packet from
+the flow.
+
+::
+
+  startts, lastts = SCFlowTimestamps()
+  startts_s, lastts_s, startts_us, lastts_us = SCFlowTimestamps()
+
+SCFlowTimeString
+~~~~~~~~~~~~~~~~
+
+::
+
+  startts = SCFlowTimeString()
+
+SCFlowTuple
+~~~~~~~~~~~
+
+::
+
+  ipver, srcip, dstip, proto, sp, dp = SCFlowTuple()
+
+SCFlowAppLayerProto
+~~~~~~~~~~~~~~~~~~~
+
+Get alprotos as string from the flow. If a alproto is not (yet) known, it
+returns "unknown".
+
+Example:
+
+::
+
+  function log(args)
+      alproto = SCFlowAppLayerProto()
+      if alproto ~= nil then
+          print (alproto)
+      end
+  end
+
+Returns 5 values: <alproto> <alproto_ts> <alproto_tc> <alproto_orig> <alproto_expect>
+
+Orig and expect are used when changing and upgrading protocols. In a SMTP STARTTLS
+case, orig would normally be set to "smtp" and expect to "tls".
+
+
+SCFlowHasAlerts
+~~~~~~~~~~~~~~~
+
+Returns true if flow has alerts.
+
+Example:
+
+::
+
+  function log(args)
+      has_alerts = SCFlowHasAlerts()
+      if has_alerts then
+          -- do something
+      end
+  end
+
+SCFlowStats
+~~~~~~~~~~~
+
+Gets the packet and byte counts per flow.
+
+::
+
+  tscnt, tsbytes, tccnt, tcbytes = SCFlowStats()
+
+SCFlowId
+~~~~~~~~
+
+Gets the flow id.
+
+::
+
+    id = SCFlowId()
+
+Note that simply printing 'id' will likely result in printing a scientific
+notation. To avoid that, simply do:
+
+::
+
+    id = SCFlowId()
+    idstr = string.format("%.0f",id)
+    print ("Flow ID: " .. idstr .. "\n")
+
+
+http
+----
+
+Init with:
+
+::
+
+  function init (args)
+      local needs = {}
+      needs["protocol"] = "http"
+      return needs
+  end
+
+HttpGetRequestBody and HttpGetResponseBody.
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Make normalized body data available to the script through
+HttpGetRequestBody and HttpGetResponseBody.
+
+There no guarantees that all of the body will be availble.
+
+Example:
+
+::
+
+  function log(args)
+      a, o, e = HttpGetResponseBody();
+      --print("offset " .. o .. " end " .. e)
+      for n, v in ipairs(a) do
+          print(v)
+      end
+  end
+
+HttpGetRequestHost
+~~~~~~~~~~~~~~~~~~
+
+Get the host from libhtp's tx->request_hostname, which can either be
+the host portion of the url or the host portion of the Host header.
+
+Example:
+
+::
+
+  http_host = HttpGetRequestHost()
+  if http_host == nil then
+      http_host = "<hostname unknown>"
+  end
+
+HttpGetRequestHeader
+~~~~~~~~~~~~~~~~~~~~
+
+::
+
+  http_ua = HttpGetRequestHeader("User-Agent")
+  if http_ua == nil then
+      http_ua = "<useragent unknown>"
+  end
+
+HttpGetResponseHeader
+~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+  server = HttpGetResponseHeader("Server");
+  print ("Server: " .. server);
+
+HttpGetRequestLine
+~~~~~~~~~~~~~~~~~~
+
+::
+
+  rl = HttpGetRequestLine();
+  print ("Request Line: " .. rl);
+
+HttpGetResponseLine
+~~~~~~~~~~~~~~~~~~~
+
+::
+
+  rsl = HttpGetResponseLine();
+  print ("Response Line: " .. rsl);
+
+HttpGetRawRequestHeaders
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+  rh = HttpGetRawRequestHeaders();
+  print ("Raw Request Headers: " .. rh);
+
+HttpGetRawResponseHeaders
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+  rh = HttpGetRawResponseHeaders();
+  print ("Raw Response Headers: " .. rh);
+
+HttpGetRequestUriRaw
+~~~~~~~~~~~~~~~~~~~~
+
+::
+
+  http_uri = HttpGetRequestUriRaw()
+  if http_uri == nil then
+      http_uri = "<unknown>"
+  end
+
+HttpGetRequestUriNormalized
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+  http_uri = HttpGetRequestUriNormalized()
+  if http_uri == nil then
+      http_uri = "<unknown>"
+  end
+
+HttpGetRequestHeaders
+~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+  a = HttpGetRequestHeaders();
+  for n, v in pairs(a) do
+      print(n,v)
+  end
+
+HttpGetResponseHeaders
+~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+  a = HttpGetResponseHeaders();
+  for n, v in pairs(a) do
+      print(n,v)
+  end
+
+DNS
+---
+
+DnsGetQueries
+~~~~~~~~~~~~~
+
+::
+
+  dns_query = DnsGetQueries();
+  if dns_query ~= nil then
+      for n, t in pairs(dns_query) do
+          rrname = t["rrname"]
+          rrtype = t["type"]
+
+          print ("QUERY: " .. ts .. " " .. rrname .. " [**] " .. rrtype .. " [**] " ..
+                 "TODO" .. " [**] " .. srcip .. ":" .. sp .. " -> " ..
+                 dstip .. ":" .. dp)
+      end
+  end
+
+returns a table of tables
+
+DnsGetAnswers
+~~~~~~~~~~~~~
+
+::
+
+  dns_answers = DnsGetAnswers();
+  if dns_answers ~= nil then
+      for n, t in pairs(dns_answers) do
+          rrname = t["rrname"]
+          rrtype = t["type"]
+          ttl = t["ttl"]
+
+          print ("ANSWER: " .. ts .. " " .. rrname .. " [**] " .. rrtype .. " [**] " ..
+                 ttl .. " [**] " .. srcip .. ":" .. sp .. " -> " ..
+                 dstip .. ":" .. dp)
+      end
+  end
+
+returns a table of tables
+
+DnsGetAuthorities
+~~~~~~~~~~~~~~~~~
+
+::
+
+  dns_auth = DnsGetAuthorities();
+  if dns_auth ~= nil then
+      for n, t in pairs(dns_auth) do
+          rrname = t["rrname"]
+          rrtype = t["type"]
+          ttl = t["ttl"]
+
+          print ("AUTHORITY: " .. ts .. " " .. rrname .. " [**] " .. rrtype .. " [**] " ..
+                 ttl .. " [**] " .. srcip .. ":" .. sp .. " -> " ..
+                 dstip .. ":" .. dp)
+      end
+  end
+
+returns a table of tables
+
+DnsGetRcode
+~~~~~~~~~~~
+
+::
+
+  rcode = DnsGetRcode();
+  if rcode == nil then
+      return 0
+  end
+  print (rcode)
+
+returns a lua string with the error message, or nil
+
+DnsGetRecursionDesired
+~~~~~~~~~~~~~~~~~~~~~~
+
+::
+
+  if DnsGetRecursionDesired() == true then
+      print ("RECURSION DESIRED")
+  end
+
+returns a bool
+
+TLS
+---
+
+Initialize with:
+
+::
+
+  function init (args)
+      local needs = {}
+      needs["protocol"] = "tls"
+      return needs
+  end
+
+TlsGetCertInfo
+~~~~~~~~~~~~~~
+
+Make certificate information available to the script through TlsGetCertInfo.
+
+Example:
+
+::
+
+  function log (args)
+      version, subject, issuer, fingerprint = TlsGetCertInfo()
+      if version == nil then
+          return 0
+      end
+  end
+
+TlsGetCertChain
+~~~~~~~~~~~~~~~
+
+Make certificate chain available to the script through TlsGetCertChain.
+
+The output is an array of certificate with each certificate being an hash
+with `data` and `length` keys.
+
+Example:
+
+::
+
+  -- Use debian lua-luaossl coming from https://github.com/wahern/luaossl
+  local x509 = require"openssl.x509"
+
+     chain = TlsGetCertChain()
+     for k, v in pairs(chain) do
+        -- v.length is length of data
+        -- v.data is raw binary data of certificate
+        cert = x509.new(v["data"], "DER")
+        print(cert:text() .. "\n")
+     end
+
+
+TlsGetCertNotAfter
+~~~~~~~~~~~~~~~~~~
+
+Get the Unix timestamp of end of validity of certificate.
+
+Example:
+
+::
+
+  function log (args)
+      notafter = TlsGetCertNotAfter()
+      if notafter < os.time() then
+          -- expired certificate
+      end
+  end
+
+TlsGetCertNotBefore
+~~~~~~~~~~~~~~~~~~~
+
+Get the Unix timestamp of beginning of validity of certificate.
+
+Example:
+
+::
+
+  function log (args)
+      notbefore = TlsGetCertNotBefore()
+      if notbefore > os.time() then
+          -- not yet valid certificate
+      end
+  end
+
+TlsGetCertSerial
+~~~~~~~~~~~~~~~~
+
+Get TLS certificate serial number through TlsGetCertSerial.
+
+Example:
+
+::
+
+  function log (args)
+      serial = TlsGetCertSerial()
+      if serial then
+          -- do something
+      end
+  end
+
+TlsGetSNI
+~~~~~~~~~
+
+Get the Server name Indication from a TLS connection.
+
+Example:
+
+::
+
+  function log (args)
+      asked_domain = TlsGetSNI()
+      if string.find(asked_domain, "badguys") then
+          -- ok connection to bad guys let's do someting
+      end
+  end
+
+
+JA3
+---
+
+JA3 must be enabled in the Suricata config file (set 'app-layer.protocols.tls.ja3-fingerprints' to 'yes').
+
+Initialize with:
+
+::
+
+  function init (args)
+      local needs = {}
+      needs["protocol"] = "tls"
+      return needs
+  end
+
+Ja3GetHash
+~~~~~~~~~~
+
+Get the JA3 hash (md5sum of JA3 string) through Ja3GetHash.
+
+Example:
+
+::
+
+  function log (args)
+      hash = Ja3GetHash()
+      if hash == nil then
+          return
+      end
+  end
+
+Ja3GetString
+~~~~~~~~~~~~
+
+Get the JA3 string through Ja3GetString.
+
+Example:
+
+::
+
+  function log (args)
+      str = Ja3GetString()
+      if str == nil then
+          return
+      end
+  end
+
+
+SSH
+---
+
+Initialize with:
+
+::
+
+
+  function init (args)
+      local needs = {}
+      needs["protocol"] = "ssh"
+      return needs
+  end
+
+SshGetServerProtoVersion
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+Get SSH protocol version used by the server through SshGetServerProtoVersion.
+
+Example:
+
+::
+
+  function log (args)
+      version = SshGetServerProtoVersion()
+      if version == nil then
+          return 0
+      end
+  end
+
+SshGetServerSoftwareVersion
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Get SSH software used by the server through SshGetServerSoftwareVersion.
+
+Example:
+
+::
+
+
+  function log (args)
+      software = SshGetServerSoftwareVersion()
+      if software == nil then
+          return 0
+      end
+  end
+
+SshGetClientProtoVersion
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+Get SSH protocol version used by the client through SshGetClientProtoVersion.
+
+Example:
+
+::
+
+  function log (args)
+      version = SshGetClientProtoVersion()
+      if version == nil then
+          return 0
+      end
+  end
+
+SshGetClientSoftwareVersion
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Get SSH software used by the client through SshGetClientSoftwareVersion.
+
+Example:
+
+::
+
+  function log (args)
+      software = SshGetClientSoftwareVersion()
+      if software == nil then
+          return 0
+      end
+  end
+
+Files
+-----
+
+To use the file logging API, the script's init() function needs to look like:
+
+::
+
+  function init (args)
+      local needs = {}
+      needs['type'] = 'file'
+      return needs
+  end
+
+SCFileInfo
+~~~~~~~~~~
+
+::
+
+
+  fileid, txid, name, size, magic, md5 = SCFileInfo()
+
+returns fileid (number), txid (number), name (string), size (number),
+magic (string), md5 in hex (string)
+
+SCFileState
+~~~~~~~~~~~
+
+::
+
+  state, stored = SCFileState()
+
+returns state (string), stored (bool)
+
+Alerts
+------
+
+Alerts are a subset of the 'packet' logger:
+
+::
+
+  function init (args)
+      local needs = {}
+      needs["type"] = "packet"
+      needs["filter"] = "alerts"
+      return needs
+  end
+
+SCRuleIds
+~~~~~~~~~
+
+::
+
+  sid, rev, gid = SCRuleIds()
+
+SCRuleMsg
+~~~~~~~~~
+
+::
+
+  msg = SCRuleMsg()
+
+SCRuleClass
+~~~~~~~~~~~
+
+::
+
+
+  class, prio = SCRuleClass()
+
+Streaming Data
+--------------
+
+Streaming data can currently log out reassembled TCP data and
+normalized HTTP data. The script will be invoked for each consecutive
+data chunk.
+
+In case of TCP reassembled data, all possible overlaps are removed
+according to the host OS settings.
+
+::
+
+  function init (args)
+      local needs = {}
+      needs["type"] = "streaming"
+      needs["filter"] = "tcp"
+      return needs
+  end
+
+In case of HTTP body data, the bodies are unzipped and dechunked if applicable.
+
+::
+
+  function init (args)
+      local needs = {}
+      needs["type"] = "streaming"
+      needs["protocol"] = "http"
+      return needs
+  end
+
+SCStreamingBuffer
+~~~~~~~~~~~~~~~~~
+
+::
+
+  function log(args)
+      data = SCStreamingBuffer()
+      hex_dump(data)
+  end
+
+Misc
+----
+
+SCThreadInfo
+~~~~~~~~~~~~
+
+::
+
+  tid, tname, tgroup = SCThreadInfo()
+
+It gives: tid (integer), tname (string), tgroup (string)
+
+SCLogError, SCLogWarning, SCLogNotice, SCLogInfo, SCLogDebug
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Print a message. It will go into the outputs defined in the
+yaml. Whether it will be printed depends on the log level.
+
+Example:
+
+::
+
+  SCLogError("some error message")
+
+SCLogPath
+~~~~~~~~~
+
+Expose the log path.
+
+::
+
+
+  name = "fast_lua.log"
+  function setup (args)
+      filename = SCLogPath() .. "/" .. name
+      file = assert(io.open(filename, "a"))
+  end
diff --git a/doc/userguide/lua/lua-usage.rst b/doc/userguide/lua/lua-usage.rst
new file mode 100644 (file)
index 0000000..5c3c8ad
--- /dev/null
@@ -0,0 +1,17 @@
+Lua usage in Suricata
+=====================
+
+Lua can be used in two components of Suricata. First one is output an the second one in signature.
+
+Both features are using a list of functions to access to data extracted by Suricata. You can get the
+list of functions in the :ref:`lua-functions` page.
+
+Lua output
+----------
+
+Lua can be used to write arbitrary output. See :ref:`lua-output` for more information.
+
+Lua signature
+-------------
+
+Lua script can be used as a filter in signatures. See :ref:`lua-scripting` for more information.
index 6d4414eaf56dbe2878b3c7d0e665a165a8546aed..fef235c19977a7763cfc29417840c3f1bb62ec77 100644 (file)
@@ -1,3 +1,5 @@
+.. _lua-output:
+
 Lua Output
 ==========
 
@@ -93,771 +95,7 @@ The scripts-dir option is optional. It makes Suricata load the scripts
 from this directory. Otherwise scripts will be loaded from the current
 workdir.
 
-packet
-------
-
-Initialize with:
-
-::
-
-  function init (args)
-      local needs = {}
-      needs["type"] = "packet"
-      return needs
-  end
-
-SCPacketTimestamp
-~~~~~~~~~~~~~~~~~
-
-Get packets timestamp as 2 numbers: seconds & microseconds elapsed since
-1970-01-01 00:00:00 UTC.
-
-::
-
-  function log(args)
-      local sec, usec = SCPacketTimestamp()
-  end
-
-SCPacketTimeString
-~~~~~~~~~~~~~~~~~~
-
-Add SCPacketTimeString to get the packets time string in the format:
-11/24/2009-18:57:25.179869
-
-::
-
-  function log(args)
-      timestring = SCPacketTimeString()
-  end
-
-SCPacketTuple
-~~~~~~~~~~~~~
-
-::
-
-  ip_version, src_ip, dst_ip, protocol, src_port, dst_port = SCPacketTuple()
-
-SCPacketPayload
-~~~~~~~~~~~~~~~
-
-::
-
-  payload = SCPacketPayload()
-
-flow
-----
-
-::
-
-  function init (args)
-      local needs = {}
-      needs["type"] = "flow"
-      return needs
-  end
-
-SCFlowTimestamps
-~~~~~~~~~~~~~~~~
-
-Get timestamps (seconds and microseconds) of the first and the last packet from
-the flow.
-
-::
-
-  startts, lastts = SCFlowTimestamps()
-  startts_s, lastts_s, startts_us, lastts_us = SCFlowTimestamps()
-
-SCFlowTimeString
-~~~~~~~~~~~~~~~~
-
-::
-
-  startts = SCFlowTimeString()
-
-SCFlowTuple
-~~~~~~~~~~~
-
-::
-
-  ip_version, src_ip, dst_ip, protocol, src_port, dst_port = SCFlowTuple()
-
-SCFlowAppLayerProto
-~~~~~~~~~~~~~~~~~~~
-
-Get alprotos as string from the flow. If a alproto is not (yet) known, it
-returns "unknown".
-
-Example:
-
-::
-
-  function log(args)
-      alproto = SCFlowAppLayerProto()
-      if alproto ~= nil then
-          print (alproto)
-      end
-  end
-
-Returns 5 values: <alproto> <alproto_ts> <alproto_tc> <alproto_orig> <alproto_expect>
-
-Orig and expect are used when changing and upgrading protocols. In a SMTP STARTTLS
-case, orig would normally be set to "smtp" and expect to "tls".
-
-
-SCFlowHasAlerts
-~~~~~~~~~~~~~~~
-
-Returns true if flow has alerts.
-
-Example:
-
-::
-
-  function log(args)
-      has_alerts = SCFlowHasAlerts()
-      if has_alerts then
-          -- do something
-      end
-  end
-
-SCFlowStats
-~~~~~~~~~~~
-
-Gets the packet and byte counts per flow.
-
-::
-
-  tscnt, tsbytes, tccnt, tcbytes = SCFlowStats()
-
-SCFlowId
-~~~~~~~~
-
-Gets the flow id.
-
-::
-
-    id = SCFlowId()
-
-Note that simply printing 'id' will likely result in printing a scientific
-notation. To avoid that, simply do:
-
-::
-
-    id = SCFlowId()
-    idstr = string.format("%.0f",id)
-    print ("Flow ID: " .. idstr .. "\n")
-
-
-http
-----
-
-Init with:
-
-::
-
-  function init (args)
-      local needs = {}
-      needs["protocol"] = "http"
-      return needs
-  end
-
-HttpGetRequestBody and HttpGetResponseBody.
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Make normalized body data available to the script through
-HttpGetRequestBody and HttpGetResponseBody.
-
-There no guarantees that all of the body will be availble.
-
-Example:
-
-::
-
-  function log(args)
-      a, o, e = HttpGetResponseBody();
-      --print("offset " .. o .. " end " .. e)
-      for n, v in ipairs(a) do
-          print(v)
-      end
-  end
-
-HttpGetRequestHost
-~~~~~~~~~~~~~~~~~~
-
-Get the host from libhtp's tx->request_hostname, which can either be
-the host portion of the url or the host portion of the Host header.
-
-Example:
-
-::
-
-  http_host = HttpGetRequestHost()
-  if http_host == nil then
-      http_host = "<hostname unknown>"
-  end
-
-HttpGetRequestHeader
-~~~~~~~~~~~~~~~~~~~~
-
-::
-
-  http_ua = HttpGetRequestHeader("User-Agent")
-  if http_ua == nil then
-      http_ua = "<useragent unknown>"
-  end
-
-HttpGetResponseHeader
-~~~~~~~~~~~~~~~~~~~~~
-
-::
-
-  server = HttpGetResponseHeader("Server");
-  print ("Server: " .. server);
-
-HttpGetRequestLine
-~~~~~~~~~~~~~~~~~~
-
-::
-
-  rl = HttpGetRequestLine();
-  print ("Request Line: " .. rl);
-
-HttpGetResponseLine
-~~~~~~~~~~~~~~~~~~~
-
-::
-
-  rsl = HttpGetResponseLine();
-  print ("Response Line: " .. rsl);
-
-HttpGetRawRequestHeaders
-~~~~~~~~~~~~~~~~~~~~~~~~
-
-::
-
-  rh = HttpGetRawRequestHeaders();
-  print ("Raw Request Headers: " .. rh);
-
-HttpGetRawResponseHeaders
-~~~~~~~~~~~~~~~~~~~~~~~~~
-
-::
-
-  rh = HttpGetRawResponseHeaders();
-  print ("Raw Response Headers: " .. rh);
-
-HttpGetRequestUriRaw
-~~~~~~~~~~~~~~~~~~~~
-
-::
-
-  http_uri = HttpGetRequestUriRaw()
-  if http_uri == nil then
-      http_uri = "<unknown>"
-  end
-
-HttpGetRequestUriNormalized
-~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-::
-
-  http_uri = HttpGetRequestUriNormalized()
-  if http_uri == nil then
-      http_uri = "<unknown>"
-  end
-
-HttpGetRequestHeaders
-~~~~~~~~~~~~~~~~~~~~~
-
-::
-
-  a = HttpGetRequestHeaders();
-  for n, v in pairs(a) do
-      print(n,v)
-  end
-
-HttpGetResponseHeaders
-~~~~~~~~~~~~~~~~~~~~~~
-
-::
-
-  a = HttpGetResponseHeaders();
-  for n, v in pairs(a) do
-      print(n,v)
-  end
-
-DNS
----
-
-DnsGetQueries
-~~~~~~~~~~~~~
-
-::
-
-  dns_query = DnsGetQueries();
-  if dns_query ~= nil then
-      for n, t in pairs(dns_query) do
-          rrname = t["rrname"]
-          rrtype = t["type"]
-
-          print ("QUERY: " .. ts .. " " .. rrname .. " [**] " .. rrtype .. " [**] " ..
-                 "TODO" .. " [**] " .. src_ip .. ":" .. src_port .. " -> " ..
-                 dst_ip .. ":" .. dst_port)
-      end
-  end
-
-returns a table of tables
-
-DnsGetAnswers
-~~~~~~~~~~~~~
-
-::
-
-  dns_answers = DnsGetAnswers();
-  if dns_answers ~= nil then
-      for n, t in pairs(dns_answers) do
-          rrname = t["rrname"]
-          rrtype = t["type"]
-          ttl = t["ttl"]
-
-          print ("ANSWER: " .. ts .. " " .. rrname .. " [**] " .. rrtype .. " [**] " ..
-                 ttl .. " [**] " .. src_ip .. ":" .. src_port .. " -> " ..
-                 dst_ip .. ":" .. dst_port)
-      end
-  end
-
-returns a table of tables
-
-DnsGetAuthorities
-~~~~~~~~~~~~~~~~~
-
-::
-
-  dns_auth = DnsGetAuthorities();
-  if dns_auth ~= nil then
-      for n, t in pairs(dns_auth) do
-          rrname = t["rrname"]
-          rrtype = t["type"]
-          ttl = t["ttl"]
-
-          print ("AUTHORITY: " .. ts .. " " .. rrname .. " [**] " .. rrtype .. " [**] " ..
-                 ttl .. " [**] " .. src_ip .. ":" .. src_port .. " -> " ..
-                 dst_ip .. ":" .. dst_port)
-      end
-  end
-
-returns a table of tables
-
-DnsGetRcode
-~~~~~~~~~~~
-
-::
-
-  rcode = DnsGetRcode();
-  if rcode == nil then
-      return 0
-  end
-  print (rcode)
-
-returns a lua string with the error message, or nil
-
-DnsGetRecursionDesired
-~~~~~~~~~~~~~~~~~~~~~~
-
-::
-
-  if DnsGetRecursionDesired() == true then
-      print ("RECURSION DESIRED")
-  end
-
-returns a bool
-
-TLS
----
-
-Initialize with:
-
-::
-
-  function init (args)
-      local needs = {}
-      needs["protocol"] = "tls"
-      return needs
-  end
-
-TlsGetCertInfo
-~~~~~~~~~~~~~~
-
-Make certificate information available to the script through TlsGetCertInfo.
-
-Example:
-
-::
-
-  function log (args)
-      version, subject, issuer, fingerprint = TlsGetCertInfo()
-      if version == nil then
-          return 0
-      end
-  end
-
-TlsGetCertChain
-~~~~~~~~~~~~~~~
-
-Make certificate chain available to the script through TlsGetCertChain.
-
-The output is an array of certificate with each certificate being an hash
-with `data` and `length` keys.
-
-Example:
-
-::
-
-  -- Use debian lua-luaossl coming from https://github.com/wahern/luaossl
-  local x509 = require"openssl.x509"
-
-     chain = TlsGetCertChain()
-     for k, v in pairs(chain) do
-        -- v.length is length of data
-        -- v.data is raw binary data of certificate
-        cert = x509.new(v["data"], "DER")
-        print(cert:text() .. "\n")
-     end
-
-
-TlsGetCertNotAfter
-~~~~~~~~~~~~~~~~~~
-
-Get the Unix timestamp of end of validity of certificate.
-
-Example:
-
-::
-
-  function log (args)
-      notafter = TlsGetCertNotAfter()
-      if notafter < os.time() then
-          -- expired certificate
-      end
-  end
-
-TlsGetCertNotBefore
-~~~~~~~~~~~~~~~~~~~
-
-Get the Unix timestamp of beginning of validity of certificate.
-
-Example:
-
-::
-
-  function log (args)
-      notbefore = TlsGetCertNotBefore()
-      if notbefore > os.time() then
-          -- not yet valid certificate
-      end
-  end
-
-TlsGetCertSerial
-~~~~~~~~~~~~~~~~
-
-Get TLS certificate serial number through TlsGetCertSerial.
-
-Example:
-
-::
-
-  function log (args)
-      serial = TlsGetCertSerial()
-      if serial then
-          -- do something
-      end
-  end
-
-TlsGetSNI
-~~~~~~~~~
-
-Get the Server name Indication from a TLS connection.
-
-Example:
-
-::
-
-  function log (args)
-      asked_domain = TlsGetSNI()
-      if string.find(asked_domain, "badguys") then
-          -- ok connection to bad guys let's do someting
-      end
-  end
-
-
-JA3
----
-
-JA3 must be enabled in the Suricata config file (set 'app-layer.protocols.tls.ja3-fingerprints' to 'yes').
-
-Initialize with:
-
-::
-
-  function init (args)
-      local needs = {}
-      needs["protocol"] = "tls"
-      return needs
-  end
-
-Ja3GetHash
-~~~~~~~~~~
-
-Get the JA3 hash (md5sum of JA3 string) through Ja3GetHash.
-
-Example:
-
-::
-
-  function log (args)
-      hash = Ja3GetHash()
-      if hash == nil then
-          return
-      end
-  end
-
-Ja3GetString
-~~~~~~~~~~~~
-
-Get the JA3 string through Ja3GetString.
-
-Example:
-
-::
-
-  function log (args)
-      str = Ja3GetString()
-      if str == nil then
-          return
-      end
-  end
-
-SSH
----
-
-Initialize with:
-
-::
-
-
-  function init (args)
-      local needs = {}
-      needs["protocol"] = "ssh"
-      return needs
-  end
-
-SshGetServerProtoVersion
-~~~~~~~~~~~~~~~~~~~~~~~~
-
-Get SSH protocol version used by the server through SshGetServerProtoVersion.
-
-Example:
-
-::
-
-  function log (args)
-      version = SshGetServerProtoVersion()
-      if version == nil then
-          return 0
-      end
-  end
-
-SshGetServerSoftwareVersion
-~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Get SSH software used by the server through SshGetServerSoftwareVersion.
-
-Example:
-
-::
-
-
-  function log (args)
-      software = SshGetServerSoftwareVersion()
-      if software == nil then
-          return 0
-      end
-  end
+Developping lua output script
+-----------------------------
 
-SshGetClientProtoVersion
-~~~~~~~~~~~~~~~~~~~~~~~~
-
-Get SSH protocol version used by the client through SshGetClientProtoVersion.
-
-Example:
-
-::
-
-  function log (args)
-      version = SshGetClientProtoVersion()
-      if version == nil then
-          return 0
-      end
-  end
-
-SshGetClientSoftwareVersion
-~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Get SSH software used by the client through SshGetClientSoftwareVersion.
-
-Example:
-
-::
-
-  function log (args)
-      software = SshGetClientSoftwareVersion()
-      if software == nil then
-          return 0
-      end
-  end
-
-Files
------
-
-To use the file logging API, the script's init() function needs to look like:
-
-::
-
-  function init (args)
-      local needs = {}
-      needs['type'] = 'file'
-      return needs
-  end
-
-SCFileInfo
-~~~~~~~~~~
-
-::
-
-
-  fileid, txid, name, size, magic, md5 = SCFileInfo()
-
-returns fileid (number), txid (number), name (string), size (number),
-magic (string), md5 in hex (string)
-
-SCFileState
-~~~~~~~~~~~
-
-::
-
-  state, stored = SCFileState()
-
-returns state (string), stored (bool)
-
-Alerts
-------
-
-Alerts are a subset of the 'packet' logger:
-
-::
-
-  function init (args)
-      local needs = {}
-      needs["type"] = "packet"
-      needs["filter"] = "alerts"
-      return needs
-  end
-
-SCRuleIds
-~~~~~~~~~
-
-::
-
-  sid, rev, gid = SCRuleIds()
-
-SCRuleMsg
-~~~~~~~~~
-
-::
-
-  msg = SCRuleMsg()
-
-SCRuleClass
-~~~~~~~~~~~
-
-::
-
-
-  class, prio = SCRuleClass()
-
-Streaming Data
---------------
-
-Streaming data can currently log out reassembled TCP data and
-normalized HTTP data. The script will be invoked for each consecutive
-data chunk.
-
-In case of TCP reassembled data, all possible overlaps are removed
-according to the host OS settings.
-
-::
-
-  function init (args)
-      local needs = {}
-      needs["type"] = "streaming"
-      needs["filter"] = "tcp"
-      return needs
-  end
-
-In case of HTTP body data, the bodies are unzipped and dechunked if applicable.
-
-::
-
-  function init (args)
-      local needs = {}
-      needs["type"] = "streaming"
-      needs["protocol"] = "http"
-      return needs
-  end
-
-SCStreamingBuffer
-~~~~~~~~~~~~~~~~~
-
-::
-
-  function log(args)
-      data = SCStreamingBuffer()
-      hex_dump(data)
-  end
-
-Misc
-----
-
-SCThreadInfo
-~~~~~~~~~~~~
-
-::
-
-  tid, tname, tgroup = SCThreadInfo()
-
-It gives: tid (integer), tname (string), tgroup (string)
-
-SCLogError, SCLogWarning, SCLogNotice, SCLogInfo, SCLogDebug
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Print a message. It will go into the outputs defined in the
-yaml. Whether it will be printed depends on the log level.
-
-Example:
-
-::
-
-  SCLogError("some error message")
-
-SCLogPath
-~~~~~~~~~
-
-Expose the log path.
-
-::
-
-
-  name = "fast_lua.log"
-  function setup (args)
-      filename = SCLogPath() .. "/" .. name
-      file = assert(io.open(filename, "a"))
-  end
+You can use functions described in :ref:`Lua Functions <lua-functions>`
index 8094ec85d0341993f5913d971079748d450621f6..2f1bbfd7ac0418481abee0614b10df9122f7b290 100644 (file)
@@ -1,3 +1,5 @@
+.. _lua-scripting:
+
 Lua Scripting
 =============