Merge remote-tracking branch 'origin/master' into topic/johanna/tls12-decryption

This commit is contained in:
Johanna Amann 2021-10-13 10:49:29 +01:00
commit b8b6ac744e
1531 changed files with 109968 additions and 46436 deletions

View file

@ -13,10 +13,13 @@ memory: &MEMORY 4GB
config: &CONFIG --build-type=release --enable-cpp-tests --disable-broker-tests --prefix=$CIRRUS_WORKING_DIR/install config: &CONFIG --build-type=release --enable-cpp-tests --disable-broker-tests --prefix=$CIRRUS_WORKING_DIR/install
static_config: &STATIC_CONFIG --build-type=release --enable-cpp-tests --disable-broker-tests --enable-static-broker --enable-static-binpac --prefix=$CIRRUS_WORKING_DIR/install static_config: &STATIC_CONFIG --build-type=release --enable-cpp-tests --disable-broker-tests --enable-static-broker --enable-static-binpac --prefix=$CIRRUS_WORKING_DIR/install
sanitizer_config: &SANITIZER_CONFIG --build-type=debug --enable-cpp-tests --disable-broker-tests --sanitizers=address,undefined --enable-fuzzers --enable-coverage sanitizer_config: &SANITIZER_CONFIG --build-type=debug --enable-cpp-tests --disable-broker-tests --sanitizers=address,undefined --enable-fuzzers --enable-coverage
mobile_ipv6_config: &MOBILE_IPV6_CONFIG --build-type=release --enable-cpp-tests --enable-mobile-ipv6 --disable-broker-tests --prefix=$CIRRUS_WORKING_DIR/install
resources_template: &RESOURCES_TEMPLATE resources_template: &RESOURCES_TEMPLATE
cpu: *CPUS cpu: *CPUS
memory: *MEMORY memory: *MEMORY
# For greediness, see https://medium.com/cirruslabs/introducing-greedy-container-instances-29aad06dc2b4
greedy: true
macos_resources_template: &MACOS_RESOURCES_TEMPLATE macos_resources_template: &MACOS_RESOURCES_TEMPLATE
# https://medium.com/cirruslabs/new-macos-task-execution-architecture-for-cirrus-ci-604250627c94 # https://medium.com/cirruslabs/new-macos-task-execution-architecture-for-cirrus-ci-604250627c94
@ -77,12 +80,12 @@ env:
# This is the key used to create HMAC auth keys for the benchmark script. This # This is the key used to create HMAC auth keys for the benchmark script. This
# was generated by creating a new key using openssl, and then running sha256 # was generated by creating a new key using openssl, and then running sha256
# on it. # on it.
ZEEK_BENCHMARK_HMAC_KEY: ENCRYPTED[412224bbea9652030da976537f4d96c79ee79a0ba5a2f93b6c32953e1be0362defdf5fa07b3dc54ae61f9a52be30eac7] ZEEK_BENCHMARK_HMAC_KEY: ENCRYPTED[363e79b9942f348e53ab1f39f6ac8f7118bea2f4228ad1ef7b55981d3ef8d26dd756872f600ff40f2d7dcadb71f88513]
# This is the https endpoint host and port used for benchmarking. It's kept # This is the https endpoint host and port used for benchmarking. It's kept
# encrypted as a security measure to avoid leaking the host's information. # encrypted as a security measure to avoid leaking the host's information.
ZEEK_BENCHMARK_HOST: ENCRYPTED[62ecdc93e839800d754d09d9a9070e9cb9b209e7d7dd2472ba38648f786ff272d0e0ea71233d0910025f2c6f3771259c] ZEEK_BENCHMARK_HOST: ENCRYPTED[62ecdc93e839800d754d09d9a9070e9cb9b209e7d7dd2472ba38648f786ff272d0e0ea71233d0910025f2c6f3771259c]
ZEEK_BENCHMARK_PORT: ENCRYPTED[fb34ae2d51bac798fc01da052f3772154e17bbe2c1c5615509e82935248e748053fda399a0caf909632b6272cebff9f4] ZEEK_BENCHMARK_PORT: ENCRYPTED[b97fabf4d6bd5eef107c8469c5cb2c44e0107d89c220f43e7d1e7bdfb32dbdc2620855fee8e5a8d889458d5a6ac3e5c7]
# The repo token used for uploading data to Coveralls.io # The repo token used for uploading data to Coveralls.io
ZEEK_COVERALLS_REPO_TOKEN: ENCRYPTED[7ffd1e041f848f02b62f5abc7fda8a5a8a1561fbb2b46d88cefb67c74408ddeef6ea6f3b279c7953ca14ae9b4d050e2d] ZEEK_COVERALLS_REPO_TOKEN: ENCRYPTED[7ffd1e041f848f02b62f5abc7fda8a5a8a1561fbb2b46d88cefb67c74408ddeef6ea6f3b279c7953ca14ae9b4d050e2d]
@ -90,6 +93,13 @@ env:
# Linux EOL timelines: https://linuxlifecycle.com/ # Linux EOL timelines: https://linuxlifecycle.com/
# Fedora (~13 months): https://fedoraproject.org/wiki/Fedora_Release_Life_Cycle # Fedora (~13 months): https://fedoraproject.org/wiki/Fedora_Release_Life_Cycle
fedora34_task:
container:
# Fedora 34 EOL: Around May 2022
dockerfile: ci/fedora-34/Dockerfile
<< : *RESOURCES_TEMPLATE
<< : *CI_TEMPLATE
fedora33_task: fedora33_task:
container: container:
# Fedora 33 EOL: Around November 2022 # Fedora 33 EOL: Around November 2022
@ -97,13 +107,6 @@ fedora33_task:
<< : *RESOURCES_TEMPLATE << : *RESOURCES_TEMPLATE
<< : *CI_TEMPLATE << : *CI_TEMPLATE
fedora32_task:
container:
# Fedora 32 EOL: Around May 2021
dockerfile: ci/fedora-32/Dockerfile
<< : *RESOURCES_TEMPLATE
<< : *CI_TEMPLATE
centosstream8_task: centosstream8_task:
container: container:
# Stream 8 support should be 5 years, so until 2024. but I cannot find a concrete timeline --cpk # Stream 8 support should be 5 years, so until 2024. but I cannot find a concrete timeline --cpk
@ -130,6 +133,23 @@ centos7_task:
<< : *RESOURCES_TEMPLATE << : *RESOURCES_TEMPLATE
<< : *CI_TEMPLATE << : *CI_TEMPLATE
debian11_task:
container:
# Debian 11 EOL: June 2026
dockerfile: ci/debian-11/Dockerfile
<< : *RESOURCES_TEMPLATE
<< : *CI_TEMPLATE
debian11_static_task:
container:
# Just use a recent/common distro to run a static compile test.
# Debian 11 EOL: June 2026
dockerfile: ci/debian-11/Dockerfile
<< : *RESOURCES_TEMPLATE
<< : *CI_TEMPLATE
env:
ZEEK_CI_CONFIGURE_FLAGS: *STATIC_CONFIG
debian10_task: debian10_task:
container: container:
# Debian 10 EOL: June 2024 # Debian 10 EOL: June 2024
@ -137,16 +157,6 @@ debian10_task:
<< : *RESOURCES_TEMPLATE << : *RESOURCES_TEMPLATE
<< : *CI_TEMPLATE << : *CI_TEMPLATE
debian10_static_task:
container:
# Just uses a recent/common distro to run a static compile test.
# Debian 10 EOL: June 2024
dockerfile: ci/debian-10/Dockerfile
<< : *RESOURCES_TEMPLATE
<< : *CI_TEMPLATE
env:
ZEEK_CI_CONFIGURE_FLAGS: *STATIC_CONFIG
debian9_task: debian9_task:
container: container:
# Debian 9 EOL: June 2022 # Debian 9 EOL: June 2022
@ -168,6 +178,13 @@ opensuse_leap_15_2_task:
<< : *RESOURCES_TEMPLATE << : *RESOURCES_TEMPLATE
<< : *CI_TEMPLATE << : *CI_TEMPLATE
opensuse_leap_15_3_task:
container:
# Opensuse Leap 15.3 EOL: TBD
dockerfile: ci/opensuse-leap-15.3/Dockerfile
<< : *RESOURCES_TEMPLATE
<< : *CI_TEMPLATE
ubuntu20_task: ubuntu20_task:
container: container:
# Ubuntu 20.04 EOL: April 2025 # Ubuntu 20.04 EOL: April 2025
@ -181,13 +198,8 @@ ubuntu18_task:
dockerfile: ci/ubuntu-18.04/Dockerfile dockerfile: ci/ubuntu-18.04/Dockerfile
<< : *RESOURCES_TEMPLATE << : *RESOURCES_TEMPLATE
<< : *CI_TEMPLATE << : *CI_TEMPLATE
env:
ubuntu16_task: ZEEK_CI_CONFIGURE_FLAGS: *MOBILE_IPV6_CONFIG
container:
# Ubuntu 16.04 EOL: April 2021
dockerfile: ci/ubuntu-16.04/Dockerfile
<< : *RESOURCES_TEMPLATE
<< : *CI_TEMPLATE
alpine_task: alpine_task:
container: container:
@ -202,33 +214,47 @@ alpine_task:
# We aim to support both the current and previous macOS release. # We aim to support both the current and previous macOS release.
macos_big_sur_task: macos_big_sur_task:
macos_instance: macos_instance:
image: big-sur-base image: big-sur-xcode-12.5
prepare_script: ./ci/macos/prepare.sh prepare_script: ./ci/macos/prepare.sh
<< : *CI_TEMPLATE << : *CI_TEMPLATE
<< : *MACOS_RESOURCES_TEMPLATE << : *MACOS_RESOURCES_TEMPLATE
macos_catalina_task: macos_catalina_task:
macos_instance: macos_instance:
image: catalina-xcode-11.6 image: catalina-xcode
prepare_script: ./ci/macos/prepare.sh prepare_script: ./ci/macos/prepare.sh
<< : *CI_TEMPLATE << : *CI_TEMPLATE
<< : *MACOS_RESOURCES_TEMPLATE << : *MACOS_RESOURCES_TEMPLATE
# FreeBSD EOL timelines: https://www.freebsd.org/security/security.html#sup # FreeBSD EOL timelines: https://www.freebsd.org/security/security.html#sup
freebsd12_task: freebsd14_task:
freebsd_instance: freebsd_instance:
# FreeBSD 12 EOL: June 30, 2024 # We don't support FreeBSD 14 yet, this is a purely informative task
image_family: freebsd-12-2 image_family: freebsd-14-0-snap
cpu: 8
# Not allowed to request less than 8GB for an 8 CPU FreeBSD VM.
memory: 8GB
allow_failures: true
skip_notification: true
prepare_script: ./ci/freebsd/prepare.sh
<< : *CI_TEMPLATE
freebsd13_task:
freebsd_instance:
# FreeBSD 13 EOL: January 31, 2026
image_family: freebsd-13-0
cpu: 8 cpu: 8
# Not allowed to request less than 8GB for an 8 CPU FreeBSD VM. # Not allowed to request less than 8GB for an 8 CPU FreeBSD VM.
memory: 8GB memory: 8GB
prepare_script: ./ci/freebsd/prepare.sh prepare_script: ./ci/freebsd/prepare.sh
<< : *CI_TEMPLATE << : *CI_TEMPLATE
freebsd11_task: freebsd12_task:
freebsd_instance: freebsd_instance:
# FreeBSD 11 EOL: September 30, 2021 # FreeBSD 12 EOL: June 30, 2024
image_family: freebsd-11-4 image_family: freebsd-12-2
cpu: 8 cpu: 8
# Not allowed to request less than 8GB for an 8 CPU FreeBSD VM. # Not allowed to request less than 8GB for an 8 CPU FreeBSD VM.
memory: 8GB memory: 8GB
@ -249,4 +275,5 @@ sanitizer_task:
CXXFLAGS: -DZEEK_DICT_DEBUG CXXFLAGS: -DZEEK_DICT_DEBUG
ZEEK_CI_CONFIGURE_FLAGS: *SANITIZER_CONFIG ZEEK_CI_CONFIGURE_FLAGS: *SANITIZER_CONFIG
ZEEK_TAILORED_UB_CHECKS: 1 ZEEK_TAILORED_UB_CHECKS: 1
ZEEK_CI_DISABLE_SCRIPT_PROFILING: 1
UBSAN_OPTIONS: print_stacktrace=1 UBSAN_OPTIONS: print_stacktrace=1

105
.clang-format Normal file
View file

@ -0,0 +1,105 @@
# Clang-format configuration for Zeek. This configuration requires
# at least clang-format 12.0.1 to format correctly.
#
# The easiest way to run this from the command-line is using the
# python script in auxil/run-clang-format:
#
# python3 auxil/run-clang-format/run-clang-format.py --clang-format-executable /path/to/clang-format -r src -i
Language: Cpp
Standard: c++17
BreakBeforeBraces: Whitesmiths
# BraceWrapping:
# AfterCaseLabel: true
# AfterClass: false
# AfterControlStatement: Always
# AfterEnum: false
# AfterFunction: true
# AfterNamespace: false
# AfterStruct: false
# AfterUnion: false
# AfterExternBlock: false
# BeforeCatch: true
# BeforeElse: true
# BeforeWhile: false
# IndentBraces: true
# SplitEmptyFunction: false
# SplitEmptyRecord: false
# SplitEmptyNamespace: false
AccessModifierOffset: -4
AlignAfterOpenBracket: Align
AlignTrailingComments: false
AllowShortBlocksOnASingleLine: Empty
AllowShortEnumsOnASingleLine: true
AllowShortFunctionsOnASingleLine: Inline
AllowShortIfStatementsOnASingleLine: false
AllowShortLambdasOnASingleLine: Empty
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterReturnType: None
BinPackArguments: true
BinPackParameters: true
BreakConstructorInitializers: BeforeColon
BreakInheritanceList: BeforeColon
ColumnLimit: 100
ConstructorInitializerAllOnOneLineOrOnePerLine: false
FixNamespaceComments: false
IndentCaseLabels: true
IndentCaseBlocks: false
IndentExternBlock: NoIndent
IndentPPDirectives: None
IndentWidth: 4
NamespaceIndentation: None
PointerAlignment: Left
SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: true
SpaceBeforeAssignmentOperators: true
SpaceBeforeCpp11BracedList: false
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatements
SpaceBeforeRangeBasedForLoopColon: true
SpaceInEmptyBlock: true
SpaceInEmptyParentheses: false
SpacesInAngles: false
SpacesInConditionalStatement: true
SpacesInContainerLiterals: false
SpacesInParentheses: false
TabWidth: 4
UseTab: AlignWithSpaces
# Setting this to a high number causes clang-format to prefer breaking somewhere else
# over breaking after the assignment operator in a line that's over the column limit
PenaltyBreakAssignment: 100
IncludeBlocks: Regroup
# Include categories go like this:
# 0: reserved, since this automatically is the primary header for any .cc file
# 1: zeek-config.h
# 2: any c-style header
# 3: any c++-style header
# 4: any header that starts with "zeek/"
# 5: everything else, which should catch any of the auto-generated code from the
# build directory as well
#
# Sections 0-1 and 2-3 get grouped together in their respective blocks
IncludeCategories:
- Regex: '^"zeek-config\.h"'
Priority: 1
SortPriority: 1
- Regex: '^"zeek/zeek-config\.h"'
Priority: 1
SortPriority: 2
- Regex: '^<[[:print:]]+\.(h|hh)>'
Priority: 2
SortPriority: 2
- Regex: '^<[[:print:]]+>'
Priority: 2
SortPriority: 3
- Regex: '^"zeek/'
Priority: 4
- Regex: '.*'
Priority: 5

17
.clang-format-ignore Normal file
View file

@ -0,0 +1,17 @@
# Ignore everything 3rdparty
src/3rdparty/*
# These are files that are technically sourced from other places but aren't in 3rdparty
# and shouldn't be reformatted.
src/ConvertUTF.*
src/bro_inet_ntop.*
src/bsd-getopt-long.*
src/in_cksum.*
src/nb_dns.*
src/modp_numtoa.*
src/patricia.*
src/strsep.c
src/setsignal.c
# These files are generated code
src/DebugCmdInfoConstants.*

3
.dockerignore Normal file
View file

@ -0,0 +1,3 @@
**/.tmp
**/.btest.failed.dat
**/diag.log

93
.github/workflows/docker.yml vendored Normal file
View file

@ -0,0 +1,93 @@
name: Check and publish Docker images
on:
pull_request:
push:
branches: [master]
tags:
- 'v*'
- '!v*-dev'
- 'release'
defaults:
run:
shell: bash
jobs:
build:
runs-on: ubuntu-latest
env:
TEST_TAG: zeek:latest
CONFFLAGS: --generator=Ninja --build-type=Release
steps:
- uses: actions/checkout@v2
with:
submodules: "recursive"
# Create and boot a loader. This will e.g., provide caching
# so we avoid rebuilds of the same image after this step.
- uses: docker/setup-buildx-action@v1
- name: Build
uses: docker/build-push-action@v2
with:
context: ./
file: docker/Dockerfile
build-args: |
CONFFLAGS=${{ env.CONFFLAGS }}
load: true
tags: ${{ env.TEST_TAG }}
- name: Run btests
run: make -C docker/btest
- name: Get version
id: version
run: echo "::set-output name=RELEASE_VERSION::$(cat VERSION)"
- name: Compute target tag
id: target
env:
RELEASE_VERSION: ${{ steps.version.outputs.RELEASE_VERSION }}
run: |
# Translate the Github reference into a tag name.
#
# - `release` tag maps to `zeek:latest`
# - `v*` tag (excluding `v*-dev` tags) maps to `zeek:RELEASE_VERSION`
# - `master` branch maps to `zeek-dev:latest`
#
# Any other refs are not published below.
if [ "${GITHUB_REF}" = "refs/tags/release" ]; then
echo "::set-output name=tag::zeek:latest"
elif [ "${GITHUB_REF}" = "refs/heads/master" ]; then
echo "::set-output name=tag::zeek-dev:latest"
elif [[ "${GITHUB_REF}" = refs/heads/v* ]] && [[ "${GITHUB_REF}" != refs/heads/v*-dev ]]; then
echo "::set-output name=tag::zeek:${RELEASE_VERSION}"
fi
- name: Login to DockerHub
uses: docker/login-action@v1
# Secrets for the login are not available for pull requests.
if: github.event_name == 'push'
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Push
# Only publish if we did compute a tag.
if: github.event_name == 'push' && steps.target.outputs.tag != ''
uses: docker/build-push-action@v2
with:
context: ./
file: docker/Dockerfile
build-args: |
CONFFLAGS=${{ env.CONFFLAGS }}
push: true
tags: |
zeekurity/${{ steps.target.outputs.tag }}
- name: Preserve artifacts
uses: actions/upload-artifact@v2
if: failure()
with:
name: docker-btest
path: docker/btest/.tmp
if-no-files-found: ignore

View file

@ -92,3 +92,16 @@ jobs:
git add doc git add doc
git status git status
git commit -m 'Update doc submodule [nomail] [skip ci]' && git push auth master || /bin/true git commit -m 'Update doc submodule [nomail] [skip ci]' && git push auth master || /bin/true
- name: Send email
if: failure()
uses: dawidd6/action-send-mail@v3.4.1
with:
server_address: ${{secrets.SMTP_HOST}}
server_port: ${{secrets.SMTP_PORT}}
username: ${{secrets.SMTP_USER}}
password: ${{secrets.SMTP_PASS}}
subject: generate-docs Github Action failed!
body: generate-docs job of ${{github.repository}} Failed! See https://github.com/${{github.repository}}/actions/runs/${{github.run_id}} for details.
to: ${{secrets.MAIL_TO}}
from: Github Actions <${{secrets.MAIL_FROM}}>

8
.gitignore vendored
View file

@ -1,4 +1,7 @@
build # Ignore anything prefixed with build since people
# tend to name all of their build directories prefixed that way.
build*
tmp tmp
*.gcov *.gcov
@ -11,3 +14,6 @@ cmake-build-*
# ignore pyenv local settings # ignore pyenv local settings
.python-version .python-version
# clangd
.cache

6
.gitmodules vendored
View file

@ -46,3 +46,9 @@
[submodule "auxil/package-manager"] [submodule "auxil/package-manager"]
path = auxil/package-manager path = auxil/package-manager
url = https://github.com/zeek/package-manager url = https://github.com/zeek/package-manager
[submodule "auxil/zeek-client"]
path = auxil/zeek-client
url = https://github.com/zeek/zeek-client
[submodule "auxil/run-clang-format"]
path = auxil/run-clang-format
url = https://github.com/Sarcasm/run-clang-format

1494
CHANGES

File diff suppressed because it is too large Load diff

View file

@ -147,6 +147,10 @@ if ( ZEEK_SANITIZERS )
set(ZEEK_SANITIZERS "${ZEEK_SANITIZERS},") set(ZEEK_SANITIZERS "${ZEEK_SANITIZERS},")
endif () endif ()
if ( _sanitizer STREQUAL "thread" )
set(ZEEK_TSAN true)
endif ()
if ( NOT _sanitizer STREQUAL "undefined" ) if ( NOT _sanitizer STREQUAL "undefined" )
set(ZEEK_SANITIZERS "${ZEEK_SANITIZERS}${_sanitizer}") set(ZEEK_SANITIZERS "${ZEEK_SANITIZERS}${_sanitizer}")
continue() continue()
@ -490,10 +494,10 @@ endif()
# Tell the plugin code that we're building as part of the main tree. # Tell the plugin code that we're building as part of the main tree.
set(ZEEK_PLUGIN_INTERNAL_BUILD true CACHE INTERNAL "" FORCE) set(ZEEK_PLUGIN_INTERNAL_BUILD true CACHE INTERNAL "" FORCE)
set(DEFAULT_ZEEKPATH .:${ZEEK_SCRIPT_INSTALL_PATH}:${ZEEK_SCRIPT_INSTALL_PATH}/policy:${ZEEK_SCRIPT_INSTALL_PATH}/site) set(DEFAULT_ZEEKPATH .:${ZEEK_SCRIPT_INSTALL_PATH}:${ZEEK_SCRIPT_INSTALL_PATH}/policy:${ZEEK_SCRIPT_INSTALL_PATH}/site:${ZEEK_SCRIPT_INSTALL_PATH}/builtin-plugins)
if ( NOT BINARY_PACKAGING_MODE ) if ( NOT BINARY_PACKAGING_MODE )
set(ZEEK_DIST ${CMAKE_SOURCE_DIR}) set(ZEEK_DIST ${PROJECT_SOURCE_DIR})
endif () endif ()
string(TOLOWER ${CMAKE_BUILD_TYPE} CMAKE_BUILD_TYPE_LOWER) string(TOLOWER ${CMAKE_BUILD_TYPE} CMAKE_BUILD_TYPE_LOWER)
@ -539,12 +543,16 @@ if ( GooglePerftools_INCLUDE_DIR )
set(ZEEK_CONFIG_GooglePerftools_INCLUDE_DIR ${GooglePerftools_INCLUDE_DIR}) set(ZEEK_CONFIG_GooglePerftools_INCLUDE_DIR ${GooglePerftools_INCLUDE_DIR})
endif () endif ()
set(ZEEK_CONFIG_BTEST_TOOLS_DIR ${ZEEK_ROOT_DIR}/share/btest)
install(DIRECTORY DESTINATION ${ZEEK_CONFIG_BTEST_TOOLS_DIR})
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/zeek-config.in configure_file(${CMAKE_CURRENT_SOURCE_DIR}/zeek-config.in
${CMAKE_CURRENT_BINARY_DIR}/zeek-config @ONLY) ${CMAKE_CURRENT_BINARY_DIR}/zeek-config @ONLY)
install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/zeek-config DESTINATION bin) install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/zeek-config DESTINATION bin)
install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/cmake DESTINATION share/zeek install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/cmake DESTINATION share/zeek
USE_SOURCE_PERMISSIONS) USE_SOURCE_PERMISSIONS
PATTERN ".git" EXCLUDE)
# Install wrapper script for Bro-to-Zeek renaming. # Install wrapper script for Bro-to-Zeek renaming.
include(InstallShellScript) include(InstallShellScript)
@ -570,12 +578,41 @@ if ( INSTALL_ZKG )
DESTINATION ${ZEEK_ZKG_CONFIG_DIR} RENAME config) DESTINATION ${ZEEK_ZKG_CONFIG_DIR} RENAME config)
endif () endif ()
########################################################################
## Look for external plugins to build in
string(REPLACE "," " " _build_in_plugins "${ZEEK_INCLUDE_PLUGINS}")
separate_arguments(_build_in_plugins)
foreach(plugin_dir ${_build_in_plugins})
if ( NOT IS_ABSOLUTE "${plugin_dir}/CMakeLists.txt" )
message(FATAL_ERROR "Plugins to build in need to be defined with absolute path! ${plugin_dir}")
endif()
if ( NOT EXISTS "${plugin_dir}/CMakeLists.txt" )
message(FATAL_ERROR "No plugin found at ${plugin_dir}!")
endif()
get_filename_component(plugin_name ${plugin_dir} NAME)
# Create a list of plugin directories that will then be added in the src/CMakeLists.txt
list(APPEND BUILTIN_PLUGIN_LIST ${plugin_dir})
message(STATUS " Building in plugin: ${plugin_name} (${plugin_dir})")
if ( "${ZEEK_BUILTIN_PLUGINS}" STREQUAL "" )
set(ZEEK_BUILTIN_PLUGINS ${plugin_name})
else ()
set(ZEEK_BUILTIN_PLUGINS "${ZEEK_BUILTIN_PLUGINS}, ${plugin_name}")
endif ()
endforeach()
######################################################################## ########################################################################
## Recurse on sub-directories ## Recurse on sub-directories
add_subdirectory(src) add_subdirectory(src)
add_subdirectory(scripts) add_subdirectory(scripts)
add_subdirectory(man) add_subdirectory(man)
add_subdirectory(testing)
include(CheckOptionalBuildSources) include(CheckOptionalBuildSources)
@ -584,11 +621,12 @@ CheckOptionalBuildSources(auxil/package-manager ZKG INSTALL_ZKG)
CheckOptionalBuildSources(auxil/zeekctl ZeekControl INSTALL_ZEEKCTL) CheckOptionalBuildSources(auxil/zeekctl ZeekControl INSTALL_ZEEKCTL)
CheckOptionalBuildSources(auxil/zeek-aux Zeek-Aux INSTALL_AUX_TOOLS) CheckOptionalBuildSources(auxil/zeek-aux Zeek-Aux INSTALL_AUX_TOOLS)
CheckOptionalBuildSources(auxil/zeek-archiver ZeekArchiver INSTALL_ZEEK_ARCHIVER) CheckOptionalBuildSources(auxil/zeek-archiver ZeekArchiver INSTALL_ZEEK_ARCHIVER)
CheckOptionalBuildSources(auxil/zeek-client ZeekClient INSTALL_ZEEK_CLIENT)
######################################################################## ########################################################################
## Packaging Setup ## Packaging Setup
if ( INSTALL_ZEEKCTL OR INSTALL_ZKG ) if ( INSTALL_ZEEKCTL OR INSTALL_ZKG OR INSTALL_ZEEK_CLIENT )
# CPack RPM Generator may not automatically detect this # CPack RPM Generator may not automatically detect this
set(CPACK_RPM_PACKAGE_REQUIRES "python >= ${ZEEK_PYTHON_MIN}") set(CPACK_RPM_PACKAGE_REQUIRES "python >= ${ZEEK_PYTHON_MIN}")
endif () endif ()
@ -608,17 +646,24 @@ if (CMAKE_BUILD_TYPE)
string(TOUPPER ${CMAKE_BUILD_TYPE} BuildType) string(TOUPPER ${CMAKE_BUILD_TYPE} BuildType)
endif () endif ()
if ( INSTALL_BTEST_PCAPS )
set(_install_btest_tools_msg "all")
else ()
set(_install_btest_tools_msg "no pcaps")
endif ()
message( message(
"\n====================| Zeek Build Summary |====================" "\n====================| Zeek Build Summary |===================="
"\n" "\n"
"\nBuild type: ${CMAKE_BUILD_TYPE}" "\nBuild type: ${CMAKE_BUILD_TYPE}"
"\nBuild dir: ${CMAKE_BINARY_DIR}" "\nBuild dir: ${PROJECT_BINARY_DIR}"
"\nInstall prefix: ${CMAKE_INSTALL_PREFIX}" "\nInstall prefix: ${CMAKE_INSTALL_PREFIX}"
"\nPlugin dir: ${BRO_PLUGIN_INSTALL_PATH}" "\nPlugin dir: ${BRO_PLUGIN_INSTALL_PATH}"
"\nPython module dir: ${PY_MOD_INSTALL_DIR}" "\nPython module dir: ${PY_MOD_INSTALL_DIR}"
"\nZeek Script Path: ${ZEEK_SCRIPT_INSTALL_PATH}" "\nZeek Script Path: ${ZEEK_SCRIPT_INSTALL_PATH}"
"\nDebug mode: ${ENABLE_DEBUG}" "\nDebug mode: ${ENABLE_DEBUG}"
"\nUnit tests: ${ENABLE_ZEEK_UNIT_TESTS}" "\nUnit tests: ${ENABLE_ZEEK_UNIT_TESTS}"
"\nBuiltin Plugins: ${ZEEK_BUILTIN_PLUGINS}"
"\n" "\n"
"\nCC: ${CMAKE_C_COMPILER}" "\nCC: ${CMAKE_C_COMPILER}"
"\nCFLAGS: ${CMAKE_C_FLAGS} ${CMAKE_C_FLAGS_${BuildType}}" "\nCFLAGS: ${CMAKE_C_FLAGS} ${CMAKE_C_FLAGS_${BuildType}}"
@ -629,6 +674,7 @@ message(
"\nZeekControl: ${INSTALL_ZEEKCTL}" "\nZeekControl: ${INSTALL_ZEEKCTL}"
"\nAux. Tools: ${INSTALL_AUX_TOOLS}" "\nAux. Tools: ${INSTALL_AUX_TOOLS}"
"\nBTest: ${INSTALL_BTEST}" "\nBTest: ${INSTALL_BTEST}"
"\nBTest tooling: ${_install_btest_tools_msg}"
"\nzkg: ${INSTALL_ZKG}" "\nzkg: ${INSTALL_ZKG}"
"\n" "\n"
"\nlibmaxminddb: ${USE_GEOIP}" "\nlibmaxminddb: ${USE_GEOIP}"

252
NEWS
View file

@ -3,6 +3,59 @@ This document summarizes the most important changes in the current Zeek
release. For an exhaustive list of changes, see the ``CHANGES`` file release. For an exhaustive list of changes, see the ``CHANGES`` file
(note that submodules, such as Broker, come with their own ``CHANGES``.) (note that submodules, such as Broker, come with their own ``CHANGES``.)
Zeek 4.2.0
==========
New Functionality
-----------------
- We now provide minimal official Docker images for the Zeek project via two
repositories on the Docker hub, ``zeekurity/zeek`` and ``zeekurity/zeek-dev``.
The former receives all Zeek release versions, with tag ``zeek:latest`` being
the most recent. An image corresponding to our latest merge into the master
branch is tagged at ``zeek-dev:latest``.
The images run Debian and provide a full install of the Zeek distribution into
``/usr/local/zeek``. They do not set Zeek-specific entrypoints or provide any
particular configuration for operationally running Zeek. To keep the images
lightweight they also do not contain a development toolchain as needed for
example to build a Zeek plugin. You can add any required system packages in a
derived image, or install them directly in the running container.
- Zeek now supports formatting the C++ code using clang-format. It requires at
least clang-format 12.0.1 due to some additions that were made in that version
to better support the Whitesmiths style. Zeek also includes a set of python
scripts to more easily reformat in the auxil/run-clang-format directory. An
example command to reformat the code:
`python3 auxil/run-clang-format/run-clang-format.py --clang-format-executable `which clang-format-12` -r src -i`
- Experimental support for speeding up Zeek script execution by compiling
scripts to a low-level form called "ZAM". You activate this feature by
specifying ``-O ZAM`` on the command line. See
``src/script_opt/ZAM/README.md`` for more information.
Changed Functionality
---------------------
- Zeek now treats non-atomic index types for sets and tables more consistently.
Indexing now generally works with any types Zeek's hashing subsystem knows how
to serialize, meaning that you can now also index with sets, vectors,
patterns, and even tables.
- The traditional TSV Zeek logs are now valid UTF8 by default. It's possible
to revert to the previous behavior by setting ``LogAscii::enable_utf_8`` to
false.
- The ``SYN_packet`` record now records TCP timestamps (TSval/TSecr)
when available.
Removed Functionality
---------------------
Deprecated Functionality
------------------------
Zeek 4.1.0 Zeek 4.1.0
========== ==========
@ -19,6 +72,9 @@ New Functionality
skips past the VN-Tag header, allowing for further analysis of subsequent skips past the VN-Tag header, allowing for further analysis of subsequent
packet contents. packet contents.
- Support for decapsulating Geneve packets to process the inner
payload, similar in operation to the existing VXLAN support.
- Support for Zeek script "Reaching Definitions" (RD) analysis: tracking the - Support for Zeek script "Reaching Definitions" (RD) analysis: tracking the
extent to which a given variable definition (assignment) can be visible extent to which a given variable definition (assignment) can be visible
elsewhere in the Zeek script. The analysis works on local variables in elsewhere in the Zeek script. The analysis works on local variables in
@ -46,24 +102,184 @@ New Functionality
variable or a record field to inform Zeek's analysis that the script writer variable or a record field to inform Zeek's analysis that the script writer
asserts the value will be set, suppressing the associated warnings. asserts the value will be set, suppressing the associated warnings.
- A Telemetry API was added to assist in gathering arbitrary runtime metrics - A Telemetry API was added to assist in gathering arbitrary runtime
and allows potential export to Prometheus. metrics and allows export to Prometheus. This is still
work-in-progress, preliminary documentation for current, low-level
API lives at https://github.com/zeek/zeek/wiki/Telemetry for now.
- Experimental support for translating Zeek scripts to equivalent C++.
The generated C++ can then be compiled directly into the ``zeek`` binary,
replacing use of the interpreter and producing better runtime performance.
See ``src/script_opt/CPP/README.md`` for a guide on how to use this feature.
- Support for more generic session management. The NetSessions class has been
renamed to SessionMgr (with the old name marked deprecated). The new
class allows plugins to take advantage of session management similar to how
Connection objects were handled previously, but without the need to be based
on IP-based protocols.
- The logging framework now provides a global policy hook, ``Log::log_stream_policy``.
Like the existing filter-level hooks, handlers for the new hook can provide
additional processing and veto the log write. The new hook runs once per
write, prior to any filter-level policy hooks. Even when it vetoes,
filter-level policy hooks still run, but cannot "un-veto" the write.
- The ASCII writer gained a new option LogAscii::logdir, which can be used to
change the logging output directory.
- Added a ``--include-plugins`` argument to ``configure``. This argument
takes a semicolon separated list of paths containing plugins that will be
statically built into Zeek.
- Added a ``--plugindir`` argument to ``configure`` to set the
installation path for plugins.
- The X509 analyzer now can check if a specific hostname is valid for a
certificate. Two new BIFs were added for this, ``x509_check_hostname`` and
``x509_check_cert_hostname``. A new field ``sni_matches_cert`` that tracks
this information was added to ``ssl.log``.
- Added new functions to dynamically enable/disable file analyzers:
- ``global enable_analyzer: function(tag: Files::Tag): bool;``
- ``global disable_analyzer: function(tag: Files::Tag): bool;``
- ``global analyzer_enabled: function(tag: Files::Tag): bool;``
- Zeek now includes its own BTest tooling in the distribution, enabling other
tests (e.g. in Zeek packages) to use it. The ``$PREFIX/share/btest folder``,
reported via ``zeek-config --btest_tools_dir``, includes:
- ``scripts/`` for ``btest-diff`` canonifiers
- ``data/`` for data files, including ``random.seed``
- ``data/pcaps`` for the test pcaps
Configuring with ``--disable-btest-pcaps`` suppresses installation of the
test pcaps.
- The Supervisor now defaults to starting with a minimal set of Zeek
scripts controlled by a new init file, ``base/init-supervisor.zeek``.
One may still run it with a larger configuration by loading additional
scripts, including ``init-default.zeek``, as always. (Bare mode continues
to work as usual, reducing the configuration to a minimum.)
The ``NodeConfig`` record has two new members, providing additional
control over launched nodes. The ``env`` member allows setting environment
variables in the launched process. The ``bare_mode`` member, an optional
boolean, provides control over the bare-mode state of the new node.
When not provided, the node inherits the bare-mode status of the
Supervisor, and setting the variable enables/disables bare mode.
- Zeek now includes an incomplete, preliminary version of the future
cluster controller framework. Loading ``policy/frameworks/cluster/agent``
and/or ``policy/frameworks/cluster/agent`` in a Zeek running with the
Supervisor will launch the corresponding cluster management node(s).
An experimental management client, `zeek-client`, connects to the
controller and lets you issue commands. It requires configuration with
``--enable-zeek-client``. This does not yet provide a functional
substitute for ``zeekctl``, which users should continue to use for now.
Changed Functionality Changed Functionality
--------------------- ---------------------
- The ``in`` operator does not any more track whether a given vector element - The default IP-based transport protocols (UDP, TCP, and ICMP) have been
has been assigned-to. It now simply equates to "is this index between zero moved to the packet analysis framework. This change allows us to move other
and the size-of-the-vector-minus-one, inclusive". Previously, the ``in`` analyzers in the future that better align with the packet analysis framework
operator could have detected whether, by purpose or accident, a "hole" was than they do with session analysis.
created in a vector by way of assigning to an index that's more than 1 beyond
the end of the vector (with intermediate elements becoming "holes") and
whether a "hole" had ever been subsequently filled by an assignment.
The behavior of creating a "hole" in a vector was never explicitly - The input framework's handling of unset fields (commonly expressed as "-")
documented, and should be thought of as undefined behavior and not something in ingested data is now safer and more consistent. When reading data into
the ``in`` operator can be used to detect. For this kind of usage, a records, Zeek now accepts unset fields in the input data only when the
``table[count] of X`` is more appropriate than a vector. corresponding record field is ``&optional``. Unset fields for non-optional
fields cause the input line to be skipped. Reading data into tables with complex
index types (such as ``table[count, count] of string``) now also skips lines
with unset fields, since such indexes require fields to be present.
Note that this may change the behavior of existing scripts if you have unset
fields in your input data.
- The version field in ssh.log is now optional and will not be set if we cannot
determine the version that was negotiated by the client and server.
- Add a new field ``email_dest`` to NOTICEs, which defines where to
send email to. The email-related NOTICE actions fill this now, and
then emails will be sent to all recorded addresses at the end of
NOTICE processing. This makes email generation more consistent and
extensible.
- Add page and email administrator to mails processed by hostnames extension.
- SSL and X509 handling was significantly overhauled with the goal to make
the data that is logged by Zeek more helpful and compact.
This change means that there are significant changes to the default log files,
as well as changes to functionality:
- ``x509.log`` is now indexed by the sha256 of the certificate, with deduplication
being automatically performed. By default, the same certificate is only logged
once per day.
This also means that the file ID is no longer present in X509 log. Similarly,
``ssl.log`` now contains hashes for X509 certificates.
The hash function that is used for indexing the certificates is changeable by
changing the ``X509::hash_function`` option.
The time period after which a certificate is logged again can be configured by
changing ``X509::relog_known_certificates_after``.
By default deduplication of certificates is done across the entire cluster using
broker. If this is not desired due to the higher communication overhead, this
behavior can be disabled using ``X509::known_log_certs_use_broker``.
- X509 certificates are, by default, no longer logged into files.log. This
behavior is configurable and the previous default can be restored by changing
the ``X509::log_x509_in_files_log`` option.
- ``x509.log`` now tracks if a certificate was encountered as a end-host certificate
or as a client certificate.
- OCSP logging is now enabled by default.
- ``ssl.log`` now no longer includes information about the certificate issuer and
subject. This information is still available in X509.log. If you need this
information in ``ssl.log``, the old behavior can be restored by changing the
``SSL::log_include_server_certificate_subject_issuer`` and
``SSL::log_include_client_certificate_subject_issuer`` configuration options.
- ``ssl.log`` now contains a ``ssl_history`` field, which tracks which protocol
messages were seen in an SSL/TLS connection.
- We added a policy script ``ssl-log-ext.zeek`` which greatly extends the amount
of protocol information logged to SSL.log. The script is not loaded by default.
- We added a ``disable-certificate-events-known-certs.zeek`` policy script. This script
will completely disable X509 events for known certificates over SSL/TLS connections.
For Zeek installations in settings where you encounter a lot of certificates,
this could improve the performance of your installation. Before enabling this
script, make sure that you do not use any third-party scripts that depend on the
X509 events. The script is not loaded by default.
- The ICSI SSL Notary script was deprecated. This functionality is superseeded by newer
approaches, like SCT validation (which is supported by Zeek).
- ``extract-certs-pem.zeek`` was deprecated - it never really worked in cluster modes.
A new policy script, ``log-certs-base64.zeek`` that can be used to log raw certificates
was added instead.
- The CT logs listed in ``ct-list.zeek`` are now derived from the list of CT
logs that are accepted by Google Chrome. In the past, we allowed the list
of all known CT logs. This no longer makes sense since nowadays logs exist that
contain, e.g., only outdated or invalid certificates. If the old behavior is
desired, you can re-add Logs to ``SSL::ct_logs``.
- The Mozilla CA list was updated to the state of NSS 3.67.
- SQLite was updated to 3.36.0.
- The list of subnets that are considered private addresses was updated to mostly
match IANA's list unroutable addresses. This brings it in line with Chrome, the
W3C spec, and Python's ipaddress module.
Removed Functionality Removed Functionality
--------------------- ---------------------
@ -71,6 +287,11 @@ Removed Functionality
- Support for the RocksDB Broker data store was previously broken and unusable, - Support for the RocksDB Broker data store was previously broken and unusable,
so all code/options related to it are now removed. so all code/options related to it are now removed.
- Support for the ``ENABLE_MOBILE_IPV6`` compiler variable has been removed. Mobile
IPv6 is now enabled by default. The ``--enable-mobile-ipv6`` option for
``configure`` now returns a warning that it will be removed in v5.1 and no
longer has any effect.
Deprecated Functionality Deprecated Functionality
------------------------ ------------------------
@ -92,6 +313,11 @@ Deprecated Functionality
- ``supervisor_rotation_format_func`` is renamed to ``archiver_rotation_format_func`` - ``supervisor_rotation_format_func`` is renamed to ``archiver_rotation_format_func``
- The ``MemoryAllocation()`` function implemented by a number of interfaces
is now deprecated. In testing we found that the values returned were mostly
incorrect and weren't useful. The ``val_size`` and ``global_sizes`` BIF
methods have also both been marked deprecated.
Zeek 4.0.0 Zeek 4.0.0
========== ==========

View file

@ -1 +1 @@
4.1.0-dev.526 4.2.0-dev.255

@ -1 +1 @@
Subproject commit 919416a0a3457c95f23b67b39ce8e4da0b84c00b Subproject commit 6bd264351813eedb92753d2d4ed76ac6ddc076b3

@ -1 +1 @@
Subproject commit f946ef50de1896df07adafd879c360ef29bea965 Subproject commit 8169f1630993b34189b2c221d0e5ab8ba9777967

@ -1 +1 @@
Subproject commit 938fd7de65220a986361ec596f2335ad471102d7 Subproject commit 47cac80cbe1e1bde8e3b425903e50d62715972a2

@ -1 +1 @@
Subproject commit 72b8e3a6a5863715cbbce873cd8e1bf5358086ab Subproject commit 0a37819d484358999a47e76ac473da74799ab08d

@ -1 +1 @@
Subproject commit bb8b31c7377e047049466246bb1d2c00db8bc0bc Subproject commit ca0ff296b116354957276cef2c61be171ac2f897

@ -1 +1 @@
Subproject commit ccdd3f305cb56040e212dab9ec9239a4bd0cc62b Subproject commit feffa1d51e4e5494fef7daf2bd044138cb04f621

@ -1 +1 @@
Subproject commit a4efe7a6508333a2e4f50f66223d212770e0f098 Subproject commit 8dbff934dfbba1c2736152831c2cf45ee68f6fc3

@ -0,0 +1 @@
Subproject commit 39081c9c42768ab5e8321127a7494ad1647c6a2f

@ -1 +1 @@
Subproject commit 7fe80115aa159119febc623cec0660774bcae50c Subproject commit f3a1e8fe464c0425688eff67e30f35c678914ad2

@ -1 +1 @@
Subproject commit b2ce33bc3e4f57a72cd7bb7db2e3c7dc62e7a202 Subproject commit 296383d577a3f089c4f491061a985293cf6736e6

1
auxil/zeek-client Submodule

@ -0,0 +1 @@
Subproject commit afe253c77591e87b2a6cf6d5682cd02caa78e9d2

@ -1 +1 @@
Subproject commit c383d515ef89bd8c4d9785ed23ef6e1c2aafe6ce Subproject commit d31885671d74932d951778c029fa74d44cf3e542

View file

@ -1,9 +1,18 @@
#! /usr/bin/env bash #! /usr/bin/env bash
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" &> /dev/null && pwd)"
. ${SCRIPT_DIR}/common.sh
set -e set -e
set -x set -x
if [ "${ZEEK_CI_CREATE_ARTIFACT}" != "1" ]; then # If we're on macOS, use --osx-sysroot to ensure we can find the SDKs from Xcode. This avoids
# some problems with Catalina specifically, but it doesn't break anything on Big Sur either.
if [[ "${CIRRUS_OS}" == "darwin" ]]; then
export ZEEK_CI_CONFIGURE_FLAGS="${ZEEK_CI_CONFIGURE_FLAGS} --osx-sysroot=$(xcrun --show-sdk-path)"
fi
if [[ "${ZEEK_CI_CREATE_ARTIFACT}" != "1" ]]; then
./configure ${ZEEK_CI_CONFIGURE_FLAGS} ./configure ${ZEEK_CI_CONFIGURE_FLAGS}
cd build cd build
make -j ${ZEEK_CI_CPUS} make -j ${ZEEK_CI_CPUS}

View file

@ -7,7 +7,7 @@ RUN dnf config-manager --set-enabled powertools
RUN dnf -y update && dnf -y install \ RUN dnf -y update && dnf -y install \
git \ git \
cmake3 \ cmake \
make \ make \
gcc \ gcc \
gcc-c++ \ gcc-c++ \

12
ci/common.sh Normal file
View file

@ -0,0 +1,12 @@
# Common material sourced by Bash CI scripts in this directory
# On Cirrus, oversubscribe the CPUs when on Linux. This uses Cirrus' "greedy" feature.
if [[ "${CIRRUS_OS}" == linux ]]; then
if [[ -n "${ZEEK_CI_CPUS}" ]]; then
ZEEK_CI_CPUS=$(( 2 * ${ZEEK_CI_CPUS} ))
fi
if [[ -n "${ZEEK_CI_BTEST_JOBS}" ]]; then
ZEEK_CI_BTEST_JOBS=$(( 2 * ${ZEEK_CI_BTEST_JOBS} ))
fi
fi

View file

@ -1,4 +1,4 @@
FROM ubuntu:16.04 FROM debian:11
ENV DEBIAN_FRONTEND="noninteractive" TZ="America/Los_Angeles" ENV DEBIAN_FRONTEND="noninteractive" TZ="America/Los_Angeles"
@ -15,9 +15,6 @@ RUN apt-get update && apt-get -y install \
python3 \ python3 \
python3-dev \ python3-dev \
python3-pip\ python3-pip\
clang-8 \
libc++-8-dev \
libc++abi-8-dev \
swig \ swig \
zlib1g-dev \ zlib1g-dev \
libkrb5-dev \ libkrb5-dev \
@ -29,7 +26,3 @@ RUN apt-get update && apt-get -y install \
&& rm -rf /var/lib/apt/lists/* && rm -rf /var/lib/apt/lists/*
RUN pip3 install junit2html RUN pip3 install junit2html
ENV CC=/usr/bin/clang-8
ENV CXX=/usr/bin/clang++-8
ENV CXXFLAGS=-stdlib=libc++

View file

@ -2,6 +2,10 @@ FROM i386/debian:9
ENV DEBIAN_FRONTEND="noninteractive" TZ="America/Los_Angeles" ENV DEBIAN_FRONTEND="noninteractive" TZ="America/Los_Angeles"
# A version field to invalide Cirrus's build cache when needed, as suggested in
# https://github.com/cirruslabs/cirrus-ci-docs/issues/544#issuecomment-566066822
ENV DOCKERFILE_VERSION 221001
RUN apt-get update && apt-get -y install \ RUN apt-get update && apt-get -y install \
git \ git \
cmake \ cmake \

View file

@ -2,6 +2,10 @@ FROM debian:9
ENV DEBIAN_FRONTEND="noninteractive" TZ="America/Los_Angeles" ENV DEBIAN_FRONTEND="noninteractive" TZ="America/Los_Angeles"
# A version field to invalide Cirrus's build cache when needed, as suggested in
# https://github.com/cirruslabs/cirrus-ci-docs/issues/544#issuecomment-566066822
ENV DOCKERFILE_VERSION 221001
RUN apt-get update && apt-get -y install \ RUN apt-get update && apt-get -y install \
git \ git \
cmake \ cmake \

View file

@ -1,4 +1,4 @@
FROM fedora:32 FROM fedora:34
RUN dnf -y install \ RUN dnf -y install \
bison \ bison \

View file

@ -7,6 +7,7 @@ set -x
env ASSUME_ALWAYS_YES=YES pkg bootstrap env ASSUME_ALWAYS_YES=YES pkg bootstrap
pkg install -y bash git cmake swig bison python3 base64 pkg install -y bash git cmake swig bison python3 base64
pkg upgrade -y curl
pyver=`python3 -c 'import sys; print(f"py{sys.version_info[0]}{sys.version_info[1]}")'` pyver=`python3 -c 'import sys; print(f"py{sys.version_info[0]}{sys.version_info[1]}")'`
pkg install -y $pyver-sqlite3 $pyver-pip pkg install -y $pyver-sqlite3 $pyver-pip
pip install junit2html pip install junit2html

View file

@ -31,9 +31,10 @@ fi
make update-traces make update-traces
cd .. cd ..
# When running in Cirrus for the main repo, try to clone the private testsuite.
# Note that this script is also called when populating the public cache, so # Note that this script is also called when populating the public cache, so
# the zeek-testing-private dir could have been created/populated already. # the zeek-testing-private dir could have been created/populated already.
if [[ -n "${CIRRUS_CI}" ]] && [[ ! -d zeek-testing-private ]]; then if [[ -n "${CIRRUS_CI}" ]] && [[ "${CIRRUS_REPO_OWNER}" == "zeek" ]] && [[ ! -d zeek-testing-private ]]; then
# If we're running this on Cirrus, the SSH key won't be available to PRs, # If we're running this on Cirrus, the SSH key won't be available to PRs,
# so don't make any of this fail the task in that case. (But technically, # so don't make any of this fail the task in that case. (But technically,
# the key is also available in PRs for people with write access to the # the key is also available in PRs for people with write access to the

View file

@ -5,4 +5,6 @@ sysctl hw.model hw.machine hw.ncpu hw.physicalcpu hw.logicalcpu
set -e set -e
set -x set -x
brew install cmake swig openssl bison brew update
brew upgrade cmake openssl@1.1
brew install swig bison

View file

@ -0,0 +1,25 @@
FROM opensuse/leap:15.3
RUN zypper in -y \
cmake \
make \
gcc \
gcc-c++ \
python3 \
python3-devel \
flex \
bison \
libpcap-devel \
libopenssl-devel \
zlib-devel \
swig \
git \
curl \
python3-pip \
which \
gzip \
tar \
&& rm -rf /var/cache/zypp
RUN pip3 install junit2html

65
ci/run-clang-format.sh Executable file
View file

@ -0,0 +1,65 @@
#! /bin/sh
#
# Copyright (c) 2020 by the Zeek Project. See LICENSE for details.
base=$(git rev-parse --show-toplevel)
fix=0
pre_commit_hook=0
# Directories to run on by default. When changing, adapt .pre-commit-config.yam
# as well.
files="src"
error() {
test "${pre_commit_hook}" = 0 && echo "$@" >&2 && exit 1
exit 0
}
if [ $# != 0 ]; then
case "$1" in
--fixit)
shift
fix=1
;;
--pre-commit-hook)
shift
fix=1
pre_commit_hook=1
;;
-*)
echo "usage: $(basename $0) [--fixit | --pre-commit-hook] [<files>]"
exit 1
esac
fi
test $# != 0 && files="$@"
if [ -z "${CLANG_FORMAT}" ]; then
CLANG_FORMAT=$(which clang-format 2>/dev/null)
fi
if [ -z "${CLANG_FORMAT}" -o ! -x "${CLANG_FORMAT}" ]; then
error "Cannot find clang-format. If not in PATH, set CLANG_FORMAT."
fi
if ! (cd / && ${CLANG_FORMAT} -dump-config | grep -q SpacesInConditionalStatement); then
error "${CLANG_FORMAT} does not support SpacesInConditionalStatement. Install custom version and put it into PATH, or point CLANG_FORMAT to it."
fi
if [ ! -e .clang-format ]; then
error "Must execute in top-level directory."
fi
cmd="${base}/auxil/run-clang-format/run-clang-format.py -r --clang-format-executable ${CLANG_FORMAT} --exclude '*/3rdparty/*' ${files}"
tmp=/tmp/$(basename $0).$$.tmp
trap "rm -f ${tmp}" EXIT
eval "${cmd}" >"${tmp}"
if [ "${fix}" = 1 ]; then
test -s "${tmp}" && cat "${tmp}" | git apply -p0
true
else
cat "${tmp}"
fi

View file

@ -16,6 +16,9 @@ if [[ -z "${CIRRUS_CI}" ]]; then
ZEEK_CI_BTEST_RETRIES=2 ZEEK_CI_BTEST_RETRIES=2
fi fi
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" &> /dev/null && pwd)"
. ${SCRIPT_DIR}/common.sh
function pushd function pushd
{ {
command pushd "$@" > /dev/null || exit 1 command pushd "$@" > /dev/null || exit 1
@ -57,6 +60,14 @@ function run_btests
banner "Running baseline tests: zeek" banner "Running baseline tests: zeek"
pushd testing/btest pushd testing/btest
# Commenting out this line in btest.cfg causes the script profiling/coverage
# to be disabled. We do this for the sanitizer build right now because of a
# fairly significant performance bug when running tests.
if [ "${ZEEK_CI_DISABLE_SCRIPT_PROFILING}" = "1" ]; then
sed -i 's/^ZEEK_PROFILER_FILE/#ZEEK_PROFILER_FILE/g' btest.cfg
fi
${BTEST} -z ${ZEEK_CI_BTEST_RETRIES} -d -b -x btest-results.xml -j ${ZEEK_CI_BTEST_JOBS} || result=1 ${BTEST} -z ${ZEEK_CI_BTEST_RETRIES} -d -b -x btest-results.xml -j ${ZEEK_CI_BTEST_JOBS} || result=1
make coverage make coverage
prep_artifacts prep_artifacts
@ -66,6 +77,15 @@ function run_btests
function run_external_btests function run_external_btests
{ {
# Commenting out this line in btest.cfg causes the script profiling/coverage
# to be disabled. We do this for the sanitizer build right now because of a
# fairly significant performance bug when running tests.
if [ "${ZEEK_CI_DISABLE_SCRIPT_PROFILING}" = "1" ]; then
pushd testing/external
sed -i 's/^ZEEK_PROFILER_FILE/#ZEEK_PROFILER_FILE/g' subdir-btest.cfg
popd
fi
local zeek_testing_pid="" local zeek_testing_pid=""
local zeek_testing_pid_private="" local zeek_testing_pid_private=""
pushd testing/external/zeek-testing pushd testing/external/zeek-testing

2
cmake

@ -1 +1 @@
Subproject commit cce53d15008a26dcb1b7eb534a78f52f9355c676 Subproject commit 4d1990f0e4c273cf51ec52278add6ff256f9c889

25
configure vendored
View file

@ -28,6 +28,8 @@ Usage: $0 [OPTION]... [VAR=VALUE]...
--toolchain=PATH path to a CMAKE_TOOLCHAIN_FILE --toolchain=PATH path to a CMAKE_TOOLCHAIN_FILE
(useful for cross-compiling) (useful for cross-compiling)
--sanitizers=LIST comma-separated list of sanitizer names to enable --sanitizers=LIST comma-separated list of sanitizer names to enable
--include-plugins=PATHS paths containing plugins to build directly into Zeek
(semicolon delimited and quoted when multiple)
Installation Directories: Installation Directories:
--prefix=PREFIX installation directory [/usr/local/zeek] --prefix=PREFIX installation directory [/usr/local/zeek]
@ -62,10 +64,12 @@ Usage: $0 [OPTION]... [VAR=VALUE]...
--enable-static-broker build Broker statically (ignored if --with-broker is specified) --enable-static-broker build Broker statically (ignored if --with-broker is specified)
--enable-static-binpac build binpac statically (ignored if --with-binpac is specified) --enable-static-binpac build binpac statically (ignored if --with-binpac is specified)
--enable-cpp-tests build Zeek's C++ unit tests --enable-cpp-tests build Zeek's C++ unit tests
--enable-zeek-client install the Zeek cluster management client (experimental)
--disable-zeekctl don't install ZeekControl --disable-zeekctl don't install ZeekControl
--disable-auxtools don't build or install auxiliary tools --disable-auxtools don't build or install auxiliary tools
--disable-archiver don't build or install zeek-archiver tool --disable-archiver don't build or install zeek-archiver tool
--disable-btest don't install BTest --disable-btest don't install BTest
--disable-btest-pcaps don't install Zeek's BTest input pcaps
--disable-python don't try to build python bindings for Broker --disable-python don't try to build python bindings for Broker
--disable-broker-tests don't try to build Broker unit tests --disable-broker-tests don't try to build Broker unit tests
--disable-zkg don't install zkg --disable-zkg don't install zkg
@ -162,12 +166,15 @@ append_cache_entry ENABLE_JEMALLOC BOOL false
append_cache_entry BUILD_SHARED_LIBS BOOL true append_cache_entry BUILD_SHARED_LIBS BOOL true
append_cache_entry INSTALL_AUX_TOOLS BOOL true append_cache_entry INSTALL_AUX_TOOLS BOOL true
append_cache_entry INSTALL_BTEST BOOL true append_cache_entry INSTALL_BTEST BOOL true
append_cache_entry INSTALL_BTEST_PCAPS BOOL true
append_cache_entry INSTALL_ZEEK_ARCHIVER BOOL true append_cache_entry INSTALL_ZEEK_ARCHIVER BOOL true
append_cache_entry INSTALL_ZEEKCTL BOOL true append_cache_entry INSTALL_ZEEKCTL BOOL true
append_cache_entry INSTALL_ZKG BOOL true append_cache_entry INSTALL_ZKG BOOL true
append_cache_entry CPACK_SOURCE_IGNORE_FILES STRING append_cache_entry CPACK_SOURCE_IGNORE_FILES STRING
append_cache_entry ENABLE_MOBILE_IPV6 BOOL false
append_cache_entry ZEEK_SANITIZERS STRING "" append_cache_entry ZEEK_SANITIZERS STRING ""
append_cache_entry ZEEK_INCLUDE_PLUGINS STRING ""
has_enable_mobile_ipv6=0
# parse arguments # parse arguments
while [ $# -ne 0 ]; do while [ $# -ne 0 ]; do
@ -206,6 +213,9 @@ while [ $# -ne 0 ]; do
--toolchain=*) --toolchain=*)
append_cache_entry CMAKE_TOOLCHAIN_FILE PATH $optarg append_cache_entry CMAKE_TOOLCHAIN_FILE PATH $optarg
;; ;;
--include-plugins=*)
append_cache_entry ZEEK_INCLUDE_PLUGINS STRING $optarg
;;
--prefix=*) --prefix=*)
prefix=$optarg prefix=$optarg
append_cache_entry CMAKE_INSTALL_PREFIX PATH $optarg append_cache_entry CMAKE_INSTALL_PREFIX PATH $optarg
@ -257,7 +267,7 @@ while [ $# -ne 0 ]; do
append_cache_entry ENABLE_DEBUG BOOL true append_cache_entry ENABLE_DEBUG BOOL true
;; ;;
--enable-mobile-ipv6) --enable-mobile-ipv6)
append_cache_entry ENABLE_MOBILE_IPV6 BOOL true has_enable_mobile_ipv6=1
;; ;;
--enable-perftools) --enable-perftools)
append_cache_entry ENABLE_PERFTOOLS BOOL true append_cache_entry ENABLE_PERFTOOLS BOOL true
@ -281,6 +291,9 @@ while [ $# -ne 0 ]; do
--enable-cpp-tests) --enable-cpp-tests)
append_cache_entry ENABLE_ZEEK_UNIT_TESTS BOOL true append_cache_entry ENABLE_ZEEK_UNIT_TESTS BOOL true
;; ;;
--enable-zeek-client)
append_cache_entry INSTALL_ZEEK_CLIENT BOOL true
;;
--disable-zeekctl) --disable-zeekctl)
append_cache_entry INSTALL_ZEEKCTL BOOL false append_cache_entry INSTALL_ZEEKCTL BOOL false
;; ;;
@ -293,6 +306,9 @@ while [ $# -ne 0 ]; do
--disable-btest) --disable-btest)
append_cache_entry INSTALL_BTEST BOOL false append_cache_entry INSTALL_BTEST BOOL false
;; ;;
--disable-btest-pcaps)
append_cache_entry INSTALL_BTEST_PCAPS BOOL false
;;
--disable-python) --disable-python)
append_cache_entry DISABLE_PYTHON_BINDINGS BOOL true append_cache_entry DISABLE_PYTHON_BINDINGS BOOL true
;; ;;
@ -429,3 +445,8 @@ fi
echo "# This is the command used to configure this build" > config.status echo "# This is the command used to configure this build" > config.status
echo $command >> config.status echo $command >> config.status
chmod u+x config.status chmod u+x config.status
if [ $has_enable_mobile_ipv6 -eq 1 ]; then
echo
echo "NOTE: The --enable-mobile-ipv6 argument no longer has any effect and will be removed in v5.1."
fi

2
doc

@ -1 +1 @@
Subproject commit d273f2be33866ce8240bd83632def252aca69d1b Subproject commit fefd7e6ceb67dd011c268c658171967f1281b970

60
docker/Dockerfile Normal file
View file

@ -0,0 +1,60 @@
# See the file "COPYING" in the main distribution directory for copyright.
# Layer to build Zeek.
FROM debian:bullseye-slim AS build
# Configure system for build.
RUN apt-get -q update \
&& apt-get install -q -y --no-install-recommends \
bind9 \
bison \
cmake \
flex \
g++ \
gcc \
libmaxminddb-dev \
libpcap-dev \
libssl-dev \
libz-dev \
make \
python3-minimal \
python3.9-dev \
swig \
ninja-build \
python3-pip \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
# Copy over the Zeek source tree.
# NOTE: This assumes that we build in the context of the parent directory (the
# Git checkout root). We e.g., ensure that in the `Makefile` in this directory.
COPY . /src/zeek
RUN make -C /src/zeek distclean
ARG CONFFLAGS="--generator=Ninja --build-type=Release"
WORKDIR /src/zeek
RUN ./configure $CONFFLAGS && ninja -C build install
# Final layer containing all artifacts.
FROM debian:bullseye-slim AS final
RUN apt-get -q update \
&& apt-get install -q -y --no-install-recommends \
ca-certificates \
git \
libmaxminddb0 \
libpython3.9 \
libpcap0.8 \
libssl1.1 \
libz1 \
python3-minimal \
python3-git \
python3-semantic-version \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
# Copy over Zeek installation.
COPY --from=build /usr/local/zeek /usr/local/zeek
ENV PATH "/usr/local/zeek/bin:${PATH}"
ENV PYTHONPATH "/usr/local/zeek/lib/zeek/python:${PYTHONPATH}"

12
docker/Makefile Normal file
View file

@ -0,0 +1,12 @@
# See the file "COPYING" in the main distribution directory for copyright.
VERSION := $$(cat ../VERSION)
.PHONY: all
all:
@docker build -t zeek:$(VERSION) -f Dockerfile ..
@docker tag zeek:$(VERSION) zeek:latest
test:
@TEST_TAG=zeek:$(VERSION) $(MAKE) -C btest

19
docker/README Normal file
View file

@ -0,0 +1,19 @@
Container image for Zeek
========================
This directory contains a minimal container image for Zeek. This image is
published automatically to [DockerHub](https://hub.docker.com/u/zeekurity) for
releases and for commits on the `master` branch.
- Images for release are published as
[`zeekurity/zeek`](https://hub.docker.com/r/zeekurity/zeek) with the `latest`
tag pointing to the latest release.
- Development images for the `master` branch are published as
[`zeekurity/zeek-dev`](https://hub.docker.com/r/zeekurity/zeek-dev).
To run the image execute e.g.,:
docker run -it zeekurity/zeek
To build the image execute `make` from this directory.

3
docker/btest/.gitignore vendored Normal file
View file

@ -0,0 +1,3 @@
.tmp
.btest.failed.dat
diag.log

View file

@ -0,0 +1,20 @@
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
zeek version xxx
XXX
[sources]
zeek = https://github.com/zeek/packages
[paths]
state_dir = /usr/local/zeek/var/lib/zkg
script_dir = /usr/local/zeek/share/zeek/site
plugin_dir = /usr/local/zeek/lib/zeek/plugins
bin_dir = /usr/local/zeek/bin
zeek_dist =
[templates]
default = https://github.com/zeek/package-template
Installing "zeek/sethhall/domain-tld"
Installed "zeek/sethhall/domain-tld" (XXX)
Loaded "zeek/sethhall/domain-tld"

11
docker/btest/Makefile Normal file
View file

@ -0,0 +1,11 @@
DIAG=diag.log
BTEST=../../auxil/btest/btest
all: cleanup btest-verbose
# Showing all tests.
btest-verbose:
@$(BTEST) -d -j -f $(DIAG)
cleanup:
@rm -f $(DIAG)

12
docker/btest/btest.cfg Normal file
View file

@ -0,0 +1,12 @@
[btest]
TestDirs = docker
TmpDir = %(testbase)s/.tmp
BaselineDir = %(testbase)s/Baseline
IgnoreDirs = .tmp
IgnoreFiles = *.tmp *.swp #* *.trace .DS_Store
MinVersion = 0.63
[environment]
LC_ALL=C
PATH=%(testbase)s/../../auxil/btest:%(default_path)s
TZ=UTC

View file

@ -0,0 +1,23 @@
# @TEST-REQUIRES: docker inspect ${TEST_TAG:-zeek:latest}
# @TEST-EXEC: bash -euxo pipefail %INPUT >output
# @TEST-EXEC: btest-diff output
TEST_TAG=${TEST_TAG:-zeek:latest}
# Check that `zeek` can be run.
docker run --rm "${TEST_TAG}" zeek -v | sed 's/\(zeek version\) .*/\1 xxx/'
# Check that this is a release build.
docker run --rm "${TEST_TAG}" zeek-config --build_type | grep -q 'release'
# Check that `btest` can be run.
docker run --rm "${TEST_TAG}" btest --version | sed 's/^[0-9].*/XXX/g'
# Check that the zkg config looks valid.
docker run --rm "${TEST_TAG}" zkg config
# Check that a plugin can be installed. We pick any plugin with minimal deps here.
docker run --rm "${TEST_TAG}" zkg install --force sethhall/domain-tld | sed 's/(.*)/(XXX)/'
# Check that the Broker Python module loads
docker run --rm "${TEST_TAG}" python3 -c "import broker"

View file

@ -16,6 +16,8 @@ tasks, including detecting malware by interfacing to external registries,
reporting vulnerable versions of software seen on the network, identifying reporting vulnerable versions of software seen on the network, identifying
popular web applications, detecting SSH brute-forcing, validating SSL popular web applications, detecting SSH brute-forcing, validating SSL
certificate chains, among others. certificate chains, among others.
You must have the necessary permissions to access to the files or interfaces specified.
.SH OPTIONS .SH OPTIONS
.TP .TP
.B <file> .B <file>
@ -148,6 +150,31 @@ Output file for script execution statistics
.TP .TP
.B ZEEK_DISABLE_ZEEKYGEN .B ZEEK_DISABLE_ZEEKYGEN
Disable Zeekygen (Broxygen) documentation support Disable Zeekygen (Broxygen) documentation support
.SH OUTPUT FORMAT
Output is written in multiple files depending on configuration. The default
location is the current directory.
The output written by Zeek can be formatted in multiple ways using the
logging framework.
.PP
The default are files in human-readable (ASCII) format. The data is organized
into columns (tab-delimited). The data can be processed using, e.g., the \fBzeek-cut\fR tool.
.SH EXAMPLES
Read a capture file and generate the default logs:
.br
# zeek -r test-capture.pcap
.PP
When running on live traffic, Zeek is usually started by running \fBzeekctl\fR. To configure
Zeek with an initial configuration, install, and restart:
.br
# zeekctl deploy
Note: the zeekctl configuration may need to be updated before first use. Especially the
network interface used should be the correct one.
.SH SEE ALSO
zeekctl(8) zeek-cut(1)
.SH AUTHOR .SH AUTHOR
.B zeek .B zeek
was written by The Zeek Project <info@zeek.org>. was written by The Zeek Project <info@zeek.org>.

View file

@ -1 +1,4 @@
@load ./main @load ./main
@load ./certificate-event-cache
@load ./log-ocsp

View file

@ -0,0 +1,112 @@
##! This script sets up the certificate event cache handling of Zeek.
##!
##! The Zeek core provided a method to skip certificate processing for known certificates.
##! For more details about this functionality, see :zeek:see:`x509_set_certificate_cache`.
##!
##! This script uses this feature to lower the amount of processing that has to be performed
##! by Zeek by caching all certificate events for common certificates. For these certificates,
##! the parsing of certificate information in the core is disabled. Instead, the cached events
##! and data structures from the previous certificates are used.
@load ./main
module X509;
export {
## How often do you have to encounter a certificate before
## caching the events for it. Set to 0 to disable caching of certificates.
option caching_required_encounters : count = 10;
## The timespan over which caching_required_encounters has to be reached
option caching_required_encounters_interval : interval = 62 secs;
## After a certificate has not been encountered for this time, it
## may be evicted from the certificate event cache.
option certificate_cache_minimum_eviction_interval : interval = 62 secs;
## Maximum size of the certificate event cache
option certificate_cache_max_entries : count = 10000;
## This hook performs event-replays in case a certificate that already
## is in the cache is encountered.
##
## It is possible to change this behavior/skip sending the events by
## installing a higher priority hook instead.
global x509_certificate_cache_replay: hook(f: fa_file, e: X509::Info, sha256: string);
}
# Table tracking potential certificates to cache - indexed by the SHA256 of the
# raw on-the-wire representation (DER).
global certificates_encountered: table[string] of count &create_expire=caching_required_encounters_interval;
# Table caching the output of the X509 analyzer for commonly seen certificates.
# This is indexed by SHA256 and contains the Info record of the first certificate
# encountered. We use this info record to re-play the events.
global certificate_cache: table[string] of X509::Info &read_expire=certificate_cache_minimum_eviction_interval;
event zeek_init() &priority=5
{
x509_set_certificate_cache(certificate_cache);
x509_set_certificate_cache_hit_callback(x509_certificate_cache_replay);
}
hook x509_certificate_cache_replay(f: fa_file, e: X509::Info, sha256: string)
{
# we encountered a cached cert. The X509 analyzer will skip it. Let's raise all the events that it typically
# raises by ourselfes.
# first - let's checked if it already has an x509 record. That would mean that someone raised the file_hash event
# several times for the certificate - in which case we bail out.
if ( f$info?$x509 )
return;
event x509_certificate(f, e$handle, e$certificate);
for ( i in e$extensions_cache )
{
local ext = e$extensions_cache[i];
if ( ext is X509::Extension )
event x509_extension(f, (ext as X509::Extension));
else if ( ext is X509::BasicConstraints )
event x509_ext_basic_constraints(f, (ext as X509::BasicConstraints));
else if ( ext is X509::SubjectAlternativeName )
event x509_ext_subject_alternative_name(f, (ext as X509::SubjectAlternativeName));
else if ( ext is X509::SctInfo )
{
local s = ( ext as X509::SctInfo);
event x509_ocsp_ext_signed_certificate_timestamp(f, s$version, s$logid, s$timestamp, s$hash_alg, s$sig_alg, s$signature);
}
else
Reporter::error(fmt("Encountered unknown extension while replaying certificate with fuid %s", f$id));
}
}
event file_state_remove(f: fa_file) &priority=5
{
if ( ! f$info?$x509 )
return;
if ( f$info?$sha256 && f$info$sha256 !in certificate_cache &&
caching_required_encounters > 0 &&
f$info$sha256 in certificates_encountered &&
certificates_encountered[f$info$sha256] >= caching_required_encounters &&
|certificate_cache| < certificate_cache_max_entries )
{
delete certificates_encountered[f$info$sha256];
certificate_cache[f$info$sha256] = f$info$x509;
}
}
event file_hash(f: fa_file, kind: string, hash: string)
{
if ( ! f?$info || "X509" !in f$info$analyzers || kind != "sha256" )
return;
if ( caching_required_encounters == 0 || hash in certificate_cache )
return;
if ( hash !in certificates_encountered )
certificates_encountered[hash] = 1;
else
certificates_encountered[hash] += 1;
}

View file

@ -0,0 +1,61 @@
##! Enable logging of OCSP responses.
module OCSP;
export {
redef enum Log::ID += { LOG };
global log_policy: Log::PolicyHook;
## The record type which contains the fields of the OCSP log.
type Info: record {
## Time when the OCSP reply was encountered.
ts: time &log;
## File id of the OCSP reply.
id: string &log;
## Hash algorithm used to generate issuerNameHash and issuerKeyHash.
hashAlgorithm: string &log;
## Hash of the issuer's distingueshed name.
issuerNameHash: string &log;
## Hash of the issuer's public key.
issuerKeyHash: string &log;
## Serial number of the affected certificate.
serialNumber: string &log;
## Status of the affected certificate.
certStatus: string &log;
## Time at which the certificate was revoked.
revoketime: time &log &optional;
## Reason for which the certificate was revoked.
revokereason: string &log &optional;
## The time at which the status being shows is known to have been correct.
thisUpdate: time &log;
## The latest time at which new information about the status of the certificate will be available.
nextUpdate: time &log &optional;
};
## Event that can be handled to access the OCSP record
## as it is sent to the logging framework.
global log_ocsp: event(rec: Info);
}
event zeek_init() &priority=5
{
Log::create_stream(LOG, [$columns=Info, $ev=log_ocsp, $path="ocsp", $policy=log_policy]);
Files::register_for_mime_type(Files::ANALYZER_OCSP_REPLY, "application/ocsp-response");
}
event ocsp_response_certificate(f: fa_file, hashAlgorithm: string, issuerNameHash: string, issuerKeyHash: string, serialNumber: string, certStatus: string, revoketime: time, revokereason: string, thisUpdate: time, nextUpdate: time)
{
local wr = OCSP::Info($ts=f$info$ts, $id=f$id, $hashAlgorithm=hashAlgorithm, $issuerNameHash=issuerNameHash,
$issuerKeyHash=issuerKeyHash, $serialNumber=serialNumber, $certStatus=certStatus,
$thisUpdate=thisUpdate);
if ( revokereason != "" )
wr$revokereason = revokereason;
if ( time_to_double(revoketime) != 0 )
wr$revoketime = revoketime;
if ( time_to_double(nextUpdate) != 0 )
wr$nextUpdate = nextUpdate;
Log::write(LOG, wr);
}

View file

@ -1,6 +1,7 @@
@load base/frameworks/files @load base/frameworks/files
@load base/files/hash @load base/files/hash
@load base/frameworks/cluster
module X509; module X509;
@ -9,26 +10,32 @@ export {
global log_policy: Log::PolicyHook; global log_policy: Log::PolicyHook;
## How often do you have to encounter a certificate before ## The hash function used for certificate hashes. By default this is sha256; you can use
## caching it. Set to 0 to disable caching of certificates. ## any other hash function and the hashes will change in ssl.log and in x509.log.
option caching_required_encounters : count = 10; option hash_function: function(cert: string): string = sha256_hash;
## The timespan over which caching_required_encounters has to be reached ## This option specifies if X.509 certificates are logged in file.log. Typically, there
option caching_required_encounters_interval : interval = 62 secs; ## is not much value to having the entry in files.log - especially since, by default, the
## file ID is not present in the X509 log.
option log_x509_in_files_log: bool = F;
## After a certificate has not been encountered for this time, it ## Type that is used to decide which certificates are duplicates for logging purposes.
## may be evicted from the certificate cache. ## When adding entries to this, also change the create_deduplication_index to update them.
option certificate_cache_minimum_eviction_interval : interval = 62 secs; type LogCertHash: record {
## Certificate fingerprint
## Maximum size of the certificate cache fingerprint: string;
option certificate_cache_max_entries : count = 10000; ## Indicates if this certificate was a end-host certificate, or sent as part of a chain
host_cert: bool;
## Indicates if this certificate was sent from the client
client_cert: bool;
};
## The record type which contains the fields of the X.509 log. ## The record type which contains the fields of the X.509 log.
type Info: record { type Info: record {
## Current timestamp. ## Current timestamp.
ts: time &log; ts: time &log;
## File id of this certificate. ## Fingerprint of the certificate - uses chosen algorithm.
id: string &log; fingerprint: string &log;
## Basic information about the certificate. ## Basic information about the certificate.
certificate: X509::Certificate &log; certificate: X509::Certificate &log;
## The opaque wrapping the certificate. Mainly used ## The opaque wrapping the certificate. Mainly used
@ -44,8 +51,17 @@ export {
## This is used for caching certificates that are commonly ## This is used for caching certificates that are commonly
## encountered and should not be relied on in user scripts. ## encountered and should not be relied on in user scripts.
extensions_cache: vector of any &default=vector(); extensions_cache: vector of any &default=vector();
## Indicates if this certificate was a end-host certificate, or sent as part of a chain
host_cert: bool &log &default=F;
## Indicates if this certificate was sent from the client
client_cert: bool &log &default=F;
## Record that is used to deduplicate log entries.
deduplication_index: LogCertHash &optional;
}; };
## Hook that is used to create the index value used for log deduplication.
global create_deduplication_index: hook(c: X509::Info);
## This record is used to store information about the SCTs that are ## This record is used to store information about the SCTs that are
## encountered in Certificates. ## encountered in Certificates.
type SctInfo: record { type SctInfo: record {
@ -66,25 +82,32 @@ export {
signature: string; signature: string;
}; };
## This hook performs event-replays in case a certificate that already ## By default, x509 certificates are deduplicated. This configuration option configures
## is in the cache is encountered. ## the maximum time after which certificates are re-logged. Note - depending on other configuration
## options, this setting might only apply on a per-worker basis and you still might see certificates
## logged several times.
## ##
## It is possible to change this behavior/skip sending the events by ## To disable deduplication completely, set this to 0secs.
## installing a higher priority hook instead. option relog_known_certificates_after = 1day;
global x509_certificate_cache_replay: hook(f: fa_file, e: X509::Info, sha256: string);
## The set that stores information about certificates that already have been logged and should
## not be logged again.
global known_log_certs: set[LogCertHash] &create_expire=relog_known_certificates_after;
## Maximum size of the known_log_certs table
option known_log_certs_maximum_size = 1000000;
## Use broker stores to deduplicate certificates across the whole cluster. This will cause log-deduplication
## to work cluster wide, but come at a slightly higher cost of memory and inter-node-communication.
##
## This setting is ignored if Zeek is run in standalone mode.
global known_log_certs_use_broker: bool = T;
## Event for accessing logged records. ## Event for accessing logged records.
global log_x509: event(rec: Info); global log_x509: event(rec: Info);
} }
# Table tracking potential certificates to cache - indexed by the SHA256 of the global known_log_certs_with_broker: set[LogCertHash] &create_expire=relog_known_certificates_after &backend=Broker::MEMORY;
# raw on-the-wire representation (DER).
global certificates_encountered: table[string] of count &create_expire=caching_required_encounters_interval;
# Table caching the output of the X509 analyzer for commonly seen certificates.
# This is indexed by SHA256 and contains the Info record of the first certificate
# encountered. We use this info record to re-play the events.
global certificate_cache: table[string] of X509::Info &read_expire=certificate_cache_minimum_eviction_interval;
redef record Files::Info += { redef record Files::Info += {
## Information about X509 certificates. This is used to keep ## Information about X509 certificates. This is used to keep
@ -114,49 +137,41 @@ event zeek_init() &priority=5
Files::register_for_mime_type(Files::ANALYZER_SHA1, "application/x-x509-ca-cert"); Files::register_for_mime_type(Files::ANALYZER_SHA1, "application/x-x509-ca-cert");
Files::register_for_mime_type(Files::ANALYZER_SHA1, "application/pkix-cert"); Files::register_for_mime_type(Files::ANALYZER_SHA1, "application/pkix-cert");
# SHA256 is used by us to determine which certificates to cache. # Please note that SHA256 caching is required to be enabled for the certificate event
# caching that is set up in certificate-event-cache.zeek to work.
Files::register_for_mime_type(Files::ANALYZER_SHA256, "application/x-x509-user-cert"); Files::register_for_mime_type(Files::ANALYZER_SHA256, "application/x-x509-user-cert");
Files::register_for_mime_type(Files::ANALYZER_SHA256, "application/x-x509-ca-cert"); Files::register_for_mime_type(Files::ANALYZER_SHA256, "application/x-x509-ca-cert");
Files::register_for_mime_type(Files::ANALYZER_SHA256, "application/pkix-cert"); Files::register_for_mime_type(Files::ANALYZER_SHA256, "application/pkix-cert");
x509_set_certificate_cache(certificate_cache); @if ( Cluster::is_enabled() )
x509_set_certificate_cache_hit_callback(x509_certificate_cache_replay); if ( known_log_certs_use_broker )
known_log_certs = known_log_certs_with_broker;
@endif
} }
hook x509_certificate_cache_replay(f: fa_file, e: X509::Info, sha256: string) hook Files::log_policy(rec: Files::Info, id: Log::ID, filter: Log::Filter) &priority=5
{ {
# we encountered a cached cert. The X509 analyzer will skip it. Let's raise all the events that it typically if ( ( log_x509_in_files_log == F ) && ( "X509" in rec$analyzers ) )
# raises by ourselfes. break;
}
# first - let's checked if it already has an x509 record. That would mean that someone raised the file_hash event hook create_deduplication_index(i: X509::Info)
# several times for the certificate - in which case we bail out. {
if ( f$info?$x509 ) if ( i?$deduplication_index || relog_known_certificates_after == 0secs )
return; return;
event x509_certificate(f, e$handle, e$certificate); i$deduplication_index = LogCertHash($fingerprint=i$fingerprint, $host_cert=i$host_cert, $client_cert=i$client_cert);
for ( i in e$extensions_cache )
{
local ext = e$extensions_cache[i];
if ( ext is X509::Extension )
event x509_extension(f, (ext as X509::Extension));
else if ( ext is X509::BasicConstraints )
event x509_ext_basic_constraints(f, (ext as X509::BasicConstraints));
else if ( ext is X509::SubjectAlternativeName )
event x509_ext_subject_alternative_name(f, (ext as X509::SubjectAlternativeName));
else if ( ext is X509::SctInfo )
{
local s = ( ext as X509::SctInfo);
event x509_ocsp_ext_signed_certificate_timestamp(f, s$version, s$logid, s$timestamp, s$hash_alg, s$sig_alg, s$signature);
}
else
Reporter::error(fmt("Encountered unknown extension while replaying certificate with fuid %s", f$id));
}
} }
event x509_certificate(f: fa_file, cert_ref: opaque of x509, cert: X509::Certificate) &priority=5 event x509_certificate(f: fa_file, cert_ref: opaque of x509, cert: X509::Certificate) &priority=5
{ {
f$info$x509 = [$ts=f$info$ts, $id=f$id, $certificate=cert, $handle=cert_ref]; local der_cert = x509_get_certificate_string(cert_ref);
local fp = hash_function(der_cert);
f$info$x509 = [$ts=f$info$ts, $fingerprint=fp, $certificate=cert, $handle=cert_ref];
if ( f$info$mime_type == "application/x-x509-user-cert" )
f$info$x509$host_cert = T;
if ( f$is_orig )
f$info$x509$client_cert = T;
} }
event x509_extension(f: fa_file, ext: X509::Extension) &priority=5 event x509_extension(f: fa_file, ext: X509::Extension) &priority=5
@ -197,30 +212,17 @@ event file_state_remove(f: fa_file) &priority=5
if ( ! f$info?$x509 ) if ( ! f$info?$x509 )
return; return;
if ( ! f$info$x509?$deduplication_index )
hook create_deduplication_index(f$info$x509);
if ( f$info$x509?$deduplication_index )
{
if ( f$info$x509$deduplication_index in known_log_certs )
return;
else if ( |known_log_certs| < known_log_certs_maximum_size )
add known_log_certs[f$info$x509$deduplication_index];
}
Log::write(LOG, f$info$x509); Log::write(LOG, f$info$x509);
if ( f$info?$sha256 && f$info$sha256 !in certificate_cache &&
caching_required_encounters > 0 &&
f$info$sha256 in certificates_encountered &&
certificates_encountered[f$info$sha256] >= caching_required_encounters &&
|certificate_cache| < certificate_cache_max_entries )
{
delete certificates_encountered[f$info$sha256];
certificate_cache[f$info$sha256] = f$info$x509;
} }
}
event file_hash(f: fa_file, kind: string, hash: string)
{
if ( ! f?$info || "X509" !in f$info$analyzers || kind != "sha256" )
return;
if ( caching_required_encounters == 0 || hash in certificate_cache )
return;
if ( hash !in certificates_encountered )
certificates_encountered[hash] = 1;
else
certificates_encountered[hash] += 1;
}

View file

@ -124,7 +124,6 @@ export {
## A set of analyzers to disable by default at startup. The default set ## A set of analyzers to disable by default at startup. The default set
## contains legacy analyzers that are no longer supported. ## contains legacy analyzers that are no longer supported.
global disabled_analyzers: set[Analyzer::Tag] = { global disabled_analyzers: set[Analyzer::Tag] = {
ANALYZER_STEPPINGSTONE,
ANALYZER_TCPSTATS, ANALYZER_TCPSTATS,
} &redef; } &redef;
} }

View file

@ -122,6 +122,37 @@ export {
## done reading the pcap. ## done reading the pcap.
option peer_counts_as_iosource = T; option peer_counts_as_iosource = T;
## Port for Broker's metric exporter. Setting this to a valid TCP port causes
## Broker to make metrics available to Prometheus scrapers via HTTP. Zeek
## overrides any value provided in zeek_init or earlier at startup if the
## environment variable BROKER_METRICS_PORT is defined.
const metrics_port = 0/unknown &redef;
## Frequency for publishing scraped metrics to the target topic. Zeek
## overrides any value provided in zeek_init or earlier at startup if the
## environment variable BROKER_METRICS_EXPORT_INTERVAL is defined.
option metrics_export_interval = 1 sec;
## Target topic for the metrics. Setting a non-empty string starts the
## periodic publishing of local metrics. Zeek overrides any value provided in
## zeek_init or earlier at startup if the environment variable
## BROKER_METRICS_EXPORT_TOPIC is defined.
option metrics_export_topic = "";
## ID for the metrics exporter. When setting a target topic for the
## exporter, Broker sets this option to the suffix of the new topic *unless*
## the ID is a non-empty string. Since setting a topic starts the periodic
## publishing of events, we recommend setting the ID always first or avoid
## setting it at all if the topic suffix serves as a good-enough ID. Zeek
## overrides any value provided in zeek_init or earlier at startup if the
## environment variable BROKER_METRICS_ENDPOINT_NAME is defined.
option metrics_export_endpoint_name = "";
## Selects prefixes from the local metrics. Only metrics with prefixes
## listed in this variable are included when publishing local metrics.
## Setting an empty vector selects *all* metrics.
option metrics_export_prefixes: vector of string = vector();
## The default topic prefix where logs will be published. The log's stream ## The default topic prefix where logs will be published. The log's stream
## id is appended when writing to a particular stream. ## id is appended when writing to a particular stream.
const default_log_topic_prefix = "zeek/logs/" &redef; const default_log_topic_prefix = "zeek/logs/" &redef;
@ -255,6 +286,7 @@ export {
global listen: function(a: string &default = default_listen_address, global listen: function(a: string &default = default_listen_address,
p: port &default = default_port, p: port &default = default_port,
retry: interval &default = default_listen_retry): port; retry: interval &default = default_listen_retry): port;
## Initiate a remote connection. ## Initiate a remote connection.
## ##
## a: an address to connect to, e.g. "localhost" or "127.0.0.1". ## a: an address to connect to, e.g. "localhost" or "127.0.0.1".
@ -385,9 +417,53 @@ event Broker::log_flush() &priority=10
schedule Broker::log_batch_interval { Broker::log_flush() }; schedule Broker::log_batch_interval { Broker::log_flush() };
} }
function update_metrics_export_interval(id: string, val: interval): interval
{
Broker::__set_metrics_export_interval(val);
return val;
}
function update_metrics_export_topic(id: string, val: string): string
{
Broker::__set_metrics_export_topic(val);
return val;
}
function update_metrics_export_endpoint_name(id: string, val: string): string
{
Broker::__set_metrics_export_endpoint_name(val);
return val;
}
function update_metrics_export_prefixes(id: string, filter: vector of string): vector of string
{
Broker::__set_metrics_export_prefixes(filter);
return filter;
}
event zeek_init() event zeek_init()
{ {
schedule Broker::log_batch_interval { Broker::log_flush() }; schedule Broker::log_batch_interval { Broker::log_flush() };
# interval
update_metrics_export_interval("Broker::metrics_export_interval",
Broker::metrics_export_interval);
Option::set_change_handler("Broker::metrics_export_interval",
update_metrics_export_interval);
# topic
update_metrics_export_topic("Broker::metrics_export_topic",
Broker::metrics_export_topic);
Option::set_change_handler("Broker::metrics_export_topic",
update_metrics_export_topic);
# endpoint name
update_metrics_export_endpoint_name("Broker::metrics_export_endpoint_name",
Broker::metrics_export_endpoint_name);
Option::set_change_handler("Broker::metrics_export_endpoint_name",
update_metrics_export_endpoint_name);
# prefixes
update_metrics_export_prefixes("Broker::metrics_export_prefixes",
Broker::metrics_export_prefixes);
Option::set_change_handler("Broker::metrics_export_prefixes",
update_metrics_export_prefixes);
} }
event retry_listen(a: string, p: port, retry: interval) event retry_listen(a: string, p: port, retry: interval)

View file

@ -298,10 +298,25 @@ export {
config: table[string] of string &default=table(); config: table[string] of string &default=table();
}; };
## A hook type to implement filtering policy. Hook handlers can ## A hook type to implement filtering policy. Hook handlers run
## veto the logging of a record or alter it prior to logging. ## on each log record. They can implement arbitrary per-record
## You can pass arbitrary state into the hook via the ## processing, alter the log record, or veto the writing of the
## filter argument and its config member. ## given record by breaking from the hook handler.
##
## rec: An instance of the stream's ``columns`` type with its
## fields set to the values to be logged.
##
## id: The ID associated with the logging stream the filter
## belongs to.
type StreamPolicyHook: hook(rec: any, id: ID);
## A hook type to implement filtering policy at log filter
## granularity. Like :zeek:see:`Log::StreamPolicyHook`, these can
## implement added functionality, alter it prior to logging, or
## veto the write. These hooks run at log filter granularity,
## so get a :zeek:see:`Log::Filter` instance as additional
## argument. You can pass additional state into the hook via the
## the filter$config table.
## ##
## rec: An instance of the stream's ``columns`` type with its ## rec: An instance of the stream's ``columns`` type with its
## fields set to the values to be logged. ## fields set to the values to be logged.
@ -309,8 +324,8 @@ export {
## id: The ID associated with the logging stream the filter ## id: The ID associated with the logging stream the filter
## belongs to. ## belongs to.
## ##
## filter: The :zeek:type:`Log::Filter` instance that controls ## filter: The :zeek:type:`Log::Filter` instance that steers
## the fate of the given log record. ## the output of the given log record.
type PolicyHook: hook(rec: any, id: ID, filter: Filter); type PolicyHook: hook(rec: any, id: ID, filter: Filter);
# To allow Filters to have a policy hook that refers to # To allow Filters to have a policy hook that refers to
@ -551,6 +566,13 @@ export {
## This table is not meant to be modified by users! Only use it for ## This table is not meant to be modified by users! Only use it for
## examining which streams are active. ## examining which streams are active.
global active_streams: table[ID] of Stream = table(); global active_streams: table[ID] of Stream = table();
## The global log policy hook. The framework invokes this hook for any
## log write, prior to iterating over the stream's associated filters.
## As with filter-specific hooks, breaking from the hook vetoes writing
## of the given log record. Note that filter-level policy hooks still get
## invoked after the global hook vetos, but they cannot "un-veto" the write.
global log_stream_policy: Log::StreamPolicyHook;
} }
global all_streams: table[ID] of Stream = table(); global all_streams: table[ID] of Stream = table();
@ -627,7 +649,7 @@ function run_rotation_postprocessor_cmd(info: RotationInfo, npath: string) : boo
# The date format is hard-coded here to provide a standardized # The date format is hard-coded here to provide a standardized
# script interface. # script interface.
system(fmt("%s %s %s %s %s %d %s", system(fmt("%s %s %s %s %s %d %s",
pp_cmd, npath, info$path, pp_cmd, safe_shell_quote(npath), safe_shell_quote(info$path),
strftime("%y-%m-%d_%H.%M.%S", info$open), strftime("%y-%m-%d_%H.%M.%S", info$open),
strftime("%y-%m-%d_%H.%M.%S", info$close), strftime("%y-%m-%d_%H.%M.%S", info$close),
info$terminating, writer)); info$terminating, writer));

View file

@ -66,7 +66,7 @@ function scp_postprocessor(info: Log::RotationInfo): bool
command += fmt("scp %s %s@%s:%s;", info$fname, d$user, d$host, dst); command += fmt("scp %s %s@%s:%s;", info$fname, d$user, d$host, dst);
} }
command += fmt("/bin/rm %s", info$fname); command += fmt("/bin/rm %s", safe_shell_quote(info$fname));
system(command); system(command);
return T; return T;
} }

View file

@ -69,7 +69,7 @@ function sftp_postprocessor(info: Log::RotationInfo): bool
d$host_port, d$user, d$host); d$host_port, d$user, d$host);
} }
command += fmt("/bin/rm %s", info$fname); command += fmt("/bin/rm %s", safe_shell_quote(info$fname));
system(command); system(command);
return T; return T;
} }

View file

@ -38,7 +38,7 @@ export {
## written into logs. ## written into logs.
## ##
## This option is also available as a per-filter ``$config`` option. ## This option is also available as a per-filter ``$config`` option.
const enable_utf_8 = F &redef; const enable_utf_8 = T &redef;
## Define the gzip level to compress the logs. If 0, then no gzip ## Define the gzip level to compress the logs. If 0, then no gzip
## compression is performed. Enabling compression also changes ## compression is performed. Enabling compression also changes
@ -54,6 +54,11 @@ export {
## This option is also available as a per-filter ``$config`` option. ## This option is also available as a per-filter ``$config`` option.
const gzip_file_extension = "gz" &redef; const gzip_file_extension = "gz" &redef;
## Define the default logging directory. If empty, logs are written
## to the current working directory.
##
const logdir = "" &redef;
## Format of timestamps when writing out JSON. By default, the JSON ## Format of timestamps when writing out JSON. By default, the JSON
## formatter will use double values for timestamps which represent the ## formatter will use double values for timestamps which represent the
## number of seconds from the UNIX epoch. ## number of seconds from the UNIX epoch.

View file

@ -18,18 +18,15 @@ export {
}; };
} }
hook notice(n: Notice::Info) &priority=-5 hook notice(n: Notice::Info)
{ {
if ( |Site::local_admins| > 0 && if ( |Site::local_admins| > 0 &&
ACTION_EMAIL_ADMIN in n$actions ) ACTION_EMAIL_ADMIN in n$actions )
{ {
local email = ""; local email = "";
if ( n?$src && |Site::get_emails(n$src)| > 0 ) if ( n?$src && |Site::get_emails(n$src)| > 0 )
email = fmt("%s, %s", email, Site::get_emails(n$src)); add n$email_dest[Site::get_emails(n$src)];
if ( n?$dst && |Site::get_emails(n$dst)| > 0 ) if ( n?$dst && |Site::get_emails(n$dst)| > 0 )
email = fmt("%s, %s", email, Site::get_emails(n$dst)); add n$email_dest[Site::get_emails(n$dst)];
if ( email != "" )
email_notice_to(n, email, T);
} }
} }

View file

@ -17,8 +17,8 @@ export {
option mail_page_dest = ""; option mail_page_dest = "";
} }
hook notice(n: Notice::Info) &priority=-5 hook notice(n: Notice::Info)
{ {
if ( ACTION_PAGE in n$actions ) if ( ACTION_PAGE in n$actions )
email_notice_to(n, mail_page_dest, F); add n$email_dest[mail_page_dest];
} }

View file

@ -136,6 +136,9 @@ export {
## The actions which have been applied to this notice. ## The actions which have been applied to this notice.
actions: ActionSet &log &default=ActionSet(); actions: ActionSet &log &default=ActionSet();
## The email address(es) where to send this notice
email_dest: set[string] &log &default=set();
## By adding chunks of text into this element, other scripts ## By adding chunks of text into this element, other scripts
## can expand on notices that are being emailed. The normal ## can expand on notices that are being emailed. The normal
## way to add text is to extend the vector by handling the ## way to add text is to extend the vector by handling the
@ -199,11 +202,12 @@ export {
## ##
## Note that this is overridden by the ZeekControl SendMail option. ## Note that this is overridden by the ZeekControl SendMail option.
option sendmail = "/usr/sbin/sendmail"; option sendmail = "/usr/sbin/sendmail";
## Email address to send notices with the ## The default email address to send notices with the
## :zeek:enum:`Notice::ACTION_EMAIL` action or to send bulk alarm logs ## :zeek:enum:`Notice::ACTION_EMAIL` action or to send bulk alarm logs
## on rotation with :zeek:enum:`Notice::ACTION_ALARM`. ## on rotation with :zeek:enum:`Notice::ACTION_ALARM`.
## ##
## Note that this is overridden by the ZeekControl MailTo option. ## Note that this is overridden by the ZeekControl MailTo option or by
## the `email_dest` field in the :zeek:see:`Notice::Info` record.
const mail_dest = "" &redef; const mail_dest = "" &redef;
## Address that emails will be from. ## Address that emails will be from.
@ -380,12 +384,13 @@ function log_mailing_postprocessor(info: Log::RotationInfo): bool
{ {
local headers = email_headers(fmt("Log Contents: %s", info$fname), local headers = email_headers(fmt("Log Contents: %s", info$fname),
mail_dest); mail_dest);
local tmpfilename = fmt("%s.mailheaders.tmp", info$fname); local tmpfilename = safe_shell_quote(fmt("%s.mailheaders.tmp", info$fname));
local tmpfile = open(tmpfilename); local tmpfile = open(tmpfilename);
write_file(tmpfile, headers); write_file(tmpfile, headers);
close(tmpfile); close(tmpfile);
system(fmt("/bin/cat %s %s | %s -t -oi && /bin/rm %s %s", system(fmt("/bin/cat %s %s | %s -t -oi && /bin/rm %s %s",
tmpfilename, info$fname, sendmail, tmpfilename, info$fname)); tmpfilename, safe_shell_quote(info$fname), sendmail,
tmpfilename, safe_shell_quote(info$fname)));
} }
return T; return T;
} }
@ -510,10 +515,17 @@ hook Notice::policy(n: Notice::Info) &priority=10
add n$actions[ACTION_LOG]; add n$actions[ACTION_LOG];
} }
hook Notice::notice(n: Notice::Info) &priority=-5 hook Notice::notice(n: Notice::Info)
{ {
if ( ACTION_EMAIL in n$actions ) if ( ACTION_EMAIL in n$actions )
email_notice_to(n, mail_dest, T); add n$email_dest[mail_dest];
}
hook Notice::notice(n: Notice::Info) &priority=-5
{
for ( dest in n$email_dest )
email_notice_to(n, dest, T);
if ( ACTION_LOG in n$actions ) if ( ACTION_LOG in n$actions )
Log::write(Notice::LOG, n); Log::write(Notice::LOG, n);
if ( ACTION_ALARM in n$actions ) if ( ACTION_ALARM in n$actions )

View file

@ -238,6 +238,18 @@ function parse(unparsed_version: string): Description
return [$version=v, $unparsed_version=unparsed_version, $name=alternate_names[software_name]]; return [$version=v, $unparsed_version=unparsed_version, $name=alternate_names[software_name]];
} }
global parse_cache: table[string] of Description &read_expire=65secs;
# Call parse, but cache results in the parse_cache table
function parse_with_cache(unparsed_version: string): Description
{
if (unparsed_version in parse_cache)
return parse_cache[unparsed_version];
local res = parse(unparsed_version);
parse_cache[unparsed_version] = res;
return res;
}
function parse_mozilla(unparsed_version: string): Description function parse_mozilla(unparsed_version: string): Description
{ {
@ -464,8 +476,25 @@ function software_fmt(i: Info): string
return fmt("%s %s", i$name, software_fmt_version(i$version)); return fmt("%s %s", i$name, software_fmt_version(i$version));
} }
# Parse unparsed_version if needed before raising register event
# This is used to maintain the behavior of the exported Software::register
# event that expects a pre-parsed 'name' field.
event Software::new(info: Info)
{
if ( ! info?$version )
{
local sw = parse_with_cache(info$unparsed_version);
info$unparsed_version = sw$unparsed_version;
info$name = sw$name;
info$version = sw$version;
}
event Software::register(info);
}
event Software::register(info: Info) event Software::register(info: Info)
{ {
local ts: SoftwareSet; local ts: SoftwareSet;
if ( info$host in tracked ) if ( info$host in tracked )
@ -514,19 +543,10 @@ function found(id: conn_id, info: Info): bool
return F; return F;
} }
if ( ! info?$version )
{
local sw = parse(info$unparsed_version);
info$unparsed_version = sw$unparsed_version;
info$name = sw$name;
info$version = sw$version;
}
@if ( Cluster::is_enabled() ) @if ( Cluster::is_enabled() )
Cluster::publish_hrw(Cluster::proxy_pool, info$host, Software::register, Cluster::publish_hrw(Cluster::proxy_pool, info$host, Software::new, info);
info);
@else @else
event Software::register(info); event Software::new(info);
@endif @endif
return T; return T;

View file

@ -42,8 +42,13 @@ export {
stdout_file: string &optional; stdout_file: string &optional;
## The filename/path to which the node's stderr will be redirected. ## The filename/path to which the node's stderr will be redirected.
stderr_file: string &optional; stderr_file: string &optional;
## Whether to start the node in bare mode. When left out, the node
## inherits the bare-mode status the supervisor itself runs with.
bare_mode: bool &optional;
## Additional script filenames/paths that the node should load. ## Additional script filenames/paths that the node should load.
scripts: vector of string &default = vector(); scripts: vector of string &default = vector();
## Environment variables to define in the supervised node.
env: table[string] of string &default=table();
## A cpu/core number to which the node will try to pin itself. ## A cpu/core number to which the node will try to pin itself.
cpu_affinity: int &optional; cpu_affinity: int &optional;
## The Cluster Layout definition. Each node in the Cluster Framework ## The Cluster Layout definition. Each node in the Cluster Framework

View file

@ -4,6 +4,7 @@
##! That is, it may change in various incompatible ways without warning or ##! That is, it may change in various incompatible ways without warning or
##! deprecation until the stable 4.0.0 release. ##! deprecation until the stable 4.0.0 release.
@load base/frameworks/broker
@load ./api @load ./api
module SupervisorControl; module SupervisorControl;
@ -15,6 +16,10 @@ export {
## for their topic names. ## for their topic names.
const topic_prefix = "zeek/supervisor" &redef; const topic_prefix = "zeek/supervisor" &redef;
## When enabled, the Supervisor will listen on the configured Broker
## :zeek:see:`Broker::default_listen_address`.
const enable_listen = F &redef;
## Send a request to a remote Supervisor process to create a node. ## Send a request to a remote Supervisor process to create a node.
## ##
## reqid: an arbitrary string that will be directly echoed in the response ## reqid: an arbitrary string that will be directly echoed in the response

View file

@ -3,7 +3,6 @@
@load ./api @load ./api
@load ./control @load ./control
@load base/frameworks/broker
function Supervisor::status(node: string): Supervisor::Status function Supervisor::status(node: string): Supervisor::Status
{ {
@ -42,6 +41,14 @@ function Supervisor::node(): Supervisor::NodeConfig
event zeek_init() &priority=10 event zeek_init() &priority=10
{ {
if ( Supervisor::is_supervisor() && SupervisorControl::enable_listen )
{
# This may fail, possibly with scheduled retries. Any failures
# already get logged by the listen() implementation, so we don't
# report additionally.
Broker::listen();
}
Broker::subscribe(SupervisorControl::topic_prefix); Broker::subscribe(SupervisorControl::topic_prefix);
} }

View file

@ -93,7 +93,7 @@ export {
const ayiya_ports = { 5072/udp }; const ayiya_ports = { 5072/udp };
const teredo_ports = { 3544/udp }; const teredo_ports = { 3544/udp };
const gtpv1_ports = { 2152/udp, 2123/udp }; const gtpv1_ports = { 2152/udp, 2123/udp };
redef likely_server_ports += { ayiya_ports, teredo_ports, gtpv1_ports, vxlan_ports }; redef likely_server_ports += { ayiya_ports, teredo_ports, gtpv1_ports, vxlan_ports, geneve_ports };
event zeek_init() &priority=5 event zeek_init() &priority=5
{ {
@ -103,6 +103,7 @@ event zeek_init() &priority=5
Analyzer::register_for_ports(Analyzer::ANALYZER_TEREDO, teredo_ports); Analyzer::register_for_ports(Analyzer::ANALYZER_TEREDO, teredo_ports);
Analyzer::register_for_ports(Analyzer::ANALYZER_GTPV1, gtpv1_ports); Analyzer::register_for_ports(Analyzer::ANALYZER_GTPV1, gtpv1_ports);
Analyzer::register_for_ports(Analyzer::ANALYZER_VXLAN, vxlan_ports); Analyzer::register_for_ports(Analyzer::ANALYZER_VXLAN, vxlan_ports);
Analyzer::register_for_ports(Analyzer::ANALYZER_GENEVE, geneve_ports);
} }
function register_all(ecv: EncapsulatingConnVector) function register_all(ecv: EncapsulatingConnVector)

View file

@ -25,6 +25,13 @@ type string_any_table: table[string] of any;
## directly and then remove this alias. ## directly and then remove this alias.
type string_set: set[string]; type string_set: set[string];
## A set of subnets.
##
## .. todo:: We need this type definition only for declaring builtin functions
## via ``bifcl``. We should extend ``bifcl`` to understand composite types
## directly and then remove this alias.
type subnet_set: set[subnet];
## A set of addresses. ## A set of addresses.
## ##
## .. todo:: We need this type definition only for declaring builtin functions ## .. todo:: We need this type definition only for declaring builtin functions
@ -582,6 +589,8 @@ type SYN_packet: record {
win_scale: int; ##< The window scale option if present, or -1 if not. win_scale: int; ##< The window scale option if present, or -1 if not.
MSS: count; ##< The maximum segment size if present, or 0 if not. MSS: count; ##< The maximum segment size if present, or 0 if not.
SACK_OK: bool; ##< True if the *SACK* option is present. SACK_OK: bool; ##< True if the *SACK* option is present.
TSval: count &optional; ##< The TCP TS value if present.
TSecr: count &optional; ##< The TCP TS echo reply if present.
}; };
## Packet capture statistics. All counts are cumulative. ## Packet capture statistics. All counts are cumulative.
@ -635,7 +644,7 @@ type ProcStats: record {
real_time: interval; ##< Elapsed real time since Zeek started running. real_time: interval; ##< Elapsed real time since Zeek started running.
user_time: interval; ##< User CPU seconds. user_time: interval; ##< User CPU seconds.
system_time: interval; ##< System CPU seconds. system_time: interval; ##< System CPU seconds.
mem: count; ##< Maximum memory consumed, in KB. mem: count; ##< Maximum memory consumed, in bytes.
minor_faults: count; ##< Page faults not requiring actual I/O. minor_faults: count; ##< Page faults not requiring actual I/O.
major_faults: count; ##< Page faults requiring actual I/O. major_faults: count; ##< Page faults requiring actual I/O.
num_swap: count; ##< Times swapped out. num_swap: count; ##< Times swapped out.
@ -1933,6 +1942,7 @@ type gtp_delete_pdp_ctx_response_elements: record {
@load base/frameworks/supervisor/api @load base/frameworks/supervisor/api
@load base/bif/supervisor.bif @load base/bif/supervisor.bif
@load base/bif/packet_analysis.bif @load base/bif/packet_analysis.bif
@load base/bif/CPP-load.bif
## Internal function. ## Internal function.
function add_interface(iold: string, inew: string): string function add_interface(iold: string, inew: string): string
@ -2789,13 +2799,21 @@ export {
type SMB::MACTimes: record { type SMB::MACTimes: record {
## The time when data was last written to the file. ## The time when data was last written to the file.
modified : time &log; modified : time &log;
## Same as `modified` but in SMB's original `FILETIME` integer format.
modified_raw: count;
## The time when the file was last accessed. ## The time when the file was last accessed.
accessed : time &log; accessed : time &log;
## Same as `accessed` but in SMB's original `FILETIME` integer format.
accessed_raw: count;
## The time the file was created. ## The time the file was created.
created : time &log; created : time &log;
## Same as `created` but in SMB's original `FILETIME` integer format.
created_raw : count;
## The time when the file was last modified. ## The time when the file was last modified.
changed : time &log; changed : time &log;
} &log; ## Same as `changed` but in SMB's original `FILETIME` integer format.
changed_raw : count;
};
## A set of file names used as named pipes over SMB. This ## A set of file names used as named pipes over SMB. This
## only comes into play as a heuristic to identify named ## only comes into play as a heuristic to identify named
@ -4117,15 +4135,6 @@ type PE::SectionHeader: record {
} }
module GLOBAL; module GLOBAL;
## Internal to the stepping stone detector.
const stp_delta: interval &redef;
## Internal to the stepping stone detector.
const stp_idle_min: interval &redef;
## Internal to the stepping stone detector.
global stp_skip_src: set[addr] &redef;
## Description of a signature match. ## Description of a signature match.
## ##
## .. zeek:see:: signature_match ## .. zeek:see:: signature_match
@ -4890,9 +4899,21 @@ const dpd_reassemble_first_packets = T &redef;
## connections will be able to analyze the session. ## connections will be able to analyze the session.
## ##
## .. zeek:see:: dpd_reassemble_first_packets dpd_match_only_beginning ## .. zeek:see:: dpd_reassemble_first_packets dpd_match_only_beginning
## dpd_ignore_ports ## dpd_ignore_ports dpd_max_packets
const dpd_buffer_size = 1024 &redef; const dpd_buffer_size = 1024 &redef;
## Maximum number of per-connection packets that will be buffered for dynamic
## protocol detection. For each connection, Zeek buffers up to this amount
## of packets in memory so that complete protocol analysis can start even after
## the initial packets have already passed through (i.e., when a DPD signature
## matches only later). However, once the buffer is full, data is deleted and lost
## to analyzers that are activated afterwards. Then only analyzers that can deal
## with partial connections will be able to analyze the session.
##
## .. zeek:see:: dpd_reassemble_first_packets dpd_match_only_beginning
## dpd_ignore_ports dpd_buffer_size
const dpd_max_packets = 100 &redef;
## If true, stops signature matching if :zeek:see:`dpd_buffer_size` has been ## If true, stops signature matching if :zeek:see:`dpd_buffer_size` has been
## reached. ## reached.
## ##
@ -5029,6 +5050,12 @@ export {
## if you customize this, you may still want to manually ensure that ## if you customize this, you may still want to manually ensure that
## :zeek:see:`likely_server_ports` also gets populated accordingly. ## :zeek:see:`likely_server_ports` also gets populated accordingly.
const vxlan_ports: set[port] = { 4789/udp } &redef; const vxlan_ports: set[port] = { 4789/udp } &redef;
## The set of UDP ports used for Geneve traffic. Traffic using this
## UDP destination port will attempt to be decapsulated. Note that if
## if you customize this, you may still want to manually ensure that
## :zeek:see:`likely_server_ports` also gets populated accordingly.
const geneve_ports: set[port] = { 6081/udp } &redef;
} # end export } # end export
module Reporter; module Reporter;

View file

@ -0,0 +1,5 @@
##! This script loads functionality needed by the supervisor. Zeek only sources
##! this when the supervisor is active (-j). Like init-default.zeek, this isn't
##! loaded in bare mode.
@load base/frameworks/supervisor

View file

@ -15,3 +15,6 @@
@load base/packet-protocols/gre @load base/packet-protocols/gre
@load base/packet-protocols/iptunnel @load base/packet-protocols/iptunnel
@load base/packet-protocols/vntag @load base/packet-protocols/vntag
@load base/packet-protocols/udp
@load base/packet-protocols/tcp
@load base/packet-protocols/icmp

View file

@ -0,0 +1 @@
@load ./main

View file

@ -0,0 +1,5 @@
module PacketAnalyzer::ICMP;
#event zeek_init() &priority=20
# {
# }

View file

@ -1,8 +1,32 @@
module PacketAnalyzer::IP; module PacketAnalyzer::IP;
const IPPROTO_TCP : count = 6;
const IPPROTO_UDP : count = 17;
const IPPROTO_ICMP : count = 1;
const IPPROTO_ICMP6 : count = 58;
const IPPROTO_IPIP : count = 4;
const IPPROTO_IPV6 : count = 41;
const IPPROTO_GRE : count = 47;
function analyzer_option_change_ignore_checksums_nets(ID: string, new_value: set[subnet], location: string) : set[subnet]
{
if ( ID == "ignore_checksums_nets" )
PacketAnalyzer::__set_ignore_checksums_nets(new_value);
return new_value;
}
event zeek_init() &priority=20 event zeek_init() &priority=20
{ {
PacketAnalyzer::register_packet_analyzer(PacketAnalyzer::ANALYZER_IP, 4, PacketAnalyzer::ANALYZER_IPTUNNEL); PacketAnalyzer::register_packet_analyzer(PacketAnalyzer::ANALYZER_IP, IPPROTO_IPIP, PacketAnalyzer::ANALYZER_IPTUNNEL);
PacketAnalyzer::register_packet_analyzer(PacketAnalyzer::ANALYZER_IP, 41, PacketAnalyzer::ANALYZER_IPTUNNEL); PacketAnalyzer::register_packet_analyzer(PacketAnalyzer::ANALYZER_IP, IPPROTO_IPV6, PacketAnalyzer::ANALYZER_IPTUNNEL);
PacketAnalyzer::register_packet_analyzer(PacketAnalyzer::ANALYZER_IP, 47, PacketAnalyzer::ANALYZER_GRE); PacketAnalyzer::register_packet_analyzer(PacketAnalyzer::ANALYZER_IP, IPPROTO_GRE, PacketAnalyzer::ANALYZER_GRE);
PacketAnalyzer::register_packet_analyzer(PacketAnalyzer::ANALYZER_IP, IPPROTO_TCP, PacketAnalyzer::ANALYZER_TCP);
PacketAnalyzer::register_packet_analyzer(PacketAnalyzer::ANALYZER_IP, IPPROTO_UDP, PacketAnalyzer::ANALYZER_UDP);
PacketAnalyzer::register_packet_analyzer(PacketAnalyzer::ANALYZER_IP, IPPROTO_ICMP, PacketAnalyzer::ANALYZER_ICMP);
PacketAnalyzer::register_packet_analyzer(PacketAnalyzer::ANALYZER_IP, IPPROTO_ICMP6, PacketAnalyzer::ANALYZER_ICMP);
Option::set_change_handler("ignore_checksums_nets", analyzer_option_change_ignore_checksums_nets, 5);
} }

View file

@ -0,0 +1 @@
@load ./main

View file

@ -0,0 +1,5 @@
module PacketAnalyzer::TCP;
#event zeek_init() &priority=20
# {
# }

View file

@ -0,0 +1 @@
@load ./main

View file

@ -0,0 +1,5 @@
module PacketAnalyzer::UDP;
#event zeek_init() &priority=20
# {
# }

View file

@ -239,10 +239,7 @@ function determine_service(c: connection): string
function set_conn(c: connection, eoc: bool) function set_conn(c: connection, eoc: bool)
{ {
if ( ! c?$conn ) if ( ! c?$conn )
{ c$conn = Info();
local tmp: Info &is_assigned;
c$conn = tmp;
}
c$conn$ts=c$start_time; c$conn$ts=c$start_time;
c$conn$uid=c$uid; c$conn$uid=c$uid;

View file

@ -2197,6 +2197,27 @@ export {
["5422fd3a-d4b8-4cef-a12e-e87d4ca22e90",0x08] = "GetCAPropertyInfo", ["5422fd3a-d4b8-4cef-a12e-e87d4ca22e90",0x08] = "GetCAPropertyInfo",
["5422fd3a-d4b8-4cef-a12e-e87d4ca22e90",0x09] = "Ping2", ["5422fd3a-d4b8-4cef-a12e-e87d4ca22e90",0x09] = "Ping2",
# IDispatch - MSDN Ref: OLE Automation Protocol [ms-oaut]
["00020400-0000-0000-c000-000000000046",0x03] = "GetTypeInfoCount",
["00020400-0000-0000-c000-000000000046",0x04] = "GetTypeInfo",
["00020400-0000-0000-c000-000000000046",0x05] = "GetIDsOfNames",
["00020400-0000-0000-c000-000000000046",0x06] = "Invoke",
# ITypeInfo - MSDN Ref: OLE Automation Protocol [ms-oaut]
["00020401-0000-0000-c000-000000000046",0x03] = "GetTypeAttr",
["00020401-0000-0000-c000-000000000046",0x04] = "GetTypeComp",
["00020401-0000-0000-c000-000000000046",0x05] = "GetFuncDesc",
["00020401-0000-0000-c000-000000000046",0x06] = "GetVarDesc",
["00020401-0000-0000-c000-000000000046",0x07] = "GetNames",
["00020401-0000-0000-c000-000000000046",0x08] = "GetRefTypeOfImplType",
["00020401-0000-0000-c000-000000000046",0x09] = "GetImplTypeFlags",
["00020401-0000-0000-c000-000000000046",0x0C] = "GetDocumentation",
["00020401-0000-0000-c000-000000000046",0x0D] = "GetDllEntry",
["00020401-0000-0000-c000-000000000046",0x0E] = "GetRefTypeInfo",
["00020401-0000-0000-c000-000000000046",0x10] = "CreateInstance",
["00020401-0000-0000-c000-000000000046",0x11] = "GetMops",
["00020401-0000-0000-c000-000000000046",0x12] = "GetContainingTypeLib",
# IDMNotify - MSDN Ref: Disk Mgmt Remote Protocol [ms-dmrp] # IDMNotify - MSDN Ref: Disk Mgmt Remote Protocol [ms-dmrp]
["d2d79df7-3400-11d0-b40b-00aa005ff586",0x00] = "ObjectsChanged", ["d2d79df7-3400-11d0-b40b-00aa005ff586",0x00] = "ObjectsChanged",

View file

@ -63,15 +63,22 @@ export {
[50] = "NSEC3", [50] = "NSEC3",
[51] = "NSEC3PARAM", [51] = "NSEC3PARAM",
[52] = "TLSA", [52] = "TLSA",
[53] = "SMIMEA",
[55] = "HIP", [55] = "HIP",
[59] = "CDS", [59] = "CDS",
[60] = "CDNSKEY", [60] = "CDNSKEY",
[61] = "OPENPGPKEY", [61] = "OPENPGPKEY",
[62] = "CSYNC",
[63] = "ZONEMD",
[64] = "SVCB",
[65] = "HTTPS",
[99] = "SPF", [99] = "SPF",
[100] = "UINFO", [100] = "UINFO",
[101] = "UID", [101] = "UID",
[102] = "GID", [102] = "GID",
[103] = "UNSPEC", [103] = "UNSPEC",
[108] = "EUI48",
[109] = "EUI64",
[249] = "TKEY", [249] = "TKEY",
[250] = "TSIG", [250] = "TSIG",
[251] = "IXFR", [251] = "IXFR",
@ -83,6 +90,7 @@ export {
[257] = "CAA", [257] = "CAA",
[32768] = "TA", [32768] = "TA",
[32769] = "DLV", [32769] = "DLV",
[65521] = "INTEGRITY", # google: https://docs.google.com/document/d/14eCqVyT_3MSj7ydqNFl1Yl0yg1fs6g24qmYUUdi5V-k/edit
} &default = function(n: count): string { return fmt("query-%d", n); }; } &default = function(n: count): string { return fmt("query-%d", n); };
## Errors used for non-TSIG/EDNS types. ## Errors used for non-TSIG/EDNS types.

View file

@ -434,7 +434,11 @@ event dns_request(c: connection, msg: dns_msg, query: string, qtype: count, qcla
# worked into the query/response in some fashion. # worked into the query/response in some fashion.
if ( c$id$resp_p == 137/udp ) if ( c$id$resp_p == 137/udp )
{ {
query = decode_netbios_name(query); local decoded_query = decode_netbios_name(query);
if ( |decoded_query| != 0 )
query = decoded_query;
if ( c$dns$qtype_name == "SRV" ) if ( c$dns$qtype_name == "SRV" )
{ {
# The SRV RFC used the ID used for NetBios Status RRs. # The SRV RFC used the ID used for NetBios Status RRs.

View file

@ -107,7 +107,8 @@ event ssl_established(c: connection) &priority=5
function data_channel_initial_criteria(c: connection): bool function data_channel_initial_criteria(c: connection): bool
{ {
return ( c?$ssl && c$ssl?$client_subject && c$ssl?$subject && return ( c?$ssl && c$ssl?$cert_chain && c$ssl?$client_cert_chain &&
|c$ssl$cert_chain| > 0 && |c$ssl$client_cert_chain| > 0 &&
c$ssl?$cipher && /WITH_NULL/ in c$ssl$cipher ); c$ssl?$cipher && /WITH_NULL/ in c$ssl$cipher );
} }

View file

@ -24,8 +24,9 @@ function get_file_handle(c: connection, is_orig: bool): string
local path_name = current_file?$path ? current_file$path : ""; local path_name = current_file?$path ? current_file$path : "";
local file_name = current_file?$name ? current_file$name : ""; local file_name = current_file?$name ? current_file$name : "";
# Include last_mod time if available because if a file has been modified it # Include last_mod time if available because if a file has been modified it
# should be considered a new file. # should be considered a new file. We use the raw version here to avoid
local last_mod = cat(current_file?$times ? current_file$times$modified : double_to_time(0.0)); # getting differences when double precision varies by architecture.
local last_mod = cat(current_file?$times ? current_file$times$modified_raw : 0);
# TODO: This is doing hexdump to avoid problems due to file analysis handling # TODO: This is doing hexdump to avoid problems due to file analysis handling
# using CheckString which is not immune to encapsulated null bytes. # using CheckString which is not immune to encapsulated null bytes.
# This needs to be fixed lower in the file analysis code later. # This needs to be fixed lower in the file analysis code later.

View file

@ -109,7 +109,7 @@ event zeek_init() &priority=5
function find_address_in_smtp_header(header: string): string function find_address_in_smtp_header(header: string): string
{ {
local ips = extract_ip_addresses(header); local ips = extract_ip_addresses(header, T);
# If there are more than one IP address found, return the second. # If there are more than one IP address found, return the second.
if ( |ips| > 1 ) if ( |ips| > 1 )
return ips[1]; return ips[1];

View file

@ -20,8 +20,12 @@ export {
uid: string &log; uid: string &log;
## The connection's 4-tuple of endpoint addresses/ports. ## The connection's 4-tuple of endpoint addresses/ports.
id: conn_id &log; id: conn_id &log;
## SSH major version (1 or 2) ## SSH major version (1, 2, or unset). The version can be unset if the
version: count &log; ## client and server version strings are unset, malformed or incompatible
## so no common version can be extracted. If no version can be extracted
## even though both client and server versions are set a weird
## will be generated.
version: count &log &optional;
## Authentication result (T=success, F=failure, unset=unknown) ## Authentication result (T=success, F=failure, unset=unknown)
auth_success: bool &log &optional; auth_success: bool &log &optional;
## The number of authentication attemps we observed. There's always ## The number of authentication attemps we observed. There's always
@ -155,9 +159,20 @@ function set_session(c: connection)
} }
} }
function set_version(c: connection, version: string) function set_version(c: connection)
{ {
if ( c$ssh?$server && c$ssh?$client && |c$ssh$client| > 4 && |c$ssh$server| > 4 ) # We always either set the version field to a concrete value, or unset it.
delete c$ssh$version;
# If either the client or server string is unset we cannot compute a
# version and return early. We do not raise a weird in this case as we
# might arrive here while having only seen one side of the handshake.
const has_server = c$ssh?$server && |c$ssh$server| > 0;
const has_client = c$ssh?$client && |c$ssh$client| > 0;
if ( ! ( has_server && has_client ) )
return;
if ( |c$ssh$client| > 4 && |c$ssh$server| > 4 )
{ {
if ( c$ssh$client[4] == "1" && c$ssh$server[4] == "2" ) if ( c$ssh$client[4] == "1" && c$ssh$server[4] == "2" )
{ {
@ -166,7 +181,8 @@ function set_version(c: connection, version: string)
c$ssh$version = 2; c$ssh$version = 2;
# SSH1 vs SSH2 -> Undefined # SSH1 vs SSH2 -> Undefined
else else
c$ssh$version = 0; Reporter::conn_weird("SSH_version_mismatch", c, fmt("%s vs %s", c$ssh$server, c$ssh$client));
return;
} }
else if ( c$ssh$client[4] == "2" && c$ssh$server[4] == "1" ) else if ( c$ssh$client[4] == "2" && c$ssh$server[4] == "1" )
{ {
@ -175,7 +191,8 @@ function set_version(c: connection, version: string)
c$ssh$version = 2; c$ssh$version = 2;
else else
# SSH2 vs SSH1 -> Undefined # SSH2 vs SSH1 -> Undefined
c$ssh$version = 0; Reporter::conn_weird("SSH_version_mismatch", c, fmt("%s vs %s", c$ssh$server, c$ssh$client));
return;
} }
else if ( c$ssh$client[4] == "1" && c$ssh$server[4] == "1" ) else if ( c$ssh$client[4] == "1" && c$ssh$server[4] == "1" )
{ {
@ -199,21 +216,25 @@ function set_version(c: connection, version: string)
{ {
c$ssh$version = 2; c$ssh$version = 2;
} }
return;
} }
Reporter::conn_weird("SSH_cannot_determine_version", c, fmt("%s vs %s", c$ssh$server, c$ssh$client));
} }
event ssh_server_version(c: connection, version: string) event ssh_server_version(c: connection, version: string)
{ {
set_session(c); set_session(c);
c$ssh$server = version; c$ssh$server = version;
set_version(c, version); set_version(c);
} }
event ssh_client_version(c: connection, version: string) event ssh_client_version(c: connection, version: string)
{ {
set_session(c); set_session(c);
c$ssh$client = version; c$ssh$client = version;
set_version(c, version); set_version(c);
} }
event ssh_auth_attempted(c: connection, authenticated: bool) &priority=5 event ssh_auth_attempted(c: connection, authenticated: bool) &priority=5

View file

@ -1,22 +1,15 @@
# #
# Do not edit this file. This file is automatically generated by gen-ct-list.pl # Do not edit this file. This file is automatically generated by gen-ct-list.pl
# File generated at Wed Dec 9 21:42:12 2020 # File generated at Wed Jun 30 13:58:18 2021
# File generated from https://www.gstatic.com/ct/log_list/all_logs_list.json # File generated from https://www.gstatic.com/ct/log_list/log_list.json
# #
@load base/protocols/ssl @load base/protocols/ssl
module SSL; module SSL;
redef ct_logs += { redef ct_logs += {
["\xfa\xd4\xc9\x7c\xc4\x9e\xe2\xf8\xac\x85\xc5\xea\x5c\xea\x09\xd0\x22\x0d\xbb\xf4\xe4\x9c\x6b\x50\x66\x2f\xf8\x68\xf8\x6b\x8c\x28"] = CTInfo($description="Google 'Argon2017' log", $operator="Google", $url="ct.googleapis.com/logs/argon2017/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x54\x6d\x7c\x89\xdd\xea\x9d\xf0\xba\x5f\xf4\x6d\x60\x7a\x37\x4f\x02\x25\xbf\x1c\xf6\x6f\x85\xae\xaf\x15\xdf\x69\x6e\xed\xdb\xa9\x9a\x29\x97\xf2\x99\x76\x1e\xe6\x33\x46\x1e\x27\xf4\xbe\x70\xdd\x59\xd7\xba\xcf\xfe\xd0\x72\x8e\xb0\x57\x0f\x9d\x37\x89\x62\xa3"),
["\xa4\x50\x12\x69\x05\x5a\x15\x54\x5e\x62\x11\xab\x37\xbc\x10\x3f\x62\xae\x55\x76\xa4\x5e\x4b\x17\x14\x45\x3e\x1b\x22\x10\x6a\x25"] = CTInfo($description="Google 'Argon2018' log", $operator="Google", $url="ct.googleapis.com/logs/argon2018/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\xd2\x00\x55\x05\xad\xd5\x47\xb4\x19\xbb\xcd\x95\xfb\x29\xd7\x58\x3d\x78\x24\xcd\xce\x46\x9d\xfb\x32\xd4\x71\x4e\x60\x02\x25\x5e\x59\x3e\xd7\xd4\x03\xb8\x6d\x43\x68\x68\x7e\xe8\xa0\x65\x0b\x3e\x6e\x71\x59\x92\x37\xbe\xa9\xe8\xf1\xa3\x2b\xe4\xd9\x0d\x55\x68"),
["\x63\xf2\xdb\xcd\xe8\x3b\xcc\x2c\xcf\x0b\x72\x84\x27\x57\x6b\x33\xa4\x8d\x61\x77\x8f\xbd\x75\xa6\x38\xb1\xc7\x68\x54\x4b\xd8\x8d"] = CTInfo($description="Google 'Argon2019' log", $operator="Google", $url="ct.googleapis.com/logs/argon2019/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x23\x73\x10\x9b\xe1\xf3\x5e\xf6\x98\x6b\x69\x95\x96\x10\x78\xce\x49\xdb\xb4\x04\xfc\x71\x2c\x5a\x92\x60\x68\x25\xc0\x4a\x1a\xa1\xb0\x61\x2d\x1b\x87\x14\xa9\xba\xf0\x01\x33\x59\x1d\x05\x30\xe9\x42\x15\xe7\x55\xd7\x2a\xf8\xb4\xa2\xba\x45\xc9\x46\x91\x87\x56"),
["\xb2\x1e\x05\xcc\x8b\xa2\xcd\x8a\x20\x4e\x87\x66\xf9\x2b\xb9\x8a\x25\x20\x67\x6b\xda\xfa\x70\xe7\xb2\x49\x53\x2d\xef\x8b\x90\x5e"] = CTInfo($description="Google 'Argon2020' log", $operator="Google", $url="ct.googleapis.com/logs/argon2020/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\xe9\x3c\x76\xa7\x5c\x8a\x63\x8d\x35\xe4\xdc\x88\x62\xf7\x6b\x93\x7e\x9e\xb3\x4b\x80\x73\x5c\xc0\xe0\xf4\x3e\x4c\x64\x58\xfb\x76\x63\x51\x32\x18\x63\xd5\xb2\xbb\xed\xea\xff\x5e\x3b\x24\x6e\x2f\x35\x52\x8b\xb4\x35\x9a\xad\x9c\x15\xa8\x69\x20\xea\x50\x18\xcc"),
["\xf6\x5c\x94\x2f\xd1\x77\x30\x22\x14\x54\x18\x08\x30\x94\x56\x8e\xe3\x4d\x13\x19\x33\xbf\xdf\x0c\x2f\x20\x0b\xcc\x4e\xf1\x64\xe3"] = CTInfo($description="Google 'Argon2021' log", $operator="Google", $url="ct.googleapis.com/logs/argon2021/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x4d\xe0\x66\x64\xea\xf3\x64\xaa\x38\xc5\x89\x2d\xc7\xd8\x08\xd9\xc8\x44\x71\xed\xdc\xc3\xfb\x5b\xaf\x9c\x64\xa1\x09\x66\x84\x1d\x7c\x68\xa7\xec\xc4\x3f\x8c\x9c\x82\xe0\x18\xd9\x74\x14\xe9\xb4\x79\x81\xa2\x94\x55\x62\xf3\x9c\x0b\x44\x83\xa1\x2b\xc9\x71\x2b"), ["\xf6\x5c\x94\x2f\xd1\x77\x30\x22\x14\x54\x18\x08\x30\x94\x56\x8e\xe3\x4d\x13\x19\x33\xbf\xdf\x0c\x2f\x20\x0b\xcc\x4e\xf1\x64\xe3"] = CTInfo($description="Google 'Argon2021' log", $operator="Google", $url="ct.googleapis.com/logs/argon2021/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x4d\xe0\x66\x64\xea\xf3\x64\xaa\x38\xc5\x89\x2d\xc7\xd8\x08\xd9\xc8\x44\x71\xed\xdc\xc3\xfb\x5b\xaf\x9c\x64\xa1\x09\x66\x84\x1d\x7c\x68\xa7\xec\xc4\x3f\x8c\x9c\x82\xe0\x18\xd9\x74\x14\xe9\xb4\x79\x81\xa2\x94\x55\x62\xf3\x9c\x0b\x44\x83\xa1\x2b\xc9\x71\x2b"),
["\x29\x79\xbe\xf0\x9e\x39\x39\x21\xf0\x56\x73\x9f\x63\xa5\x77\xe5\xbe\x57\x7d\x9c\x60\x0a\xf8\xf9\x4d\x5d\x26\x5c\x25\x5d\xc7\x84"] = CTInfo($description="Google 'Argon2022' log", $operator="Google", $url="ct.googleapis.com/logs/argon2022/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x78\x83\xdc\xe9\xf1\xa6\xb8\x18\x3a\x00\x99\x2f\xff\x3e\xcd\x15\xc9\x26\x1e\xf7\xff\x3a\xa9\xa3\x72\x16\x49\xeb\x09\xb6\xa8\xdd\xb4\xd2\x47\x91\x0e\x0d\xf9\xd9\xd5\xa9\x8b\xb0\x87\x9d\x25\x79\xd4\x1a\x50\x60\x08\xf5\x09\x06\x39\x26\xe4\x40\xc2\xba\xc3\xc2"), ["\x29\x79\xbe\xf0\x9e\x39\x39\x21\xf0\x56\x73\x9f\x63\xa5\x77\xe5\xbe\x57\x7d\x9c\x60\x0a\xf8\xf9\x4d\x5d\x26\x5c\x25\x5d\xc7\x84"] = CTInfo($description="Google 'Argon2022' log", $operator="Google", $url="ct.googleapis.com/logs/argon2022/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x78\x83\xdc\xe9\xf1\xa6\xb8\x18\x3a\x00\x99\x2f\xff\x3e\xcd\x15\xc9\x26\x1e\xf7\xff\x3a\xa9\xa3\x72\x16\x49\xeb\x09\xb6\xa8\xdd\xb4\xd2\x47\x91\x0e\x0d\xf9\xd9\xd5\xa9\x8b\xb0\x87\x9d\x25\x79\xd4\x1a\x50\x60\x08\xf5\x09\x06\x39\x26\xe4\x40\xc2\xba\xc3\xc2"),
["\xe8\x3e\xd0\xda\x3e\xf5\x06\x35\x32\xe7\x57\x28\xbc\x89\x6b\xc9\x03\xd3\xcb\xd1\x11\x6b\xec\xeb\x69\xe1\x77\x7d\x6d\x06\xbd\x6e"] = CTInfo($description="Google 'Argon2023' log", $operator="Google", $url="ct.googleapis.com/logs/argon2023/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\xd0\x90\x8f\x64\x52\x4e\x42\xac\x84\xb6\x2e\x4c\xf2\x3d\x77\x00\xb3\x77\x08\x05\x47\xaa\x45\x4c\xe3\x2c\x8e\x70\xa5\x82\xbb\x6c\xb2\x7b\x9c\x98\x7a\xa0\xe9\x11\x76\x28\x00\xb2\x20\xb4\xcd\xd3\x98\x7b\x4d\x96\x27\xe6\xb7\xee\x22\x6a\xd1\xb0\x2e\x91\x77\x78"), ["\xe8\x3e\xd0\xda\x3e\xf5\x06\x35\x32\xe7\x57\x28\xbc\x89\x6b\xc9\x03\xd3\xcb\xd1\x11\x6b\xec\xeb\x69\xe1\x77\x7d\x6d\x06\xbd\x6e"] = CTInfo($description="Google 'Argon2023' log", $operator="Google", $url="ct.googleapis.com/logs/argon2023/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\xd0\x90\x8f\x64\x52\x4e\x42\xac\x84\xb6\x2e\x4c\xf2\x3d\x77\x00\xb3\x77\x08\x05\x47\xaa\x45\x4c\xe3\x2c\x8e\x70\xa5\x82\xbb\x6c\xb2\x7b\x9c\x98\x7a\xa0\xe9\x11\x76\x28\x00\xb2\x20\xb4\xcd\xd3\x98\x7b\x4d\x96\x27\xe6\xb7\xee\x22\x6a\xd1\xb0\x2e\x91\x77\x78"),
["\xb1\x0c\xd5\x59\xa6\xd6\x78\x46\x81\x1f\x7d\xf9\xa5\x15\x32\x73\x9a\xc4\x8d\x70\x3b\xea\x03\x23\xda\x5d\x38\x75\x5b\xc0\xad\x4e"] = CTInfo($description="Google 'Xenon2018' log", $operator="Google", $url="ct.googleapis.com/logs/xenon2018/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\xd6\xcc\x89\xbf\x04\x1d\xae\xfd\x1a\xf1\xd3\x36\x54\x09\xca\xfd\x29\x87\x24\xdc\x3f\xf8\x5c\x42\xf8\x29\xdc\x15\xc9\xd7\x31\x7d\xa3\x34\x7f\x57\xb3\xb4\x39\xe8\x58\x95\xde\xd6\x86\xe4\x6d\x82\xa2\x43\x2c\x8b\x38\x69\x72\x6e\xf1\x5f\x3b\x91\xdc\x81\xe6\x6a"),
["\x08\x41\x14\x98\x00\x71\x53\x2c\x16\x19\x04\x60\xbc\xfc\x47\xfd\xc2\x65\x3a\xfa\x29\x2c\x72\xb3\x7f\xf8\x63\xae\x29\xcc\xc9\xf0"] = CTInfo($description="Google 'Xenon2019' log", $operator="Google", $url="ct.googleapis.com/logs/xenon2019/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\xfd\x7c\x83\xc2\xac\xd7\x2f\xd8\xb6\x19\x38\xcc\x62\x4a\x9a\x13\x28\x91\x2f\x40\xf2\xf6\xc1\xea\xfc\x14\xde\x6c\x57\x6c\x85\xbb\xc2\x69\x75\xc4\x87\xa9\xa3\x50\xad\x18\xcb\xe0\x2c\x0d\xc2\x38\x32\x9c\xc5\xd6\x5e\xca\x75\xe7\x76\x30\x3e\x73\x8b\x8d\xb4\x80"),
["\x07\xb7\x5c\x1b\xe5\x7d\x68\xff\xf1\xb0\xc6\x1d\x23\x15\xc7\xba\xe6\x57\x7c\x57\x94\xb7\x6a\xee\xbc\x61\x3a\x1a\x69\xd3\xa2\x1c"] = CTInfo($description="Google 'Xenon2020' log", $operator="Google", $url="ct.googleapis.com/logs/xenon2020/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x65\x4e\xf9\x56\xa8\xf2\xcd\x24\xe0\x15\x92\x80\x9d\x68\x35\x41\xe6\x1f\x14\x52\x11\x65\x33\x0a\xee\xad\xe4\x59\x66\x6c\x98\x78\x50\x76\xb0\x58\x9c\x74\x59\xdc\xe0\x38\x91\x47\x94\xc7\x42\x4d\xfb\x15\xfe\x75\x28\x2d\xd6\xbb\xaa\x52\x18\x65\xee\x33\xaf\x9b"),
["\x7d\x3e\xf2\xf8\x8f\xff\x88\x55\x68\x24\xc2\xc0\xca\x9e\x52\x89\x79\x2b\xc5\x0e\x78\x09\x7f\x2e\x6a\x97\x68\x99\x7e\x22\xf0\xd7"] = CTInfo($description="Google 'Xenon2021' log", $operator="Google", $url="ct.googleapis.com/logs/xenon2021/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x47\xed\x4c\x22\x7b\xbc\x43\x7f\x41\xc0\x36\x79\x46\x9f\x53\xc1\x78\x70\x9b\x79\x2d\xbe\x02\x73\xa6\x4f\xeb\xed\xd0\xe0\x1a\x4e\xd9\x69\xc3\x26\xde\x58\xdf\x72\x82\x2f\x3f\x51\x3b\xd9\x3f\x23\xbf\x22\xd3\xd5\xbb\xdd\x6a\x9c\xa5\x6a\x36\x5c\x4c\x7e\x96\xe6"), ["\x7d\x3e\xf2\xf8\x8f\xff\x88\x55\x68\x24\xc2\xc0\xca\x9e\x52\x89\x79\x2b\xc5\x0e\x78\x09\x7f\x2e\x6a\x97\x68\x99\x7e\x22\xf0\xd7"] = CTInfo($description="Google 'Xenon2021' log", $operator="Google", $url="ct.googleapis.com/logs/xenon2021/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x47\xed\x4c\x22\x7b\xbc\x43\x7f\x41\xc0\x36\x79\x46\x9f\x53\xc1\x78\x70\x9b\x79\x2d\xbe\x02\x73\xa6\x4f\xeb\xed\xd0\xe0\x1a\x4e\xd9\x69\xc3\x26\xde\x58\xdf\x72\x82\x2f\x3f\x51\x3b\xd9\x3f\x23\xbf\x22\xd3\xd5\xbb\xdd\x6a\x9c\xa5\x6a\x36\x5c\x4c\x7e\x96\xe6"),
["\x46\xa5\x55\xeb\x75\xfa\x91\x20\x30\xb5\xa2\x89\x69\xf4\xf3\x7d\x11\x2c\x41\x74\xbe\xfd\x49\xb8\x85\xab\xf2\xfc\x70\xfe\x6d\x47"] = CTInfo($description="Google 'Xenon2022' log", $operator="Google", $url="ct.googleapis.com/logs/xenon2022/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\xf9\x64\xbd\x15\x2c\x40\x62\x50\x95\x13\x38\x3c\xc7\x21\xb0\x3a\xb9\x8f\xa2\x7a\x15\xd7\x89\xd6\x8e\x31\x13\x00\x87\x59\xbc\xbb\xee\x90\xfc\xc8\x58\x13\x0a\xbf\xab\x43\x36\x54\x23\xa4\x81\xcd\xad\x47\x14\xb7\x58\xa0\x44\xfa\x6a\xa0\xa0\xd7\xc3\x63\x1e\x2b"), ["\x46\xa5\x55\xeb\x75\xfa\x91\x20\x30\xb5\xa2\x89\x69\xf4\xf3\x7d\x11\x2c\x41\x74\xbe\xfd\x49\xb8\x85\xab\xf2\xfc\x70\xfe\x6d\x47"] = CTInfo($description="Google 'Xenon2022' log", $operator="Google", $url="ct.googleapis.com/logs/xenon2022/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\xf9\x64\xbd\x15\x2c\x40\x62\x50\x95\x13\x38\x3c\xc7\x21\xb0\x3a\xb9\x8f\xa2\x7a\x15\xd7\x89\xd6\x8e\x31\x13\x00\x87\x59\xbc\xbb\xee\x90\xfc\xc8\x58\x13\x0a\xbf\xab\x43\x36\x54\x23\xa4\x81\xcd\xad\x47\x14\xb7\x58\xa0\x44\xfa\x6a\xa0\xa0\xd7\xc3\x63\x1e\x2b"),
["\xad\xf7\xbe\xfa\x7c\xff\x10\xc8\x8b\x9d\x3d\x9c\x1e\x3e\x18\x6a\xb4\x67\x29\x5d\xcf\xb1\x0c\x24\xca\x85\x86\x34\xeb\xdc\x82\x8a"] = CTInfo($description="Google 'Xenon2023' log", $operator="Google", $url="ct.googleapis.com/logs/xenon2023/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x72\x16\x3e\x0b\xef\xef\xce\x3e\x60\xdd\x95\xcb\x63\x7a\xb9\xa9\x8d\x4a\x6f\x6c\xdc\x61\x80\xa6\x45\x5e\x2f\x83\xac\x94\xf3\x85\x88\xd0\xa5\x74\xd0\x7b\x8e\xff\xc5\xee\x42\xa2\xf0\x2d\x93\xe3\xc2\xd0\xb2\x99\xe2\xe1\x42\xe9\xd2\xc6\x00\x27\x69\x74\xae\xce"), ["\xad\xf7\xbe\xfa\x7c\xff\x10\xc8\x8b\x9d\x3d\x9c\x1e\x3e\x18\x6a\xb4\x67\x29\x5d\xcf\xb1\x0c\x24\xca\x85\x86\x34\xeb\xdc\x82\x8a"] = CTInfo($description="Google 'Xenon2023' log", $operator="Google", $url="ct.googleapis.com/logs/xenon2023/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x72\x16\x3e\x0b\xef\xef\xce\x3e\x60\xdd\x95\xcb\x63\x7a\xb9\xa9\x8d\x4a\x6f\x6c\xdc\x61\x80\xa6\x45\x5e\x2f\x83\xac\x94\xf3\x85\x88\xd0\xa5\x74\xd0\x7b\x8e\xff\xc5\xee\x42\xa2\xf0\x2d\x93\xe3\xc2\xd0\xb2\x99\xe2\xe1\x42\xe9\xd2\xc6\x00\x27\x69\x74\xae\xce"),
@ -25,87 +18,32 @@ redef ct_logs += {
["\xa4\xb9\x09\x90\xb4\x18\x58\x14\x87\xbb\x13\xa2\xcc\x67\x70\x0a\x3c\x35\x98\x04\xf9\x1b\xdf\xb8\xe3\x77\xcd\x0e\xc8\x0d\xdc\x10"] = CTInfo($description="Google 'Pilot' log", $operator="Google", $url="ct.googleapis.com/pilot/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x7d\xa8\x4b\x12\x29\x80\xa3\x3d\xad\xd3\x5a\x77\xb8\xcc\xe2\x88\xb3\xa5\xfd\xf1\xd3\x0c\xcd\x18\x0c\xe8\x41\x46\xe8\x81\x01\x1b\x15\xe1\x4b\xf1\x1b\x62\xdd\x36\x0a\x08\x18\xba\xed\x0b\x35\x84\xd0\x9e\x40\x3c\x2d\x9e\x9b\x82\x65\xbd\x1f\x04\x10\x41\x4c\xa0"), ["\xa4\xb9\x09\x90\xb4\x18\x58\x14\x87\xbb\x13\xa2\xcc\x67\x70\x0a\x3c\x35\x98\x04\xf9\x1b\xdf\xb8\xe3\x77\xcd\x0e\xc8\x0d\xdc\x10"] = CTInfo($description="Google 'Pilot' log", $operator="Google", $url="ct.googleapis.com/pilot/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x7d\xa8\x4b\x12\x29\x80\xa3\x3d\xad\xd3\x5a\x77\xb8\xcc\xe2\x88\xb3\xa5\xfd\xf1\xd3\x0c\xcd\x18\x0c\xe8\x41\x46\xe8\x81\x01\x1b\x15\xe1\x4b\xf1\x1b\x62\xdd\x36\x0a\x08\x18\xba\xed\x0b\x35\x84\xd0\x9e\x40\x3c\x2d\x9e\x9b\x82\x65\xbd\x1f\x04\x10\x41\x4c\xa0"),
["\xee\x4b\xbd\xb7\x75\xce\x60\xba\xe1\x42\x69\x1f\xab\xe1\x9e\x66\xa3\x0f\x7e\x5f\xb0\x72\xd8\x83\x00\xc4\x7b\x89\x7a\xa8\xfd\xcb"] = CTInfo($description="Google 'Rocketeer' log", $operator="Google", $url="ct.googleapis.com/rocketeer/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x20\x5b\x18\xc8\x3c\xc1\x8b\xb3\x31\x08\x00\xbf\xa0\x90\x57\x2b\xb7\x47\x8c\x6f\xb5\x68\xb0\x8e\x90\x78\xe9\xa0\x73\xea\x4f\x28\x21\x2e\x9c\xc0\xf4\x16\x1b\xaa\xf9\xd5\xd7\xa9\x80\xc3\x4e\x2f\x52\x3c\x98\x01\x25\x46\x24\x25\x28\x23\x77\x2d\x05\xc2\x40\x7a"), ["\xee\x4b\xbd\xb7\x75\xce\x60\xba\xe1\x42\x69\x1f\xab\xe1\x9e\x66\xa3\x0f\x7e\x5f\xb0\x72\xd8\x83\x00\xc4\x7b\x89\x7a\xa8\xfd\xcb"] = CTInfo($description="Google 'Rocketeer' log", $operator="Google", $url="ct.googleapis.com/rocketeer/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x20\x5b\x18\xc8\x3c\xc1\x8b\xb3\x31\x08\x00\xbf\xa0\x90\x57\x2b\xb7\x47\x8c\x6f\xb5\x68\xb0\x8e\x90\x78\xe9\xa0\x73\xea\x4f\x28\x21\x2e\x9c\xc0\xf4\x16\x1b\xaa\xf9\xd5\xd7\xa9\x80\xc3\x4e\x2f\x52\x3c\x98\x01\x25\x46\x24\x25\x28\x23\x77\x2d\x05\xc2\x40\x7a"),
["\xbb\xd9\xdf\xbc\x1f\x8a\x71\xb5\x93\x94\x23\x97\xaa\x92\x7b\x47\x38\x57\x95\x0a\xab\x52\xe8\x1a\x90\x96\x64\x36\x8e\x1e\xd1\x85"] = CTInfo($description="Google 'Skydiver' log", $operator="Google", $url="ct.googleapis.com/skydiver/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x12\x6c\x86\x0e\xf6\x17\xb1\x12\x6c\x37\x25\xd2\xad\x87\x3d\x0e\x31\xec\x21\xad\xb1\xcd\xbe\x14\x47\xb6\x71\x56\x85\x7a\x9a\xb7\x3d\x89\x90\x7b\xc6\x32\x3a\xf8\xda\xce\x8b\x01\xfe\x3f\xfc\x71\x91\x19\x8e\x14\x6e\x89\x7a\x5d\xb4\xab\x7e\xe1\x4e\x1e\x7c\xac"), ["\xbb\xd9\xdf\xbc\x1f\x8a\x71\xb5\x93\x94\x23\x97\xaa\x92\x7b\x47\x38\x57\x95\x0a\xab\x52\xe8\x1a\x90\x96\x64\x36\x8e\x1e\xd1\x85"] = CTInfo($description="Google 'Skydiver' log", $operator="Google", $url="ct.googleapis.com/skydiver/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x12\x6c\x86\x0e\xf6\x17\xb1\x12\x6c\x37\x25\xd2\xad\x87\x3d\x0e\x31\xec\x21\xad\xb1\xcd\xbe\x14\x47\xb6\x71\x56\x85\x7a\x9a\xb7\x3d\x89\x90\x7b\xc6\x32\x3a\xf8\xda\xce\x8b\x01\xfe\x3f\xfc\x71\x91\x19\x8e\x14\x6e\x89\x7a\x5d\xb4\xab\x7e\xe1\x4e\x1e\x7c\xac"),
["\xa8\x99\xd8\x78\x0c\x92\x90\xaa\xf4\x62\xf3\x18\x80\xcc\xfb\xd5\x24\x51\xe9\x70\xd0\xfb\xf5\x91\xef\x75\xb0\xd9\x9b\x64\x56\x81"] = CTInfo($description="Google 'Submariner' log", $operator="Google", $url="ct.googleapis.com/submariner/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x39\xf8\x9f\x20\x62\xd4\x57\x55\x68\xa2\xef\x49\x2d\xf0\x39\x2d\x9a\xde\x44\xb4\x94\x30\xe0\x9e\x7a\x27\x3c\xab\x70\xf0\xd1\xfa\x51\x90\x63\x16\x57\x41\xad\xab\x6d\x1f\x80\x74\x30\x79\x02\x5e\x2d\x59\x84\x07\x24\x23\xf6\x9f\x35\xb8\x85\xb8\x42\x45\xa4\x4f"),
["\x1d\x02\x4b\x8e\xb1\x49\x8b\x34\x4d\xfd\x87\xea\x3e\xfc\x09\x96\xf7\x50\x6f\x23\x5d\x1d\x49\x70\x61\xa4\x77\x3c\x43\x9c\x25\xfb"] = CTInfo($description="Google 'Daedalus' log", $operator="Google", $url="ct.googleapis.com/daedalus/", $maximum_merge_delay=604800, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x6e\x0c\x1c\xba\xee\x2b\x6a\x41\x85\x60\x1d\x7b\x7e\xab\x08\x2c\xfc\x0c\x0a\xa5\x08\xb3\x3e\xd5\x70\x24\xd1\x6d\x1d\x2d\xb6\xb7\xf3\x8b\x36\xdc\x23\x4d\x95\x63\x12\xbb\xe4\x86\x8d\xcc\xe9\xd1\xee\xa1\x40\xa2\xdf\x0b\xa3\x06\x0a\x30\xca\x8d\xac\xa4\x29\x56"),
["\xb0\xcc\x83\xe5\xa5\xf9\x7d\x6b\xaf\x7c\x09\xcc\x28\x49\x04\x87\x2a\xc7\xe8\x8b\x13\x2c\x63\x50\xb7\xc6\xfd\x26\xe1\x6c\x6c\x77"] = CTInfo($description="Google 'Testtube' log", $operator="Google", $url="ct.googleapis.com/testtube/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\xc3\xc8\xbc\x4b\xba\xa2\x18\x4b\x3d\x35\x7b\xf4\x64\x91\x61\xea\xeb\x8e\x99\x1d\x90\xed\xd3\xe9\xaf\x39\x3d\x5c\xd3\x46\x91\x45\xe3\xce\xac\x76\x48\x3b\xd1\x7e\x2c\x0a\x63\x00\x65\x8d\xf5\xae\x8e\x8c\xc7\x11\x25\x4f\x43\x2c\x9d\x19\xa1\xe1\x91\xa4\xb3\xfe"),
["\xc3\xbf\x03\xa7\xe1\xca\x88\x41\xc6\x07\xba\xe3\xff\x42\x70\xfc\xa5\xec\x45\xb1\x86\xeb\xbe\x4e\x2c\xf3\xfc\x77\x86\x30\xf5\xf6"] = CTInfo($description="Google 'Crucible' log", $operator="Google", $url="ct.googleapis.com/logs/crucible/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x28\x04\xe5\xd8\x1d\xd2\x01\xbc\x72\xcc\x63\x9f\x35\x10\x7e\x03\x2b\x4d\x4c\x6b\xdd\x17\xf1\x45\x63\xa1\xf3\x59\xbf\xbf\x1c\xf1\x38\x94\x9d\xfb\xbf\x1d\xa7\x12\x6f\x7d\x29\x85\x32\xf5\x2a\x0d\xcc\x5e\x55\xc9\x3c\x02\x40\x6e\x67\x2f\xf7\x39\x43\xbe\xf2\x41"),
["\x52\xeb\x4b\x22\x5e\xc8\x96\x97\x48\x50\x67\x5f\x23\xe4\x3b\xc1\xd0\x21\xe3\x21\x4c\xe5\x2e\xcd\x5f\xa8\x7c\x20\x3c\xdf\xca\x03"] = CTInfo($description="Google 'Solera2018' log", $operator="Google", $url="ct.googleapis.com/logs/solera2018/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x12\xe1\x6a\x9f\x97\x32\xd6\x70\x02\x01\x19\x56\x21\x48\xde\x25\xa4\x43\x2a\x5d\x26\x71\xff\x60\xbc\x56\x57\xa4\xf8\x47\xb3\x2c\xa4\x8b\x35\xef\x50\xb1\x79\x19\x93\x46\x7e\xe7\x16\x23\x25\x1c\x70\x14\x5f\x99\x82\x59\x4d\x3a\xd7\xab\x0d\x26\x56\xdb\x3b\x84"),
["\x0b\x76\x0e\x9a\x8b\x9a\x68\x2f\x88\x98\x5b\x15\xe9\x47\x50\x1a\x56\x44\x6b\xba\x88\x30\x78\x5c\x38\x42\x99\x43\x86\x45\x0c\x00"] = CTInfo($description="Google 'Solera2019' log", $operator="Google", $url="ct.googleapis.com/logs/solera2019/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x25\x4c\x06\x8a\x75\xd4\x59\x53\x5a\x06\x22\xb6\x56\x5f\xeb\x77\x23\x24\xc4\xa6\x96\x24\x74\x7c\x76\x3f\x72\x0f\x90\x25\x64\x4b\x44\x6d\xfb\xc0\x31\x04\x3c\xa3\xb0\xd0\xc9\x75\x66\xed\x35\xfe\x78\x00\x3d\xc0\xbd\x95\xb6\xde\x83\xa6\x83\x04\x2f\x4a\xbf\xaf"),
["\x1f\xc7\x2c\xe5\xa1\xb7\x99\xf4\x00\xc3\x59\xbf\xf9\x6c\xa3\x91\x35\x48\xe8\x64\x42\x20\x61\x09\x52\xe9\xba\x17\x74\xf7\xba\xc7"] = CTInfo($description="Google 'Solera2020' log", $operator="Google", $url="ct.googleapis.com/logs/solera2020/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x88\xa7\xd6\xb6\xea\x16\x08\xf3\x04\xcd\x22\xb2\x4a\x33\x23\x5e\x9a\x37\xf1\x63\x9d\x66\xbe\x98\xab\x45\x98\x6b\x62\x50\x3a\xfd\x6e\x54\xcc\x64\xa8\x7c\xb0\x7f\xd1\xb3\xd6\x41\x9e\x44\xba\xbf\x47\x3d\xed\x55\x5b\xd7\x82\xa6\xf8\x8d\x0d\x54\xa8\xa5\x4a\x9f"),
["\xa3\xc9\x98\x45\xe8\x0a\xb7\xce\x00\x15\x7b\x37\x42\xdf\x02\x07\xdd\x27\x2b\x2b\x60\x2e\xcf\x98\xee\x2c\x12\xdb\x9c\x5a\xe7\xe7"] = CTInfo($description="Google 'Solera2021' log", $operator="Google", $url="ct.googleapis.com/logs/solera2021/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\xd6\x09\x70\xc6\xa5\xec\xc3\x65\x6a\x94\x06\xc7\x49\xe5\x9b\x4e\xd8\x4c\x18\xd2\x2e\x00\x25\x67\xf0\x98\xff\x8e\xb9\xd8\xda\x23\x76\xb9\x55\x2b\x10\x4c\x0b\x8f\x95\x54\x09\xbf\x96\x17\x65\xd8\xe3\x8f\xa6\x7d\x45\x58\x63\xb4\x7f\x77\xc4\xc8\x67\x8a\x25\x9f"),
["\x69\x7a\xaf\xca\x1a\x6b\x53\x6f\xae\x21\x20\x50\x46\xde\xba\xd7\xe0\xea\xea\x13\xd2\x43\x2e\x6e\x9d\x8f\xb3\x79\xf2\xb9\xaa\xf3"] = CTInfo($description="Google 'Solera2022' log", $operator="Google", $url="ct.googleapis.com/logs/solera2022/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x15\x68\xfa\x51\x00\xf1\xcc\x75\xa6\x83\x34\x2d\x41\x0e\xd1\x10\x30\xb4\x9f\x19\xd4\xf6\x6a\x4e\x98\x0d\x25\xbf\x9b\x6b\x03\x4b\x7b\x21\x1c\xd2\x92\x1e\x03\x3b\x39\xcf\x7b\xe9\xe4\xc6\x66\x82\xf2\x24\xb5\x71\xaa\x42\xb4\xa8\xf2\x62\x15\x0d\x46\xbb\xd6\xa8"),
["\xf9\x7e\x97\xb8\xd3\x3e\xf7\xa1\x59\x02\xa5\x3a\x19\xe1\x79\x90\xe5\xdc\x40\x6a\x03\x18\x25\xba\xad\x93\xe9\x8f\x9b\x9c\x69\xcb"] = CTInfo($description="Google 'Solera2023' log", $operator="Google", $url="ct.googleapis.com/logs/solera2023/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x2b\xd6\x39\xe8\x83\xfa\x0c\x64\x32\xd9\xdf\x66\xa1\x81\x89\x0a\x16\x4f\xa2\x4b\x57\xa1\x8c\x1a\x1b\x43\x01\x37\xfe\x17\xe4\xc4\x85\x98\x16\x98\x25\xf3\x66\xde\x60\xb0\xcc\xb5\x5e\x7e\x48\xe1\xdb\x0c\xfc\x43\xaa\xb6\x4b\xbe\x61\x4b\xf3\x9e\x1c\x68\x99\x52"),
["\x1f\xbc\x36\xe0\x02\xed\xe9\x7f\x40\x19\x9e\x86\xb3\x57\x3b\x8a\x42\x17\xd8\x01\x87\x74\x6a\xd0\xda\x03\xa0\x60\x54\xd2\x0d\xf4"] = CTInfo($description="Cloudflare 'Nimbus2017' Log", $operator="Cloudflare", $url="ct.cloudflare.com/logs/nimbus2017/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\xd7\x9c\xa9\x07\x8d\x22\x41\xee\x93\xa0\x52\x41\xda\xf4\x80\xf0\x25\xbc\xeb\xfa\xf3\x3c\xd2\x7e\x91\xd8\x3f\x2c\xda\x51\xbd\xc8\xee\x2a\x72\xe3\xff\x18\x56\xe4\x3a\x22\x0f\x22\x3c\xc6\xd5\x30\xb3\x9b\x68\x2e\xab\x56\xc2\x41\x5f\xd6\x64\x57\x14\xb1\x5a\xaf"),
["\xdb\x74\xaf\xee\xcb\x29\xec\xb1\xfe\xca\x3e\x71\x6d\x2c\xe5\xb9\xaa\xbb\x36\xf7\x84\x71\x83\xc7\x5d\x9d\x4f\x37\xb6\x1f\xbf\x64"] = CTInfo($description="Cloudflare 'Nimbus2018' Log", $operator="Cloudflare", $url="ct.cloudflare.com/logs/nimbus2018/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x02\xc5\x69\x5a\xfa\xc7\xdc\xa7\xb4\x55\x16\x8c\x83\xd6\x50\xa1\x08\xdb\xe6\x0f\xf1\x87\x5c\xf7\x0c\x36\xba\x22\xec\x58\xe4\x3c\x8f\xb2\x4e\x9b\xae\x5b\xeb\x50\xd5\xd9\xce\x82\x20\xd0\x37\x2f\x16\x20\x27\xda\x47\x7a\xc6\x6b\xb8\x39\xb9\x39\x5c\x0f\xe7\x46"),
["\x74\x7e\xda\x83\x31\xad\x33\x10\x91\x21\x9c\xce\x25\x4f\x42\x70\xc2\xbf\xfd\x5e\x42\x20\x08\xc6\x37\x35\x79\xe6\x10\x7b\xcc\x56"] = CTInfo($description="Cloudflare 'Nimbus2019' Log", $operator="Cloudflare", $url="ct.cloudflare.com/logs/nimbus2019/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x91\x91\xf3\xd6\xfe\x6b\xf1\xaf\x4b\x99\x74\x8c\x7a\x06\x19\x02\x0e\x14\x5b\xe5\x20\xe7\xa1\xad\x35\xf2\x53\x0c\xd1\x59\xba\xe6\xc4\x25\x88\x16\x7f\x81\x5c\x0b\x90\xfe\x66\x46\x30\xb6\xd5\xd3\x0d\x2a\x38\x3a\x46\xa7\x1b\xd6\xf7\x00\x8e\x2c\xc0\x84\x36\xf2"),
["\x5e\xa7\x73\xf9\xdf\x56\xc0\xe7\xb5\x36\x48\x7d\xd0\x49\xe0\x32\x7a\x91\x9a\x0c\x84\xa1\x12\x12\x84\x18\x75\x96\x81\x71\x45\x58"] = CTInfo($description="Cloudflare 'Nimbus2020' Log", $operator="Cloudflare", $url="ct.cloudflare.com/logs/nimbus2020/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\xd3\x51\x00\x87\x1e\x28\xd3\x33\xd0\xad\x74\xdc\x62\x38\x02\xb7\x83\x15\x16\xc4\xf4\x3f\x08\xf3\x6f\x54\x70\xac\xcd\x25\x85\x60\xe5\xc4\x06\x0f\x3f\xaf\xe0\xc8\xc0\x97\x36\x43\xa7\xff\xb2\x85\xb2\x32\xfb\xaf\x09\x3b\xf2\xd1\xcc\xa5\x8f\x2b\x5e\x7f\x00\x62"),
["\x44\x94\x65\x2e\xb0\xee\xce\xaf\xc4\x40\x07\xd8\xa8\xfe\x28\xc0\xda\xe6\x82\xbe\xd8\xcb\x31\xb5\x3f\xd3\x33\x96\xb5\xb6\x81\xa8"] = CTInfo($description="Cloudflare 'Nimbus2021' Log", $operator="Cloudflare", $url="ct.cloudflare.com/logs/nimbus2021/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\xc6\x9a\x27\xee\x2a\x6c\xa9\xe8\x48\x79\x4d\x5b\x9a\x9a\x20\xf5\x31\x68\xe0\xf9\x3c\xfb\xda\x0d\xf0\xe6\x07\x97\x54\x36\x24\x65\x57\x9e\x45\x45\x9e\xeb\xaf\x3e\x04\xa8\xd8\x4a\x7e\xea\xf2\xdf\x7c\xd2\xdc\x98\x46\xf1\x3a\xe7\x33\xd3\x7b\x05\x89\xe9\x9a\xb6"), ["\x44\x94\x65\x2e\xb0\xee\xce\xaf\xc4\x40\x07\xd8\xa8\xfe\x28\xc0\xda\xe6\x82\xbe\xd8\xcb\x31\xb5\x3f\xd3\x33\x96\xb5\xb6\x81\xa8"] = CTInfo($description="Cloudflare 'Nimbus2021' Log", $operator="Cloudflare", $url="ct.cloudflare.com/logs/nimbus2021/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\xc6\x9a\x27\xee\x2a\x6c\xa9\xe8\x48\x79\x4d\x5b\x9a\x9a\x20\xf5\x31\x68\xe0\xf9\x3c\xfb\xda\x0d\xf0\xe6\x07\x97\x54\x36\x24\x65\x57\x9e\x45\x45\x9e\xeb\xaf\x3e\x04\xa8\xd8\x4a\x7e\xea\xf2\xdf\x7c\xd2\xdc\x98\x46\xf1\x3a\xe7\x33\xd3\x7b\x05\x89\xe9\x9a\xb6"),
["\x41\xc8\xca\xb1\xdf\x22\x46\x4a\x10\xc6\xa1\x3a\x09\x42\x87\x5e\x4e\x31\x8b\x1b\x03\xeb\xeb\x4b\xc7\x68\xf0\x90\x62\x96\x06\xf6"] = CTInfo($description="Cloudflare 'Nimbus2022' Log", $operator="Cloudflare", $url="ct.cloudflare.com/logs/nimbus2022/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x48\xb2\x47\x4e\x50\x32\x72\x62\x4a\x0d\x0c\x48\xbf\xad\x29\x64\x6f\x20\xdf\x79\x52\x63\x16\x29\x0a\x2e\x60\xb5\xe2\x3a\x1c\xb7\xaf\x59\xb1\x55\x09\xdb\x59\xc7\xe9\xbd\x6f\xed\x0b\xaf\x05\x96\x97\xff\x3b\x9a\x43\x4d\xeb\x11\x34\x33\x8a\xe7\xac\x83\xc0\xff"), ["\x41\xc8\xca\xb1\xdf\x22\x46\x4a\x10\xc6\xa1\x3a\x09\x42\x87\x5e\x4e\x31\x8b\x1b\x03\xeb\xeb\x4b\xc7\x68\xf0\x90\x62\x96\x06\xf6"] = CTInfo($description="Cloudflare 'Nimbus2022' Log", $operator="Cloudflare", $url="ct.cloudflare.com/logs/nimbus2022/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x48\xb2\x47\x4e\x50\x32\x72\x62\x4a\x0d\x0c\x48\xbf\xad\x29\x64\x6f\x20\xdf\x79\x52\x63\x16\x29\x0a\x2e\x60\xb5\xe2\x3a\x1c\xb7\xaf\x59\xb1\x55\x09\xdb\x59\xc7\xe9\xbd\x6f\xed\x0b\xaf\x05\x96\x97\xff\x3b\x9a\x43\x4d\xeb\x11\x34\x33\x8a\xe7\xac\x83\xc0\xff"),
["\x7a\x32\x8c\x54\xd8\xb7\x2d\xb6\x20\xea\x38\xe0\x52\x1e\xe9\x84\x16\x70\x32\x13\x85\x4d\x3b\xd2\x2b\xc1\x3a\x57\xa3\x52\xeb\x52"] = CTInfo($description="Cloudflare 'Nimbus2023' Log", $operator="Cloudflare", $url="ct.cloudflare.com/logs/nimbus2023/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x8b\xff\x2d\x92\x18\xcb\x46\x9d\x12\x5e\xb9\x59\x75\x3c\xcd\x91\x37\x7a\x1e\xa9\x9c\x99\x78\x83\x27\x3d\xdf\x01\xd5\x8b\x80\xe8\x63\x9a\xfe\x26\xa2\x1b\xd1\x87\x05\xee\x97\xd6\xe0\x5b\x43\x83\x81\x1c\x02\xf5\x41\x80\x80\x7f\xef\xa4\x61\xcf\xbc\x84\xb5\xa8"), ["\x7a\x32\x8c\x54\xd8\xb7\x2d\xb6\x20\xea\x38\xe0\x52\x1e\xe9\x84\x16\x70\x32\x13\x85\x4d\x3b\xd2\x2b\xc1\x3a\x57\xa3\x52\xeb\x52"] = CTInfo($description="Cloudflare 'Nimbus2023' Log", $operator="Cloudflare", $url="ct.cloudflare.com/logs/nimbus2023/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x8b\xff\x2d\x92\x18\xcb\x46\x9d\x12\x5e\xb9\x59\x75\x3c\xcd\x91\x37\x7a\x1e\xa9\x9c\x99\x78\x83\x27\x3d\xdf\x01\xd5\x8b\x80\xe8\x63\x9a\xfe\x26\xa2\x1b\xd1\x87\x05\xee\x97\xd6\xe0\x5b\x43\x83\x81\x1c\x02\xf5\x41\x80\x80\x7f\xef\xa4\x61\xcf\xbc\x84\xb5\xa8"),
["\x56\x14\x06\x9a\x2f\xd7\xc2\xec\xd3\xf5\xe1\xbd\x44\xb2\x3e\xc7\x46\x76\xb9\xbc\x99\x11\x5c\xc0\xef\x94\x98\x55\xd6\x89\xd0\xdd"] = CTInfo($description="DigiCert Log Server", $operator="DigiCert", $url="ct1.digicert-ct.com/log/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x02\x46\xc5\xbe\x1b\xbb\x82\x40\x16\xe8\xc1\xd2\xac\x19\x69\x13\x59\xf8\xf8\x70\x85\x46\x40\xb9\x38\xb0\x23\x82\xa8\x64\x4c\x7f\xbf\xbb\x34\x9f\x4a\x5f\x28\x8a\xcf\x19\xc4\x00\xf6\x36\x06\x93\x65\xed\x4c\xf5\xa9\x21\x62\x5a\xd8\x91\xeb\x38\x24\x40\xac\xe8"), ["\x56\x14\x06\x9a\x2f\xd7\xc2\xec\xd3\xf5\xe1\xbd\x44\xb2\x3e\xc7\x46\x76\xb9\xbc\x99\x11\x5c\xc0\xef\x94\x98\x55\xd6\x89\xd0\xdd"] = CTInfo($description="DigiCert Log Server", $operator="DigiCert", $url="ct1.digicert-ct.com/log/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x02\x46\xc5\xbe\x1b\xbb\x82\x40\x16\xe8\xc1\xd2\xac\x19\x69\x13\x59\xf8\xf8\x70\x85\x46\x40\xb9\x38\xb0\x23\x82\xa8\x64\x4c\x7f\xbf\xbb\x34\x9f\x4a\x5f\x28\x8a\xcf\x19\xc4\x00\xf6\x36\x06\x93\x65\xed\x4c\xf5\xa9\x21\x62\x5a\xd8\x91\xeb\x38\x24\x40\xac\xe8"),
["\x87\x75\xbf\xe7\x59\x7c\xf8\x8c\x43\x99\x5f\xbd\xf3\x6e\xff\x56\x8d\x47\x56\x36\xff\x4a\xb5\x60\xc1\xb4\xea\xff\x5e\xa0\x83\x0f"] = CTInfo($description="DigiCert Log Server 2", $operator="DigiCert", $url="ct2.digicert-ct.com/log/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\xcc\x5d\x39\x2f\x66\xb8\x4c\x7f\xc1\x2e\x03\xa1\x34\xa3\xe8\x8a\x86\x02\xae\x4a\x11\xc6\xf7\x26\x6a\x37\x9b\xf0\x38\xf8\x5d\x09\x8d\x63\xe8\x31\x6b\x86\x66\xcf\x79\xb3\x25\x3c\x1e\xdf\x78\xb4\xa8\xc5\x69\xfa\xb7\xf0\x82\x79\x62\x43\xf6\xcc\xfe\x81\x66\x84"), ["\x87\x75\xbf\xe7\x59\x7c\xf8\x8c\x43\x99\x5f\xbd\xf3\x6e\xff\x56\x8d\x47\x56\x36\xff\x4a\xb5\x60\xc1\xb4\xea\xff\x5e\xa0\x83\x0f"] = CTInfo($description="DigiCert Log Server 2", $operator="DigiCert", $url="ct2.digicert-ct.com/log/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\xcc\x5d\x39\x2f\x66\xb8\x4c\x7f\xc1\x2e\x03\xa1\x34\xa3\xe8\x8a\x86\x02\xae\x4a\x11\xc6\xf7\x26\x6a\x37\x9b\xf0\x38\xf8\x5d\x09\x8d\x63\xe8\x31\x6b\x86\x66\xcf\x79\xb3\x25\x3c\x1e\xdf\x78\xb4\xa8\xc5\x69\xfa\xb7\xf0\x82\x79\x62\x43\xf6\xcc\xfe\x81\x66\x84"),
["\xc1\x16\x4a\xe0\xa7\x72\xd2\xd4\x39\x2d\xc8\x0a\xc1\x07\x70\xd4\xf0\xc4\x9b\xde\x99\x1a\x48\x40\xc1\xfa\x07\x51\x64\xf6\x33\x60"] = CTInfo($description="DigiCert Yeti2018 Log", $operator="DigiCert", $url="yeti2018.ct.digicert.com/log/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x49\x89\x4a\x14\x32\xcb\x16\x60\x3d\x25\x27\x1a\x89\xa3\x67\xaa\x55\x3c\xa1\x60\xf2\xb7\x12\x18\x31\xfb\x30\x1f\x2f\x44\xb2\x0d\x1a\x89\x7f\x96\x9c\xff\xf2\x8f\x83\xb4\x56\x21\x07\xb4\xbc\x1b\x98\xe4\x1e\x49\x60\x46\x90\x8b\xbd\x60\xaf\x42\x2d\xe7\xab\xfa"),
["\xe2\x69\x4b\xae\x26\xe8\xe9\x40\x09\xe8\x86\x1b\xb6\x3b\x83\xd4\x3e\xe7\xfe\x74\x88\xfb\xa4\x8f\x28\x93\x01\x9d\xdd\xf1\xdb\xfe"] = CTInfo($description="DigiCert Yeti2019 Log", $operator="DigiCert", $url="yeti2019.ct.digicert.com/log/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x91\x97\x7f\xa3\x0f\x17\xf8\x54\x95\x58\x05\x52\x7f\xcc\x73\x90\x5a\x21\x70\xfa\x61\xff\x1e\xa9\x4b\x52\x47\x87\xb8\x35\xc2\x70\x99\xe7\x2f\xfc\x1e\x4e\xa3\xcc\x9c\x6c\xea\xdd\xd8\x30\x05\xb3\xd8\x23\xdd\xe1\x59\x02\x77\x1c\x0a\x7b\x11\xa1\x70\x5c\x43\xf4"),
["\xf0\x95\xa4\x59\xf2\x00\xd1\x82\x40\x10\x2d\x2f\x93\x88\x8e\xad\x4b\xfe\x1d\x47\xe3\x99\xe1\xd0\x34\xa6\xb0\xa8\xaa\x8e\xb2\x73"] = CTInfo($description="DigiCert Yeti2020 Log", $operator="DigiCert", $url="yeti2020.ct.digicert.com/log/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x51\x10\x06\xf9\x9a\x34\x69\xcd\xe7\xdf\xb8\x9f\x64\xa5\x21\x04\x51\x15\xea\x37\xdc\x0b\x31\x88\x47\x3d\xed\xb2\xaf\x02\x6b\xd0\x4f\xff\x95\xd4\x1f\x2e\x99\x8a\xab\x0f\x68\x01\x1b\x54\xcd\x2e\x23\x74\xe6\xf5\x4d\xb8\x45\x50\x47\x47\xd2\x71\x0c\x49\x4f\x9a"),
["\x5c\xdc\x43\x92\xfe\xe6\xab\x45\x44\xb1\x5e\x9a\xd4\x56\xe6\x10\x37\xfb\xd5\xfa\x47\xdc\xa1\x73\x94\xb2\x5e\xe6\xf6\xc7\x0e\xca"] = CTInfo($description="DigiCert Yeti2021 Log", $operator="DigiCert", $url="yeti2021.ct.digicert.com/log/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\xe8\x9e\x04\x6d\xca\x48\x02\x5d\x7e\x02\x44\x91\xb1\xb8\x68\x63\x9a\x11\x4e\x3d\xd5\xa0\x57\xda\x7f\x50\xe5\x42\x47\xe2\xed\x16\xde\xfc\x77\x23\x7d\x5b\x6b\xc0\xdf\x23\x68\x2f\xad\x40\x31\xa3\x17\xe7\x6a\xbc\xa8\x56\x24\x04\x3a\x43\xa7\xaf\xea\xaf\x4c\x7b"), ["\x5c\xdc\x43\x92\xfe\xe6\xab\x45\x44\xb1\x5e\x9a\xd4\x56\xe6\x10\x37\xfb\xd5\xfa\x47\xdc\xa1\x73\x94\xb2\x5e\xe6\xf6\xc7\x0e\xca"] = CTInfo($description="DigiCert Yeti2021 Log", $operator="DigiCert", $url="yeti2021.ct.digicert.com/log/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\xe8\x9e\x04\x6d\xca\x48\x02\x5d\x7e\x02\x44\x91\xb1\xb8\x68\x63\x9a\x11\x4e\x3d\xd5\xa0\x57\xda\x7f\x50\xe5\x42\x47\xe2\xed\x16\xde\xfc\x77\x23\x7d\x5b\x6b\xc0\xdf\x23\x68\x2f\xad\x40\x31\xa3\x17\xe7\x6a\xbc\xa8\x56\x24\x04\x3a\x43\xa7\xaf\xea\xaf\x4c\x7b"),
["\x22\x45\x45\x07\x59\x55\x24\x56\x96\x3f\xa1\x2f\xf1\xf7\x6d\x86\xe0\x23\x26\x63\xad\xc0\x4b\x7f\x5d\xc6\x83\x5c\x6e\xe2\x0f\x02"] = CTInfo($description="DigiCert Yeti2022 Log", $operator="DigiCert", $url="yeti2022.ct.digicert.com/log/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x9f\xf8\xd8\x1d\xde\xfb\x5b\x51\xb5\xfb\x5d\xf5\xb5\xde\x66\x11\xb0\x9d\x5f\xfd\x6f\xfc\xa8\x98\x5b\x98\x4f\x2d\xc3\x91\x3a\xfb\xfe\xc4\x0f\x0d\xc3\x60\x43\x8c\x1e\xf2\xf9\x11\xb2\xba\xd0\xf6\xbc\xa5\xd2\xb6\x9f\xf9\x5c\x87\xa2\x7d\xfc\xd4\x7d\xd6\x13\x26"), ["\x22\x45\x45\x07\x59\x55\x24\x56\x96\x3f\xa1\x2f\xf1\xf7\x6d\x86\xe0\x23\x26\x63\xad\xc0\x4b\x7f\x5d\xc6\x83\x5c\x6e\xe2\x0f\x02"] = CTInfo($description="DigiCert Yeti2022 Log", $operator="DigiCert", $url="yeti2022.ct.digicert.com/log/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x9f\xf8\xd8\x1d\xde\xfb\x5b\x51\xb5\xfb\x5d\xf5\xb5\xde\x66\x11\xb0\x9d\x5f\xfd\x6f\xfc\xa8\x98\x5b\x98\x4f\x2d\xc3\x91\x3a\xfb\xfe\xc4\x0f\x0d\xc3\x60\x43\x8c\x1e\xf2\xf9\x11\xb2\xba\xd0\xf6\xbc\xa5\xd2\xb6\x9f\xf9\x5c\x87\xa2\x7d\xfc\xd4\x7d\xd6\x13\x26"),
["\x35\xcf\x19\x1b\xbf\xb1\x6c\x57\xbf\x0f\xad\x4c\x6d\x42\xcb\xbb\xb6\x27\x20\x26\x51\xea\x3f\xe1\x2a\xef\xa8\x03\xc3\x3b\xd6\x4c"] = CTInfo($description="DigiCert Yeti2023 Log", $operator="DigiCert", $url="yeti2023.ct.digicert.com/log/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x7d\x0d\x03\xb1\xd5\x98\x8a\xdc\xf0\x15\x3b\xc6\xdc\x5e\x0d\x6e\x3f\x0d\xbf\x95\xc8\x55\x8c\xd0\xa6\x4c\x96\xb1\x4e\x27\xb9\x26\x25\x99\xcc\x2b\x02\x9e\xa6\xd3\xdd\x9f\xb1\xd5\xc4\xc3\xac\x35\x04\x07\x87\x97\x36\xaa\xad\x28\x0d\x7f\x2b\xd9\x68\x9f\x72\xd1"), ["\x35\xcf\x19\x1b\xbf\xb1\x6c\x57\xbf\x0f\xad\x4c\x6d\x42\xcb\xbb\xb6\x27\x20\x26\x51\xea\x3f\xe1\x2a\xef\xa8\x03\xc3\x3b\xd6\x4c"] = CTInfo($description="DigiCert Yeti2023 Log", $operator="DigiCert", $url="yeti2023.ct.digicert.com/log/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x7d\x0d\x03\xb1\xd5\x98\x8a\xdc\xf0\x15\x3b\xc6\xdc\x5e\x0d\x6e\x3f\x0d\xbf\x95\xc8\x55\x8c\xd0\xa6\x4c\x96\xb1\x4e\x27\xb9\x26\x25\x99\xcc\x2b\x02\x9e\xa6\xd3\xdd\x9f\xb1\xd5\xc4\xc3\xac\x35\x04\x07\x87\x97\x36\xaa\xad\x28\x0d\x7f\x2b\xd9\x68\x9f\x72\xd1"),
["\x6f\xf1\x41\xb5\x64\x7e\x42\x22\xf7\xef\x05\x2c\xef\xae\x7c\x21\xfd\x60\x8e\x27\xd2\xaf\x5a\x6e\x9f\x4b\x8a\x37\xd6\x63\x3e\xe5"] = CTInfo($description="DigiCert Nessie2018 Log", $operator="DigiCert", $url="nessie2018.ct.digicert.com/log/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x56\xaa\x4b\x6b\x65\xbe\x47\x3d\x57\x0d\x93\xc1\x23\x22\x89\x3b\xe2\x8a\x14\xe6\x19\x4e\x3f\x4c\xa4\x95\xa7\x65\xe1\x54\xab\x37\x39\x6a\x2b\xce\x89\x61\x15\x86\xcf\x06\xcb\x60\x25\x1f\x78\xab\x58\xf1\x63\x21\x93\xd9\x32\xcd\xc3\xbf\xb3\x3e\xd0\xb6\xcf\xc9"),
["\xfe\x44\x61\x08\xb1\xd0\x1a\xb7\x8a\x62\xcc\xfe\xab\x6a\xb2\xb2\xba\xbf\xf3\xab\xda\xd8\x0a\x4d\x8b\x30\xdf\x2d\x00\x08\x83\x0c"] = CTInfo($description="DigiCert Nessie2019 Log", $operator="DigiCert", $url="nessie2019.ct.digicert.com/log/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x5f\xed\x27\xb9\xd0\x8a\x22\x67\x7b\x40\x2b\x5e\x96\x13\x2b\x0d\x6d\x0e\x5e\x78\xb9\x44\x4d\x74\xb6\x28\x82\x95\x97\xac\x9a\xbc\x14\x93\x68\x87\x2c\x2a\x13\x1c\x75\x55\xfb\x28\x39\x0f\x89\xff\xaf\x10\x91\x57\x24\x61\x8a\x43\xe9\x54\x33\x8b\x30\xbc\x49\x68"),
["\xc6\x52\xa0\xec\x48\xce\xb3\xfc\xab\x17\x09\x92\xc4\x3a\x87\x41\x33\x09\xe8\x00\x65\xa2\x62\x52\x40\x1b\xa3\x36\x2a\x17\xc5\x65"] = CTInfo($description="DigiCert Nessie2020 Log", $operator="DigiCert", $url="nessie2020.ct.digicert.com/log/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\xe2\x11\xc8\xc8\xc5\x48\xad\x1f\x68\x4a\x18\x1b\x40\xc6\x04\x93\xc5\x97\xd6\x59\xa4\x7c\x52\x81\xe3\x8f\x06\x9f\xdd\xca\x6e\xc6\x67\x9f\x09\x63\x0c\x76\x3a\x31\x0a\x84\x9d\x67\xca\x1a\x03\x0e\xab\x48\x21\xdd\x02\xb8\xf1\xce\x59\x07\x75\x0a\x48\x81\x59\xe2"),
["\xee\xc0\x95\xee\x8d\x72\x64\x0f\x92\xe3\xc3\xb9\x1b\xc7\x12\xa3\x69\x6a\x09\x7b\x4b\x6a\x1a\x14\x38\xe6\x47\xb2\xcb\xed\xc5\xf9"] = CTInfo($description="DigiCert Nessie2021 Log", $operator="DigiCert", $url="nessie2021.ct.digicert.com/log/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\xf6\x8e\xc0\x8b\x0a\xdb\x18\x12\x17\xe8\xb9\xdc\xe3\xb2\x3a\x39\xf2\xcc\x75\x99\xd1\xcc\xaa\x0f\xe6\xed\x3b\xda\x70\x62\xea\xfa\x48\x38\x4a\x28\x92\xd4\xe2\xd6\x03\x70\x95\x13\xf3\x18\x2d\xb2\x48\x67\xee\x73\x5c\x4b\x0d\xe6\x80\xff\x04\x85\x1a\x0a\x58\x16"), ["\xee\xc0\x95\xee\x8d\x72\x64\x0f\x92\xe3\xc3\xb9\x1b\xc7\x12\xa3\x69\x6a\x09\x7b\x4b\x6a\x1a\x14\x38\xe6\x47\xb2\xcb\xed\xc5\xf9"] = CTInfo($description="DigiCert Nessie2021 Log", $operator="DigiCert", $url="nessie2021.ct.digicert.com/log/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\xf6\x8e\xc0\x8b\x0a\xdb\x18\x12\x17\xe8\xb9\xdc\xe3\xb2\x3a\x39\xf2\xcc\x75\x99\xd1\xcc\xaa\x0f\xe6\xed\x3b\xda\x70\x62\xea\xfa\x48\x38\x4a\x28\x92\xd4\xe2\xd6\x03\x70\x95\x13\xf3\x18\x2d\xb2\x48\x67\xee\x73\x5c\x4b\x0d\xe6\x80\xff\x04\x85\x1a\x0a\x58\x16"),
["\x51\xa3\xb0\xf5\xfd\x01\x79\x9c\x56\x6d\xb8\x37\x78\x8f\x0c\xa4\x7a\xcc\x1b\x27\xcb\xf7\x9e\x88\x42\x9a\x0d\xfe\xd4\x8b\x05\xe5"] = CTInfo($description="DigiCert Nessie2022 Log", $operator="DigiCert", $url="nessie2022.ct.digicert.com/log/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x27\x24\xdd\x68\x03\x28\xcb\xfe\x63\xbe\x0e\x11\x47\x4d\x7d\x17\x68\xa1\x11\x5d\x4c\x71\xc9\x41\x28\xc7\xb6\xa2\x4b\x97\xec\xc0\xaf\xfc\x2f\x3b\xbf\xe9\xf1\xb1\xfc\xf5\x01\xff\xa9\xfb\x49\x40\x0c\x63\x24\x98\xd7\x79\x2e\xa6\x55\xab\x16\xc6\xbe\x51\xd8\x71"), ["\x51\xa3\xb0\xf5\xfd\x01\x79\x9c\x56\x6d\xb8\x37\x78\x8f\x0c\xa4\x7a\xcc\x1b\x27\xcb\xf7\x9e\x88\x42\x9a\x0d\xfe\xd4\x8b\x05\xe5"] = CTInfo($description="DigiCert Nessie2022 Log", $operator="DigiCert", $url="nessie2022.ct.digicert.com/log/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x27\x24\xdd\x68\x03\x28\xcb\xfe\x63\xbe\x0e\x11\x47\x4d\x7d\x17\x68\xa1\x11\x5d\x4c\x71\xc9\x41\x28\xc7\xb6\xa2\x4b\x97\xec\xc0\xaf\xfc\x2f\x3b\xbf\xe9\xf1\xb1\xfc\xf5\x01\xff\xa9\xfb\x49\x40\x0c\x63\x24\x98\xd7\x79\x2e\xa6\x55\xab\x16\xc6\xbe\x51\xd8\x71"),
["\xb3\x73\x77\x07\xe1\x84\x50\xf8\x63\x86\xd6\x05\xa9\xdc\x11\x09\x4a\x79\x2d\xb1\x67\x0c\x0b\x87\xdc\xf0\x03\x0e\x79\x36\xa5\x9a"] = CTInfo($description="DigiCert Nessie2023 Log", $operator="DigiCert", $url="nessie2023.ct.digicert.com/log/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x11\x7b\xbc\x89\x0c\x12\x09\x14\x9f\xd8\x26\xc8\x4c\x6a\x54\xa4\x1b\x45\x56\xdf\x3e\x23\x42\x14\xd1\xdd\x42\xdf\xa2\xdf\x7b\x5f\x9f\x6f\x07\x5a\x23\x46\x79\x16\x4b\x5f\x33\x67\xc1\xa0\x8d\x5b\x5c\x17\x75\xf2\x4d\xa0\x80\xa1\x98\x1a\x07\x59\x06\x02\xca\x4e"), ["\xb3\x73\x77\x07\xe1\x84\x50\xf8\x63\x86\xd6\x05\xa9\xdc\x11\x09\x4a\x79\x2d\xb1\x67\x0c\x0b\x87\xdc\xf0\x03\x0e\x79\x36\xa5\x9a"] = CTInfo($description="DigiCert Nessie2023 Log", $operator="DigiCert", $url="nessie2023.ct.digicert.com/log/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x11\x7b\xbc\x89\x0c\x12\x09\x14\x9f\xd8\x26\xc8\x4c\x6a\x54\xa4\x1b\x45\x56\xdf\x3e\x23\x42\x14\xd1\xdd\x42\xdf\xa2\xdf\x7b\x5f\x9f\x6f\x07\x5a\x23\x46\x79\x16\x4b\x5f\x33\x67\xc1\xa0\x8d\x5b\x5c\x17\x75\xf2\x4d\xa0\x80\xa1\x98\x1a\x07\x59\x06\x02\xca\x4e"),
["\xdd\xeb\x1d\x2b\x7a\x0d\x4f\xa6\x20\x8b\x81\xad\x81\x68\x70\x7e\x2e\x8e\x9d\x01\xd5\x5c\x88\x8d\x3d\x11\xc4\xcd\xb6\xec\xbe\xcc"] = CTInfo($description="Symantec log", $operator="DigiCert", $url="ct.ws.symantec.com/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x96\xea\xac\x1c\x46\x0c\x1b\x55\xdc\x0d\xfc\xb5\x94\x27\x46\x57\x42\x70\x3a\x69\x18\xe2\xbf\x3b\xc4\xdb\xab\xa0\xf4\xb6\x6c\xc0\x53\x3f\x4d\x42\x10\x33\xf0\x58\x97\x8f\x6b\xbe\x72\xf4\x2a\xec\x1c\x42\xaa\x03\x2f\x1a\x7e\x28\x35\x76\x99\x08\x3d\x21\x14\x86"), ["\xdd\xeb\x1d\x2b\x7a\x0d\x4f\xa6\x20\x8b\x81\xad\x81\x68\x70\x7e\x2e\x8e\x9d\x01\xd5\x5c\x88\x8d\x3d\x11\xc4\xcd\xb6\xec\xbe\xcc"] = CTInfo($description="Symantec log", $operator="DigiCert", $url="ct.ws.symantec.com/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x96\xea\xac\x1c\x46\x0c\x1b\x55\xdc\x0d\xfc\xb5\x94\x27\x46\x57\x42\x70\x3a\x69\x18\xe2\xbf\x3b\xc4\xdb\xab\xa0\xf4\xb6\x6c\xc0\x53\x3f\x4d\x42\x10\x33\xf0\x58\x97\x8f\x6b\xbe\x72\xf4\x2a\xec\x1c\x42\xaa\x03\x2f\x1a\x7e\x28\x35\x76\x99\x08\x3d\x21\x14\x86"),
["\xbc\x78\xe1\xdf\xc5\xf6\x3c\x68\x46\x49\x33\x4d\xa1\x0f\xa1\x5f\x09\x79\x69\x20\x09\xc0\x81\xb4\xf3\xf6\x91\x7f\x3e\xd9\xb8\xa5"] = CTInfo($description="Symantec 'Vega' log", $operator="DigiCert", $url="vega.ws.symantec.com/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\xea\x95\x9e\x02\xff\xee\xf1\x33\x6d\x4b\x87\xbc\xcd\xfd\x19\x17\x62\xff\x94\xd3\xd0\x59\x07\x3f\x02\x2d\x1c\x90\xfe\xc8\x47\x30\x3b\xf1\xdd\x0d\xb8\x11\x0c\x5d\x1d\x86\xdd\xab\xd3\x2b\x46\x66\xfb\x6e\x65\xb7\x3b\xfd\x59\x68\xac\xdf\xa6\xf8\xce\xd2\x18\x4d"), ["\xbc\x78\xe1\xdf\xc5\xf6\x3c\x68\x46\x49\x33\x4d\xa1\x0f\xa1\x5f\x09\x79\x69\x20\x09\xc0\x81\xb4\xf3\xf6\x91\x7f\x3e\xd9\xb8\xa5"] = CTInfo($description="Symantec 'Vega' log", $operator="DigiCert", $url="vega.ws.symantec.com/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\xea\x95\x9e\x02\xff\xee\xf1\x33\x6d\x4b\x87\xbc\xcd\xfd\x19\x17\x62\xff\x94\xd3\xd0\x59\x07\x3f\x02\x2d\x1c\x90\xfe\xc8\x47\x30\x3b\xf1\xdd\x0d\xb8\x11\x0c\x5d\x1d\x86\xdd\xab\xd3\x2b\x46\x66\xfb\x6e\x65\xb7\x3b\xfd\x59\x68\xac\xdf\xa6\xf8\xce\xd2\x18\x4d"),
["\xa7\xce\x4a\x4e\x62\x07\xe0\xad\xde\xe5\xfd\xaa\x4b\x1f\x86\x76\x87\x67\xb5\xd0\x02\xa5\x5d\x47\x31\x0e\x7e\x67\x0a\x95\xea\xb2"] = CTInfo($description="Symantec Deneb", $operator="DigiCert", $url="deneb.ws.symantec.com/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x96\x82\x1e\xa3\xcd\x3a\x80\x84\x1e\x97\xb8\xb7\x07\x19\xae\x76\x1a\x0e\xf8\x55\x76\x9d\x12\x33\x4e\x91\x88\xe4\xd0\x48\x50\x5c\xc1\x9f\x6a\x72\xd6\x01\xf5\x14\xd6\xd0\x38\x6e\xe1\x32\xbc\x67\x0d\x37\xe8\xba\x22\x10\xd1\x72\x86\x79\x28\x96\xf9\x17\x1e\x98"),
["\x15\x97\x04\x88\xd7\xb9\x97\xa0\x5b\xeb\x52\x51\x2a\xde\xe8\xd2\xe8\xb4\xa3\x16\x52\x64\x12\x1a\x9f\xab\xfb\xd5\xf8\x5a\xd9\x3f"] = CTInfo($description="Symantec 'Sirius' log", $operator="DigiCert", $url="sirius.ws.symantec.com/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\xa3\x02\x64\x84\x22\xbb\x25\xec\x0d\xe3\xbc\xc2\xc9\x89\x7d\xdd\x45\xd0\xee\xe6\x15\x85\x8f\xd9\xe7\x17\x1b\x13\x80\xea\xed\xb2\x85\x37\xad\x6a\xc5\xd8\x25\x9d\xfa\xf4\xb4\xf3\x6e\x16\x28\x25\x37\xea\xa3\x37\x64\xb2\xc7\x0b\xfd\x51\xe5\xc1\x05\xf4\x0e\xb5"), ["\x15\x97\x04\x88\xd7\xb9\x97\xa0\x5b\xeb\x52\x51\x2a\xde\xe8\xd2\xe8\xb4\xa3\x16\x52\x64\x12\x1a\x9f\xab\xfb\xd5\xf8\x5a\xd9\x3f"] = CTInfo($description="Symantec 'Sirius' log", $operator="DigiCert", $url="sirius.ws.symantec.com/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\xa3\x02\x64\x84\x22\xbb\x25\xec\x0d\xe3\xbc\xc2\xc9\x89\x7d\xdd\x45\xd0\xee\xe6\x15\x85\x8f\xd9\xe7\x17\x1b\x13\x80\xea\xed\xb2\x85\x37\xad\x6a\xc5\xd8\x25\x9d\xfa\xf4\xb4\xf3\x6e\x16\x28\x25\x37\xea\xa3\x37\x64\xb2\xc7\x0b\xfd\x51\xe5\xc1\x05\xf4\x0e\xb5"),
["\xcd\xb5\x17\x9b\x7f\xc1\xc0\x46\xfe\xea\x31\x13\x6a\x3f\x8f\x00\x2e\x61\x82\xfa\xf8\x89\x6f\xec\xc8\xb2\xf5\xb5\xab\x60\x49\x00"] = CTInfo($description="Certly.IO log", $operator="Certly", $url="log.certly.io/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x0b\x23\xcb\x85\x62\x98\x61\x48\x04\x73\xeb\x54\x5d\xf3\xd0\x07\x8c\x2d\x19\x2d\x8c\x36\xf5\xeb\x8f\x01\x42\x0a\x7c\x98\x26\x27\xc1\xb5\xdd\x92\x93\xb0\xae\xf8\x9b\x3d\x0c\xd8\x4c\x4e\x1d\xf9\x15\xfb\x47\x68\x7b\xba\x66\xb7\x25\x9c\xd0\x4a\xc2\x66\xdb\x48"), ["\xcd\xb5\x17\x9b\x7f\xc1\xc0\x46\xfe\xea\x31\x13\x6a\x3f\x8f\x00\x2e\x61\x82\xfa\xf8\x89\x6f\xec\xc8\xb2\xf5\xb5\xab\x60\x49\x00"] = CTInfo($description="Certly.IO log", $operator="Certly", $url="log.certly.io/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x0b\x23\xcb\x85\x62\x98\x61\x48\x04\x73\xeb\x54\x5d\xf3\xd0\x07\x8c\x2d\x19\x2d\x8c\x36\xf5\xeb\x8f\x01\x42\x0a\x7c\x98\x26\x27\xc1\xb5\xdd\x92\x93\xb0\xae\xf8\x9b\x3d\x0c\xd8\x4c\x4e\x1d\xf9\x15\xfb\x47\x68\x7b\xba\x66\xb7\x25\x9c\xd0\x4a\xc2\x66\xdb\x48"),
["\x74\x61\xb4\xa0\x9c\xfb\x3d\x41\xd7\x51\x59\x57\x5b\x2e\x76\x49\xa4\x45\xa8\xd2\x77\x09\xb0\xcc\x56\x4a\x64\x82\xb7\xeb\x41\xa3"] = CTInfo($description="Izenpe log", $operator="Izenpe", $url="ct.izenpe.com/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x27\x64\x39\x0c\x2d\xdc\x50\x18\xf8\x21\x00\xa2\x0e\xed\x2c\xea\x3e\x75\xba\x9f\x93\x64\x09\x00\x11\xc4\x11\x17\xab\x5c\xcf\x0f\x74\xac\xb5\x97\x90\x93\x00\x5b\xb8\xeb\xf7\x27\x3d\xd9\xb2\x0a\x81\x5f\x2f\x0d\x75\x38\x94\x37\x99\x1e\xf6\x07\x76\xe0\xee\xbe"), ["\x74\x61\xb4\xa0\x9c\xfb\x3d\x41\xd7\x51\x59\x57\x5b\x2e\x76\x49\xa4\x45\xa8\xd2\x77\x09\xb0\xcc\x56\x4a\x64\x82\xb7\xeb\x41\xa3"] = CTInfo($description="Izenpe log", $operator="Izenpe", $url="ct.izenpe.com/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x27\x64\x39\x0c\x2d\xdc\x50\x18\xf8\x21\x00\xa2\x0e\xed\x2c\xea\x3e\x75\xba\x9f\x93\x64\x09\x00\x11\xc4\x11\x17\xab\x5c\xcf\x0f\x74\xac\xb5\x97\x90\x93\x00\x5b\xb8\xeb\xf7\x27\x3d\xd9\xb2\x0a\x81\x5f\x2f\x0d\x75\x38\x94\x37\x99\x1e\xf6\x07\x76\xe0\xee\xbe"),
["\x89\x41\x44\x9c\x70\x74\x2e\x06\xb9\xfc\x9c\xe7\xb1\x16\xba\x00\x24\xaa\x36\xd5\x9a\xf4\x4f\x02\x04\x40\x4f\x00\xf7\xea\x85\x66"] = CTInfo($description="Izenpe 'Argi' log", $operator="Izenpe", $url="ct.izenpe.eus/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\xd7\xc8\x0e\x23\x3e\x9e\x02\x3c\x9a\xb8\x07\x4a\x2a\x05\xff\x4a\x4b\x88\xd4\x8a\x4d\x39\xce\xf7\xc5\xf2\xb6\x37\xe9\xa3\xed\xe4\xf5\x45\x09\x0e\x67\x14\xfd\x53\x24\xd5\x3a\x94\xf2\xea\xb5\x13\xd9\x1d\x8b\x5c\xa7\xc3\xf3\x6b\xd8\x3f\x2d\x3b\x65\x72\x58\xd6"),
["\x9e\x4f\xf7\x3d\xc3\xce\x22\x0b\x69\x21\x7c\x89\x9e\x46\x80\x76\xab\xf8\xd7\x86\x36\xd5\xcc\xfc\x85\xa3\x1a\x75\x62\x8b\xa8\x8b"] = CTInfo($description="WoSign CT log #1", $operator="WoSign", $url="ct.wosign.com/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\xd7\xec\x2f\x2b\x75\x4f\x37\xbc\xa3\x43\xba\x8b\x65\x66\x3c\x7d\x6a\xe5\x0c\x2a\xa6\xc2\xe5\x26\xfe\x0c\x7d\x4e\x7c\xf0\x3a\xbc\xe2\xd3\x22\xdc\x01\xd0\x1f\x6e\x43\x9c\x5c\x6e\x83\xad\x9c\x15\xf6\xc4\x8d\x60\xb5\x1d\xbb\xa3\x62\x69\x7e\xeb\xa7\xaa\x01\x9b"),
["\x41\xb2\xdc\x2e\x89\xe6\x3c\xe4\xaf\x1b\xa7\xbb\x29\xbf\x68\xc6\xde\xe6\xf9\xf1\xcc\x04\x7e\x30\xdf\xfa\xe3\xb3\xba\x25\x92\x63"] = CTInfo($description="WoSign log", $operator="WoSign", $url="ctlog.wosign.com/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\xcc\x11\x88\x7b\x2d\x66\xcb\xae\x8f\x4d\x30\x66\x27\x19\x25\x22\x93\x21\x46\xb4\x2f\x01\xd3\xc6\xf9\x2b\xd5\xc8\xba\x73\x9b\x06\xa2\xf0\x8a\x02\x9c\xd0\x6b\x46\x18\x30\x85\xba\xe9\x24\x8b\x0e\xd1\x5b\x70\x28\x0c\x7e\xf1\x3a\x45\x7f\x5a\xf3\x82\x42\x60\x31"), ["\x41\xb2\xdc\x2e\x89\xe6\x3c\xe4\xaf\x1b\xa7\xbb\x29\xbf\x68\xc6\xde\xe6\xf9\xf1\xcc\x04\x7e\x30\xdf\xfa\xe3\xb3\xba\x25\x92\x63"] = CTInfo($description="WoSign log", $operator="WoSign", $url="ctlog.wosign.com/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\xcc\x11\x88\x7b\x2d\x66\xcb\xae\x8f\x4d\x30\x66\x27\x19\x25\x22\x93\x21\x46\xb4\x2f\x01\xd3\xc6\xf9\x2b\xd5\xc8\xba\x73\x9b\x06\xa2\xf0\x8a\x02\x9c\xd0\x6b\x46\x18\x30\x85\xba\xe9\x24\x8b\x0e\xd1\x5b\x70\x28\x0c\x7e\xf1\x3a\x45\x7f\x5a\xf3\x82\x42\x60\x31"),
["\x63\xd0\x00\x60\x26\xdd\xe1\x0b\xb0\x60\x1f\x45\x24\x46\x96\x5e\xe2\xb6\xea\x2c\xd4\xfb\xc9\x5a\xc8\x66\xa5\x50\xaf\x90\x75\xb7"] = CTInfo($description="WoSign log 2", $operator="WoSign", $url="ctlog2.wosign.com/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\xa5\x8c\xe8\x35\x2e\x8e\xe5\x6a\x75\xad\x5c\x4b\x31\x61\x29\x9d\x30\x57\x8e\x02\x13\x5f\xe9\xca\xbb\x52\xa8\x43\x05\x60\xbf\x0d\x73\x57\x77\xb2\x05\xd8\x67\xf6\xf0\x33\xc9\xf9\x44\xde\xb6\x53\x73\xaa\x0c\x55\xc2\x83\x0a\x4b\xce\x5e\x1a\xc7\x17\x1d\xb3\xcd"),
["\xc9\xcf\x89\x0a\x21\x10\x9c\x66\x6c\xc1\x7a\x3e\xd0\x65\xc9\x30\xd0\xe0\x13\x5a\x9f\xeb\xa8\x5a\xf1\x42\x10\xb8\x07\x24\x21\xaa"] = CTInfo($description="GDCA CT log #1", $operator="Wang Shengnan", $url="ct.gdca.com.cn/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\xad\x0f\x30\xad\x9e\x79\xa4\x38\x89\x26\x54\x86\xab\x41\x72\x90\x6f\xfb\xca\x17\xa6\xac\xee\xc6\x9f\x7d\x02\x05\xec\x41\xa8\xc7\x41\x9d\x32\x49\xad\xb0\x39\xbd\x3a\x87\x3e\x7c\xee\x68\x6c\x60\xd1\x47\x2a\x93\xae\xe1\x40\xf4\x0b\xc8\x35\x3c\x1d\x0f\x65\xd3"),
["\x92\x4a\x30\xf9\x09\x33\x6f\xf4\x35\xd6\x99\x3a\x10\xac\x75\xa2\xc6\x41\x72\x8e\x7f\xc2\xd6\x59\xae\x61\x88\xff\xad\x40\xce\x01"] = CTInfo($description="GDCA CT log #2", $operator="GDCA", $url="ctlog.gdca.com.cn/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x5b\x4a\xc7\x01\xb7\x74\x54\xba\x40\x9c\x43\x75\x94\x3f\xac\xef\xb3\x71\x56\xb8\xd3\xe2\x7b\xae\xa1\xb1\x3e\x53\xaa\x97\x33\xa1\x82\xbb\x5f\x5d\x1c\x0b\xfa\x85\x0d\xbc\xf7\xe5\xa0\xe0\x22\xf0\xa0\x89\xd9\x0a\x7f\x5f\x26\x94\xd3\x24\xe3\x99\x2e\xe4\x15\x8d"),
["\x71\x7e\xa7\x42\x09\x75\xbe\x84\xa2\x72\x35\x53\xf1\x77\x7c\x26\xdd\x51\xaf\x4e\x10\x21\x44\x09\x4d\x90\x19\xb4\x62\xfb\x66\x68"] = CTInfo($description="GDCA Log 1", $operator="GDCA", $url="log.gdca.com.cn/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\xcd\x51\xff\xa9\xef\xab\x82\xbf\xcc\xa3\xea\x30\x43\x4d\x08\xe9\xa7\xa0\x0d\x28\xc7\xb6\xd8\x2a\x40\x19\xa0\xfa\x10\x5d\x4d\x75\xcb\x80\x94\xff\xfb\xc2\xdd\x4a\x08\xdf\x63\xff\x25\x38\x1b\x5f\x8a\xf9\xdd\x27\x34\x25\x4c\xd4\x3d\x2d\xed\x5c\x53\xac\x17\x35"),
["\x14\x30\x8d\x90\xcc\xd0\x30\x13\x50\x05\xc0\x1c\xa5\x26\xd8\x1e\x84\xe8\x76\x24\xe3\x9b\x62\x48\xe0\x8f\x72\x4a\xea\x3b\xb4\x2a"] = CTInfo($description="GDCA Log 2", $operator="GDCA", $url="log2.gdca.com.cn/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\xc7\xac\xc2\xf3\x00\x9b\x32\xcd\xdf\xa5\x05\xa7\x48\x27\xa8\xd9\x1b\xc6\xf3\x6e\xc0\x12\xcb\x06\x90\xc6\xbe\xe5\x15\x48\xa5\x11\x74\x48\x33\xb8\x84\x5b\x27\xd8\xf8\x75\x97\xc9\x9a\xad\x20\xae\xc1\x52\xe1\xbf\x42\x48\x37\x76\xab\x4b\x36\xd4\x89\xe5\xfa\x1c"),
["\xdb\x76\xfd\xad\xac\x65\xe7\xd0\x95\x08\x88\x6e\x21\x59\xbd\x8b\x90\x35\x2f\x5f\xea\xd3\xe3\xdc\x5e\x22\xeb\x35\x0a\xcc\x7b\x98"] = CTInfo($description="Sectigo 'Dodo' CT log", $operator="Sectigo", $url="dodo.ct.comodo.com/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x2c\xf5\xc2\x31\xf5\x63\x43\x6a\x16\x4a\x0a\xde\xc2\xee\x1f\x21\x6e\x12\x7e\x1d\xe5\x72\x8f\x74\x0b\x02\x99\xd3\xad\x69\xbc\x02\x35\x79\xf9\x61\xe9\xcf\x00\x08\x4f\x74\xa4\xa3\x34\x9a\xe0\x43\x1c\x23\x7e\x8f\x41\xd5\xee\xc7\x1c\xa3\x82\x8a\x40\xfa\xaa\xe0"),
["\xac\x3b\x9a\xed\x7f\xa9\x67\x47\x57\x15\x9e\x6d\x7d\x57\x56\x72\xf9\xd9\x81\x00\x94\x1e\x9b\xde\xff\xec\xa1\x31\x3b\x75\x78\x2d"] = CTInfo($description="Venafi log", $operator="Venafi", $url="ctlog.api.venafi.com/", $maximum_merge_delay=86400, $key="\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xa2\x5a\x48\x1f\x17\x52\x95\x35\xcb\xa3\x5b\x3a\x1f\x53\x82\x76\x94\xa3\xff\x80\xf2\x1c\x37\x3c\xc0\xb1\xbd\xc1\x59\x8b\xab\x2d\x65\x93\xd7\xf3\xe0\x04\xd5\x9a\x6f\xbf\xd6\x23\x76\x36\x4f\x23\x99\xcb\x54\x28\xad\x8c\x15\x4b\x65\x59\x76\x41\x4a\x9c\xa6\xf7\xb3\x3b\x7e\xb1\xa5\x49\xa4\x17\x51\x6c\x80\xdc\x2a\x90\x50\x4b\x88\x24\xe9\xa5\x12\x32\x93\x04\x48\x90\x02\xfa\x5f\x0e\x30\x87\x8e\x55\x76\x05\xee\x2a\x4c\xce\xa3\x6a\x69\x09\x6e\x25\xad\x82\x76\x0f\x84\x92\xfa\x38\xd6\x86\x4e\x24\x8f\x9b\xb0\x72\xcb\x9e\xe2\x6b\x3f\xe1\x6d\xc9\x25\x75\x23\x88\xa1\x18\x58\x06\x23\x33\x78\xda\x00\xd0\x38\x91\x67\xd2\xa6\x7d\x27\x97\x67\x5a\xc1\xf3\x2f\x17\xe6\xea\xd2\x5b\xe8\x81\xcd\xfd\x92\x68\xe7\xf3\x06\xf0\xe9\x72\x84\xee\x01\xa5\xb1\xd8\x33\xda\xce\x83\xa5\xdb\xc7\xcf\xd6\x16\x7e\x90\x75\x18\xbf\x16\xdc\x32\x3b\x6d\x8d\xab\x82\x17\x1f\x89\x20\x8d\x1d\x9a\xe6\x4d\x23\x08\xdf\x78\x6f\xc6\x05\xbf\x5f\xae\x94\x97\xdb\x5f\x64\xd4\xee\x16\x8b\xa3\x84\x6c\x71\x2b\xf1\xab\x7f\x5d\x0d\x32\xee\x04\xe2\x90\xec\x41\x9f\xfb\x39\xc1\x02\x03\x01\x00\x01"), ["\xac\x3b\x9a\xed\x7f\xa9\x67\x47\x57\x15\x9e\x6d\x7d\x57\x56\x72\xf9\xd9\x81\x00\x94\x1e\x9b\xde\xff\xec\xa1\x31\x3b\x75\x78\x2d"] = CTInfo($description="Venafi log", $operator="Venafi", $url="ctlog.api.venafi.com/", $maximum_merge_delay=86400, $key="\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xa2\x5a\x48\x1f\x17\x52\x95\x35\xcb\xa3\x5b\x3a\x1f\x53\x82\x76\x94\xa3\xff\x80\xf2\x1c\x37\x3c\xc0\xb1\xbd\xc1\x59\x8b\xab\x2d\x65\x93\xd7\xf3\xe0\x04\xd5\x9a\x6f\xbf\xd6\x23\x76\x36\x4f\x23\x99\xcb\x54\x28\xad\x8c\x15\x4b\x65\x59\x76\x41\x4a\x9c\xa6\xf7\xb3\x3b\x7e\xb1\xa5\x49\xa4\x17\x51\x6c\x80\xdc\x2a\x90\x50\x4b\x88\x24\xe9\xa5\x12\x32\x93\x04\x48\x90\x02\xfa\x5f\x0e\x30\x87\x8e\x55\x76\x05\xee\x2a\x4c\xce\xa3\x6a\x69\x09\x6e\x25\xad\x82\x76\x0f\x84\x92\xfa\x38\xd6\x86\x4e\x24\x8f\x9b\xb0\x72\xcb\x9e\xe2\x6b\x3f\xe1\x6d\xc9\x25\x75\x23\x88\xa1\x18\x58\x06\x23\x33\x78\xda\x00\xd0\x38\x91\x67\xd2\xa6\x7d\x27\x97\x67\x5a\xc1\xf3\x2f\x17\xe6\xea\xd2\x5b\xe8\x81\xcd\xfd\x92\x68\xe7\xf3\x06\xf0\xe9\x72\x84\xee\x01\xa5\xb1\xd8\x33\xda\xce\x83\xa5\xdb\xc7\xcf\xd6\x16\x7e\x90\x75\x18\xbf\x16\xdc\x32\x3b\x6d\x8d\xab\x82\x17\x1f\x89\x20\x8d\x1d\x9a\xe6\x4d\x23\x08\xdf\x78\x6f\xc6\x05\xbf\x5f\xae\x94\x97\xdb\x5f\x64\xd4\xee\x16\x8b\xa3\x84\x6c\x71\x2b\xf1\xab\x7f\x5d\x0d\x32\xee\x04\xe2\x90\xec\x41\x9f\xfb\x39\xc1\x02\x03\x01\x00\x01"),
["\x03\x01\x9d\xf3\xfd\x85\xa6\x9a\x8e\xbd\x1f\xac\xc6\xda\x9b\xa7\x3e\x46\x97\x74\xfe\x77\xf5\x79\xfc\x5a\x08\xb8\x32\x8c\x1d\x6b"] = CTInfo($description="Venafi Gen2 CT log", $operator="Venafi", $url="ctlog-gen2.api.venafi.com/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x8e\x27\x27\x7a\xb6\x55\x09\x74\xeb\x6c\x4b\x94\x84\x65\xbc\xe4\x15\xf1\xea\x5a\xd8\x7c\x0e\x37\xce\xba\x3f\x6c\x09\xda\xe7\x29\x96\xd3\x45\x50\x6f\xde\x1e\xb4\x1c\xd2\x83\x88\xff\x29\x2f\xce\xa9\xff\xdf\x34\xde\x75\x0f\xc0\xcc\x18\x0d\x94\x2e\xfc\x37\x01"),
["\xa5\x77\xac\x9c\xed\x75\x48\xdd\x8f\x02\x5b\x67\xa2\x41\x08\x9d\xf8\x6e\x0f\x47\x6e\xc2\x03\xc2\xec\xbe\xdb\x18\x5f\x28\x26\x38"] = CTInfo($description="CNNIC CT log", $operator="CNNIC", $url="ctserver.cnnic.cn/", $maximum_merge_delay=86400, $key="\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xbf\xb5\x08\x61\x9a\x29\x32\x04\xd3\x25\x63\xe9\xd8\x85\xe1\x86\xe0\x1f\xd6\x5e\x9a\xf7\x33\x3b\x80\x1b\xe7\xb6\x3e\x5f\x2d\xa1\x66\xf6\x95\x4a\x84\xa6\x21\x56\x79\xe8\xf7\x85\xee\x5d\xe3\x7c\x12\xc0\xe0\x89\x22\x09\x22\x3e\xba\x16\x95\x06\xbd\xa8\xb9\xb1\xa9\xb2\x7a\xd6\x61\x2e\x87\x11\xb9\x78\x40\x89\x75\xdb\x0c\xdc\x90\xe0\xa4\x79\xd6\xd5\x5e\x6e\xd1\x2a\xdb\x34\xf4\x99\x3f\x65\x89\x3b\x46\xc2\x29\x2c\x15\x07\x1c\xc9\x4b\x1a\x54\xf8\x6c\x1e\xaf\x60\x27\x62\x0a\x65\xd5\x9a\xb9\x50\x36\x16\x6e\x71\xf6\x1f\x01\xf7\x12\xa7\xfc\xbf\xf6\x21\xa3\x29\x90\x86\x2d\x77\xde\xbb\x4c\xd4\xcf\xfd\xd2\xcf\x82\x2c\x4d\xd4\xf2\xc2\x2d\xac\xa9\xbe\xea\xc3\x19\x25\x43\xb2\xe5\x9a\x6c\x0d\xc5\x1c\xa5\x8b\xf7\x3f\x30\xaf\xb9\x01\x91\xb7\x69\x12\x12\xe5\x83\x61\xfe\x34\x00\xbe\xf6\x71\x8a\xc7\xeb\x50\x92\xe8\x59\xfe\x15\x91\xeb\x96\x97\xf8\x23\x54\x3f\x2d\x8e\x07\xdf\xee\xda\xb3\x4f\xc8\x3c\x9d\x6f\xdf\x3c\x2c\x43\x57\xa1\x47\x0c\x91\x04\xf4\x75\x4d\xda\x89\x81\xa4\x14\x06\x34\xb9\x98\xc3\xda\xf1\xfd\xed\x33\x36\xd3\x16\x2d\x35\x02\x03\x01\x00\x01"), ["\xa5\x77\xac\x9c\xed\x75\x48\xdd\x8f\x02\x5b\x67\xa2\x41\x08\x9d\xf8\x6e\x0f\x47\x6e\xc2\x03\xc2\xec\xbe\xdb\x18\x5f\x28\x26\x38"] = CTInfo($description="CNNIC CT log", $operator="CNNIC", $url="ctserver.cnnic.cn/", $maximum_merge_delay=86400, $key="\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xbf\xb5\x08\x61\x9a\x29\x32\x04\xd3\x25\x63\xe9\xd8\x85\xe1\x86\xe0\x1f\xd6\x5e\x9a\xf7\x33\x3b\x80\x1b\xe7\xb6\x3e\x5f\x2d\xa1\x66\xf6\x95\x4a\x84\xa6\x21\x56\x79\xe8\xf7\x85\xee\x5d\xe3\x7c\x12\xc0\xe0\x89\x22\x09\x22\x3e\xba\x16\x95\x06\xbd\xa8\xb9\xb1\xa9\xb2\x7a\xd6\x61\x2e\x87\x11\xb9\x78\x40\x89\x75\xdb\x0c\xdc\x90\xe0\xa4\x79\xd6\xd5\x5e\x6e\xd1\x2a\xdb\x34\xf4\x99\x3f\x65\x89\x3b\x46\xc2\x29\x2c\x15\x07\x1c\xc9\x4b\x1a\x54\xf8\x6c\x1e\xaf\x60\x27\x62\x0a\x65\xd5\x9a\xb9\x50\x36\x16\x6e\x71\xf6\x1f\x01\xf7\x12\xa7\xfc\xbf\xf6\x21\xa3\x29\x90\x86\x2d\x77\xde\xbb\x4c\xd4\xcf\xfd\xd2\xcf\x82\x2c\x4d\xd4\xf2\xc2\x2d\xac\xa9\xbe\xea\xc3\x19\x25\x43\xb2\xe5\x9a\x6c\x0d\xc5\x1c\xa5\x8b\xf7\x3f\x30\xaf\xb9\x01\x91\xb7\x69\x12\x12\xe5\x83\x61\xfe\x34\x00\xbe\xf6\x71\x8a\xc7\xeb\x50\x92\xe8\x59\xfe\x15\x91\xeb\x96\x97\xf8\x23\x54\x3f\x2d\x8e\x07\xdf\xee\xda\xb3\x4f\xc8\x3c\x9d\x6f\xdf\x3c\x2c\x43\x57\xa1\x47\x0c\x91\x04\xf4\x75\x4d\xda\x89\x81\xa4\x14\x06\x34\xb9\x98\xc3\xda\xf1\xfd\xed\x33\x36\xd3\x16\x2d\x35\x02\x03\x01\x00\x01"),
["\x34\xbb\x6a\xd6\xc3\xdf\x9c\x03\xee\xa8\xa4\x99\xff\x78\x91\x48\x6c\x9d\x5e\x5c\xac\x92\xd0\x1f\x7b\xfd\x1b\xce\x19\xdb\x48\xef"] = CTInfo($description="StartCom log", $operator="StartCom", $url="ct.startssl.com/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x48\xf3\x59\xf3\xf6\x05\x18\xd3\xdb\xb2\xed\x46\x7e\xcf\xc8\x11\xb5\x57\xb1\xa8\xd6\x4c\xe6\x9f\xb7\x4a\x1a\x14\x86\x43\xa9\x48\xb0\xcb\x5a\x3f\x3c\x4a\xca\xdf\xc4\x82\x14\x55\x9a\xf8\xf7\x8e\x40\x55\xdc\xf4\xd2\xaf\xea\x75\x74\xfb\x4e\x7f\x60\x86\x2e\x51"), ["\x34\xbb\x6a\xd6\xc3\xdf\x9c\x03\xee\xa8\xa4\x99\xff\x78\x91\x48\x6c\x9d\x5e\x5c\xac\x92\xd0\x1f\x7b\xfd\x1b\xce\x19\xdb\x48\xef"] = CTInfo($description="StartCom log", $operator="StartCom", $url="ct.startssl.com/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x48\xf3\x59\xf3\xf6\x05\x18\xd3\xdb\xb2\xed\x46\x7e\xcf\xc8\x11\xb5\x57\xb1\xa8\xd6\x4c\xe6\x9f\xb7\x4a\x1a\x14\x86\x43\xa9\x48\xb0\xcb\x5a\x3f\x3c\x4a\xca\xdf\xc4\x82\x14\x55\x9a\xf8\xf7\x8e\x40\x55\xdc\xf4\xd2\xaf\xea\x75\x74\xfb\x4e\x7f\x60\x86\x2e\x51"),
["\xe0\x12\x76\x29\xe9\x04\x96\x56\x4e\x3d\x01\x47\x98\x44\x98\xaa\x48\xf8\xad\xb1\x66\x00\xeb\x79\x02\xa1\xef\x99\x09\x90\x62\x73"] = CTInfo($description="PuChuangSiDa CT log", $operator="Beijing PuChuangSiDa Technology Ltd.", $url="www.certificatetransparency.cn/ct/", $maximum_merge_delay=86400, $key="\x30\x82\x01\x22\x30\x0d\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x00\x30\x82\x01\x0a\x02\x82\x01\x01\x00\xac\xcf\x2f\x4b\x70\xac\xf1\x0d\x96\xbf\xe8\x0a\xfe\x44\x9d\xd4\x8c\x17\x9d\xc3\x9a\x10\x11\x84\x13\xed\x8c\xf9\x37\x6d\x83\xe4\x00\x6f\xb1\x4b\xc0\xa6\x89\xc7\x61\x8f\x9a\x34\xbb\x56\x52\xca\x03\x56\x50\xef\x24\x7f\x4b\x49\xe9\x35\x81\xdd\xf0\xe7\x17\xf5\x72\xd2\x23\xc5\xe3\x13\x7f\xd7\x8e\x78\x35\x8f\x49\xde\x98\x04\x8a\x63\xaf\xad\xa2\x39\x70\x95\x84\x68\x4b\x91\x33\xfe\x4c\xe1\x32\x17\xc2\xf2\x61\xb8\x3a\x8d\x39\x7f\xd5\x95\x82\x3e\x56\x19\x50\x45\x6f\xcb\x08\x33\x0d\xd5\x19\x42\x08\x1a\x48\x42\x10\xf1\x68\xc3\xc3\x41\x13\xcb\x0d\x1e\xdb\x02\xb7\x24\x7a\x51\x96\x6e\xbc\x08\xea\x69\xaf\x6d\xef\x92\x98\x8e\x55\xf3\x65\xe5\xe8\x9c\xbe\x1a\x47\x60\x30\x7d\x7a\x80\xad\x56\x83\x7a\x93\xc3\xae\x93\x2b\x6a\x28\x8a\xa6\x5f\x63\x19\x0c\xbe\x7c\x7b\x21\x63\x41\x38\xb7\xf7\xe8\x76\x73\x6b\x85\xcc\xbc\x72\x2b\xc1\x52\xd0\x5b\x5d\x31\x4e\x9d\x2a\xf3\x4d\x9b\x64\x14\x99\x26\xc6\x71\xf8\x7b\xf8\x44\xd5\xe3\x23\x20\xf3\x0a\xd7\x8b\x51\x3e\x72\x80\xd2\x78\x78\x35\x2d\x4a\xe7\x40\x99\x11\x95\x34\xd4\x2f\x7f\xf9\x5f\x35\x37\x02\x03\x01\x00\x01"),
["\x55\x81\xd4\xc2\x16\x90\x36\x01\x4a\xea\x0b\x9b\x57\x3c\x53\xf0\xc0\xe4\x38\x78\x70\x25\x08\x17\x2f\xa3\xaa\x1d\x07\x13\xd3\x0c"] = CTInfo($description="Sectigo 'Sabre' CT log", $operator="Sectigo", $url="sabre.ct.comodo.com/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\xf2\x6f\xd2\x89\x0f\x3f\xc5\xf8\x87\x1e\xab\x65\xb3\xd9\xbb\x17\x23\x8c\x06\x0e\x09\x55\x96\x3d\x0a\x08\xa2\xc5\x71\xb3\xd1\xa9\x2f\x28\x3e\x83\x10\xbf\x12\xd0\x44\x66\x15\xef\x54\xe1\x98\x80\xd0\xce\x24\x6d\x3e\x67\x9a\xe9\x37\x23\xce\x52\x93\x86\xda\x80"), ["\x55\x81\xd4\xc2\x16\x90\x36\x01\x4a\xea\x0b\x9b\x57\x3c\x53\xf0\xc0\xe4\x38\x78\x70\x25\x08\x17\x2f\xa3\xaa\x1d\x07\x13\xd3\x0c"] = CTInfo($description="Sectigo 'Sabre' CT log", $operator="Sectigo", $url="sabre.ct.comodo.com/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\xf2\x6f\xd2\x89\x0f\x3f\xc5\xf8\x87\x1e\xab\x65\xb3\xd9\xbb\x17\x23\x8c\x06\x0e\x09\x55\x96\x3d\x0a\x08\xa2\xc5\x71\xb3\xd1\xa9\x2f\x28\x3e\x83\x10\xbf\x12\xd0\x44\x66\x15\xef\x54\xe1\x98\x80\xd0\xce\x24\x6d\x3e\x67\x9a\xe9\x37\x23\xce\x52\x93\x86\xda\x80"),
["\x6f\x53\x76\xac\x31\xf0\x31\x19\xd8\x99\x00\xa4\x51\x15\xff\x77\x15\x1c\x11\xd9\x02\xc1\x00\x29\x06\x8d\xb2\x08\x9a\x37\xd9\x13"] = CTInfo($description="Sectigo 'Mammoth' CT log", $operator="Sectigo", $url="mammoth.ct.comodo.com/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\xef\xe4\x7d\x74\x2e\x15\x15\xb6\xe9\xbb\x23\x8b\xfb\x2c\xb5\xe1\xc7\x80\x98\x47\xfb\x40\x69\x68\xfc\x49\xad\x61\x4e\x83\x47\x3c\x1a\xb7\x8d\xdf\xff\x7b\x30\xb4\xba\xff\x2f\xcb\xa0\x14\xe3\xad\xd5\x85\x3f\x44\x59\x8c\x8c\x60\x8b\xd7\xb8\xb1\xbf\xae\x8c\x67"), ["\x6f\x53\x76\xac\x31\xf0\x31\x19\xd8\x99\x00\xa4\x51\x15\xff\x77\x15\x1c\x11\xd9\x02\xc1\x00\x29\x06\x8d\xb2\x08\x9a\x37\xd9\x13"] = CTInfo($description="Sectigo 'Mammoth' CT log", $operator="Sectigo", $url="mammoth.ct.comodo.com/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\xef\xe4\x7d\x74\x2e\x15\x15\xb6\xe9\xbb\x23\x8b\xfb\x2c\xb5\xe1\xc7\x80\x98\x47\xfb\x40\x69\x68\xfc\x49\xad\x61\x4e\x83\x47\x3c\x1a\xb7\x8d\xdf\xff\x7b\x30\xb4\xba\xff\x2f\xcb\xa0\x14\xe3\xad\xd5\x85\x3f\x44\x59\x8c\x8c\x60\x8b\xd7\xb8\xb1\xbf\xae\x8c\x67"),
["\x53\x7b\x69\xa3\x56\x43\x35\xa9\xc0\x49\x04\xe3\x95\x93\xb2\xc2\x98\xeb\x8d\x7a\x6e\x83\x02\x36\x35\xc6\x27\x24\x8c\xd6\xb4\x40"] = CTInfo($description="Nordu 'flimsy' log", $operator="NORDUnet", $url="flimsy.ct.nordu.net:8080/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\xe2\xa5\xaa\xe9\xa7\xe1\x05\x48\xb4\x39\xd7\x16\x51\x88\x72\x24\xb3\x57\x4e\x41\xaa\x43\xd3\xcc\x4b\x99\x6a\xa0\x28\x24\x57\x68\x75\x66\xfa\x4d\x8c\x11\xf6\xbb\xc5\x1b\x81\xc3\x90\xc2\xa0\xe8\xeb\xac\xfa\x05\x64\x09\x1a\x89\x68\xcd\x96\x26\x34\x71\x36\x91"),
["\xaa\xe7\x0b\x7f\x3c\xb8\xd5\x66\xc8\x6c\x2f\x16\x97\x9c\x9f\x44\x5f\x69\xab\x0e\xb4\x53\x55\x89\xb2\xf7\x7a\x03\x01\x04\xf3\xcd"] = CTInfo($description="Nordu 'plausible' log", $operator="NORDUnet", $url="plausible.ct.nordu.net/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\xf5\x45\x7d\xfa\x33\xb6\x30\x24\xf3\x91\xa6\xe8\x74\xed\x85\xec\xb3\x34\xdc\xc5\x01\x73\xc3\x2b\x74\x0b\x64\x71\x6e\xaf\xe8\x60\x3d\xb5\xa4\xd3\xc3\xd4\x09\xaa\x87\xe6\xd0\x16\xdd\x02\xc6\xed\x24\xbf\xee\x9f\x21\x1f\xd3\x32\x24\x46\x05\xe3\x8f\x36\x98\xa9"),
["\xcf\x55\xe2\x89\x23\x49\x7c\x34\x0d\x52\x06\xd0\x53\x53\xae\xb2\x58\x34\xb5\x2f\x1f\x8d\xc9\x52\x68\x09\xf2\x12\xef\xdd\x7c\xa6"] = CTInfo($description="SHECA CT log 1", $operator="SHECA", $url="ctlog.sheca.com/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x11\xa9\x60\x2b\xb4\x71\x45\x66\xe0\x2e\xde\xd5\x87\x3b\xd5\xfe\xf0\x92\x37\xf4\x68\xc6\x92\xdd\x3f\x1a\xe2\xbc\x0c\x22\xd6\x99\x63\x29\x6e\x32\x28\x14\xc0\x76\x2c\x80\xa8\x22\x51\x91\xd6\xeb\xa6\xd8\xf1\xec\xf0\x07\x7e\xb0\xfc\x76\x70\x76\x72\x7c\x91\xe9"),
["\x32\xdc\x59\xc2\xd4\xc4\x19\x68\xd5\x6e\x14\xbc\x61\xac\x8f\x0e\x45\xdb\x39\xfa\xf3\xc1\x55\xaa\x42\x52\xf5\x00\x1f\xa0\xc6\x23"] = CTInfo($description="SHECA CT log 2", $operator="SHECA", $url="ct.sheca.com/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\xb1\x8e\x1d\x8a\xaa\x3a\xac\xce\x86\xcb\x53\x76\xe8\xa8\x9d\x59\xbe\x17\x88\x03\x07\xf2\x27\xe0\x82\xbe\xb1\xfc\x67\x3b\x46\xee\xd3\xf1\x8d\xd6\x77\xe8\xa3\xb4\xdb\x09\x5c\xa0\x09\x43\xfc\x5f\xd0\x68\x34\x23\x24\x08\xc2\x4f\xd8\xd2\xb6\x9d\xed\xd5\x8c\xdb"),
["\x96\x06\xc0\x2c\x69\x00\x33\xaa\x1d\x14\x5f\x59\xc6\xe2\x64\x8d\x05\x49\xf0\xdf\x96\xaa\xb8\xdb\x91\x5a\x70\xd8\xec\xf3\x90\xa5"] = CTInfo($description="Akamai CT Log", $operator="Akamai", $url="ct.akamai.com/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x43\x79\xeb\x49\x5c\x50\x2a\x4a\x6a\x8f\x59\x93\xbc\xc3\x42\x76\xc2\x99\xf8\x27\x81\x3c\x06\x6c\xd2\xc8\x04\x8f\x74\x7b\xb4\xb5\x21\xf2\xe3\xa8\xdc\x33\xb9\xfe\x25\xe9\x3d\x04\xfc\x3f\xb4\xae\x40\xe3\x45\x7e\x84\x92\x2a\xd8\x52\xeb\x1f\x3f\x73\x13\xd0\xc8"),
["\x39\x37\x6f\x54\x5f\x7b\x46\x07\xf5\x97\x42\xd7\x68\xcd\x5d\x24\x37\xbf\x34\x73\xb6\x53\x4a\x48\x34\xbc\xf7\x2e\x68\x1c\x83\xc9"] = CTInfo($description="Alpha CT Log", $operator="Matt Palmer", $url="alpha.ctlogs.org/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\xa2\xf7\xed\x13\xe1\xd3\x5c\x02\x08\xc4\x8e\x8b\x9b\x8b\x3b\x39\x68\xc7\x92\x6a\x38\xa1\x4f\x23\xc5\xa5\x6f\x6f\xd7\x65\x81\xf8\xc1\x9b\xf4\x9f\xa9\x8b\x45\xf4\xb9\x4e\x1b\xc9\xa2\x69\x17\xa5\x78\x87\xd9\xce\x88\x6f\x41\x03\xbb\xa3\x2a\xe3\x77\x97\x8d\x78"),
["\x65\x9b\x33\x50\xf4\x3b\x12\xcc\x5e\xa5\xab\x4e\xc7\x65\xd3\xfd\xe6\xc8\x82\x43\x77\x77\x78\xe7\x20\x03\xf9\xeb\x2b\x8c\x31\x29"] = CTInfo($description="Let's Encrypt 'Oak2019' log", $operator="Let's Encrypt", $url="oak.ct.letsencrypt.org/2019/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x16\x4a\x8d\x29\x1b\x99\xf9\x9f\x08\x3a\xc9\xcd\x26\xb5\x19\xf2\x0c\x29\xf8\xa2\x86\x39\xd4\x2b\x27\xf1\xca\x85\x26\x9d\x2b\xf4\x89\xba\x80\x9c\xf7\xe7\x71\x43\xb6\xb0\xa6\x65\x88\x32\xbf\x52\x29\xc4\x1e\x1b\x9b\x91\xcc\x6d\x64\x55\x2c\x85\x37\x85\x9f\x73"),
["\xe7\x12\xf2\xb0\x37\x7e\x1a\x62\xfb\x8e\xc9\x0c\x61\x84\xf1\xea\x7b\x37\xcb\x56\x1d\x11\x26\x5b\xf3\xe0\xf3\x4b\xf2\x41\x54\x6e"] = CTInfo($description="Let's Encrypt 'Oak2020' log", $operator="Let's Encrypt", $url="oak.ct.letsencrypt.org/2020/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x7f\x36\xf8\xd9\x97\x6b\xfe\x1e\xe1\x82\xa8\x03\x0a\x8d\x6f\xac\xd2\x6a\x1a\xa6\xdc\x52\xf2\x46\x24\x41\x11\xf4\x30\xea\xa7\x5f\x56\xff\x01\x52\x07\x49\x75\xeb\xa8\x43\xf9\x4e\x5c\x01\x77\x21\xa4\x7f\x19\x90\x13\x54\xba\xf3\x87\x4b\x43\xa7\x27\x8a\x09\xad"),
["\x94\x20\xbc\x1e\x8e\xd5\x8d\x6c\x88\x73\x1f\x82\x8b\x22\x2c\x0d\xd1\xda\x4d\x5e\x6c\x4f\x94\x3d\x61\xdb\x4e\x2f\x58\x4d\xa2\xc2"] = CTInfo($description="Let's Encrypt 'Oak2021' log", $operator="Let's Encrypt", $url="oak.ct.letsencrypt.org/2021/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x2e\xc6\x33\x18\xc3\x70\xa3\xca\xc1\x22\x56\xa4\x94\x12\x1d\x98\x3d\x8e\x7e\x7e\x87\x91\xfa\xe3\x2b\x45\x24\xcf\x5b\x8e\x21\x40\xba\x2e\x6d\x23\x4c\x84\xc2\x5e\x1a\x08\x76\x3b\x3b\x26\x4c\x97\x9f\x0b\xb0\x62\x22\x58\x88\x7e\xec\x13\x56\x1e\x2a\xef\x24\xf7"), ["\x94\x20\xbc\x1e\x8e\xd5\x8d\x6c\x88\x73\x1f\x82\x8b\x22\x2c\x0d\xd1\xda\x4d\x5e\x6c\x4f\x94\x3d\x61\xdb\x4e\x2f\x58\x4d\xa2\xc2"] = CTInfo($description="Let's Encrypt 'Oak2021' log", $operator="Let's Encrypt", $url="oak.ct.letsencrypt.org/2021/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x2e\xc6\x33\x18\xc3\x70\xa3\xca\xc1\x22\x56\xa4\x94\x12\x1d\x98\x3d\x8e\x7e\x7e\x87\x91\xfa\xe3\x2b\x45\x24\xcf\x5b\x8e\x21\x40\xba\x2e\x6d\x23\x4c\x84\xc2\x5e\x1a\x08\x76\x3b\x3b\x26\x4c\x97\x9f\x0b\xb0\x62\x22\x58\x88\x7e\xec\x13\x56\x1e\x2a\xef\x24\xf7"),
["\xdf\xa5\x5e\xab\x68\x82\x4f\x1f\x6c\xad\xee\xb8\x5f\x4e\x3e\x5a\xea\xcd\xa2\x12\xa4\x6a\x5e\x8e\x3b\x12\xc0\x20\x44\x5c\x2a\x73"] = CTInfo($description="Let's Encrypt 'Oak2022' log", $operator="Let's Encrypt", $url="oak.ct.letsencrypt.org/2022/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x86\x3c\xb1\x0d\x52\x23\x5a\xde\x6e\xf6\xc0\x7f\xa3\x64\xbc\xad\xc1\x89\xda\x97\x59\x4c\x60\x3c\xf8\x8a\x57\x84\x8f\xed\xbc\xa0\x63\x12\x51\x84\xe6\xbd\xdd\x7b\x8c\x80\x7d\xe3\x8f\x86\xa4\xea\xa9\xcf\xa8\xee\xf3\xe0\x5e\x70\xe0\xbb\xf6\xbd\xfc\x1f\x91\x2e"), ["\xdf\xa5\x5e\xab\x68\x82\x4f\x1f\x6c\xad\xee\xb8\x5f\x4e\x3e\x5a\xea\xcd\xa2\x12\xa4\x6a\x5e\x8e\x3b\x12\xc0\x20\x44\x5c\x2a\x73"] = CTInfo($description="Let's Encrypt 'Oak2022' log", $operator="Let's Encrypt", $url="oak.ct.letsencrypt.org/2022/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x86\x3c\xb1\x0d\x52\x23\x5a\xde\x6e\xf6\xc0\x7f\xa3\x64\xbc\xad\xc1\x89\xda\x97\x59\x4c\x60\x3c\xf8\x8a\x57\x84\x8f\xed\xbc\xa0\x63\x12\x51\x84\xe6\xbd\xdd\x7b\x8c\x80\x7d\xe3\x8f\x86\xa4\xea\xa9\xcf\xa8\xee\xf3\xe0\x5e\x70\xe0\xbb\xf6\xbd\xfc\x1f\x91\x2e"),
["\xb7\x3e\xfb\x24\xdf\x9c\x4d\xba\x75\xf2\x39\xc5\xba\x58\xf4\x6c\x5d\xfc\x42\xcf\x7a\x9f\x35\xc4\x9e\x1d\x09\x81\x25\xed\xb4\x99"] = CTInfo($description="Let's Encrypt 'Oak2023' log", $operator="Let's Encrypt", $url="oak.ct.letsencrypt.org/2023/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\xb3\x3d\x0e\x78\xbe\xe3\xad\x5c\x44\x5c\x9b\xbe\xa3\x84\x16\x41\x82\xca\xca\x89\x17\x1e\x23\xce\x38\xa5\x54\x2f\x7f\xd3\x34\x51\x6a\xb9\x5c\xc3\x49\xea\xfb\x91\x9d\xe0\x8a\x3c\x73\x06\x9f\x7c\x65\x38\x11\x80\xc4\x9a\x5a\x00\xa6\x67\xc3\x83\xef\x89\x85\x51"), ["\xb7\x3e\xfb\x24\xdf\x9c\x4d\xba\x75\xf2\x39\xc5\xba\x58\xf4\x6c\x5d\xfc\x42\xcf\x7a\x9f\x35\xc4\x9e\x1d\x09\x81\x25\xed\xb4\x99"] = CTInfo($description="Let's Encrypt 'Oak2023' log", $operator="Let's Encrypt", $url="oak.ct.letsencrypt.org/2023/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\xb3\x3d\x0e\x78\xbe\xe3\xad\x5c\x44\x5c\x9b\xbe\xa3\x84\x16\x41\x82\xca\xca\x89\x17\x1e\x23\xce\x38\xa5\x54\x2f\x7f\xd3\x34\x51\x6a\xb9\x5c\xc3\x49\xea\xfb\x91\x9d\xe0\x8a\x3c\x73\x06\x9f\x7c\x65\x38\x11\x80\xc4\x9a\x5a\x00\xa6\x67\xc3\x83\xef\x89\x85\x51"),
["\x84\x9f\x5f\x7f\x58\xd2\xbf\x7b\x54\xec\xbd\x74\x61\x1c\xea\x45\xc4\x9c\x98\xf1\xd6\x48\x1b\xc6\xf6\x9e\x8c\x17\x4f\x24\xf3\xcf"] = CTInfo($description="Let's Encrypt 'Testflume2019' log", $operator="Let's Encrypt", $url="testflume.ct.letsencrypt.org/2019/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x02\x0d\xfe\xbc\x53\x9e\xb0\x55\xb9\xd6\xb2\x84\x09\xe9\x22\xa0\x0b\x7d\x66\x8e\x74\x6a\xd4\x68\x38\x9d\x2a\x2f\x11\x7b\x0c\x81\x07\xb0\x79\xde\x5c\xb1\x29\x80\xed\x56\x32\xb7\xa5\x79\x1c\xb5\xbc\x46\xd4\x24\x3e\xd3\x5e\x81\xfd\xaf\xca\x92\x0c\x6b\xf2\x7b"), ["\xa8\xdc\x52\xf6\x3d\x6b\x24\x25\xe5\x31\xe3\x7c\xf4\xe4\x4a\x71\x4f\x14\x2a\x20\x80\x3b\x0d\x04\xd2\xe2\xee\x06\x64\x79\x4a\x23"] = CTInfo($description="Trust Asia CT2021", $operator="TrustAsia", $url="ct2021.trustasia.com/log2021/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x49\xd0\x1f\x0b\xe8\x75\x49\x93\x6c\x48\x04\x6c\xd7\xcf\x27\xfd\xd0\xa2\x35\x88\xc6\x4a\x09\x13\xed\xab\xcb\x61\xed\x66\x99\x72\x73\xcc\x78\x6c\x9b\x19\x80\xa2\xb1\xed\x3b\x38\x43\x90\x58\x1a\x09\x20\xab\x50\xfa\xd7\x76\xe9\xca\xf7\x8e\x9e\xc8\x87\x92\x98"),
["\xc6\x3f\x22\x18\xc3\x7d\x56\xa6\xaa\x06\xb5\x96\xda\x8e\x53\xd4\xd7\x15\x6d\x1e\x9b\xac\x8e\x44\xd2\x20\x2d\xe6\x4d\x69\xd9\xdc"] = CTInfo($description="Let's Encrypt 'Testflume2020' log", $operator="Let's Encrypt", $url="testflume.ct.letsencrypt.org/2020/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x8d\xd8\xdc\xa0\xaa\x5e\x05\x28\x47\x80\x7b\xd1\x9b\x70\x71\x0f\x9f\xa5\xf9\xe1\xd9\xb9\xdb\xf7\x2a\x60\xf9\x48\x37\x0b\x70\x8d\x35\x56\x3e\x53\x0d\x39\xb1\x6a\x74\x0a\x0a\x0a\x6f\x9b\xda\x5f\x9d\xf0\x7a\x51\x13\x10\x57\x78\x61\x53\x52\x34\xda\x34\x68\x47"),
["\x03\xed\xf1\xda\x97\x76\xb6\xf3\x8c\x34\x1e\x39\xed\x9d\x70\x7a\x75\x70\x36\x9c\xf9\x84\x4f\x32\x7f\xe9\xe1\x41\x38\x36\x1b\x60"] = CTInfo($description="Let's Encrypt 'Testflume2021' log", $operator="Let's Encrypt", $url="testflume.ct.letsencrypt.org/2021/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x74\x22\xe8\x24\xdb\x75\x41\xc3\x5a\xee\xc3\x43\xa7\xb8\x3b\xa1\x32\x7e\xa3\xf5\x08\x60\x43\x3a\x37\xf2\x19\x59\x3f\x9d\x85\xda\xad\x25\x90\xbe\x00\xe0\xc9\xff\x87\xb1\x74\xec\x06\xd3\x80\x78\x2b\xa5\xab\x37\x55\x41\xd8\x42\xca\x40\x87\x3f\xc1\x4d\x65\x0b"),
["\x23\x27\xef\xda\x35\x25\x10\xdb\xc0\x19\xef\x49\x1a\xe3\xff\x1c\xc5\xa4\x79\xbc\xe3\x78\x78\x36\x0e\xe3\x18\xcf\xfb\x64\xf8\xc8"] = CTInfo($description="Let's Encrypt 'Testflume2022' log", $operator="Let's Encrypt", $url="testflume.ct.letsencrypt.org/2022/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x8f\x2f\xeb\x5d\xc0\x01\xb9\xfd\x32\x86\xb9\xb5\xf9\x78\x23\x0e\x78\x78\x5c\xf0\xfb\xbd\xf3\x28\xc8\x93\xb2\x4f\xe2\x80\xf9\xcd\xb3\xb9\x75\x51\xf7\xcc\x90\x9a\x9f\xc1\x97\x96\x45\x74\x61\x70\x26\xe1\x5c\x56\xb0\xb0\xec\x80\xe8\xd0\x41\x8a\xb3\xb5\x02\xc3"),
["\x55\x34\xb7\xab\x5a\x6a\xc3\xa7\xcb\xeb\xa6\x54\x87\xb2\xa2\xd7\x1b\x48\xf6\x50\xfa\x17\xc5\x19\x7c\x97\xa0\xcb\x20\x76\xf3\xc6"] = CTInfo($description="Let's Encrypt 'Testflume2023' log", $operator="Let's Encrypt", $url="testflume.ct.letsencrypt.org/2023/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\xf1\xa2\xe9\x9e\xe9\xaa\x78\x84\xa6\x40\x40\x77\x84\xa3\xe0\xb4\xf2\x50\x1b\x78\xcf\xd8\x87\xed\x7d\xa5\x10\xe1\x63\xd4\x8a\x13\x41\xc1\x43\x84\x93\x54\x7d\x04\xc8\x39\x44\x64\x30\x79\xb5\x92\xb1\x19\x46\x21\x18\x82\xbe\xd1\x3d\xed\x0e\x39\x56\x1d\xe6\xa8"),
["\x29\x6a\xfa\x2d\x56\x8b\xca\x0d\x2e\xa8\x44\x95\x6a\xe9\x72\x1f\xc3\x5f\xa3\x55\xec\xda\x99\x69\x3a\xaf\xd4\x58\xa7\x1a\xef\xdd"] = CTInfo($description="Let's Encrypt 'Clicky' log", $operator="Let's Encrypt", $url="clicky.ct.letsencrypt.org/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x1f\x1a\x15\x83\x77\x00\x75\x62\xb9\x9f\xf6\x06\x05\xed\x95\x89\x83\x41\x81\x97\xe7\xe0\xd4\x33\xfe\x76\xba\x3b\xc9\x49\xc2\xcd\xf1\xcf\xfe\x12\x70\xd7\xbe\xa8\x22\x5f\xb2\xa4\x67\x02\x7b\x71\xae\x1d\xac\xa8\xe9\xd1\x08\xd5\xce\xef\x33\x7a\xc3\x5f\x00\xdc"),
["\xb0\xb7\x84\xbc\x81\xc0\xdd\xc4\x75\x44\xe8\x83\xf0\x59\x85\xbb\x90\x77\xd1\x34\xd8\xab\x88\xb2\xb2\xe5\x33\x98\x0b\x8e\x50\x8b"] = CTInfo($description="Up In The Air 'Behind the Sofa' log", $operator="Up In The Air Consulting", $url="ct.filippo.io/behindthesofa/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x59\x39\xb2\xa6\x94\xc6\x32\xb9\xfe\x63\x69\x1e\x30\x3b\xa3\x5b\xd5\xb0\x43\xc9\x50\x1e\x95\xa5\x2d\xa7\x4c\x4a\x49\x8e\x8b\x8f\xb7\xf8\xcc\xe2\x5b\x97\x72\xd5\xea\x3f\xb1\x21\x48\xe8\x44\x6b\x7f\xea\xef\x22\xff\xdf\xf4\x5f\x3b\x6d\x77\x04\xb1\xaf\x90\x8f"),
["\x47\x44\x47\x7c\x75\xde\x42\x6d\x5c\x44\xef\xd4\xa9\x2c\x96\x77\x59\x7f\x65\x7a\x8f\xe0\xca\xdb\xc6\xd6\x16\xed\xa4\x97\xc4\x25"] = CTInfo($description="Qihoo 360 2020", $operator="Qihoo 360", $url="ct.browser.360.cn/2020/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\xfa\x7b\x8f\xd1\x78\xc4\xdf\xaa\x3e\x1d\xf8\xd2\xf4\x82\xa7\x0c\x8b\x42\x9e\x9d\xd3\x9f\xd3\x5a\x7d\x9a\x49\xff\xc1\x87\xbc\xb9\xbe\x67\xf0\x17\x63\xb1\x6e\x37\x72\xf8\x2c\xf5\xd1\xae\x54\xf2\x74\x12\xed\xeb\x43\xaa\xce\x4b\x47\xa0\x9e\x2d\xe1\xf3\x68\x76"),
["\xc6\xd7\xed\x9e\xdb\x8e\x74\xf0\xa7\x1b\x4d\x4a\x98\x4b\xcb\xeb\xab\xbd\x28\xcc\x1f\xd7\x63\x29\xe8\x87\x26\xcd\x4c\x25\x46\x63"] = CTInfo($description="Qihoo 360 2021", $operator="Qihoo 360", $url="ct.browser.360.cn/2021/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x60\x5b\x65\xa8\xa0\xb9\xf4\x8c\xbe\x37\x5b\x16\x69\x49\x2d\x9d\x23\x69\x6e\x1a\xeb\x2f\x85\x4c\x89\xaa\x9d\x0e\xb4\x2e\xff\x78\x4e\x9f\x13\x89\x89\x71\x65\x91\x26\x10\x8c\x1a\x07\x0c\x25\x40\xe6\x20\xbd\xa6\xef\x3e\xd4\x3b\x2b\x98\xdb\x2f\xe4\x52\x0c\x0f"),
["\x66\x3c\xb0\x9c\x1f\xcd\x9b\xaa\x62\x76\x3c\xcb\x53\x4e\xec\x80\x58\x12\x28\x05\x07\xac\x69\xa4\x5f\xcd\x38\xcf\x4c\xc7\x4c\xf1"] = CTInfo($description="Qihoo 360 2022", $operator="Qihoo 360", $url="ct.browser.360.cn/2022/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x43\x85\x25\x14\xb1\x37\xbf\x10\xc7\xb6\xca\x8e\xe6\xce\xa4\x35\x44\x52\xc9\xa2\xca\xf5\xb1\xd5\xe7\xec\xc3\x5d\x34\x33\xc2\x25\x09\x75\x31\x4a\xc4\x4f\x39\x2f\x9b\xaf\x62\xfa\x1b\xbb\x26\x69\xc9\x2a\x3b\x19\x76\x32\xa2\x92\xf8\x13\x1b\x2b\x9b\x81\xc9\x30"),
["\xe2\x64\x7f\x6e\xda\x34\x05\x03\xc6\x4d\x4e\x10\xa8\x69\x68\x1f\xde\x9c\x5a\x2c\xf3\xb3\x2d\x5f\x20\x0b\x96\x36\x05\x90\x88\x23"] = CTInfo($description="Qihoo 360 2023", $operator="Qihoo 360", $url="ct.browser.360.cn/2023/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x05\x02\xc8\x1a\xd4\x07\xde\x67\xab\x93\x63\x8c\x3b\x62\xdb\x29\x4d\x93\x16\xba\x0a\xc5\xa0\xa1\xaf\x8f\x85\xc4\x1e\x54\x30\xb6\x13\xb2\x9a\x84\x24\xa7\x03\xee\x64\x57\x10\xe6\xc7\x27\xa3\xc8\xff\x7f\x54\xbc\x42\x3d\xf0\xde\x02\xc9\xff\x71\xda\xb2\xaf\xaa"),
["\xc5\xcf\xe5\x4b\x61\x51\xb4\x9b\x14\x2e\xd2\x63\xbd\xe7\x32\x93\x36\x37\x99\x79\x95\x50\xae\x44\x35\xcd\x1a\x69\x97\xc9\xc3\xc3"] = CTInfo($description="Qihoo 360 v1 2020", $operator="Qihoo 360", $url="ct.browser.360.cn/v1/2020/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x0e\x44\x19\x9f\x55\xaa\xc6\xa5\xb2\x58\x71\xbc\xea\x2d\x78\xa9\xb6\x7e\xca\x4f\xf5\xed\x0f\x12\x59\xeb\x9b\x38\x9c\x3a\x8d\x07\x4d\x25\x18\x78\xcc\x9c\x03\xde\x61\x93\x64\x84\x20\x7b\x74\xfa\x40\xe8\x33\x0a\x15\x94\x24\x0d\xf0\x63\x3b\x52\xc7\xe3\x3f\x82"),
["\x48\x14\x58\x7c\xf2\x8b\x08\xfe\x68\x3f\xd2\xbc\xd9\x45\x99\x4c\x2e\xb7\x4c\x8a\xe8\xc8\x7f\xce\x42\x9b\x7c\xd3\x1d\x51\xbd\xc4"] = CTInfo($description="Qihoo 360 v1 2021", $operator="Qihoo 360", $url="ct.browser.360.cn/v1/2021/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x07\x53\x93\xe7\x6c\xbf\xfb\x04\x94\xa9\xa1\xdf\x26\x1e\xbf\x06\xf4\xc3\xdb\xb9\xa5\x66\xbe\xaa\x65\xd7\x64\x8a\xce\xcc\x71\xc9\x0e\x69\x7c\x79\x71\x4d\xc8\xfd\xf0\x71\xf7\x4a\x77\x8f\x5b\x56\xa8\x40\x2b\x56\xe8\x8a\x98\x71\xc0\xbe\xef\x36\x97\xd5\x33\xdb"),
["\x49\x11\xb8\xd6\x14\xcf\xd3\xd9\x9f\x16\xd3\x76\x54\x5e\xe1\xb8\xcc\xfc\x51\x1f\x50\x9f\x08\x0b\xa0\xa0\x87\xd9\x1d\xfa\xee\xa9"] = CTInfo($description="Qihoo 360 v1 2022", $operator="Qihoo 360", $url="ct.browser.360.cn/v1/2022/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x02\xfa\x9c\xb5\xe1\xc7\x18\x46\x42\x13\x99\x12\xbc\x4a\x50\x20\xf0\xf8\x7d\x7b\x04\x14\x76\x2d\xd7\xf1\x15\x89\x23\x2f\xed\x00\xed\x04\x74\xe9\x2b\xde\x08\x65\x24\x9c\x64\xb3\x96\x93\x97\xe9\xbc\x62\x01\xff\xa8\x9b\x57\x34\x79\x30\x25\xbf\x35\x23\x1d\xfc"),
["\xb6\x74\x0b\x12\x00\x2e\x03\x3f\xd0\xe7\xe9\x41\xf4\xba\x3e\xe1\xbf\xc1\x49\xb5\x24\xb4\xcf\x62\x8d\x53\xef\xea\x1f\x40\x3a\x8d"] = CTInfo($description="Qihoo 360 v1 2023", $operator="Qihoo 360", $url="ct.browser.360.cn/v1/2023/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\xa6\xf2\x0f\x06\x4a\x4f\x7d\xc8\x38\x6e\x86\xac\x8d\xae\xac\xae\xf0\x5f\x96\x00\xc0\xce\x74\xf2\xb4\xa8\xcd\x58\xf5\xf5\xe7\x58\xcf\xfc\x46\x91\x66\x63\x4e\x14\x16\xaf\x80\x12\x36\xa3\x19\x50\x69\xb8\x18\x1b\x5d\x58\x1d\xdc\x07\xf8\x51\xe7\xc9\x54\xda\x37"),
["\x45\x35\x94\x98\xd9\x3a\x89\xe0\x28\x03\x08\xd3\x7d\x62\x6d\xc4\x23\x75\x47\x58\xdc\xe0\x37\x00\x36\xfb\xab\x0e\xdf\x8a\x6b\xcf"] = CTInfo($description="Trust Asia Log1", $operator="TrustAsia", $url="ct.trustasia.com/log1/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x79\x47\x98\xd1\x20\xe8\x51\xd0\x12\x38\xc8\x05\xc0\xe1\x54\x4a\x46\x99\xf0\xda\x0a\x9e\x49\xe3\xb5\xb6\xa4\x98\x10\xd4\x24\x98\x4f\x56\x7f\x4b\xfd\xa7\x67\x13\x16\x41\x5e\x5e\x3a\x64\x14\xfb\xd3\x5a\x94\x8b\x17\xea\x77\xfb\x37\x06\x9b\x8c\xc9\x65\x94\x77"),
["\xa5\x95\x94\x3b\x53\x70\xbe\xe9\x06\xe0\x05\x0d\x1f\xb5\xbb\xc6\xa4\x0e\x65\xf2\x65\xae\x85\x2c\x76\x36\x3f\xad\xb2\x33\x36\xed"] = CTInfo($description="Trust Asia Log2020", $operator="TrustAsia", $url="ct.trustasia.com/log2020/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x6e\xc5\x82\xee\xe9\x27\xd9\x66\x0e\x33\x14\xc0\x72\xa2\xfc\x80\xc4\x59\x11\x04\xd9\x17\xdf\x87\xa3\x53\x01\xf5\x62\xe1\x1c\x86\x82\x1e\x91\xec\x25\x2c\x74\x0e\x32\x5d\x54\x82\xd6\xf6\x6b\x4c\xe7\x16\x6d\x5b\x2c\x0c\x58\xc4\x3d\xfd\x1d\xce\x06\x04\x04\x5d"),
["\x67\x8d\xb6\x5b\x3e\x74\x43\xb6\xf3\xa3\x70\xd5\xe1\x3a\xb1\xb4\x3b\xe0\xa0\xd3\x51\xf7\xca\x74\x22\x50\xc7\xc6\xfa\x51\xa8\x8a"] = CTInfo($description="Trust Asia Log2021", $operator="TrustAsia", $url="ct.trustasia.com/log2021/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x8f\x09\x73\x63\x3b\x2c\x0c\x41\xb8\x0e\x93\xe8\x39\x2e\xf7\x13\x0b\x1d\xa2\x17\x34\x33\x36\xa8\x87\x34\x66\x53\x3f\x5d\x8a\x1e\xd9\xf1\x21\xf2\xca\xf8\x8a\x9a\x74\x0b\xd4\xa2\x9f\x63\xa5\x46\x16\x7b\x74\xba\x56\xd5\xba\x9c\xc6\x5d\x26\x98\x50\x0a\x2e\xa4"), ["\x67\x8d\xb6\x5b\x3e\x74\x43\xb6\xf3\xa3\x70\xd5\xe1\x3a\xb1\xb4\x3b\xe0\xa0\xd3\x51\xf7\xca\x74\x22\x50\xc7\xc6\xfa\x51\xa8\x8a"] = CTInfo($description="Trust Asia Log2021", $operator="TrustAsia", $url="ct.trustasia.com/log2021/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x8f\x09\x73\x63\x3b\x2c\x0c\x41\xb8\x0e\x93\xe8\x39\x2e\xf7\x13\x0b\x1d\xa2\x17\x34\x33\x36\xa8\x87\x34\x66\x53\x3f\x5d\x8a\x1e\xd9\xf1\x21\xf2\xca\xf8\x8a\x9a\x74\x0b\xd4\xa2\x9f\x63\xa5\x46\x16\x7b\x74\xba\x56\xd5\xba\x9c\xc6\x5d\x26\x98\x50\x0a\x2e\xa4"),
["\xc3\x65\xf9\xb3\x65\x4f\x32\x83\xc7\x9d\xa9\x8e\x93\xd7\x41\x8f\x5b\xab\x7b\xe3\x25\x2c\x98\xe1\xd2\xf0\x4b\xb9\xeb\x42\x7d\x23"] = CTInfo($description="Trust Asia Log2022", $operator="TrustAsia", $url="ct.trustasia.com/log2022/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\xbb\x52\xf2\x16\xcf\x92\x0b\xce\x79\xe6\x54\x6d\xc2\x37\x53\xa4\xf5\xf9\x3a\xa9\xb3\x05\xec\x1d\xbd\x16\xec\x30\xac\x2e\xf8\x79\x62\x35\x15\x8e\x1a\xd8\x16\x2e\xe4\x48\x6b\xf6\xc6\x13\xf1\x96\x2e\x5c\x10\xfe\x19\x1e\xa8\x18\xb8\x0f\x2d\xc3\xa4\x86\x51\x97"), ["\xc3\x65\xf9\xb3\x65\x4f\x32\x83\xc7\x9d\xa9\x8e\x93\xd7\x41\x8f\x5b\xab\x7b\xe3\x25\x2c\x98\xe1\xd2\xf0\x4b\xb9\xeb\x42\x7d\x23"] = CTInfo($description="Trust Asia Log2022", $operator="TrustAsia", $url="ct.trustasia.com/log2022/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\xbb\x52\xf2\x16\xcf\x92\x0b\xce\x79\xe6\x54\x6d\xc2\x37\x53\xa4\xf5\xf9\x3a\xa9\xb3\x05\xec\x1d\xbd\x16\xec\x30\xac\x2e\xf8\x79\x62\x35\x15\x8e\x1a\xd8\x16\x2e\xe4\x48\x6b\xf6\xc6\x13\xf1\x96\x2e\x5c\x10\xfe\x19\x1e\xa8\x18\xb8\x0f\x2d\xc3\xa4\x86\x51\x97"),
["\xe8\x7e\xa7\x66\x0b\xc2\x6c\xf6\x00\x2e\xf5\x72\x5d\x3f\xe0\xe3\x31\xb9\x39\x3b\xb9\x2f\xbf\x58\xeb\x3b\x90\x49\xda\xf5\x43\x5a"] = CTInfo($description="Trust Asia Log2023", $operator="TrustAsia", $url="ct.trustasia.com/log2023/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\xa4\x11\x52\xdb\x17\x41\x4e\x90\xd4\x56\x51\x12\x30\x52\xf8\x9b\x03\xcf\x4c\x9f\xf8\x2e\x38\xb5\xf1\x5a\xba\xfa\x38\xb9\xd2\x8f\x1a\x81\xda\x95\xcc\x33\xec\x21\x28\x66\xc6\x56\x3e\x60\x36\x21\x20\xd9\xd4\xac\x5d\xfa\x5c\x19\xa1\x05\x7d\xfe\x20\x23\xfc\xf5"), ["\xe8\x7e\xa7\x66\x0b\xc2\x6c\xf6\x00\x2e\xf5\x72\x5d\x3f\xe0\xe3\x31\xb9\x39\x3b\xb9\x2f\xbf\x58\xeb\x3b\x90\x49\xda\xf5\x43\x5a"] = CTInfo($description="Trust Asia Log2023", $operator="TrustAsia", $url="ct.trustasia.com/log2023/", $maximum_merge_delay=86400, $key="\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42\x00\x04\xa4\x11\x52\xdb\x17\x41\x4e\x90\xd4\x56\x51\x12\x30\x52\xf8\x9b\x03\xcf\x4c\x9f\xf8\x2e\x38\xb5\xf1\x5a\xba\xfa\x38\xb9\xd2\x8f\x1a\x81\xda\x95\xcc\x33\xec\x21\x28\x66\xc6\x56\x3e\x60\x36\x21\x20\xd9\xd4\xac\x5d\xfa\x5c\x19\xa1\x05\x7d\xfe\x20\x23\xfc\xf5"),

View file

@ -6,27 +6,37 @@
module SSL; module SSL;
export { export {
## Set this to true to includd the server certificate subject and
## issuer from the SSL log file. This information is still available
## in x509.log.
const log_include_server_certificate_subject_issuer = F &redef;
## Set this to true to include the client certificate subject
## and issuer in the SSL logfile. This information is rarely present
## and probably only interesting in very specific circumstances
const log_include_client_certificate_subject_issuer = F &redef;
redef record Info += { redef record Info += {
## Chain of certificates offered by the server to validate its ## Chain of certificates offered by the server to validate its
## complete signing chain. ## complete signing chain.
cert_chain: vector of Files::Info &optional; cert_chain: vector of Files::Info &optional;
## An ordered vector of all certificate file unique IDs for the ## An ordered vector of all certificate fingerprints for the
## certificates offered by the server. ## certificates offered by the server.
cert_chain_fuids: vector of string &optional &log; cert_chain_fps: vector of string &optional &log;
## Chain of certificates offered by the client to validate its ## Chain of certificates offered by the client to validate its
## complete signing chain. ## complete signing chain.
client_cert_chain: vector of Files::Info &optional; client_cert_chain: vector of Files::Info &optional;
## An ordered vector of all certificate file unique IDs for the ## An ordered vector of all certificate fingerprints for the
## certificates offered by the client. ## certificates offered by the client.
client_cert_chain_fuids: vector of string &optional &log; client_cert_chain_fps: vector of string &optional &log;
## Subject of the X.509 certificate offered by the server. ## Subject of the X.509 certificate offered by the server.
subject: string &log &optional; subject: string &log &optional;
## Subject of the signer of the X.509 certificate offered by the ## Issuer of the signer of the X.509 certificate offered by the
## server. ## server.
issuer: string &log &optional; issuer: string &log &optional;
@ -37,6 +47,11 @@ export {
## client. ## client.
client_issuer: string &log &optional; client_issuer: string &log &optional;
## Set to true if the hostname sent in the SNI matches the certificate.
## Set to false if they do not match. Unset if the client did not send
## an SNI.
sni_matches_cert: bool &log &optional;
## Current number of certificates seen from either side. Used ## Current number of certificates seen from either side. Used
## to create file handles. ## to create file handles.
server_depth: count &default=0; server_depth: count &default=0;
@ -88,6 +103,25 @@ event zeek_init() &priority=5
Files::register_protocol(Analyzer::ANALYZER_DTLS, Files::register_protocol(Analyzer::ANALYZER_DTLS,
[$get_file_handle = SSL::get_file_handle, [$get_file_handle = SSL::get_file_handle,
$describe = SSL::describe_file]); $describe = SSL::describe_file]);
local ssl_filter = Log::get_filter(SSL::LOG, "default");
if ( ssl_filter$name != "<not found>" )
{
if ( ! ssl_filter?$exclude )
ssl_filter$exclude = set();
if ( ! log_include_server_certificate_subject_issuer )
{
add ssl_filter$exclude["subject"];
add ssl_filter$exclude["issuer"];
}
if ( ! log_include_client_certificate_subject_issuer )
{
add ssl_filter$exclude["client_subject"];
add ssl_filter$exclude["client_issuer"];
}
Log::add_filter(SSL::LOG, ssl_filter);
}
} }
event file_sniff(f: fa_file, meta: fa_metadata) &priority=5 event file_sniff(f: fa_file, meta: fa_metadata) &priority=5
@ -114,28 +148,39 @@ event file_sniff(f: fa_file, meta: fa_metadata) &priority=5
{ {
c$ssl$cert_chain = vector(); c$ssl$cert_chain = vector();
c$ssl$client_cert_chain = vector(); c$ssl$client_cert_chain = vector();
c$ssl$cert_chain_fuids = string_vec(); c$ssl$cert_chain_fps = string_vec();
c$ssl$client_cert_chain_fuids = string_vec(); c$ssl$client_cert_chain_fps = string_vec();
} }
if ( f$is_orig ) if ( f$is_orig )
{
c$ssl$client_cert_chain += f$info; c$ssl$client_cert_chain += f$info;
c$ssl$client_cert_chain_fuids += f$id;
}
else else
{
c$ssl$cert_chain += f$info; c$ssl$cert_chain += f$info;
c$ssl$cert_chain_fuids += f$id;
}
} }
event ssl_established(c: connection) &priority=6 hook ssl_finishing(c: connection) &priority=20
{ {
# update subject and issuer information if ( c$ssl?$cert_chain)
for ( i in c$ssl$cert_chain )
if ( c$ssl$cert_chain[i]?$x509 && c$ssl$cert_chain[i]$x509?$fingerprint )
c$ssl$cert_chain_fps += c$ssl$cert_chain[i]$x509$fingerprint;
if ( c$ssl?$client_cert_chain )
for ( i in c$ssl$client_cert_chain )
if ( c$ssl$client_cert_chain[i]?$x509 && c$ssl$client_cert_chain[i]$x509?$fingerprint )
c$ssl$client_cert_chain_fps += c$ssl$client_cert_chain[i]$x509$fingerprint;
if ( c$ssl?$cert_chain && |c$ssl$cert_chain| > 0 && if ( c$ssl?$cert_chain && |c$ssl$cert_chain| > 0 &&
c$ssl$cert_chain[0]?$x509 ) c$ssl$cert_chain[0]?$x509 )
{ {
if ( c$ssl?$server_name )
{
if ( x509_check_cert_hostname(c$ssl$cert_chain[0]$x509$handle, c$ssl$server_name) != "" )
c$ssl$sni_matches_cert = T;
else
c$ssl$sni_matches_cert = F;
}
c$ssl$subject = c$ssl$cert_chain[0]$x509$certificate$subject; c$ssl$subject = c$ssl$cert_chain[0]$x509$certificate$subject;
c$ssl$issuer = c$ssl$cert_chain[0]$x509$certificate$issuer; c$ssl$issuer = c$ssl$cert_chain[0]$x509$certificate$issuer;
} }

View file

@ -68,6 +68,36 @@ export {
## Flag to indicate if this record already has been logged, to ## Flag to indicate if this record already has been logged, to
## prevent duplicates. ## prevent duplicates.
logged: bool &default=F; logged: bool &default=F;
## SSL history showing which types of packets we received in which order.
## Letters have the following meaning with client-sent letters being capitalized:
## H hello_request
## C client_hello
## S server_hello
## V hello_verify_request
## T NewSessionTicket
## X certificate
## K server_key_exchange
## R certificate_request
## N server_hello_done
## Y certificate_verify
## G client_key_exchange
## F finished
## W certificate_url
## U certificate_status
## A supplemental_data
## Z unassigned_handshake_type
## I change_cipher_spec
## B heartbeat
## D application_data
## E end_of_early_data
## O encrypted_extensions
## P key_update
## M message_hash
## J hello_retry_request
## L alert
## Q unknown_content_type
ssl_history: string &log &default="";
}; };
## The default root CA bundle. By default, the mozilla-ca-list.zeek ## The default root CA bundle. By default, the mozilla-ca-list.zeek
@ -111,8 +141,8 @@ export {
## record as it is sent on to the logging framework. ## record as it is sent on to the logging framework.
global log_ssl: event(rec: Info); global log_ssl: event(rec: Info);
# Hook that can be used to perform actions right before the log record ## Hook that can be used to perform actions right before the log record
# is written. ## is written.
global ssl_finishing: hook(c: connection); global ssl_finishing: hook(c: connection);
## SSL finalization hook. Remaining SSL info may get logged when it's called. ## SSL finalization hook. Remaining SSL info may get logged when it's called.
@ -145,7 +175,8 @@ const dtls_ports = { 443/udp };
redef likely_server_ports += { ssl_ports, dtls_ports }; redef likely_server_ports += { ssl_ports, dtls_ports };
event zeek_init() &priority=5 # Priority needs to be higher than priority of zeek_init in ssl/files.zeek
event zeek_init() &priority=6
{ {
Log::create_stream(SSL::LOG, [$columns=Info, $ev=log_ssl, $path="ssl", $policy=log_policy]); Log::create_stream(SSL::LOG, [$columns=Info, $ev=log_ssl, $path="ssl", $policy=log_policy]);
Analyzer::register_for_ports(Analyzer::ANALYZER_SSL, ssl_ports); Analyzer::register_for_ports(Analyzer::ANALYZER_SSL, ssl_ports);
@ -161,6 +192,14 @@ function set_session(c: connection)
} }
} }
function add_to_history(c: connection, is_orig: bool, char: string)
{
if ( is_orig )
c$ssl$ssl_history = c$ssl$ssl_history+to_upper(char);
else
c$ssl$ssl_history = c$ssl$ssl_history+to_lower(char);
}
function delay_log(info: Info, token: string) function delay_log(info: Info, token: string)
{ {
if ( ! info?$delay_tokens ) if ( ! info?$delay_tokens )
@ -295,6 +334,75 @@ event ssl_handshake_message(c: connection, is_orig: bool, msg_type: count, lengt
if ( is_orig && msg_type == SSL::CLIENT_KEY_EXCHANGE ) if ( is_orig && msg_type == SSL::CLIENT_KEY_EXCHANGE )
c$ssl$client_key_exchange_seen = T; c$ssl$client_key_exchange_seen = T;
switch ( msg_type )
{
case SSL::HELLO_REQUEST:
add_to_history(c, is_orig, "h");
break;
case SSL::CLIENT_HELLO:
add_to_history(c, is_orig, "c");
break;
case SSL::SERVER_HELLO:
add_to_history(c, is_orig, "s");
break;
case SSL::HELLO_VERIFY_REQUEST:
add_to_history(c, is_orig, "v");
break;
case SSL::SESSION_TICKET:
add_to_history(c, is_orig, "t");
break;
# end of early data
case 5:
add_to_history(c, is_orig, "e");
break;
case SSL::HELLO_RETRY_REQUEST:
add_to_history(c, is_orig, "j");
break;
case SSL::ENCRYPTED_EXTENSIONS:
add_to_history(c, is_orig, "o");
break;
case SSL::CERTIFICATE:
add_to_history(c, is_orig, "x");
break;
case SSL::SERVER_KEY_EXCHANGE:
add_to_history(c, is_orig, "k");
break;
case SSL::CERTIFICATE_REQUEST:
add_to_history(c, is_orig, "r");
break;
case SSL::SERVER_HELLO_DONE:
add_to_history(c, is_orig, "n");
break;
case SSL::CERTIFICATE_VERIFY:
add_to_history(c, is_orig, "y");
break;
case SSL::CLIENT_KEY_EXCHANGE:
add_to_history(c, is_orig, "g");
break;
case SSL::FINISHED:
add_to_history(c, is_orig, "f");
break;
case SSL::CERTIFICATE_URL:
add_to_history(c, is_orig, "w");
break;
case SSL::CERTIFICATE_STATUS:
add_to_history(c, is_orig, "u");
break;
case SSL::SUPPLEMENTAL_DATA:
add_to_history(c, is_orig, "a");
break;
case SSL::KEY_UPDATE:
add_to_history(c, is_orig, "p");
break;
# message hash
case 254:
add_to_history(c, is_orig, "m");
break;
default:
add_to_history(c, is_orig, "z");
break;
}
} }
# Extension event is fired _before_ the respective client or server hello. # Extension event is fired _before_ the respective client or server hello.
@ -318,6 +426,7 @@ event ssl_extension(c: connection, is_orig: bool, code: count, val: string) &pri
event ssl_change_cipher_spec(c: connection, is_orig: bool) &priority=5 event ssl_change_cipher_spec(c: connection, is_orig: bool) &priority=5
{ {
set_session(c); set_session(c);
add_to_history(c, is_orig, "i");
if ( is_orig && c$ssl$client_ticket_empty_session_seen && ! c$ssl$client_key_exchange_seen ) if ( is_orig && c$ssl$client_ticket_empty_session_seen && ! c$ssl$client_key_exchange_seen )
c$ssl$resumed = T; c$ssl$resumed = T;
@ -326,10 +435,17 @@ event ssl_change_cipher_spec(c: connection, is_orig: bool) &priority=5
event ssl_alert(c: connection, is_orig: bool, level: count, desc: count) &priority=5 event ssl_alert(c: connection, is_orig: bool, level: count, desc: count) &priority=5
{ {
set_session(c); set_session(c);
add_to_history(c, is_orig, "l");
c$ssl$last_alert = alert_descriptions[desc]; c$ssl$last_alert = alert_descriptions[desc];
} }
event ssl_heartbeat(c: connection, is_orig: bool, length: count, heartbeat_type: count, payload_length: count, payload: string)
{
set_session(c);
add_to_history(c, is_orig, "b");
}
event ssl_established(c: connection) &priority=7 event ssl_established(c: connection) &priority=7
{ {
c$ssl$established = T; c$ssl$established = T;

File diff suppressed because one or more lines are too long

View file

@ -78,6 +78,19 @@ function request2curl(r: Request, bodyfile: string, headersfile: string): string
function request(req: Request): ActiveHTTP::Response function request(req: Request): ActiveHTTP::Response
{ {
local resp: Response;
resp$code = 0;
resp$msg = "";
resp$body = "";
resp$headers = table();
# Sanity-check the method parameter as it will go directly into our command line.
if ( req$method != /[A-Za-z]+/ )
{
Reporter::error(fmt("There was an illegal method specified with ActiveHTTP (\"%s\").", req$method));
return resp;
}
local tmpfile = "/tmp/zeek-activehttp-" + unique_id(""); local tmpfile = "/tmp/zeek-activehttp-" + unique_id("");
local bodyfile = fmt("%s_body", tmpfile); local bodyfile = fmt("%s_body", tmpfile);
local headersfile = fmt("%s_headers", tmpfile); local headersfile = fmt("%s_headers", tmpfile);
@ -85,11 +98,6 @@ function request(req: Request): ActiveHTTP::Response
local cmd = request2curl(req, bodyfile, headersfile); local cmd = request2curl(req, bodyfile, headersfile);
local stdin_data = req?$client_data ? req$client_data : ""; local stdin_data = req?$client_data ? req$client_data : "";
local resp: Response;
resp$code = 0;
resp$msg = "";
resp$body = "";
resp$headers = table();
return when ( local result = Exec::run([$cmd=cmd, $stdin=stdin_data, $read_files=set(bodyfile, headersfile)]) ) return when ( local result = Exec::run([$cmd=cmd, $stdin=stdin_data, $read_files=set(bodyfile, headersfile)]) )
{ {
# If there is no response line then nothing else will work either. # If there is no response line then nothing else will work either.

View file

@ -83,8 +83,10 @@ function has_valid_octets(octets: string_vec): bool
## ##
## input: a string that may contain an IP address anywhere within it. ## input: a string that may contain an IP address anywhere within it.
## ##
## check_wrapping: if true, will only return IP addresses that are wrapped in matching pairs of spaces, square brackets, curly braces, or parens. This can be used to avoid extracting strings that look like IPs from innocuous strings, such as SMTP headers.
##
## Returns: an array containing all valid IP address strings found in *input*. ## Returns: an array containing all valid IP address strings found in *input*.
function extract_ip_addresses(input: string): string_vec function extract_ip_addresses(input: string, check_wrapping: bool &default=F): string_vec
{ {
local parts = split_string_all(input, ip_addr_regex); local parts = split_string_all(input, ip_addr_regex);
local output: string_vec; local output: string_vec;
@ -92,8 +94,25 @@ function extract_ip_addresses(input: string): string_vec
for ( i in parts ) for ( i in parts )
{ {
if ( i % 2 == 1 && is_valid_ip(parts[i]) ) if ( i % 2 == 1 && is_valid_ip(parts[i]) )
{
if ( ! check_wrapping )
{
output += parts[i]; output += parts[i];
} }
else if ( i > 0 && i < |parts| - 1 )
{
local p1 = parts[i-1];
local p3 = parts[i+1];
if ( ( |p1| == 0 && |p3| == 0 ) ||
( p1[-1] == "\[" && p3[0] == "\]" ) ||
( p1[-1] == "\(" && p3[0] == "\)" ) ||
( p1[-1] == "\{" && p3[0] == "\}" ) ||
( p1[-1] == " " && p3[0] == " " ) )
output += parts[i];
}
}
}
return output; return output;
} }

View file

@ -5,16 +5,102 @@
module Site; module Site;
export { export {
## Address space that is considered private and unrouted. ## A list of subnets that are considered private address space.
## By default it has RFC defined non-routable IPv4 address space. ##
## By default, it has address blocks defined by IANA as not being routable over the Internet.
##
## See the `IPv4 Special-Purpose Address Registry <https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml>`_
## and the `IPv6 Special-Purpose Address Registry <https://www.iana.org/assignments/iana-ipv6-special-registry/iana-ipv6-special-registry.xhtml>`_
option private_address_space: set[subnet] = { option private_address_space: set[subnet] = {
# "This network", see :rfc:`791`
0.0.0.0/8,
# 0.0.0.0/8 as a 6to4 address, see :rfc:`791` and :rfc:`3056`
[2002::]/24,
# Private-Use, see :rfc:`1918`
10.0.0.0/8, 10.0.0.0/8,
192.168.0.0/16, # 10.0.0.0/8 as a 6to4 address, see :rfc:`1918` and :rfc:`3056`
172.16.0.0/12, [2002:a00::]/24,
100.64.0.0/10, # RFC6598 Carrier Grade NAT
# Shared Address Space (also known as Carrier-grade NAT), see :rfc:`6598`
100.64.0.0/10,
# 100.64.0.0/10 as a 6to4 address, see :rfc:`6598` and :rfc:`3056`
[2002:6440::]/26,
# Loopback, see :rfc:`1122`
127.0.0.0/8, 127.0.0.0/8,
[fe80::]/10, # 127.0.0.0/8 as a 6to4 address, see :rfc:`1122` and :rfc:`3056`
[2002:7f00::]/24,
# Link Local, see :rfc:`3927`
169.254.0.0/16,
# 169.254.0.0/16 as a 6to4 address, see :rfc:`3927` and :rfc:`3056`
[2002:a9fe::]/32,
# Private-Use, see :rfc:`1918`
172.16.0.0/12,
# 172.16.0.0/12 as a 6to4 address, see :rfc:`1918` and :rfc:`3056`
[2002:ac10::]/28,
# IETF Protocol Assignments, see :rfc:`6890`
192.0.0.0/24,
# 192.0.0.0/24 as a 6to4 address, see :rfc:`6890` and :rfc:`3056`
[2002:c000::]/40,
# Documentation (TEST-NET-1), see :rfc:`5737`
192.0.2.0/24,
# 192.0.2.0/24 as a 6to4 address, see :rfc:`5737` and :rfc:`3056`
[2002:c000:200::]/40,
# Private-Use, see :rfc:`1918`
192.168.0.0/16,
# 192.168.0.0/16 as a 6to4 address, see :rfc:`1918` and :rfc:`3056`
[2002:c0a8::]/32,
# Benchmarking, see :rfc:`2544`
198.18.0.0/15,
# 198.18.0.0/15 as a 6to4 address, see :rfc:`2544` and :rfc:`3056`
[2002:c612::]/31,
# Documentation (TEST-NET-2), see :rfc:`5737`
198.51.100.0/24,
# 198.51.100.0/24 as a 6to4 address, see :rfc:`5737` and :rfc:`3056`
[2002:c633:6400::]/40,
# Documentation (TEST-NET-3), see :rfc:`5737`
203.0.113.0/24,
# 203.0.113.0/24 as a 6to4 address, see :rfc:`5737` and :rfc:`3056`
[2002:cb00:7100::]/40,
# Reserved, see :rfc:`1112`
240.0.0.0/4,
# 240.0.0.0/4 as a 6to4 address, see :rfc:`1112` and :rfc:`3056`
[2002:f000::]/20,
# Limited Broadcast, see :rfc:`919` and :rfc:`8190`
255.255.255.255/32,
# 255.255.255.255/32 as a 6to4 address, see :rfc:`8190` and :rfc:`3056`
[2002:ffff:ffff::]/48,
# Unspecified Address, see :rfc:`4291`
[::]/128,
# Loopback Address, see :rfc:`4291`
[::1]/128, [::1]/128,
# IPv4-IPv6 Translation, see :rfc:`8215`
[64:ff9b:1::]/48,
# Discard-Only Address Block, see :rfc:`6666`
[100::]/64,
# IETF Protocol Assignments, see :rfc:`2928`
[2001::]/23,
# Benchmarking, see :rfc:`5180`
[2001:2::]/48,
# Documentation, see :rfc:`3849`
[2001:db8::]/32,
# Unique-Local, see :rfc:`4193` and :rfc:`8190`
[fc00::]/7,
# Link-Local Unicast, see :rfc:`4291`
[fe80::]/10,
}; };
## Networks that are considered "local". Note that ZeekControl sets ## Networks that are considered "local". Note that ZeekControl sets

View file

@ -0,0 +1,84 @@
##! This script disables repeat certificate events for hosts for hosts for which the same
##! certificate was seen in the recent past;
##!
##! This script specifically plugs into the event caching mechanism that is set up by the
##! base X509 script certificate-event-cache.zeek. It adds another layer of tracking that
##! checks if the same certificate was seen for the server IP address before, when the same
##! SNI was used to connect. If the certificate is in the event cache and all of these conditions
##! apply, then no certificate related events will be raised.
##!
##! Please note that while this optimization can lead to a considerable reduction of load in some
##! settings, it also means that certain detection scripts that rely on the certificate events being
##! raised do no longer work - since the events will not be raised for all connections.
##!
##! Currently this script only works for X509 certificates that are sent via SSL/TLS connections.
##!
##! If you use any script that requires certificate events for each single connection,
##! you should not load this script.
@load base/protocols/ssl
@load base/files/x509
module DisableX509Events;
## Let's be a bit more generous with the number of certificates that we allow to be put into
## the cache.
redef X509::certificate_cache_max_entries = 100000;
type CacheIndex: record {
## IP address of the server the certificate was seen on.
ip: addr;
## SNI the client sent in the connection
sni: string &optional;
## sha256 of the certificate
sha256: string;
};
redef record SSL::Info += {
## Set to true to force certificate events to always be raised for this connection.
always_raise_x509_events: bool &default=F;
};
redef record X509::Info += {
## Set to true to force certificate events to always be raised for this certificate.
always_raise_x509_events: bool &default=F;
};
global certificate_replay_tracking: set[CacheIndex] &read_expire=X509::certificate_cache_minimum_eviction_interval;
hook X509::x509_certificate_cache_replay(f: fa_file, e: X509::Info, sha256: string) &priority=5
{
# Bail out if x509 is already set - or if the file tells us that we should always raise events.
if ( f$info?$x509 || e$always_raise_x509_events )
return;
local raise_events = F;
# not sure how that could happen - but let's be safe...
if ( |f$conns| == 0 )
return;
for ( c in f$conns )
{
if ( ! f$conns[c]?$ssl )
return;
local test = CacheIndex($ip=f$conns[c]$id$resp_h, $sha256=sha256);
if ( f$conns[c]$ssl?$server_name )
test$sni = f$conns[c]$ssl$server_name;
if ( test !in certificate_replay_tracking || f$conns[c]$ssl$always_raise_x509_events )
{
raise_events = T;
add certificate_replay_tracking[test];
}
}
if ( ! raise_events )
{
# We don't have to raise the events. :).
# Instead we just already set f$x509. That makes the data available to scripts that might need them - and the x509_certificate_cache_replayh
# hook in certificate-event-cache will just abort.
f$info$x509 = e;
}
}

View file

@ -1,64 +1 @@
##! Enable logging of OCSP responses. @deprecated("Remove in v5.1. OCSP logging is now enabled by default")
#
# This script is in policy and not loaded by default because OCSP logging
# does not provide a lot of interesting information in most environments.
module OCSP;
export {
redef enum Log::ID += { LOG };
global log_policy: Log::PolicyHook;
## The record type which contains the fields of the OCSP log.
type Info: record {
## Time when the OCSP reply was encountered.
ts: time &log;
## File id of the OCSP reply.
id: string &log;
## Hash algorithm used to generate issuerNameHash and issuerKeyHash.
hashAlgorithm: string &log;
## Hash of the issuer's distingueshed name.
issuerNameHash: string &log;
## Hash of the issuer's public key.
issuerKeyHash: string &log;
## Serial number of the affected certificate.
serialNumber: string &log;
## Status of the affected certificate.
certStatus: string &log;
## Time at which the certificate was revoked.
revoketime: time &log &optional;
## Reason for which the certificate was revoked.
revokereason: string &log &optional;
## The time at which the status being shows is known to have been correct.
thisUpdate: time &log;
## The latest time at which new information about the status of the certificate will be available.
nextUpdate: time &log &optional;
};
## Event that can be handled to access the OCSP record
## as it is sent to the logging framework.
global log_ocsp: event(rec: Info);
}
event zeek_init() &priority=5
{
Log::create_stream(LOG, [$columns=Info, $ev=log_ocsp, $path="ocsp", $policy=log_policy]);
Files::register_for_mime_type(Files::ANALYZER_OCSP_REPLY, "application/ocsp-response");
}
event ocsp_response_certificate(f: fa_file, hashAlgorithm: string, issuerNameHash: string, issuerKeyHash: string, serialNumber: string, certStatus: string, revoketime: time, revokereason: string, thisUpdate: time, nextUpdate: time)
{
local wr = OCSP::Info($ts=f$info$ts, $id=f$id, $hashAlgorithm=hashAlgorithm, $issuerNameHash=issuerNameHash,
$issuerKeyHash=issuerKeyHash, $serialNumber=serialNumber, $certStatus=certStatus,
$thisUpdate=thisUpdate);
if ( revokereason != "" )
wr$revokereason = revokereason;
if ( time_to_double(revoketime) != 0 )
wr$revoketime = revoketime;
if ( time_to_double(nextUpdate) != 0 )
wr$nextUpdate = nextUpdate;
Log::write(LOG, wr);
}

View file

@ -0,0 +1,5 @@
# The entry point for the cluster agent. It only runs bootstrap logic for
# launching via the Supervisor. If we're not running the Supervisor, this does
# nothing.
@load ./boot

View file

@ -0,0 +1,33 @@
@load base/frameworks/supervisor/control
@load policy/frameworks/cluster/controller/types
module ClusterAgent::API;
export {
const version = 1;
# Agent API events
global set_configuration_request: event(reqid: string,
config: ClusterController::Types::Configuration);
global set_configuration_response: event(reqid: string,
result: ClusterController::Types::Result);
# Notification events, agent -> controller
# Report agent being available.
global notify_agent_hello: event(instance: string, host: addr,
api_version: count);
# Report node state changes.
global notify_change: event(instance: string,
n: ClusterController::Types::Node,
old: ClusterController::Types::State,
new: ClusterController::Types::State);
# Report operational error.
global notify_error: event(instance: string, msg: string, node: string &default="");
# Report informational message.
global notify_log: event(instance: string, msg: string, node: string &default="");
}

View file

@ -0,0 +1,35 @@
@load ./config
# The agent needs the supervisor to listen for node management requests. We
# need to tell it to do so, and we need to do so here, in the agent
# bootstrapping code, so the redef applies prior to the fork of the agent
# process itself.
redef SupervisorControl::enable_listen = T;
event zeek_init()
{
if ( ! Supervisor::is_supervisor() )
return;
local epi = ClusterAgent::endpoint_info();
local sn = Supervisor::NodeConfig($name=epi$id, $bare_mode=T,
$scripts=vector("policy/frameworks/cluster/agent/main.zeek"));
if ( ClusterAgent::directory != "" )
sn$directory = ClusterAgent::directory;
if ( ClusterAgent::stdout_file_suffix != "" )
sn$stdout_file = epi$id + "." + ClusterAgent::stdout_file_suffix;
if ( ClusterAgent::stderr_file_suffix != "" )
sn$stderr_file = epi$id + "." + ClusterAgent::stderr_file_suffix;
# This helps Zeek run controller and agent with a minimal set of scripts.
sn$env["ZEEK_CLUSTER_MGMT_NODE"] = "AGENT";
local res = Supervisor::create(sn);
if ( res != "" )
{
print(fmt("error: supervisor could not create agent node: %s", res));
exit(1);
}
}

View file

@ -0,0 +1,85 @@
@load policy/frameworks/cluster/controller/types
module ClusterAgent;
export {
# The name this agent uses to represent the cluster instance
# it manages. When the environment variable isn't set and there's,
# no redef, this falls back to "agent-<hostname>".
const name = getenv("ZEEK_AGENT_NAME") &redef;
# Agent stdout/stderr log files to produce in Zeek's working
# directory. If empty, no such logs will result. The actual
# log files have the agent's name (as per above) dot-prefixed.
const stdout_file_suffix = "agent.stdout" &redef;
const stderr_file_suffix = "agent.stderr" &redef;
# The address and port the agent listens on. When
# undefined, falls back to configurable default values.
const listen_address = getenv("ZEEK_AGENT_ADDR") &redef;
const default_address = Broker::default_listen_address &redef;
const listen_port = getenv("ZEEK_AGENT_PORT") &redef;
const default_port = 2151/tcp &redef;
# The agent communicates under to following topic prefix,
# suffixed with "/<name>" (see above):
const topic_prefix = "zeek/cluster-control/agent" &redef;
# The coordinates of the controller. When defined, it means
# agents peer with (connect to) the controller; otherwise the
# controller knows all agents and peers with them.
const controller: Broker::NetworkInfo = [
$address="0.0.0.0", $bound_port=0/unknown] &redef;
# Agent and controller currently log only, not via the data cluster's
# logger. (This might get added later.) For now, this means that
# if both write to the same log file, it gets garbled. The following
# lets you specify the working directory specifically for the agent.
const directory = "" &redef;
# Working directory for data cluster nodes. When relative, note
# that this will apply from the working directory of the agent,
# since it creates data cluster nodes.
const cluster_directory = "" &redef;
# The following functions return the effective network endpoint
# information for this agent, in two related forms.
global instance: function(): ClusterController::Types::Instance;
global endpoint_info: function(): Broker::EndpointInfo;
}
function instance(): ClusterController::Types::Instance
{
local epi = endpoint_info();
return ClusterController::Types::Instance($name=epi$id,
$host=to_addr(epi$network$address),
$listen_port=epi$network$bound_port);
}
function endpoint_info(): Broker::EndpointInfo
{
local epi: Broker::EndpointInfo;
local network: Broker::NetworkInfo;
if ( ClusterAgent::name != "" )
epi$id = ClusterAgent::name;
else
epi$id = fmt("agent-%s", gethostname());
if ( ClusterAgent::listen_address != "" )
network$address = ClusterAgent::listen_address;
else if ( ClusterAgent::default_address != "" )
network$address = ClusterAgent::default_address;
else
network$address = "127.0.0.1";
if ( ClusterAgent::listen_port != "" )
network$bound_port = to_port(ClusterAgent::listen_port);
else
network$bound_port = ClusterAgent::default_port;
epi$network = network;
return epi;
}

View file

@ -0,0 +1,223 @@
@load base/frameworks/broker
@load policy/frameworks/cluster/controller/config
@load policy/frameworks/cluster/controller/log
@load policy/frameworks/cluster/controller/request
@load ./api
redef ClusterController::role = ClusterController::Types::AGENT;
# The global configuration as passed to us by the controller
global global_config: ClusterController::Types::Configuration;
# A map to make other instance info accessible
global instances: table[string] of ClusterController::Types::Instance;
# A map for the nodes we run on this instance, via this agent.
global nodes: table[string] of ClusterController::Types::Node;
# The node map employed by the supervisor to describe the cluster
# topology to newly forked nodes. We refresh it when we receive
# new configurations.
global data_cluster: table[string] of Supervisor::ClusterEndpoint;
event SupervisorControl::create_response(reqid: string, result: string)
{
local req = ClusterController::Request::lookup(reqid);
if ( ClusterController::Request::is_null(req) )
return;
local name = req$supervisor_state$node;
if ( |result| > 0 )
{
local msg = fmt("failed to create node %s: %s", name, result);
ClusterController::Log::error(msg);
event ClusterAgent::API::notify_error(ClusterAgent::name, msg, name);
}
ClusterController::Request::finish(reqid);
}
event SupervisorControl::destroy_response(reqid: string, result: bool)
{
local req = ClusterController::Request::lookup(reqid);
if ( ClusterController::Request::is_null(req) )
return;
local name = req$supervisor_state$node;
if ( ! result )
{
local msg = fmt("failed to destroy node %s, %s", name, reqid);
ClusterController::Log::error(msg);
event ClusterAgent::API::notify_error(ClusterAgent::name, msg, name);
}
ClusterController::Request::finish(reqid);
}
function supervisor_create(nc: Supervisor::NodeConfig)
{
local req = ClusterController::Request::create();
req$supervisor_state = ClusterController::Request::SupervisorState($node = nc$name);
event SupervisorControl::create_request(req$id, nc);
ClusterController::Log::info(fmt("issued supervisor create for %s, %s", nc$name, req$id));
}
function supervisor_destroy(node: string)
{
local req = ClusterController::Request::create();
req$supervisor_state = ClusterController::Request::SupervisorState($node = node);
event SupervisorControl::destroy_request(req$id, node);
ClusterController::Log::info(fmt("issued supervisor destroy for %s, %s", node, req$id));
}
event ClusterAgent::API::set_configuration_request(reqid: string, config: ClusterController::Types::Configuration)
{
ClusterController::Log::info(fmt("rx ClusterAgent::API::set_configuration_request %s", reqid));
local nodename: string;
local node: ClusterController::Types::Node;
local nc: Supervisor::NodeConfig;
local msg: string;
# Adopt the global configuration provided.
# XXX this can later handle validation and persistence
# XXX should do this transactionally, only set when all else worked
global_config = config;
# Refresh the instances table:
instances = table();
for ( inst in config$instances )
instances[inst$name] = inst;
# Terminate existing nodes
for ( nodename in nodes )
supervisor_destroy(nodename);
nodes = table();
# Refresh the data cluster and nodes tables
data_cluster = table();
for ( node in config$nodes )
{
if ( node$instance == ClusterAgent::name )
nodes[node$name] = node;
local cep = Supervisor::ClusterEndpoint(
$role = node$role,
$host = instances[node$instance]$host,
$p = node$p);
if ( node?$interface )
cep$interface = node$interface;
data_cluster[node$name] = cep;
}
# Apply the new configuration via the supervisor
for ( nodename in nodes )
{
node = nodes[nodename];
nc = Supervisor::NodeConfig($name=nodename);
if ( ClusterAgent::cluster_directory != "" )
nc$directory = ClusterAgent::cluster_directory;
if ( node?$interface )
nc$interface = node$interface;
if ( node?$cpu_affinity )
nc$cpu_affinity = node$cpu_affinity;
if ( node?$scripts )
nc$scripts = node$scripts;
if ( node?$env )
nc$env = node$env;
# XXX could use options to enable per-node overrides for
# directory, stdout, stderr, others?
nc$cluster = data_cluster;
supervisor_create(nc);
}
# XXX this currently doesn not fail if any of above problems occurred,
# mainly due to the tediousness of handling the supervisor's response
# events asynchonously. The only indication of error will be
# notification events to the controller.
local res = ClusterController::Types::Result(
$reqid = reqid,
$instance = ClusterAgent::name);
ClusterController::Log::info(fmt("tx ClusterAgent::API::set_configuration_response %s", reqid));
event ClusterAgent::API::set_configuration_response(reqid, res);
}
event Broker::peer_added(peer: Broker::EndpointInfo, msg: string)
{
# This does not (cannot?) immediately verify that the new peer
# is in fact a controller, so we might send this redundantly.
# Controllers handle the hello event accordingly.
local epi = ClusterAgent::endpoint_info();
# XXX deal with unexpected peers, unless we're okay with it
event ClusterAgent::API::notify_agent_hello(epi$id,
to_addr(epi$network$address), ClusterAgent::API::version);
}
event zeek_init()
{
local epi = ClusterAgent::endpoint_info();
local agent_topic = ClusterAgent::topic_prefix + "/" + epi$id;
# The agent needs to peer with the supervisor -- this doesn't currently
# happen automatically. The address defaults to Broker's default, which
# relies on ZEEK_DEFAULT_LISTEN_ADDR and so might just be "". Broker
# internally falls back to listening on any; we pick 127.0.0.1.
local supervisor_addr = Broker::default_listen_address;
if ( supervisor_addr == "" )
supervisor_addr = "127.0.0.1";
Broker::peer(supervisor_addr, Broker::default_port, Broker::default_listen_retry);
# Agents need receive communication targeted at it, and any responses
# from the supervisor.
Broker::subscribe(agent_topic);
Broker::subscribe(SupervisorControl::topic_prefix);
# Auto-publish a bunch of events. Glob patterns or module-level
# auto-publish would be helpful here.
Broker::auto_publish(agent_topic, ClusterAgent::API::set_configuration_response);
Broker::auto_publish(agent_topic, ClusterAgent::API::notify_agent_hello);
Broker::auto_publish(agent_topic, ClusterAgent::API::notify_change);
Broker::auto_publish(agent_topic, ClusterAgent::API::notify_error);
Broker::auto_publish(agent_topic, ClusterAgent::API::notify_log);
Broker::auto_publish(SupervisorControl::topic_prefix, SupervisorControl::create_request);
Broker::auto_publish(SupervisorControl::topic_prefix, SupervisorControl::create_response);
Broker::auto_publish(SupervisorControl::topic_prefix, SupervisorControl::destroy_request);
Broker::auto_publish(SupervisorControl::topic_prefix, SupervisorControl::destroy_response);
Broker::auto_publish(SupervisorControl::topic_prefix, SupervisorControl::restart_request);
Broker::auto_publish(SupervisorControl::topic_prefix, SupervisorControl::restart_response);
Broker::auto_publish(SupervisorControl::topic_prefix, SupervisorControl::stop_request);
# Establish connectivity with the controller.
if ( ClusterAgent::controller$address != "0.0.0.0" )
{
# We connect to the controller.
Broker::peer(ClusterAgent::controller$address,
ClusterAgent::controller$bound_port,
ClusterController::connect_retry);
}
else
{
# Controller connects to us; listen for it.
Broker::listen(cat(epi$network$address), epi$network$bound_port);
}
ClusterController::Log::info("agent is live");
}

View file

@ -0,0 +1,5 @@
# The entry point for the cluster controller. It only runs bootstrap logic for
# launching via the Supervisor. If we're not running the Supervisor, this does
# nothing.
@load ./boot

Some files were not shown because too many files have changed in this diff Show more