diff --git a/scripts/base/init-bare.zeek b/scripts/base/init-bare.zeek index 7ab94432d7..3e153c204a 100644 --- a/scripts/base/init-bare.zeek +++ b/scripts/base/init-bare.zeek @@ -458,6 +458,41 @@ export { const upgrade_analyzers: table[string] of Analyzer::Tag &redef; } +module WebSocket; +export { + ## The WebSocket analyzer consumes and forwards + ## frame payload in chunks to keep memory usage + ## bounded. There should not be a reason to change + ## this value except for debugging and + ## testing reasons. + const payload_chunk_size = 8192 &redef; + + ## Whether to enable DPD on WebSocket frame payload by default. + const use_dpd_default = T &redef; + + ## Record type that is passed to :zeek:see:`WebSocket::__configure_analyzer`. + ## + ## This allows to configure the WebSocket analyzer given parameters + ## collected from HTTP headers. + type AnalyzerConfig: record { + ## The analyzer to attach for analysis of the WebSocket + ## frame payload. See *use_dpd* below for the behavior + ## when unset. + analyzer: Analyzer::Tag &optional; + + ## If *analyzer* is unset, determines whether to attach a + ## PIA_TCP analyzer for dynamic protocol detection with + ## WebSocket payload. + use_dpd: bool &default=use_dpd_default; + + ## The subprotocol as selected by the server, if any. + subprotocol: string &optional; + + ## The WebSocket extensions as selected by the server, if any. + server_extensions: vector of string &optional; + }; +} + module GLOBAL; ## A type alias for a vector of encapsulating "connections", i.e. for when diff --git a/scripts/base/init-default.zeek b/scripts/base/init-default.zeek index 95b1c64628..3a3efb6853 100644 --- a/scripts/base/init-default.zeek +++ b/scripts/base/init-default.zeek @@ -78,6 +78,7 @@ @load base/protocols/ssh @load base/protocols/ssl @load base/protocols/syslog +@load base/protocols/websocket @load base/protocols/tunnels @load base/protocols/xmpp diff --git a/scripts/base/protocols/websocket/__load__.zeek b/scripts/base/protocols/websocket/__load__.zeek new file mode 100644 index 0000000000..465d04deda --- /dev/null +++ b/scripts/base/protocols/websocket/__load__.zeek @@ -0,0 +1,2 @@ +@load ./consts.zeek +@load ./main.zeek diff --git a/scripts/base/protocols/websocket/consts.zeek b/scripts/base/protocols/websocket/consts.zeek new file mode 100644 index 0000000000..9bdffc2b7c --- /dev/null +++ b/scripts/base/protocols/websocket/consts.zeek @@ -0,0 +1,21 @@ +##! WebSocket constants. + +module WebSocket; + +export { + const OPCODE_CONTINUATION = 0x00; + const OPCODE_TEXT = 0x01; + const OPCODE_BINARY = 0x02; + const OPCODE_CLOSE = 0x08; + const OPCODE_PING = 0x09; + const OPCODE_PONG = 0x0a; + + const opcodes: table[count] of string = { + [OPCODE_CONTINUATION] = "continuation", + [OPCODE_TEXT] = "text", + [OPCODE_BINARY] = "binary", + [OPCODE_CLOSE] = "close", + [OPCODE_PING] = "ping", + [OPCODE_PONG] = "pong", + } &default=function(opcode: count): string { return fmt("unknown-%x", opcode); } &redef; +} diff --git a/scripts/base/protocols/websocket/main.zeek b/scripts/base/protocols/websocket/main.zeek new file mode 100644 index 0000000000..8d22c250db --- /dev/null +++ b/scripts/base/protocols/websocket/main.zeek @@ -0,0 +1,176 @@ +##! Implements base functionality for WebSocket analysis. +##! +##! Upon a websocket_handshake(), logs all gathered information into websocket.log +##! and then configures the WebSocket analyzer with the headers collected using +##! http events. + +@load base/protocols/http + +module WebSocket; + +# Register the WebSocket analyzer as HTTP upgrade analyzer. +redef HTTP::upgrade_analyzers += { + ["websocket"] = Analyzer::ANALYZER_WEBSOCKET, +}; + +export { + redef enum Log::ID += { LOG }; + + ## The record type for the WebSocket log. + type Info: record { + ## Timestamp + ts: time &log; + ## Unique ID for the connection. + uid: string &log; + ## The connection's 4-tuple of endpoint addresses/ports. + id: conn_id &log; + ## Same as in the HTTP log. + host: string &log &optional; + ## Same as in the HTTP log. + uri: string &log &optional; + ## Same as in the HTTP log. + user_agent: string &log &optional; + ## The WebSocket subprotocol as selected by the server. + subprotocol: string &log &optional; + ## The protocols requested by the client, if any. + client_protocols: vector of string &log &optional; + ## The extensions selected by the the server, if any. + server_extensions: vector of string &log &optional; + ## The extensions requested by the client, if any. + client_extensions: vector of string &log &optional; + }; + + ## Event that can be handled to access the WebSocket record as it is + ## sent on to the logging framework. + global log_websocket: event(rec: Info); + + ## Log policy hook. + global log_policy: Log::PolicyHook; + + ## Hook to allow interception of WebSocket analyzer configuration. + ## + ## c: The connection + ## + ## aid: The analyzer ID for the WebSocket analyzer. + ## + ## config: The configuration record, also containing information + ## about the subprotocol and extensions. + global configure_analyzer: hook(c: connection, aid: count, config: AnalyzerConfig); +} + +redef record connection += { + websocket: Info &optional; +}; + +function set_websocket(c: connection) + { + c$websocket = Info( + $ts=network_time(), + $uid=c$uid, + $id=c$id, + ); + } + +event http_header(c: connection, is_orig: bool, name: string, value: string) + { + if ( ! starts_with(name, "SEC-WEBSOCKET-") ) + return; + + if ( ! c?$websocket ) + set_websocket(c); + + local ws = c$websocket; + + if ( is_orig ) + { + if ( name == "SEC-WEBSOCKET-PROTOCOL" ) + { + if ( ! ws?$client_protocols ) + ws$client_protocols = vector(); + + ws$client_protocols += split_string(value, / *, */); + } + + else if ( name == "SEC-WEBSOCKET-EXTENSIONS" ) + { + if ( ! ws?$client_extensions ) + ws$client_extensions = vector(); + + ws$client_extensions += split_string(value, / *, */); + } + } + else + { + if ( name == "SEC-WEBSOCKET-PROTOCOL" ) + { + ws$subprotocol = value; + } + else if ( name == "SEC-WEBSOCKET-EXTENSIONS" ) + { + if ( ! ws?$server_extensions ) + ws$server_extensions = vector(); + + ws$server_extensions += split_string(value, / *, */); + } + } + } + +event http_request(c: connection, method: string, original_URI: string, + unescaped_URI: string, version: string) + { + # If we see a http_request and have websocket state, wipe it as + # we should've seen a websocket_handshake even on success and + # likely no more http events. + if ( ! c?$websocket ) + delete c$websocket; + } + +event websocket_handshake(c: connection, aid: count) &priority=5 + { + if ( ! c?$websocket ) + { + # This means we never saw a Sec-WebSocket-* header, weird. + Reporter::conn_weird("websocket_handshake_unexpected", c, "", "WebSocket"); + set_websocket(c); + } + + local ws = c$websocket; + + # Replicate some information from the HTTP.log + if ( c?$http ) + { + if ( c$http?$host ) + ws$host = c$http$host; + + if ( c$http?$uri ) + ws$uri = c$http$uri; + + if ( c$http?$user_agent ) + ws$user_agent = c$http$user_agent; + } + } + +event websocket_handshake(c: connection, aid: count) &priority=-5 + { + local ws = c$websocket; + + local config = AnalyzerConfig(); + if ( ws?$subprotocol ) + config$subprotocol = ws$subprotocol; + + if ( ws?$server_extensions ) + config$server_extensions = ws$server_extensions; + + # Give other scripts a chance to modify the analyzer configuration. + hook WebSocket::configure_analyzer(c, aid, config); + + WebSocket::__configure_analyzer(c, aid, config); + + ws$ts = network_time(); + Log::write(LOG, ws); + } + +event zeek_init() + { + Log::create_stream(LOG, [$columns=Info, $ev=log_websocket, $path="websocket", $policy=log_policy]); + } diff --git a/src/analyzer/protocol/CMakeLists.txt b/src/analyzer/protocol/CMakeLists.txt index 79e5b6cea0..896c53b4e6 100644 --- a/src/analyzer/protocol/CMakeLists.txt +++ b/src/analyzer/protocol/CMakeLists.txt @@ -42,5 +42,6 @@ add_subdirectory(ssh) add_subdirectory(ssl) add_subdirectory(syslog) add_subdirectory(tcp) +add_subdirectory(websocket) add_subdirectory(xmpp) add_subdirectory(zip) diff --git a/src/analyzer/protocol/websocket/CMakeLists.txt b/src/analyzer/protocol/websocket/CMakeLists.txt new file mode 100644 index 0000000000..d522c58821 --- /dev/null +++ b/src/analyzer/protocol/websocket/CMakeLists.txt @@ -0,0 +1,15 @@ +zeek_add_plugin( + Zeek + WebSocket + SOURCES + WebSocket.cc + Plugin.cc + BIFS + consts.bif + events.bif + functions.bif + types.bif + PAC + websocket.pac + websocket-analyzer.pac + websocket-protocol.pac) diff --git a/src/analyzer/protocol/websocket/Plugin.cc b/src/analyzer/protocol/websocket/Plugin.cc new file mode 100644 index 0000000000..c3ef84765a --- /dev/null +++ b/src/analyzer/protocol/websocket/Plugin.cc @@ -0,0 +1,24 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#include "zeek/plugin/Plugin.h" + +#include "zeek/analyzer/Component.h" + +#include "analyzer/protocol/websocket/WebSocket.h" + +namespace zeek::plugin::detail::Zeek_WebSocket { + +class Plugin : public zeek::plugin::Plugin { +public: + zeek::plugin::Configuration Configure() override { + AddComponent( + new zeek::analyzer::Component("WebSocket", zeek::analyzer::websocket::WebSocket_Analyzer::Instantiate)); + + zeek::plugin::Configuration config; + config.name = "Zeek::WebSocket"; + config.description = "WebSocket analyzer"; + return config; + } +} plugin; + +} // namespace zeek::plugin::detail::Zeek_WebSocket diff --git a/src/analyzer/protocol/websocket/WebSocket.cc b/src/analyzer/protocol/websocket/WebSocket.cc new file mode 100644 index 0000000000..20e8a22086 --- /dev/null +++ b/src/analyzer/protocol/websocket/WebSocket.cc @@ -0,0 +1,101 @@ +// See the file in the main distribution directory for copyright. + +#include "zeek/analyzer/protocol/websocket/WebSocket.h" + +#include + +#include "zeek/analyzer/Manager.h" +#include "zeek/analyzer/protocol/pia/PIA.h" +#include "zeek/analyzer/protocol/websocket/events.bif.h" + +namespace zeek::analyzer::websocket { + +WebSocket_Analyzer::WebSocket_Analyzer(Connection* conn) : analyzer::tcp::TCP_ApplicationAnalyzer("WebSocket", conn) { + // TODO: Consider approaches dispatching to optionally use a + // Spicy analyzer here instead of the BinPac interpreter. + // + // E.g. we could instantiate a SPICY_WEBSOCKET analyzer and pass it the necessary + // information and call DeliverStream() directly on it. + interp = std::make_unique(this); +} + +void WebSocket_Analyzer::Init() { + tcp::TCP_ApplicationAnalyzer::Init(); + + // This event calls back via Configure() + zeek::BifEvent::enqueue_websocket_handshake(this, Conn(), GetID()); +} + +bool WebSocket_Analyzer::Configure(zeek::RecordValPtr config) { + // TODO: Check extensions and modify parsing if needed, e.g. WebSocket frame + // compression extension: https://www.rfc-editor.org/rfc/rfc7692.html + // + // interp->SetExtensions(...) + // + // TODO: The Sec-WebSocket-Protocol header might provide some information + // that we could leverage to instantiate a more specific analyzer. + // + // For now, we just attach a PIA analyzer as child analyzer. + + static const auto& config_type = id::find_type("WebSocket::AnalyzerConfig"); + static int analyzer_idx = config_type->FieldOffset("analyzer"); + static int use_dpd_idx = config_type->FieldOffset("use_dpd"); + + if ( config->HasField(analyzer_idx) ) { + const auto& analyzer_tag_val = config->GetField(analyzer_idx); + auto analyzer_tag = analyzer_mgr->GetComponentTag(analyzer_tag_val.get()); + + if ( analyzer_tag == zeek::Tag() ) { + reporter->InternalWarning("no component tag for enum '%s'", + analyzer_tag_val->GetType()->Lookup(analyzer_tag_val->AsEnum())); + return false; + } + + DBG_LOG(DBG_ANALYZER, "%s Configure() using analyzer %s", fmt_analyzer(this).c_str(), + analyzer_tag_val->GetType()->Lookup(analyzer_tag_val->AsEnum())); + + auto* analyzer = analyzer_mgr->InstantiateAnalyzer(analyzer_tag, Conn()); + if ( ! analyzer ) + return false; + + return AddChildAnalyzer(analyzer); + } + else if ( config->GetField(use_dpd_idx)->AsBool() ) { + DBG_LOG(DBG_ANALYZER, "%s Configure() enables DPD via PIA_TCP", fmt_analyzer(this).c_str()); + + auto* pia = new analyzer::pia::PIA_TCP(Conn()); + if ( AddChildAnalyzer(pia) ) { + pia->FirstPacket(true, nullptr); + pia->FirstPacket(false, nullptr); + return true; + } + + return false; + } + + // Neither analyzer nor dpd was enabled, success. + return true; +} + + +void WebSocket_Analyzer::DeliverStream(int len, const u_char* data, bool orig) { + analyzer::tcp::TCP_ApplicationAnalyzer::DeliverStream(len, data, orig); + if ( had_gap ) { + DBG_LOG(DBG_ANALYZER, "Skipping data after gap len=%d orig=%d", len, orig); + return; + } + + try { + interp->NewData(orig, data, data + len); + } catch ( const binpac::Exception& e ) { + AnalyzerViolation(e.c_msg(), reinterpret_cast(data), len); + } +} + +void WebSocket_Analyzer::Undelivered(uint64_t seq, int len, bool orig) { + analyzer::tcp::TCP_ApplicationAnalyzer::Undelivered(seq, len, orig); + interp->NewGap(orig, len); + had_gap = true; +} + +} // namespace zeek::analyzer::websocket diff --git a/src/analyzer/protocol/websocket/WebSocket.h b/src/analyzer/protocol/websocket/WebSocket.h new file mode 100644 index 0000000000..394eab194e --- /dev/null +++ b/src/analyzer/protocol/websocket/WebSocket.h @@ -0,0 +1,38 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#pragma once + +#include + +#include "zeek/analyzer/protocol/tcp/TCP.h" +#include "zeek/analyzer/protocol/websocket/websocket_pac.h" + +namespace zeek::analyzer::websocket { + +/** + * A WebSocket analyzer to be used directly on top of HTTP. + */ +class WebSocket_Analyzer : public analyzer::tcp::TCP_ApplicationAnalyzer { +public: + WebSocket_Analyzer(zeek::Connection* conn); + ~WebSocket_Analyzer() = default; + + /** + * Allows script land to configure the WebSocket analyzer before analysis. + * + * @param config Zeek value of type WebSocket::AnalyzerConfig + */ + bool Configure(zeek::RecordValPtr config); + + void Init() override; + void DeliverStream(int len, const u_char* data, bool orig) override; + void Undelivered(uint64_t seq, int len, bool orig) override; + + static zeek::analyzer::Analyzer* Instantiate(Connection* conn) { return new WebSocket_Analyzer(conn); } + +private: + std::unique_ptr interp; + bool had_gap = false; +}; + +} // namespace zeek::analyzer::websocket diff --git a/src/analyzer/protocol/websocket/consts.bif b/src/analyzer/protocol/websocket/consts.bif new file mode 100644 index 0000000000..164181474c --- /dev/null +++ b/src/analyzer/protocol/websocket/consts.bif @@ -0,0 +1 @@ +const WebSocket::payload_chunk_size: count; diff --git a/src/analyzer/protocol/websocket/events.bif b/src/analyzer/protocol/websocket/events.bif new file mode 100644 index 0000000000..77f450c5fe --- /dev/null +++ b/src/analyzer/protocol/websocket/events.bif @@ -0,0 +1,71 @@ +## Generated when a WebSocket handshake completed. +## +## This is a bit artificial. It can be used to configure the WebSocket +## analyzer if the HTTP headers contained protocol and extension headers. +## +## c: The WebSocket connection. +## +## aid: The analyzer identifier of the WebSocket analyzer. +## +## .. zeek:see:: WebSocket::__configure_analyzer +## +## .. zeek:see:: WebSocket::configure_analyzer +## +event websocket_handshake%(c: connection, aid: count%); + +## Generated for every WebSocket frame. +## +## c: The WebSocket connection. +## +## is_orig: True if the frame is from the originator, else false. +## +## fin: True if the fin bit is set, else false. +## +## rsv: The value of the RSV1, RSV2 and RSV3 bits. +## +## opcode: The frame's opcode. +## +## payload_len: The frame's payload length. +## +event websocket_frame%(c: connection, is_orig: bool, fin: bool, rsv: count, opcode: count, payload_len: count%); + +## Generated for every chunk of WebSocket frame payload data. +## +## Do not use it to extract data from a WebSocket connection unless for testing +## or experimentation. Consider implementing a proper analyzer instead. +## +## c: The WebSocket connection. +## +## is_orig: True if the frame is from the originator, else false. +## +## data: One data chunk of frame payload. The length of is at most +## :zeek:see:`WebSocket::payload_chunk_size` bytes. A frame with +## a longer payload will result in multiple events events. +## +## .. zeek:see:: WebSocket::payload_chunk_size +event websocket_frame_data%(c: connection, is_orig: bool, data: string%); + + +## Generated for every completed WebSocket message. +## +## c: The WebSocket connection. +## +## is_orig: True if the frame is from the originator, else false. +## +## opcode: The first frame's opcode. +event websocket_message%(c: connection, is_orig: bool, opcode: count%); + +## Generated for WebSocket Close frames. +## +## c: The WebSocket connection. +## +## is_orig: True if the frame is from the originator, else false. +## +## status: If the CloseFrame had no payload, this is 0, otherwise the value +## of the first two bytes in the frame's payload. +## +## reason: Remaining payload after *status*. This is capped at +## 2 bytes less than :zeek:see:`WebSocket::payload_chunk_size`. +## +## .. zeek:see:: WebSocket::payload_chunk_size +event websocket_close%(c: connection, is_orig: bool, status: count, reason: string%); diff --git a/src/analyzer/protocol/websocket/functions.bif b/src/analyzer/protocol/websocket/functions.bif new file mode 100644 index 0000000000..bb06a3fd30 --- /dev/null +++ b/src/analyzer/protocol/websocket/functions.bif @@ -0,0 +1,46 @@ +%%{ +#include "zeek/analyzer/protocol/websocket/WebSocket.h" +%%} + +module WebSocket; + +## Configure the WebSocket analyzer. +## +## Called during :zeek:see:`websocket_handshake` to configure +## the WebSocket analyzer given the selected protocol and extension +## as chosen by the server. +## +## c: The WebSocket connection. +# +## aid: The identifier for the WebSocket analyzer as provided to :zeek:see:`websocket_handshake`. +## +## server_protocol: The protocol as found in the server's Sec-WebSocket-Protocol HTTP header, or empty. +## +## server_extensions: The extension as selected by the server via the Sec-WebSocket-Extensions HTTP Header. +## +## .. zeek:see:: websocket_handshake +function __configure_analyzer%(c: connection, aid: count, config: WebSocket::AnalyzerConfig%): bool + %{ + auto* analyzer = c->FindAnalyzer(aid); + auto* ws_analyzer = dynamic_cast(analyzer); + if ( ! ws_analyzer ) + { + reporter->Warning("WebSocket analyzer to configure not found"); + return zeek::val_mgr->False(); + } + + static const auto& config_type = zeek::id::find_type("WebSocket::AnalyzerConfig"); + + if ( config->GetType() != config_type ) + { + reporter->Warning("config has wrong type %s, expected %s", + config->GetType()->GetName().c_str(), + config_type->GetName().c_str()); + return zeek::val_mgr->False(); + } + + if ( ! ws_analyzer->Configure({zeek::NewRef{}, config->AsRecordVal()}) ) + return zeek::val_mgr->False(); + + return zeek::val_mgr->True(); + %} diff --git a/src/analyzer/protocol/websocket/types.bif b/src/analyzer/protocol/websocket/types.bif new file mode 100644 index 0000000000..90378cef1b --- /dev/null +++ b/src/analyzer/protocol/websocket/types.bif @@ -0,0 +1,4 @@ +module WebSocket; + +# A configuration record used for the WebSocket analyzer. +type AnalyzerConfig: record; diff --git a/src/analyzer/protocol/websocket/websocket-analyzer.pac b/src/analyzer/protocol/websocket/websocket-analyzer.pac new file mode 100644 index 0000000000..c57dd9a651 --- /dev/null +++ b/src/analyzer/protocol/websocket/websocket-analyzer.pac @@ -0,0 +1,126 @@ +# See the file "COPYING" in the main distribution directory for copyright. +# +# The WebSocket analyzer. +# + +refine flow WebSocket_Flow += { + + function process_message(msg: WebSocket_Message): bool + %{ + connection()->zeek_analyzer()->AnalyzerConfirmation(); + + if ( websocket_message ) + { + zeek::BifEvent::enqueue_websocket_message(connection()->zeek_analyzer(), + connection()->zeek_analyzer()->Conn(), + is_orig(), + ${msg.opcode}); + } + + return true; + %} + + function process_header(hdr: WebSocket_FrameHeader): bool + %{ + if ( websocket_frame ) + { + zeek::BifEvent::enqueue_websocket_frame(connection()->zeek_analyzer(), + connection()->zeek_analyzer()->Conn(), + is_orig(), + ${hdr.b.fin}, + ${hdr.b.reserved}, + ${hdr.b.opcode}, + ${hdr.payload_len}); + } + + return true; + %} + + function process_payload_unmask(chunk: WebSocket_FramePayloadUnmask): bool + %{ + auto& data = ${chunk.data}; + + // In-place unmasking if frame payload is masked. + if ( has_mask_ ) + { + auto *d = data.data(); + for ( int i = 0; i < data.length(); i++ ) + d[i] = d[i] ^ mask_[mask_idx_++ % mask_.size()]; + } + + return true; + %} + + function process_payload_close(close: WebSocket_FramePayloadClose): bool + %{ + if ( websocket_close ) + { + const auto& reason = ${close.reason}; + auto reason_val = zeek::make_intrusive(reason.length(), + reinterpret_cast(reason.data())); + zeek::BifEvent::enqueue_websocket_close(connection()->zeek_analyzer(), + connection()->zeek_analyzer()->Conn(), + is_orig(), + ${close.status}, + reason_val); + } + + return true; + %} + + function process_empty_close(hdr: WebSocket_FrameHeader): bool + %{ + if ( websocket_close ) + { + zeek::BifEvent::enqueue_websocket_close(connection()->zeek_analyzer(), + connection()->zeek_analyzer()->Conn(), + is_orig(), + 0, /* use placeholder status */ + zeek::val_mgr->EmptyString()); + } + + return true; + %} + + function process_payload_chunk(chunk: WebSocket_FramePayloadChunk): bool + %{ + auto& data = ${chunk.unmask.data}; + + if ( websocket_frame_data ) + { + auto data_val = zeek::make_intrusive(data.length(), reinterpret_cast(data.data())); + zeek::BifEvent::enqueue_websocket_frame_data(connection()->zeek_analyzer(), + connection()->zeek_analyzer()->Conn(), + is_orig(), + data_val); + } + + // Forward text and binary data to downstream analyzers. + if ( ${chunk.hdr.b.opcode} == OPCODE_TEXT|| ${chunk.hdr.b.opcode} == OPCODE_BINARY) + connection()->zeek_analyzer()->ForwardStream(data.length(), + data.data(), + is_orig()); + + return true; + %} +}; + +refine typeattr WebSocket_Message += &let { + proc_message = $context.flow.process_message(this); +}; + +refine typeattr WebSocket_FrameHeader += &let { + proc_header = $context.flow.process_header(this); +}; + +refine typeattr WebSocket_FramePayloadUnmask += &let { + proc_payload_unmask = $context.flow.process_payload_unmask(this); +}; + +refine typeattr WebSocket_FramePayloadClose += &let { + proc_payload_close = $context.flow.process_payload_close(this); +}; + +refine typeattr WebSocket_FramePayloadChunk += &let { + proc_payload_chunk = $context.flow.process_payload_chunk(this); +}; diff --git a/src/analyzer/protocol/websocket/websocket-protocol.pac b/src/analyzer/protocol/websocket/websocket-protocol.pac new file mode 100644 index 0000000000..01ab76ff9e --- /dev/null +++ b/src/analyzer/protocol/websocket/websocket-protocol.pac @@ -0,0 +1,149 @@ +# See the file "COPYING" in the main distribution directory for copyright. +# +# The WebSocket protocol. +# +# https://datatracker.ietf.org/doc/html/rfc6455 + +enum Opcodes { + OPCODE_CONTINUATION = 0x00, + OPCODE_TEXT = 0x01, + OPCODE_BINARY = 0x02, + OPCODE_CLOSE = 0x08, + OPCODE_PING = 0x09, + OPCODE_PONG = 0x0a, +} + +type WebSocket_FrameHeaderFixed(first_frame: bool) = record { + # First frame in message cannot be continuation, following + # frames are only expected to be continuations. + b: uint16 &enforce((first_frame && opcode != 0) || (!first_frame && opcode == 0)); +} &let { + fin: bool = (b & 0x8000) ? true : false; + reserved: uint8 = ((b & 0x7000) >> 12); + opcode: uint8 = (b & 0x0f00) >> 8; + has_mask: bool = (b & 0x0080) ? true : false; + payload_len1: uint8 = (b & 0x007f); + rest_header_len: uint64 = (has_mask ? 4 : 0) + (payload_len1 < 126 ? 0 : (payload_len1 == 126 ? 2 : 8)); +} &length=2; + +type WebSocket_FrameHeader(b: WebSocket_FrameHeaderFixed) = record { + maybe_more_len: case b.payload_len1 of { + 126 -> payload_len2: uint16; + 127 -> payload_len8: uint64; + default -> short_len: empty; + }; + + maybe_mask: case b.has_mask of { + true -> mask: bytestring &length=4; + false -> no_mask: empty; + }; +} &let { + payload_len: uint64 = b.payload_len1 < 126 ? b.payload_len1 : (b.payload_len1 == 126 ? payload_len2 : payload_len8); + new_frame_payload = $context.flow.new_frame_payload(this); +} &length=b.rest_header_len; + +type WebSocket_FramePayloadClose(hdr: WebSocket_FrameHeader) = record { + status: uint16; + reason: bytestring &restofdata; +} &byteorder=bigendian; + +type WebSocket_FramePayloadUnmask(hdr: WebSocket_FrameHeader) = record { + data: bytestring &restofdata; +}; + +type WebSocket_FramePayloadChunk(len: uint64, hdr: WebSocket_FrameHeader) = record { + unmask: WebSocket_FramePayloadUnmask(hdr); +} &let { + consumed_payload = $context.flow.consumed_chunk(len); + close_payload: WebSocket_FramePayloadClose(hdr) withinput unmask.data &length=len &if(hdr.b.opcode == OPCODE_CLOSE); +} &length=len; + +type WebSocket_Frame(first_frame: bool, msg: WebSocket_Message) = record { + b: WebSocket_FrameHeaderFixed(first_frame); + hdr: WebSocket_FrameHeader(b); + + # This is implementing frame payload chunking so that we do not + # attempt to buffer huge frames and forward data to downstream + # analyzers in chunks. + # + # I tried &chunked and it didn't do anything very useful. + chunks: WebSocket_FramePayloadChunk($context.flow.next_chunk_len(), hdr)[] + &until($context.flow.remaining_frame_payload_len() == 0) + &transient; +} &let { + # If we find a close frame without payload, raise the event here + # as the close won't have been parsed via chunks. + empty_close = $context.flow.process_empty_close(hdr) &if(b.opcode == OPCODE_CLOSE) && hdr.payload_len == 0; +}; + +type WebSocket_Message = record { + first_frame: WebSocket_Frame(true, this); + optional_more_frames: case first_frame.hdr.b.fin of { + true -> no_more_frames: empty; + false -> more_frames: WebSocket_Frame(false, this)[] &until($element.hdr.b.fin) &transient; + }; +} &let { + opcode = first_frame.hdr.b.opcode; +} &byteorder=bigendian; + +flow WebSocket_Flow(is_orig: bool) { + flowunit = WebSocket_Message withcontext(connection, this); + + %member{ + bool has_mask_; + uint64_t mask_idx_; + uint64_t frame_payload_len_; + std::array mask_; + %} + + %init{ + has_mask_ = false; + mask_idx_ = 0; + frame_payload_len_ = 0; + %} + + function new_frame_payload(hdr: WebSocket_FrameHeader): uint64 + %{ + if ( frame_payload_len_ > 0 ) + connection()->zeek_analyzer()->Weird("websocket_frame_not_consumed"); + + frame_payload_len_ = ${hdr.payload_len}; + has_mask_ = ${hdr.b.has_mask}; + mask_idx_ = 0; + if ( has_mask_ ) { + assert(${hdr.mask}.length() == static_cast(mask_.size())); + memcpy(mask_.data(), ${hdr.mask}.data(), mask_.size()); + } + return frame_payload_len_; + %} + + function remaining_frame_payload_len(): uint64 + %{ + return frame_payload_len_; + %} + + function consumed_chunk(len: uint64): uint64 + %{ + if ( len > frame_payload_len_ ) { + connection()->zeek_analyzer()->Weird("websocket_frame_consuming_too_much"); + len = frame_payload_len_; + } + + frame_payload_len_ -= len; + return len; + %} + + function next_chunk_len(): uint64 + %{ + uint64_t len = frame_payload_len_; + + // It would be somewhat nicer if we could just consume + // anything still left to consume from the current packet, + // but couldn't figure out if that information can be pulled + // flow buffer. + if ( len > zeek::BifConst::WebSocket::payload_chunk_size ) + len = zeek::BifConst::WebSocket::payload_chunk_size; + + return len; + %} +}; diff --git a/src/analyzer/protocol/websocket/websocket.pac b/src/analyzer/protocol/websocket/websocket.pac new file mode 100644 index 0000000000..4e710e2712 --- /dev/null +++ b/src/analyzer/protocol/websocket/websocket.pac @@ -0,0 +1,24 @@ +# See the file "COPYING" in the main distribution directory for copyright. + +%include binpac.pac +%include zeek.pac + +%extern{ +#include + +#include "zeek/analyzer/protocol/websocket/consts.bif.h" +#include "zeek/analyzer/protocol/websocket/events.bif.h" +%} + +analyzer WebSocket withcontext { + connection: WebSocket_Conn; + flow: WebSocket_Flow; +}; + +connection WebSocket_Conn(zeek_analyzer: ZeekAnalyzer) { + upflow = WebSocket_Flow(true); + downflow = WebSocket_Flow(false); +}; + +%include websocket-protocol.pac +%include websocket-analyzer.pac diff --git a/testing/btest/Baseline/coverage.bare-load-baseline/canonified_loaded_scripts.log b/testing/btest/Baseline/coverage.bare-load-baseline/canonified_loaded_scripts.log index 13a58ed17e..f7ca9ce013 100644 --- a/testing/btest/Baseline/coverage.bare-load-baseline/canonified_loaded_scripts.log +++ b/testing/btest/Baseline/coverage.bare-load-baseline/canonified_loaded_scripts.log @@ -244,6 +244,10 @@ scripts/base/init-frameworks-and-bifs.zeek build/scripts/base/bif/plugins/Zeek_TCP.events.bif.zeek build/scripts/base/bif/plugins/Zeek_TCP.types.bif.zeek build/scripts/base/bif/plugins/Zeek_TCP.functions.bif.zeek + build/scripts/base/bif/plugins/Zeek_WebSocket.consts.bif.zeek + build/scripts/base/bif/plugins/Zeek_WebSocket.events.bif.zeek + build/scripts/base/bif/plugins/Zeek_WebSocket.functions.bif.zeek + build/scripts/base/bif/plugins/Zeek_WebSocket.types.bif.zeek build/scripts/base/bif/plugins/Zeek_XMPP.events.bif.zeek build/scripts/base/bif/plugins/Zeek_ARP.events.bif.zeek build/scripts/base/bif/plugins/Zeek_UDP.events.bif.zeek diff --git a/testing/btest/Baseline/coverage.default-load-baseline/canonified_loaded_scripts.log b/testing/btest/Baseline/coverage.default-load-baseline/canonified_loaded_scripts.log index 43d87b3515..77e4e88706 100644 --- a/testing/btest/Baseline/coverage.default-load-baseline/canonified_loaded_scripts.log +++ b/testing/btest/Baseline/coverage.default-load-baseline/canonified_loaded_scripts.log @@ -244,6 +244,10 @@ scripts/base/init-frameworks-and-bifs.zeek build/scripts/base/bif/plugins/Zeek_TCP.events.bif.zeek build/scripts/base/bif/plugins/Zeek_TCP.types.bif.zeek build/scripts/base/bif/plugins/Zeek_TCP.functions.bif.zeek + build/scripts/base/bif/plugins/Zeek_WebSocket.consts.bif.zeek + build/scripts/base/bif/plugins/Zeek_WebSocket.events.bif.zeek + build/scripts/base/bif/plugins/Zeek_WebSocket.functions.bif.zeek + build/scripts/base/bif/plugins/Zeek_WebSocket.types.bif.zeek build/scripts/base/bif/plugins/Zeek_XMPP.events.bif.zeek build/scripts/base/bif/plugins/Zeek_ARP.events.bif.zeek build/scripts/base/bif/plugins/Zeek_UDP.events.bif.zeek @@ -465,6 +469,9 @@ scripts/base/init-default.zeek scripts/base/protocols/syslog/spicy-events.zeek scripts/base/protocols/syslog/consts.zeek scripts/base/protocols/syslog/main.zeek + scripts/base/protocols/websocket/__load__.zeek + scripts/base/protocols/websocket/consts.zeek + scripts/base/protocols/websocket/main.zeek scripts/base/protocols/tunnels/__load__.zeek scripts/base/protocols/xmpp/__load__.zeek scripts/base/protocols/xmpp/main.zeek diff --git a/testing/btest/Baseline/coverage.find-bro-logs/out b/testing/btest/Baseline/coverage.find-bro-logs/out index efe4d98b6d..ad46a67218 100644 --- a/testing/btest/Baseline/coverage.find-bro-logs/out +++ b/testing/btest/Baseline/coverage.find-bro-logs/out @@ -65,6 +65,7 @@ telemetry_histogram traceroute tunnel unknown_protocols +websocket weird weird_stats x509 diff --git a/testing/btest/Baseline/coverage.record-fields/out.default b/testing/btest/Baseline/coverage.record-fields/out.default index cf0204c6dd..527f4fead2 100644 --- a/testing/btest/Baseline/coverage.record-fields/out.default +++ b/testing/btest/Baseline/coverage.record-fields/out.default @@ -884,4 +884,18 @@ connection { } * uid: string, log=F, optional=F * vlan: int, log=F, optional=T + * websocket: record WebSocket::Info, log=F, optional=T + WebSocket::Info { + * client_extensions: vector of string, log=T, optional=T + * client_protocols: vector of string, log=T, optional=T + * host: string, log=T, optional=T + * id: record conn_id, log=T, optional=F + conn_id { ... } + * server_extensions: vector of string, log=T, optional=T + * subprotocol: string, log=T, optional=T + * ts: time, log=T, optional=F + * uid: string, log=T, optional=F + * uri: string, log=T, optional=T + * user_agent: string, log=T, optional=T + } } diff --git a/testing/btest/Baseline/plugins.hooks/output b/testing/btest/Baseline/plugins.hooks/output index 386e891e7a..db0b88a431 100644 --- a/testing/btest/Baseline/plugins.hooks/output +++ b/testing/btest/Baseline/plugins.hooks/output @@ -463,6 +463,10 @@ 0.000000 MetaHookPost LoadFile(0, ./Zeek_Teredo.functions.bif.zeek, <...>/Zeek_Teredo.functions.bif.zeek) -> -1 0.000000 MetaHookPost LoadFile(0, ./Zeek_UDP.events.bif.zeek, <...>/Zeek_UDP.events.bif.zeek) -> -1 0.000000 MetaHookPost LoadFile(0, ./Zeek_VXLAN.events.bif.zeek, <...>/Zeek_VXLAN.events.bif.zeek) -> -1 +0.000000 MetaHookPost LoadFile(0, ./Zeek_WebSocket.consts.bif.zeek, <...>/Zeek_WebSocket.consts.bif.zeek) -> -1 +0.000000 MetaHookPost LoadFile(0, ./Zeek_WebSocket.events.bif.zeek, <...>/Zeek_WebSocket.events.bif.zeek) -> -1 +0.000000 MetaHookPost LoadFile(0, ./Zeek_WebSocket.functions.bif.zeek, <...>/Zeek_WebSocket.functions.bif.zeek) -> -1 +0.000000 MetaHookPost LoadFile(0, ./Zeek_WebSocket.types.bif.zeek, <...>/Zeek_WebSocket.types.bif.zeek) -> -1 0.000000 MetaHookPost LoadFile(0, ./Zeek_X509.events.bif.zeek, <...>/Zeek_X509.events.bif.zeek) -> -1 0.000000 MetaHookPost LoadFile(0, ./Zeek_X509.functions.bif.zeek, <...>/Zeek_X509.functions.bif.zeek) -> -1 0.000000 MetaHookPost LoadFile(0, ./Zeek_X509.ocsp_events.bif.zeek, <...>/Zeek_X509.ocsp_events.bif.zeek) -> -1 @@ -752,6 +756,10 @@ 0.000000 MetaHookPost LoadFileExtended(0, ./Zeek_Teredo.functions.bif.zeek, <...>/Zeek_Teredo.functions.bif.zeek) -> (-1, ) 0.000000 MetaHookPost LoadFileExtended(0, ./Zeek_UDP.events.bif.zeek, <...>/Zeek_UDP.events.bif.zeek) -> (-1, ) 0.000000 MetaHookPost LoadFileExtended(0, ./Zeek_VXLAN.events.bif.zeek, <...>/Zeek_VXLAN.events.bif.zeek) -> (-1, ) +0.000000 MetaHookPost LoadFileExtended(0, ./Zeek_WebSocket.consts.bif.zeek, <...>/Zeek_WebSocket.consts.bif.zeek) -> (-1, ) +0.000000 MetaHookPost LoadFileExtended(0, ./Zeek_WebSocket.events.bif.zeek, <...>/Zeek_WebSocket.events.bif.zeek) -> (-1, ) +0.000000 MetaHookPost LoadFileExtended(0, ./Zeek_WebSocket.functions.bif.zeek, <...>/Zeek_WebSocket.functions.bif.zeek) -> (-1, ) +0.000000 MetaHookPost LoadFileExtended(0, ./Zeek_WebSocket.types.bif.zeek, <...>/Zeek_WebSocket.types.bif.zeek) -> (-1, ) 0.000000 MetaHookPost LoadFileExtended(0, ./Zeek_X509.events.bif.zeek, <...>/Zeek_X509.events.bif.zeek) -> (-1, ) 0.000000 MetaHookPost LoadFileExtended(0, ./Zeek_X509.functions.bif.zeek, <...>/Zeek_X509.functions.bif.zeek) -> (-1, ) 0.000000 MetaHookPost LoadFileExtended(0, ./Zeek_X509.ocsp_events.bif.zeek, <...>/Zeek_X509.ocsp_events.bif.zeek) -> (-1, ) @@ -1389,6 +1397,10 @@ 0.000000 MetaHookPre LoadFile(0, ./Zeek_Teredo.functions.bif.zeek, <...>/Zeek_Teredo.functions.bif.zeek) 0.000000 MetaHookPre LoadFile(0, ./Zeek_UDP.events.bif.zeek, <...>/Zeek_UDP.events.bif.zeek) 0.000000 MetaHookPre LoadFile(0, ./Zeek_VXLAN.events.bif.zeek, <...>/Zeek_VXLAN.events.bif.zeek) +0.000000 MetaHookPre LoadFile(0, ./Zeek_WebSocket.consts.bif.zeek, <...>/Zeek_WebSocket.consts.bif.zeek) +0.000000 MetaHookPre LoadFile(0, ./Zeek_WebSocket.events.bif.zeek, <...>/Zeek_WebSocket.events.bif.zeek) +0.000000 MetaHookPre LoadFile(0, ./Zeek_WebSocket.functions.bif.zeek, <...>/Zeek_WebSocket.functions.bif.zeek) +0.000000 MetaHookPre LoadFile(0, ./Zeek_WebSocket.types.bif.zeek, <...>/Zeek_WebSocket.types.bif.zeek) 0.000000 MetaHookPre LoadFile(0, ./Zeek_X509.events.bif.zeek, <...>/Zeek_X509.events.bif.zeek) 0.000000 MetaHookPre LoadFile(0, ./Zeek_X509.functions.bif.zeek, <...>/Zeek_X509.functions.bif.zeek) 0.000000 MetaHookPre LoadFile(0, ./Zeek_X509.ocsp_events.bif.zeek, <...>/Zeek_X509.ocsp_events.bif.zeek) @@ -1678,6 +1690,10 @@ 0.000000 MetaHookPre LoadFileExtended(0, ./Zeek_Teredo.functions.bif.zeek, <...>/Zeek_Teredo.functions.bif.zeek) 0.000000 MetaHookPre LoadFileExtended(0, ./Zeek_UDP.events.bif.zeek, <...>/Zeek_UDP.events.bif.zeek) 0.000000 MetaHookPre LoadFileExtended(0, ./Zeek_VXLAN.events.bif.zeek, <...>/Zeek_VXLAN.events.bif.zeek) +0.000000 MetaHookPre LoadFileExtended(0, ./Zeek_WebSocket.consts.bif.zeek, <...>/Zeek_WebSocket.consts.bif.zeek) +0.000000 MetaHookPre LoadFileExtended(0, ./Zeek_WebSocket.events.bif.zeek, <...>/Zeek_WebSocket.events.bif.zeek) +0.000000 MetaHookPre LoadFileExtended(0, ./Zeek_WebSocket.functions.bif.zeek, <...>/Zeek_WebSocket.functions.bif.zeek) +0.000000 MetaHookPre LoadFileExtended(0, ./Zeek_WebSocket.types.bif.zeek, <...>/Zeek_WebSocket.types.bif.zeek) 0.000000 MetaHookPre LoadFileExtended(0, ./Zeek_X509.events.bif.zeek, <...>/Zeek_X509.events.bif.zeek) 0.000000 MetaHookPre LoadFileExtended(0, ./Zeek_X509.functions.bif.zeek, <...>/Zeek_X509.functions.bif.zeek) 0.000000 MetaHookPre LoadFileExtended(0, ./Zeek_X509.ocsp_events.bif.zeek, <...>/Zeek_X509.ocsp_events.bif.zeek) @@ -2314,6 +2330,10 @@ 0.000000 | HookLoadFile ./Zeek_Teredo.functions.bif.zeek <...>/Zeek_Teredo.functions.bif.zeek 0.000000 | HookLoadFile ./Zeek_UDP.events.bif.zeek <...>/Zeek_UDP.events.bif.zeek 0.000000 | HookLoadFile ./Zeek_VXLAN.events.bif.zeek <...>/Zeek_VXLAN.events.bif.zeek +0.000000 | HookLoadFile ./Zeek_WebSocket.consts.bif.zeek <...>/Zeek_WebSocket.consts.bif.zeek +0.000000 | HookLoadFile ./Zeek_WebSocket.events.bif.zeek <...>/Zeek_WebSocket.events.bif.zeek +0.000000 | HookLoadFile ./Zeek_WebSocket.functions.bif.zeek <...>/Zeek_WebSocket.functions.bif.zeek +0.000000 | HookLoadFile ./Zeek_WebSocket.types.bif.zeek <...>/Zeek_WebSocket.types.bif.zeek 0.000000 | HookLoadFile ./Zeek_X509.events.bif.zeek <...>/Zeek_X509.events.bif.zeek 0.000000 | HookLoadFile ./Zeek_X509.functions.bif.zeek <...>/Zeek_X509.functions.bif.zeek 0.000000 | HookLoadFile ./Zeek_X509.ocsp_events.bif.zeek <...>/Zeek_X509.ocsp_events.bif.zeek @@ -2603,6 +2623,10 @@ 0.000000 | HookLoadFileExtended ./Zeek_Teredo.functions.bif.zeek <...>/Zeek_Teredo.functions.bif.zeek 0.000000 | HookLoadFileExtended ./Zeek_UDP.events.bif.zeek <...>/Zeek_UDP.events.bif.zeek 0.000000 | HookLoadFileExtended ./Zeek_VXLAN.events.bif.zeek <...>/Zeek_VXLAN.events.bif.zeek +0.000000 | HookLoadFileExtended ./Zeek_WebSocket.consts.bif.zeek <...>/Zeek_WebSocket.consts.bif.zeek +0.000000 | HookLoadFileExtended ./Zeek_WebSocket.events.bif.zeek <...>/Zeek_WebSocket.events.bif.zeek +0.000000 | HookLoadFileExtended ./Zeek_WebSocket.functions.bif.zeek <...>/Zeek_WebSocket.functions.bif.zeek +0.000000 | HookLoadFileExtended ./Zeek_WebSocket.types.bif.zeek <...>/Zeek_WebSocket.types.bif.zeek 0.000000 | HookLoadFileExtended ./Zeek_X509.events.bif.zeek <...>/Zeek_X509.events.bif.zeek 0.000000 | HookLoadFileExtended ./Zeek_X509.functions.bif.zeek <...>/Zeek_X509.functions.bif.zeek 0.000000 | HookLoadFileExtended ./Zeek_X509.ocsp_events.bif.zeek <...>/Zeek_X509.ocsp_events.bif.zeek diff --git a/testing/btest/Baseline/scripts.base.files.x509.files/files.log b/testing/btest/Baseline/scripts.base.files.x509.files/files.log index e64dfc52c0..ce19924fa1 100644 --- a/testing/btest/Baseline/scripts.base.files.x509.files/files.log +++ b/testing/btest/Baseline/scripts.base.files.x509.files/files.log @@ -7,10 +7,10 @@ #open XXXX-XX-XX-XX-XX-XX #fields ts fuid uid id.orig_h id.orig_p id.resp_h id.resp_p source depth analyzers mime_type filename duration local_orig is_orig seen_bytes total_bytes missing_bytes overflow_bytes timedout parent_fuid md5 sha1 sha256 #types time string string addr port addr port string count set[string] string string interval bool bool count count count count bool string string string string -XXXXXXXXXX.XXXXXX FgN3AE3of2TRIqaeQe CHhAvVGS1DHFjwGM9 192.168.4.149 60623 74.125.239.129 443 SSL 0 SHA256,X509,SHA1,MD5 application/x-x509-user-cert - 0.000000 F F 1859 - 0 0 F - 7af07aca6d5c6e8e87fe4bb34786edc0 548b9e03bc183d1cd39f93a37985cb3950f8f06f 6bacfa4536150ed996f2b0c05ab6e345a257225f449aeb9d2018ccd88f4ede43 -XXXXXXXXXX.XXXXXX Fv2Agc4z5boBOacQi6 CHhAvVGS1DHFjwGM9 192.168.4.149 60623 74.125.239.129 443 SSL 0 SHA256,X509,SHA1,MD5 application/x-x509-ca-cert - 0.000000 F F 1032 - 0 0 F - 9e4ac96474245129d9766700412a1f89 d83c1a7f4d0446bb2081b81a1670f8183451ca24 a047a37fa2d2e118a4f5095fe074d6cfe0e352425a7632bf8659c03919a6c81d -XXXXXXXXXX.XXXXXX Ftmyeg2qgI2V38Dt3g CHhAvVGS1DHFjwGM9 192.168.4.149 60623 74.125.239.129 443 SSL 0 SHA256,X509,SHA1,MD5 application/x-x509-ca-cert - 0.000000 F F 897 - 0 0 F - 2e7db2a31d0e3da4b25f49b9542a2e1a 7359755c6df9a0abc3060bce369564c8ec4542a3 3c35cc963eb004451323d3275d05b353235053490d9cd83729a2faf5e7ca1cc0 -XXXXXXXXXX.XXXXXX FUFNf84cduA0IJCp07 ClEkJM2Vm5giqnMf4h 192.168.4.149 60624 74.125.239.129 443 SSL 0 SHA256,X509,SHA1,MD5 application/x-x509-user-cert - 0.000000 F F 1859 - 0 0 F - 7af07aca6d5c6e8e87fe4bb34786edc0 548b9e03bc183d1cd39f93a37985cb3950f8f06f 6bacfa4536150ed996f2b0c05ab6e345a257225f449aeb9d2018ccd88f4ede43 -XXXXXXXXXX.XXXXXX F1H4bd2OKGbLPEdHm4 ClEkJM2Vm5giqnMf4h 192.168.4.149 60624 74.125.239.129 443 SSL 0 SHA256,X509,SHA1,MD5 application/x-x509-ca-cert - 0.000000 F F 1032 - 0 0 F - 9e4ac96474245129d9766700412a1f89 d83c1a7f4d0446bb2081b81a1670f8183451ca24 a047a37fa2d2e118a4f5095fe074d6cfe0e352425a7632bf8659c03919a6c81d -XXXXXXXXXX.XXXXXX Fgsbci2jxFXYMOHOhi ClEkJM2Vm5giqnMf4h 192.168.4.149 60624 74.125.239.129 443 SSL 0 SHA256,X509,SHA1,MD5 application/x-x509-ca-cert - 0.000000 F F 897 - 0 0 F - 2e7db2a31d0e3da4b25f49b9542a2e1a 7359755c6df9a0abc3060bce369564c8ec4542a3 3c35cc963eb004451323d3275d05b353235053490d9cd83729a2faf5e7ca1cc0 +XXXXXXXXXX.XXXXXX FgN3AE3of2TRIqaeQe CHhAvVGS1DHFjwGM9 192.168.4.149 60623 74.125.239.129 443 SSL 0 X509,SHA256,SHA1,MD5 application/x-x509-user-cert - 0.000000 F F 1859 - 0 0 F - 7af07aca6d5c6e8e87fe4bb34786edc0 548b9e03bc183d1cd39f93a37985cb3950f8f06f 6bacfa4536150ed996f2b0c05ab6e345a257225f449aeb9d2018ccd88f4ede43 +XXXXXXXXXX.XXXXXX Fv2Agc4z5boBOacQi6 CHhAvVGS1DHFjwGM9 192.168.4.149 60623 74.125.239.129 443 SSL 0 X509,SHA256,SHA1,MD5 application/x-x509-ca-cert - 0.000000 F F 1032 - 0 0 F - 9e4ac96474245129d9766700412a1f89 d83c1a7f4d0446bb2081b81a1670f8183451ca24 a047a37fa2d2e118a4f5095fe074d6cfe0e352425a7632bf8659c03919a6c81d +XXXXXXXXXX.XXXXXX Ftmyeg2qgI2V38Dt3g CHhAvVGS1DHFjwGM9 192.168.4.149 60623 74.125.239.129 443 SSL 0 X509,SHA256,SHA1,MD5 application/x-x509-ca-cert - 0.000000 F F 897 - 0 0 F - 2e7db2a31d0e3da4b25f49b9542a2e1a 7359755c6df9a0abc3060bce369564c8ec4542a3 3c35cc963eb004451323d3275d05b353235053490d9cd83729a2faf5e7ca1cc0 +XXXXXXXXXX.XXXXXX FUFNf84cduA0IJCp07 ClEkJM2Vm5giqnMf4h 192.168.4.149 60624 74.125.239.129 443 SSL 0 X509,SHA256,SHA1,MD5 application/x-x509-user-cert - 0.000000 F F 1859 - 0 0 F - 7af07aca6d5c6e8e87fe4bb34786edc0 548b9e03bc183d1cd39f93a37985cb3950f8f06f 6bacfa4536150ed996f2b0c05ab6e345a257225f449aeb9d2018ccd88f4ede43 +XXXXXXXXXX.XXXXXX F1H4bd2OKGbLPEdHm4 ClEkJM2Vm5giqnMf4h 192.168.4.149 60624 74.125.239.129 443 SSL 0 X509,SHA256,SHA1,MD5 application/x-x509-ca-cert - 0.000000 F F 1032 - 0 0 F - 9e4ac96474245129d9766700412a1f89 d83c1a7f4d0446bb2081b81a1670f8183451ca24 a047a37fa2d2e118a4f5095fe074d6cfe0e352425a7632bf8659c03919a6c81d +XXXXXXXXXX.XXXXXX Fgsbci2jxFXYMOHOhi ClEkJM2Vm5giqnMf4h 192.168.4.149 60624 74.125.239.129 443 SSL 0 X509,SHA256,SHA1,MD5 application/x-x509-ca-cert - 0.000000 F F 897 - 0 0 F - 2e7db2a31d0e3da4b25f49b9542a2e1a 7359755c6df9a0abc3060bce369564c8ec4542a3 3c35cc963eb004451323d3275d05b353235053490d9cd83729a2faf5e7ca1cc0 #close XXXX-XX-XX-XX-XX-XX diff --git a/testing/btest/Baseline/scripts.base.protocols.websocket.broker-websocket/conn.log.cut b/testing/btest/Baseline/scripts.base.protocols.websocket.broker-websocket/conn.log.cut new file mode 100644 index 0000000000..f5bd2aa2ab --- /dev/null +++ b/testing/btest/Baseline/scripts.base.protocols.websocket.broker-websocket/conn.log.cut @@ -0,0 +1,3 @@ +### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63. +ts uid history service +XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 ShADadfF websocket,http diff --git a/testing/btest/Baseline/scripts.base.protocols.websocket.broker-websocket/websocket.log b/testing/btest/Baseline/scripts.base.protocols.websocket.broker-websocket/websocket.log new file mode 100644 index 0000000000..ba6652b2bb --- /dev/null +++ b/testing/btest/Baseline/scripts.base.protocols.websocket.broker-websocket/websocket.log @@ -0,0 +1,11 @@ +### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63. +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path websocket +#open XXXX-XX-XX-XX-XX-XX +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p host uri user_agent subprotocol client_protocols server_extensions client_extensions +#types time string addr port addr port string string string string vector[string] vector[string] vector[string] +XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 127.0.0.1 38776 127.0.0.1 27599 localhost:27599 /v1/messages/json Python/3.10 websockets/12.0 - - - permessage-deflate; client_max_window_bits +#close XXXX-XX-XX-XX-XX-XX diff --git a/testing/btest/Baseline/scripts.base.protocols.websocket.events/out b/testing/btest/Baseline/scripts.base.protocols.websocket.events/out new file mode 100644 index 0000000000..6c6a139ac6 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.protocols.websocket.events/out @@ -0,0 +1,91 @@ +### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63. +jupyter-websocket.pcap +websocket_handshake, CHhAvVGS1DHFjwGM9, 7, [ts=XXXXXXXXXX.XXXXXX, uid=CHhAvVGS1DHFjwGM9, id=[orig_h=127.0.0.1, orig_p=40492/tcp, resp_h=127.0.0.1, resp_p=51185/tcp], host=192.168.122.182, uri=/user/christian/api/kernels/f8645ecd-0a76-4bb1-9e6e-cb464276bc69/channels?session_id=deeecee7-efc2-42a1-a7c1-e1c0569436e3, user_agent=Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/118.0, subprotocol=v1.kernel.websocket.jupyter.org, client_protocols=[v1.kernel.websocket.jupyter.org], server_extensions=, client_extensions=[permessage-deflate]] +websocket_frame, CHhAvVGS1DHFjwGM9, T, fin, T, rsv, 0, opcode, binary, payload_len, 262 +websocket_frame_data, CHhAvVGS1DHFjwGM9, T, len, 262, data, \x06\x00\x00\x00\x00\x00\x00\x008\x00\x00\x00\x00\x00\x00\x00=\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x02\x01\x00\x00\x00\x00\x00\x00\x04\x01\x00\x00\x00\x00\x00\x00\x06\x01\x00\x00\x00\x00\x00\x00shell{"date":"2023-09-29T23:25:05.568Z","msg_id":"5af8fd02-14a1- +websocket_message, CHhAvVGS1DHFjwGM9, T, opcode, binary +websocket_frame, CHhAvVGS1DHFjwGM9, F, fin, T, rsv, 0, opcode, binary, payload_len, 539 +websocket_frame_data, CHhAvVGS1DHFjwGM9, F, len, 539, data, \x06\x00\x00\x00\x00\x00\x00\x008\x00\x00\x00\x00\x00\x00\x00=\x00\x00\x00\x00\x00\x00\x00\x14\x01\x00\x00\x00\x00\x00\x00\xfe\x01\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x1b\x02\x00\x00\x00\x00\x00\x00iopub{"msg_id": "5accb611-84744090d18c920147a97eb5_25702_7", "ms +websocket_message, CHhAvVGS1DHFjwGM9, F, opcode, binary +websocket_frame, CHhAvVGS1DHFjwGM9, F, fin, T, rsv, 0, opcode, binary, payload_len, 527 +websocket_frame_data, CHhAvVGS1DHFjwGM9, F, len, 527, data, \x06\x00\x00\x00\x00\x00\x00\x008\x00\x00\x00\x00\x00\x00\x00=\x00\x00\x00\x00\x00\x00\x00\x14\x01\x00\x00\x00\x00\x00\x00\xf2\x01\x00\x00\x00\x00\x00\x00\xf4\x01\x00\x00\x00\x00\x00\x00\x0f\x02\x00\x00\x00\x00\x00\x00iopub{"msg_id": "5accb611-84744090d18c920147a97eb5_25702_9", "ms +websocket_message, CHhAvVGS1DHFjwGM9, F, opcode, binary +websocket_frame, CHhAvVGS1DHFjwGM9, F, fin, T, rsv, 0, opcode, binary, payload_len, 1647 +websocket_frame_data, CHhAvVGS1DHFjwGM9, F, len, 1647, data, \x06\x00\x00\x00\x00\x00\x00\x008\x00\x00\x00\x00\x00\x00\x00=\x00\x00\x00\x00\x00\x00\x00 \x01\x00\x00\x00\x00\x00\x00\xf1\x01\x00\x00\x00\x00\x00\x00\xf3\x01\x00\x00\x00\x00\x00\x00o\x06\x00\x00\x00\x00\x00\x00shell{"msg_id": "5accb611-84744090d18c920147a97eb5_25702_14", "m +websocket_message, CHhAvVGS1DHFjwGM9, F, opcode, binary +websocket_frame, CHhAvVGS1DHFjwGM9, F, fin, T, rsv, 0, opcode, binary, payload_len, 540 +websocket_frame_data, CHhAvVGS1DHFjwGM9, F, len, 540, data, \x06\x00\x00\x00\x00\x00\x00\x008\x00\x00\x00\x00\x00\x00\x00=\x00\x00\x00\x00\x00\x00\x00\x15\x01\x00\x00\x00\x00\x00\x00\xff\x01\x00\x00\x00\x00\x00\x00\x01\x02\x00\x00\x00\x00\x00\x00\x1c\x02\x00\x00\x00\x00\x00\x00iopub{"msg_id": "5accb611-84744090d18c920147a97eb5_25702_10", "m +websocket_message, CHhAvVGS1DHFjwGM9, F, opcode, binary +websocket_frame, CHhAvVGS1DHFjwGM9, F, fin, T, rsv, 0, opcode, binary, payload_len, 540 +websocket_frame_data, CHhAvVGS1DHFjwGM9, F, len, 540, data, \x06\x00\x00\x00\x00\x00\x00\x008\x00\x00\x00\x00\x00\x00\x00=\x00\x00\x00\x00\x00\x00\x00\x15\x01\x00\x00\x00\x00\x00\x00\xff\x01\x00\x00\x00\x00\x00\x00\x01\x02\x00\x00\x00\x00\x00\x00\x1c\x02\x00\x00\x00\x00\x00\x00iopub{"msg_id": "5accb611-84744090d18c920147a97eb5_25702_12", "m +websocket_message, CHhAvVGS1DHFjwGM9, F, opcode, binary +websocket_frame, CHhAvVGS1DHFjwGM9, F, fin, T, rsv, 0, opcode, binary, payload_len, 515 +websocket_frame_data, CHhAvVGS1DHFjwGM9, F, len, 515, data, \x06\x00\x00\x00\x00\x00\x00\x008\x00\x00\x00\x00\x00\x00\x00=\x00\x00\x00\x00\x00\x00\x00\x15\x01\x00\x00\x00\x00\x00\x00\xe6\x01\x00\x00\x00\x00\x00\x00\xe8\x01\x00\x00\x00\x00\x00\x00\x03\x02\x00\x00\x00\x00\x00\x00iopub{"msg_id": "5accb611-84744090d18c920147a97eb5_25702_13", "m +websocket_message, CHhAvVGS1DHFjwGM9, F, opcode, binary +websocket_frame, CHhAvVGS1DHFjwGM9, F, fin, T, rsv, 0, opcode, binary, payload_len, 515 +websocket_frame_data, CHhAvVGS1DHFjwGM9, F, len, 515, data, \x06\x00\x00\x00\x00\x00\x00\x008\x00\x00\x00\x00\x00\x00\x00=\x00\x00\x00\x00\x00\x00\x00\x15\x01\x00\x00\x00\x00\x00\x00\xe6\x01\x00\x00\x00\x00\x00\x00\xe8\x01\x00\x00\x00\x00\x00\x00\x03\x02\x00\x00\x00\x00\x00\x00iopub{"msg_id": "5accb611-84744090d18c920147a97eb5_25702_15", "m +websocket_message, CHhAvVGS1DHFjwGM9, F, opcode, binary +websocket_frame, CHhAvVGS1DHFjwGM9, F, fin, T, rsv, 0, opcode, binary, payload_len, 540 +websocket_frame_data, CHhAvVGS1DHFjwGM9, F, len, 540, data, \x06\x00\x00\x00\x00\x00\x00\x008\x00\x00\x00\x00\x00\x00\x00=\x00\x00\x00\x00\x00\x00\x00\x15\x01\x00\x00\x00\x00\x00\x00\xff\x01\x00\x00\x00\x00\x00\x00\x01\x02\x00\x00\x00\x00\x00\x00\x1c\x02\x00\x00\x00\x00\x00\x00iopub{"msg_id": "5accb611-84744090d18c920147a97eb5_25702_16", "m +websocket_message, CHhAvVGS1DHFjwGM9, F, opcode, binary +websocket_frame, CHhAvVGS1DHFjwGM9, F, fin, T, rsv, 0, opcode, binary, payload_len, 540 +websocket_frame_data, CHhAvVGS1DHFjwGM9, F, len, 540, data, \x06\x00\x00\x00\x00\x00\x00\x008\x00\x00\x00\x00\x00\x00\x00=\x00\x00\x00\x00\x00\x00\x00\x15\x01\x00\x00\x00\x00\x00\x00\xff\x01\x00\x00\x00\x00\x00\x00\x01\x02\x00\x00\x00\x00\x00\x00\x1c\x02\x00\x00\x00\x00\x00\x00iopub{"msg_id": "5accb611-84744090d18c920147a97eb5_25702_18", "m +websocket_message, CHhAvVGS1DHFjwGM9, F, opcode, binary +websocket_frame, CHhAvVGS1DHFjwGM9, F, fin, T, rsv, 0, opcode, binary, payload_len, 540 +websocket_frame_data, CHhAvVGS1DHFjwGM9, F, len, 540, data, \x06\x00\x00\x00\x00\x00\x00\x008\x00\x00\x00\x00\x00\x00\x00=\x00\x00\x00\x00\x00\x00\x00\x15\x01\x00\x00\x00\x00\x00\x00\xff\x01\x00\x00\x00\x00\x00\x00\x01\x02\x00\x00\x00\x00\x00\x00\x1c\x02\x00\x00\x00\x00\x00\x00iopub{"msg_id": "5accb611-84744090d18c920147a97eb5_25702_20", "m +websocket_message, CHhAvVGS1DHFjwGM9, F, opcode, binary +websocket_frame, CHhAvVGS1DHFjwGM9, F, fin, T, rsv, 0, opcode, binary, payload_len, 540 +websocket_frame_data, CHhAvVGS1DHFjwGM9, F, len, 540, data, \x06\x00\x00\x00\x00\x00\x00\x008\x00\x00\x00\x00\x00\x00\x00=\x00\x00\x00\x00\x00\x00\x00\x15\x01\x00\x00\x00\x00\x00\x00\xff\x01\x00\x00\x00\x00\x00\x00\x01\x02\x00\x00\x00\x00\x00\x00\x1c\x02\x00\x00\x00\x00\x00\x00iopub{"msg_id": "5accb611-84744090d18c920147a97eb5_25702_21", "m +websocket_message, CHhAvVGS1DHFjwGM9, F, opcode, binary +websocket_frame, CHhAvVGS1DHFjwGM9, T, fin, T, rsv, 0, opcode, close, payload_len, 0 +websocket_close, CHhAvVGS1DHFjwGM9, T, status, 0, reason, +websocket_message, CHhAvVGS1DHFjwGM9, T, opcode, close +websocket_frame, CHhAvVGS1DHFjwGM9, F, fin, T, rsv, 0, opcode, close, payload_len, 0 +websocket_close, CHhAvVGS1DHFjwGM9, F, status, 0, reason, +websocket_message, CHhAvVGS1DHFjwGM9, F, opcode, close +wstunnel-http.pcap +websocket_handshake, CHhAvVGS1DHFjwGM9, 7, [ts=XXXXXXXXXX.XXXXXX, uid=CHhAvVGS1DHFjwGM9, id=[orig_h=127.0.0.1, orig_p=51102/tcp, resp_h=127.0.0.1, resp_p=8888/tcp], host=localhost:8888, uri=/v1/events, user_agent=, subprotocol=v1, client_protocols=[v1, authorization.bearer.eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6IjAxOGNmZWFiLWY5OWQtNzBmNy05NmFmLTBlOGJhNjk2YTFmNiIsInAiOiJUY3AiLCJyIjoiemVlay5vcmciLCJycCI6ODB9.FsquetBp_jsIDzBslWyyTPlS2hcMprVuWmbT2r57N0A], server_extensions=, client_extensions=] +websocket_frame, CHhAvVGS1DHFjwGM9, T, fin, T, rsv, 0, opcode, binary, payload_len, 72 +websocket_frame_data, CHhAvVGS1DHFjwGM9, T, len, 72, data, GET / HTTP/1.1\x0d\x0aHost: zeek.org\x0d\x0aUser-Agent: curl/7.81.0\x0d\x0aAccept: */*\x0d\x0a\x0d\x0a +websocket_message, CHhAvVGS1DHFjwGM9, T, opcode, binary +websocket_frame, CHhAvVGS1DHFjwGM9, F, fin, T, rsv, 0, opcode, binary, payload_len, 409 +websocket_frame_data, CHhAvVGS1DHFjwGM9, F, len, 409, data, HTTP/1.1 301 Moved Permanently\x0d\x0aServer: nginx\x0d\x0aDate: Fri, 12 Jan 2024 17:15:32 GMT\x0d\x0aContent-Type: text/html\x0d\x0aContent-Len +websocket_message, CHhAvVGS1DHFjwGM9, F, opcode, binary +websocket_frame, CHhAvVGS1DHFjwGM9, T, fin, T, rsv, 0, opcode, close, payload_len, 2 +websocket_close, CHhAvVGS1DHFjwGM9, T, status, 1000, reason, +websocket_frame_data, CHhAvVGS1DHFjwGM9, T, len, 2, data, \x03\xe8 +websocket_message, CHhAvVGS1DHFjwGM9, T, opcode, close +websocket_frame, CHhAvVGS1DHFjwGM9, F, fin, T, rsv, 0, opcode, close, payload_len, 2 +websocket_close, CHhAvVGS1DHFjwGM9, F, status, 1000, reason, +websocket_frame_data, CHhAvVGS1DHFjwGM9, F, len, 2, data, \x03\xe8 +websocket_message, CHhAvVGS1DHFjwGM9, F, opcode, close +broker-websocket.pcap +websocket_handshake, CHhAvVGS1DHFjwGM9, 7, [ts=XXXXXXXXXX.XXXXXX, uid=CHhAvVGS1DHFjwGM9, id=[orig_h=127.0.0.1, orig_p=38776/tcp, resp_h=127.0.0.1, resp_p=27599/tcp], host=localhost:27599, uri=/v1/messages/json, user_agent=Python/3.10 websockets/12.0, subprotocol=, client_protocols=, server_extensions=, client_extensions=[permessage-deflate; client_max_window_bits]] +websocket_frame, CHhAvVGS1DHFjwGM9, T, fin, T, rsv, 0, opcode, text, payload_len, 24 +websocket_frame_data, CHhAvVGS1DHFjwGM9, T, len, 24, data, ["/zeek/event/my_topic"] +websocket_message, CHhAvVGS1DHFjwGM9, T, opcode, text +websocket_frame, CHhAvVGS1DHFjwGM9, F, fin, T, rsv, 0, opcode, text, payload_len, 91 +websocket_frame_data, CHhAvVGS1DHFjwGM9, F, len, 91, data, {"type": "ack", "endpoint": "cfc03c41-7983-5fe2-b22e-6894100e6305", "version": "2.8.0-dev"} +websocket_message, CHhAvVGS1DHFjwGM9, F, opcode, text +websocket_frame, CHhAvVGS1DHFjwGM9, F, fin, T, rsv, 0, opcode, text, payload_len, 533 +websocket_frame_data, CHhAvVGS1DHFjwGM9, F, len, 533, data, {"type": "data-message", "topic": "/zeek/event/my_topic", "@data-type": "vector", "data": [{"@data-type": "count", "data +websocket_message, CHhAvVGS1DHFjwGM9, F, opcode, text +websocket_frame, CHhAvVGS1DHFjwGM9, T, fin, T, rsv, 0, opcode, text, payload_len, 361 +websocket_frame_data, CHhAvVGS1DHFjwGM9, T, len, 361, data, {"type": "data-message", "topic": "/zeek/event/my_topic", "@data-type": "vector", "data": [{"@data-type": "count", "data +websocket_message, CHhAvVGS1DHFjwGM9, T, opcode, text +websocket_frame, CHhAvVGS1DHFjwGM9, F, fin, T, rsv, 0, opcode, text, payload_len, 533 +websocket_frame_data, CHhAvVGS1DHFjwGM9, F, len, 533, data, {"type": "data-message", "topic": "/zeek/event/my_topic", "@data-type": "vector", "data": [{"@data-type": "count", "data +websocket_message, CHhAvVGS1DHFjwGM9, F, opcode, text +websocket_frame, CHhAvVGS1DHFjwGM9, T, fin, T, rsv, 0, opcode, text, payload_len, 361 +websocket_frame_data, CHhAvVGS1DHFjwGM9, T, len, 361, data, {"type": "data-message", "topic": "/zeek/event/my_topic", "@data-type": "vector", "data": [{"@data-type": "count", "data +websocket_message, CHhAvVGS1DHFjwGM9, T, opcode, text +websocket_frame, CHhAvVGS1DHFjwGM9, F, fin, T, rsv, 0, opcode, text, payload_len, 533 +websocket_frame_data, CHhAvVGS1DHFjwGM9, F, len, 533, data, {"type": "data-message", "topic": "/zeek/event/my_topic", "@data-type": "vector", "data": [{"@data-type": "count", "data +websocket_message, CHhAvVGS1DHFjwGM9, F, opcode, text +websocket_frame, CHhAvVGS1DHFjwGM9, T, fin, T, rsv, 0, opcode, text, payload_len, 361 +websocket_frame_data, CHhAvVGS1DHFjwGM9, T, len, 361, data, {"type": "data-message", "topic": "/zeek/event/my_topic", "@data-type": "vector", "data": [{"@data-type": "count", "data +websocket_message, CHhAvVGS1DHFjwGM9, T, opcode, text +websocket_frame, CHhAvVGS1DHFjwGM9, T, fin, T, rsv, 0, opcode, close, payload_len, 2 +websocket_close, CHhAvVGS1DHFjwGM9, T, status, 1000, reason, +websocket_frame_data, CHhAvVGS1DHFjwGM9, T, len, 2, data, \x03\xe8 +websocket_message, CHhAvVGS1DHFjwGM9, T, opcode, close diff --git a/testing/btest/Baseline/scripts.base.protocols.websocket.jupyter-websocket/conn.log.cut b/testing/btest/Baseline/scripts.base.protocols.websocket.jupyter-websocket/conn.log.cut new file mode 100644 index 0000000000..f5bd2aa2ab --- /dev/null +++ b/testing/btest/Baseline/scripts.base.protocols.websocket.jupyter-websocket/conn.log.cut @@ -0,0 +1,3 @@ +### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63. +ts uid history service +XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 ShADadfF websocket,http diff --git a/testing/btest/Baseline/scripts.base.protocols.websocket.jupyter-websocket/websocket.log b/testing/btest/Baseline/scripts.base.protocols.websocket.jupyter-websocket/websocket.log new file mode 100644 index 0000000000..c9c00fc79f --- /dev/null +++ b/testing/btest/Baseline/scripts.base.protocols.websocket.jupyter-websocket/websocket.log @@ -0,0 +1,11 @@ +### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63. +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path websocket +#open XXXX-XX-XX-XX-XX-XX +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p host uri user_agent subprotocol client_protocols server_extensions client_extensions +#types time string addr port addr port string string string string vector[string] vector[string] vector[string] +XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 127.0.0.1 40492 127.0.0.1 51185 192.168.122.182 /user/christian/api/kernels/f8645ecd-0a76-4bb1-9e6e-cb464276bc69/channels?session_id=deeecee7-efc2-42a1-a7c1-e1c0569436e3 Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/118.0 v1.kernel.websocket.jupyter.org v1.kernel.websocket.jupyter.org - permessage-deflate +#close XXXX-XX-XX-XX-XX-XX diff --git a/testing/btest/Baseline/scripts.base.protocols.websocket.wstunnel-http/conn.log.cut b/testing/btest/Baseline/scripts.base.protocols.websocket.wstunnel-http/conn.log.cut new file mode 100644 index 0000000000..bb892cdeb5 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.protocols.websocket.wstunnel-http/conn.log.cut @@ -0,0 +1,3 @@ +### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63. +ts uid history service +XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 ShADadFR websocket,http diff --git a/testing/btest/Baseline/scripts.base.protocols.websocket.wstunnel-http/http.log.cut b/testing/btest/Baseline/scripts.base.protocols.websocket.wstunnel-http/http.log.cut new file mode 100644 index 0000000000..0aa3a4d7a5 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.protocols.websocket.wstunnel-http/http.log.cut @@ -0,0 +1,4 @@ +### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63. +ts uid host uri status_code user_agent +XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 localhost:8888 /v1/events 301 - +XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 zeek.org / - curl/7.81.0 diff --git a/testing/btest/Baseline/scripts.base.protocols.websocket.wstunnel-http/websocket.log b/testing/btest/Baseline/scripts.base.protocols.websocket.wstunnel-http/websocket.log new file mode 100644 index 0000000000..e577952088 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.protocols.websocket.wstunnel-http/websocket.log @@ -0,0 +1,11 @@ +### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63. +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path websocket +#open XXXX-XX-XX-XX-XX-XX +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p host uri user_agent subprotocol client_protocols server_extensions client_extensions +#types time string addr port addr port string string string string vector[string] vector[string] vector[string] +XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 127.0.0.1 51102 127.0.0.1 8888 localhost:8888 /v1/events - v1 v1,authorization.bearer.eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6IjAxOGNmZWFiLWY5OWQtNzBmNy05NmFmLTBlOGJhNjk2YTFmNiIsInAiOiJUY3AiLCJyIjoiemVlay5vcmciLCJycCI6ODB9.FsquetBp_jsIDzBslWyyTPlS2hcMprVuWmbT2r57N0A - - +#close XXXX-XX-XX-XX-XX-XX diff --git a/testing/btest/Baseline/scripts.base.protocols.websocket.wstunnel-https/conn.log.cut b/testing/btest/Baseline/scripts.base.protocols.websocket.wstunnel-https/conn.log.cut new file mode 100644 index 0000000000..b61cd3bda1 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.protocols.websocket.wstunnel-https/conn.log.cut @@ -0,0 +1,3 @@ +### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63. +ts uid history service +XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 ShADadFR websocket,ssl,http diff --git a/testing/btest/Baseline/scripts.base.protocols.websocket.wstunnel-https/ssl.log.cut b/testing/btest/Baseline/scripts.base.protocols.websocket.wstunnel-https/ssl.log.cut new file mode 100644 index 0000000000..e98e26c97c --- /dev/null +++ b/testing/btest/Baseline/scripts.base.protocols.websocket.wstunnel-https/ssl.log.cut @@ -0,0 +1,3 @@ +### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63. +ts uid version server_name ssl_history +XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 TLSv13 zeek.org CsiI diff --git a/testing/btest/Baseline/scripts.base.protocols.websocket.wstunnel-https/websocket.log b/testing/btest/Baseline/scripts.base.protocols.websocket.wstunnel-https/websocket.log new file mode 100644 index 0000000000..a814ca5986 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.protocols.websocket.wstunnel-https/websocket.log @@ -0,0 +1,11 @@ +### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63. +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path websocket +#open XXXX-XX-XX-XX-XX-XX +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p host uri user_agent subprotocol client_protocols server_extensions client_extensions +#types time string addr port addr port string string string string vector[string] vector[string] vector[string] +XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 127.0.0.1 39992 127.0.0.1 8888 localhost:8888 /v1/events - v1 v1,authorization.bearer.eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6IjAxOGQwNTY1LTlmZTItNzFkZS1iNjRlLTU5MzhmZTI0ZmIyZCIsInAiOiJUY3AiLCJyIjoiMTkyLjAuNzguMTUwIiwicnAiOjQ0M30.xyDNRR4kK4fQSGfEyGzuUINn0xBVltxrFVBieMlqwEI - - +#close XXXX-XX-XX-XX-XX-XX diff --git a/testing/btest/Baseline/scripts.base.protocols.websocket.wstunnel-ssh-configure-wrong/conn.log.cut b/testing/btest/Baseline/scripts.base.protocols.websocket.wstunnel-ssh-configure-wrong/conn.log.cut new file mode 100644 index 0000000000..e8d2c4ae9a --- /dev/null +++ b/testing/btest/Baseline/scripts.base.protocols.websocket.wstunnel-ssh-configure-wrong/conn.log.cut @@ -0,0 +1,4 @@ +### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63. +ts uid history service +XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 ShADadR websocket,http +XXXXXXXXXX.XXXXXX ClEkJM2Vm5giqnMf4h ShADadR websocket,http diff --git a/testing/btest/Baseline/scripts.base.protocols.websocket.wstunnel-ssh-configure-wrong/websocket.log b/testing/btest/Baseline/scripts.base.protocols.websocket.wstunnel-ssh-configure-wrong/websocket.log new file mode 100644 index 0000000000..e993d7b4cf --- /dev/null +++ b/testing/btest/Baseline/scripts.base.protocols.websocket.wstunnel-ssh-configure-wrong/websocket.log @@ -0,0 +1,12 @@ +### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63. +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path websocket +#open XXXX-XX-XX-XX-XX-XX +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p host uri user_agent subprotocol client_protocols server_extensions client_extensions +#types time string addr port addr port string string string string vector[string] vector[string] vector[string] +XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 127.0.0.1 42906 127.0.0.1 8888 localhost:8888 /v1/events - v1 v1,authorization.bearer.eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6IjAxOGQwNTVkLTQ5OTgtNzI5Zi04Yjg2LTMwZTBiZWEyZGE4ZiIsInAiOiJUY3AiLCJyIjoiMTk1LjIwMS4xNDguMjA5IiwicnAiOjIyfQ.jjTNJL12tQbAuhTB9p_geFXRkEHkxcvOS6zf76qDklQ - - +XXXXXXXXXX.XXXXXX ClEkJM2Vm5giqnMf4h 127.0.0.1 46796 127.0.0.1 8888 localhost:8888 /v1/events - v1 v1,authorization.bearer.eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6IjAxOGQwNTVkLTc4MWYtNzNiYi1hZDkwLTEzNjA5NzRjY2JmMyIsInAiOiJUY3AiLCJyIjoiMTk1LjIwMS4xNDguMjA5IiwicnAiOjIyfQ.2HQ4uC23p_OYIXnQWeSZCqdA3jc_lVVH7-T5xZDPrz4 - - +#close XXXX-XX-XX-XX-XX-XX diff --git a/testing/btest/Baseline/scripts.base.protocols.websocket.wstunnel-ssh-configure/conn.log.cut b/testing/btest/Baseline/scripts.base.protocols.websocket.wstunnel-ssh-configure/conn.log.cut new file mode 100644 index 0000000000..72dcb1c5fa --- /dev/null +++ b/testing/btest/Baseline/scripts.base.protocols.websocket.wstunnel-ssh-configure/conn.log.cut @@ -0,0 +1,4 @@ +### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63. +ts uid history service +XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 ShADadR websocket,ssh,http +XXXXXXXXXX.XXXXXX ClEkJM2Vm5giqnMf4h ShADadR websocket,ssh,http diff --git a/testing/btest/Baseline/scripts.base.protocols.websocket.wstunnel-ssh-configure/ssh.log.cut b/testing/btest/Baseline/scripts.base.protocols.websocket.wstunnel-ssh-configure/ssh.log.cut new file mode 100644 index 0000000000..0780213a89 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.protocols.websocket.wstunnel-ssh-configure/ssh.log.cut @@ -0,0 +1,4 @@ +### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63. +ts uid client server auth_success auth_attempts kex_alg host_key_alg +XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 SSH-2.0-OpenSSH_8.9p1 Ubuntu-3ubuntu0.6 SSH-2.0-OpenSSH_8.2p1 Ubuntu-4ubuntu0.5 F 4 curve25519-sha256 ssh-ed25519 +XXXXXXXXXX.XXXXXX ClEkJM2Vm5giqnMf4h SSH-2.0-OpenSSH_8.9p1 Ubuntu-3ubuntu0.6 SSH-2.0-OpenSSH_8.2p1 Ubuntu-4ubuntu0.5 T 5 curve25519-sha256 ssh-ed25519 diff --git a/testing/btest/Baseline/scripts.base.protocols.websocket.wstunnel-ssh-configure/websocket.log b/testing/btest/Baseline/scripts.base.protocols.websocket.wstunnel-ssh-configure/websocket.log new file mode 100644 index 0000000000..e993d7b4cf --- /dev/null +++ b/testing/btest/Baseline/scripts.base.protocols.websocket.wstunnel-ssh-configure/websocket.log @@ -0,0 +1,12 @@ +### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63. +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path websocket +#open XXXX-XX-XX-XX-XX-XX +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p host uri user_agent subprotocol client_protocols server_extensions client_extensions +#types time string addr port addr port string string string string vector[string] vector[string] vector[string] +XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 127.0.0.1 42906 127.0.0.1 8888 localhost:8888 /v1/events - v1 v1,authorization.bearer.eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6IjAxOGQwNTVkLTQ5OTgtNzI5Zi04Yjg2LTMwZTBiZWEyZGE4ZiIsInAiOiJUY3AiLCJyIjoiMTk1LjIwMS4xNDguMjA5IiwicnAiOjIyfQ.jjTNJL12tQbAuhTB9p_geFXRkEHkxcvOS6zf76qDklQ - - +XXXXXXXXXX.XXXXXX ClEkJM2Vm5giqnMf4h 127.0.0.1 46796 127.0.0.1 8888 localhost:8888 /v1/events - v1 v1,authorization.bearer.eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6IjAxOGQwNTVkLTc4MWYtNzNiYi1hZDkwLTEzNjA5NzRjY2JmMyIsInAiOiJUY3AiLCJyIjoiMTk1LjIwMS4xNDguMjA5IiwicnAiOjIyfQ.2HQ4uC23p_OYIXnQWeSZCqdA3jc_lVVH7-T5xZDPrz4 - - +#close XXXX-XX-XX-XX-XX-XX diff --git a/testing/btest/Baseline/scripts.base.protocols.websocket.wstunnel-ssh/conn.log.cut b/testing/btest/Baseline/scripts.base.protocols.websocket.wstunnel-ssh/conn.log.cut new file mode 100644 index 0000000000..72dcb1c5fa --- /dev/null +++ b/testing/btest/Baseline/scripts.base.protocols.websocket.wstunnel-ssh/conn.log.cut @@ -0,0 +1,4 @@ +### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63. +ts uid history service +XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 ShADadR websocket,ssh,http +XXXXXXXXXX.XXXXXX ClEkJM2Vm5giqnMf4h ShADadR websocket,ssh,http diff --git a/testing/btest/Baseline/scripts.base.protocols.websocket.wstunnel-ssh/ssh.log.cut b/testing/btest/Baseline/scripts.base.protocols.websocket.wstunnel-ssh/ssh.log.cut new file mode 100644 index 0000000000..0780213a89 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.protocols.websocket.wstunnel-ssh/ssh.log.cut @@ -0,0 +1,4 @@ +### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63. +ts uid client server auth_success auth_attempts kex_alg host_key_alg +XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 SSH-2.0-OpenSSH_8.9p1 Ubuntu-3ubuntu0.6 SSH-2.0-OpenSSH_8.2p1 Ubuntu-4ubuntu0.5 F 4 curve25519-sha256 ssh-ed25519 +XXXXXXXXXX.XXXXXX ClEkJM2Vm5giqnMf4h SSH-2.0-OpenSSH_8.9p1 Ubuntu-3ubuntu0.6 SSH-2.0-OpenSSH_8.2p1 Ubuntu-4ubuntu0.5 T 5 curve25519-sha256 ssh-ed25519 diff --git a/testing/btest/Baseline/scripts.base.protocols.websocket.wstunnel-ssh/websocket.log b/testing/btest/Baseline/scripts.base.protocols.websocket.wstunnel-ssh/websocket.log new file mode 100644 index 0000000000..e993d7b4cf --- /dev/null +++ b/testing/btest/Baseline/scripts.base.protocols.websocket.wstunnel-ssh/websocket.log @@ -0,0 +1,12 @@ +### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63. +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path websocket +#open XXXX-XX-XX-XX-XX-XX +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p host uri user_agent subprotocol client_protocols server_extensions client_extensions +#types time string addr port addr port string string string string vector[string] vector[string] vector[string] +XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 127.0.0.1 42906 127.0.0.1 8888 localhost:8888 /v1/events - v1 v1,authorization.bearer.eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6IjAxOGQwNTVkLTQ5OTgtNzI5Zi04Yjg2LTMwZTBiZWEyZGE4ZiIsInAiOiJUY3AiLCJyIjoiMTk1LjIwMS4xNDguMjA5IiwicnAiOjIyfQ.jjTNJL12tQbAuhTB9p_geFXRkEHkxcvOS6zf76qDklQ - - +XXXXXXXXXX.XXXXXX ClEkJM2Vm5giqnMf4h 127.0.0.1 46796 127.0.0.1 8888 localhost:8888 /v1/events - v1 v1,authorization.bearer.eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6IjAxOGQwNTVkLTc4MWYtNzNiYi1hZDkwLTEzNjA5NzRjY2JmMyIsInAiOiJUY3AiLCJyIjoiMTk1LjIwMS4xNDguMjA5IiwicnAiOjIyfQ.2HQ4uC23p_OYIXnQWeSZCqdA3jc_lVVH7-T5xZDPrz4 - - +#close XXXX-XX-XX-XX-XX-XX diff --git a/testing/btest/Traces/websocket/broker-websocket.pcap b/testing/btest/Traces/websocket/broker-websocket.pcap new file mode 100644 index 0000000000..4d7ea41199 Binary files /dev/null and b/testing/btest/Traces/websocket/broker-websocket.pcap differ diff --git a/testing/btest/Traces/websocket/jupyter-websocket.pcap b/testing/btest/Traces/websocket/jupyter-websocket.pcap new file mode 100644 index 0000000000..6c2f292202 Binary files /dev/null and b/testing/btest/Traces/websocket/jupyter-websocket.pcap differ diff --git a/testing/btest/Traces/websocket/wstunnel-http.pcap b/testing/btest/Traces/websocket/wstunnel-http.pcap new file mode 100644 index 0000000000..338fe62374 Binary files /dev/null and b/testing/btest/Traces/websocket/wstunnel-http.pcap differ diff --git a/testing/btest/Traces/websocket/wstunnel-https.pcap b/testing/btest/Traces/websocket/wstunnel-https.pcap new file mode 100644 index 0000000000..ff653db770 Binary files /dev/null and b/testing/btest/Traces/websocket/wstunnel-https.pcap differ diff --git a/testing/btest/Traces/websocket/wstunnel-ssh.pcap b/testing/btest/Traces/websocket/wstunnel-ssh.pcap new file mode 100644 index 0000000000..29d1da9cd1 Binary files /dev/null and b/testing/btest/Traces/websocket/wstunnel-ssh.pcap differ diff --git a/testing/btest/scripts/base/protocols/websocket/broker-websocket.zeek b/testing/btest/scripts/base/protocols/websocket/broker-websocket.zeek new file mode 100644 index 0000000000..bd66b7ce7e --- /dev/null +++ b/testing/btest/scripts/base/protocols/websocket/broker-websocket.zeek @@ -0,0 +1,13 @@ +# @TEST-DOC: Test Broker WebSocket traffic. +# +# @TEST-EXEC: zeek -b -r $TRACES/websocket/broker-websocket.pcap %INPUT +# +# @TEST-EXEC: zeek-cut -m ts uid history service < conn.log > conn.log.cut + +# @TEST-EXEC: btest-diff conn.log.cut +# @TEST-EXEC: btest-diff websocket.log +# @TEST-EXEC: test ! -f analyzer.log +# @TEST-EXEC: test ! -f weird.log + +@load base/protocols/conn +@load base/protocols/websocket diff --git a/testing/btest/scripts/base/protocols/websocket/events.zeek b/testing/btest/scripts/base/protocols/websocket/events.zeek new file mode 100644 index 0000000000..27dc66d9eb --- /dev/null +++ b/testing/btest/scripts/base/protocols/websocket/events.zeek @@ -0,0 +1,38 @@ +# @TEST-DOC: Test WebSocket events. +# +# @TEST-EXEC: echo "jupyter-websocket.pcap" >>out +# @TEST-EXEC: zeek -b -r $TRACES/websocket/jupyter-websocket.pcap %INPUT >>out +# @TEST-EXEC: echo "wstunnel-http.pcap" >>out +# @TEST-EXEC: zeek -b -r $TRACES/websocket/wstunnel-http.pcap %INPUT >>out +# @TEST-EXEC: echo "broker-websocket.pcap" >>out +# @TEST-EXEC: zeek -b -r $TRACES//websocket/broker-websocket.pcap %INPUT >>out +# @TEST-EXEC: btest-diff out +# @TEST-EXEC: test ! -f analyzer.log +# @TEST-EXEC: test ! -f weird.log + +@load base/protocols/websocket + +event websocket_handshake(c: connection, aid: count) + { + print "websocket_handshake", c$uid, aid, c$websocket; + } + +event websocket_message(c: connection, is_orig: bool, opcode: count) + { + print "websocket_message", c$uid, is_orig, "opcode", WebSocket::opcodes[opcode]; + } + +event websocket_frame(c: connection, is_orig: bool, fin: bool, rsv: count, opcode: count, payload_len: count) + { + print "websocket_frame", c$uid, is_orig, "fin", fin, "rsv", rsv, "opcode", WebSocket::opcodes[opcode], "payload_len", payload_len; + } + +event websocket_frame_data(c: connection, is_orig: bool, data: string) + { + print "websocket_frame_data", c$uid, is_orig, "len", |data|, "data", data[:120]; + } + +event websocket_close(c: connection, is_orig: bool, status: count, reason: string) + { + print "websocket_close", c$uid, is_orig, "status", status, "reason", reason; + } diff --git a/testing/btest/scripts/base/protocols/websocket/jupyter-websocket.zeek b/testing/btest/scripts/base/protocols/websocket/jupyter-websocket.zeek new file mode 100644 index 0000000000..d7a62476ae --- /dev/null +++ b/testing/btest/scripts/base/protocols/websocket/jupyter-websocket.zeek @@ -0,0 +1,13 @@ +# @TEST-DOC: Testing Jupyter WebSocket traffic. +# +# @TEST-EXEC: zeek -b -r $TRACES/websocket/jupyter-websocket.pcap %INPUT +# +# @TEST-EXEC: zeek-cut -m ts uid history service < conn.log > conn.log.cut +# +# @TEST-EXEC: btest-diff conn.log.cut +# @TEST-EXEC: btest-diff websocket.log +# @TEST-EXEC: test ! -f analyzer.log +# @TEST-EXEC: test ! -f weird.log + +@load base/protocols/conn +@load base/protocols/websocket diff --git a/testing/btest/scripts/base/protocols/websocket/wstunnel-http.zeek b/testing/btest/scripts/base/protocols/websocket/wstunnel-http.zeek new file mode 100644 index 0000000000..5d676868a0 --- /dev/null +++ b/testing/btest/scripts/base/protocols/websocket/wstunnel-http.zeek @@ -0,0 +1,16 @@ +# @TEST-DOC: Test HTTP connection tunneled within WebSocket using wstunnel. Seems something in the HTTP scripts gets confused :-/ +# +# @TEST-EXEC: zeek -b -r $TRACES/websocket/wstunnel-http.pcap %INPUT +# +# @TEST-EXEC: zeek-cut -m ts uid history service < conn.log > conn.log.cut +# @TEST-EXEC: zeek-cut -m ts uid host uri status_code user_agent < http.log > http.log.cut + +# @TEST-EXEC: btest-diff conn.log.cut +# @TEST-EXEC: btest-diff http.log.cut +# @TEST-EXEC: btest-diff websocket.log +# @TEST-EXEC: test ! -f analyzer.log +# @TEST-EXEC: test ! -f weird.log + +@load base/protocols/conn +@load base/protocols/ssh +@load base/protocols/websocket diff --git a/testing/btest/scripts/base/protocols/websocket/wstunnel-https.zeek b/testing/btest/scripts/base/protocols/websocket/wstunnel-https.zeek new file mode 100644 index 0000000000..3212023b87 --- /dev/null +++ b/testing/btest/scripts/base/protocols/websocket/wstunnel-https.zeek @@ -0,0 +1,16 @@ +# @TEST-DOC: Test SSH connection tunneled within WebSocket using wstunnel. +# +# @TEST-EXEC: zeek -b -r $TRACES/websocket/wstunnel-https.pcap %INPUT +# +# @TEST-EXEC: zeek-cut -m ts uid history service < conn.log > conn.log.cut +# @TEST-EXEC: zeek-cut -m ts uid version server_name ssl_history < ssl.log > ssl.log.cut + +# @TEST-EXEC: btest-diff conn.log.cut +# @TEST-EXEC: btest-diff ssl.log.cut +# @TEST-EXEC: btest-diff websocket.log +# @TEST-EXEC: test ! -f analyzer.log +# @TEST-EXEC: test ! -f weird.log + +@load base/protocols/conn +@load base/protocols/ssl +@load base/protocols/websocket diff --git a/testing/btest/scripts/base/protocols/websocket/wstunnel-ssh-configure-wrong.zeek b/testing/btest/scripts/base/protocols/websocket/wstunnel-ssh-configure-wrong.zeek new file mode 100644 index 0000000000..bbcba7683a --- /dev/null +++ b/testing/btest/scripts/base/protocols/websocket/wstunnel-ssh-configure-wrong.zeek @@ -0,0 +1,21 @@ +# @TEST-DOC: Test SSH connection tunneled within WebSocket using wstunnel, attaches HTTP analyzer instead of SSH. +# +# @TEST-EXEC: zeek -b -r $TRACES/websocket/wstunnel-ssh.pcap %INPUT +# +# @TEST-EXEC: zeek-cut -m ts uid history service < conn.log > conn.log.cut + +# @TEST-EXEC: btest-diff conn.log.cut +# @TEST-EXEC: btest-diff websocket.log +# @TEST-EXEC: test ! -f ssh.log +# @TEST-EXEC: test ! -f analyzer.log + +@load base/protocols/conn +@load base/protocols/http +@load base/protocols/ssh +@load base/protocols/websocket + +hook WebSocket::configure_analyzer(c: connection, aid: count, config: WebSocket::AnalyzerConfig) + { + print "WebSocket::configure_analyzer", c$uid, aid; + config$analyzer = Analyzer::ANALYZER_HTTP; # this is obviously wrong :-) + } diff --git a/testing/btest/scripts/base/protocols/websocket/wstunnel-ssh-configure.zeek b/testing/btest/scripts/base/protocols/websocket/wstunnel-ssh-configure.zeek new file mode 100644 index 0000000000..560e9694a8 --- /dev/null +++ b/testing/btest/scripts/base/protocols/websocket/wstunnel-ssh-configure.zeek @@ -0,0 +1,22 @@ +# @TEST-DOC: Test SSH connection tunneled within WebSocket using wstunnel, configure SSH analyzer via hook explicitly. +# +# @TEST-EXEC: zeek -b -r $TRACES/websocket/wstunnel-ssh.pcap %INPUT +# +# @TEST-EXEC: zeek-cut -m ts uid history service < conn.log > conn.log.cut +# @TEST-EXEC: zeek-cut -m ts uid client server auth_success auth_attempts kex_alg host_key_alg < ssh.log > ssh.log.cut + +# @TEST-EXEC: btest-diff conn.log.cut +# @TEST-EXEC: btest-diff ssh.log.cut +# @TEST-EXEC: btest-diff websocket.log +# @TEST-EXEC: test ! -f analyzer.log +# @TEST-EXEC: test ! -f weird.log + +@load base/protocols/conn +@load base/protocols/ssh +@load base/protocols/websocket + +hook WebSocket::configure_analyzer(c: connection, aid: count, config: WebSocket::AnalyzerConfig) + { + print "WebSocket::configure_analyzer", c$uid, aid; + config$analyzer = Analyzer::ANALYZER_SSH; + } diff --git a/testing/btest/scripts/base/protocols/websocket/wstunnel-ssh.zeek b/testing/btest/scripts/base/protocols/websocket/wstunnel-ssh.zeek new file mode 100644 index 0000000000..02f445ed6c --- /dev/null +++ b/testing/btest/scripts/base/protocols/websocket/wstunnel-ssh.zeek @@ -0,0 +1,16 @@ +# @TEST-DOC: Test SSH connection tunneled within WebSocket using wstunnel. +# +# @TEST-EXEC: zeek -b -r $TRACES/websocket/wstunnel-ssh.pcap %INPUT +# +# @TEST-EXEC: zeek-cut -m ts uid history service < conn.log > conn.log.cut +# @TEST-EXEC: zeek-cut -m ts uid client server auth_success auth_attempts kex_alg host_key_alg < ssh.log > ssh.log.cut + +# @TEST-EXEC: btest-diff conn.log.cut +# @TEST-EXEC: btest-diff ssh.log.cut +# @TEST-EXEC: btest-diff websocket.log +# @TEST-EXEC: test ! -f analyzer.log +# @TEST-EXEC: test ! -f weird.log + +@load base/protocols/conn +@load base/protocols/ssh +@load base/protocols/websocket